Commit 913f4f42 by Tim Van Patten Committed by Commit Bot

Vulkan: Support VS, FS, and CS in the same PPO

This CL adds support for a Program Pipeline Object to have a VS, FS, and CS attached to the same PPO and then using that PPO for both draw and dispatch calls. Bug: angleproject:3570 Test: KHR-GLES31.core.compute_shader.sso* Change-Id: I262cdbdfd442f6db5ba2b45d1308003102b237cb Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2150078Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Reviewed-by: 's avatarCourtney Goeltzenleuchter <courtneygo@google.com> Commit-Queue: Tim Van Patten <timvp@google.com>
parent 78dcba58
......@@ -3579,6 +3579,10 @@ ANGLE_INLINE angle::Result Context::prepareForCopyImage()
ANGLE_INLINE angle::Result Context::prepareForDispatch()
{
// We always assume PPOs are used for draws, until they aren't. If we are executing a dispatch
// with a PPO, we need to convert it from a "draw"-type to "dispatch"-type.
convertPpoToComputeOrDraw(true);
ANGLE_TRY(syncDirtyObjects(mComputeDirtyObjects));
return syncDirtyBits(mComputeDirtyBits);
}
......@@ -5516,11 +5520,35 @@ void Context::dispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGr
}
ANGLE_CONTEXT_TRY(prepareForDispatch());
ANGLE_CONTEXT_TRY(mImplementation->dispatchCompute(this, numGroupsX, numGroupsY, numGroupsZ));
angle::Result result =
mImplementation->dispatchCompute(this, numGroupsX, numGroupsY, numGroupsZ);
// We always assume PPOs are used for draws, until they aren't. If we just executed a dispatch
// with a PPO, we need to convert it back to a "draw"-type.
convertPpoToComputeOrDraw(false);
if (ANGLE_UNLIKELY(IsError(result)))
{
return;
}
MarkShaderStorageBufferUsage(this);
}
void Context::convertPpoToComputeOrDraw(bool isCompute)
{
Program *program = mState.getProgram();
ProgramPipeline *pipeline = mState.getProgramPipeline();
if (!program && pipeline)
{
pipeline->getExecutable().setIsCompute(isCompute);
pipeline->setDirtyBit(ProgramPipeline::DirtyBitType::DIRTY_BIT_DRAW_DISPATCH_CHANGE);
mState.mDirtyObjects.set(State::DIRTY_OBJECT_PROGRAM_PIPELINE);
mState.mDirtyBits.set(State::DirtyBitType::DIRTY_BIT_PROGRAM_EXECUTABLE);
}
}
void Context::dispatchComputeIndirect(GLintptr indirect)
{
ANGLE_CONTEXT_TRY(prepareForDispatch());
......
......@@ -651,6 +651,8 @@ class Context final : public egl::LabeledObject, angle::NonCopyable, public angl
GLsizei count,
const GLint *v);
void convertPpoToComputeOrDraw(bool isCompute);
State mState;
bool mShared;
bool mSkipValidation;
......
......@@ -1211,20 +1211,12 @@ bool ProgramState::hasAttachedShader() const
ShaderType ProgramState::getFirstAttachedShaderStageType() const
{
for (const gl::ShaderType shaderType : gl::kAllGraphicsShaderTypes)
if (mExecutable.getLinkedShaderStages().none())
{
if (mExecutable.hasLinkedShaderStage(shaderType))
{
return shaderType;
}
return ShaderType::InvalidEnum;
}
if (mExecutable.hasLinkedShaderStage(ShaderType::Compute))
{
return ShaderType::Compute;
}
return ShaderType::InvalidEnum;
return *mExecutable.getLinkedShaderStages().begin();
}
ShaderType ProgramState::getLastAttachedShaderStageType() const
......@@ -1665,13 +1657,13 @@ void Program::resolveLinkImpl(const Context *context)
void Program::updateLinkedShaderStages()
{
mState.mExecutable.getLinkedShaderStages().reset();
mState.mExecutable.resetLinkedShaderStages();
for (const Shader *shader : mState.mAttachedShaders)
{
if (shader)
{
mState.mExecutable.getLinkedShaderStages().set(shader->getType());
mState.mExecutable.setLinkedShaderStages(shader->getType());
}
}
}
......@@ -5064,13 +5056,6 @@ angle::Result Program::serialize(const Context *context, angle::MemoryBuffer *bi
stream.writeInt(mState.mNumViews);
stream.writeInt(mState.mEarlyFramentTestsOptimization);
static_assert(MAX_VERTEX_ATTRIBS * 2 <= sizeof(uint32_t) * 8,
"All bits of mAttributesTypeMask types and mask fit into 32 bits each");
stream.writeInt(static_cast<int>(mState.mExecutable.mAttributesTypeMask.to_ulong()));
stream.writeInt(static_cast<int>(mState.mExecutable.mAttributesMask.to_ulong()));
stream.writeInt(mState.mExecutable.getActiveAttribLocationsMask().to_ulong());
stream.writeInt(mState.mExecutable.mMaxActiveAttribLocation);
stream.writeInt(mState.getProgramInputs().size());
for (const sh::ShaderVariable &attrib : mState.getProgramInputs())
{
......@@ -5216,7 +5201,7 @@ angle::Result Program::serialize(const Context *context, angle::MemoryBuffer *bi
stream.writeInt(mState.getAtomicCounterUniformRange().low());
stream.writeInt(mState.getAtomicCounterUniformRange().high());
stream.writeInt(mState.mExecutable.getLinkedShaderStages().to_ulong());
mState.mExecutable.save(&stream);
mProgram->save(context, &stream);
......@@ -5265,14 +5250,6 @@ angle::Result Program::deserialize(const Context *context,
mState.mNumViews = stream.readInt<int>();
mState.mEarlyFramentTestsOptimization = stream.readInt<bool>();
static_assert(MAX_VERTEX_ATTRIBS * 2 <= sizeof(uint32_t) * 8,
"Too many vertex attribs for mask: All bits of mAttributesTypeMask types and "
"mask fit into 32 bits each");
mState.mExecutable.mAttributesTypeMask = gl::ComponentTypeMask(stream.readInt<uint32_t>());
mState.mExecutable.mAttributesMask = stream.readInt<gl::AttributesMask>();
mState.mExecutable.mActiveAttribLocationsMask = stream.readInt<gl::AttributesMask>();
mState.mExecutable.mMaxActiveAttribLocation = stream.readInt<unsigned int>();
unsigned int attribCount = stream.readInt<unsigned int>();
ASSERT(mState.mProgramInputs.empty());
for (unsigned int attribIndex = 0; attribIndex < attribCount; ++attribIndex)
......@@ -5470,13 +5447,14 @@ angle::Result Program::deserialize(const Context *context,
static_assert(static_cast<unsigned long>(ShaderType::EnumCount) <= sizeof(unsigned long) * 8,
"Too many shader types");
mState.mExecutable.getLinkedShaderStages() = ShaderBitSet(stream.readInt<uint8_t>());
if (!mState.mAttachedShaders[ShaderType::Compute])
{
mState.updateTransformFeedbackStrides();
}
mState.mExecutable.load(&stream);
postResolveLink(context);
return angle::Result::Continue;
......
......@@ -353,6 +353,10 @@ class ProgramState final : angle::NonCopyable
return mAttachedShadersMarkedForDetach[shaderType];
}
// A Program can only either be graphics or compute, but never both, so it
// can answer isCompute() based on which shaders it has.
bool isCompute() const { return mExecutable.hasLinkedShaderStage(ShaderType::Compute); }
private:
friend class MemoryProgramCache;
friend class Program;
......
......@@ -48,6 +48,33 @@ void ProgramExecutable::reset()
mActiveImagesMask.reset();
}
void ProgramExecutable::load(gl::BinaryInputStream *stream)
{
static_assert(MAX_VERTEX_ATTRIBS * 2 <= sizeof(uint32_t) * 8,
"Too many vertex attribs for mask: All bits of mAttributesTypeMask types and "
"mask fit into 32 bits each");
mAttributesTypeMask = gl::ComponentTypeMask(stream->readInt<uint32_t>());
mAttributesMask = stream->readInt<gl::AttributesMask>();
mActiveAttribLocationsMask = stream->readInt<gl::AttributesMask>();
mMaxActiveAttribLocation = stream->readInt<unsigned int>();
mLinkedGraphicsShaderStages = ShaderBitSet(stream->readInt<uint8_t>());
mLinkedComputeShaderStages = ShaderBitSet(stream->readInt<uint8_t>());
}
void ProgramExecutable::save(gl::BinaryOutputStream *stream) const
{
static_assert(MAX_VERTEX_ATTRIBS * 2 <= sizeof(uint32_t) * 8,
"All bits of mAttributesTypeMask types and mask fit into 32 bits each");
stream->writeInt(static_cast<int>(mAttributesTypeMask.to_ulong()));
stream->writeInt(static_cast<int>(mAttributesMask.to_ulong()));
stream->writeInt(mActiveAttribLocationsMask.to_ulong());
stream->writeInt(mMaxActiveAttribLocation);
stream->writeInt(mLinkedGraphicsShaderStages.bits());
stream->writeInt(mLinkedComputeShaderStages.bits());
}
const ProgramState *ProgramExecutable::getProgramState(ShaderType shaderType) const
{
if (mProgramState &&
......@@ -64,6 +91,30 @@ const ProgramState *ProgramExecutable::getProgramState(ShaderType shaderType) co
return nullptr;
}
bool ProgramExecutable::isCompute() const
{
ASSERT(mProgramState || mProgramPipelineState);
if (mProgramState)
{
return mProgramState->isCompute();
}
return mProgramPipelineState->isCompute();
}
void ProgramExecutable::setIsCompute(bool isComputeIn)
{
// A Program can only either be graphics or compute, but never both, so it can answer
// isCompute() based on which shaders it has. However, a PPO can have both graphics and compute
// programs attached, so we don't know if the PPO is a 'graphics' or 'compute' PPO until the
// actual draw/dispatch call, which is why only PPOs need to record the type of call here.
if (mProgramPipelineState)
{
mProgramPipelineState->setIsCompute(isComputeIn);
}
}
int ProgramExecutable::getInfoLogLength() const
{
return static_cast<int>(mInfoLog.getLength());
......
......@@ -9,6 +9,7 @@
#ifndef LIBANGLE_PROGRAMEXECUTABLE_H_
#define LIBANGLE_PROGRAMEXECUTABLE_H_
#include "BinaryStream.h"
#include "libANGLE/Caps.h"
#include "libANGLE/InfoLog.h"
#include "libANGLE/VaryingPacking.h"
......@@ -63,6 +64,9 @@ class ProgramExecutable
void reset();
void save(gl::BinaryOutputStream *stream) const;
void load(gl::BinaryInputStream *stream);
const ProgramState *getProgramState(ShaderType shaderType) const;
int getInfoLogLength() const;
......@@ -71,15 +75,38 @@ class ProgramExecutable
std::string getInfoLogString() const;
void resetInfoLog() { mInfoLog.reset(); }
const ShaderBitSet &getLinkedShaderStages() const { return mLinkedShaderStages; }
ShaderBitSet &getLinkedShaderStages() { return mLinkedShaderStages; }
void resetLinkedShaderStages()
{
mLinkedComputeShaderStages.reset();
mLinkedGraphicsShaderStages.reset();
}
const ShaderBitSet &getLinkedShaderStages() const
{
return isCompute() ? mLinkedComputeShaderStages : mLinkedGraphicsShaderStages;
}
void setLinkedShaderStages(ShaderType shaderType)
{
if (shaderType == ShaderType::Compute)
{
mLinkedComputeShaderStages.set(ShaderType::Compute);
}
else
{
mLinkedGraphicsShaderStages.set(shaderType);
}
}
bool hasLinkedShaderStage(ShaderType shaderType) const
{
ASSERT(shaderType != ShaderType::InvalidEnum);
return mLinkedShaderStages[shaderType];
return (shaderType == ShaderType::Compute) ? mLinkedComputeShaderStages[shaderType]
: mLinkedGraphicsShaderStages[shaderType];
}
size_t getLinkedShaderStageCount() const { return mLinkedShaderStages.count(); }
bool isCompute() const { return hasLinkedShaderStage(ShaderType::Compute); }
size_t getLinkedShaderStageCount() const
{
return isCompute() ? mLinkedComputeShaderStages.count()
: mLinkedGraphicsShaderStages.count();
}
bool isCompute() const;
const AttributesMask &getActiveAttribLocationsMask() const
{
......@@ -136,6 +163,8 @@ class ProgramExecutable
mProgramPipelineState = state;
}
void setIsCompute(bool isComputeIn);
private:
// TODO(timvp): http://anglebug.com/3570: Investigate removing these friend
// class declarations and accessing the necessary members with getters/setters.
......@@ -156,7 +185,8 @@ class ProgramExecutable
InfoLog mInfoLog;
ShaderBitSet mLinkedShaderStages;
ShaderBitSet mLinkedGraphicsShaderStages;
ShaderBitSet mLinkedComputeShaderStages;
angle::BitSet<MAX_VERTEX_ATTRIBS> mActiveAttribLocationsMask;
unsigned int mMaxActiveAttribLocation;
......
......@@ -23,7 +23,11 @@ namespace gl
{
ProgramPipelineState::ProgramPipelineState()
: mLabel(), mActiveShaderProgram(nullptr), mValid(false), mHasBeenBound(false)
: mLabel(),
mIsCompute(false),
mActiveShaderProgram(nullptr),
mValid(false),
mHasBeenBound(false)
{
mExecutable.setProgramPipelineState(this);
......@@ -118,7 +122,7 @@ bool ProgramPipelineState::usesShaderProgram(ShaderProgramID programId) const
bool ProgramPipelineState::hasDefaultUniforms() const
{
for (const gl::ShaderType shaderType : gl::AllShaderTypes())
for (const gl::ShaderType shaderType : mExecutable.getLinkedShaderStages())
{
const Program *shaderProgram = getShaderProgram(shaderType);
if (shaderProgram && shaderProgram->getState().hasDefaultUniforms())
......@@ -132,7 +136,7 @@ bool ProgramPipelineState::hasDefaultUniforms() const
bool ProgramPipelineState::hasTextures() const
{
for (const gl::ShaderType shaderType : gl::AllShaderTypes())
for (const gl::ShaderType shaderType : mExecutable.getLinkedShaderStages())
{
const Program *shaderProgram = getShaderProgram(shaderType);
if (shaderProgram && shaderProgram->getState().hasTextures())
......@@ -146,7 +150,7 @@ bool ProgramPipelineState::hasTextures() const
bool ProgramPipelineState::hasUniformBuffers() const
{
for (const gl::ShaderType shaderType : gl::AllShaderTypes())
for (const gl::ShaderType shaderType : mExecutable.getLinkedShaderStages())
{
const Program *shaderProgram = getShaderProgram(shaderType);
if (shaderProgram && shaderProgram->getState().hasUniformBuffers())
......@@ -160,7 +164,7 @@ bool ProgramPipelineState::hasUniformBuffers() const
bool ProgramPipelineState::hasStorageBuffers() const
{
for (const gl::ShaderType shaderType : gl::AllShaderTypes())
for (const gl::ShaderType shaderType : mExecutable.getLinkedShaderStages())
{
const Program *shaderProgram = getShaderProgram(shaderType);
if (shaderProgram && shaderProgram->getState().hasStorageBuffers())
......@@ -174,7 +178,7 @@ bool ProgramPipelineState::hasStorageBuffers() const
bool ProgramPipelineState::hasAtomicCounterBuffers() const
{
for (const gl::ShaderType shaderType : gl::AllShaderTypes())
for (const gl::ShaderType shaderType : mExecutable.getLinkedShaderStages())
{
const Program *shaderProgram = getShaderProgram(shaderType);
if (shaderProgram && shaderProgram->getState().hasAtomicCounterBuffers())
......@@ -188,7 +192,7 @@ bool ProgramPipelineState::hasAtomicCounterBuffers() const
bool ProgramPipelineState::hasImages() const
{
for (const gl::ShaderType shaderType : gl::AllShaderTypes())
for (const gl::ShaderType shaderType : mExecutable.getLinkedShaderStages())
{
const Program *shaderProgram = getShaderProgram(shaderType);
if (shaderProgram && shaderProgram->getState().hasImages())
......@@ -202,7 +206,7 @@ bool ProgramPipelineState::hasImages() const
bool ProgramPipelineState::hasTransformFeedbackOutput() const
{
for (const gl::ShaderType shaderType : gl::AllShaderTypes())
for (const gl::ShaderType shaderType : mExecutable.getLinkedShaderStages())
{
const Program *shaderProgram = getShaderProgram(shaderType);
if (shaderProgram && shaderProgram->getState().hasTransformFeedbackOutput())
......@@ -273,13 +277,14 @@ void ProgramPipeline::useProgramStages(const Context *context,
void ProgramPipeline::updateLinkedShaderStages()
{
mState.mExecutable.mLinkedShaderStages.reset();
mState.mExecutable.resetLinkedShaderStages();
for (const ShaderType shaderType : gl::AllShaderTypes())
{
if (mState.mPrograms[shaderType])
Program *program = mState.mPrograms[shaderType];
if (program)
{
mState.mExecutable.mLinkedShaderStages.set(shaderType);
mState.mExecutable.setLinkedShaderStages(shaderType);
}
}
}
......@@ -302,7 +307,7 @@ void ProgramPipeline::updateExecutableAttributes()
void ProgramPipeline::updateExecutableTextures()
{
for (const ShaderType shaderType : gl::AllShaderTypes())
for (const ShaderType shaderType : mState.mExecutable.getLinkedShaderStages())
{
const Program *program = getShaderProgram(shaderType);
if (program)
......@@ -342,15 +347,13 @@ ProgramMergedVaryings ProgramPipeline::getMergedVaryings() const
// Note that kAllGraphicsShaderTypes is sorted according to the rendering pipeline.
ShaderType lastActiveStage = ShaderType::InvalidEnum;
for (ShaderType stage : kAllGraphicsShaderTypes)
for (ShaderType shaderType : getExecutable().getLinkedShaderStages())
{
previousActiveStage[stage] = lastActiveStage;
previousActiveStage[shaderType] = lastActiveStage;
const Program *program = getShaderProgram(stage);
if (program)
{
lastActiveStage = stage;
}
const Program *program = getShaderProgram(shaderType);
ASSERT(program);
lastActiveStage = shaderType;
}
// First, go through output varyings and create two maps (one by name, one by location) for
......@@ -362,18 +365,12 @@ ProgramMergedVaryings ProgramPipeline::getMergedVaryings() const
ProgramMergedVaryings merged;
// Gather output varyings.
for (ShaderType shaderType : kAllGraphicsShaderTypes)
for (ShaderType shaderType : getExecutable().getLinkedShaderStages())
{
const Program *program = getShaderProgram(shaderType);
if (!program)
{
continue;
}
ASSERT(program);
Shader *shader = program->getState().getAttachedShader(shaderType);
if (!shader)
{
continue;
}
ASSERT(shader);
for (const sh::ShaderVariable &varying : shader->getOutputVaryings())
{
......@@ -397,18 +394,12 @@ ProgramMergedVaryings ProgramPipeline::getMergedVaryings() const
}
// Gather input varyings, and match them with output varyings of the previous stage.
for (ShaderType shaderType : kAllGraphicsShaderTypes)
for (ShaderType shaderType : getExecutable().getLinkedShaderStages())
{
const Program *program = getShaderProgram(shaderType);
if (!program)
{
continue;
}
ASSERT(program);
Shader *shader = program->getState().getAttachedShader(shaderType);
if (!shader)
{
continue;
}
ASSERT(shader);
ShaderType previousStage = previousActiveStage[shaderType];
for (const sh::ShaderVariable &varying : shader->getInputVaryings())
......@@ -497,14 +488,12 @@ angle::Result ProgramPipeline::link(const Context *context)
VaryingPacking varyingPacking(maxVaryingVectors, packMode);
const ProgramMergedVaryings &mergedVaryings = getMergedVaryings();
for (ShaderType shaderType : kAllGraphicsShaderTypes)
for (ShaderType shaderType : getExecutable().getLinkedShaderStages())
{
Program *program = mState.mPrograms[shaderType];
if (program)
{
program->getResources().varyingPacking.reset();
ANGLE_TRY(program->linkMergedVaryings(context, mergedVaryings));
}
ASSERT(program);
program->getResources().varyingPacking.reset();
ANGLE_TRY(program->linkMergedVaryings(context, mergedVaryings));
}
}
......@@ -516,13 +505,10 @@ angle::Result ProgramPipeline::link(const Context *context)
bool ProgramPipeline::linkVaryings(InfoLog &infoLog) const
{
Shader *previousShader = nullptr;
for (ShaderType shaderType : kAllGraphicsShaderTypes)
for (ShaderType shaderType : getExecutable().getLinkedShaderStages())
{
Program *currentProgram = mState.mPrograms[shaderType];
if (!currentProgram)
{
continue;
}
ASSERT(currentProgram);
Shader *currentShader =
const_cast<Shader *>(currentProgram->getState().getAttachedShader(shaderType));
......@@ -563,7 +549,7 @@ void ProgramPipeline::validate(const gl::Context *context)
InfoLog &infoLog = mState.mExecutable.getInfoLog();
infoLog.reset();
for (const ShaderType shaderType : gl::AllShaderTypes())
for (const ShaderType shaderType : mState.mExecutable.getLinkedShaderStages())
{
Program *shaderProgram = mState.mPrograms[shaderType];
if (shaderProgram)
......@@ -591,17 +577,15 @@ void ProgramPipeline::validate(const gl::Context *context)
{
mState.mValid = false;
for (const ShaderType shaderType : gl::AllShaderTypes())
for (const ShaderType shaderType : mState.mExecutable.getLinkedShaderStages())
{
Program *shaderProgram = mState.mPrograms[shaderType];
if (shaderProgram)
ASSERT(shaderProgram);
shaderProgram->validate(caps);
std::string shaderInfoString = shaderProgram->getExecutable().getInfoLogString();
if (shaderInfoString.length())
{
shaderProgram->validate(caps);
std::string shaderInfoString = shaderProgram->getExecutable().getInfoLogString();
if (shaderInfoString.length())
{
infoLog << shaderInfoString << "\n";
}
infoLog << shaderInfoString << "\n";
}
}
}
......
......@@ -38,6 +38,12 @@ class ProgramPipelineState final : angle::NonCopyable
const std::string &getLabel() const;
// A PPO can have both graphics and compute programs attached, so
// we don't know if the PPO is a 'graphics' or 'compute' PPO until the
// actual draw/dispatch call.
bool isCompute() const { return mIsCompute; }
void setIsCompute(bool isCompute) { mIsCompute = isCompute; }
const ProgramExecutable &getProgramExecutable() const { return mExecutable; }
ProgramExecutable &getProgramExecutable() { return mExecutable; }
......@@ -67,6 +73,8 @@ class ProgramPipelineState final : angle::NonCopyable
std::string mLabel;
bool mIsCompute;
// The active shader program
Program *mActiveShaderProgram;
// The shader programs for each stage.
......@@ -140,9 +148,9 @@ class ProgramPipeline final : public RefCountObject<ProgramPipelineID>, public L
{
// One of the program stages in the PPO changed.
DIRTY_BIT_PROGRAM_STAGE,
DIRTY_BIT_DUMMY, // Used to make DIRTY_BIT_COUNT > 0
DIRTY_BIT_DRAW_DISPATCH_CHANGE,
DIRTY_BIT_COUNT = DIRTY_BIT_DUMMY,
DIRTY_BIT_COUNT = DIRTY_BIT_DRAW_DISPATCH_CHANGE + 1,
};
using DirtyBits = angle::BitSet<DIRTY_BIT_COUNT>;
......
......@@ -1817,7 +1817,6 @@ angle::Result State::useProgramStages(const Context *context,
{
programPipeline->useProgramStages(context, stages, shaderProgram);
ANGLE_TRY(onProgramPipelineExecutableChange(context, programPipeline));
mDirtyObjects.set(DIRTY_OBJECT_PROGRAM_PIPELINE);
return angle::Result::Continue;
}
......@@ -3273,7 +3272,7 @@ angle::Result State::onProgramPipelineExecutableChange(const Context *context,
if (programPipeline->hasAnyDirtyBit())
{
mDirtyObjects.set(DIRTY_OBJECT_PROGRAM);
mDirtyObjects.set(DIRTY_OBJECT_PROGRAM_PIPELINE);
}
// Set any bound textures.
......
......@@ -1966,6 +1966,7 @@ angle::Result GlslangTransformSpirvCode(const GlslangErrorCallback &callback,
}
angle::Result GlslangGetShaderSpirvCode(const GlslangErrorCallback &callback,
const gl::ShaderBitSet &linkedShaderStages,
const gl::Caps &glCaps,
const gl::ShaderMap<std::string> &shaderSources,
const ShaderMapInterfaceVariableInfoMap &variableInfoMap,
......@@ -1974,7 +1975,7 @@ angle::Result GlslangGetShaderSpirvCode(const GlslangErrorCallback &callback,
gl::ShaderMap<SpirvBlob> initialSpirvBlobs;
ANGLE_TRY(GetShaderSpirvCode(callback, glCaps, shaderSources, &initialSpirvBlobs));
for (const gl::ShaderType shaderType : gl::AllShaderTypes())
for (const gl::ShaderType shaderType : linkedShaderStages)
{
// we pass in false here to skip modifications related to early fragment tests
// optimizations and line rasterization. These are done in the initProgram time since they
......
......@@ -124,6 +124,7 @@ angle::Result GlslangTransformSpirvCode(const GlslangErrorCallback &callback,
SpirvBlob *spirvBlobOut);
angle::Result GlslangGetShaderSpirvCode(const GlslangErrorCallback &callback,
const gl::ShaderBitSet &linkedShaderStages,
const gl::Caps &glCaps,
const gl::ShaderMap<std::string> &shaderSources,
const ShaderMapInterfaceVariableInfoMap &variableInfoMap,
......
......@@ -317,8 +317,9 @@ angle::Result ProgramMtl::linkImpl(const gl::Context *glContext,
// Convert GLSL to spirv code
gl::ShaderMap<std::vector<uint32_t>> shaderCodes;
ANGLE_TRY(mtl::GlslangGetShaderSpirvCode(contextMtl, contextMtl->getCaps(), shaderSources,
variableInfoMap, &shaderCodes));
ANGLE_TRY(mtl::GlslangGetShaderSpirvCode(
contextMtl, mState.getProgramExecutable().getLinkedShaderStages(), contextMtl->getCaps(),
shaderSources, variableInfoMap, &shaderCodes));
// Convert spirv code to MSL
ANGLE_TRY(convertToMsl(glContext, gl::ShaderType::Vertex, infoLog,
......
......@@ -25,6 +25,7 @@ void GlslangGetShaderSource(const gl::ProgramState &programState,
ShaderMapInterfaceVariableInfoMap *variableInfoMapOut);
angle::Result GlslangGetShaderSpirvCode(ErrorHandler *context,
const gl::ShaderBitSet &linkedShaderStages,
const gl::Caps &glCaps,
const gl::ShaderMap<std::string> &shaderSources,
const ShaderMapInterfaceVariableInfoMap &variableInfoMap,
......
......@@ -59,14 +59,15 @@ void GlslangGetShaderSource(const gl::ProgramState &programState,
}
angle::Result GlslangGetShaderSpirvCode(ErrorHandler *context,
const gl::ShaderBitSet &linkedShaderStages,
const gl::Caps &glCaps,
const gl::ShaderMap<std::string> &shaderSources,
const ShaderMapInterfaceVariableInfoMap &variableInfoMap,
gl::ShaderMap<std::vector<uint32_t>> *shaderCodeOut)
{
return rx::GlslangGetShaderSpirvCode(
[context](GlslangError error) { return HandleError(context, error); }, glCaps,
shaderSources, variableInfoMap, shaderCodeOut);
[context](GlslangError error) { return HandleError(context, error); }, linkedShaderStages,
glCaps, shaderSources, variableInfoMap, shaderCodeOut);
}
} // namespace mtl
} // namespace rx
......@@ -2659,18 +2659,15 @@ angle::Result ContextVk::updateScissor(const gl::State &glState)
void ContextVk::invalidateProgramBindingHelper(const gl::State &glState)
{
mExecutable = nullptr;
mProgram = nullptr;
mProgramPipeline = nullptr;
mExecutable = nullptr;
if (glState.getProgram())
{
mProgram = vk::GetImpl(glState.getProgram());
mExecutable = &mProgram->getExecutable();
}
else
{
mProgram = nullptr;
mExecutable = nullptr;
}
if (glState.getProgramPipeline())
{
......@@ -2681,10 +2678,6 @@ void ContextVk::invalidateProgramBindingHelper(const gl::State &glState)
mExecutable = &mProgramPipeline->getExecutable();
}
}
else
{
mProgramPipeline = nullptr;
}
}
angle::Result ContextVk::invalidateProgramExecutableHelper(const gl::Context *context)
......
......@@ -71,14 +71,15 @@ void GlslangWrapperVk::GetShaderSource(const angle::FeaturesVk &features,
// static
angle::Result GlslangWrapperVk::GetShaderCode(
vk::Context *context,
const gl::ShaderBitSet &linkedShaderStages,
const gl::Caps &glCaps,
const gl::ShaderMap<std::string> &shaderSources,
const ShaderMapInterfaceVariableInfoMap &variableInfoMap,
gl::ShaderMap<std::vector<uint32_t>> *shaderCodeOut)
{
return GlslangGetShaderSpirvCode(
[context](GlslangError error) { return ErrorHandler(context, error); }, glCaps,
shaderSources, variableInfoMap, shaderCodeOut);
[context](GlslangError error) { return ErrorHandler(context, error); }, linkedShaderStages,
glCaps, shaderSources, variableInfoMap, shaderCodeOut);
}
// static
......
......@@ -38,6 +38,7 @@ class GlslangWrapperVk
ShaderMapInterfaceVariableInfoMap *variableInfoMapOut);
static angle::Result GetShaderCode(vk::Context *context,
const gl::ShaderBitSet &linkedShaderStages,
const gl::Caps &glCaps,
const gl::ShaderMap<std::string> &shaderSources,
const ShaderMapInterfaceVariableInfoMap &variableInfoMap,
......
......@@ -31,13 +31,14 @@ ShaderInfo::ShaderInfo() {}
ShaderInfo::~ShaderInfo() = default;
angle::Result ShaderInfo::initShaders(ContextVk *contextVk,
const gl::ShaderBitSet &linkedShaderStages,
const gl::ShaderMap<std::string> &shaderSources,
const ShaderMapInterfaceVariableInfoMap &variableInfoMap)
{
ASSERT(!valid());
ANGLE_TRY(GlslangWrapperVk::GetShaderCode(contextVk, contextVk->getCaps(), shaderSources,
variableInfoMap, &mSpirvBlobs));
ANGLE_TRY(GlslangWrapperVk::GetShaderCode(contextVk, linkedShaderStages, contextVk->getCaps(),
shaderSources, variableInfoMap, &mSpirvBlobs));
mIsInitialized = true;
return angle::Result::Continue;
......@@ -140,7 +141,6 @@ void ProgramInfo::release(ContextVk *contextVk)
ProgramExecutableVk::ProgramExecutableVk()
: mEmptyDescriptorSets{},
mNumDefaultUniformDescriptors(0),
mPipelineLayoutCreated(false),
mDynamicBufferOffsets{},
mProgram(nullptr),
mProgramPipeline(nullptr)
......@@ -162,7 +162,6 @@ void ProgramExecutableVk::reset(ContextVk *contextVk)
mDescriptorSets.clear();
mEmptyDescriptorSets.fill(VK_NULL_HANDLE);
mPipelineLayoutCreated = false;
mNumDefaultUniformDescriptors = 0;
mTransformOptionBits.reset();
......@@ -179,10 +178,11 @@ void ProgramExecutableVk::reset(ContextVk *contextVk)
mTextureDescriptorsCache.clear();
mDescriptorBuffersCache.clear();
for (ProgramInfo &programInfo : mProgramInfos)
for (ProgramInfo &programInfo : mGraphicsProgramInfos)
{
programInfo.release(contextVk);
}
mComputeProgramInfo.release(contextVk);
}
std::unique_ptr<rx::LinkEvent> ProgramExecutableVk::load(gl::BinaryInputStream *stream)
......@@ -575,14 +575,14 @@ angle::Result ProgramExecutableVk::getGraphicsPipeline(
const gl::State &glState = contextVk->getState();
mTransformOptionBits[ProgramTransformOption::EnableLineRasterEmulation] =
contextVk->isBresenhamEmulationEnabled(mode);
ProgramInfo &programInfo = getProgramInfo(mTransformOptionBits);
ProgramInfo &programInfo = getGraphicsProgramInfo(mTransformOptionBits);
RendererVk *renderer = contextVk->getRenderer();
vk::PipelineCache *pipelineCache = nullptr;
const gl::ProgramExecutable *executable = glState.getProgramExecutable();
ASSERT(executable);
const gl::ProgramExecutable *glExecutable = glState.getProgramExecutable();
ASSERT(glExecutable && !glExecutable->isCompute());
for (const gl::ShaderType shaderType : executable->getLinkedShaderStages())
for (const gl::ShaderType shaderType : glExecutable->getLinkedShaderStages())
{
ProgramVk *programVk = getShaderProgram(glState, shaderType);
if (programVk)
......@@ -593,7 +593,7 @@ angle::Result ProgramExecutableVk::getGraphicsPipeline(
}
vk::ShaderProgramHelper *shaderProgram = programInfo.getShaderProgram();
ASSERT(shaderProgram && shaderProgram->isGraphicsProgram());
ASSERT(shaderProgram);
ANGLE_TRY(renderer->getPipelineCache(&pipelineCache));
return shaderProgram->getGraphicsPipeline(
contextVk, &contextVk->getRenderPassCache(), *pipelineCache,
......@@ -604,25 +604,22 @@ angle::Result ProgramExecutableVk::getGraphicsPipeline(
angle::Result ProgramExecutableVk::getComputePipeline(ContextVk *contextVk,
vk::PipelineAndSerial **pipelineOut)
{
const gl::State &glState = contextVk->getState();
ProgramInfo &programInfo = getDefaultProgramInfo();
const gl::State &glState = contextVk->getState();
const gl::ProgramExecutable *glExecutable = glState.getProgramExecutable();
ASSERT(glExecutable && glExecutable->isCompute());
ProgramVk *programVk = getShaderProgram(glState, gl::ShaderType::Compute);
ASSERT(programVk);
ProgramInfo &programInfo = getComputeProgramInfo();
ANGLE_TRY(programVk->initComputeProgram(contextVk, programInfo));
vk::ShaderProgramHelper *shaderProgram = programInfo.getShaderProgram();
ASSERT(shaderProgram && !shaderProgram->isGraphicsProgram());
ASSERT(shaderProgram);
return shaderProgram->getComputePipeline(contextVk, getPipelineLayout(), pipelineOut);
}
angle::Result ProgramExecutableVk::createPipelineLayout(const gl::Context *glContext)
{
if (mPipelineLayoutCreated)
{
return angle::Result::Continue;
}
const gl::State &glState = glContext->getState();
ContextVk *contextVk = vk::GetImpl(glContext);
RendererVk *renderer = contextVk->getRenderer();
......@@ -819,8 +816,6 @@ angle::Result ProgramExecutableVk::createPipelineLayout(const gl::Context *glCon
constexpr VkMemoryPropertyFlags kMemoryType = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
angle::Result status = mEmptyBuffer.init(contextVk, emptyBufferInfo, kMemoryType);
mPipelineLayoutCreated = true;
return status;
}
......
......@@ -28,6 +28,7 @@ class ShaderInfo final : angle::NonCopyable
~ShaderInfo();
angle::Result initShaders(ContextVk *contextVk,
const gl::ShaderBitSet &linkedShaderStages,
const gl::ShaderMap<std::string> &shaderSources,
const ShaderMapInterfaceVariableInfoMap &variableInfoMap);
void release(ContextVk *contextVk);
......@@ -119,11 +120,12 @@ class ProgramExecutableVk
gl::ShaderMap<const gl::ProgramState *> *programStatesOut);
const gl::ProgramExecutable &getGlExecutable();
ProgramInfo &getDefaultProgramInfo() { return mProgramInfos[0]; }
ProgramInfo &getProgramInfo(ProgramTransformOptionBits optionBits)
ProgramInfo &getGraphicsDefaultProgramInfo() { return mGraphicsProgramInfos[0]; }
ProgramInfo &getGraphicsProgramInfo(ProgramTransformOptionBits optionBits)
{
return mProgramInfos[optionBits.to_ulong()];
return mGraphicsProgramInfos[optionBits.to_ulong()];
}
ProgramInfo &getComputeProgramInfo() { return mComputeProgramInfo; }
angle::Result getGraphicsPipeline(ContextVk *contextVk,
gl::PrimitiveMode mode,
......@@ -223,7 +225,6 @@ class ProgramExecutableVk
// deleted while this program is in use.
vk::BindingPointer<vk::PipelineLayout> mPipelineLayout;
vk::DescriptorSetLayoutPointerArray mDescriptorSetLayouts;
bool mPipelineLayoutCreated;
// Keep bindings to the descriptor pools. This ensures the pools stay valid while the Program
// is in use.
......@@ -240,7 +241,8 @@ class ProgramExecutableVk
// since that's slow to calculate.
ShaderMapInterfaceVariableInfoMap mVariableInfoMap;
ProgramInfo mProgramInfos[static_cast<int>(ProgramTransformOption::PermutationCount)];
ProgramInfo mGraphicsProgramInfos[static_cast<int>(ProgramTransformOption::PermutationCount)];
ProgramInfo mComputeProgramInfo;
ProgramTransformOptionBits mTransformOptionBits;
......
......@@ -302,7 +302,8 @@ std::unique_ptr<LinkEvent> ProgramVk::link(const gl::Context *context,
// Compile the shaders.
angle::Result status =
mShaderInfo.initShaders(contextVk, shaderSources, mExecutable.mVariableInfoMap);
mShaderInfo.initShaders(contextVk, mState.getProgramExecutable().getLinkedShaderStages(),
shaderSources, mExecutable.mVariableInfoMap);
if (status != angle::Result::Continue)
{
return std::make_unique<LinkEventDone>(status);
......
......@@ -1278,14 +1278,6 @@ class ShaderProgramHelper : angle::NonCopyable
void destroy(VkDevice device);
void release(ContextVk *contextVk);
bool isGraphicsProgram() const
{
ASSERT((mShaders[gl::ShaderType::Vertex].valid() ||
mShaders[gl::ShaderType::Fragment].valid()) !=
mShaders[gl::ShaderType::Compute].valid());
return !mShaders[gl::ShaderType::Compute].valid();
}
ShaderAndSerial &getShader(gl::ShaderType shaderType) { return mShaders[shaderType].get(); }
void setShader(gl::ShaderType shaderType, RefCounted<ShaderAndSerial> *shader);
......
......@@ -36,11 +36,6 @@
//// Failures blocking an official GLES 3.1 conformance run on SwiftShader
////
// Verify that compute and non-compute stages can be attached to one pipeline object:
3570 VULKAN : KHR-GLES31.core.compute_shader.sso-compute-pipeline = SKIP
3570 VULKAN : KHR-GLES31.core.compute_shader.sso-case2 = SKIP
3570 VULKAN : KHR-GLES31.core.compute_shader.sso-case3 = SKIP
3570 SWIFTSHADER : KHR-GLES31.core.shader_image_load_store.advanced-sso-simple = SKIP
// Separate shader objects:
3570 VULKAN : KHR-GLES31.core.sepshaderobjs.StateInteraction = SKIP
......@@ -75,9 +70,6 @@
3605 VULKAN : KHR-GLES31.core.texture_gather.* = FAIL
// Dispatch indirect:
4188 VULKAN : KHR-GLES31.core.compute_shader.resource-image = FAIL
4191 VULKAN : KHR-GLES31.core.compute_shader.resources-max = FAIL
4192 VULKAN : KHR-GLES31.core.compute_shader.pipeline-post-xfb = FAIL
3726 VULKAN PIXEL2ORXL : KHR-GLES31.core.compute_shader.pipeline-compute-chain = FAIL
4194 VULKAN PIXEL2ORXL : KHR-GLES31.core.compute_shader.resource-ubo = FAIL
4194 VULKAN PIXEL2ORXL : KHR-GLES31.core.compute_shader.built-in-variables = FAIL
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment