Vulkan: Use global buffer barriers.
This switches from using resource barriers for buffers to using global
barriers. This matches the general advised best practice. It also
allows us to combine multiple barriers into one. On a draw we might
combine all the vertex and index barriers into a single barrier call.
We implement this using a bit of extra state tracking in BufferHelper.
Bug: angleproject:2828
Change-Id: I196b368804ff50e60d085687a643e5566ba1c5b6
Reviewed-on: https://chromium-review.googlesource.com/c/1309977
Commit-Queue: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
diff --git a/src/libANGLE/renderer/vulkan/CommandGraph.cpp b/src/libANGLE/renderer/vulkan/CommandGraph.cpp
index 6754132..bc9363c 100644
--- a/src/libANGLE/renderer/vulkan/CommandGraph.cpp
+++ b/src/libANGLE/renderer/vulkan/CommandGraph.cpp
@@ -33,17 +33,17 @@
ASSERT(!commandBuffer->valid());
VkCommandBufferAllocateInfo createInfo = {};
- createInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
- createInfo.commandPool = commandPool.getHandle();
- createInfo.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY;
- createInfo.commandBufferCount = 1;
+ createInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
+ createInfo.commandPool = commandPool.getHandle();
+ createInfo.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY;
+ createInfo.commandBufferCount = 1;
ANGLE_TRY(commandBuffer->init(context, createInfo));
VkCommandBufferBeginInfo beginInfo = {};
- beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
- beginInfo.flags = flags | VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
- beginInfo.pInheritanceInfo = &inheritanceInfo;
+ beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+ beginInfo.flags = flags | VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
+ beginInfo.pInheritanceInfo = &inheritanceInfo;
ANGLE_TRY(commandBuffer->begin(context, beginInfo));
return angle::Result::Continue();
@@ -297,7 +297,9 @@
mQueryPool(VK_NULL_HANDLE),
mQueryIndex(0),
mHasChildren(false),
- mVisitedState(VisitedState::Unvisited)
+ mVisitedState(VisitedState::Unvisited),
+ mGlobalMemoryBarrierSrcAccess(0),
+ mGlobalMemoryBarrierDstAccess(0)
{
}
@@ -323,14 +325,14 @@
ASSERT(!mHasChildren);
VkCommandBufferInheritanceInfo inheritanceInfo = {};
- inheritanceInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
- inheritanceInfo.renderPass = VK_NULL_HANDLE;
- inheritanceInfo.subpass = 0;
- inheritanceInfo.framebuffer = VK_NULL_HANDLE;
+ inheritanceInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
+ inheritanceInfo.renderPass = VK_NULL_HANDLE;
+ inheritanceInfo.subpass = 0;
+ inheritanceInfo.framebuffer = VK_NULL_HANDLE;
inheritanceInfo.occlusionQueryEnable =
context->getRenderer()->getPhysicalDeviceFeatures().inheritedQueries;
- inheritanceInfo.queryFlags = 0;
- inheritanceInfo.pipelineStatistics = 0;
+ inheritanceInfo.queryFlags = 0;
+ inheritanceInfo.pipelineStatistics = 0;
ANGLE_TRY(InitAndBeginCommandBuffer(context, commandPool, inheritanceInfo, 0,
&mOutsideRenderPassCommands));
@@ -351,14 +353,14 @@
&compatibleRenderPass));
VkCommandBufferInheritanceInfo inheritanceInfo = {};
- inheritanceInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
- inheritanceInfo.renderPass = compatibleRenderPass->getHandle();
- inheritanceInfo.subpass = 0;
- inheritanceInfo.framebuffer = mRenderPassFramebuffer.getHandle();
+ inheritanceInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
+ inheritanceInfo.renderPass = compatibleRenderPass->getHandle();
+ inheritanceInfo.subpass = 0;
+ inheritanceInfo.framebuffer = mRenderPassFramebuffer.getHandle();
inheritanceInfo.occlusionQueryEnable =
context->getRenderer()->getPhysicalDeviceFeatures().inheritedQueries;
- inheritanceInfo.queryFlags = 0;
- inheritanceInfo.pipelineStatistics = 0;
+ inheritanceInfo.queryFlags = 0;
+ inheritanceInfo.pipelineStatistics = 0;
ANGLE_TRY(InitAndBeginCommandBuffer(
context, context->getRenderer()->getCommandPool(), inheritanceInfo,
@@ -429,6 +431,12 @@
mQueryIndex = queryIndex;
}
+void CommandGraphNode::addGlobalMemoryBarrier(VkFlags srcAccess, VkFlags dstAccess)
+{
+ mGlobalMemoryBarrierSrcAccess |= srcAccess;
+ mGlobalMemoryBarrierDstAccess |= dstAccess;
+}
+
void CommandGraphNode::setHasChildren()
{
mHasChildren = true;
@@ -480,6 +488,21 @@
case CommandGraphNodeFunction::Generic:
ASSERT(mQueryPool == VK_NULL_HANDLE);
+ // Record the deferred pipeline barrier if necessary.
+ ASSERT((mGlobalMemoryBarrierDstAccess == 0) == (mGlobalMemoryBarrierSrcAccess == 0));
+ if (mGlobalMemoryBarrierSrcAccess)
+ {
+ VkMemoryBarrier memoryBarrier = {};
+ memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
+ memoryBarrier.srcAccessMask = mGlobalMemoryBarrierSrcAccess;
+ memoryBarrier.dstAccessMask = mGlobalMemoryBarrierDstAccess;
+
+ // Use the top of pipe stage to keep the state management simple.
+ primaryCommandBuffer->pipelineBarrier(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 1,
+ &memoryBarrier, 0, nullptr, 0, nullptr);
+ }
+
if (mOutsideRenderPassCommands.valid())
{
ANGLE_TRY(mOutsideRenderPassCommands.end(context));
@@ -630,10 +653,10 @@
mLastBarrierIndex = kInvalidNodeIndex;
VkCommandBufferAllocateInfo primaryInfo = {};
- primaryInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
- primaryInfo.commandPool = commandPool->getHandle();
- primaryInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
- primaryInfo.commandBufferCount = 1;
+ primaryInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
+ primaryInfo.commandPool = commandPool->getHandle();
+ primaryInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+ primaryInfo.commandBufferCount = 1;
ANGLE_TRY(primaryCommandBufferOut->init(context, primaryInfo));