Commit e3bb6b79 by Jamie Madill Committed by Commit Bot

Update Textures immediately on program change.

Instead of deferring this work, we can process it immediately. We have access to the information we need in the prior and current states so can optimize the update more effectively. Bug: angleproject:2763 Change-Id: I77482b0ea490fddf403ccc4a4f32665301fd6e7a Reviewed-on: https://chromium-review.googlesource.com/c/1254042Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent 49b0f6eb
...@@ -1179,7 +1179,7 @@ void Context::bindImageTexture(GLuint unit, ...@@ -1179,7 +1179,7 @@ void Context::bindImageTexture(GLuint unit,
void Context::useProgram(GLuint program) void Context::useProgram(GLuint program)
{ {
mGLState.setProgram(this, getProgramResolveLink(program)); ANGLE_CONTEXT_TRY(mGLState.setProgram(this, getProgramResolveLink(program)));
mStateCache.onProgramExecutableChange(this); mStateCache.onProgramExecutableChange(this);
} }
...@@ -5779,9 +5779,8 @@ void Context::linkProgram(GLuint program) ...@@ -5779,9 +5779,8 @@ void Context::linkProgram(GLuint program)
programObject->resolveLink(); programObject->resolveLink();
if (programObject->isLinked()) if (programObject->isLinked())
{ {
mGLState.onProgramExecutableChange(programObject); ANGLE_CONTEXT_TRY(mGLState.onProgramExecutableChange(this, programObject));
} }
mStateCache.onProgramExecutableChange(this); mStateCache.onProgramExecutableChange(this);
} }
} }
...@@ -5994,7 +5993,7 @@ void Context::programBinary(GLuint program, GLenum binaryFormat, const void *bin ...@@ -5994,7 +5993,7 @@ void Context::programBinary(GLuint program, GLenum binaryFormat, const void *bin
handleError(programObject->loadBinary(this, binaryFormat, binary, length)); handleError(programObject->loadBinary(this, binaryFormat, binary, length));
if (programObject->isInUse()) if (programObject->isInUse())
{ {
mGLState.onProgramExecutableChange(programObject); ANGLE_CONTEXT_TRY(mGLState.onProgramExecutableChange(this, programObject));
mStateCache.onProgramExecutableChange(this); mStateCache.onProgramExecutableChange(this);
} }
} }
......
...@@ -36,7 +36,7 @@ void GLES1Renderer::onDestroy(Context *context, State *state) ...@@ -36,7 +36,7 @@ void GLES1Renderer::onDestroy(Context *context, State *state)
{ {
if (mRendererProgramInitialized) if (mRendererProgramInitialized)
{ {
state->setProgram(context, 0); context->handleError(state->setProgram(context, 0));
mShaderPrograms->deleteProgram(context, mProgramState.program); mShaderPrograms->deleteProgram(context, mProgramState.program);
mShaderPrograms->release(context); mShaderPrograms->release(context);
...@@ -540,7 +540,7 @@ Error GLES1Renderer::linkProgram(Context *context, ...@@ -540,7 +540,7 @@ Error GLES1Renderer::linkProgram(Context *context,
ANGLE_TRY(programObject->link(context)); ANGLE_TRY(programObject->link(context));
programObject->resolveLink(); programObject->resolveLink();
glState->onProgramExecutableChange(programObject); ANGLE_TRY(glState->onProgramExecutableChange(context, programObject));
if (!programObject->isLinked()) if (!programObject->isLinked())
{ {
...@@ -711,7 +711,7 @@ Error GLES1Renderer::initializeRendererProgram(Context *context, State *glState) ...@@ -711,7 +711,7 @@ Error GLES1Renderer::initializeRendererProgram(Context *context, State *glState)
mProgramState.drawTextureNormalizedCropRectLoc = mProgramState.drawTextureNormalizedCropRectLoc =
programObject->getUniformLocation("draw_texture_normalized_crop_rect"); programObject->getUniformLocation("draw_texture_normalized_crop_rect");
glState->setProgram(context, programObject); ANGLE_TRY(glState->setProgram(context, programObject));
for (int i = 0; i < kTexUnitCount; i++) for (int i = 0; i < kTexUnitCount; i++)
{ {
......
...@@ -355,10 +355,55 @@ void State::reset(const Context *context) ...@@ -355,10 +355,55 @@ void State::reset(const Context *context)
mPathStencilRef = 0; mPathStencilRef = 0;
mPathStencilMask = std::numeric_limits<GLuint>::max(); mPathStencilMask = std::numeric_limits<GLuint>::max();
// TODO(jmadill): Is this necessary?
setAllDirtyBits(); setAllDirtyBits();
} }
ANGLE_INLINE void State::unsetActiveTextures(ActiveTextureMask textureMask)
{
// Unset any relevant bound textures.
for (size_t textureIndex : mProgram->getActiveSamplersMask())
{
mActiveTexturesCache[textureIndex] = nullptr;
mCompleteTextureBindings[textureIndex].reset();
}
}
ANGLE_INLINE Error State::updateActiveTexture(const Context *context,
size_t textureIndex,
Texture *texture)
{
const Sampler *sampler = mSamplers[textureIndex].get();
if (!texture)
{
mActiveTexturesCache[textureIndex] = nullptr;
mCompleteTextureBindings[textureIndex].bind(nullptr);
return NoError();
}
mCompleteTextureBindings[textureIndex].bind(texture->getSubject());
if (!texture->isSamplerComplete(context, sampler))
{
mActiveTexturesCache[textureIndex] = nullptr;
return NoError();
}
mActiveTexturesCache[textureIndex] = texture;
if (texture->hasAnyDirtyBit())
{
ANGLE_TRY(texture->syncState(context));
}
if (texture->initState() == InitState::MayNeedInit)
{
mCachedTexturesInitState = InitState::MayNeedInit;
}
return NoError();
}
const RasterizerState &State::getRasterizerState() const const RasterizerState &State::getRasterizerState() const
{ {
return mRasterizer; return mRasterizer;
...@@ -1330,12 +1375,13 @@ void State::setVertexBindingDivisor(GLuint bindingIndex, GLuint divisor) ...@@ -1330,12 +1375,13 @@ void State::setVertexBindingDivisor(GLuint bindingIndex, GLuint divisor)
mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY); mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
} }
void State::setProgram(const Context *context, Program *newProgram) Error State::setProgram(const Context *context, Program *newProgram)
{ {
if (mProgram != newProgram) if (mProgram != newProgram)
{ {
if (mProgram) if (mProgram)
{ {
unsetActiveTextures(mProgram->getActiveSamplersMask());
mProgram->release(context); mProgram->release(context);
} }
...@@ -1344,7 +1390,7 @@ void State::setProgram(const Context *context, Program *newProgram) ...@@ -1344,7 +1390,7 @@ void State::setProgram(const Context *context, Program *newProgram)
if (mProgram) if (mProgram)
{ {
newProgram->addRef(); newProgram->addRef();
onProgramExecutableChange(newProgram); ANGLE_TRY(onProgramExecutableChange(context, newProgram));
} }
// Note that rendering is undefined if glUseProgram(0) is called. But ANGLE will generate // Note that rendering is undefined if glUseProgram(0) is called. But ANGLE will generate
...@@ -1352,6 +1398,8 @@ void State::setProgram(const Context *context, Program *newProgram) ...@@ -1352,6 +1398,8 @@ void State::setProgram(const Context *context, Program *newProgram)
mDirtyBits.set(DIRTY_BIT_PROGRAM_BINDING); mDirtyBits.set(DIRTY_BIT_PROGRAM_BINDING);
} }
return NoError();
} }
void State::setTransformFeedbackBinding(const Context *context, void State::setTransformFeedbackBinding(const Context *context,
...@@ -2749,46 +2797,19 @@ Error State::syncProgramTextures(const Context *context) ...@@ -2749,46 +2797,19 @@ Error State::syncProgramTextures(const Context *context)
Texture *texture = Texture *texture =
getSamplerTexture(static_cast<unsigned int>(textureUnitIndex), textureType); getSamplerTexture(static_cast<unsigned int>(textureUnitIndex), textureType);
Sampler *sampler = getSampler(static_cast<GLuint>(textureUnitIndex));
ASSERT(static_cast<size_t>(textureUnitIndex) < mActiveTexturesCache.size());
ASSERT(static_cast<size_t>(textureUnitIndex) < newActiveTextures.size()); ASSERT(static_cast<size_t>(textureUnitIndex) < newActiveTextures.size());
ASSERT(texture); ASSERT(texture);
// Mark the texture binding bit as dirty if the texture completeness changes.
// TODO(jmadill): Use specific dirty bit for completeness change.
if (texture->isSamplerComplete(context, sampler))
{
if (texture->hasAnyDirtyBit())
{
ANGLE_TRY(texture->syncState(context));
}
mActiveTexturesCache[textureUnitIndex] = texture;
}
else
{
mActiveTexturesCache[textureUnitIndex] = nullptr;
}
// Bind the texture unconditionally, to recieve completeness change notifications.
mCompleteTextureBindings[textureUnitIndex].bind(texture->getImplementation());
newActiveTextures.set(textureUnitIndex); newActiveTextures.set(textureUnitIndex);
ANGLE_TRY(updateActiveTexture(context, textureUnitIndex, texture));
if (texture->initState() == InitState::MayNeedInit)
{
mCachedTexturesInitState = InitState::MayNeedInit;
}
} }
// Unset now missing textures. // Unset now missing textures.
ActiveTextureMask negativeMask = activeTextures & ~newActiveTextures; ActiveTextureMask negativeMask = activeTextures & ~newActiveTextures;
if (negativeMask.any()) if (negativeMask.any())
{ {
for (auto textureIndex : negativeMask) unsetActiveTextures(negativeMask);
{
mCompleteTextureBindings[textureIndex].reset();
mActiveTexturesCache[textureIndex] = nullptr;
}
} }
for (size_t imageUnitIndex : mProgram->getActiveImagesMask()) for (size_t imageUnitIndex : mProgram->getActiveImagesMask())
...@@ -2875,7 +2896,7 @@ void State::setObjectDirty(GLenum target) ...@@ -2875,7 +2896,7 @@ void State::setObjectDirty(GLenum target)
} }
} }
void State::onProgramExecutableChange(Program *program) Error State::onProgramExecutableChange(const Context *context, Program *program)
{ {
// OpenGL Spec: // OpenGL Spec:
// "If LinkProgram or ProgramBinary successfully re-links a program object // "If LinkProgram or ProgramBinary successfully re-links a program object
...@@ -2884,8 +2905,40 @@ void State::onProgramExecutableChange(Program *program) ...@@ -2884,8 +2905,40 @@ void State::onProgramExecutableChange(Program *program)
ASSERT(program->isLinked()); ASSERT(program->isLinked());
mDirtyBits.set(DIRTY_BIT_PROGRAM_EXECUTABLE); mDirtyBits.set(DIRTY_BIT_PROGRAM_EXECUTABLE);
mDirtyObjects.set(DIRTY_OBJECT_PROGRAM_TEXTURES);
mDirtyObjects.set(DIRTY_OBJECT_PROGRAM); mDirtyObjects.set(DIRTY_OBJECT_PROGRAM);
// Set any bound textures.
const ActiveTextureTypeArray &textureTypes = program->getActiveSamplerTypes();
for (size_t textureIndex : program->getActiveSamplersMask())
{
TextureType type = textureTypes[textureIndex];
// This can happen if there is a conflicting texture type.
if (type == TextureType::InvalidEnum)
continue;
Texture *texture = mSamplerTextures[type][textureIndex].get();
ANGLE_TRY(updateActiveTexture(context, textureIndex, texture));
}
for (size_t imageUnitIndex : program->getActiveImagesMask())
{
Texture *image = mImageUnits[imageUnitIndex].texture.get();
if (!image)
continue;
if (image->hasAnyDirtyBit())
{
ANGLE_TRY(image->syncState(context));
}
if (image->initState() == InitState::MayNeedInit)
{
mCachedImageTexturesInitState = InitState::MayNeedInit;
}
}
return NoError();
} }
void State::setSamplerDirty(size_t samplerIndex) void State::setSamplerDirty(size_t samplerIndex)
......
...@@ -226,7 +226,7 @@ class State : angle::NonCopyable ...@@ -226,7 +226,7 @@ class State : angle::NonCopyable
bool removeVertexArrayBinding(const Context *context, GLuint vertexArray); bool removeVertexArrayBinding(const Context *context, GLuint vertexArray);
// Program binding manipulation // Program binding manipulation
void setProgram(const Context *context, Program *newProgram); Error setProgram(const Context *context, Program *newProgram);
Program *getProgram() const Program *getProgram() const
{ {
...@@ -377,7 +377,7 @@ class State : angle::NonCopyable ...@@ -377,7 +377,7 @@ class State : angle::NonCopyable
bool isRobustResourceInitEnabled() const { return mRobustResourceInit; } bool isRobustResourceInitEnabled() const { return mRobustResourceInit; }
// Sets the dirty bit for the program executable. // Sets the dirty bit for the program executable.
void onProgramExecutableChange(Program *program); Error onProgramExecutableChange(const Context *context, Program *program);
enum DirtyBitType enum DirtyBitType
{ {
...@@ -513,6 +513,8 @@ class State : angle::NonCopyable ...@@ -513,6 +513,8 @@ class State : angle::NonCopyable
private: private:
void syncSamplers(const Context *context); void syncSamplers(const Context *context);
Error syncProgramTextures(const Context *context); Error syncProgramTextures(const Context *context);
void unsetActiveTextures(ActiveTextureMask textureMask);
Error updateActiveTexture(const Context *context, size_t textureIndex, Texture *texture);
// Cached values from Context's caps // Cached values from Context's caps
GLuint mMaxDrawBuffers; GLuint mMaxDrawBuffers;
......
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