Commit e96d1744 by Shahbaz Youssefi Committed by Commit Bot

Vulkan: Optimize glMemoryBarrier

Previous to this change, glMemoryBarrier was processed as it is issued. This made it impossible to know whether a draw call would follow or a dispatch call, and what resources it would use. The render pass was conservatively broken due to this limitation. To address this limitation, handling of glMemoryBarrier is deferred until the next draw or dispatch call. Note that glMemoryBarrier acts as two barriers: - An execution+memory barrier: shader writes are made visible to subsequent accesses - Another execution barrier: shader accesses are finished before subsequent writes An important observation is that for most resources, ANGLE actually necessarily has to issue memory barriers automatically to conform with Vulkan. In terms of memory barrier thus, ANGLE already does the right thing except for when there's no binding change. This means WaW hazards (i.e. storage buffer and image writes) with no binding change require a memory barrier as a result of glMemoryBarrier. In all other cases, it's enough for glMemoryBarrier to break the render pass if necessary and ensure that corresponding bindings are marked dirty (for the execution or memory barriers to happen automatically later). Bug: angleproject:5070 Change-Id: Ide359c43362f8a78805ecf797a91de7aa79221f9 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2693473Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
parent 22aea430
......@@ -594,6 +594,8 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText
// Dirty bits.
enum DirtyBitType : size_t
{
// A glMemoryBarrier has been called and command buffers may need flushing.
DIRTY_BIT_MEMORY_BARRIER,
// Dirty bits that must be processed before the render pass is started. The handlers for
// these dirty bits don't record any commands.
DIRTY_BIT_DEFAULT_ATTRIBS,
......@@ -781,6 +783,8 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText
void invalidateDriverUniforms();
// Handlers for graphics pipeline dirty bits.
angle::Result handleDirtyGraphicsMemorybarrier(DirtyBits::Iterator *dirtyBitsIterator,
DirtyBits dirtyBitMask);
angle::Result handleDirtyGraphicsEventLog(DirtyBits::Iterator *dirtyBitsIterator,
DirtyBits dirtyBitMask);
angle::Result handleDirtyGraphicsDefaultAttribs(DirtyBits::Iterator *dirtyBitsIterator,
......@@ -817,6 +821,7 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText
DirtyBits dirtyBitMask);
// Handlers for compute pipeline dirty bits.
angle::Result handleDirtyComputeMemoryBarrier();
angle::Result handleDirtyComputeEventLog();
angle::Result handleDirtyComputePipelineDesc();
angle::Result handleDirtyComputePipelineBinding();
......@@ -827,6 +832,8 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText
angle::Result handleDirtyComputeDescriptorSets();
// Common parts of the common dirty bit handlers.
angle::Result handleDirtyMemorybarrierImpl(DirtyBits::Iterator *dirtyBitsIterator,
DirtyBits dirtyBitMask);
angle::Result handleDirtyEventLogImpl(vk::CommandBuffer *commandBuffer);
angle::Result handleDirtyTexturesImpl(vk::CommandBufferHelper *commandBufferHelper);
angle::Result handleDirtyShaderResourcesImpl(vk::CommandBufferHelper *commandBufferHelper);
......@@ -890,6 +897,7 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText
angle::Result onResourceAccess(const vk::CommandBufferAccess &access);
angle::Result flushCommandBuffersIfNecessary(const vk::CommandBufferAccess &access);
bool renderPassUsesStorageResources() const;
void outputCumulativePerfCounters();
......
......@@ -793,6 +793,8 @@ CommandBufferHelper::CommandBufferHelper()
mIsTransformFeedbackActiveUnpaused(false),
mIsRenderPassCommandBuffer(false),
mReadOnlyDepthStencilMode(false),
mHasShaderStorageOutput(false),
mHasGLMemoryBarrierIssued(false),
mDepthAccess(ResourceAccess::Unused),
mStencilAccess(ResourceAccess::Unused),
mDepthCmdSizeInvalidated(kInfiniteCmdSize),
......@@ -1553,6 +1555,8 @@ void CommandBufferHelper::reset()
mRenderPassStarted = false;
mValidTransformFeedbackBufferCount = 0;
mRebindTransformFeedbackBuffers = false;
mHasShaderStorageOutput = false;
mHasGLMemoryBarrierIssued = false;
mDepthAccess = ResourceAccess::Unused;
mStencilAccess = ResourceAccess::Unused;
mDepthCmdSizeInvalidated = kInfiniteCmdSize;
......
......@@ -1170,6 +1170,18 @@ class CommandBufferHelper : angle::NonCopyable
bool hasRenderPass() const { return mIsRenderPassCommandBuffer; }
void setHasShaderStorageOutput() { mHasShaderStorageOutput = true; }
bool hasShaderStorageOutput() const { return mHasShaderStorageOutput; }
void setGLMemoryBarrierIssued()
{
if (!empty())
{
mHasGLMemoryBarrierIssued = true;
}
}
bool hasGLMemoryBarrierIssued() const { return mHasGLMemoryBarrierIssued; }
private:
bool onDepthStencilAccess(ResourceAccess access,
uint32_t *cmdCountInvalidated,
......@@ -1207,6 +1219,15 @@ class CommandBufferHelper : angle::NonCopyable
bool mIsRenderPassCommandBuffer;
bool mReadOnlyDepthStencilMode;
// Whether the command buffers contains any draw/dispatch calls that possibly output data
// through storage buffers and images. This is used to determine whether glMemoryBarrier*
// should flush the command buffer.
bool mHasShaderStorageOutput;
// Whether glMemoryBarrier has been called while commands are recorded in this command buffer.
// This is used to know when to check and potentially flush the command buffer if storage
// buffers and images are used in it.
bool mHasGLMemoryBarrierIssued;
// State tracking for the maximum (Write been the highest) depth access during the entire
// renderpass. Note that this does not include VK_ATTACHMENT_LOAD_OP_CLEAR which is tracked
// separately. This is done this way to allow clear op to being optimized out when we find out
......
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