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.
439{
441 vk::ImageMemoryBarrier barrier {};
442 barrier.oldLayout = old_layout;
443 barrier.newLayout = new_layout;
444 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
445 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
446 barrier.image = image;
447 barrier.subresourceRange.aspectMask = aspect_flags;
448 barrier.subresourceRange.baseMipLevel = 0;
449 barrier.subresourceRange.levelCount = mip_levels;
450 barrier.subresourceRange.baseArrayLayer = 0;
451 barrier.subresourceRange.layerCount = array_layers;
452
453 vk::PipelineStageFlags src_stage;
454 vk::PipelineStageFlags dst_stage;
455
456 if (old_layout == vk::ImageLayout::eUndefined && new_layout == vk::ImageLayout::eTransferDstOptimal) {
457 barrier.srcAccessMask = vk::AccessFlags {};
458 barrier.dstAccessMask = vk::AccessFlagBits::eTransferWrite;
459 src_stage = vk::PipelineStageFlagBits::eTopOfPipe;
460 dst_stage = vk::PipelineStageFlagBits::eTransfer;
461 } else if (old_layout == vk::ImageLayout::eTransferDstOptimal && new_layout == vk::ImageLayout::eShaderReadOnlyOptimal) {
462 barrier.srcAccessMask = vk::AccessFlagBits::eTransferWrite;
463 barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead;
464 src_stage = vk::PipelineStageFlagBits::eTransfer;
465 dst_stage = vk::PipelineStageFlagBits::eFragmentShader;
466 } else if (old_layout == vk::ImageLayout::eUndefined && new_layout == vk::ImageLayout::eShaderReadOnlyOptimal) {
467 barrier.srcAccessMask = vk::AccessFlags {};
468 barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead;
469 src_stage = vk::PipelineStageFlagBits::eTopOfPipe;
470 dst_stage = vk::PipelineStageFlagBits::eFragmentShader;
471 } else if (old_layout == vk::ImageLayout::eUndefined && new_layout == vk::ImageLayout::eColorAttachmentOptimal) {
472 barrier.srcAccessMask = vk::AccessFlags {};
473 barrier.dstAccessMask = vk::AccessFlagBits::eColorAttachmentWrite;
474 src_stage = vk::PipelineStageFlagBits::eTopOfPipe;
475 dst_stage = vk::PipelineStageFlagBits::eColorAttachmentOutput;
476 } else if (old_layout == vk::ImageLayout::eUndefined && new_layout == vk::ImageLayout::eDepthStencilAttachmentOptimal) {
477 barrier.srcAccessMask = vk::AccessFlags {};
478 barrier.dstAccessMask = vk::AccessFlagBits::eDepthStencilAttachmentRead | vk::AccessFlagBits::eDepthStencilAttachmentWrite;
479 src_stage = vk::PipelineStageFlagBits::eTopOfPipe;
480 dst_stage = vk::PipelineStageFlagBits::eEarlyFragmentTests;
481 } else if (old_layout == vk::ImageLayout::eUndefined && new_layout == vk::ImageLayout::eGeneral) {
482 barrier.srcAccessMask = vk::AccessFlags {};
483 barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite;
484 src_stage = vk::PipelineStageFlagBits::eTopOfPipe;
485 dst_stage = vk::PipelineStageFlagBits::eComputeShader;
486 } else {
487 barrier.srcAccessMask = vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eMemoryWrite;
488 barrier.dstAccessMask = vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eMemoryWrite;
489 src_stage = vk::PipelineStageFlagBits::eAllCommands;
490 dst_stage = vk::PipelineStageFlagBits::eAllCommands;
491
493 "Using generic image layout transition");
494 }
495
496 cmd.pipelineBarrier(
497 src_stage, dst_stage,
498 vk::DependencyFlags {},
499 0, nullptr,
500 0, nullptr,
501 1, &barrier
502 );
503 });
504
506 "Image layout transitioned: {} -> {}",
507 vk::to_string(old_layout), vk::to_string(new_layout));
508}
#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.