Commit 4db77367 by Tim Van Patten Committed by Commit Bot

Vulkan: Don't detach separable shaders in Program::detachShader()

To support Program Pipeline Objects, we need to hold on to the shaders in separable programs, rather than detaching them during glDetachShader()/glCreateShaderProgramv(). This is necessary due to requiring the shader information for validating shader interfaces, varyings, etc. Instead, a new ShaderMap of bools will be stored in ProgramState::mAttachedShadersMarkedForDetach to track when a caller attempts to detach a shader from a separable Program. Later, when a new shader is attached, we will first validate that the old shader is marked to be detached, and if so, release it then. Bug: angleproject:3570 Change-Id: I63fac2e5914c1c1a73f0b37863bac0f185ecb44c Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2084399Reviewed-by: 's avatarCourtney Goeltzenleuchter <courtneygo@google.com> Commit-Queue: Tim Van Patten <timvp@google.com>
parent 745e0712
...@@ -5154,7 +5154,7 @@ void Context::attachShader(ShaderProgramID program, ShaderProgramID shader) ...@@ -5154,7 +5154,7 @@ void Context::attachShader(ShaderProgramID program, ShaderProgramID shader)
Program *programObject = mState.mShaderProgramManager->getProgram(program); Program *programObject = mState.mShaderProgramManager->getProgram(program);
Shader *shaderObject = mState.mShaderProgramManager->getShader(shader); Shader *shaderObject = mState.mShaderProgramManager->getShader(shader);
ASSERT(programObject && shaderObject); ASSERT(programObject && shaderObject);
programObject->attachShader(shaderObject); programObject->attachShader(this, shaderObject);
} }
void Context::copyBufferSubData(BufferBinding readTarget, void Context::copyBufferSubData(BufferBinding readTarget,
......
...@@ -559,8 +559,8 @@ angle::Result GLES1Renderer::linkProgram(Context *context, ...@@ -559,8 +559,8 @@ angle::Result GLES1Renderer::linkProgram(Context *context,
*programOut = program; *programOut = program;
programObject->attachShader(getShader(vertexShader)); programObject->attachShader(context, getShader(vertexShader));
programObject->attachShader(getShader(fragmentShader)); programObject->attachShader(context, getShader(fragmentShader));
for (auto it : attribLocs) for (auto it : attribLocs)
{ {
......
...@@ -1091,6 +1091,7 @@ ImageBinding::~ImageBinding() = default; ...@@ -1091,6 +1091,7 @@ ImageBinding::~ImageBinding() = default;
ProgramState::ProgramState() ProgramState::ProgramState()
: mLabel(), : mLabel(),
mAttachedShaders{}, mAttachedShaders{},
mAttachedShadersMarkedForDetach{},
mTransformFeedbackBufferMode(GL_INTERLEAVED_ATTRIBS), mTransformFeedbackBufferMode(GL_INTERLEAVED_ATTRIBS),
mDefaultUniformRange(0, 0), mDefaultUniformRange(0, 0),
mSamplerUniformRange(0, 0), mSamplerUniformRange(0, 0),
...@@ -1299,7 +1300,8 @@ void Program::onDestroy(const Context *context) ...@@ -1299,7 +1300,8 @@ void Program::onDestroy(const Context *context)
if (mState.mAttachedShaders[shaderType]) if (mState.mAttachedShaders[shaderType])
{ {
mState.mAttachedShaders[shaderType]->release(context); mState.mAttachedShaders[shaderType]->release(context);
mState.mAttachedShaders[shaderType] = nullptr; mState.mAttachedShaders[shaderType] = nullptr;
mState.mAttachedShadersMarkedForDetach[shaderType] = false;
} }
} }
...@@ -1328,12 +1330,21 @@ const std::string &Program::getLabel() const ...@@ -1328,12 +1330,21 @@ const std::string &Program::getLabel() const
return mState.mLabel; return mState.mLabel;
} }
void Program::attachShader(Shader *shader) void Program::attachShader(const Context *context, Shader *shader)
{ {
ASSERT(mLinkResolved); ASSERT(mLinkResolved);
ShaderType shaderType = shader->getType(); ShaderType shaderType = shader->getType();
ASSERT(shaderType != ShaderType::InvalidEnum); ASSERT(shaderType != ShaderType::InvalidEnum);
// Since detachShader doesn't actually detach anymore, we need to do that work when attaching a
// new shader to make sure we don't lose track of it and free the resources.
if (mState.mAttachedShaders[shaderType])
{
mState.mAttachedShaders[shaderType]->release(context);
mState.mAttachedShaders[shaderType] = nullptr;
mState.mAttachedShadersMarkedForDetach[shaderType] = false;
}
mState.mAttachedShaders[shaderType] = shader; mState.mAttachedShaders[shaderType] = shader;
mState.mAttachedShaders[shaderType]->addRef(); mState.mAttachedShaders[shaderType]->addRef();
} }
...@@ -1345,8 +1356,19 @@ void Program::detachShader(const Context *context, Shader *shader) ...@@ -1345,8 +1356,19 @@ void Program::detachShader(const Context *context, Shader *shader)
ASSERT(shaderType != ShaderType::InvalidEnum); ASSERT(shaderType != ShaderType::InvalidEnum);
ASSERT(mState.mAttachedShaders[shaderType] == shader); ASSERT(mState.mAttachedShaders[shaderType] == shader);
if (isSeparable())
{
// Don't actually detach the shader since we still need it in case this
// Program is part of a Program Pipeline Object. Instead, leave a mark
// that indicates we intended to.
mState.mAttachedShadersMarkedForDetach[shaderType] = true;
return;
}
shader->release(context); shader->release(context);
mState.mAttachedShaders[shaderType] = nullptr; mState.mAttachedShaders[shaderType] = nullptr;
mState.mAttachedShadersMarkedForDetach[shaderType] = false;
} }
int Program::getAttachedShadersCount() const int Program::getAttachedShadersCount() const
......
...@@ -349,6 +349,11 @@ class ProgramState final : angle::NonCopyable ...@@ -349,6 +349,11 @@ class ProgramState final : angle::NonCopyable
return !getLinkedTransformFeedbackVaryings().empty(); return !getLinkedTransformFeedbackVaryings().empty();
} }
bool isShaderMarkedForDetach(gl::ShaderType shaderType) const
{
return mAttachedShadersMarkedForDetach[shaderType];
}
private: private:
friend class MemoryProgramCache; friend class MemoryProgramCache;
friend class Program; friend class Program;
...@@ -367,6 +372,7 @@ class ProgramState final : angle::NonCopyable ...@@ -367,6 +372,7 @@ class ProgramState final : angle::NonCopyable
sh::WorkGroupSize mComputeShaderLocalSize; sh::WorkGroupSize mComputeShaderLocalSize;
ShaderMap<Shader *> mAttachedShaders; ShaderMap<Shader *> mAttachedShaders;
ShaderMap<bool> mAttachedShadersMarkedForDetach;
uint32_t mLocationsUsedForXfbExtension; uint32_t mLocationsUsedForXfbExtension;
std::vector<std::string> mTransformFeedbackVaryingNames; std::vector<std::string> mTransformFeedbackVaryingNames;
...@@ -490,7 +496,7 @@ class Program final : angle::NonCopyable, public LabeledObject ...@@ -490,7 +496,7 @@ class Program final : angle::NonCopyable, public LabeledObject
return mProgram; return mProgram;
} }
void attachShader(Shader *shader); void attachShader(const Context *context, Shader *shader);
void detachShader(const Context *context, Shader *shader); void detachShader(const Context *context, Shader *shader);
int getAttachedShadersCount() const; int getAttachedShadersCount() const;
......
...@@ -4226,7 +4226,8 @@ bool ValidateAttachShader(const Context *context, ShaderProgramID program, Shade ...@@ -4226,7 +4226,8 @@ bool ValidateAttachShader(const Context *context, ShaderProgramID program, Shade
return false; return false;
} }
if (programObject->getAttachedShader(shaderObject->getType())) if (programObject->getAttachedShader(shaderObject->getType()) &&
!programObject->getState().isShaderMarkedForDetach(shaderObject->getType()))
{ {
context->validationError(GL_INVALID_OPERATION, kShaderAttachmentHasShader); context->validationError(GL_INVALID_OPERATION, kShaderAttachmentHasShader);
return false; return false;
......
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