Commit 1f9d6843 by Jamie Madill Committed by Commit Bot

StateManager11: Defer RenderTarget invalidation to draw.

Although this adds a boolean check (and state flag maintenance) cost to each draw call, it makes ANGLE's internal life a lot simpler because it doesn't have to process a framebuffer change until the draw call. It turns out there are a few dependent checks of the Framebuffer that aren't always easy to do. In one test, Context destruction was triggering RenderTarget invalidation, after the Context had already freed the Framebuffer manager. This also fixes the problem in feature level 9_3 with framebuffer invalidation affecting the internal dirty bit set. (Note that it still dirties the Framebuffer for the next frame). BUG=chromium:767279 BUG=angleproject:2151 Change-Id: I74d61bddf9926004a04f712a9f9eb1205d5df0e1 Reviewed-on: https://chromium-review.googlesource.com/676657Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent 981f0f8f
......@@ -440,7 +440,7 @@ void Framebuffer11::syncState(const gl::Context *context,
FramebufferD3D::syncState(context, dirtyBits);
// Call this last to allow the state manager to take advantage of the cached render targets.
mRenderer->getStateManager()->invalidateRenderTarget(context);
mRenderer->getStateManager()->invalidateRenderTarget();
// Call this to syncViewport for framebuffer default parameters.
if (mState.getDefaultWidth() != 0 || mState.getDefaultHeight() != 0)
......@@ -465,7 +465,7 @@ void Framebuffer11::signal(size_t channelID, const gl::Context *context)
// Notify the context we need to re-validate the RenderTarget.
// TODO(jmadill): Check that we're the active draw framebuffer.
mRenderer->getStateManager()->invalidateRenderTarget(context);
mRenderer->getStateManager()->invalidateRenderTarget();
}
gl::Error Framebuffer11::getSamplePosition(size_t index, GLfloat *xy) const
......
......@@ -536,6 +536,7 @@ StateManager11::StateManager11(Renderer11 *renderer)
mCurNear(0.0f),
mCurFar(0.0f),
mViewportBounds(),
mRenderTargetIsDirty(true),
mCurPresentPathFastEnabled(false),
mCurPresentPathFastColorBufferHeight(0),
mDirtyCurrentValueAttribs(),
......@@ -928,7 +929,7 @@ void StateManager11::syncState(const gl::Context *context, const gl::State::Dirt
}
break;
case gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING:
invalidateRenderTarget(context);
invalidateRenderTarget();
if (mIsMultiviewEnabled)
{
handleMultiviewDrawFramebufferChange(context);
......@@ -951,7 +952,7 @@ void StateManager11::syncState(const gl::Context *context, const gl::State::Dirt
{
mInternalDirtyBits.set(DIRTY_BIT_SHADERS);
invalidateVertexBuffer();
invalidateRenderTarget(context);
invalidateRenderTarget();
invalidateTexturesAndSamplers();
invalidateProgramUniforms();
invalidateProgramUniformBuffers();
......@@ -1290,8 +1291,21 @@ void StateManager11::syncViewport(const gl::Context *context)
mShaderConstants.onViewportChange(viewport, adjustViewport, is9_3, mCurPresentPathFastEnabled);
}
void StateManager11::invalidateRenderTarget(const gl::Context *context)
void StateManager11::invalidateRenderTarget()
{
mRenderTargetIsDirty = true;
}
void StateManager11::processFramebufferInvalidation(const gl::Context *context)
{
if (!mRenderTargetIsDirty)
{
return;
}
ASSERT(context);
mRenderTargetIsDirty = false;
mInternalDirtyBits.set(DIRTY_BIT_RENDER_TARGET);
// The pixel shader is dependent on the output layout.
......@@ -1300,19 +1314,8 @@ void StateManager11::invalidateRenderTarget(const gl::Context *context)
// The D3D11 blend state is heavily dependent on the current render target.
mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
// nullptr only on display initialization.
if (!context)
{
return;
}
gl::Framebuffer *fbo = context->getGLState().getDrawFramebuffer();
// nullptr fbo can occur in some egl events like display initialization.
if (!fbo)
{
return;
}
ASSERT(fbo);
// Disable the depth test/depth write if we are using a stencil-only attachment.
// This is because ANGLE emulates stencil-only with D24S8 on D3D11 - we should neither read
......@@ -1354,12 +1357,12 @@ void StateManager11::invalidateRenderTarget(const gl::Context *context)
}
}
void StateManager11::invalidateBoundViews(const gl::Context *context)
void StateManager11::invalidateBoundViews()
{
mCurVertexSRVs.clear();
mCurPixelSRVs.clear();
invalidateRenderTarget(context);
invalidateRenderTarget();
}
void StateManager11::invalidateVertexBuffer()
......@@ -1843,6 +1846,9 @@ gl::Error StateManager11::updateState(const gl::Context *context, GLenum drawMod
auto *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());
// TODO(jmadill): Use dirty bits.
processFramebufferInvalidation(context);
// TODO(jmadill): Use dirty bits.
if (programD3D->updateSamplerMapping() == ProgramD3D::SamplerMapping::WasDirty)
{
invalidateTexturesAndSamplers();
......@@ -1960,9 +1966,7 @@ gl::Error StateManager11::updateState(const gl::Context *context, GLenum drawMod
ANGLE_TRY(syncTransformFeedbackBuffers(context));
// Check that we haven't set any dirty bits in the flushing of the dirty bits loop.
// TODO(jmadill): Fix FL 9_3 RenderTarget dirtying in call to syncTextures.
ASSERT(mInternalDirtyBits.none() ||
mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3);
ASSERT(mInternalDirtyBits.none());
return gl::NoError();
}
......
......@@ -161,14 +161,14 @@ class StateManager11 final : angle::NonCopyable
// These invalidations methods are called externally.
// Called from TextureStorage11.
void invalidateBoundViews(const gl::Context *context);
void invalidateBoundViews();
// Called from VertexArray11::updateVertexAttribStorage.
void invalidateCurrentValueAttrib(size_t attribIndex);
// Checks are done on a framebuffer state change to trigger other state changes.
// The Context is allowed to be nullptr for these methods, when called in EGL init code.
void invalidateRenderTarget(const gl::Context *context);
void invalidateRenderTarget();
// Called by instanced point sprite emulation.
void invalidateVertexBuffer();
......@@ -331,7 +331,7 @@ class StateManager11 final : angle::NonCopyable
void invalidateConstantBuffer(unsigned int slot);
// Called by the Framebuffer11 directly.
void dirtyDrawFramebuffer();
void processFramebufferInvalidation(const gl::Context *context);
enum DirtyBitType
{
......@@ -393,6 +393,7 @@ class StateManager11 final : angle::NonCopyable
// Render target variables
gl::Extents mViewportBounds;
bool mRenderTargetIsDirty;
// EGL_ANGLE_experimental_present_path variables
bool mCurPresentPathFastEnabled;
......
......@@ -898,7 +898,7 @@ EGLint SwapChain11::present(const gl::Context *context,
// Some swapping mechanisms such as DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL unbind the current render
// target. Mark it dirty. Use the proxy context in display since there is none available.
mRenderer->getStateManager()->invalidateRenderTarget(context);
mRenderer->getStateManager()->invalidateRenderTarget();
if (result == DXGI_ERROR_DEVICE_REMOVED)
{
......
......@@ -818,7 +818,7 @@ gl::Error TextureStorage11_2D::onDestroy(const gl::Context *context)
{
// If the keyed mutex is released that will unbind it and cause the state cache to become
// desynchronized.
mRenderer->getStateManager()->invalidateBoundViews(context);
mRenderer->getStateManager()->invalidateBoundViews();
}
// Invalidate RenderTargets.
......@@ -1312,7 +1312,7 @@ gl::Error TextureStorage11_External::onDestroy(const gl::Context *context)
{
// If the keyed mutex is released that will unbind it and cause the state cache to become
// desynchronized.
mRenderer->getStateManager()->invalidateBoundViews(context);
mRenderer->getStateManager()->invalidateBoundViews();
}
return gl::NoError();
......
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