Commit 30298dc2 by Charlie Lao Committed by Commit Bot

Vulkan: Optimize out barrier needs for transition between shaderReadOnly

If we are transition between different kind of shaderReadOnly, there is no actual layout change or accessType change. Instead of always insert a barrier, this will track what shaderStage has made read access and only insert barrier if the read is from new shader stage. The barrier inserted will be always from last non-ShaderReadOnly transition. There is no read to read barrier generated. Bug: angleproject:4550 Change-Id: I4aeb7d4bddf2d072b60839f98e7af1aa23f977b5 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2204480 Commit-Queue: Charlie Lao <cclao@google.com> Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Reviewed-by: 's avatarCourtney Goeltzenleuchter <courtneygo@google.com>
parent 6de7ee52
...@@ -575,8 +575,10 @@ void CommandBufferHelper::imageRead(vk::ResourceUseList *resourceUseList, ...@@ -575,8 +575,10 @@ void CommandBufferHelper::imageRead(vk::ResourceUseList *resourceUseList,
PipelineStage barrierIndex = kImageMemoryBarrierData[imageLayout].barrierIndex; PipelineStage barrierIndex = kImageMemoryBarrierData[imageLayout].barrierIndex;
ASSERT(barrierIndex != PipelineStage::InvalidEnum); ASSERT(barrierIndex != PipelineStage::InvalidEnum);
PipelineBarrier *barrier = &mPipelineBarriers[barrierIndex]; PipelineBarrier *barrier = &mPipelineBarriers[barrierIndex];
image->updateLayoutAndBarrier(aspectFlags, imageLayout, barrier); if (image->updateLayoutAndBarrier(aspectFlags, imageLayout, barrier))
mPipelineBarrierMask.set(barrierIndex); {
mPipelineBarrierMask.set(barrierIndex);
}
} }
} }
...@@ -590,8 +592,10 @@ void CommandBufferHelper::imageWrite(vk::ResourceUseList *resourceUseList, ...@@ -590,8 +592,10 @@ void CommandBufferHelper::imageWrite(vk::ResourceUseList *resourceUseList,
PipelineStage barrierIndex = kImageMemoryBarrierData[imageLayout].barrierIndex; PipelineStage barrierIndex = kImageMemoryBarrierData[imageLayout].barrierIndex;
ASSERT(barrierIndex != PipelineStage::InvalidEnum); ASSERT(barrierIndex != PipelineStage::InvalidEnum);
PipelineBarrier *barrier = &mPipelineBarriers[barrierIndex]; PipelineBarrier *barrier = &mPipelineBarriers[barrierIndex];
image->updateLayoutAndBarrier(aspectFlags, imageLayout, barrier); if (image->updateLayoutAndBarrier(aspectFlags, imageLayout, barrier))
mPipelineBarrierMask.set(barrierIndex); {
mPipelineBarrierMask.set(barrierIndex);
}
} }
void CommandBufferHelper::executeBarriers(vk::PrimaryCommandBuffer *primary) void CommandBufferHelper::executeBarriers(vk::PrimaryCommandBuffer *primary)
...@@ -2428,6 +2432,8 @@ ImageHelper::ImageHelper(ImageHelper &&other) ...@@ -2428,6 +2432,8 @@ ImageHelper::ImageHelper(ImageHelper &&other)
mSerial(other.mSerial), mSerial(other.mSerial),
mCurrentLayout(other.mCurrentLayout), mCurrentLayout(other.mCurrentLayout),
mCurrentQueueFamilyIndex(other.mCurrentQueueFamilyIndex), mCurrentQueueFamilyIndex(other.mCurrentQueueFamilyIndex),
mLastNonShaderReadOnlyLayout(other.mLastNonShaderReadOnlyLayout),
mCurrentShaderReadStageMask(other.mCurrentShaderReadStageMask),
mBaseLevel(other.mBaseLevel), mBaseLevel(other.mBaseLevel),
mMaxLevel(other.mMaxLevel), mMaxLevel(other.mMaxLevel),
mLayerCount(other.mLayerCount), mLayerCount(other.mLayerCount),
...@@ -2446,17 +2452,19 @@ ImageHelper::~ImageHelper() ...@@ -2446,17 +2452,19 @@ ImageHelper::~ImageHelper()
void ImageHelper::resetCachedProperties() void ImageHelper::resetCachedProperties()
{ {
mImageType = VK_IMAGE_TYPE_2D; mImageType = VK_IMAGE_TYPE_2D;
mExtents = {}; mExtents = {};
mFormat = nullptr; mFormat = nullptr;
mSamples = 1; mSamples = 1;
mSerial = rx::kZeroSerial; mSerial = rx::kZeroSerial;
mCurrentLayout = ImageLayout::Undefined; mCurrentLayout = ImageLayout::Undefined;
mCurrentQueueFamilyIndex = std::numeric_limits<uint32_t>::max(); mCurrentQueueFamilyIndex = std::numeric_limits<uint32_t>::max();
mBaseLevel = 0; mLastNonShaderReadOnlyLayout = ImageLayout::Undefined;
mMaxLevel = 0; mCurrentShaderReadStageMask = 0;
mLayerCount = 0; mBaseLevel = 0;
mLevelCount = 0; mMaxLevel = 0;
mLayerCount = 0;
mLevelCount = 0;
} }
void ImageHelper::initStagingBuffer(RendererVk *renderer, void ImageHelper::initStagingBuffer(RendererVk *renderer,
...@@ -2927,16 +2935,25 @@ void ImageHelper::forceChangeLayoutAndQueue(VkImageAspectFlags aspectMask, ...@@ -2927,16 +2935,25 @@ void ImageHelper::forceChangeLayoutAndQueue(VkImageAspectFlags aspectMask,
VkImageMemoryBarrier imageMemoryBarrier = {}; VkImageMemoryBarrier imageMemoryBarrier = {};
initImageMemoryBarrierStruct(aspectMask, newLayout, newQueueFamilyIndex, &imageMemoryBarrier); initImageMemoryBarrierStruct(aspectMask, newLayout, newQueueFamilyIndex, &imageMemoryBarrier);
commandBuffer->imageBarrier(transitionFrom.srcStageMask, transitionTo.dstStageMask, // There might be other shaderRead operations there other than the current layout.
imageMemoryBarrier); VkPipelineStageFlags srcStageMask = transitionFrom.srcStageMask;
if (mCurrentShaderReadStageMask)
{
srcStageMask |= mCurrentShaderReadStageMask;
mCurrentShaderReadStageMask = 0;
mLastNonShaderReadOnlyLayout = ImageLayout::Undefined;
}
commandBuffer->imageBarrier(srcStageMask, transitionTo.dstStageMask, imageMemoryBarrier);
mCurrentLayout = newLayout; mCurrentLayout = newLayout;
mCurrentQueueFamilyIndex = newQueueFamilyIndex; mCurrentQueueFamilyIndex = newQueueFamilyIndex;
} }
void ImageHelper::updateLayoutAndBarrier(VkImageAspectFlags aspectMask, bool ImageHelper::updateLayoutAndBarrier(VkImageAspectFlags aspectMask,
ImageLayout newLayout, ImageLayout newLayout,
PipelineBarrier *barrier) PipelineBarrier *barrier)
{ {
bool barrierModified = false;
if (newLayout == mCurrentLayout) if (newLayout == mCurrentLayout)
{ {
const ImageMemoryBarrierData &layoutData = kImageMemoryBarrierData[mCurrentLayout]; const ImageMemoryBarrierData &layoutData = kImageMemoryBarrierData[mCurrentLayout];
...@@ -2944,20 +2961,63 @@ void ImageHelper::updateLayoutAndBarrier(VkImageAspectFlags aspectMask, ...@@ -2944,20 +2961,63 @@ void ImageHelper::updateLayoutAndBarrier(VkImageAspectFlags aspectMask,
// No layout change, only memory barrier is required // No layout change, only memory barrier is required
barrier->mergeMemoryBarrier(layoutData.srcStageMask, layoutData.dstStageMask, barrier->mergeMemoryBarrier(layoutData.srcStageMask, layoutData.dstStageMask,
layoutData.srcAccessMask, layoutData.dstAccessMask); layoutData.srcAccessMask, layoutData.dstAccessMask);
barrierModified = true;
} }
else else
{ {
const ImageMemoryBarrierData &transitionFrom = kImageMemoryBarrierData[mCurrentLayout]; const ImageMemoryBarrierData &transitionFrom = kImageMemoryBarrierData[mCurrentLayout];
const ImageMemoryBarrierData &transitionTo = kImageMemoryBarrierData[newLayout]; const ImageMemoryBarrierData &transitionTo = kImageMemoryBarrierData[newLayout];
VkPipelineStageFlags srcStageMask = transitionFrom.srcStageMask;
VkPipelineStageFlags dstStageMask = transitionTo.dstStageMask;
VkImageMemoryBarrier imageMemoryBarrier = {}; if (transitionTo.layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL &&
initImageMemoryBarrierStruct(aspectMask, newLayout, mCurrentQueueFamilyIndex, transitionFrom.layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
&imageMemoryBarrier); {
// If we are switching between different shader stage reads, then there is no actual
// layout change or access type change. We only need a barrier if we are making a read
// that is from a new stage. Also note that we barrier against previous non-shaderRead
// layout. We do not barrier between one shaderRead and another shaderRead.
bool isNewReadStage = (mCurrentShaderReadStageMask & dstStageMask) != dstStageMask;
if (isNewReadStage)
{
const ImageMemoryBarrierData &layoutData =
kImageMemoryBarrierData[mLastNonShaderReadOnlyLayout];
barrier->mergeMemoryBarrier(layoutData.srcStageMask, dstStageMask,
layoutData.srcAccessMask, transitionTo.dstAccessMask);
barrierModified = true;
// Accumulate new read stage.
mCurrentShaderReadStageMask |= dstStageMask;
}
}
else
{
VkImageMemoryBarrier imageMemoryBarrier = {};
initImageMemoryBarrierStruct(aspectMask, newLayout, mCurrentQueueFamilyIndex,
&imageMemoryBarrier);
// if we transition from shaderReadOnly, we must add in stashed shader stage masks since
// there might be outstanding shader reads from stages other than current layout. We do
// not insert barrier between one shaderRead to another shaderRead
if (mCurrentShaderReadStageMask)
{
srcStageMask |= mCurrentShaderReadStageMask;
mCurrentShaderReadStageMask = 0;
mLastNonShaderReadOnlyLayout = ImageLayout::Undefined;
}
barrier->mergeImageBarrier(srcStageMask, dstStageMask, imageMemoryBarrier);
barrierModified = true;
barrier->mergeImageBarrier(transitionFrom.srcStageMask, transitionTo.dstStageMask, // If we are transition into shaderRead layout, remember the last
imageMemoryBarrier); // non-shaderRead layout here.
if (transitionTo.layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
{
ASSERT(transitionFrom.layout != VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
mLastNonShaderReadOnlyLayout = mCurrentLayout;
mCurrentShaderReadStageMask = dstStageMask;
}
}
mCurrentLayout = newLayout; mCurrentLayout = newLayout;
} }
return barrierModified;
} }
void ImageHelper::clearColor(const VkClearColorValue &color, void ImageHelper::clearColor(const VkClearColorValue &color,
......
...@@ -1296,7 +1296,8 @@ class ImageHelper final : public Resource, public angle::Subject ...@@ -1296,7 +1296,8 @@ class ImageHelper final : public Resource, public angle::Subject
uint32_t newQueueFamilyIndex, uint32_t newQueueFamilyIndex,
CommandBuffer *commandBuffer); CommandBuffer *commandBuffer);
void updateLayoutAndBarrier(VkImageAspectFlags aspectMask, // Returns true if barrier has been generated
bool updateLayoutAndBarrier(VkImageAspectFlags aspectMask,
ImageLayout newLayout, ImageLayout newLayout,
PipelineBarrier *barrier); PipelineBarrier *barrier);
...@@ -1474,6 +1475,9 @@ class ImageHelper final : public Resource, public angle::Subject ...@@ -1474,6 +1475,9 @@ class ImageHelper final : public Resource, public angle::Subject
// Current state. // Current state.
ImageLayout mCurrentLayout; ImageLayout mCurrentLayout;
uint32_t mCurrentQueueFamilyIndex; uint32_t mCurrentQueueFamilyIndex;
// For optimizing transition between different shader readonly layouts
ImageLayout mLastNonShaderReadOnlyLayout;
VkPipelineStageFlags mCurrentShaderReadStageMask;
// Cached properties. // Cached properties.
uint32_t mBaseLevel; uint32_t mBaseLevel;
......
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