Commit dceaabb1 by Jamie Madill Committed by Commit Bot

Vulkan: Clean up ImageHelper barrier functions.

We don't need to explicitly check if a barrier is required for write barriers. Write barriers always require a barrier and read barriers need the layout change check. We introduce a new enum encoding ReadOnly vs Write layout types and call specialized write/read functions instead. Also renames the helper APIs to be more consistent. Refactoring change only. Bug: angleproject:4959 Change-Id: I0ce39ceaca6be588327c381194a580dc6b11f036 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2344744 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCharlie Lao <cclao@google.com> Reviewed-by: 's avatarTim Van Patten <timvp@google.com>
parent 863115fb
...@@ -4364,12 +4364,10 @@ angle::Result ContextVk::onImageRead(VkImageAspectFlags aspectFlags, ...@@ -4364,12 +4364,10 @@ angle::Result ContextVk::onImageRead(VkImageAspectFlags aspectFlags,
// than a transfer read. So we cannot support simultaneous read usage as easily as for Buffers. // than a transfer read. So we cannot support simultaneous read usage as easily as for Buffers.
ANGLE_TRY(endRenderPassIfImageUsed(*image)); ANGLE_TRY(endRenderPassIfImageUsed(*image));
if (image->isLayoutChangeNecessary(imageLayout)) image->recordReadBarrier(aspectFlags, imageLayout,
{
image->changeLayout(aspectFlags, imageLayout,
&mOutsideRenderPassCommands->getCommandBuffer()); &mOutsideRenderPassCommands->getCommandBuffer());
}
image->retain(&mResourceUseList); image->retain(&mResourceUseList);
return angle::Result::Continue; return angle::Result::Continue;
} }
...@@ -4380,12 +4378,10 @@ angle::Result ContextVk::onImageWrite(VkImageAspectFlags aspectFlags, ...@@ -4380,12 +4378,10 @@ angle::Result ContextVk::onImageWrite(VkImageAspectFlags aspectFlags,
ASSERT(!image->isReleasedToExternal()); ASSERT(!image->isReleasedToExternal());
ASSERT(image->getImageSerial().valid()); ASSERT(image->getImageSerial().valid());
// Barriers are always required for image writes.
ASSERT(image->isLayoutChangeNecessary(imageLayout));
ANGLE_TRY(endRenderPassIfImageUsed(*image)); ANGLE_TRY(endRenderPassIfImageUsed(*image));
image->changeLayout(aspectFlags, imageLayout, &mOutsideRenderPassCommands->getCommandBuffer()); image->recordWriteBarrier(aspectFlags, imageLayout,
&mOutsideRenderPassCommands->getCommandBuffer());
image->retain(&mResourceUseList); image->retain(&mResourceUseList);
image->onWrite(); image->onWrite();
......
...@@ -1195,7 +1195,8 @@ angle::Result WindowSurfaceVk::present(ContextVk *contextVk, ...@@ -1195,7 +1195,8 @@ angle::Result WindowSurfaceVk::present(ContextVk *contextVk,
} }
// This does nothing if it already in the requested layout // This does nothing if it already in the requested layout
image.image.changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::Present, commandBuffer); image.image.recordReadBarrier(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::Present,
commandBuffer);
// Knowing that the kSwapHistorySize'th submission ago has finished, we can know that the // Knowing that the kSwapHistorySize'th submission ago has finished, we can know that the
// (kSwapHistorySize+1)'th present ago of this image is definitely finished and so its wait // (kSwapHistorySize+1)'th present ago of this image is definitely finished and so its wait
......
...@@ -65,6 +65,12 @@ constexpr angle::PackedEnumMap<PipelineStage, VkPipelineStageFlagBits> kPipeline ...@@ -65,6 +65,12 @@ constexpr angle::PackedEnumMap<PipelineStage, VkPipelineStageFlagBits> kPipeline
constexpr size_t kDefaultPoolAllocatorPageSize = 16 * 1024; constexpr size_t kDefaultPoolAllocatorPageSize = 16 * 1024;
enum BarrierType
{
ReadOnly,
Write
};
struct ImageMemoryBarrierData struct ImageMemoryBarrierData
{ {
// The Vk layout corresponding to the ImageLayout key. // The Vk layout corresponding to the ImageLayout key.
...@@ -80,13 +86,8 @@ struct ImageMemoryBarrierData ...@@ -80,13 +86,8 @@ struct ImageMemoryBarrierData
// Access mask when transitioning out from this layout. Note that source access mask never // Access mask when transitioning out from this layout. Note that source access mask never
// needs a READ bit, as WAR hazards don't need memory barriers (just execution barriers). // needs a READ bit, as WAR hazards don't need memory barriers (just execution barriers).
VkAccessFlags srcAccessMask; VkAccessFlags srcAccessMask;
// Read or write.
// If access is read-only, the memory barrier can be skipped altogether if retransitioning to BarrierType type;
// the same layout. This is because read-after-read does not need an execution or memory
// barrier.
//
// Otherwise, some same-layout transitions require a memory barrier.
bool sameLayoutTransitionRequiresBarrier;
// CommandBufferHelper tracks an array of PipelineBarriers. This indicates which array element // CommandBufferHelper tracks an array of PipelineBarriers. This indicates which array element
// this should be merged into. Right now we track individual barrier for every PipelineStage. If // this should be merged into. Right now we track individual barrier for every PipelineStage. If
// layout has a single stage mask bit, we use that stage as index. If layout has multiple stage // layout has a single stage mask bit, we use that stage as index. If layout has multiple stage
...@@ -110,7 +111,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -110,7 +111,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
0, 0,
// Transition from: there's no data in the image to care about. // Transition from: there's no data in the image to care about.
0, 0,
false, BarrierType::ReadOnly,
PipelineStage::InvalidEnum, PipelineStage::InvalidEnum,
}, },
}, },
...@@ -124,7 +125,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -124,7 +125,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
0, 0,
// Transition from: all writes must finish before barrier. // Transition from: all writes must finish before barrier.
VK_ACCESS_MEMORY_WRITE_BIT, VK_ACCESS_MEMORY_WRITE_BIT,
false, BarrierType::ReadOnly,
PipelineStage::InvalidEnum, PipelineStage::InvalidEnum,
}, },
}, },
...@@ -138,7 +139,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -138,7 +139,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_SHADER_READ_BIT,
// Transition from: RAR and WAR don't need memory barrier. // Transition from: RAR and WAR don't need memory barrier.
0, 0,
false, BarrierType::ReadOnly,
// In case of multiple destination stages, We barrier the earliest stage // In case of multiple destination stages, We barrier the earliest stage
PipelineStage::TopOfPipe, PipelineStage::TopOfPipe,
}, },
...@@ -153,7 +154,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -153,7 +154,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
// Transition from: all writes must finish before barrier. // Transition from: all writes must finish before barrier.
VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_WRITE_BIT,
true, BarrierType::Write,
// In case of multiple destination stages, We barrier the earliest stage // In case of multiple destination stages, We barrier the earliest stage
PipelineStage::TopOfPipe, PipelineStage::TopOfPipe,
}, },
...@@ -168,7 +169,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -168,7 +169,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_TRANSFER_READ_BIT,
// Transition from: RAR and WAR don't need memory barrier. // Transition from: RAR and WAR don't need memory barrier.
0, 0,
false, BarrierType::ReadOnly,
PipelineStage::Transfer, PipelineStage::Transfer,
}, },
}, },
...@@ -182,7 +183,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -182,7 +183,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_WRITE_BIT,
// Transition from: all writes must finish before barrier. // Transition from: all writes must finish before barrier.
VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_WRITE_BIT,
true, BarrierType::Write,
PipelineStage::Transfer, PipelineStage::Transfer,
}, },
}, },
...@@ -196,7 +197,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -196,7 +197,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_SHADER_READ_BIT,
// Transition from: RAR and WAR don't need memory barrier. // Transition from: RAR and WAR don't need memory barrier.
0, 0,
false, BarrierType::ReadOnly,
PipelineStage::VertexShader, PipelineStage::VertexShader,
}, },
}, },
...@@ -210,7 +211,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -210,7 +211,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
// Transition from: all writes must finish before barrier. // Transition from: all writes must finish before barrier.
VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_WRITE_BIT,
true, BarrierType::Write,
PipelineStage::VertexShader, PipelineStage::VertexShader,
}, },
}, },
...@@ -224,7 +225,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -224,7 +225,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_SHADER_READ_BIT,
// Transition from: RAR and WAR don't need memory barrier. // Transition from: RAR and WAR don't need memory barrier.
0, 0,
false, BarrierType::ReadOnly,
PipelineStage::GeometryShader, PipelineStage::GeometryShader,
}, },
}, },
...@@ -238,7 +239,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -238,7 +239,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
// Transition from: all writes must finish before barrier. // Transition from: all writes must finish before barrier.
VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_WRITE_BIT,
true, BarrierType::Write,
PipelineStage::GeometryShader, PipelineStage::GeometryShader,
}, },
}, },
...@@ -252,7 +253,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -252,7 +253,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_SHADER_READ_BIT,
// Transition from: RAR and WAR don't need memory barrier. // Transition from: RAR and WAR don't need memory barrier.
0, 0,
false, BarrierType::ReadOnly,
PipelineStage::FragmentShader, PipelineStage::FragmentShader,
}, },
}, },
...@@ -266,7 +267,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -266,7 +267,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
// Transition from: all writes must finish before barrier. // Transition from: all writes must finish before barrier.
VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_WRITE_BIT,
true, BarrierType::Write,
PipelineStage::FragmentShader, PipelineStage::FragmentShader,
}, },
}, },
...@@ -280,7 +281,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -280,7 +281,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_SHADER_READ_BIT,
// Transition from: RAR and WAR don't need memory barrier. // Transition from: RAR and WAR don't need memory barrier.
0, 0,
false, BarrierType::ReadOnly,
PipelineStage::ComputeShader, PipelineStage::ComputeShader,
}, },
}, },
...@@ -294,7 +295,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -294,7 +295,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
// Transition from: all writes must finish before barrier. // Transition from: all writes must finish before barrier.
VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_WRITE_BIT,
true, BarrierType::Write,
PipelineStage::ComputeShader, PipelineStage::ComputeShader,
}, },
}, },
...@@ -308,7 +309,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -308,7 +309,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_SHADER_READ_BIT,
// Transition from: RAR and WAR don't need memory barrier. // Transition from: RAR and WAR don't need memory barrier.
0, 0,
false, BarrierType::ReadOnly,
// In case of multiple destination stages, We barrier the earliest stage // In case of multiple destination stages, We barrier the earliest stage
PipelineStage::VertexShader, PipelineStage::VertexShader,
}, },
...@@ -323,7 +324,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -323,7 +324,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
// Transition from: all writes must finish before barrier. // Transition from: all writes must finish before barrier.
VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_WRITE_BIT,
true, BarrierType::Write,
// In case of multiple destination stages, We barrier the earliest stage // In case of multiple destination stages, We barrier the earliest stage
PipelineStage::VertexShader, PipelineStage::VertexShader,
}, },
...@@ -338,7 +339,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -338,7 +339,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
// Transition from: all writes must finish before barrier. // Transition from: all writes must finish before barrier.
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
true, BarrierType::Write,
PipelineStage::ColorAttachmentOutput, PipelineStage::ColorAttachmentOutput,
}, },
}, },
...@@ -352,7 +353,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -352,7 +353,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
// Transition from: all writes must finish before barrier. // Transition from: all writes must finish before barrier.
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
true, BarrierType::Write,
PipelineStage::EarlyFragmentTest, PipelineStage::EarlyFragmentTest,
}, },
}, },
...@@ -371,7 +372,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -371,7 +372,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
0, 0,
// Transition from: RAR and WAR don't need memory barrier. // Transition from: RAR and WAR don't need memory barrier.
0, 0,
false, BarrierType::ReadOnly,
PipelineStage::BottomOfPipe, PipelineStage::BottomOfPipe,
}, },
}, },
...@@ -594,7 +595,7 @@ void CommandBufferHelper::bufferRead(ResourceUseList *resourceUseList, ...@@ -594,7 +595,7 @@ void CommandBufferHelper::bufferRead(ResourceUseList *resourceUseList,
{ {
buffer->retain(resourceUseList); buffer->retain(resourceUseList);
VkPipelineStageFlagBits stageBits = kPipelineStageFlagBitMap[readStage]; VkPipelineStageFlagBits stageBits = kPipelineStageFlagBitMap[readStage];
if (buffer->updateReadBarrier(readAccessType, stageBits, &mPipelineBarriers[readStage])) if (buffer->recordReadBarrier(readAccessType, stageBits, &mPipelineBarriers[readStage]))
{ {
mPipelineBarrierMask.set(readStage); mPipelineBarrierMask.set(readStage);
} }
...@@ -614,7 +615,7 @@ void CommandBufferHelper::bufferWrite(ResourceUseList *resourceUseList, ...@@ -614,7 +615,7 @@ void CommandBufferHelper::bufferWrite(ResourceUseList *resourceUseList,
{ {
buffer->retain(resourceUseList); buffer->retain(resourceUseList);
VkPipelineStageFlagBits stageBits = kPipelineStageFlagBitMap[writeStage]; VkPipelineStageFlagBits stageBits = kPipelineStageFlagBitMap[writeStage];
if (buffer->updateWriteBarrier(writeAccessType, stageBits, &mPipelineBarriers[writeStage])) if (buffer->recordWriteBarrier(writeAccessType, stageBits, &mPipelineBarriers[writeStage]))
{ {
mPipelineBarrierMask.set(writeStage); mPipelineBarrierMask.set(writeStage);
} }
...@@ -636,7 +637,8 @@ void CommandBufferHelper::imageRead(ResourceUseList *resourceUseList, ...@@ -636,7 +637,8 @@ void CommandBufferHelper::imageRead(ResourceUseList *resourceUseList,
ImageHelper *image) ImageHelper *image)
{ {
image->retain(resourceUseList); image->retain(resourceUseList);
if (image->isLayoutChangeNecessary(imageLayout))
if (image->isReadBarrierNecessary(imageLayout))
{ {
PipelineStage barrierIndex = kImageMemoryBarrierData[imageLayout].barrierIndex; PipelineStage barrierIndex = kImageMemoryBarrierData[imageLayout].barrierIndex;
ASSERT(barrierIndex != PipelineStage::InvalidEnum); ASSERT(barrierIndex != PipelineStage::InvalidEnum);
...@@ -2599,7 +2601,7 @@ bool BufferHelper::isReleasedToExternal() const ...@@ -2599,7 +2601,7 @@ bool BufferHelper::isReleasedToExternal() const
#endif #endif
} }
bool BufferHelper::updateReadBarrier(VkAccessFlags readAccessType, bool BufferHelper::recordReadBarrier(VkAccessFlags readAccessType,
VkPipelineStageFlags readStage, VkPipelineStageFlags readStage,
PipelineBarrier *barrier) PipelineBarrier *barrier)
{ {
...@@ -2620,7 +2622,7 @@ bool BufferHelper::updateReadBarrier(VkAccessFlags readAccessType, ...@@ -2620,7 +2622,7 @@ bool BufferHelper::updateReadBarrier(VkAccessFlags readAccessType,
return barrierModified; return barrierModified;
} }
bool BufferHelper::updateWriteBarrier(VkAccessFlags writeAccessType, bool BufferHelper::recordWriteBarrier(VkAccessFlags writeAccessType,
VkPipelineStageFlags writeStage, VkPipelineStageFlags writeStage,
PipelineBarrier *barrier) PipelineBarrier *barrier)
{ {
...@@ -2827,7 +2829,7 @@ angle::Result ImageHelper::initializeNonZeroMemory(Context *context, VkDeviceSiz ...@@ -2827,7 +2829,7 @@ angle::Result ImageHelper::initializeNonZeroMemory(Context *context, VkDeviceSiz
ANGLE_TRY(renderer->getCommandBufferOneOff(context, &commandBuffer)); ANGLE_TRY(renderer->getCommandBufferOneOff(context, &commandBuffer));
// Queue a DMA copy. // Queue a DMA copy.
forceChangeLayoutAndQueue(getAspectFlags(), ImageLayout::TransferDst, mCurrentQueueFamilyIndex, barrierImpl(getAspectFlags(), ImageLayout::TransferDst, mCurrentQueueFamilyIndex,
&commandBuffer); &commandBuffer);
StagingBuffer stagingBuffer; StagingBuffer stagingBuffer;
...@@ -3187,17 +3189,17 @@ gl::Extents ImageHelper::getLevelExtents2D(uint32_t levelVK) const ...@@ -3187,17 +3189,17 @@ gl::Extents ImageHelper::getLevelExtents2D(uint32_t levelVK) const
return extents; return extents;
} }
bool ImageHelper::isLayoutChangeNecessary(ImageLayout newLayout) const bool ImageHelper::isReadBarrierNecessary(ImageLayout newLayout) const
{ {
const ImageMemoryBarrierData &layoutData = kImageMemoryBarrierData[mCurrentLayout]; // If transitioning to a different layout, we need always need a barrier.
if (mCurrentLayout != newLayout)
// If transitioning to the same layout, we don't need a barrier if the layout is read-only as {
// RAR (read-after-read) doesn't need a barrier. WAW (write-after-write) does require a memory return true;
// barrier though. }
bool sameLayoutAndNoNeedForBarrier =
mCurrentLayout == newLayout && !layoutData.sameLayoutTransitionRequiresBarrier;
return !sameLayoutAndNoNeedForBarrier; // RAW (read-after-write) hazards always requires a memory barrier.
const ImageMemoryBarrierData &layoutData = kImageMemoryBarrierData[mCurrentLayout];
return layoutData.type == BarrierType::Write;
} }
void ImageHelper::changeLayoutAndQueue(VkImageAspectFlags aspectMask, void ImageHelper::changeLayoutAndQueue(VkImageAspectFlags aspectMask,
...@@ -3206,7 +3208,7 @@ void ImageHelper::changeLayoutAndQueue(VkImageAspectFlags aspectMask, ...@@ -3206,7 +3208,7 @@ void ImageHelper::changeLayoutAndQueue(VkImageAspectFlags aspectMask,
CommandBuffer *commandBuffer) CommandBuffer *commandBuffer)
{ {
ASSERT(isQueueChangeNeccesary(newQueueFamilyIndex)); ASSERT(isQueueChangeNeccesary(newQueueFamilyIndex));
forceChangeLayoutAndQueue(aspectMask, newLayout, newQueueFamilyIndex, commandBuffer); barrierImpl(aspectMask, newLayout, newQueueFamilyIndex, commandBuffer);
} }
void ImageHelper::acquireFromExternal(ContextVk *contextVk, void ImageHelper::acquireFromExternal(ContextVk *contextVk,
...@@ -3282,7 +3284,7 @@ ANGLE_INLINE void ImageHelper::initImageMemoryBarrierStruct( ...@@ -3282,7 +3284,7 @@ ANGLE_INLINE void ImageHelper::initImageMemoryBarrierStruct(
// Generalized to accept both "primary" and "secondary" command buffers. // Generalized to accept both "primary" and "secondary" command buffers.
template <typename CommandBufferT> template <typename CommandBufferT>
void ImageHelper::forceChangeLayoutAndQueue(VkImageAspectFlags aspectMask, void ImageHelper::barrierImpl(VkImageAspectFlags aspectMask,
ImageLayout newLayout, ImageLayout newLayout,
uint32_t newQueueFamilyIndex, uint32_t newQueueFamilyIndex,
CommandBufferT *commandBuffer) CommandBufferT *commandBuffer)
...@@ -3315,7 +3317,7 @@ bool ImageHelper::updateLayoutAndBarrier(VkImageAspectFlags aspectMask, ...@@ -3315,7 +3317,7 @@ bool ImageHelper::updateLayoutAndBarrier(VkImageAspectFlags aspectMask,
if (newLayout == mCurrentLayout) if (newLayout == mCurrentLayout)
{ {
const ImageMemoryBarrierData &layoutData = kImageMemoryBarrierData[mCurrentLayout]; const ImageMemoryBarrierData &layoutData = kImageMemoryBarrierData[mCurrentLayout];
ASSERT(layoutData.sameLayoutTransitionRequiresBarrier); ASSERT(layoutData.type == BarrierType::Write);
// 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);
...@@ -4378,7 +4380,7 @@ angle::Result ImageHelper::flushStagedUpdates(ContextVk *contextVk, ...@@ -4378,7 +4380,7 @@ angle::Result ImageHelper::flushStagedUpdates(ContextVk *contextVk,
if (updateLayerCount >= kMaxParallelSubresourceUpload) if (updateLayerCount >= kMaxParallelSubresourceUpload)
{ {
// If there are more subresources than bits we can track, always insert a barrier. // If there are more subresources than bits we can track, always insert a barrier.
changeLayout(aspectFlags, ImageLayout::TransferDst, commandBuffer); recordWriteBarrier(aspectFlags, ImageLayout::TransferDst, commandBuffer);
subresourceUploadsInProgress = std::numeric_limits<uint64_t>::max(); subresourceUploadsInProgress = std::numeric_limits<uint64_t>::max();
} }
else else
...@@ -4392,7 +4394,7 @@ angle::Result ImageHelper::flushStagedUpdates(ContextVk *contextVk, ...@@ -4392,7 +4394,7 @@ angle::Result ImageHelper::flushStagedUpdates(ContextVk *contextVk,
if ((subresourceUploadsInProgress & subresourceHash) != 0) if ((subresourceUploadsInProgress & subresourceHash) != 0)
{ {
// If there's overlap in subresource upload, issue a barrier. // If there's overlap in subresource upload, issue a barrier.
changeLayout(aspectFlags, ImageLayout::TransferDst, commandBuffer); recordWriteBarrier(aspectFlags, ImageLayout::TransferDst, commandBuffer);
subresourceUploadsInProgress = 0; subresourceUploadsInProgress = 0;
} }
subresourceUploadsInProgress |= subresourceHash; subresourceUploadsInProgress |= subresourceHash;
......
...@@ -798,11 +798,11 @@ class BufferHelper final : public Resource ...@@ -798,11 +798,11 @@ class BufferHelper final : public Resource
// Returns true if the image is owned by an external API or instance. // Returns true if the image is owned by an external API or instance.
bool isReleasedToExternal() const; bool isReleasedToExternal() const;
bool updateReadBarrier(VkAccessFlags readAccessType, bool recordReadBarrier(VkAccessFlags readAccessType,
VkPipelineStageFlags readStage, VkPipelineStageFlags readStage,
PipelineBarrier *barrier); PipelineBarrier *barrier);
bool updateWriteBarrier(VkAccessFlags writeAccessType, bool recordWriteBarrier(VkAccessFlags writeAccessType,
VkPipelineStageFlags writeStage, VkPipelineStageFlags writeStage,
PipelineBarrier *barrier); PipelineBarrier *barrier);
...@@ -1353,22 +1353,26 @@ class ImageHelper final : public Resource, public angle::Subject ...@@ -1353,22 +1353,26 @@ class ImageHelper final : public Resource, public angle::Subject
bool isUpdateStaged(uint32_t levelGL, uint32_t layer); bool isUpdateStaged(uint32_t levelGL, uint32_t layer);
bool hasStagedUpdates() const { return !mSubresourceUpdates.empty(); } bool hasStagedUpdates() const { return !mSubresourceUpdates.empty(); }
// changeLayout automatically skips the layout change if it's unnecessary. This function can be void recordWriteBarrier(VkImageAspectFlags aspectMask,
// used to prevent creating a command graph node and subsequently a command buffer for the sole ImageLayout newLayout,
// purpose of performing a transition (which may then not be issued). CommandBuffer *commandBuffer)
bool isLayoutChangeNecessary(ImageLayout newLayout) const; {
barrierImpl(aspectMask, newLayout, mCurrentQueueFamilyIndex, commandBuffer);
}
template <typename CommandBufferT> // This function can be used to prevent issuing redundant layout transition commands.
void changeLayout(VkImageAspectFlags aspectMask, bool isReadBarrierNecessary(ImageLayout newLayout) const;
void recordReadBarrier(VkImageAspectFlags aspectMask,
ImageLayout newLayout, ImageLayout newLayout,
CommandBufferT *commandBuffer) CommandBuffer *commandBuffer)
{ {
if (!isLayoutChangeNecessary(newLayout)) if (!isReadBarrierNecessary(newLayout))
{ {
return; return;
} }
forceChangeLayoutAndQueue(aspectMask, newLayout, mCurrentQueueFamilyIndex, commandBuffer); barrierImpl(aspectMask, newLayout, mCurrentQueueFamilyIndex, commandBuffer);
} }
bool isQueueChangeNeccesary(uint32_t newQueueFamilyIndex) const bool isQueueChangeNeccesary(uint32_t newQueueFamilyIndex) const
...@@ -1531,7 +1535,7 @@ class ImageHelper final : public Resource, public angle::Subject ...@@ -1531,7 +1535,7 @@ class ImageHelper final : public Resource, public angle::Subject
// Generalized to accept both "primary" and "secondary" command buffers. // Generalized to accept both "primary" and "secondary" command buffers.
template <typename CommandBufferT> template <typename CommandBufferT>
void forceChangeLayoutAndQueue(VkImageAspectFlags aspectMask, void barrierImpl(VkImageAspectFlags aspectMask,
ImageLayout newLayout, ImageLayout newLayout,
uint32_t newQueueFamilyIndex, uint32_t newQueueFamilyIndex,
CommandBufferT *commandBuffer); CommandBufferT *commandBuffer);
......
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