Upload image data using a caller-supplied persistent staging buffer.
778{
779 if (!
image || !data || !staging) {
781 "Invalid parameters for upload_image_data_with_staging");
782 return;
783 }
784
785 void* mapped = staging->get_mapped_ptr();
786 if (!mapped) {
788 "upload_image_data_with_staging: staging buffer has no mapped pointer");
789 return;
790 }
791
792 std::memcpy(mapped, data, size);
793 staging->mark_dirty_range(0, size);
794
795 auto& resources = staging->get_buffer_resources();
796 vk::MappedMemoryRange
range { resources.memory, 0, VK_WHOLE_SIZE };
797
799 result != vk::Result::eSuccess) {
801 "upload_image_data_with_staging: flush failed: {}", vk::to_string(result));
802 }
803
804 auto record_command = [&](vk::CommandBuffer
cmd) {
805 vk::ImageMemoryBarrier barrier {};
806 barrier.oldLayout =
image->get_current_layout();
807 barrier.newLayout = vk::ImageLayout::eTransferDstOptimal;
808 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
809 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
810 barrier.image =
image->get_image();
811 barrier.subresourceRange = {
812 image->get_aspect_flags(), 0,
813 image->get_mip_levels(), 0,
814 image->get_array_layers()
815 };
816 barrier.srcAccessMask = vk::AccessFlagBits::eShaderRead;
817 barrier.dstAccessMask = vk::AccessFlagBits::eTransferWrite;
818
820 vk::PipelineStageFlagBits::eFragmentShader,
821 vk::PipelineStageFlagBits::eTransfer,
822 {}, 0, nullptr, 0, nullptr, 1, &barrier);
823
824 vk::BufferImageCopy region {};
825 region.imageSubresource.aspectMask =
image->get_aspect_flags();
826 region.imageSubresource.layerCount =
image->get_array_layers();
827 region.imageOffset = vk::Offset3D { 0, 0, 0 };
828 region.imageExtent = vk::Extent3D {
832 };
833
834 cmd.copyBufferToImage(
835 staging->get_buffer(),
837 vk::ImageLayout::eTransferDstOptimal,
838 1, ®ion);
839
840 barrier.oldLayout = vk::ImageLayout::eTransferDstOptimal;
841 barrier.newLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
842 barrier.srcAccessMask = vk::AccessFlagBits::eTransferWrite;
843 barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead;
844
846 vk::PipelineStageFlagBits::eTransfer,
847 vk::PipelineStageFlagBits::eFragmentShader,
848 {}, 0, nullptr, 0, nullptr, 1, &barrier);
849 };
850
851 if (deferred) {
853 } else {
855 }
856
857 image->set_current_layout(vk::ImageLayout::eShaderReadOnlyOptimal);
858
860 "upload_image_data_with_staging: {} bytes to image {}x{}",
861 size,
image->get_width(),
image->get_height());
862}
#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.
void record_deferred_commands(const std::function< void(vk::CommandBuffer)> &recorder)
Record deferred 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.