Upload image data using a caller-supplied persistent staging buffer.
613{
614 if (!image || !data || !staging) {
616 "Invalid parameters for upload_image_data_with_staging");
617 return;
618 }
619
620 void* mapped = staging->get_mapped_ptr();
621 if (!mapped) {
623 "upload_image_data_with_staging: staging buffer has no mapped pointer");
624 return;
625 }
626
627 std::memcpy(mapped, data, size);
628 staging->mark_dirty_range(0, size);
629
630 auto& resources = staging->get_buffer_resources();
631 vk::MappedMemoryRange
range { resources.memory, 0, VK_WHOLE_SIZE };
632
634 result != vk::Result::eSuccess) {
636 "upload_image_data_with_staging: flush failed: {}", vk::to_string(result));
637 }
638
640 vk::ImageMemoryBarrier barrier {};
641 barrier.oldLayout = image->get_current_layout();
642 barrier.newLayout = vk::ImageLayout::eTransferDstOptimal;
643 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
644 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
645 barrier.image = image->get_image();
646 barrier.subresourceRange = {
647 image->get_aspect_flags(), 0,
648 image->get_mip_levels(), 0,
649 image->get_array_layers()
650 };
651 barrier.srcAccessMask = vk::AccessFlagBits::eShaderRead;
652 barrier.dstAccessMask = vk::AccessFlagBits::eTransferWrite;
653
654 cmd.pipelineBarrier(
655 vk::PipelineStageFlagBits::eFragmentShader,
656 vk::PipelineStageFlagBits::eTransfer,
657 {}, 0, nullptr, 0, nullptr, 1, &barrier);
658
659 vk::BufferImageCopy region {};
660 region.imageSubresource.aspectMask = image->get_aspect_flags();
661 region.imageSubresource.layerCount = image->get_array_layers();
662 region.imageOffset = vk::Offset3D { 0, 0, 0 };
663 region.imageExtent = vk::Extent3D {
664 image->get_width(),
665 image->get_height(),
666 image->get_depth()
667 };
668
669 cmd.copyBufferToImage(
670 staging->get_buffer(),
671 image->get_image(),
672 vk::ImageLayout::eTransferDstOptimal,
673 1, ®ion);
674
675 barrier.oldLayout = vk::ImageLayout::eTransferDstOptimal;
676 barrier.newLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
677 barrier.srcAccessMask = vk::AccessFlagBits::eTransferWrite;
678 barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead;
679
680 cmd.pipelineBarrier(
681 vk::PipelineStageFlagBits::eTransfer,
682 vk::PipelineStageFlagBits::eFragmentShader,
683 {}, 0, nullptr, 0, nullptr, 1, &barrier);
684 });
685
686 image->set_current_layout(vk::ImageLayout::eShaderReadOnlyOptimal);
687
689 "upload_image_data_with_staging: {} bytes to image {}x{}",
690 size, image->get_width(), image->get_height());
691}
#define MF_ERROR(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.
vk::Device get_device() const
Get logical device.
@ GraphicsBackend
Graphics/visual rendering backend (Vulkan, OpenGL)
@ Core
Core engine, backend, subsystems.
std::vector< double > range(std::span< const double > data, size_t n_windows, uint32_t hop_size, uint32_t window_size)
Value range (max - min) per window.