MayaFlux 0.1.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
TransferProcessor.cpp
Go to the documentation of this file.
2
5#include <algorithm>
6
8#include "StagingUtils.hpp"
9
10namespace MayaFlux::Buffers {
11
16
18 const std::shared_ptr<AudioBuffer>& source,
19 const std::shared_ptr<VKBuffer>& target)
21{
22 connect_audio_to_gpu(source, target);
24}
25
27 const std::shared_ptr<AudioBuffer>& audio_buffer,
28 const std::shared_ptr<VKBuffer>& gpu_buffer,
29 TransferDirection direction)
31{
32 m_direction = direction;
33
34 if (direction == TransferDirection::AUDIO_TO_GPU) {
35 connect_audio_to_gpu(audio_buffer, gpu_buffer);
36 } else if (direction == TransferDirection::GPU_TO_AUDIO) {
37 connect_gpu_to_audio(gpu_buffer, audio_buffer);
38 }
39}
40
42 const std::shared_ptr<AudioBuffer>& source,
43 const std::shared_ptr<VKBuffer>& target)
44{
45 if (!source || !target) {
47 "TransferProcessor::connect_audio_to_gpu: null buffer provided");
48 return;
49 }
50
51 m_audio_to_gpu_map[source] = target;
53}
54
56 const std::shared_ptr<VKBuffer>& source,
57 const std::shared_ptr<AudioBuffer>& target)
58{
59 if (!source || !target) {
61 "TransferProcessor::connect_gpu_to_audio: null buffer provided");
62 return;
63 }
64
65 m_gpu_to_audio_map[source] = target;
67}
68
70 const std::shared_ptr<VKBuffer>& target,
71 std::shared_ptr<VKBuffer> staging_buffer)
72{
73 if (!target) {
75 "TransferProcessor::setup_staging: null target provided");
76 return;
77 }
78
79 m_staging_map[target] = std::move(staging_buffer);
80}
81
82bool TransferProcessor::validate_audio_to_gpu(const std::shared_ptr<VKBuffer>& target) const
83{
84 return std::ranges::any_of(m_audio_to_gpu_map,
85 [&target](const auto& pair) { return pair.second == target; });
86}
87
88bool TransferProcessor::validate_gpu_to_audio(const std::shared_ptr<AudioBuffer>& target) const
89{
90 return std::ranges::any_of(m_gpu_to_audio_map,
91 [&target](const auto& pair) { return pair.second == target; });
92}
93
94void TransferProcessor::on_attach(std::shared_ptr<Buffer> buffer)
95{
97 if (auto vk_buffer = std::dynamic_pointer_cast<VKBuffer>(buffer)) {
98 if (!validate_audio_to_gpu(vk_buffer)) {
100 "TransferProcessor not configured for the attached VKBuffer instance (audio→gpu).");
101 return;
102 }
103
104 if (!vk_buffer->is_initialized()) {
106 "VKBuffer not initialized - register with BufferManager first.");
107 return;
108 }
109
110 if (!vk_buffer->is_host_visible()) {
111 auto it = m_staging_map.find(vk_buffer);
112 if (it == m_staging_map.end()) {
114 "No staging buffer configured for device-local VKBuffer. Create one for efficient transfers.");
115 }
116 }
117 } else {
119 std::source_location::current(),
120 "TransferProcessor (audio→gpu) requires VKBuffer attachment");
121 }
122
124 if (auto audio_buffer = std::dynamic_pointer_cast<AudioBuffer>(buffer)) {
125 if (!validate_gpu_to_audio(audio_buffer)) {
127 "TransferProcessor not configured for the attached AudioBuffer instance (gpu→audio).");
128 return;
129 }
130 } else {
132 std::source_location::current(),
133 "TransferProcessor (gpu→audio) requires AudioBuffer attachment");
134 }
135 }
136}
137
138void TransferProcessor::on_detach(std::shared_ptr<Buffer> buffer)
139{
141 if (auto vk_buffer = std::dynamic_pointer_cast<VKBuffer>(buffer)) {
142 m_staging_map.erase(vk_buffer);
143 for (auto it = m_audio_to_gpu_map.begin(); it != m_audio_to_gpu_map.end();) {
144 if (it->second == vk_buffer) {
145 it = m_audio_to_gpu_map.erase(it);
146 } else {
147 ++it;
148 }
149 }
150 }
152 if (auto audio_buffer = std::dynamic_pointer_cast<AudioBuffer>(buffer)) {
153 for (auto it = m_gpu_to_audio_map.begin(); it != m_gpu_to_audio_map.end();) {
154 if (it->second == audio_buffer) {
155 it = m_gpu_to_audio_map.erase(it);
156 } else {
157 ++it;
158 }
159 }
160 }
161 }
162}
163
164void TransferProcessor::processing_function(std::shared_ptr<Buffer> buffer)
165{
167 process_audio_to_gpu(buffer);
169 process_gpu_to_audio(buffer);
170 }
171}
172
173void TransferProcessor::process_audio_to_gpu(const std::shared_ptr<Buffer>& gpu_buffer)
174{
175 auto vk_buffer = std::dynamic_pointer_cast<VKBuffer>(gpu_buffer);
176 if (!vk_buffer) {
178 "TransferProcessor (audio→gpu) requires VKBuffer.");
179 return;
180 }
181
182 auto transfer_it = std::ranges::find_if(m_audio_to_gpu_map,
183 [&vk_buffer](const auto& pair) { return pair.second == vk_buffer; });
184
185 if (transfer_it == m_audio_to_gpu_map.end()) {
187 "No source AudioBuffer configured for this VKBuffer.");
188 return;
189 }
190
191 auto source_audio = transfer_it->first;
192
193 if (vk_buffer->is_host_visible()) {
194 upload_audio_to_gpu(source_audio, vk_buffer, nullptr);
195 } else {
196 auto staging_it = m_staging_map.find(vk_buffer);
197 if (staging_it == m_staging_map.end()) {
199 "No staging buffer configured for device-local VKBuffer.");
200 return;
201 }
202 upload_audio_to_gpu(source_audio, vk_buffer, staging_it->second);
203 }
204}
205
206void TransferProcessor::process_gpu_to_audio(const std::shared_ptr<Buffer>& audio_buffer)
207{
208 auto audio = std::dynamic_pointer_cast<AudioBuffer>(audio_buffer);
209 if (!audio) {
211 "TransferProcessor (gpu→audio) requires AudioBuffer.");
212 return;
213 }
214
215 auto transfer_it = std::ranges::find_if(m_gpu_to_audio_map,
216 [&audio](const auto& pair) { return pair.second == audio; });
217
218 if (transfer_it == m_gpu_to_audio_map.end()) {
220 "No source VKBuffer configured for this AudioBuffer.");
221 return;
222 }
223
224 auto source_gpu = transfer_it->first;
225
226 auto staging_it = m_staging_map.find(source_gpu);
227 std::shared_ptr<VKBuffer> staging = (staging_it != m_staging_map.end()) ? staging_it->second : nullptr;
228
229 download_audio_from_gpu(source_gpu, audio, staging);
230}
231
232} // namespace MayaFlux::Buffers
#define MF_ERROR(comp, ctx,...)
#define MF_RT_ERROR(comp, ctx,...)
#define MF_WARN(comp, ctx,...)
bool validate_audio_to_gpu(const std::shared_ptr< VKBuffer > &target) const
void processing_function(std::shared_ptr< Buffer > buffer) override
The core processing function that must be implemented by derived classes.
void on_attach(std::shared_ptr< Buffer > buffer) override
Called when this processor is attached to a buffer.
void connect_audio_to_gpu(const std::shared_ptr< AudioBuffer > &source, const std::shared_ptr< VKBuffer > &target)
Configure audio→GPU transfer.
void connect_gpu_to_audio(const std::shared_ptr< VKBuffer > &source, const std::shared_ptr< AudioBuffer > &target)
Configure GPU→audio transfer.
void setup_staging(const std::shared_ptr< VKBuffer > &target, std::shared_ptr< VKBuffer > staging_buffer)
Set up staging buffer for device-local GPU buffer.
std::unordered_map< std::shared_ptr< VKBuffer >, std::shared_ptr< AudioBuffer > > m_gpu_to_audio_map
bool validate_gpu_to_audio(const std::shared_ptr< AudioBuffer > &target) const
void process_gpu_to_audio(const std::shared_ptr< Buffer > &audio_buffer)
std::unordered_map< std::shared_ptr< VKBuffer >, std::shared_ptr< VKBuffer > > m_staging_map
void process_audio_to_gpu(const std::shared_ptr< Buffer > &gpu_buffer)
void on_detach(std::shared_ptr< Buffer > buffer) override
Called when this processor is detached from a buffer.
std::unordered_map< std::shared_ptr< AudioBuffer >, std::shared_ptr< VKBuffer > > m_audio_to_gpu_map
void upload_audio_to_gpu(const std::shared_ptr< AudioBuffer > &audio_buffer, const std::shared_ptr< VKBuffer > &gpu_buffer, const std::shared_ptr< VKBuffer > &staging)
Upload AudioBuffer to GPU (always double precision)
@ GRAPHICS_BACKEND
Standard graphics processing backend configuration.
void download_audio_from_gpu(const std::shared_ptr< VKBuffer > &gpu_buffer, const std::shared_ptr< AudioBuffer > &audio_buffer, const std::shared_ptr< VKBuffer > &staging)
Download GPU buffer to AudioBuffer (expects double precision)
TransferDirection
Specifies the direction of data transfer.
@ BufferProcessing
Buffer processing (Buffers::BufferManager, processing chains)
@ Buffers
Buffers, Managers, processors and processing chains.