Commit 999da35e by Shahbaz Youssefi Committed by Commit Bot

Vulkan: Optimize glMemoryBarrier more

The implementation assumed that the X_BARRIER_BIT bits implied two barriers; write->X and X->write. However, they only imply write->X, with the exception of SHADER_IMAGE_ACCESS_BARRIER_BIT and SHADER_STORAGE_BARRIER_BIT which handle X->write for images and buffers respectively. As a result, the other bits no longer set the MEMORY_BARRIER dirty bit as they don't guard against X->write usage. Bug: angleproject:5070 Change-Id: Id23904c455a5f56dc45fc6832a74fdfbba6a4827 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2705702Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
parent 7ff605a5
......@@ -4004,10 +4004,13 @@ angle::Result ContextVk::memoryBarrier(const gl::Context *context, GLbitfield ba
return angle::Result::Continue;
}
// glMemoryBarrier acts as two barriers:
// glMemoryBarrier for barrier bit X_BARRIER_BIT implies:
//
// - An execution+memory barrier: shader writes are made visible to subsequent accesses
// - Another execution barrier: shader accesses are finished before subsequent writes
// - An execution+memory barrier: shader writes are made visible to subsequent X accesses
//
// Additionally, SHADER_IMAGE_ACCESS_BARRIER_BIT and SHADER_STORAGE_BARRIER_BIT imply:
//
// - An execution+memory barrier: all accesses are finished before image/buffer writes
//
// For the first barrier, we can simplify the implementation by assuming that prior writes are
// expected to be used right after this barrier, so we can close the render pass or flush the
......@@ -4033,29 +4036,10 @@ angle::Result ContextVk::memoryBarrier(const gl::Context *context, GLbitfield ba
// To achieve this, a dirty bit is added that breaks the render pass if any storage
// buffer/images are used in it. Until the render pass breaks, changing the program or storage
// buffer/image bindings should set this dirty bit again.
constexpr GLbitfield kBarrierBitsAffectinDrawDispatch =
GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT | GL_UNIFORM_BARRIER_BIT |
GL_TEXTURE_FETCH_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_COMMAND_BARRIER_BIT |
GL_TRANSFORM_FEEDBACK_BARRIER_BIT | GL_ATOMIC_COUNTER_BARRIER_BIT |
GL_SHADER_STORAGE_BARRIER_BIT;
const bool hasAnyBitsAffectingDrawDispatch =
(barriers & ~kBarrierBitsAffectinDrawDispatch) != 0;
if (hasAnyBitsAffectingDrawDispatch)
{
mGraphicsDirtyBits.set(DIRTY_BIT_MEMORY_BARRIER);
mComputeDirtyBits.set(DIRTY_BIT_MEMORY_BARRIER);
}
// Make sure memory barrier is issued for future usages of storage buffers and images even if
// there's no binding change.
mGraphicsDirtyBits.set(DIRTY_BIT_SHADER_RESOURCES);
mComputeDirtyBits.set(DIRTY_BIT_SHADER_RESOURCES);
// Break the render pass if necessary as future non-draw commands can't know if they should.
if (mRenderPassCommands->hasShaderStorageOutput())
{
// Break the render pass if necessary as future non-draw commands can't know if they should.
ANGLE_TRY(flushCommandsAndEndRenderPass());
}
else if (mOutsideRenderPassCommands->hasShaderStorageOutput())
......@@ -4064,6 +4048,24 @@ angle::Result ContextVk::memoryBarrier(const gl::Context *context, GLbitfield ba
ANGLE_TRY(flushOutsideRenderPassCommands());
}
constexpr GLbitfield kWriteAfterAccessBarriers =
GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_SHADER_STORAGE_BARRIER_BIT;
if ((barriers & kWriteAfterAccessBarriers) == 0)
{
return angle::Result::Continue;
}
// Defer flushing the command buffers until a draw/dispatch with storage buffer/image is
// encountered.
mGraphicsDirtyBits.set(DIRTY_BIT_MEMORY_BARRIER);
mComputeDirtyBits.set(DIRTY_BIT_MEMORY_BARRIER);
// Make sure memory barrier is issued for future usages of storage buffers and images even if
// there's no binding change.
mGraphicsDirtyBits.set(DIRTY_BIT_SHADER_RESOURCES);
mComputeDirtyBits.set(DIRTY_BIT_SHADER_RESOURCES);
// Mark the command buffers as affected by glMemoryBarrier, so future program and storage
// buffer/image binding changes can set DIRTY_BIT_MEMORY_BARRIER again.
mOutsideRenderPassCommands->setGLMemoryBarrierIssued();
......
......@@ -24,6 +24,7 @@
// Test bug with missing glMemoryBarrier call
5673 VULKAN : KHR-GLES31.core.texture_buffer.texture_buffer_operations_transform_feedback = FAIL
5673 VULKAN : KHR-GLES31.core.compute_shader.pipeline-post-xfb = FAIL
// Framebuffer without attachments:
3579 VULKAN : KHR-GLES31.core.framebuffer_no_attachments.api = FAIL
......
......@@ -4240,7 +4240,7 @@ void main()
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);
glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
glUseProgram(writeProgram);
glDrawArrays(GL_TRIANGLES, 0, 6);
......@@ -4341,7 +4341,7 @@ void main()
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);
glMemoryBarrier(GL_UNIFORM_BARRIER_BIT);
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
glUseProgram(writeProgram);
glDrawArrays(GL_TRIANGLES, 0, 6);
......
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