GL: Use the executable instead of program

In a few places, the program was still being directly referenced instead
of the executable (in particular when dealing with multiview).

Bug: angleproject:8297
Change-Id: I15d0865bf58376a9f85efeec739dd93b49ceaea7
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/4846475
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
This commit is contained in:
Shahbaz Youssefi
2023-09-06 13:23:34 -04:00
committed by Angle LUCI CQ
parent 632ded9e0a
commit 06411d1623
11 changed files with 277 additions and 155 deletions

View File

@@ -37,6 +37,25 @@
namespace rx
{
namespace
{
GLsizei GetDrawAdjustedInstanceCount(const gl::ProgramExecutable *executable)
{
const bool usesMultiview = executable->usesMultiview();
return usesMultiview ? executable->getNumViews() : 0;
}
GLsizei GetInstancedDrawAdjustedInstanceCount(const gl::ProgramExecutable *executable,
GLsizei instanceCount)
{
GLsizei adjustedInstanceCount = instanceCount;
if (executable->usesMultiview())
{
adjustedInstanceCount *= executable->getNumViews();
}
return adjustedInstanceCount;
}
} // anonymous namespace
ContextGL::ContextGL(const gl::State &state,
gl::ErrorSet *errorSet,
@@ -322,16 +341,15 @@ angle::Result ContextGL::drawArrays(const gl::Context *context,
GLint first,
GLsizei count)
{
const gl::Program *program = context->getState().getProgram();
const bool usesMultiview = program->usesMultiview();
const GLsizei instanceCount = usesMultiview ? program->getNumViews() : 0;
const gl::ProgramExecutable *executable = context->getState().getProgramExecutable();
const GLsizei instanceCount = GetDrawAdjustedInstanceCount(executable);
#if defined(ANGLE_STATE_VALIDATION_ENABLED)
validateState();
#endif
ANGLE_TRY(setDrawArraysState(context, first, count, instanceCount));
if (!usesMultiview)
if (!executable->usesMultiview())
{
ANGLE_GL_TRY(context, getFunctions()->drawArrays(ToGLenum(mode), first, count));
}
@@ -351,12 +369,9 @@ angle::Result ContextGL::drawArraysInstanced(const gl::Context *context,
GLsizei count,
GLsizei instanceCount)
{
GLsizei adjustedInstanceCount = instanceCount;
const gl::Program *program = context->getState().getProgram();
if (program->usesMultiview())
{
adjustedInstanceCount *= program->getNumViews();
}
const gl::ProgramExecutable *executable = context->getState().getProgramExecutable();
const GLsizei adjustedInstanceCount =
GetInstancedDrawAdjustedInstanceCount(executable, instanceCount);
ANGLE_TRY(setDrawArraysState(context, first, count, adjustedInstanceCount));
ANGLE_GL_TRY(context, getFunctions()->drawArraysInstanced(ToGLenum(mode), first, count,
@@ -366,8 +381,7 @@ angle::Result ContextGL::drawArraysInstanced(const gl::Context *context,
return angle::Result::Continue;
}
gl::AttributesMask ContextGL::updateAttributesForBaseInstance(const gl::Program *program,
GLuint baseInstance)
gl::AttributesMask ContextGL::updateAttributesForBaseInstance(GLuint baseInstance)
{
const gl::ProgramExecutable *executable = getState().getProgramExecutable();
gl::AttributesMask attribToUpdateMask;
@@ -450,12 +464,9 @@ angle::Result ContextGL::drawArraysInstancedBaseInstance(const gl::Context *cont
GLsizei instanceCount,
GLuint baseInstance)
{
GLsizei adjustedInstanceCount = instanceCount;
const gl::Program *program = context->getState().getProgram();
if (program->usesMultiview())
{
adjustedInstanceCount *= program->getNumViews();
}
const gl::ProgramExecutable *executable = context->getState().getProgramExecutable();
const GLsizei adjustedInstanceCount =
GetInstancedDrawAdjustedInstanceCount(executable, instanceCount);
ANGLE_TRY(setDrawArraysState(context, first, count, adjustedInstanceCount));
@@ -475,8 +486,7 @@ angle::Result ContextGL::drawArraysInstancedBaseInstance(const gl::Context *cont
// pointer offset calling vertexAttribPointer Will refactor stateCache and pass baseInstance
// to setDrawArraysState to set pointer offset
gl::AttributesMask attribToResetMask =
updateAttributesForBaseInstance(program, baseInstance);
gl::AttributesMask attribToResetMask = updateAttributesForBaseInstance(baseInstance);
ANGLE_GL_TRY(context, functions->drawArraysInstanced(ToGLenum(mode), first, count,
adjustedInstanceCount));
@@ -495,18 +505,17 @@ angle::Result ContextGL::drawElements(const gl::Context *context,
gl::DrawElementsType type,
const void *indices)
{
const gl::State &glState = context->getState();
const gl::Program *program = glState.getProgram();
const bool usesMultiview = program->usesMultiview();
const GLsizei instanceCount = usesMultiview ? program->getNumViews() : 0;
const void *drawIndexPtr = nullptr;
const gl::State &glState = context->getState();
const gl::ProgramExecutable *executable = glState.getProgramExecutable();
const GLsizei instanceCount = GetDrawAdjustedInstanceCount(executable);
const void *drawIndexPtr = nullptr;
#if defined(ANGLE_STATE_VALIDATION_ENABLED)
validateState();
#endif // ANGLE_STATE_VALIDATION_ENABLED
ANGLE_TRY(setDrawElementsState(context, count, type, indices, instanceCount, &drawIndexPtr));
if (!usesMultiview)
if (!executable->usesMultiview())
{
ANGLE_GL_TRY(context, getFunctions()->drawElements(ToGLenum(mode), count, ToGLenum(type),
drawIndexPtr));
@@ -529,18 +538,17 @@ angle::Result ContextGL::drawElementsBaseVertex(const gl::Context *context,
const void *indices,
GLint baseVertex)
{
const gl::State &glState = context->getState();
const gl::Program *program = glState.getProgram();
const bool usesMultiview = program->usesMultiview();
const GLsizei instanceCount = usesMultiview ? program->getNumViews() : 0;
const void *drawIndexPtr = nullptr;
const gl::State &glState = context->getState();
const gl::ProgramExecutable *executable = glState.getProgramExecutable();
const GLsizei instanceCount = GetDrawAdjustedInstanceCount(executable);
const void *drawIndexPtr = nullptr;
#if defined(ANGLE_STATE_VALIDATION_ENABLED)
validateState();
#endif // ANGLE_STATE_VALIDATION_ENABLED
ANGLE_TRY(setDrawElementsState(context, count, type, indices, instanceCount, &drawIndexPtr));
if (!usesMultiview)
if (!executable->usesMultiview())
{
ANGLE_GL_TRY(context, getFunctions()->drawElementsBaseVertex(
ToGLenum(mode), count, ToGLenum(type), drawIndexPtr, baseVertex));
@@ -563,12 +571,9 @@ angle::Result ContextGL::drawElementsInstanced(const gl::Context *context,
const void *indices,
GLsizei instances)
{
GLsizei adjustedInstanceCount = instances;
const gl::Program *program = context->getState().getProgram();
if (program->usesMultiview())
{
adjustedInstanceCount *= program->getNumViews();
}
const gl::ProgramExecutable *executable = context->getState().getProgramExecutable();
const GLsizei adjustedInstanceCount =
GetInstancedDrawAdjustedInstanceCount(executable, instances);
const void *drawIndexPointer = nullptr;
ANGLE_TRY(setDrawElementsState(context, count, type, indices, adjustedInstanceCount,
@@ -587,12 +592,9 @@ angle::Result ContextGL::drawElementsInstancedBaseVertex(const gl::Context *cont
GLsizei instances,
GLint baseVertex)
{
GLsizei adjustedInstanceCount = instances;
const gl::Program *program = context->getState().getProgram();
if (program->usesMultiview())
{
adjustedInstanceCount *= program->getNumViews();
}
const gl::ProgramExecutable *executable = context->getState().getProgramExecutable();
const GLsizei adjustedInstanceCount =
GetInstancedDrawAdjustedInstanceCount(executable, instances);
const void *drawIndexPointer = nullptr;
ANGLE_TRY(setDrawElementsState(context, count, type, indices, adjustedInstanceCount,
@@ -614,12 +616,9 @@ angle::Result ContextGL::drawElementsInstancedBaseVertexBaseInstance(const gl::C
GLint baseVertex,
GLuint baseInstance)
{
GLsizei adjustedInstanceCount = instances;
const gl::Program *program = context->getState().getProgram();
if (program->usesMultiview())
{
adjustedInstanceCount *= program->getNumViews();
}
const gl::ProgramExecutable *executable = context->getState().getProgramExecutable();
const GLsizei adjustedInstanceCount =
GetInstancedDrawAdjustedInstanceCount(executable, instances);
const void *drawIndexPointer = nullptr;
ANGLE_TRY(setDrawElementsState(context, count, type, indices, adjustedInstanceCount,
@@ -638,8 +637,7 @@ angle::Result ContextGL::drawElementsInstancedBaseVertexBaseInstance(const gl::C
{
// GL 3.3+ or GLES 3.2+
// TODO(http://anglebug.com/3910): same as above
gl::AttributesMask attribToResetMask =
updateAttributesForBaseInstance(program, baseInstance);
gl::AttributesMask attribToResetMask = updateAttributesForBaseInstance(baseInstance);
ANGLE_GL_TRY(context, functions->drawElementsInstancedBaseVertex(
ToGLenum(mode), count, ToGLenum(type), drawIndexPointer,
@@ -661,14 +659,13 @@ angle::Result ContextGL::drawRangeElements(const gl::Context *context,
gl::DrawElementsType type,
const void *indices)
{
const gl::Program *program = context->getState().getProgram();
const bool usesMultiview = program->usesMultiview();
const GLsizei instanceCount = usesMultiview ? program->getNumViews() : 0;
const void *drawIndexPointer = nullptr;
const gl::ProgramExecutable *executable = mState.getProgramExecutable();
const GLsizei instanceCount = GetDrawAdjustedInstanceCount(executable);
const void *drawIndexPointer = nullptr;
ANGLE_TRY(
setDrawElementsState(context, count, type, indices, instanceCount, &drawIndexPointer));
if (!usesMultiview)
if (!executable->usesMultiview())
{
ANGLE_GL_TRY(context, getFunctions()->drawRangeElements(ToGLenum(mode), start, end, count,
ToGLenum(type), drawIndexPointer));
@@ -693,14 +690,13 @@ angle::Result ContextGL::drawRangeElementsBaseVertex(const gl::Context *context,
const void *indices,
GLint baseVertex)
{
const gl::Program *program = context->getState().getProgram();
const bool usesMultiview = program->usesMultiview();
const GLsizei instanceCount = usesMultiview ? program->getNumViews() : 0;
const void *drawIndexPointer = nullptr;
const gl::ProgramExecutable *executable = mState.getProgramExecutable();
const GLsizei instanceCount = GetDrawAdjustedInstanceCount(executable);
const void *drawIndexPointer = nullptr;
ANGLE_TRY(
setDrawElementsState(context, count, type, indices, instanceCount, &drawIndexPointer));
if (!usesMultiview)
if (!executable->usesMultiview())
{
ANGLE_GL_TRY(context, getFunctions()->drawRangeElementsBaseVertex(
ToGLenum(mode), start, end, count, ToGLenum(type),

View File

@@ -313,8 +313,7 @@ class ContextGL : public ContextImpl
GLsizei instanceCount,
const void **outIndices);
gl::AttributesMask updateAttributesForBaseInstance(const gl::Program *program,
GLuint baseInstance);
gl::AttributesMask updateAttributesForBaseInstance(GLuint baseInstance);
void resetUpdatedAttributes(gl::AttributesMask attribMask);
// Resets draw state prior to drawing load/store operations for EXT_shader_pixel_local_storage,

View File

@@ -1372,8 +1372,8 @@ angle::Result FramebufferGL::syncState(const gl::Context *context,
if (attachment && mState.id() == context->getState().getDrawFramebuffer()->id())
{
stateManager->updateMultiviewBaseViewLayerIndexUniform(context->getState().getProgram(),
getState());
stateManager->updateMultiviewBaseViewLayerIndexUniform(
context->getState().getProgramExecutable(), getState());
}
return angle::Result::Continue;

View File

@@ -19,7 +19,9 @@ ProgramExecutableGL::ProgramExecutableGL(const gl::ProgramExecutable *executable
: ProgramExecutableImpl(executable),
mHasAppliedTransformFeedbackVaryings(false),
mClipDistanceEnabledUniformLocation(-1),
mMultiviewBaseViewLayerIndexUniformLocation(-1)
mMultiviewBaseViewLayerIndexUniformLocation(-1),
mProgramID(0),
mFunctions(nullptr)
{}
ProgramExecutableGL::~ProgramExecutableGL() {}
@@ -39,6 +41,11 @@ void ProgramExecutableGL::postLink(const FunctionsGL *functions,
const angle::FeaturesGL &features,
GLuint programID)
{
// Cache the following so the executable is capable of making the appropriate GL calls without
// having to involve ProgramGL.
mProgramID = programID;
mFunctions = functions;
// Query the uniform information
ASSERT(mUniformRealLocationMap.empty());
const auto &uniformLocations = mExecutable->getUniformLocations();
@@ -88,4 +95,25 @@ void ProgramExecutableGL::postLink(const FunctionsGL *functions,
ASSERT(mMultiviewBaseViewLayerIndexUniformLocation != -1);
}
}
void ProgramExecutableGL::updateEnabledClipDistances(uint8_t enabledClipDistancesPacked) const
{
ASSERT(mExecutable->hasClipDistance());
ASSERT(mClipDistanceEnabledUniformLocation != -1);
ASSERT(mFunctions->programUniform1ui != nullptr);
mFunctions->programUniform1ui(mProgramID, mClipDistanceEnabledUniformLocation,
enabledClipDistancesPacked);
}
void ProgramExecutableGL::enableLayeredRenderingPath(int baseViewIndex) const
{
ASSERT(mExecutable->usesMultiview());
ASSERT(mMultiviewBaseViewLayerIndexUniformLocation != -1);
ASSERT(mFunctions->programUniform1i != nullptr);
mFunctions->programUniform1i(mProgramID, mMultiviewBaseViewLayerIndexUniformLocation,
baseViewIndex);
}
} // namespace rx

View File

@@ -29,6 +29,10 @@ class ProgramExecutableGL : public ProgramExecutableImpl
void destroy(const gl::Context *context) override;
void updateEnabledClipDistances(uint8_t enabledClipDistancesPacked) const;
void enableLayeredRenderingPath(int baseViewIndex) const;
private:
friend class ProgramGL;
@@ -45,6 +49,10 @@ class ProgramExecutableGL : public ProgramExecutableImpl
GLint mClipDistanceEnabledUniformLocation;
GLint mMultiviewBaseViewLayerIndexUniformLocation;
// The program for which the executable was built
GLuint mProgramID;
const FunctionsGL *mFunctions;
};
} // namespace rx

View File

@@ -968,26 +968,6 @@ bool ProgramGL::checkLinkStatus()
return true;
}
void ProgramGL::updateEnabledClipDistances(uint8_t enabledClipDistancesPacked) const
{
ASSERT(mState.getExecutable().hasClipDistance());
ASSERT(getExecutable()->mClipDistanceEnabledUniformLocation != -1);
ASSERT(mFunctions->programUniform1ui != nullptr);
mFunctions->programUniform1ui(mProgramID, getExecutable()->mClipDistanceEnabledUniformLocation,
enabledClipDistancesPacked);
}
void ProgramGL::enableLayeredRenderingPath(int baseViewIndex) const
{
ASSERT(mState.getExecutable().usesMultiview());
ASSERT(getExecutable()->mMultiviewBaseViewLayerIndexUniformLocation != -1);
ASSERT(mFunctions->programUniform1i != nullptr);
mFunctions->programUniform1i(
mProgramID, getExecutable()->mMultiviewBaseViewLayerIndexUniformLocation, baseViewIndex);
}
void ProgramGL::getUniformfv(const gl::Context *context, GLint location, GLfloat *params) const
{
mFunctions->getUniformfv(mProgramID, uniLoc(location), params);

View File

@@ -110,10 +110,6 @@ class ProgramGL : public ProgramImpl
ANGLE_INLINE GLuint getProgramID() const { return mProgramID; }
void updateEnabledClipDistances(uint8_t enabledClipDistancesPacked) const;
void enableLayeredRenderingPath(int baseViewIndex) const;
angle::Result syncState(const gl::Context *context,
const gl::Program::DirtyBits &dirtyBits) override;

View File

@@ -1006,13 +1006,13 @@ void StateManagerGL::updateProgramTextureBindings(const gl::Context *context)
void StateManagerGL::updateProgramStorageBufferBindings(const gl::Context *context)
{
const gl::State &glState = context->getState();
const gl::Program *program = glState.getProgram();
const gl::State &glState = context->getState();
const gl::ProgramExecutable *executable = glState.getProgramExecutable();
for (size_t blockIndex = 0; blockIndex < program->getActiveShaderStorageBlockCount();
for (size_t blockIndex = 0; blockIndex < executable->getActiveShaderStorageBlockCount();
blockIndex++)
{
GLuint binding = program->getShaderStorageBlockBinding(static_cast<GLuint>(blockIndex));
GLuint binding = executable->getShaderStorageBlockBinding(static_cast<GLuint>(blockIndex));
const auto &shaderStorageBuffer = glState.getIndexedShaderStorageBuffer(binding);
if (shaderStorageBuffer.get() != nullptr)
@@ -1034,14 +1034,14 @@ void StateManagerGL::updateProgramStorageBufferBindings(const gl::Context *conte
void StateManagerGL::updateProgramUniformBufferBindings(const gl::Context *context)
{
// Sync the current program state
const gl::State &glState = context->getState();
const gl::Program *program = glState.getProgram();
// Sync the current program executable state
const gl::State &glState = context->getState();
const gl::ProgramExecutable *executable = glState.getProgramExecutable();
for (size_t uniformBlockIndex = 0; uniformBlockIndex < program->getActiveUniformBlockCount();
for (size_t uniformBlockIndex = 0; uniformBlockIndex < executable->getActiveUniformBlockCount();
uniformBlockIndex++)
{
GLuint binding = program->getUniformBlockBinding(static_cast<GLuint>(uniformBlockIndex));
GLuint binding = executable->getUniformBlockBinding(static_cast<GLuint>(uniformBlockIndex));
const auto &uniformBuffer = glState.getIndexedUniformBuffer(binding);
if (uniformBuffer.get() != nullptr)
@@ -1063,10 +1063,10 @@ void StateManagerGL::updateProgramUniformBufferBindings(const gl::Context *conte
void StateManagerGL::updateProgramAtomicCounterBufferBindings(const gl::Context *context)
{
const gl::State &glState = context->getState();
const gl::Program *program = glState.getProgram();
const gl::State &glState = context->getState();
const gl::ProgramExecutable *executable = glState.getProgramExecutable();
for (const auto &atomicCounterBuffer : program->getState().getAtomicCounterBuffers())
for (const auto &atomicCounterBuffer : executable->getAtomicCounterBuffers())
{
GLuint binding = atomicCounterBuffer.binding;
const auto &buffer = glState.getIndexedAtomicCounterBuffer(binding);
@@ -1100,7 +1100,7 @@ void StateManagerGL::updateProgramImageBindings(const gl::Context *context)
ASSERT(context->getClientVersion() >= gl::ES_3_1 ||
context->getExtensions().shaderPixelLocalStorageANGLE ||
program->getImageBindings().empty());
executable->getImageBindings().empty());
for (size_t imageUnitIndex : executable->getActiveImagesMask())
{
const gl::ImageUnit &imageUnit = glState.getImageUnit(imageUnitIndex);
@@ -2171,10 +2171,10 @@ angle::Result StateManagerGL::syncState(const gl::Context *context,
mHasSeparateFramebufferBindings ? GL_DRAW_FRAMEBUFFER : GL_FRAMEBUFFER,
framebufferGL->getFramebufferID());
const gl::Program *program = state.getProgram();
if (program)
const gl::ProgramExecutable *executable = state.getProgramExecutable();
if (executable)
{
updateMultiviewBaseViewLayerIndexUniform(program, framebufferGL->getState());
updateMultiviewBaseViewLayerIndexUniform(executable, framebufferGL->getState());
}
// Changing the draw framebuffer binding sometimes requires resetting srgb blending.
@@ -2193,7 +2193,7 @@ angle::Result StateManagerGL::syncState(const gl::Context *context,
VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(state.getVertexArray());
bindVertexArray(vaoGL->getVertexArrayID(), vaoGL->getNativeState());
ANGLE_TRY(propagateProgramToVAO(context, state.getProgram(),
ANGLE_TRY(propagateProgramToVAO(context, state.getProgramExecutable(),
GetImplAs<VertexArrayGL>(state.getVertexArray())));
if (mFeatures.syncVertexArraysToDefault.enabled)
@@ -2240,10 +2240,9 @@ angle::Result StateManagerGL::syncState(const gl::Context *context,
}
case gl::state::DIRTY_BIT_PROGRAM_EXECUTABLE:
{
const gl::Program *program = state.getProgram();
const gl::ProgramExecutable *executable = state.getProgramExecutable();
if (program && executable)
if (executable)
{
iter.setLaterBit(gl::state::DIRTY_BIT_TEXTURE_BINDINGS);
@@ -2252,39 +2251,39 @@ angle::Result StateManagerGL::syncState(const gl::Context *context,
iter.setLaterBit(gl::state::DIRTY_BIT_IMAGE_BINDINGS);
}
if (program->getActiveShaderStorageBlockCount() > 0)
if (executable->getActiveShaderStorageBlockCount() > 0)
{
iter.setLaterBit(gl::state::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING);
}
if (program->getActiveUniformBlockCount() > 0)
if (executable->getActiveUniformBlockCount() > 0)
{
iter.setLaterBit(gl::state::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS);
}
if (program->getActiveAtomicCounterBufferCount() > 0)
if (executable->getActiveAtomicCounterBufferCount() > 0)
{
iter.setLaterBit(gl::state::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING);
}
if (mIsMultiviewEnabled && program->usesMultiview())
if (mIsMultiviewEnabled && executable->usesMultiview())
{
updateMultiviewBaseViewLayerIndexUniform(
program, state.getDrawFramebuffer()->getImplementation()->getState());
executable,
state.getDrawFramebuffer()->getImplementation()->getState());
}
if (mFeatures.emulateClipDistanceState.enabled)
{
updateEmulatedClipDistanceState(executable, program,
updateEmulatedClipDistanceState(executable,
state.getEnabledClipDistances());
}
}
if (!program ||
!program->getExecutable().hasLinkedShaderStage(gl::ShaderType::Compute))
if (!executable || !executable->hasLinkedShaderStage(gl::ShaderType::Compute))
{
ANGLE_TRY(propagateProgramToVAO(
context, program, GetImplAs<VertexArrayGL>(state.getVertexArray())));
context, executable, GetImplAs<VertexArrayGL>(state.getVertexArray())));
}
break;
}
@@ -2367,7 +2366,6 @@ angle::Result StateManagerGL::syncState(const gl::Context *context,
if (mFeatures.emulateClipDistanceState.enabled)
{
updateEmulatedClipDistanceState(state.getProgramExecutable(),
state.getProgram(),
state.getEnabledClipDistances());
}
break;
@@ -2690,7 +2688,7 @@ void StateManagerGL::setTextureCubemapSeamlessEnabled(bool enabled)
}
angle::Result StateManagerGL::propagateProgramToVAO(const gl::Context *context,
const gl::Program *program,
const gl::ProgramExecutable *executable,
VertexArrayGL *vao)
{
if (vao == nullptr)
@@ -2701,45 +2699,44 @@ angle::Result StateManagerGL::propagateProgramToVAO(const gl::Context *context,
// Number of views:
if (mIsMultiviewEnabled)
{
int programNumViews = 1;
if (program && program->usesMultiview())
int numViews = 1;
if (executable && executable->usesMultiview())
{
programNumViews = program->getNumViews();
numViews = executable->getNumViews();
}
ANGLE_TRY(vao->applyNumViewsToDivisor(context, programNumViews));
ANGLE_TRY(vao->applyNumViewsToDivisor(context, numViews));
}
// Attribute enabled mask:
if (program)
if (executable)
{
ANGLE_TRY(vao->applyActiveAttribLocationsMask(
context, program->getExecutable().getActiveAttribLocationsMask()));
ANGLE_TRY(vao->applyActiveAttribLocationsMask(context,
executable->getActiveAttribLocationsMask()));
}
return angle::Result::Continue;
}
void StateManagerGL::updateMultiviewBaseViewLayerIndexUniformImpl(
const gl::Program *program,
const gl::ProgramExecutable *executable,
const gl::FramebufferState &drawFramebufferState) const
{
ASSERT(mIsMultiviewEnabled && program && program->usesMultiview());
const ProgramGL *programGL = GetImplAs<ProgramGL>(program);
ASSERT(mIsMultiviewEnabled && executable && executable->usesMultiview());
const ProgramExecutableGL *executableGL = GetImplAs<ProgramExecutableGL>(executable);
if (drawFramebufferState.isMultiview())
{
programGL->enableLayeredRenderingPath(drawFramebufferState.getBaseViewIndex());
executableGL->enableLayeredRenderingPath(drawFramebufferState.getBaseViewIndex());
}
}
void StateManagerGL::updateEmulatedClipDistanceState(const gl::ProgramExecutable *executable,
const gl::Program *program,
const gl::ClipDistanceEnableBits enables) const
{
ASSERT(mFeatures.emulateClipDistanceState.enabled);
if (executable && executable->hasClipDistance())
{
const ProgramGL *programGL = GetImplAs<ProgramGL>(program);
programGL->updateEnabledClipDistances(static_cast<uint8_t>(enables.bits()));
const ProgramExecutableGL *executableGL = GetImplAs<ProgramExecutableGL>(executable);
executableGL->updateEnabledClipDistances(static_cast<uint8_t>(enables.bits()));
}
}

View File

@@ -290,12 +290,12 @@ class StateManagerGL final : angle::NonCopyable
const gl::state::ExtendedDirtyBits &extendedBitMask);
ANGLE_INLINE void updateMultiviewBaseViewLayerIndexUniform(
const gl::Program *program,
const gl::ProgramExecutable *executable,
const gl::FramebufferState &drawFramebufferState) const
{
if (mIsMultiviewEnabled && program && program->usesMultiview())
if (mIsMultiviewEnabled && executable && executable->usesMultiview())
{
updateMultiviewBaseViewLayerIndexUniformImpl(program, drawFramebufferState);
updateMultiviewBaseViewLayerIndexUniformImpl(executable, drawFramebufferState);
}
}
@@ -322,7 +322,7 @@ class StateManagerGL final : angle::NonCopyable
void setTextureCubemapSeamlessEnabled(bool enabled);
angle::Result propagateProgramToVAO(const gl::Context *context,
const gl::Program *program,
const gl::ProgramExecutable *executable,
VertexArrayGL *vao);
void updateProgramTextureBindings(const gl::Context *context);
@@ -344,11 +344,10 @@ class StateManagerGL final : angle::NonCopyable
void syncTransformFeedbackState(const gl::Context *context);
void updateEmulatedClipDistanceState(const gl::ProgramExecutable *executable,
const gl::Program *program,
const gl::ClipDistanceEnableBits enables) const;
void updateMultiviewBaseViewLayerIndexUniformImpl(
const gl::Program *program,
const gl::ProgramExecutable *executable,
const gl::FramebufferState &drawFramebufferState) const;
void syncBlendFromNativeContext(const gl::Extensions &extensions, ExternalContextState *state);

View File

@@ -482,17 +482,16 @@ bool ValidateTextureMaxAnisotropyValue(const Context *context,
bool ValidateFragmentShaderColorBufferMaskMatch(const Context *context)
{
const auto &glState = context->getState();
const Program *program = context->getActiveLinkedProgram();
const Framebuffer *framebuffer = glState.getDrawFramebuffer();
const auto &glState = context->getState();
const ProgramExecutable *executable = context->getState().getLinkedProgramExecutable(context);
const Framebuffer *framebuffer = glState.getDrawFramebuffer();
const auto &blendStateExt = glState.getBlendStateExt();
auto drawBufferMask = framebuffer->getDrawBufferMask() & blendStateExt.compareColorMask(0);
auto dualSourceBlendingMask = drawBufferMask & blendStateExt.getEnabledMask() &
blendStateExt.getUsesExtendedBlendFactorMask();
auto fragmentOutputMask = program->getExecutable().getActiveOutputVariablesMask();
auto fragmentSecondaryOutputMask =
program->getExecutable().getActiveSecondaryOutputVariablesMask();
auto fragmentOutputMask = executable->getActiveOutputVariablesMask();
auto fragmentSecondaryOutputMask = executable->getActiveSecondaryOutputVariablesMask();
return drawBufferMask == (drawBufferMask & fragmentOutputMask) &&
dualSourceBlendingMask == (dualSourceBlendingMask & fragmentSecondaryOutputMask);
@@ -511,11 +510,11 @@ bool ValidateFragmentShaderColorBufferTypeMatch(const Context *context)
bool ValidateVertexShaderAttributeTypeMatch(const Context *context)
{
const auto &glState = context->getState();
const Program *program = context->getActiveLinkedProgram();
const VertexArray *vao = context->getState().getVertexArray();
const auto &glState = context->getState();
const ProgramExecutable *executable = context->getState().getLinkedProgramExecutable(context);
const VertexArray *vao = context->getState().getVertexArray();
if (!program)
if (executable == nullptr)
{
return false;
}
@@ -528,9 +527,8 @@ bool ValidateVertexShaderAttributeTypeMatch(const Context *context)
vaoAttribTypeBits = (vaoAttribEnabledMask & vaoAttribTypeBits);
vaoAttribTypeBits |= (~vaoAttribEnabledMask & stateCurrentValuesTypeBits);
const ProgramExecutable &executable = program->getExecutable();
return ValidateComponentTypeMasks(executable.getAttributesTypeMask().to_ulong(),
vaoAttribTypeBits, executable.getAttributesMask().to_ulong(),
return ValidateComponentTypeMasks(executable->getAttributesTypeMask().to_ulong(),
vaoAttribTypeBits, executable->getAttributesMask().to_ulong(),
0xFFFF);
}
@@ -4402,7 +4400,7 @@ const char *ValidateDrawStates(const Context *context, GLenum *outErrorCode)
}
// Validate that we are rendering with a linked program.
if (executable == nullptr)
if (!program->isLinked())
{
return kProgramNotLinked;
}

View File

@@ -398,6 +398,12 @@ class MultiviewRenderDualViewTest : public MultiviewRenderTest
GLuint mProgram;
};
class MultiviewRenderDualViewTestNoWebGL : public MultiviewRenderDualViewTest
{
protected:
MultiviewRenderDualViewTestNoWebGL() { setWebGLCompatibilityEnabled(false); }
};
// Base class for tests that care mostly about draw call validity and not rendering results.
class MultiviewDrawValidationTest : public MultiviewTest
{
@@ -930,6 +936,116 @@ TEST_P(MultiviewRenderDualViewTest, DrawArrays)
checkOutput();
}
// The test checks that glDrawArrays can be used to render into two views, after the program
// executable has been installed and the program relinked (with a failing link, and using a
// different number of views).
TEST_P(MultiviewRenderDualViewTestNoWebGL, DrawArraysAfterFailedRelink)
{
ANGLE_SKIP_TEST_IF(!requestMultiviewExtension(isMultisampled()));
ANGLE_SKIP_TEST_IF(IsWindows() && IsD3D());
std::string ext =
GetParam().mMultiviewExtension == multiview ? "GL_OVR_multiview" : "GL_OVR_multiview2";
const std::string kVS = R"(#version 300 es
#extension )" + ext + R"( : require
layout(num_views = 2) in;
void main()
{
vec2 pos = vec2(0.0);
switch (gl_VertexID) {
case 0: pos = vec2(-1.0, -1.0); break;
case 1: pos = vec2(1.0, -1.0); break;
case 2: pos = vec2(-1.0, 1.0); break;
case 3: pos = vec2(1.0, 1.0); break;
};
pos.x = gl_ViewID_OVR == 0u ? pos.x * 0.5 + 0.5 : pos.x * 0.5 - 0.5;
gl_Position = vec4(pos, 0.0, 1.0);
})";
const std::string kFS = R"(#version 300 es
#extension )" + ext + R"( : require
precision mediump float;
out vec4 col;
void main()
{
col = vec4(0, 1, 0, 1);
})";
const std::string kBadVS = R"(#version 300 es
#extension )" + ext + R"( : require
layout(num_views = 4) in;
out vec4 linkError;
void main()
{
vec2 pos = vec2(0.0);
switch (gl_VertexID) {
case 0: pos = vec2(-1.0, -1.0); break;
case 1: pos = vec2(1.0, -1.0); break;
case 2: pos = vec2(-1.0, 1.0); break;
case 3: pos = vec2(1.0, 1.0); break;
};
pos.x = gl_ViewID_OVR == 0u ? pos.x * 0.5 + 0.5 : pos.x * 0.5 - 0.5;
gl_Position = vec4(pos, 0.0, 1.0);
linkError = vec4(0);
})";
const std::string kBadFS = R"(#version 300 es
#extension )" + ext + R"( : require
precision mediump float;
flat in uvec4 linkError;
out vec4 col;
void main()
{
col = vec4(linkError);
})";
// First, create a good program
GLuint program = glCreateProgram();
GLuint vs = CompileShader(GL_VERTEX_SHADER, kVS.c_str());
GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS.c_str());
glAttachShader(program, vs);
glAttachShader(program, fs);
glLinkProgram(program);
CheckLinkStatusAndReturnProgram(program, true);
// Detach the shaders for the sake of DrawArraysAfterFailedRelink
glDetachShader(program, vs);
glDetachShader(program, fs);
glDeleteShader(vs);
glDeleteShader(fs);
// Install the executable
glUseProgram(program);
// Relink the program but in an erroneous way
GLuint badVs = CompileShader(GL_VERTEX_SHADER, kBadVS.c_str());
GLuint badFs = CompileShader(GL_FRAGMENT_SHADER, kBadFS.c_str());
glAttachShader(program, badVs);
glAttachShader(program, badFs);
glLinkProgram(program);
glDeleteShader(badVs);
glDeleteShader(badFs);
ASSERT_GL_NO_ERROR();
// Issue a draw and make sure everything works.
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
// drawQuad(mProgram, "vPosition", 0.0f, 1.0f, true);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
ASSERT_GL_NO_ERROR();
checkOutput();
glDeleteProgram(program);
}
// The test checks that glDrawElements can be used to render into two views.
TEST_P(MultiviewRenderDualViewTest, DrawElements)
{
@@ -2377,6 +2493,11 @@ ANGLE_INSTANTIATE_TEST(MultiviewRenderDualViewTest,
ALL_SINGLESAMPLE_CONFIGS(),
ALL_MULTISAMPLE_CONFIGS());
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MultiviewRenderDualViewTestNoWebGL);
ANGLE_INSTANTIATE_TEST(MultiviewRenderDualViewTestNoWebGL,
ALL_SINGLESAMPLE_CONFIGS(),
ALL_MULTISAMPLE_CONFIGS());
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MultiviewRenderTest);
ANGLE_INSTANTIATE_TEST(MultiviewRenderTest, ALL_SINGLESAMPLE_CONFIGS(), ALL_MULTISAMPLE_CONFIGS());