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,
PipelineStage barrierIndex = kImageMemoryBarrierData[imageLayout].barrierIndex;
ASSERT(barrierIndex != PipelineStage::InvalidEnum);
PipelineBarrier *barrier = &mPipelineBarriers[barrierIndex];
image->updateLayoutAndBarrier(aspectFlags, imageLayout, barrier);
mPipelineBarrierMask.set(barrierIndex);
if (image->updateLayoutAndBarrier(aspectFlags, imageLayout, barrier))
{
mPipelineBarrierMask.set(barrierIndex);
}
}
}
......@@ -590,8 +592,10 @@ void CommandBufferHelper::imageWrite(vk::ResourceUseList *resourceUseList,
PipelineStage barrierIndex = kImageMemoryBarrierData[imageLayout].barrierIndex;
ASSERT(barrierIndex != PipelineStage::InvalidEnum);
PipelineBarrier *barrier = &mPipelineBarriers[barrierIndex];
image->updateLayoutAndBarrier(aspectFlags, imageLayout, barrier);
mPipelineBarrierMask.set(barrierIndex);
if (image->updateLayoutAndBarrier(aspectFlags, imageLayout, barrier))
{
mPipelineBarrierMask.set(barrierIndex);
}
}
void CommandBufferHelper::executeBarriers(vk::PrimaryCommandBuffer *primary)
......@@ -2428,6 +2432,8 @@ ImageHelper::ImageHelper(ImageHelper &&other)
mSerial(other.mSerial),
mCurrentLayout(other.mCurrentLayout),
mCurrentQueueFamilyIndex(other.mCurrentQueueFamilyIndex),
mLastNonShaderReadOnlyLayout(other.mLastNonShaderReadOnlyLayout),
mCurrentShaderReadStageMask(other.mCurrentShaderReadStageMask),
mBaseLevel(other.mBaseLevel),
mMaxLevel(other.mMaxLevel),
mLayerCount(other.mLayerCount),
......@@ -2446,17 +2452,19 @@ ImageHelper::~ImageHelper()
void ImageHelper::resetCachedProperties()
{
mImageType = VK_IMAGE_TYPE_2D;
mExtents = {};
mFormat = nullptr;
mSamples = 1;
mSerial = rx::kZeroSerial;
mCurrentLayout = ImageLayout::Undefined;
mCurrentQueueFamilyIndex = std::numeric_limits<uint32_t>::max();
mBaseLevel = 0;
mMaxLevel = 0;
mLayerCount = 0;
mLevelCount = 0;
mImageType = VK_IMAGE_TYPE_2D;
mExtents = {};
mFormat = nullptr;
mSamples = 1;
mSerial = rx::kZeroSerial;
mCurrentLayout = ImageLayout::Undefined;
mCurrentQueueFamilyIndex = std::numeric_limits<uint32_t>::max();
mLastNonShaderReadOnlyLayout = ImageLayout::Undefined;
mCurrentShaderReadStageMask = 0;
mBaseLevel = 0;
mMaxLevel = 0;
mLayerCount = 0;
mLevelCount = 0;
}
void ImageHelper::initStagingBuffer(RendererVk *renderer,
......@@ -2927,16 +2935,25 @@ void ImageHelper::forceChangeLayoutAndQueue(VkImageAspectFlags aspectMask,
VkImageMemoryBarrier imageMemoryBarrier = {};
initImageMemoryBarrierStruct(aspectMask, newLayout, newQueueFamilyIndex, &imageMemoryBarrier);
commandBuffer->imageBarrier(transitionFrom.srcStageMask, transitionTo.dstStageMask,
imageMemoryBarrier);
// There might be other shaderRead operations there other than the current layout.
VkPipelineStageFlags srcStageMask = transitionFrom.srcStageMask;
if (mCurrentShaderReadStageMask)
{
srcStageMask |= mCurrentShaderReadStageMask;
mCurrentShaderReadStageMask = 0;
mLastNonShaderReadOnlyLayout = ImageLayout::Undefined;
}
commandBuffer->imageBarrier(srcStageMask, transitionTo.dstStageMask, imageMemoryBarrier);
mCurrentLayout = newLayout;
mCurrentQueueFamilyIndex = newQueueFamilyIndex;
}
void ImageHelper::updateLayoutAndBarrier(VkImageAspectFlags aspectMask,
bool ImageHelper::updateLayoutAndBarrier(VkImageAspectFlags aspectMask,
ImageLayout newLayout,
PipelineBarrier *barrier)
{
bool barrierModified = false;
if (newLayout == mCurrentLayout)
{
const ImageMemoryBarrierData &layoutData = kImageMemoryBarrierData[mCurrentLayout];
......@@ -2944,20 +2961,63 @@ void ImageHelper::updateLayoutAndBarrier(VkImageAspectFlags aspectMask,
// No layout change, only memory barrier is required
barrier->mergeMemoryBarrier(layoutData.srcStageMask, layoutData.dstStageMask,
layoutData.srcAccessMask, layoutData.dstAccessMask);
barrierModified = true;
}
else
{
const ImageMemoryBarrierData &transitionFrom = kImageMemoryBarrierData[mCurrentLayout];
const ImageMemoryBarrierData &transitionTo = kImageMemoryBarrierData[newLayout];
VkPipelineStageFlags srcStageMask = transitionFrom.srcStageMask;
VkPipelineStageFlags dstStageMask = transitionTo.dstStageMask;
VkImageMemoryBarrier imageMemoryBarrier = {};
initImageMemoryBarrierStruct(aspectMask, newLayout, mCurrentQueueFamilyIndex,
&imageMemoryBarrier);
if (transitionTo.layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL &&
transitionFrom.layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
{
// 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,
imageMemoryBarrier);
// If we are transition into shaderRead layout, remember the last
// 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;
}
return barrierModified;
}
void ImageHelper::clearColor(const VkClearColorValue &color,
......
......@@ -1296,7 +1296,8 @@ class ImageHelper final : public Resource, public angle::Subject
uint32_t newQueueFamilyIndex,
CommandBuffer *commandBuffer);
void updateLayoutAndBarrier(VkImageAspectFlags aspectMask,
// Returns true if barrier has been generated
bool updateLayoutAndBarrier(VkImageAspectFlags aspectMask,
ImageLayout newLayout,
PipelineBarrier *barrier);
......@@ -1474,6 +1475,9 @@ class ImageHelper final : public Resource, public angle::Subject
// Current state.
ImageLayout mCurrentLayout;
uint32_t mCurrentQueueFamilyIndex;
// For optimizing transition between different shader readonly layouts
ImageLayout mLastNonShaderReadOnlyLayout;
VkPipelineStageFlags mCurrentShaderReadStageMask;
// Cached properties.
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