Transition image layout using a pipeline barrier.
Executes immediately on graphics queue. Use for initial setup and one-off transitions. For rendering, prefer manual barriers.
557{
559 vk::ImageMemoryBarrier barrier {};
560 barrier.oldLayout = old_layout;
561 barrier.newLayout = new_layout;
562 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
563 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
564 barrier.image =
image;
565 barrier.subresourceRange.aspectMask = aspect_flags;
566 barrier.subresourceRange.baseMipLevel = 0;
567 barrier.subresourceRange.levelCount = mip_levels;
568 barrier.subresourceRange.baseArrayLayer = 0;
569 barrier.subresourceRange.layerCount = array_layers;
570
571 vk::PipelineStageFlags src_stage;
572 vk::PipelineStageFlags dst_stage;
573
574 if (old_layout == vk::ImageLayout::eUndefined && new_layout == vk::ImageLayout::eTransferDstOptimal) {
575 barrier.srcAccessMask = vk::AccessFlags {};
576 barrier.dstAccessMask = vk::AccessFlagBits::eTransferWrite;
577 src_stage = vk::PipelineStageFlagBits::eTopOfPipe;
578 dst_stage = vk::PipelineStageFlagBits::eTransfer;
579 } else if (old_layout == vk::ImageLayout::eTransferDstOptimal && new_layout == vk::ImageLayout::eShaderReadOnlyOptimal) {
580 barrier.srcAccessMask = vk::AccessFlagBits::eTransferWrite;
581 barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead;
582 src_stage = vk::PipelineStageFlagBits::eTransfer;
583 dst_stage = vk::PipelineStageFlagBits::eFragmentShader;
584 } else if (old_layout == vk::ImageLayout::eUndefined && new_layout == vk::ImageLayout::eShaderReadOnlyOptimal) {
585 barrier.srcAccessMask = vk::AccessFlags {};
586 barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead;
587 src_stage = vk::PipelineStageFlagBits::eTopOfPipe;
588 dst_stage = vk::PipelineStageFlagBits::eFragmentShader;
589 } else if (old_layout == vk::ImageLayout::eUndefined && new_layout == vk::ImageLayout::eColorAttachmentOptimal) {
590 barrier.srcAccessMask = vk::AccessFlags {};
591 barrier.dstAccessMask = vk::AccessFlagBits::eColorAttachmentWrite;
592 src_stage = vk::PipelineStageFlagBits::eTopOfPipe;
593 dst_stage = vk::PipelineStageFlagBits::eColorAttachmentOutput;
594 } else if (old_layout == vk::ImageLayout::eUndefined && new_layout == vk::ImageLayout::eDepthStencilAttachmentOptimal) {
595 barrier.srcAccessMask = vk::AccessFlags {};
596 barrier.dstAccessMask = vk::AccessFlagBits::eDepthStencilAttachmentRead | vk::AccessFlagBits::eDepthStencilAttachmentWrite;
597 src_stage = vk::PipelineStageFlagBits::eTopOfPipe;
598 dst_stage = vk::PipelineStageFlagBits::eEarlyFragmentTests;
599 } else if (old_layout == vk::ImageLayout::eUndefined && new_layout == vk::ImageLayout::eGeneral) {
600 barrier.srcAccessMask = vk::AccessFlags {};
601 barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite;
602 src_stage = vk::PipelineStageFlagBits::eTopOfPipe;
603 dst_stage = vk::PipelineStageFlagBits::eComputeShader;
604 } else {
605 barrier.srcAccessMask = vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eMemoryWrite;
606 barrier.dstAccessMask = vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eMemoryWrite;
607 src_stage = vk::PipelineStageFlagBits::eAllCommands;
608 dst_stage = vk::PipelineStageFlagBits::eAllCommands;
609
611 "Using generic image layout transition");
612 }
613
615 src_stage, dst_stage,
616 vk::DependencyFlags {},
617 0, nullptr,
618 0, nullptr,
619 1, &barrier
620 );
621 });
622
624 "Image layout transitioned: {} -> {}",
625 vk::to_string(old_layout), vk::to_string(new_layout));
626}
#define MF_WARN(comp, ctx,...)
#define MF_DEBUG(comp, ctx,...)
void execute_immediate_commands(const std::function< void(vk::CommandBuffer)> &recorder)
Execute immediate command recording for buffer operations.
@ GraphicsBackend
Graphics/visual rendering backend (Vulkan, OpenGL)
@ Core
Core engine, backend, subsystems.