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.
537{
539 vk::ImageMemoryBarrier barrier {};
540 barrier.oldLayout = old_layout;
541 barrier.newLayout = new_layout;
542 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
543 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
544 barrier.image =
image;
545 barrier.subresourceRange.aspectMask = aspect_flags;
546 barrier.subresourceRange.baseMipLevel = 0;
547 barrier.subresourceRange.levelCount = mip_levels;
548 barrier.subresourceRange.baseArrayLayer = 0;
549 barrier.subresourceRange.layerCount = array_layers;
550
551 vk::PipelineStageFlags src_stage;
552 vk::PipelineStageFlags dst_stage;
553
554 if (old_layout == vk::ImageLayout::eUndefined && new_layout == vk::ImageLayout::eTransferDstOptimal) {
555 barrier.srcAccessMask = vk::AccessFlags {};
556 barrier.dstAccessMask = vk::AccessFlagBits::eTransferWrite;
557 src_stage = vk::PipelineStageFlagBits::eTopOfPipe;
558 dst_stage = vk::PipelineStageFlagBits::eTransfer;
559 } else if (old_layout == vk::ImageLayout::eTransferDstOptimal && new_layout == vk::ImageLayout::eShaderReadOnlyOptimal) {
560 barrier.srcAccessMask = vk::AccessFlagBits::eTransferWrite;
561 barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead;
562 src_stage = vk::PipelineStageFlagBits::eTransfer;
563 dst_stage = vk::PipelineStageFlagBits::eFragmentShader;
564 } else if (old_layout == vk::ImageLayout::eUndefined && new_layout == vk::ImageLayout::eShaderReadOnlyOptimal) {
565 barrier.srcAccessMask = vk::AccessFlags {};
566 barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead;
567 src_stage = vk::PipelineStageFlagBits::eTopOfPipe;
568 dst_stage = vk::PipelineStageFlagBits::eFragmentShader;
569 } else if (old_layout == vk::ImageLayout::eUndefined && new_layout == vk::ImageLayout::eColorAttachmentOptimal) {
570 barrier.srcAccessMask = vk::AccessFlags {};
571 barrier.dstAccessMask = vk::AccessFlagBits::eColorAttachmentWrite;
572 src_stage = vk::PipelineStageFlagBits::eTopOfPipe;
573 dst_stage = vk::PipelineStageFlagBits::eColorAttachmentOutput;
574 } else if (old_layout == vk::ImageLayout::eUndefined && new_layout == vk::ImageLayout::eDepthStencilAttachmentOptimal) {
575 barrier.srcAccessMask = vk::AccessFlags {};
576 barrier.dstAccessMask = vk::AccessFlagBits::eDepthStencilAttachmentRead | vk::AccessFlagBits::eDepthStencilAttachmentWrite;
577 src_stage = vk::PipelineStageFlagBits::eTopOfPipe;
578 dst_stage = vk::PipelineStageFlagBits::eEarlyFragmentTests;
579 } else if (old_layout == vk::ImageLayout::eUndefined && new_layout == vk::ImageLayout::eGeneral) {
580 barrier.srcAccessMask = vk::AccessFlags {};
581 barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite;
582 src_stage = vk::PipelineStageFlagBits::eTopOfPipe;
583 dst_stage = vk::PipelineStageFlagBits::eComputeShader;
584 } else {
585 barrier.srcAccessMask = vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eMemoryWrite;
586 barrier.dstAccessMask = vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eMemoryWrite;
587 src_stage = vk::PipelineStageFlagBits::eAllCommands;
588 dst_stage = vk::PipelineStageFlagBits::eAllCommands;
589
591 "Using generic image layout transition");
592 }
593
595 src_stage, dst_stage,
596 vk::DependencyFlags {},
597 0, nullptr,
598 0, nullptr,
599 1, &barrier
600 );
601 });
602
604 "Image layout transitioned: {} -> {}",
605 vk::to_string(old_layout), vk::to_string(new_layout));
606}
#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.