Commit 248119b3 by Shahbaz Youssefi Committed by Commit Bot

Vulkan: Fix render target's tracking of content defined

Imagine the following scenario: 1. Clear draw framebuffer 2. Invalidate draw framebuffer 3. Update texture attached to draw framebuffer 4. Draw again into draw framebuffer Step 3 could be a number of things, such as glCopyTex[Sub]Image, glBlitFramebuffer, glTex[Sub]Image2D, glGenerateMipmap etc. In the above scenario, at step 2, the framebuffer's render target remembers it being invalidated (mContentDefined = false). This is used to set the loadOp of the next render pass to DONT_CARE. However, mContentDefined was implemented for a very specific optimization regarding the swapchain's depth buffer. The reuse of this variable for glInvalidateFramebuffer was erroneous as this variable didn't track whether the contents are defined for the general case. With this change, mContentDefined is set to true during FramebufferVk::syncState for each render target whose contents are marked dirty. This change additionally makes glBlitFramebuffer signal the contents of the blit targets as dirty, as well as textures that are used as storage images. Bug: angleproject:4859 Change-Id: I68c829f75ff4a3d03bb293ec72c609384983026d Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2309110 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCharlie Lao <cclao@google.com>
parent 2c3ff0a0
...@@ -2245,7 +2245,7 @@ void Context::drawArraysInstanced(PrimitiveMode mode, ...@@ -2245,7 +2245,7 @@ void Context::drawArraysInstanced(PrimitiveMode mode,
ANGLE_CONTEXT_TRY( ANGLE_CONTEXT_TRY(
mImplementation->drawArraysInstanced(this, mode, first, count, instanceCount)); mImplementation->drawArraysInstanced(this, mode, first, count, instanceCount));
MarkTransformFeedbackBufferUsage(this, count, instanceCount); MarkTransformFeedbackBufferUsage(this, count, instanceCount);
MarkShaderStorageBufferUsage(this); MarkShaderStorageUsage(this);
} }
void Context::drawElementsInstanced(PrimitiveMode mode, void Context::drawElementsInstanced(PrimitiveMode mode,
...@@ -2263,7 +2263,7 @@ void Context::drawElementsInstanced(PrimitiveMode mode, ...@@ -2263,7 +2263,7 @@ void Context::drawElementsInstanced(PrimitiveMode mode,
ANGLE_CONTEXT_TRY(prepareForDraw(mode)); ANGLE_CONTEXT_TRY(prepareForDraw(mode));
ANGLE_CONTEXT_TRY( ANGLE_CONTEXT_TRY(
mImplementation->drawElementsInstanced(this, mode, count, type, indices, instances)); mImplementation->drawElementsInstanced(this, mode, count, type, indices, instances));
MarkShaderStorageBufferUsage(this); MarkShaderStorageUsage(this);
} }
void Context::drawElementsBaseVertex(PrimitiveMode mode, void Context::drawElementsBaseVertex(PrimitiveMode mode,
...@@ -2281,7 +2281,7 @@ void Context::drawElementsBaseVertex(PrimitiveMode mode, ...@@ -2281,7 +2281,7 @@ void Context::drawElementsBaseVertex(PrimitiveMode mode,
ANGLE_CONTEXT_TRY(prepareForDraw(mode)); ANGLE_CONTEXT_TRY(prepareForDraw(mode));
ANGLE_CONTEXT_TRY( ANGLE_CONTEXT_TRY(
mImplementation->drawElementsBaseVertex(this, mode, count, type, indices, basevertex)); mImplementation->drawElementsBaseVertex(this, mode, count, type, indices, basevertex));
MarkShaderStorageBufferUsage(this); MarkShaderStorageUsage(this);
} }
void Context::drawElementsInstancedBaseVertex(PrimitiveMode mode, void Context::drawElementsInstancedBaseVertex(PrimitiveMode mode,
...@@ -2300,7 +2300,7 @@ void Context::drawElementsInstancedBaseVertex(PrimitiveMode mode, ...@@ -2300,7 +2300,7 @@ void Context::drawElementsInstancedBaseVertex(PrimitiveMode mode,
ANGLE_CONTEXT_TRY(prepareForDraw(mode)); ANGLE_CONTEXT_TRY(prepareForDraw(mode));
ANGLE_CONTEXT_TRY(mImplementation->drawElementsInstancedBaseVertex( ANGLE_CONTEXT_TRY(mImplementation->drawElementsInstancedBaseVertex(
this, mode, count, type, indices, instancecount, basevertex)); this, mode, count, type, indices, instancecount, basevertex));
MarkShaderStorageBufferUsage(this); MarkShaderStorageUsage(this);
} }
void Context::drawRangeElements(PrimitiveMode mode, void Context::drawRangeElements(PrimitiveMode mode,
...@@ -2319,7 +2319,7 @@ void Context::drawRangeElements(PrimitiveMode mode, ...@@ -2319,7 +2319,7 @@ void Context::drawRangeElements(PrimitiveMode mode,
ANGLE_CONTEXT_TRY(prepareForDraw(mode)); ANGLE_CONTEXT_TRY(prepareForDraw(mode));
ANGLE_CONTEXT_TRY( ANGLE_CONTEXT_TRY(
mImplementation->drawRangeElements(this, mode, start, end, count, type, indices)); mImplementation->drawRangeElements(this, mode, start, end, count, type, indices));
MarkShaderStorageBufferUsage(this); MarkShaderStorageUsage(this);
} }
void Context::drawRangeElementsBaseVertex(PrimitiveMode mode, void Context::drawRangeElementsBaseVertex(PrimitiveMode mode,
...@@ -2339,21 +2339,21 @@ void Context::drawRangeElementsBaseVertex(PrimitiveMode mode, ...@@ -2339,21 +2339,21 @@ void Context::drawRangeElementsBaseVertex(PrimitiveMode mode,
ANGLE_CONTEXT_TRY(prepareForDraw(mode)); ANGLE_CONTEXT_TRY(prepareForDraw(mode));
ANGLE_CONTEXT_TRY(mImplementation->drawRangeElementsBaseVertex(this, mode, start, end, count, ANGLE_CONTEXT_TRY(mImplementation->drawRangeElementsBaseVertex(this, mode, start, end, count,
type, indices, basevertex)); type, indices, basevertex));
MarkShaderStorageBufferUsage(this); MarkShaderStorageUsage(this);
} }
void Context::drawArraysIndirect(PrimitiveMode mode, const void *indirect) void Context::drawArraysIndirect(PrimitiveMode mode, const void *indirect)
{ {
ANGLE_CONTEXT_TRY(prepareForDraw(mode)); ANGLE_CONTEXT_TRY(prepareForDraw(mode));
ANGLE_CONTEXT_TRY(mImplementation->drawArraysIndirect(this, mode, indirect)); ANGLE_CONTEXT_TRY(mImplementation->drawArraysIndirect(this, mode, indirect));
MarkShaderStorageBufferUsage(this); MarkShaderStorageUsage(this);
} }
void Context::drawElementsIndirect(PrimitiveMode mode, DrawElementsType type, const void *indirect) void Context::drawElementsIndirect(PrimitiveMode mode, DrawElementsType type, const void *indirect)
{ {
ANGLE_CONTEXT_TRY(prepareForDraw(mode)); ANGLE_CONTEXT_TRY(prepareForDraw(mode));
ANGLE_CONTEXT_TRY(mImplementation->drawElementsIndirect(this, mode, type, indirect)); ANGLE_CONTEXT_TRY(mImplementation->drawElementsIndirect(this, mode, type, indirect));
MarkShaderStorageBufferUsage(this); MarkShaderStorageUsage(this);
} }
void Context::flush() void Context::flush()
...@@ -5686,7 +5686,7 @@ void Context::dispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGr ...@@ -5686,7 +5686,7 @@ void Context::dispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGr
return; return;
} }
MarkShaderStorageBufferUsage(this); MarkShaderStorageUsage(this);
} }
void Context::convertPpoToComputeOrDraw(bool isCompute) void Context::convertPpoToComputeOrDraw(bool isCompute)
...@@ -5707,7 +5707,7 @@ void Context::dispatchComputeIndirect(GLintptr indirect) ...@@ -5707,7 +5707,7 @@ void Context::dispatchComputeIndirect(GLintptr indirect)
ANGLE_CONTEXT_TRY(prepareForDispatch()); ANGLE_CONTEXT_TRY(prepareForDispatch());
ANGLE_CONTEXT_TRY(mImplementation->dispatchComputeIndirect(this, indirect)); ANGLE_CONTEXT_TRY(mImplementation->dispatchComputeIndirect(this, indirect));
MarkShaderStorageBufferUsage(this); MarkShaderStorageUsage(this);
} }
void Context::texStorage2D(TextureType target, void Context::texStorage2D(TextureType target,
...@@ -8507,6 +8507,7 @@ void StateCache::onProgramExecutableChange(Context *context) ...@@ -8507,6 +8507,7 @@ void StateCache::onProgramExecutableChange(Context *context)
updateBasicDrawStatesError(); updateBasicDrawStatesError();
updateValidDrawModes(context); updateValidDrawModes(context);
updateActiveShaderStorageBufferIndices(context); updateActiveShaderStorageBufferIndices(context);
updateActiveImageUnitIndices(context);
updateCanDraw(context); updateCanDraw(context);
} }
...@@ -8772,6 +8773,26 @@ void StateCache::updateActiveShaderStorageBufferIndices(Context *context) ...@@ -8772,6 +8773,26 @@ void StateCache::updateActiveShaderStorageBufferIndices(Context *context)
} }
} }
void StateCache::updateActiveImageUnitIndices(Context *context)
{
mCachedActiveImageUnitIndices.reset();
Program *program = context->getState().getProgram();
if (program)
{
for (const ImageBinding &imageBinding : program->getState().getImageBindings())
{
if (imageBinding.unreferenced)
{
continue;
}
for (GLuint binding : imageBinding.boundImageUnits)
{
mCachedActiveImageUnitIndices.set(binding);
}
}
}
}
void StateCache::updateCanDraw(Context *context) void StateCache::updateCanDraw(Context *context)
{ {
mCachedCanDraw = (context->isGLES1() || mCachedCanDraw = (context->isGLES1() ||
......
...@@ -258,6 +258,10 @@ class StateCache final : angle::NonCopyable ...@@ -258,6 +258,10 @@ class StateCache final : angle::NonCopyable
return mCachedActiveShaderStorageBufferIndices; return mCachedActiveShaderStorageBufferIndices;
} }
// Places that can trigger updateActiveImageUnitIndices:
// 1. onProgramExecutableChange.
ImageUnitMask getActiveImageUnitIndices() const { return mCachedActiveImageUnitIndices; }
// Places that can trigger updateCanDraw: // Places that can trigger updateCanDraw:
// 1. onProgramExecutableChange. // 1. onProgramExecutableChange.
bool getCanDraw() const { return mCachedCanDraw; } bool getCanDraw() const { return mCachedCanDraw; }
...@@ -295,6 +299,7 @@ class StateCache final : angle::NonCopyable ...@@ -295,6 +299,7 @@ class StateCache final : angle::NonCopyable
void updateTransformFeedbackActiveUnpaused(Context *context); void updateTransformFeedbackActiveUnpaused(Context *context);
void updateVertexAttribTypesValidation(Context *context); void updateVertexAttribTypesValidation(Context *context);
void updateActiveShaderStorageBufferIndices(Context *context); void updateActiveShaderStorageBufferIndices(Context *context);
void updateActiveImageUnitIndices(Context *context);
void updateCanDraw(Context *context); void updateCanDraw(Context *context);
void setValidDrawModes(bool pointsOK, bool linesOK, bool trisOK, bool lineAdjOK, bool triAdjOK); void setValidDrawModes(bool pointsOK, bool linesOK, bool trisOK, bool lineAdjOK, bool triAdjOK);
...@@ -314,6 +319,7 @@ class StateCache final : angle::NonCopyable ...@@ -314,6 +319,7 @@ class StateCache final : angle::NonCopyable
mutable intptr_t mCachedBasicDrawElementsError; mutable intptr_t mCachedBasicDrawElementsError;
bool mCachedTransformFeedbackActiveUnpaused; bool mCachedTransformFeedbackActiveUnpaused;
StorageBuffersMask mCachedActiveShaderStorageBufferIndices; StorageBuffersMask mCachedActiveShaderStorageBufferIndices;
ImageUnitMask mCachedActiveImageUnitIndices;
// Reserve an extra slot at the end of these maps for invalid enum. // Reserve an extra slot at the end of these maps for invalid enum.
angle::PackedEnumMap<PrimitiveMode, bool, angle::EnumSize<PrimitiveMode>() + 1> angle::PackedEnumMap<PrimitiveMode, bool, angle::EnumSize<PrimitiveMode>() + 1>
......
...@@ -46,16 +46,26 @@ ANGLE_INLINE void MarkTransformFeedbackBufferUsage(const Context *context, ...@@ -46,16 +46,26 @@ ANGLE_INLINE void MarkTransformFeedbackBufferUsage(const Context *context,
} }
} }
ANGLE_INLINE void MarkShaderStorageBufferUsage(const Context *context) ANGLE_INLINE void MarkShaderStorageUsage(const Context *context)
{ {
for (size_t index : context->getStateCache().getActiveShaderStorageBufferIndices()) for (size_t index : context->getStateCache().getActiveShaderStorageBufferIndices())
{ {
gl::Buffer *buffer = context->getState().getIndexedShaderStorageBuffer(index).get(); Buffer *buffer = context->getState().getIndexedShaderStorageBuffer(index).get();
if (buffer) if (buffer)
{ {
buffer->onDataChanged(); buffer->onDataChanged();
} }
} }
for (size_t index : context->getStateCache().getActiveImageUnitIndices())
{
const ImageUnit &imageUnit = context->getState().getImageUnit(index);
const Texture *texture = imageUnit.texture.get();
if (texture)
{
texture->onStateChange(angle::SubjectMessage::ContentsChanged);
}
}
} }
// Return true if the draw is a no-op, else return false. // Return true if the draw is a no-op, else return false.
......
...@@ -1551,7 +1551,27 @@ angle::Result Framebuffer::blit(const Context *context, ...@@ -1551,7 +1551,27 @@ angle::Result Framebuffer::blit(const Context *context,
{ {
ASSERT(mask != 0); ASSERT(mask != 0);
return mImpl->blit(context, sourceArea, destArea, mask, filter); ANGLE_TRY(mImpl->blit(context, sourceArea, destArea, mask, filter));
// Mark the contents of the attachments dirty
if ((mask & GL_COLOR_BUFFER_BIT) != 0)
{
for (size_t colorIndex : mState.mEnabledDrawBuffers)
{
mDirtyBits.set(DIRTY_BIT_COLOR_BUFFER_CONTENTS_0 + colorIndex);
}
}
if ((mask & GL_DEPTH_BUFFER_BIT) != 0)
{
mDirtyBits.set(DIRTY_BIT_DEPTH_BUFFER_CONTENTS);
}
if ((mask & GL_STENCIL_BUFFER_BIT) != 0)
{
mDirtyBits.set(DIRTY_BIT_STENCIL_BUFFER_CONTENTS);
}
onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
return angle::Result::Continue;
} }
int Framebuffer::getSamples(const Context *context) const int Framebuffer::getSamples(const Context *context) const
......
...@@ -526,7 +526,7 @@ angle::Result Context11::drawElementsIndirect(const gl::Context *context, ...@@ -526,7 +526,7 @@ angle::Result Context11::drawElementsIndirect(const gl::Context *context,
ASSERT(counts[drawID] > 0); \ ASSERT(counts[drawID] > 0); \
DRAW_CALL(drawType, instanced, bvbi); \ DRAW_CALL(drawType, instanced, bvbi); \
ANGLE_MARK_TRANSFORM_FEEDBACK_USAGE(instanced); \ ANGLE_MARK_TRANSFORM_FEEDBACK_USAGE(instanced); \
gl::MarkShaderStorageBufferUsage(context); \ gl::MarkShaderStorageUsage(context); \
} }
angle::Result Context11::multiDrawArrays(const gl::Context *context, angle::Result Context11::multiDrawArrays(const gl::Context *context,
......
...@@ -968,7 +968,7 @@ void GetSamplePosition(GLsizei sampleCount, size_t index, GLfloat *xy) ...@@ -968,7 +968,7 @@ void GetSamplePosition(GLsizei sampleCount, size_t index, GLfloat *xy)
ANGLE_SET_BASE_INSTANCE_UNIFORM(hasBaseInstance)(baseInstances[drawID]); \ ANGLE_SET_BASE_INSTANCE_UNIFORM(hasBaseInstance)(baseInstances[drawID]); \
ANGLE_TRY(DRAW_CALL(drawType, instanced, bvbi)); \ ANGLE_TRY(DRAW_CALL(drawType, instanced, bvbi)); \
ANGLE_MARK_TRANSFORM_FEEDBACK_USAGE(instanced); \ ANGLE_MARK_TRANSFORM_FEEDBACK_USAGE(instanced); \
gl::MarkShaderStorageBufferUsage(context); \ gl::MarkShaderStorageUsage(context); \
} }
angle::Result MultiDrawArraysGeneral(ContextImpl *contextImpl, angle::Result MultiDrawArraysGeneral(ContextImpl *contextImpl,
......
...@@ -172,8 +172,12 @@ vk::ImageHelper &RenderTargetVk::getImageForWrite() const ...@@ -172,8 +172,12 @@ vk::ImageHelper &RenderTargetVk::getImageForWrite() const
angle::Result RenderTargetVk::flushStagedUpdates(ContextVk *contextVk, angle::Result RenderTargetVk::flushStagedUpdates(ContextVk *contextVk,
vk::ClearValuesArray *deferredClears, vk::ClearValuesArray *deferredClears,
uint32_t deferredClearIndex) const uint32_t deferredClearIndex)
{ {
// This function is called when the framebuffer is notified of an update to the attachment's
// contents. Therefore, set mContentDefined so that the next render pass will have loadOp=LOAD.
mContentDefined = true;
// Note that the layer index for 3D textures is always zero according to Vulkan. // Note that the layer index for 3D textures is always zero according to Vulkan.
uint32_t layerIndex = mLayerIndex; uint32_t layerIndex = mLayerIndex;
if (mImage->getType() == VK_IMAGE_TYPE_3D) if (mImage->getType() == VK_IMAGE_TYPE_3D)
......
...@@ -81,7 +81,7 @@ class RenderTargetVk final : public FramebufferAttachmentRenderTarget ...@@ -81,7 +81,7 @@ class RenderTargetVk final : public FramebufferAttachmentRenderTarget
angle::Result flushStagedUpdates(ContextVk *contextVk, angle::Result flushStagedUpdates(ContextVk *contextVk,
vk::ClearValuesArray *deferredClears, vk::ClearValuesArray *deferredClears,
uint32_t deferredClearIndex) const; uint32_t deferredClearIndex);
void retainImageViews(ContextVk *contextVk) const; void retainImageViews(ContextVk *contextVk) const;
......
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