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)
Program *programObject = mState.mShaderProgramManager->getProgram(program);
Shader *shaderObject = mState.mShaderProgramManager->getShader(shader);
ASSERT(programObject && shaderObject);
programObject->attachShader(shaderObject);
programObject->attachShader(this, shaderObject);
}
void Context::copyBufferSubData(BufferBinding readTarget,
......
......@@ -559,8 +559,8 @@ angle::Result GLES1Renderer::linkProgram(Context *context,
*programOut = program;
programObject->attachShader(getShader(vertexShader));
programObject->attachShader(getShader(fragmentShader));
programObject->attachShader(context, getShader(vertexShader));
programObject->attachShader(context, getShader(fragmentShader));
for (auto it : attribLocs)
{
......
......@@ -1091,6 +1091,7 @@ ImageBinding::~ImageBinding() = default;
ProgramState::ProgramState()
: mLabel(),
mAttachedShaders{},
mAttachedShadersMarkedForDetach{},
mTransformFeedbackBufferMode(GL_INTERLEAVED_ATTRIBS),
mDefaultUniformRange(0, 0),
mSamplerUniformRange(0, 0),
......@@ -1299,7 +1300,8 @@ void Program::onDestroy(const Context *context)
if (mState.mAttachedShaders[shaderType])
{
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
return mState.mLabel;
}
void Program::attachShader(Shader *shader)
void Program::attachShader(const Context *context, Shader *shader)
{
ASSERT(mLinkResolved);
ShaderType shaderType = shader->getType();
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]->addRef();
}
......@@ -1345,8 +1356,19 @@ void Program::detachShader(const Context *context, Shader *shader)
ASSERT(shaderType != ShaderType::InvalidEnum);
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);
mState.mAttachedShaders[shaderType] = nullptr;
mState.mAttachedShaders[shaderType] = nullptr;
mState.mAttachedShadersMarkedForDetach[shaderType] = false;
}
int Program::getAttachedShadersCount() const
......
......@@ -349,6 +349,11 @@ class ProgramState final : angle::NonCopyable
return !getLinkedTransformFeedbackVaryings().empty();
}
bool isShaderMarkedForDetach(gl::ShaderType shaderType) const
{
return mAttachedShadersMarkedForDetach[shaderType];
}
private:
friend class MemoryProgramCache;
friend class Program;
......@@ -367,6 +372,7 @@ class ProgramState final : angle::NonCopyable
sh::WorkGroupSize mComputeShaderLocalSize;
ShaderMap<Shader *> mAttachedShaders;
ShaderMap<bool> mAttachedShadersMarkedForDetach;
uint32_t mLocationsUsedForXfbExtension;
std::vector<std::string> mTransformFeedbackVaryingNames;
......@@ -490,7 +496,7 @@ class Program final : angle::NonCopyable, public LabeledObject
return mProgram;
}
void attachShader(Shader *shader);
void attachShader(const Context *context, Shader *shader);
void detachShader(const Context *context, Shader *shader);
int getAttachedShadersCount() const;
......
......@@ -4226,7 +4226,8 @@ bool ValidateAttachShader(const Context *context, ShaderProgramID program, Shade
return false;
}
if (programObject->getAttachedShader(shaderObject->getType()))
if (programObject->getAttachedShader(shaderObject->getType()) &&
!programObject->getState().isShaderMarkedForDetach(shaderObject->getType()))
{
context->validationError(GL_INVALID_OPERATION, kShaderAttachmentHasShader);
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