MayaFlux 0.5.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
BufferDownloadProcessor.cpp
Go to the documentation of this file.
2
4
7
8#include "StagingUtils.hpp"
9
10namespace MayaFlux::Buffers {
11
16
22
23void BufferDownloadProcessor::processing_function(const std::shared_ptr<Buffer>& buffer)
24{
25 auto vk_buffer = std::dynamic_pointer_cast<VKBuffer>(buffer);
26 if (!vk_buffer) {
28 "BufferDownloadProcessor 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_target_map.contains(buffer)) {
39 download_back_buffers(vk_buffer);
40 return;
41 }
42
43 auto target_it = m_target_map.find(buffer);
44 if (target_it == m_target_map.end() || !target_it->second) {
46 "BufferDownloadProcessor has no target configured for this buffer");
47 return;
48 }
49
50 if (vk_buffer->is_host_visible()) {
51 download_host_visible(vk_buffer);
52 } else {
53 download_device_local(vk_buffer);
54 }
55}
56
57void BufferDownloadProcessor::download_host_visible(const std::shared_ptr<VKBuffer>& source)
58{
59 auto target_it = m_target_map.find(source);
60 if (target_it == m_target_map.end() || !target_it->second) {
61 return;
62 }
63 auto target = target_it->second;
64
65 Buffers::download_host_visible(source, std::dynamic_pointer_cast<VKBuffer>(target));
66}
67
68void BufferDownloadProcessor::download_device_local(const std::shared_ptr<VKBuffer>& source)
69{
70 auto target_it = m_target_map.find(source);
71 if (target_it == m_target_map.end() || !target_it->second) {
72 return;
73 }
74 auto target = target_it->second;
75
77
78 auto staging_buffer = m_staging_buffers[source];
79
80 Buffers::download_device_local(source, std::dynamic_pointer_cast<VKBuffer>(target), staging_buffer);
81}
82
83void BufferDownloadProcessor::ensure_staging_buffer(const std::shared_ptr<VKBuffer>& source)
84{
85 auto it = m_staging_buffers.find(source);
86 if (it != m_staging_buffers.end() && it->second->get_size_bytes() >= source->get_size_bytes() && it->second->is_initialized()) {
87 return;
88 }
89
90 auto staging_buffer = std::make_shared<VKBuffer>(
91 source->get_size_bytes(),
92 VKBuffer::Usage::STAGING,
94
95 if (!m_buffer_service) {
96 error<std::runtime_error>(
99 std::source_location::current(),
100 "No processing context available for staging buffer initialization");
101 }
102
103 if (!staging_buffer->is_initialized()) {
104 try {
105 m_buffer_service->initialize_buffer(staging_buffer);
106 } catch (const std::exception& e) {
107 error_rethrow(
110 std::source_location::current(),
111 "Failed to initialize staging buffer: {}", e.what());
112 }
113 }
114
115 m_staging_buffers[source] = staging_buffer;
116
118 "Created staging buffer for download: {} bytes", staging_buffer->get_size_bytes());
119}
120
121void BufferDownloadProcessor::on_attach(const std::shared_ptr<Buffer>& buffer)
122{
123 if (!is_compatible_with(buffer)) {
124 error<std::runtime_error>(
127 std::source_location::current(),
128 "BufferDownloadProcessor can only be attached to VKBuffer");
129 }
130
131 if (!m_buffer_service) {
134 }
135
136 if (!m_buffer_service) {
137 error<std::runtime_error>(
140 std::source_location::current(),
141 "No processing context available for BufferDownloadProcessor");
142 }
143
145 "BufferDownloadProcessor attached");
146}
147
148void BufferDownloadProcessor::on_detach(const std::shared_ptr<Buffer>& buffer)
149{
150 m_staging_buffers.erase(buffer);
151
153 "BufferDownloadProcessor detached");
154}
155
156bool BufferDownloadProcessor::is_compatible_with(const std::shared_ptr<Buffer>& buffer) const
157{
158 return std::dynamic_pointer_cast<VKBuffer>(buffer) != nullptr;
159}
160
161void BufferDownloadProcessor::configure_target(const std::shared_ptr<Buffer>& source, std::shared_ptr<Buffer> target)
162{
163 if (!std::dynamic_pointer_cast<VKBuffer>(source)) {
164 error<std::runtime_error>(
167 std::source_location::current(),
168 "Source must be a VKBuffer");
169 }
170
171 m_target_map[source] = std::move(target);
172
174 "Configured download target for source buffer");
175}
176
177void BufferDownloadProcessor::remove_target(const std::shared_ptr<Buffer>& source)
178{
179 m_target_map.erase(source);
180}
181
183 const std::shared_ptr<Buffer>& source,
184 std::vector<std::shared_ptr<Buffer>> targets)
185{
186 if (!std::dynamic_pointer_cast<VKBuffer>(source)) {
187 error<std::runtime_error>(
190 std::source_location::current(),
191 "Source must be a VKBuffer");
192 }
193
194 m_back_buffers_target_map[source] = std::move(targets);
195
197 "Configured back_buffers download targets for source buffer");
198}
199
200void BufferDownloadProcessor::remove_back_buffers(const std::shared_ptr<Buffer>& source)
201{
202 m_back_buffers_target_map.erase(source);
203}
204
205void BufferDownloadProcessor::download_back_buffers(const std::shared_ptr<VKBuffer>& source)
206{
207 auto it = m_back_buffers_target_map.find(std::static_pointer_cast<Buffer>(source));
208 if (it == m_back_buffers_target_map.end()) {
209 return;
210 }
211
212 auto& targets = it->second;
213 auto& resources = source->get_buffer_resources();
214
215 if (targets.size() != resources.back_buffers.size()) {
217 "download_back_buffers: {} targets configured, {} entries present",
218 targets.size(), resources.back_buffers.size());
219 return;
220 }
221
222 auto& staging = m_staging_buffers[std::static_pointer_cast<Buffer>(source)];
223
224 for (size_t i = 0; i < resources.back_buffers.size(); ++i) {
225 auto target = std::dynamic_pointer_cast<VKBuffer>(targets[i]);
226 if (!target) {
228 "download_back_buffers: target {} is not a VKBuffer", i);
229 continue;
230 }
231
232 const size_t bytes = target->get_size_bytes();
233 std::vector<uint8_t> raw(bytes);
234 download_back_buffer(resources.back_buffers[i], raw.data(), bytes, staging);
235
236 target->set_data({ raw });
237 }
238}
239
240std::shared_ptr<Buffer> BufferDownloadProcessor::get_target(const std::shared_ptr<Buffer>& source) const
241{
242 auto it = m_target_map.find(source);
243 return it != m_target_map.end() ? it->second : nullptr;
244}
245
246} // namespace MayaFlux::Buffers
#define MF_INFO(comp, ctx,...)
#define MF_RT_ERROR(comp, ctx,...)
std::unordered_map< std::shared_ptr< Buffer >, std::shared_ptr< VKBuffer > > m_staging_buffers
Maps source VKBuffer -> staging buffer (for device-local transfers)
bool is_compatible_with(const std::shared_ptr< Buffer > &buffer) const override
Checks if this processor can handle the specified buffer type.
std::shared_ptr< Buffer > get_target(const std::shared_ptr< Buffer > &source) const
Get configured target for a source.
void download_device_local(const std::shared_ptr< VKBuffer > &source)
void on_attach(const std::shared_ptr< Buffer > &buffer) override
Called when this processor is attached to a buffer.
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< Buffer > > m_target_map
Maps source VKBuffer -> target Buffer.
void on_detach(const std::shared_ptr< Buffer > &buffer) override
Called when this processor is detached from a buffer.
void download_back_buffers(const std::shared_ptr< VKBuffer > &source)
void remove_back_buffers(const std::shared_ptr< Buffer > &source)
Remove back_buffers configuration for a source.
void configure_target(const std::shared_ptr< Buffer > &source, std::shared_ptr< Buffer > target)
Configure target buffer for a specific source.
void download_host_visible(const std::shared_ptr< VKBuffer > &source)
std::unordered_map< std::shared_ptr< Buffer >, std::vector< std::shared_ptr< Buffer > > > m_back_buffers_target_map
Maps source VKBuffer -> vector of target Buffers for back_buffers.
void ensure_staging_buffer(const std::shared_ptr< VKBuffer > &source)
void configure_back_buffers(const std::shared_ptr< Buffer > &source, std::vector< std::shared_ptr< Buffer > > targets)
Configure targets to receive downloads of every entry in a VKBuffer's back_buffers,...
void remove_target(const std::shared_ptr< Buffer > &source)
Remove target configuration for a source.
Registry::Service::BufferService * m_buffer_service
Definition VKBuffer.hpp:667
Interface * get_service()
Query for a backend service.
static BackendRegistry & instance()
Get the global registry instance.
@ GRAPHICS_BACKEND
Standard graphics processing backend configuration.
void download_host_visible(const std::shared_ptr< VKBuffer > &source, const std::shared_ptr< VKBuffer > &target)
Download data from a host-visible buffer.
void download_back_buffer(const VKBufferResources::GenerationSlot &slot, void *data, size_t size, std::shared_ptr< VKBuffer > &staging)
Download a raw back_buffers slot to host memory.
void download_device_local(const std::shared_ptr< VKBuffer > &source, const std::shared_ptr< VKBuffer > &target, const std::shared_ptr< VKBuffer > &staging_buffer)
Download data from a device-local buffer using a staging buffer.
@ BufferProcessing
Buffer processing (Buffers::BufferManager, processing chains)
@ Buffers
Buffers, Managers, processors and processing chains.
@ UNKNOWN
Unknown or undefined modality.
std::function< void(const std::shared_ptr< void > &)> initialize_buffer
Initialize a buffer object.
Backend buffer management service interface.