MayaFlux 0.1.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
BufferTokenDistributor.cpp
Go to the documentation of this file.
2
6// #include "MayaFlux/Journal/Archivist.hpp"
7
8namespace MayaFlux::Buffers {
9
10// ============================================================================
11// Public API
12// ============================================================================
13
15 const std::shared_ptr<Buffer>& buffer,
16 ProcessingToken requested_token)
17{
18 if (!buffer) {
21 .transfer_processor = nullptr,
22 .transfer_direction = ProcessingToken::AUDIO_BACKEND,
23 .reason = "Null buffer provided"
24 };
25 }
26
27 if (auto audio = std::dynamic_pointer_cast<AudioBuffer>(buffer)) {
28 return decide_audio_buffer(audio, requested_token);
29 }
30
31 if (auto vk = std::dynamic_pointer_cast<VKBuffer>(buffer)) {
32 return decide_vk_buffer(vk, requested_token);
33 }
34
37 .transfer_processor = nullptr,
38 .transfer_direction = ProcessingToken::AUDIO_BACKEND,
39 .reason = "Unknown buffer type"
40 };
41}
42
44 const std::shared_ptr<Buffer>& buffer,
45 ProcessingToken requested_token,
46 const std::shared_ptr<Buffer>& transfer_target,
47 ProcessingToken transfer_target_token)
48{
49 auto source_decision = distribute(buffer, requested_token);
50 if (source_decision.result == DistributionResult::REJECTED) {
51 return source_decision;
52 }
53
54 return decide_transfer(buffer, requested_token, transfer_target, transfer_target_token);
55}
56
57// ============================================================================
58// Helpers: Token Parsing
59// ============================================================================
60
65
70
75
80
81// ============================================================================
82// Validation: Token Validity
83// ============================================================================
84
86{
87 if (has_frame_rate(token)) {
88 return false;
89 }
90
91 return has_cpu(token) || has_gpu(token);
92}
93
98
99// ============================================================================
100// Decision Trees
101// ============================================================================
102
104 const std::shared_ptr<AudioBuffer>& audio,
106{
108 return DistributionDecision {
110 .transfer_processor = nullptr,
111 .transfer_direction = ProcessingToken::AUDIO_BACKEND,
112 .reason = "AudioBuffer requires SAMPLE_RATE token with CPU or GPU device"
113 };
114 }
115
116 // Decision 1: AUDIO_PARALLEL (GPU audio) → INTERNAL_ONLY
118 audio->force_internal_usage(true);
119 return DistributionDecision {
121 .transfer_processor = nullptr,
122 .transfer_direction = ProcessingToken::AUDIO_BACKEND,
123 .reason = "Audio buffer with GPU processing marked internal"
124 };
125 }
126
127 // Decision 2: Normal audio (SAMPLE_RATE + CPU) → DIRECT_ROOT
129 audio->force_internal_usage(false);
130 return DistributionDecision {
132 .transfer_processor = nullptr,
133 .transfer_direction = ProcessingToken::AUDIO_BACKEND,
134 .reason = "Audio buffer registered to root"
135 };
136 }
137
138 return DistributionDecision {
140 .transfer_processor = nullptr,
141 .transfer_direction = ProcessingToken::AUDIO_BACKEND,
142 .reason = "AudioBuffer token combination not handled"
143 };
144}
145
147 const std::shared_ptr<VKBuffer>& vk,
149{
150 if (!is_valid_vk_token(token)) {
151 return DistributionDecision {
153 .transfer_processor = nullptr,
154 .transfer_direction = ProcessingToken::AUDIO_BACKEND,
155 .reason = "VKBuffer requires GPU_PPOCESS token without CPU_PROCESS"
156 };
157 }
158
159 // Decision 1: GRAPHICS_BACKEND or FRAME_RATE GPU → DIRECT_ROOT (graphics domain)
161 return DistributionDecision {
163 .transfer_processor = nullptr,
164 .transfer_direction = ProcessingToken::GRAPHICS_BACKEND,
165 .reason = "GPU buffer registered to graphics root"
166 };
167 }
168
169 // Decision 2: AUDIO_PARALLEL (SAMPLE_RATE + GPU) → TRANSFER_ONLY
171 vk->force_internal_usage(true);
172 return DistributionDecision {
174 .transfer_processor = nullptr,
175 .transfer_direction = ProcessingToken::AUDIO_PARALLEL,
176 .reason = "GPU buffer at audio rate marked internal (awaiting transfer)"
177 };
178 }
179
180 return DistributionDecision {
182 .transfer_processor = nullptr,
183 .transfer_direction = ProcessingToken::AUDIO_BACKEND,
184 .reason = "VKBuffer token combination not handled"
185 };
186}
187
188// ============================================================================
189// Transfer Decision
190// ============================================================================
191
193 const std::shared_ptr<Buffer>& source,
194 ProcessingToken src_token,
195 const std::shared_ptr<Buffer>& target,
196 ProcessingToken tgt_token)
197{
198 if (source == target && src_token == tgt_token) {
199 return false;
200 }
201
202 auto audio_src = std::dynamic_pointer_cast<AudioBuffer>(source);
203 auto audio_tgt = std::dynamic_pointer_cast<AudioBuffer>(target);
204 auto vk_src = std::dynamic_pointer_cast<VKBuffer>(source);
205 auto vk_tgt = std::dynamic_pointer_cast<VKBuffer>(target);
206
207 // Audio (SAMPLE_RATE, CPU) → VK (SAMPLE_RATE or FRAME_RATE, GPU)
208 if (audio_src && vk_tgt) {
209 if (has_sample_rate(src_token) && has_cpu(src_token)) {
210 if (has_gpu(tgt_token)) {
211 return true;
212 }
213 }
214 }
215
216 // VK (any rate, GPU) → Audio (SAMPLE_RATE, CPU)
217 if (vk_src && audio_tgt) {
218 if (has_gpu(src_token)) {
219 if (has_sample_rate(tgt_token) && has_cpu(tgt_token)) {
220 return true;
221 }
222 }
223 }
224
225 // Audio (SAMPLE_RATE, GPU) → Audio (SAMPLE_RATE, CPU)
226 if (audio_src && audio_tgt) {
227 if (has_sample_rate(src_token) && has_gpu(src_token)) {
228 if (has_sample_rate(tgt_token) && has_cpu(tgt_token)) {
229 return true;
230 }
231 }
232 }
233
234 // VK → VK (GPU to GPU, rate-dependent)
235 if (vk_src && vk_tgt) {
236 if (has_gpu(src_token) && has_gpu(tgt_token)) {
237 return true;
238 }
239 }
240
241 return false;
242}
243
245 const std::shared_ptr<Buffer>& source,
246 ProcessingToken src_token,
247 const std::shared_ptr<Buffer>& target,
248 ProcessingToken tgt_token)
249{
250 auto audio_src = std::dynamic_pointer_cast<AudioBuffer>(source);
251 auto audio_tgt = std::dynamic_pointer_cast<AudioBuffer>(target);
252 auto vk_src = std::dynamic_pointer_cast<VKBuffer>(source);
253 auto vk_tgt = std::dynamic_pointer_cast<VKBuffer>(target);
254
255 // Pattern: Audio(SAMPLE_RATE|CPU) → VK(GPU) → Audio(SAMPLE_RATE|CPU)
256 if (audio_src && audio_tgt && has_sample_rate(src_token) && has_gpu(src_token) && has_sample_rate(tgt_token) && has_cpu(tgt_token)) {
257 // This would be Audio→GPU→Audio, which is forbidden
258 // But the distribute() call on each would catch this
259 // Just prevent if someone tries to route them together
260 }
261
262 if (!can_transfer(source, src_token, target, tgt_token)) {
263 return DistributionDecision {
265 .transfer_processor = nullptr,
266 .transfer_direction = ProcessingToken::AUDIO_BACKEND,
267 .reason = "Transfer not supported between these buffer types and tokens"
268 };
269 }
270
271 std::shared_ptr<TransferProcessor> processor;
273
274 if (audio_src && vk_tgt) {
276 processor = std::make_shared<TransferProcessor>(audio_src, vk_tgt, direction);
277 } else if (vk_src && audio_tgt) {
279 processor = std::make_shared<TransferProcessor>(audio_tgt, vk_src, direction);
280 } else if (audio_src && audio_tgt) {
281 direction = TransferDirection::AUDIO_TO_GPU; // Reuse as "copy" semantics
282 processor = std::make_shared<TransferProcessor>();
283 processor->connect_audio_to_gpu(audio_src, nullptr); // Placeholder, will be copy
284 } else if (vk_src && vk_tgt) {
285 direction = TransferDirection::AUDIO_TO_GPU; // Reuse enum, semantically "copy"
286 processor = std::make_shared<TransferProcessor>();
287 }
288
289 if (!processor) {
290 return DistributionDecision {
292 .transfer_processor = nullptr,
293 .transfer_direction = ProcessingToken::AUDIO_BACKEND,
294 .reason = "Failed to create transfer processor"
295 };
296 }
297
298 if (audio_tgt) {
299 audio_tgt->force_internal_usage(false);
300 }
301
302 return DistributionDecision {
304 .transfer_processor = processor,
305 .transfer_direction = tgt_token,
306 .reason = "Transfer processor created"
307 };
308}
309
310} // namespace MayaFlux::Buffers
static MayaFlux::Nodes::ProcessingToken token
Definition Timers.cpp:8
static bool has_frame_rate(ProcessingToken token)
static bool can_transfer(const std::shared_ptr< Buffer > &source, ProcessingToken src_token, const std::shared_ptr< Buffer > &target, ProcessingToken tgt_token)
static bool is_valid_vk_token(ProcessingToken token)
static bool is_valid_audio_token(ProcessingToken token)
static DistributionDecision decide_transfer(const std::shared_ptr< Buffer > &source, ProcessingToken src_token, const std::shared_ptr< Buffer > &target, ProcessingToken tgt_token)
static DistributionDecision distribute(const std::shared_ptr< Buffer > &buffer, ProcessingToken requested_token)
Distribute a buffer based on its type and requested token.
static bool has_gpu(ProcessingToken token)
static DistributionDecision decide_vk_buffer(const std::shared_ptr< VKBuffer > &vk, ProcessingToken token)
static DistributionDecision distribute_with_transfer(const std::shared_ptr< Buffer > &buffer, ProcessingToken requested_token, const std::shared_ptr< Buffer > &transfer_target, ProcessingToken transfer_target_token)
Distribute with optional transfer target (for cross-domain routing)
static DistributionDecision decide_audio_buffer(const std::shared_ptr< AudioBuffer > &audio, ProcessingToken token)
static bool has_cpu(ProcessingToken token)
static bool has_sample_rate(ProcessingToken token)
ProcessingToken
Bitfield enum defining processing characteristics and backend requirements for buffer operations.
@ CPU_PROCESS
Executes processing operations on CPU threads.
@ AUDIO_BACKEND
Standard audio processing backend configuration.
@ GRAPHICS_BACKEND
Standard graphics processing backend configuration.
@ FRAME_RATE
Processes data at video frame rate.
@ GPU_PPOCESS
Executes processing operations on GPU hardware.
@ AUDIO_PARALLEL
High-performance audio processing with GPU acceleration.
TransferDirection
Specifies the direction of data transfer.
Routing decision for a buffer with a given token.