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

◆ upload_image_layer()

bool MayaFlux::Core::BackendResourceManager::upload_image_layer ( const std::shared_ptr< VKImage > &  image,
uint32_t  layer,
const void *  data,
size_t  size,
const std::shared_ptr< Buffers::VKBuffer > &  staging = nullptr,
bool  deferred = false 
)

Upload pixel data into one layer of an array image.

The other layers keep their contents. size must equal one layer's byte count. With staging null a per-call staging buffer is made and released; a deferred upload needs a caller staging buffer.

Parameters
imageTarget array image.
layerLayer index.
dataSource pixels.
sizeByte count of one layer.
stagingPersistent host-visible staging buffer, or nullptr.
deferredRecord for deferred submission (requires staging).
Returns
True if the upload was recorded or executed.

Definition at line 1006 of file BackendResoureManager.cpp.

1013{
1014 if (!image || !data || layer >= image->get_array_layers()) {
1016 "upload_image_layer: invalid image, data or layer");
1017 return false;
1018 }
1019
1020 const size_t layer_bytes = image->get_size_bytes() / image->get_array_layers();
1021 if (size != layer_bytes) {
1023 "upload_image_layer: {} bytes given, layer needs {}", size, layer_bytes);
1024 return false;
1025 }
1026
1027 if (deferred && !staging) {
1029 "upload_image_layer: a deferred upload needs a caller staging buffer");
1030 return false;
1031 }
1032
1033 std::shared_ptr<Buffers::VKBuffer> local_staging;
1034 if (!staging) {
1035 local_staging = std::make_shared<Buffers::VKBuffer>(
1036 size,
1037 Buffers::VKBuffer::Usage::STAGING,
1039 initialize_buffer(local_staging);
1040 }
1041 const auto& active_staging = staging ? staging : local_staging;
1042
1043 void* mapped = active_staging->get_mapped_ptr();
1044 if (!mapped) {
1046 "upload_image_layer: staging buffer has no mapped pointer");
1047 if (local_staging) {
1048 cleanup_buffer(local_staging);
1049 }
1050 return false;
1051 }
1052
1053 std::memcpy(mapped, data, size);
1054 active_staging->mark_dirty_range(0, size);
1055
1056 vk::MappedMemoryRange range { active_staging->get_buffer_resources().memory, 0, VK_WHOLE_SIZE };
1057 if (auto result = m_context.get_device().flushMappedMemoryRanges(1, &range);
1058 result != vk::Result::eSuccess) {
1060 "upload_image_layer: flush failed: {}", vk::to_string(result));
1061 }
1062
1063 auto record_command = [&](vk::CommandBuffer cmd) {
1064 vk::ImageMemoryBarrier barrier {};
1065 barrier.oldLayout = image->get_current_layout();
1066 barrier.newLayout = vk::ImageLayout::eTransferDstOptimal;
1067 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1068 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1069 barrier.image = image->get_image();
1070 barrier.subresourceRange = {
1071 image->get_aspect_flags(), 0,
1072 image->get_mip_levels(), 0,
1073 image->get_array_layers()
1074 };
1075 barrier.srcAccessMask = vk::AccessFlagBits::eShaderRead;
1076 barrier.dstAccessMask = vk::AccessFlagBits::eTransferWrite;
1077
1078 cmd.pipelineBarrier(
1079 vk::PipelineStageFlagBits::eFragmentShader,
1080 vk::PipelineStageFlagBits::eTransfer,
1081 vk::DependencyFlags {}, {}, {}, barrier);
1082
1083 vk::BufferImageCopy region {};
1084 region.imageSubresource = { image->get_aspect_flags(), 0, layer, 1 };
1085 region.imageOffset = vk::Offset3D { 0, 0, 0 };
1086 region.imageExtent = vk::Extent3D {
1087 image->get_width(),
1088 image->get_height(),
1089 image->get_depth()
1090 };
1091
1092 cmd.copyBufferToImage(
1093 active_staging->get_buffer(),
1094 image->get_image(),
1095 vk::ImageLayout::eTransferDstOptimal,
1096 1, &region);
1097
1098 barrier.oldLayout = vk::ImageLayout::eTransferDstOptimal;
1099 barrier.newLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
1100 barrier.srcAccessMask = vk::AccessFlagBits::eTransferWrite;
1101 barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead;
1102
1103 cmd.pipelineBarrier(
1104 vk::PipelineStageFlagBits::eTransfer,
1105 vk::PipelineStageFlagBits::eFragmentShader,
1106 vk::DependencyFlags {}, {}, {}, barrier);
1107 };
1108
1109 if (deferred) {
1110 record_deferred_commands(record_command);
1111 } else {
1112 execute_immediate_commands(record_command);
1113 }
1114
1115 image->set_current_layout(vk::ImageLayout::eShaderReadOnlyOptimal);
1116
1117 if (local_staging) {
1118 cleanup_buffer(local_staging);
1119 }
1120
1121 return true;
1122}
#define MF_ERROR(comp, ctx,...)
vk::CommandBuffer cmd
IO::ImageData image
Definition Decoder.cpp:47
bool size
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.
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.
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_ERROR, record_deferred_commands(), and size.

Referenced by MayaFlux::Portal::Graphics::TextureLoom::upload_layer().

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