Commit 44a6fbfd by Jamie Madill Committed by Commit Bot

Optimize resolveLink.

This changes the program query to resolve the link if required. If the validation layer is skipped the link is resolved in the gl::Context. Resolving the link on program query allows us to avoid resolving the link on most of the gl::Program query APIs. This improves inlining and particularly affects uniform update. It fixes a performance regression introduced by the parallel shader linking extension. Gives a 17% increased score on a uniform benchmark. Also fixes two missing cases of checking for the extension in our validation code. Note that some bugs might still exist when the validation layer is disabled. Bug: angleproject:2851 Change-Id: I5d725eede3fa147cedf2ce0129791b3412a97a61 Reviewed-on: https://chromium-review.googlesource.com/1255509 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarYuly Novikov <ynovikov@google.com>
parent df836ff8
......@@ -1585,7 +1585,8 @@ class Context final : public egl::LabeledObject, angle::NonCopyable, public angl
bool getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams);
bool getIndexedQueryParameterInfo(GLenum target, GLenum *type, unsigned int *numParams);
Program *getProgram(GLuint handle) const;
Program *getProgramResolveLink(GLuint handle) const;
Program *getProgramNoResolveLink(GLuint handle) const;
Shader *getShader(GLuint handle) const;
bool isTextureGenerated(GLuint texture) const;
......
......@@ -1859,7 +1859,7 @@ FramebufferAttachment *Framebuffer::getAttachmentFromSubjectIndex(angle::Subject
bool Framebuffer::formsRenderingFeedbackLoopWith(const State &state) const
{
const Program *program = state.getProgram();
const Program *program = state.getLinkedProgram();
// TODO(jmadill): Default framebuffer feedback loops.
if (mState.mId == 0)
......
......@@ -538,6 +538,7 @@ Error GLES1Renderer::linkProgram(Context *context,
}
ANGLE_TRY(programObject->link(context));
programObject->resolveLink();
glState->onProgramExecutableChange(programObject);
......
......@@ -512,7 +512,11 @@ class Program final : angle::NonCopyable, public LabeledObject
// Peek whether there is any running linking tasks.
bool isLinking() const;
bool isLinked() const;
bool isLinked() const
{
ASSERT(mLinkResolved);
return mLinked;
}
bool hasLinkedShaderStage(ShaderType shaderType) const
{
......@@ -570,8 +574,19 @@ class Program final : angle::NonCopyable, public LabeledObject
bool isValidUniformLocation(GLint location) const;
const LinkedUniform &getUniformByLocation(GLint location) const;
const VariableLocation &getUniformLocation(GLint location) const;
const std::vector<VariableLocation> &getUniformLocations() const;
const LinkedUniform &getUniformByIndex(GLuint index) const;
const std::vector<VariableLocation> &getUniformLocations() const
{
ASSERT(mLinkResolved);
return mState.mUniformLocations;
}
const LinkedUniform &getUniformByIndex(GLuint index) const
{
ASSERT(mLinkResolved);
ASSERT(index < static_cast<size_t>(mState.mUniforms.size()));
return mState.mUniforms[index];
}
const BufferVariable &getBufferVariableByIndex(GLuint index) const;
......@@ -704,14 +719,14 @@ class Program final : angle::NonCopyable, public LabeledObject
const AttributesMask &getActiveAttribLocationsMask() const
{
resolveLink();
ASSERT(mLinkResolved);
return mState.mActiveAttribLocationsMask;
}
const std::vector<SamplerBinding> &getSamplerBindings() const;
const std::vector<ImageBinding> &getImageBindings() const
{
resolveLink();
ASSERT(mLinkResolved);
return mState.mImageBindings;
}
const sh::WorkGroupSize &getComputeShaderLocalSize() const;
......@@ -722,7 +737,7 @@ class Program final : angle::NonCopyable, public LabeledObject
const ProgramState &getState() const
{
resolveLink();
ASSERT(mLinkResolved);
return mState;
}
......@@ -780,6 +795,15 @@ class Program final : angle::NonCopyable, public LabeledObject
Error syncState(const Context *context);
// Try to resolve linking. Inlined to make sure its overhead is as low as possible.
void resolveLink()
{
if (!mLinkResolved)
{
resolveLinkImpl();
}
}
private:
struct LinkingState;
......@@ -873,16 +897,7 @@ class Program final : angle::NonCopyable, public LabeledObject
GLuint getSamplerUniformBinding(const VariableLocation &uniformLocation) const;
bool validateSamplersImpl(InfoLog *infoLog, const Caps &caps);
// Try to resolve linking.
// Note: this method is frequently called in each draw call. Please make sure its overhead
// is as low as possible.
void resolveLink() const
{
if (!mLinkResolved)
{
return const_cast<Program *>(this)->resolveLinkImpl();
}
}
// Block until linking is finished and resolve it.
void resolveLinkImpl();
......
......@@ -227,7 +227,21 @@ class State : angle::NonCopyable
// Program binding manipulation
void setProgram(const Context *context, Program *newProgram);
Program *getProgram() const { return mProgram; }
Program *getProgram() const
{
ASSERT(!mProgram || !mProgram->isLinking());
return mProgram;
}
Program *getLinkedProgram() const
{
if (mProgram)
{
mProgram->resolveLink();
}
return mProgram;
}
// Transform feedback object (not buffer) binding manipulation
void setTransformFeedbackBinding(const Context *context, TransformFeedback *transformFeedback);
......
......@@ -385,7 +385,7 @@ bool ValidateTextureMaxAnisotropyValue(Context *context, GLfloat paramValue)
bool ValidateFragmentShaderColorBufferTypeMatch(Context *context)
{
const Program *program = context->getGLState().getProgram();
const Program *program = context->getGLState().getLinkedProgram();
const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
return ComponentTypeMask::Validate(program->getDrawBufferTypeMask().to_ulong(),
......@@ -397,7 +397,7 @@ bool ValidateFragmentShaderColorBufferTypeMatch(Context *context)
bool ValidateVertexShaderAttributeTypeMatch(Context *context)
{
const auto &glState = context->getGLState();
const Program *program = context->getGLState().getProgram();
const Program *program = context->getGLState().getLinkedProgram();
const VertexArray *vao = context->getGLState().getVertexArray();
unsigned long stateCurrentValuesTypeBits = glState.getCurrentValuesTypeMask().to_ulong();
......@@ -655,7 +655,7 @@ bool ValidateDrawInstancedANGLE(Context *context)
// Verify there is at least one active attribute with a divisor of zero
const State &state = context->getGLState();
Program *program = state.getProgram();
Program *program = state.getLinkedProgram();
const auto &attribs = state.getVertexArray()->getVertexAttributes();
const auto &bindings = state.getVertexArray()->getVertexBindings();
......@@ -1011,14 +1011,14 @@ bool ValidateWebGLVertexAttribPointer(Context *context,
return true;
}
Program *GetValidProgram(Context *context, GLuint id)
Program *GetValidProgramNoResolve(Context *context, GLuint id)
{
// ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
// generate the error INVALID_VALUE if the provided name is not the name of either a shader
// or program object and INVALID_OPERATION if the provided name identifies an object
// that is not the expected type."
Program *validProgram = context->getProgram(id);
Program *validProgram = context->getProgramNoResolveLink(id);
if (!validProgram)
{
......@@ -1035,6 +1035,16 @@ Program *GetValidProgram(Context *context, GLuint id)
return validProgram;
}
Program *GetValidProgram(Context *context, GLuint id)
{
Program *program = GetValidProgramNoResolve(context, id);
if (program)
{
program->resolveLink();
}
return program;
}
Shader *GetValidShader(Context *context, GLuint id)
{
// See ValidProgram for spec details.
......@@ -1043,7 +1053,7 @@ Shader *GetValidShader(Context *context, GLuint id)
if (!validShader)
{
if (context->getProgram(id))
if (context->getProgramNoResolveLink(id))
{
ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
}
......@@ -2140,7 +2150,7 @@ bool ValidateUniformMatrixValue(Context *context, GLenum valueType, GLenum unifo
bool ValidateUniform(Context *context, GLenum valueType, GLint location, GLsizei count)
{
const LinkedUniform *uniform = nullptr;
Program *programObject = context->getGLState().getProgram();
Program *programObject = context->getGLState().getLinkedProgram();
return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
ValidateUniformValue(context, valueType, uniform->type);
}
......@@ -2148,7 +2158,7 @@ bool ValidateUniform(Context *context, GLenum valueType, GLint location, GLsizei
bool ValidateUniform1iv(Context *context, GLint location, GLsizei count, const GLint *value)
{
const LinkedUniform *uniform = nullptr;
Program *programObject = context->getGLState().getProgram();
Program *programObject = context->getGLState().getLinkedProgram();
return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
ValidateUniform1ivValue(context, uniform->type, count, value);
}
......@@ -2166,7 +2176,7 @@ bool ValidateUniformMatrix(Context *context,
}
const LinkedUniform *uniform = nullptr;
Program *programObject = context->getGLState().getProgram();
Program *programObject = context->getGLState().getLinkedProgram();
return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
ValidateUniformMatrixValue(context, valueType, uniform->type);
}
......@@ -2647,7 +2657,7 @@ const char *ValidateDrawStates(Context *context)
// If we are running GLES1, there is no current program.
if (context->getClientVersion() >= Version(2, 0))
{
Program *program = state.getProgram();
Program *program = state.getLinkedProgram();
if (!program)
{
return kErrorProgramNotBound;
......@@ -2794,7 +2804,7 @@ bool ValidateDrawMode(Context *context, PrimitiveMode mode)
{
const State &state = context->getGLState();
Program *program = state.getProgram();
Program *program = state.getLinkedProgram();
ASSERT(program);
// Do geometry shader specific validations
......@@ -3269,7 +3279,7 @@ static bool ValidateSizedGetUniform(Context *context,
return false;
}
Program *programObject = context->getProgram(program);
Program *programObject = context->getProgramResolveLink(program);
ASSERT(programObject);
// sized queries -- ensure the provided buffer is large enough
......@@ -4405,7 +4415,10 @@ bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GL
*numParams = 1;
}
Program *programObject = GetValidProgram(context, program);
// Special case for GL_COMPLETION_STATUS_KHR: don't resolve the link. Otherwise resolve it now.
Program *programObject = (pname == GL_COMPLETION_STATUS_KHR)
? GetValidProgramNoResolve(context, program)
: GetValidProgram(context, program);
if (!programObject)
{
return false;
......@@ -4415,7 +4428,6 @@ bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GL
{
case GL_DELETE_STATUS:
case GL_LINK_STATUS:
case GL_COMPLETION_STATUS_KHR:
case GL_VALIDATE_STATUS:
case GL_INFO_LOG_LENGTH:
case GL_ATTACHED_SHADERS:
......@@ -4507,6 +4519,14 @@ bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GL
}
break;
case GL_COMPLETION_STATUS_KHR:
if (!context->getExtensions().parallelShaderCompile)
{
ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
return false;
}
break;
default:
ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
return false;
......@@ -5357,7 +5377,6 @@ bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsi
case GL_SHADER_TYPE:
case GL_DELETE_STATUS:
case GL_COMPILE_STATUS:
case GL_COMPLETION_STATUS_KHR:
case GL_INFO_LOG_LENGTH:
case GL_SHADER_SOURCE_LENGTH:
break;
......@@ -5370,6 +5389,14 @@ bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsi
}
break;
case GL_COMPLETION_STATUS_KHR:
if (!context->getExtensions().parallelShaderCompile)
{
ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
return false;
}
break;
default:
ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
return false;
......
......@@ -2250,7 +2250,7 @@ static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier,
return true;
case GL_PROGRAM:
if (context->getProgram(name) == nullptr)
if (context->getProgramNoResolveLink(name) == nullptr)
{
context->handleError(InvalidValue() << "name is not a valid program.");
return false;
......@@ -3843,7 +3843,7 @@ bool ValidateBindFragmentInputLocationCHROMIUM(Context *context,
return false;
}
const auto *programObject = context->getProgram(program);
const auto *programObject = context->getProgramNoResolveLink(program);
if (!programObject)
{
ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
......@@ -3878,7 +3878,7 @@ bool ValidateProgramPathFragmentInputGenCHROMIUM(Context *context,
return false;
}
const auto *programObject = context->getProgram(program);
const auto *programObject = context->getProgramResolveLink(program);
if (!programObject || programObject->isFlaggedForDeletion())
{
ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramDoesNotExist);
......@@ -4933,7 +4933,7 @@ bool ValidateDeleteProgram(Context *context, GLuint program)
return false;
}
if (!context->getProgram(program))
if (!context->getProgramResolveLink(program))
{
if (context->getShader(program))
{
......@@ -4959,7 +4959,7 @@ bool ValidateDeleteShader(Context *context, GLuint shader)
if (!context->getShader(shader))
{
if (context->getProgram(shader))
if (context->getProgramResolveLink(shader))
{
ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidShaderName);
return false;
......@@ -6322,7 +6322,7 @@ bool ValidateUseProgram(Context *context, GLuint program)
{
if (program != 0)
{
Program *programObject = context->getProgram(program);
Program *programObject = context->getProgramResolveLink(program);
if (!programObject)
{
// ES 3.1.0 section 7.3 page 72
......
......@@ -2192,7 +2192,7 @@ bool ValidateBeginTransformFeedback(Context *context, PrimitiveMode primitiveMod
}
}
Program *program = context->getGLState().getProgram();
Program *program = context->getGLState().getLinkedProgram();
if (!program)
{
......
......@@ -1419,7 +1419,7 @@ bool ValidateDispatchCompute(Context *context,
}
const State &state = context->getGLState();
Program *program = state.getProgram();
Program *program = state.getLinkedProgram();
if (program == nullptr || !program->hasLinkedShaderStage(ShaderType::Compute))
{
......@@ -1462,7 +1462,7 @@ bool ValidateDispatchComputeIndirect(Context *context, GLintptr indirect)
}
const State &state = context->getGLState();
Program *program = state.getProgram();
Program *program = state.getLinkedProgram();
if (program == nullptr || !program->hasLinkedShaderStage(ShaderType::Compute))
{
......
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