MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches

◆ download_image_data()

void MayaFlux::Core::BackendResourceManager::download_image_data ( std::shared_ptr< VKImage image,
void *  data,
size_t  size,
vk::ImageLayout  restore_layout = vk::ImageLayout::eShaderReadOnlyOptimal,
vk::PipelineStageFlags  restore_stage = vk::PipelineStageFlagBits::eFragmentShader 
)

Download data from an image into a caller-supplied buffer.

Transitions the image to eTransferSrcOptimal, copies to a staging buffer, then restores it to restore_layout using restore_stage.

The defaults cover the common case of a device-local texture in shader read-only layout. Pass ePresentSrcKHR / eBottomOfPipe for swapchain images.

Parameters
imageSource image.
dataDestination host pointer (must be at least size bytes).
sizeByte count to read.
restore_layoutLayout to transition back to after the copy. Defaults to eShaderReadOnlyOptimal.
restore_stagePipeline stage that will consume the image after restore. Defaults to eFragmentShader.

Definition at line 817 of file BackendResoureManager.cpp.

823{
824 if (!image || !data) {
826 "Invalid parameters for download_image_data");
827 return;
828 }
829
830 auto staging = std::make_shared<Buffers::VKBuffer>(
831 size,
834
835 initialize_buffer(staging);
836
837 execute_immediate_commands([&](vk::CommandBuffer cmd) {
838 vk::ImageMemoryBarrier barrier {};
839 barrier.oldLayout = image->get_current_layout();
840 barrier.newLayout = vk::ImageLayout::eTransferSrcOptimal;
841 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
842 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
843 barrier.image = image->get_image();
844 barrier.subresourceRange.aspectMask = image->get_aspect_flags();
845 barrier.subresourceRange.baseMipLevel = 0;
846 barrier.subresourceRange.levelCount = image->get_mip_levels();
847 barrier.subresourceRange.baseArrayLayer = 0;
848 barrier.subresourceRange.layerCount = image->get_array_layers();
849 barrier.srcAccessMask = vk::AccessFlagBits::eShaderRead;
850 barrier.dstAccessMask = vk::AccessFlagBits::eTransferRead;
851
852 cmd.pipelineBarrier(
853 vk::PipelineStageFlagBits::eFragmentShader,
854 vk::PipelineStageFlagBits::eTransfer,
855 vk::DependencyFlags {}, {}, {}, barrier);
856
857 vk::BufferImageCopy region {};
858 region.bufferOffset = 0;
859 region.bufferRowLength = 0;
860 region.bufferImageHeight = 0;
861 region.imageSubresource.aspectMask = image->get_aspect_flags();
862 region.imageSubresource.mipLevel = 0;
863 region.imageSubresource.baseArrayLayer = 0;
864 region.imageSubresource.layerCount = image->get_array_layers();
865 region.imageOffset = vk::Offset3D { 0, 0, 0 };
866 region.imageExtent = vk::Extent3D {
867 image->get_width(),
868 image->get_height(),
869 image->get_depth()
870 };
871
872 cmd.copyImageToBuffer(
873 image->get_image(),
874 vk::ImageLayout::eTransferSrcOptimal,
875 staging->get_buffer(),
876 1, &region);
877
878 barrier.oldLayout = vk::ImageLayout::eTransferSrcOptimal;
879 barrier.newLayout = restore_layout;
880 barrier.srcAccessMask = vk::AccessFlagBits::eTransferRead;
881 barrier.dstAccessMask = vk::AccessFlagBits::eMemoryRead;
882
883 cmd.pipelineBarrier(
884 vk::PipelineStageFlagBits::eTransfer,
885 restore_stage,
886 vk::DependencyFlags {}, {}, {}, barrier);
887 });
888
889 staging->mark_invalid_range(0, size);
890 auto& resources = staging->get_buffer_resources();
891 vk::MappedMemoryRange range { resources.memory, 0, VK_WHOLE_SIZE };
892
893 if (auto result = m_context.get_device().invalidateMappedMemoryRanges(1, &range);
894 result != vk::Result::eSuccess) {
896 "Failed to invalidate mapped memory range: {}", vk::to_string(result));
897 }
898
899 if (void* mapped = staging->get_mapped_ptr()) {
900 std::memcpy(data, mapped, size);
901 }
902
903 cleanup_buffer(staging);
904
906 "Downloaded {} bytes from image {}x{}",
907 size, image->get_width(), image->get_height());
908}
#define MF_ERROR(comp, ctx,...)
#define MF_DEBUG(comp, ctx,...)
vk::CommandBuffer cmd
IO::ImageData image
Definition Decoder.cpp:57
@ STAGING
Host-visible staging buffer (CPU-writable, eTransferSrc|Dst)
void cleanup_buffer(const std::shared_ptr< Buffers::VKBuffer > &buffer)
Cleanup a buffer and release associated resources.
void execute_immediate_commands(const std::function< void(vk::CommandBuffer)> &recorder)
Execute immediate command recording for buffer operations.
void initialize_buffer(const std::shared_ptr< Buffers::VKBuffer > &buffer)
Initialize a buffer for use with the graphics backend.
vk::Device get_device() const
Get logical device.
Definition VKContext.hpp:49
@ GraphicsBackend
Graphics/visual rendering backend (Vulkan, OpenGL)
@ Core
Core engine, backend, subsystems.
@ IMAGE_COLOR
2D RGB/RGBA image
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.
Definition Analysis.cpp:452

References cleanup_buffer(), cmd, MayaFlux::Journal::Core, execute_immediate_commands(), MayaFlux::Core::VKContext::get_device(), MayaFlux::Journal::GraphicsBackend, image, MayaFlux::Kakshya::IMAGE_COLOR, initialize_buffer(), m_context, MF_DEBUG, MF_ERROR, and MayaFlux::Buffers::VKBuffer::STAGING.

Referenced by MayaFlux::Portal::Graphics::TextureLoom::download_data(), and MayaFlux::Core::BackendWindowHandler::setup_backend_service().

+ Here is the call graph for this function:
+ Here is the caller graph for this function: