MayaFlux 0.5.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
BufferUploadProcessor.cpp
Go to the documentation of this file.
2
4
7
8#include "StagingUtils.hpp"
9
10namespace MayaFlux::Buffers {
11
16
22
23void BufferUploadProcessor::processing_function(const std::shared_ptr<Buffer>& buffer)
24{
25 auto vk_buffer = std::dynamic_pointer_cast<VKBuffer>(buffer);
26 if (!vk_buffer) {
28 "BufferUploadProcessor requires VKBuffer");
29 return;
30 }
31
32 if (!vk_buffer->is_initialized()) {
34 "VKBuffer not initialized - register with BufferManager first");
35 return;
36 }
37
38 if (m_back_buffers_source_map.contains(buffer)) {
39 upload_back_buffers(vk_buffer);
40 return;
41 }
42
43 auto source_it = m_source_map.find(buffer);
44 if (source_it == m_source_map.end() || !source_it->second) {
46 "BufferUploadProcessor has no source configured for this buffer");
47 return;
48 }
49
50 auto source = source_it->second;
51 auto source_data = std::dynamic_pointer_cast<VKBuffer>(source)->get_data();
52 if (source_data.empty()) {
54 "Source buffer has no data to upload");
55 return;
56 }
57
58 if (vk_buffer->is_host_visible()) {
59 upload_host_visible(vk_buffer, source_data[0]);
60 } else {
61 upload_device_local(vk_buffer, source_data[0]);
62 }
63}
64
65void BufferUploadProcessor::upload_device_local(const std::shared_ptr<VKBuffer>& target, const Kakshya::DataVariant& data)
66{
68 auto staging_buffer = m_staging_buffers[target];
69 Buffers::upload_device_local(target, staging_buffer, data);
70}
71
72void BufferUploadProcessor::ensure_staging_buffer(const std::shared_ptr<VKBuffer>& target)
73{
74 auto it = m_staging_buffers.find(target);
75 if (it != m_staging_buffers.end() && it->second->get_size_bytes() >= target->get_size_bytes() && it->second->is_initialized()) {
76 return;
77 }
78
79 auto staging_buffer = std::make_shared<VKBuffer>(
80 target->get_size_bytes(),
81 VKBuffer::Usage::STAGING,
83
84 if (!m_buffer_service) {
85 error<std::runtime_error>(
88 std::source_location::current(),
89 "No processing context available for staging buffer initialization");
90 }
91
92 if (!staging_buffer->is_initialized()) {
93 try {
94 m_buffer_service->initialize_buffer(staging_buffer);
95 } catch (const std::exception& e) {
96 error_rethrow(
99 std::source_location::current(),
100 "Failed to initialize staging buffer: {}", e.what());
101 }
102 }
103
104 m_staging_buffers[target] = staging_buffer;
105
107 "Created staging buffer: {} bytes", staging_buffer->get_size_bytes());
108}
109
110void BufferUploadProcessor::on_attach(const std::shared_ptr<Buffer>& buffer)
111{
112 if (!is_compatible_with(buffer)) {
113 error<std::runtime_error>(
116 std::source_location::current(),
117 "BufferUploadProcessor can only be attached to VKBuffer");
118 }
119
120 if (!m_buffer_service) {
123 }
124
125 if (!m_buffer_service) {
126 error<std::runtime_error>(
129 std::source_location::current(),
130 "BufferUploadProcessor requires a valid buffer service");
131 }
132
134 "BufferUploadProcessor attached to buffer");
135}
136
137void BufferUploadProcessor::on_detach(const std::shared_ptr<Buffer>& buffer)
138{
139 m_staging_buffers.erase(buffer);
140
142 "BufferUploadProcessor detached from buffer");
143}
144
145bool BufferUploadProcessor::is_compatible_with(const std::shared_ptr<Buffer>& buffer) const
146{
147 return std::dynamic_pointer_cast<VKBuffer>(buffer) != nullptr;
148}
149
150void BufferUploadProcessor::configure_source(const std::shared_ptr<Buffer>& target, std::shared_ptr<Buffer> source)
151{
152 if (!std::dynamic_pointer_cast<VKBuffer>(target)) {
153 error<std::runtime_error>(
156 std::source_location::current(),
157 "Target must be a VKBuffer");
158 }
159
160 m_source_map[target] = std::move(source);
161
163 "Configured upload source for target buffer");
164}
165
167 const std::shared_ptr<Buffer>& target,
168 std::vector<std::shared_ptr<Buffer>> sources)
169{
170 if (!std::dynamic_pointer_cast<VKBuffer>(target)) {
171 error<std::runtime_error>(
174 std::source_location::current(),
175 "Target must be a VKBuffer");
176 }
177
178 m_back_buffers_source_map[target] = std::move(sources);
179
181 "Configured back_buffers upload sources for target buffer");
182}
183
184void BufferUploadProcessor::remove_back_buffers(const std::shared_ptr<Buffer>& target)
185{
186 m_back_buffers_source_map.erase(target);
187}
188
189void BufferUploadProcessor::upload_back_buffers(const std::shared_ptr<VKBuffer>& target)
190{
191 auto it = m_back_buffers_source_map.find(std::static_pointer_cast<Buffer>(target));
192 if (it == m_back_buffers_source_map.end()) {
193 return;
194 }
195
196 auto& sources = it->second;
197 auto& resources = target->get_buffer_resources();
198
199 if (sources.size() != resources.back_buffers.size()) {
201 "upload_back_buffers: {} sources configured, {} entries present",
202 sources.size(), resources.back_buffers.size());
203 return;
204 }
205
206 for (size_t i = 0; i < resources.back_buffers.size(); ++i) {
207 const auto& entry = resources.back_buffers[i];
208
209 if (!entry.mapped_ptr) {
211 "upload_back_buffers: entry {} is not host-visible, unsupported", i);
212 continue;
213 }
214
215 auto source_vk = std::dynamic_pointer_cast<VKBuffer>(sources[i]);
216 if (!source_vk) {
218 "upload_back_buffers: source {} is not a VKBuffer", i);
219 continue;
220 }
221
222 auto source_data = source_vk->get_data();
223 if (source_data.empty()) {
225 "upload_back_buffers: source {} has no data to upload", i);
226 continue;
227 }
228
229 Kakshya::DataAccess accessor(source_data[0], {}, source_vk->get_modality());
230 auto [ptr, bytes, format_hint] = accessor.gpu_buffer();
231 std::memcpy(entry.mapped_ptr, ptr, bytes);
232 }
233}
234
235void BufferUploadProcessor::remove_source(const std::shared_ptr<Buffer>& target)
236{
237 m_source_map.erase(target);
238}
239
240std::shared_ptr<Buffer> BufferUploadProcessor::get_source(const std::shared_ptr<Buffer>& target) const
241{
242 auto it = m_source_map.find(target);
243 return it != m_source_map.end() ? it->second : nullptr;
244}
245
246}
#define MF_INFO(comp, ctx,...)
#define MF_RT_WARN(comp, ctx,...)
#define MF_RT_ERROR(comp, ctx,...)
const uint8_t * ptr
void configure_source(const std::shared_ptr< Buffer > &target, std::shared_ptr< Buffer > source)
Configure source buffer for a specific target.
void on_attach(const std::shared_ptr< Buffer > &buffer) override
Called when this processor is attached to a buffer.
void on_detach(const std::shared_ptr< Buffer > &buffer) override
Called when this processor is detached from a buffer.
void remove_source(const std::shared_ptr< Buffer > &target)
Remove source configuration for a target.
std::unordered_map< std::shared_ptr< Buffer >, std::shared_ptr< Buffer > > m_source_map
Maps target VKBuffer -> source Buffer.
void remove_back_buffers(const std::shared_ptr< Buffer > &target)
Remove back_buffers configuration for a target.
void upload_back_buffers(const std::shared_ptr< VKBuffer > &target)
std::shared_ptr< Buffer > get_source(const std::shared_ptr< Buffer > &target) const
Get configured source for a target.
std::unordered_map< std::shared_ptr< Buffer >, std::vector< std::shared_ptr< Buffer > > > m_back_buffers_source_map
Maps target VKBuffer -> vector of source Buffers for back_buffers.
void upload_device_local(const std::shared_ptr< VKBuffer > &target, const Kakshya::DataVariant &data)
void processing_function(const std::shared_ptr< Buffer > &buffer) override
The core processing function that must be implemented by derived classes.
std::unordered_map< std::shared_ptr< Buffer >, std::shared_ptr< VKBuffer > > m_staging_buffers
Maps target VKBuffer -> staging buffer (for device-local transfers)
void ensure_staging_buffer(const std::shared_ptr< VKBuffer > &target)
bool is_compatible_with(const std::shared_ptr< Buffer > &buffer) const override
Checks if this processor can handle the specified buffer type.
void configure_back_buffers(const std::shared_ptr< Buffer > &target, std::vector< std::shared_ptr< Buffer > > sources)
Configure sources to upload into every entry in a VKBuffer's back_buffers, re-read every processing c...
Registry::Service::BufferService * m_buffer_service
Definition VKBuffer.hpp:667
auto gpu_buffer() const
Get raw buffer info for GPU upload.
Type-erased accessor for NDData with semantic view construction.
Interface * get_service()
Query for a backend service.
static BackendRegistry & instance()
Get the global registry instance.
@ GRAPHICS_BACKEND
Standard graphics processing backend configuration.
void upload_host_visible(const std::shared_ptr< VKBuffer > &target, const Kakshya::DataVariant &data, size_t dst_offset)
Upload data to a host-visible buffer.
void upload_device_local(const std::shared_ptr< VKBuffer > &target, const std::shared_ptr< VKBuffer > &staging_buffer, const Kakshya::DataVariant &data, size_t dst_offset)
Upload data to a device-local buffer using a staging buffer.
@ BufferProcessing
Buffer processing (Buffers::BufferManager, processing chains)
@ Buffers
Buffers, Managers, processors and processing chains.
std::variant< std::vector< double >, std::vector< float >, std::vector< uint8_t >, std::vector< uint16_t >, std::vector< uint32_t >, std::vector< std::complex< float > >, std::vector< std::complex< double > >, std::vector< glm::vec2 >, std::vector< glm::vec3 >, std::vector< glm::vec4 >, std::vector< glm::mat4 > > DataVariant
Multi-type data storage for different precision needs.
Definition NDData.hpp:102
@ UNKNOWN
Unknown or undefined modality.
std::function< void(const std::shared_ptr< void > &)> initialize_buffer
Initialize a buffer object.
Backend buffer management service interface.