MayaFlux 0.2.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
TransferProcessor.cpp
Go to the documentation of this file.
2
5
7#include "StagingUtils.hpp"
8
9namespace MayaFlux::Buffers {
10
15
17 const std::shared_ptr<AudioBuffer>& source,
18 const std::shared_ptr<VKBuffer>& target)
20{
21 connect_audio_to_gpu(source, target);
23}
24
26 const std::shared_ptr<AudioBuffer>& audio_buffer,
27 const std::shared_ptr<VKBuffer>& gpu_buffer,
28 TransferDirection direction)
30{
31 m_direction = direction;
32
33 if (direction == TransferDirection::AUDIO_TO_GPU) {
34 connect_audio_to_gpu(audio_buffer, gpu_buffer);
35 } else if (direction == TransferDirection::GPU_TO_AUDIO) {
36 connect_gpu_to_audio(gpu_buffer, audio_buffer);
37 }
38}
39
41 const std::shared_ptr<AudioBuffer>& source,
42 const std::shared_ptr<VKBuffer>& target)
43{
44 if (!source || !target) {
46 "TransferProcessor::connect_audio_to_gpu: null buffer provided");
47 return;
48 }
49
50 m_audio_to_gpu_map[source] = target;
52}
53
55 const std::shared_ptr<VKBuffer>& source,
56 const std::shared_ptr<AudioBuffer>& target)
57{
58 if (!source || !target) {
60 "TransferProcessor::connect_gpu_to_audio: null buffer provided");
61 return;
62 }
63
64 m_gpu_to_audio_map[source] = target;
66}
67
69 const std::shared_ptr<VKBuffer>& target,
70 std::shared_ptr<VKBuffer> staging_buffer)
71{
72 if (!target) {
74 "TransferProcessor::setup_staging: null target provided");
75 return;
76 }
77
78 m_staging_map[target] = std::move(staging_buffer);
79}
80
81bool TransferProcessor::validate_audio_to_gpu(const std::shared_ptr<VKBuffer>& target) const
82{
83 return std::ranges::any_of(m_audio_to_gpu_map,
84 [&target](const auto& pair) { return pair.second == target; });
85}
86
87bool TransferProcessor::validate_gpu_to_audio(const std::shared_ptr<AudioBuffer>& target) const
88{
89 return std::ranges::any_of(m_gpu_to_audio_map,
90 [&target](const auto& pair) { return pair.second == target; });
91}
92
93void TransferProcessor::on_attach(const std::shared_ptr<Buffer>& buffer)
94{
96 if (auto vk_buffer = std::dynamic_pointer_cast<VKBuffer>(buffer)) {
97 if (!validate_audio_to_gpu(vk_buffer)) {
99 "TransferProcessor not configured for the attached VKBuffer instance (audio→gpu).");
100 return;
101 }
102
103 if (!vk_buffer->is_initialized()) {
105 "VKBuffer not initialized - register with BufferManager first.");
106 return;
107 }
108
109 if (!vk_buffer->is_host_visible()) {
110 auto it = m_staging_map.find(vk_buffer);
111 if (it == m_staging_map.end()) {
113 "No staging buffer configured for device-local VKBuffer. Create one for efficient transfers.");
114 }
115 }
116 } else {
118 std::source_location::current(),
119 "TransferProcessor (audio→gpu) requires VKBuffer attachment");
120 }
121
123 if (auto audio_buffer = std::dynamic_pointer_cast<AudioBuffer>(buffer)) {
124 if (!validate_gpu_to_audio(audio_buffer)) {
126 "TransferProcessor not configured for the attached AudioBuffer instance (gpu→audio).");
127 return;
128 }
129 } else {
131 std::source_location::current(),
132 "TransferProcessor (gpu→audio) requires AudioBuffer attachment");
133 }
134 }
135}
136
137void TransferProcessor::on_detach(const std::shared_ptr<Buffer>& buffer)
138{
140 if (auto vk_buffer = std::dynamic_pointer_cast<VKBuffer>(buffer)) {
141 m_staging_map.erase(vk_buffer);
142 for (auto it = m_audio_to_gpu_map.begin(); it != m_audio_to_gpu_map.end();) {
143 if (it->second == vk_buffer) {
144 it = m_audio_to_gpu_map.erase(it);
145 } else {
146 ++it;
147 }
148 }
149 }
151 if (auto audio_buffer = std::dynamic_pointer_cast<AudioBuffer>(buffer)) {
152 for (auto it = m_gpu_to_audio_map.begin(); it != m_gpu_to_audio_map.end();) {
153 if (it->second == audio_buffer) {
154 it = m_gpu_to_audio_map.erase(it);
155 } else {
156 ++it;
157 }
158 }
159 }
160 }
161}
162
163void TransferProcessor::processing_function(const std::shared_ptr<Buffer>& buffer)
164{
166 process_audio_to_gpu(buffer);
168 process_gpu_to_audio(buffer);
169 }
170}
171
172void TransferProcessor::process_audio_to_gpu(const std::shared_ptr<Buffer>& gpu_buffer)
173{
174 auto vk_buffer = std::dynamic_pointer_cast<VKBuffer>(gpu_buffer);
175 if (!vk_buffer) {
177 "TransferProcessor (audio→gpu) requires VKBuffer.");
178 return;
179 }
180
181 auto transfer_it = std::ranges::find_if(m_audio_to_gpu_map,
182 [&vk_buffer](const auto& pair) { return pair.second == vk_buffer; });
183
184 if (transfer_it == m_audio_to_gpu_map.end()) {
186 "No source AudioBuffer configured for this VKBuffer.");
187 return;
188 }
189
190 auto source_audio = transfer_it->first;
191
192 if (vk_buffer->is_host_visible()) {
193 upload_audio_to_gpu(source_audio, vk_buffer, nullptr);
194 } else {
195 auto staging_it = m_staging_map.find(vk_buffer);
196 if (staging_it == m_staging_map.end()) {
198 "No staging buffer configured for device-local VKBuffer.");
199 return;
200 }
201 upload_audio_to_gpu(source_audio, vk_buffer, staging_it->second);
202 }
203}
204
205void TransferProcessor::process_gpu_to_audio(const std::shared_ptr<Buffer>& audio_buffer)
206{
207 auto audio = std::dynamic_pointer_cast<AudioBuffer>(audio_buffer);
208 if (!audio) {
210 "TransferProcessor (gpu→audio) requires AudioBuffer.");
211 return;
212 }
213
214 auto transfer_it = std::ranges::find_if(m_gpu_to_audio_map,
215 [&audio](const auto& pair) { return pair.second == audio; });
216
217 if (transfer_it == m_gpu_to_audio_map.end()) {
219 "No source VKBuffer configured for this AudioBuffer.");
220 return;
221 }
222
223 auto source_gpu = transfer_it->first;
224
225 auto staging_it = m_staging_map.find(source_gpu);
226 std::shared_ptr<VKBuffer> staging = (staging_it != m_staging_map.end()) ? staging_it->second : nullptr;
227
228 download_audio_from_gpu(source_gpu, audio, staging);
229}
230
231} // 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(const std::shared_ptr< Buffer > &buffer) override
The core processing function that must be implemented by derived classes.
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
void on_attach(const std::shared_ptr< Buffer > &buffer) override
Called when this processor is attached to a buffer.
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(const 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.