fix(core): Sync image transition based on layout (#4540)

This commit is contained in:
Adrian Cojocaru
2026-09-02 14:29:54 +03:00
committed by GitHub
parent e5d0fce32a
commit 96e806931d
2 changed files with 44 additions and 22 deletions

View File

@@ -510,22 +510,23 @@ void SurfaceRenderableResource::copySurfaceToReadTexture() {
auto& commandBuffer = contextImpl.getCommandBuffer();
const auto oldLayout = surface ? vk::ImageLayout::ePresentSrcKHR : vk::ImageLayout::eTransferSrcOptimal;
const auto srcStage = vk::PipelineStageFlagBits::eColorAttachmentOutput;
const vk::AccessFlags srcAccess = vk::AccessFlagBits::eColorAttachmentWrite;
const vk::AccessFlags dstAccess = vk::AccessFlagBits::eTransferRead;
const auto readBarrier = vk::ImageMemoryBarrier()
.setImage(swapchainImage)
.setOldLayout(oldLayout)
.setNewLayout(vk::ImageLayout::eTransferSrcOptimal)
.setSrcAccessMask(srcAccess)
.setDstAccessMask(dstAccess)
.setSrcAccessMask(vk::AccessFlagBits::eColorAttachmentWrite)
.setDstAccessMask(vk::AccessFlagBits::eTransferRead)
.setSrcQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
.setDstQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
.setSubresourceRange({vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1});
commandBuffer->pipelineBarrier(
srcStage, vk::PipelineStageFlagBits::eTransfer, {}, nullptr, nullptr, readBarrier, dispatcher);
commandBuffer->pipelineBarrier(vk::PipelineStageFlagBits::eColorAttachmentOutput,
vk::PipelineStageFlagBits::eTransfer,
{},
nullptr,
nullptr,
readBarrier,
dispatcher);
bool useBlit =
surface &&
@@ -545,14 +546,14 @@ void SurfaceRenderableResource::copySurfaceToReadTexture() {
.setImage(swapchainImage)
.setOldLayout(vk::ImageLayout::eTransferSrcOptimal)
.setNewLayout(vk::ImageLayout::ePresentSrcKHR)
.setSrcAccessMask(vk::AccessFlagBits::eMemoryRead)
.setDstAccessMask(vk::AccessFlagBits::eTransferWrite)
.setSrcAccessMask(vk::AccessFlagBits::eTransferRead)
.setDstAccessMask({})
.setSrcQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
.setDstQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
.setSubresourceRange({vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1});
commandBuffer->pipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe,
vk::PipelineStageFlagBits::eTransfer,
commandBuffer->pipelineBarrier(vk::PipelineStageFlagBits::eTransfer,
vk::PipelineStageFlagBits::eBottomOfPipe,
{},
nullptr,
nullptr,

View File

@@ -466,17 +466,32 @@ void Texture2D::destroySampler(bool deferred) {
}
void Texture2D::transitionToTransferWriteLayout(const vk::UniqueCommandBuffer& buffer) {
const auto barrier = vk::ImageMemoryBarrier()
.setImage(imageAllocation->image)
.setOldLayout(imageLayout)
.setNewLayout(vk::ImageLayout::eTransferDstOptimal)
.setSrcAccessMask({})
.setDstAccessMask(vk::AccessFlagBits::eTransferWrite)
.setSrcQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
.setDstQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
.setSubresourceRange({vk::ImageAspectFlagBits::eColor, 0, getMipLevels(), 0, 1});
auto barrier = vk::ImageMemoryBarrier()
.setImage(imageAllocation->image)
.setOldLayout(imageLayout)
.setNewLayout(vk::ImageLayout::eTransferDstOptimal)
.setSrcAccessMask({})
.setDstAccessMask(vk::AccessFlagBits::eTransferWrite)
.setSrcQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
.setDstQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
.setSubresourceRange({vk::ImageAspectFlagBits::eColor, 0, getMipLevels(), 0, 1});
buffer->pipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe,
vk::PipelineStageFlags srcMask = vk::PipelineStageFlagBits::eTopOfPipe;
if (imageLayout == vk::ImageLayout::eUndefined) {
barrier.setSrcAccessMask({});
srcMask = vk::PipelineStageFlagBits::eTopOfPipe;
} else if (imageLayout == vk::ImageLayout::eShaderReadOnlyOptimal) {
barrier.setSrcAccessMask(vk::AccessFlagBits::eShaderRead);
srcMask = vk::PipelineStageFlagBits::eFragmentShader;
} else if (imageLayout == vk::ImageLayout::eGeneral) {
barrier.setSrcAccessMask(vk::AccessFlagBits::eTransferWrite);
srcMask = vk::PipelineStageFlagBits::eTransfer;
} else {
assert(false);
}
buffer->pipelineBarrier(srcMask,
vk::PipelineStageFlagBits::eTransfer,
{},
nullptr,
@@ -488,6 +503,8 @@ void Texture2D::transitionToTransferWriteLayout(const vk::UniqueCommandBuffer& b
}
void Texture2D::transitionToTransferReadLayout(const vk::UniqueCommandBuffer& buffer) {
assert(imageLayout == vk::ImageLayout::eTransferDstOptimal);
const auto barrier = vk::ImageMemoryBarrier()
.setImage(imageAllocation->image)
.setOldLayout(imageLayout)
@@ -510,6 +527,8 @@ void Texture2D::transitionToTransferReadLayout(const vk::UniqueCommandBuffer& bu
}
void Texture2D::transitionToShaderReadLayout(const vk::UniqueCommandBuffer& buffer) {
assert(imageLayout == vk::ImageLayout::eTransferSrcOptimal || imageLayout == vk::ImageLayout::eTransferDstOptimal);
const auto srcAccessMask = imageLayout == vk::ImageLayout::eTransferSrcOptimal ? vk::AccessFlagBits::eTransferRead
: vk::AccessFlagBits::eTransferWrite;
@@ -535,6 +554,8 @@ void Texture2D::transitionToShaderReadLayout(const vk::UniqueCommandBuffer& buff
}
void Texture2D::transitionToGeneralLayout(const vk::UniqueCommandBuffer& buffer) {
assert(imageLayout == vk::ImageLayout::eTransferDstOptimal);
const auto barrier = vk::ImageMemoryBarrier()
.setImage(imageAllocation->image)
.setOldLayout(imageLayout)