Commit 6b924160 by Charlie Lao Committed by Commit Bot

Vulkan: Split barriers into multiple calls to ensure no extra dependency

gets introduced This tracks barriers in an array based on dstPipelineStage. Bug: b/155341891 Change-Id: Icba2ef81530edcdb9ae363b00f0e7b9efe93d48f Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2188955Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Charlie Lao <cclao@google.com>
parent fa507296
...@@ -84,8 +84,17 @@ struct ImageMemoryBarrierData ...@@ -84,8 +84,17 @@ struct ImageMemoryBarrierData
// //
// Otherwise, some same-layout transitions require a memory barrier. // Otherwise, some same-layout transitions require a memory barrier.
bool sameLayoutTransitionRequiresBarrier; bool sameLayoutTransitionRequiresBarrier;
// 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
// layout has a single stage mask bit, we use that stage as index. If layout has multiple stage
// mask bits, we pick the lowest stage as the index since it is the first stage that needs
// barrier.
PipelineStage barrierIndex;
}; };
constexpr VkPipelineStageFlags kAllShadersPipelineStageFlags =
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
// clang-format off // clang-format off
constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemoryBarrierData = { constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemoryBarrierData = {
{ {
...@@ -99,6 +108,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -99,6 +108,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
// 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, false,
PipelineStage::InvalidEnum,
}, },
}, },
{ {
...@@ -112,6 +122,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -112,6 +122,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
// 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, false,
PipelineStage::InvalidEnum,
}, },
}, },
{ {
...@@ -125,6 +136,8 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -125,6 +136,8 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
// Transition from: RAR and WAR don't need memory barrier. // Transition from: RAR and WAR don't need memory barrier.
0, 0,
false, false,
// In case of multiple destination stages, We barrier the earliest stage
PipelineStage::TopOfPipe,
}, },
}, },
{ {
...@@ -138,6 +151,8 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -138,6 +151,8 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
// 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, true,
// In case of multiple destination stages, We barrier the earliest stage
PipelineStage::TopOfPipe,
}, },
}, },
{ {
...@@ -151,6 +166,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -151,6 +166,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
// Transition from: RAR and WAR don't need memory barrier. // Transition from: RAR and WAR don't need memory barrier.
0, 0,
false, false,
PipelineStage::Transfer,
}, },
}, },
{ {
...@@ -164,6 +180,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -164,6 +180,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
// 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, true,
PipelineStage::Transfer,
}, },
}, },
{ {
...@@ -177,6 +194,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -177,6 +194,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
// Transition from: RAR and WAR don't need memory barrier. // Transition from: RAR and WAR don't need memory barrier.
0, 0,
false, false,
PipelineStage::VertexShader,
}, },
}, },
{ {
...@@ -190,6 +208,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -190,6 +208,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
// 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, true,
PipelineStage::VertexShader,
}, },
}, },
{ {
...@@ -203,6 +222,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -203,6 +222,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
// Transition from: RAR and WAR don't need memory barrier. // Transition from: RAR and WAR don't need memory barrier.
0, 0,
false, false,
PipelineStage::GeometryShader,
}, },
}, },
{ {
...@@ -216,6 +236,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -216,6 +236,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
// 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, true,
PipelineStage::GeometryShader,
}, },
}, },
{ {
...@@ -229,6 +250,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -229,6 +250,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
// Transition from: RAR and WAR don't need memory barrier. // Transition from: RAR and WAR don't need memory barrier.
0, 0,
false, false,
PipelineStage::FragmentShader,
}, },
}, },
{ {
...@@ -242,6 +264,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -242,6 +264,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
// 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, true,
PipelineStage::FragmentShader,
}, },
}, },
{ {
...@@ -255,6 +278,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -255,6 +278,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
// Transition from: RAR and WAR don't need memory barrier. // Transition from: RAR and WAR don't need memory barrier.
0, 0,
false, false,
PipelineStage::ComputeShader,
}, },
}, },
{ {
...@@ -268,32 +292,37 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -268,32 +292,37 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
// 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, true,
vk::PipelineStage::ComputeShader,
}, },
}, },
{ {
ImageLayout::AllGraphicsShadersReadOnly, ImageLayout::AllGraphicsShadersReadOnly,
{ {
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, kAllShadersPipelineStageFlags,
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, kAllShadersPipelineStageFlags,
// Transition to: all reads must happen after barrier. // Transition to: all reads must happen after barrier.
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, false,
// In case of multiple destination stages, We barrier the earliest stage
PipelineStage::VertexShader,
}, },
}, },
{ {
ImageLayout::AllGraphicsShadersReadWrite, ImageLayout::AllGraphicsShadersReadWrite,
{ {
VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL,
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, kAllShadersPipelineStageFlags,
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, kAllShadersPipelineStageFlags,
// Transition to: all reads and writes must happen after barrier. // Transition to: all reads and writes must happen after barrier.
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, true,
// In case of multiple destination stages, We barrier the earliest stage
PipelineStage::VertexShader,
}, },
}, },
{ {
...@@ -307,6 +336,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -307,6 +336,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
// 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, true,
PipelineStage::ColorAttachmentOutput,
}, },
}, },
{ {
...@@ -320,6 +350,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -320,6 +350,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
// 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, true,
PipelineStage::EarlyFragmentTest,
}, },
}, },
{ {
...@@ -338,6 +369,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -338,6 +369,7 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
// Transition from: RAR and WAR don't need memory barrier. // Transition from: RAR and WAR don't need memory barrier.
0, 0,
false, false,
PipelineStage::BottomOfPipe,
}, },
}, },
}; };
...@@ -471,7 +503,8 @@ VkImageLayout ConvertImageLayoutToVkImageLayout(ImageLayout imageLayout) ...@@ -471,7 +503,8 @@ VkImageLayout ConvertImageLayoutToVkImageLayout(ImageLayout imageLayout)
// CommandBufferHelper implementation. // CommandBufferHelper implementation.
CommandBufferHelper::CommandBufferHelper(bool hasRenderPass) CommandBufferHelper::CommandBufferHelper(bool hasRenderPass)
: mPipelineBarrier(), : mPipelineBarriers(),
mPipelineBarrierMask(),
mCounter(0), mCounter(0),
mClearValues{}, mClearValues{},
mRenderPassStarted(false), mRenderPassStarted(false),
...@@ -498,7 +531,10 @@ void CommandBufferHelper::bufferRead(vk::ResourceUseList *resourceUseList, ...@@ -498,7 +531,10 @@ void CommandBufferHelper::bufferRead(vk::ResourceUseList *resourceUseList,
{ {
buffer->retain(resourceUseList); buffer->retain(resourceUseList);
VkPipelineStageFlagBits stageBits = kPipelineStageFlagBitMap[readStage]; VkPipelineStageFlagBits stageBits = kPipelineStageFlagBitMap[readStage];
buffer->updateReadBarrier(readAccessType, stageBits, &mPipelineBarrier); if (buffer->updateReadBarrier(readAccessType, stageBits, &mPipelineBarriers[readStage]))
{
mPipelineBarrierMask.set(readStage);
}
} }
void CommandBufferHelper::bufferWrite(vk::ResourceUseList *resourceUseList, void CommandBufferHelper::bufferWrite(vk::ResourceUseList *resourceUseList,
...@@ -508,14 +544,10 @@ void CommandBufferHelper::bufferWrite(vk::ResourceUseList *resourceUseList, ...@@ -508,14 +544,10 @@ void CommandBufferHelper::bufferWrite(vk::ResourceUseList *resourceUseList,
{ {
buffer->retain(resourceUseList); buffer->retain(resourceUseList);
VkPipelineStageFlagBits stageBits = kPipelineStageFlagBitMap[writeStage]; VkPipelineStageFlagBits stageBits = kPipelineStageFlagBitMap[writeStage];
buffer->updateWriteBarrier(writeAccessType, stageBits, &mPipelineBarrier); if (buffer->updateWriteBarrier(writeAccessType, stageBits, &mPipelineBarriers[writeStage]))
} {
mPipelineBarrierMask.set(writeStage);
void CommandBufferHelper::imageBarrier(VkPipelineStageFlags srcStageMask, }
VkPipelineStageFlags dstStageMask,
const VkImageMemoryBarrier &imageMemoryBarrier)
{
mPipelineBarrier.mergeImageBarrier(srcStageMask, dstStageMask, imageMemoryBarrier);
} }
void CommandBufferHelper::imageRead(vk::ResourceUseList *resourceUseList, void CommandBufferHelper::imageRead(vk::ResourceUseList *resourceUseList,
...@@ -526,7 +558,11 @@ void CommandBufferHelper::imageRead(vk::ResourceUseList *resourceUseList, ...@@ -526,7 +558,11 @@ void CommandBufferHelper::imageRead(vk::ResourceUseList *resourceUseList,
image->retain(resourceUseList); image->retain(resourceUseList);
if (image->isLayoutChangeNecessary(imageLayout)) if (image->isLayoutChangeNecessary(imageLayout))
{ {
image->changeLayout(aspectFlags, imageLayout, this); PipelineStage barrierIndex = kImageMemoryBarrierData[imageLayout].barrierIndex;
ASSERT(barrierIndex != PipelineStage::InvalidEnum);
PipelineBarrier *barrier = &mPipelineBarriers[barrierIndex];
image->updateLayoutAndBarrier(aspectFlags, imageLayout, barrier);
mPipelineBarrierMask.set(barrierIndex);
} }
} }
...@@ -536,12 +572,27 @@ void CommandBufferHelper::imageWrite(vk::ResourceUseList *resourceUseList, ...@@ -536,12 +572,27 @@ void CommandBufferHelper::imageWrite(vk::ResourceUseList *resourceUseList,
vk::ImageHelper *image) vk::ImageHelper *image)
{ {
image->retain(resourceUseList); image->retain(resourceUseList);
image->changeLayout(aspectFlags, imageLayout, this); // Write always requires a barrier
PipelineStage barrierIndex = kImageMemoryBarrierData[imageLayout].barrierIndex;
ASSERT(barrierIndex != PipelineStage::InvalidEnum);
PipelineBarrier *barrier = &mPipelineBarriers[barrierIndex];
image->updateLayoutAndBarrier(aspectFlags, imageLayout, barrier);
mPipelineBarrierMask.set(barrierIndex);
} }
void CommandBufferHelper::executeBarriers(vk::PrimaryCommandBuffer *primary) void CommandBufferHelper::executeBarriers(vk::PrimaryCommandBuffer *primary)
{ {
mPipelineBarrier.writeCommand(primary); if (!mPipelineBarrierMask.any())
{
return;
}
for (PipelineStage pipelineStage : mPipelineBarrierMask)
{
PipelineBarrier &barrier = mPipelineBarriers[pipelineStage];
barrier.writeCommand(primary);
}
mPipelineBarrierMask.reset();
} }
void CommandBufferHelper::beginRenderPass(const vk::Framebuffer &framebuffer, void CommandBufferHelper::beginRenderPass(const vk::Framebuffer &framebuffer,
...@@ -679,7 +730,13 @@ void CommandBufferHelper::addCommandDiagnostics(ContextVk *contextVk) ...@@ -679,7 +730,13 @@ void CommandBufferHelper::addCommandDiagnostics(ContextVk *contextVk)
std::ostringstream out; std::ostringstream out;
out << "Memory Barrier: "; out << "Memory Barrier: ";
mPipelineBarrier.addDiagnosticsString(out); for (PipelineBarrier &barrier : mPipelineBarriers)
{
if (!barrier.isEmpty())
{
barrier.addDiagnosticsString(out);
}
}
out << "\\l"; out << "\\l";
if (mIsRenderPassCommandBuffer) if (mIsRenderPassCommandBuffer)
...@@ -2006,9 +2063,8 @@ void PipelineBarrier::addDiagnosticsString(std::ostringstream &out) const ...@@ -2006,9 +2063,8 @@ void PipelineBarrier::addDiagnosticsString(std::ostringstream &out) const
{ {
if (mMemoryBarrierSrcAccess != 0 || mMemoryBarrierDstAccess != 0) if (mMemoryBarrierSrcAccess != 0 || mMemoryBarrierDstAccess != 0)
{ {
out << "{" out << "Src: 0x" << std::hex << mMemoryBarrierSrcAccess << " &rarr; Dst: 0x" << std::hex
<< "Src: 0x" << std::hex << mMemoryBarrierSrcAccess << " -> Dst: 0x" << std::hex << mMemoryBarrierDstAccess << std::endl;
<< mMemoryBarrierDstAccess << "}";
} }
} }
...@@ -2271,10 +2327,11 @@ bool BufferHelper::canAccumulateWrite(ContextVk *contextVk, VkAccessFlags writeA ...@@ -2271,10 +2327,11 @@ bool BufferHelper::canAccumulateWrite(ContextVk *contextVk, VkAccessFlags writeA
return false; return false;
} }
void BufferHelper::updateReadBarrier(VkAccessFlags readAccessType, bool BufferHelper::updateReadBarrier(VkAccessFlags readAccessType,
VkPipelineStageFlags readStage, VkPipelineStageFlags readStage,
PipelineBarrier *barrier) PipelineBarrier *barrier)
{ {
bool barrierModified = false;
// If there was a prior write and we are making a read that is either a new access type or from // If there was a prior write and we are making a read that is either a new access type or from
// a new stage, we need a barrier // a new stage, we need a barrier
if (mCurrentWriteAccess != 0 && (((mCurrentReadAccess & readAccessType) != readAccessType) || if (mCurrentWriteAccess != 0 && (((mCurrentReadAccess & readAccessType) != readAccessType) ||
...@@ -2282,17 +2339,20 @@ void BufferHelper::updateReadBarrier(VkAccessFlags readAccessType, ...@@ -2282,17 +2339,20 @@ void BufferHelper::updateReadBarrier(VkAccessFlags readAccessType,
{ {
barrier->mergeMemoryBarrier(mCurrentWriteStages, readStage, mCurrentWriteAccess, barrier->mergeMemoryBarrier(mCurrentWriteStages, readStage, mCurrentWriteAccess,
readAccessType); readAccessType);
barrierModified = true;
} }
// Accumulate new read usage. // Accumulate new read usage.
mCurrentReadAccess |= readAccessType; mCurrentReadAccess |= readAccessType;
mCurrentReadStages |= readStage; mCurrentReadStages |= readStage;
return barrierModified;
} }
void BufferHelper::updateWriteBarrier(VkAccessFlags writeAccessType, bool BufferHelper::updateWriteBarrier(VkAccessFlags writeAccessType,
VkPipelineStageFlags writeStage, VkPipelineStageFlags writeStage,
PipelineBarrier *barrier) PipelineBarrier *barrier)
{ {
bool barrierModified = false;
// We don't need to check mCurrentReadStages here since if it is not zero, mCurrentReadAccess // We don't need to check mCurrentReadStages here since if it is not zero, mCurrentReadAccess
// must not be zero as well. stage is finer grain than accessType. // must not be zero as well. stage is finer grain than accessType.
ASSERT((!mCurrentReadStages && !mCurrentReadAccess) || ASSERT((!mCurrentReadStages && !mCurrentReadAccess) ||
...@@ -2301,6 +2361,7 @@ void BufferHelper::updateWriteBarrier(VkAccessFlags writeAccessType, ...@@ -2301,6 +2361,7 @@ void BufferHelper::updateWriteBarrier(VkAccessFlags writeAccessType,
{ {
barrier->mergeMemoryBarrier(mCurrentWriteStages | mCurrentReadStages, writeStage, barrier->mergeMemoryBarrier(mCurrentWriteStages | mCurrentReadStages, writeStage,
mCurrentWriteAccess, writeAccessType); mCurrentWriteAccess, writeAccessType);
barrierModified = true;
} }
// Reset usages on the new write. // Reset usages on the new write.
...@@ -2308,6 +2369,7 @@ void BufferHelper::updateWriteBarrier(VkAccessFlags writeAccessType, ...@@ -2308,6 +2369,7 @@ void BufferHelper::updateWriteBarrier(VkAccessFlags writeAccessType,
mCurrentReadAccess = 0; mCurrentReadAccess = 0;
mCurrentWriteStages = writeStage; mCurrentWriteStages = writeStage;
mCurrentReadStages = 0; mCurrentReadStages = 0;
return barrierModified;
} }
// ImageHelper implementation. // ImageHelper implementation.
...@@ -2758,6 +2820,32 @@ void ImageHelper::setBaseAndMaxLevels(uint32_t baseLevel, uint32_t maxLevel) ...@@ -2758,6 +2820,32 @@ void ImageHelper::setBaseAndMaxLevels(uint32_t baseLevel, uint32_t maxLevel)
mMaxLevel = maxLevel; mMaxLevel = maxLevel;
} }
ANGLE_INLINE void ImageHelper::initImageMemoryBarrierStruct(
VkImageAspectFlags aspectMask,
ImageLayout newLayout,
uint32_t newQueueFamilyIndex,
VkImageMemoryBarrier *imageMemoryBarrier) const
{
const ImageMemoryBarrierData &transitionFrom = kImageMemoryBarrierData[mCurrentLayout];
const ImageMemoryBarrierData &transitionTo = kImageMemoryBarrierData[newLayout];
imageMemoryBarrier->sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
imageMemoryBarrier->srcAccessMask = transitionFrom.srcAccessMask;
imageMemoryBarrier->dstAccessMask = transitionTo.dstAccessMask;
imageMemoryBarrier->oldLayout = transitionFrom.layout;
imageMemoryBarrier->newLayout = transitionTo.layout;
imageMemoryBarrier->srcQueueFamilyIndex = mCurrentQueueFamilyIndex;
imageMemoryBarrier->dstQueueFamilyIndex = newQueueFamilyIndex;
imageMemoryBarrier->image = mImage.getHandle();
// Transition the whole resource.
imageMemoryBarrier->subresourceRange.aspectMask = aspectMask;
imageMemoryBarrier->subresourceRange.baseMipLevel = 0;
imageMemoryBarrier->subresourceRange.levelCount = mLevelCount;
imageMemoryBarrier->subresourceRange.baseArrayLayer = 0;
imageMemoryBarrier->subresourceRange.layerCount = mLayerCount;
}
// 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::forceChangeLayoutAndQueue(VkImageAspectFlags aspectMask,
...@@ -2769,21 +2857,7 @@ void ImageHelper::forceChangeLayoutAndQueue(VkImageAspectFlags aspectMask, ...@@ -2769,21 +2857,7 @@ void ImageHelper::forceChangeLayoutAndQueue(VkImageAspectFlags aspectMask,
const ImageMemoryBarrierData &transitionTo = kImageMemoryBarrierData[newLayout]; const ImageMemoryBarrierData &transitionTo = kImageMemoryBarrierData[newLayout];
VkImageMemoryBarrier imageMemoryBarrier = {}; VkImageMemoryBarrier imageMemoryBarrier = {};
imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; initImageMemoryBarrierStruct(aspectMask, newLayout, newQueueFamilyIndex, &imageMemoryBarrier);
imageMemoryBarrier.srcAccessMask = transitionFrom.srcAccessMask;
imageMemoryBarrier.dstAccessMask = transitionTo.dstAccessMask;
imageMemoryBarrier.oldLayout = transitionFrom.layout;
imageMemoryBarrier.newLayout = transitionTo.layout;
imageMemoryBarrier.srcQueueFamilyIndex = mCurrentQueueFamilyIndex;
imageMemoryBarrier.dstQueueFamilyIndex = newQueueFamilyIndex;
imageMemoryBarrier.image = mImage.getHandle();
// Transition the whole resource.
imageMemoryBarrier.subresourceRange.aspectMask = aspectMask;
imageMemoryBarrier.subresourceRange.baseMipLevel = 0;
imageMemoryBarrier.subresourceRange.levelCount = mLevelCount;
imageMemoryBarrier.subresourceRange.baseArrayLayer = 0;
imageMemoryBarrier.subresourceRange.layerCount = mLayerCount;
commandBuffer->imageBarrier(transitionFrom.srcStageMask, transitionTo.dstStageMask, commandBuffer->imageBarrier(transitionFrom.srcStageMask, transitionTo.dstStageMask,
imageMemoryBarrier); imageMemoryBarrier);
...@@ -2791,11 +2865,32 @@ void ImageHelper::forceChangeLayoutAndQueue(VkImageAspectFlags aspectMask, ...@@ -2791,11 +2865,32 @@ void ImageHelper::forceChangeLayoutAndQueue(VkImageAspectFlags aspectMask,
mCurrentQueueFamilyIndex = newQueueFamilyIndex; mCurrentQueueFamilyIndex = newQueueFamilyIndex;
} }
// Explicitly instantiate forceChangeLayoutAndQueue with CommandBufferHelper. void ImageHelper::updateLayoutAndBarrier(VkImageAspectFlags aspectMask,
template void ImageHelper::forceChangeLayoutAndQueue(VkImageAspectFlags aspectMask,
ImageLayout newLayout, ImageLayout newLayout,
uint32_t newQueueFamilyIndex, PipelineBarrier *barrier)
CommandBufferHelper *commandBuffer); {
if (newLayout == mCurrentLayout)
{
const ImageMemoryBarrierData &layoutData = kImageMemoryBarrierData[mCurrentLayout];
ASSERT(layoutData.sameLayoutTransitionRequiresBarrier);
// No layout change, only memory barrier is required
barrier->mergeMemoryBarrier(layoutData.srcStageMask, layoutData.dstStageMask,
layoutData.srcAccessMask, layoutData.dstAccessMask);
}
else
{
const ImageMemoryBarrierData &transitionFrom = kImageMemoryBarrierData[mCurrentLayout];
const ImageMemoryBarrierData &transitionTo = kImageMemoryBarrierData[newLayout];
VkImageMemoryBarrier imageMemoryBarrier = {};
initImageMemoryBarrierStruct(aspectMask, newLayout, mCurrentQueueFamilyIndex,
&imageMemoryBarrier);
barrier->mergeImageBarrier(transitionFrom.srcStageMask, transitionTo.dstStageMask,
imageMemoryBarrier);
mCurrentLayout = newLayout;
}
}
void ImageHelper::clearColor(const VkClearColorValue &color, void ImageHelper::clearColor(const VkClearColorValue &color,
uint32_t baseMipLevel, uint32_t baseMipLevel,
......
...@@ -623,14 +623,15 @@ class PipelineBarrier : angle::NonCopyable ...@@ -623,14 +623,15 @@ class PipelineBarrier : angle::NonCopyable
} }
// merge two barriers into one // merge two barriers into one
void merge(const PipelineBarrier &other) void merge(PipelineBarrier *other)
{ {
mSrcStageMask |= other.mSrcStageMask; mSrcStageMask |= other->mSrcStageMask;
mDstStageMask |= other.mDstStageMask; mDstStageMask |= other->mDstStageMask;
mMemoryBarrierSrcAccess |= other.mMemoryBarrierSrcAccess; mMemoryBarrierSrcAccess |= other->mMemoryBarrierSrcAccess;
mMemoryBarrierDstAccess |= other.mMemoryBarrierDstAccess; mMemoryBarrierDstAccess |= other->mMemoryBarrierDstAccess;
mImageMemoryBarriers.insert(mImageMemoryBarriers.end(), other.mImageMemoryBarriers.begin(), mImageMemoryBarriers.insert(mImageMemoryBarriers.end(), other->mImageMemoryBarriers.begin(),
other.mImageMemoryBarriers.end()); other->mImageMemoryBarriers.end());
other->reset();
} }
void mergeMemoryBarrier(VkPipelineStageFlags srcStageMask, void mergeMemoryBarrier(VkPipelineStageFlags srcStageMask,
...@@ -775,11 +776,11 @@ class BufferHelper final : public Resource ...@@ -775,11 +776,11 @@ class BufferHelper final : public Resource
bool canAccumulateRead(ContextVk *contextVk, VkAccessFlags readAccessType); bool canAccumulateRead(ContextVk *contextVk, VkAccessFlags readAccessType);
bool canAccumulateWrite(ContextVk *contextVk, VkAccessFlags writeAccessType); bool canAccumulateWrite(ContextVk *contextVk, VkAccessFlags writeAccessType);
void updateReadBarrier(VkAccessFlags readAccessType, bool updateReadBarrier(VkAccessFlags readAccessType,
VkPipelineStageFlags readStage, VkPipelineStageFlags readStage,
PipelineBarrier *barrier); PipelineBarrier *barrier);
void updateWriteBarrier(VkAccessFlags writeAccessType, bool updateWriteBarrier(VkAccessFlags writeAccessType,
VkPipelineStageFlags writeStage, VkPipelineStageFlags writeStage,
PipelineBarrier *barrier); PipelineBarrier *barrier);
...@@ -842,10 +843,6 @@ struct CommandBufferHelper : angle::NonCopyable ...@@ -842,10 +843,6 @@ struct CommandBufferHelper : angle::NonCopyable
vk::ImageLayout imageLayout, vk::ImageLayout imageLayout,
vk::ImageHelper *image); vk::ImageHelper *image);
void imageBarrier(VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask,
const VkImageMemoryBarrier &imageMemoryBarrier);
vk::CommandBuffer &getCommandBuffer() { return mCommandBuffer; } vk::CommandBuffer &getCommandBuffer() { return mCommandBuffer; }
angle::Result flushToPrimary(ContextVk *contextVk, vk::PrimaryCommandBuffer *primary); angle::Result flushToPrimary(ContextVk *contextVk, vk::PrimaryCommandBuffer *primary);
...@@ -929,7 +926,8 @@ struct CommandBufferHelper : angle::NonCopyable ...@@ -929,7 +926,8 @@ struct CommandBufferHelper : angle::NonCopyable
void addCommandDiagnostics(ContextVk *contextVk); void addCommandDiagnostics(ContextVk *contextVk);
// General state (non-renderPass related) // General state (non-renderPass related)
vk::PipelineBarrier mPipelineBarrier; PipelineBarrierArray mPipelineBarriers;
PipelineStagesMask mPipelineBarrierMask;
vk::CommandBuffer mCommandBuffer; vk::CommandBuffer mCommandBuffer;
// RenderPass state // RenderPass state
...@@ -1278,6 +1276,10 @@ class ImageHelper final : public Resource, public angle::Subject ...@@ -1278,6 +1276,10 @@ class ImageHelper final : public Resource, public angle::Subject
uint32_t newQueueFamilyIndex, uint32_t newQueueFamilyIndex,
CommandBuffer *commandBuffer); CommandBuffer *commandBuffer);
void updateLayoutAndBarrier(VkImageAspectFlags aspectMask,
ImageLayout newLayout,
PipelineBarrier *barrier);
// Performs an ownership transfer from an external instance or API. // Performs an ownership transfer from an external instance or API.
void acquireFromExternal(ContextVk *contextVk, void acquireFromExternal(ContextVk *contextVk,
uint32_t externalQueueFamilyIndex, uint32_t externalQueueFamilyIndex,
...@@ -1402,6 +1404,11 @@ class ImageHelper final : public Resource, public angle::Subject ...@@ -1402,6 +1404,11 @@ class ImageHelper final : public Resource, public angle::Subject
}; };
}; };
void initImageMemoryBarrierStruct(VkImageAspectFlags aspectMask,
ImageLayout newLayout,
uint32_t newQueueFamilyIndex,
VkImageMemoryBarrier *imageMemoryBarrier) const;
// 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 forceChangeLayoutAndQueue(VkImageAspectFlags aspectMask,
......
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