Commit 153c14cb by Charlie Lao Committed by Commit Bot

Vulkan: Try to merge barriers if possible

This is try to reduce the number of vkCmdPipelineBarrier API calls into driver. It should not affect the actual barriers. Bug: b/155341891 Change-Id: I57b8b8cdad50d494c76a008006bd54961170c8bc Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2194841 Commit-Queue: Charlie Lao <cclao@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org>
parent 9724aa3d
...@@ -582,17 +582,49 @@ void CommandBufferHelper::imageWrite(vk::ResourceUseList *resourceUseList, ...@@ -582,17 +582,49 @@ void CommandBufferHelper::imageWrite(vk::ResourceUseList *resourceUseList,
void CommandBufferHelper::executeBarriers(vk::PrimaryCommandBuffer *primary) void CommandBufferHelper::executeBarriers(vk::PrimaryCommandBuffer *primary)
{ {
if (!mPipelineBarrierMask.any()) if (mPipelineBarrierMask.none())
{ {
return; return;
} }
for (PipelineStage pipelineStage : mPipelineBarrierMask) constexpr PipelineStagesMask kHostTransferAndCompute(
angle::Bit<uint16_t>(PipelineStage::Host) | angle::Bit<uint16_t>(PipelineStage::Transfer) |
angle::Bit<uint16_t>(PipelineStage::ComputeShader));
// Process Host/Transfer/Compute barriers individually
PipelineStagesMask mask = mPipelineBarrierMask & kHostTransferAndCompute;
for (PipelineStage pipelineStage : mask)
{
mPipelineBarriers[pipelineStage].execute(primary);
}
mPipelineBarrierMask &= ~mask;
// Graphics pipeline
if (mPipelineBarrierMask.none())
{ {
PipelineBarrier &barrier = mPipelineBarriers[pipelineStage]; return;
barrier.writeCommand(primary); }
// Now we walk through all stages in graphics pipeline and see if we can merge them without
// introducing extra dependency. If the lower stage's dependency already covers the higher
// stage's dependency, then we just merge the higher stage into lower stage.
mask = mPipelineBarrierMask;
PipelineStagesMask::Iterator iter(mask);
PipelineBarrier *barrier = &mPipelineBarriers[*iter];
mask.reset(*iter);
for (PipelineStage pipelineStage : mask)
{
PipelineBarrier *newBarrier = &mPipelineBarriers[pipelineStage];
if (!barrier->mergeIfDependencyStrongerThan(newBarrier))
{
barrier->execute(primary);
barrier = newBarrier;
}
} }
mPipelineBarrierMask.reset(); mPipelineBarrierMask.reset();
ASSERT(barrier);
barrier->execute(primary);
} }
void CommandBufferHelper::beginRenderPass(const vk::Framebuffer &framebuffer, void CommandBufferHelper::beginRenderPass(const vk::Framebuffer &framebuffer,
......
...@@ -598,7 +598,7 @@ class PipelineBarrier : angle::NonCopyable ...@@ -598,7 +598,7 @@ class PipelineBarrier : angle::NonCopyable
bool isEmpty() const { return mImageMemoryBarriers.empty() && mMemoryBarrierSrcAccess == 0; } bool isEmpty() const { return mImageMemoryBarriers.empty() && mMemoryBarrierSrcAccess == 0; }
void writeCommand(PrimaryCommandBuffer *primary) void execute(PrimaryCommandBuffer *primary)
{ {
if (isEmpty()) if (isEmpty())
{ {
...@@ -622,6 +622,22 @@ class PipelineBarrier : angle::NonCopyable ...@@ -622,6 +622,22 @@ class PipelineBarrier : angle::NonCopyable
reset(); reset();
} }
// Merge the other barrier into this one if this barrier's dependency also covers dependency of
// the other barrier. Returns true if we actually merged.
bool mergeIfDependencyStrongerThan(PipelineBarrier *other)
{
// If mDstStageMask already has the other's mDstStageMask bits, then merge it
bool doMerge = (mDstStageMask == (mDstStageMask | other->mDstStageMask)) ||
// If my dependency is stronger then we can merge
(gl::ScanReverse(mSrcStageMask) >= gl::ScanReverse(other->mSrcStageMask));
if (doMerge)
{
merge(other);
}
return doMerge;
}
// merge two barriers into one // merge two barriers into one
void merge(PipelineBarrier *other) void merge(PipelineBarrier *other)
{ {
......
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