MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
BufferPipelineExecution.cpp
Go to the documentation of this file.
2
5
6namespace MayaFlux::Kriya {
7
9{
11 if (!op.m_condition || !op.m_condition(m_current_cycle)) {
12 return false;
13 }
14 }
15
16 return m_current_cycle % op.m_cycle_interval == 0;
17}
18
20{
22 return op.m_capture.get_cycle_count();
23 }
24 return 1;
25}
26
33
35{
36 for (auto& state : m_data_states) {
37 if (state != DataState::EMPTY) {
38 state = DataState::EMPTY;
39 }
40 }
41
43}
44
45void BufferPipeline::flow_through(size_t index, uint64_t cycle)
46{
47 if (index + 1 >= m_operations.size()) {
48 return;
49 }
50
51 auto& dependent_op = m_operations[index + 1];
52
55 process_operation(dependent_op, cycle);
57 }
58}
59
60std::vector<std::shared_ptr<Vruta::Routine>> BufferPipeline::dispatch_cycle_branches(bool frame_rate)
61{
62 std::vector<std::shared_ptr<Vruta::Routine>> synchronous_tasks;
63
64 for (auto& branch : m_branches) {
65 if (!branch.condition(m_current_cycle)) {
66 continue;
67 }
68
69 std::shared_ptr<Vruta::Routine> task = frame_rate
70 ? std::shared_ptr<Vruta::Routine>(dispatch_frame_branch(branch))
71 : std::shared_ptr<Vruta::Routine>(dispatch_branch_async(branch, m_current_cycle));
72
73 if (branch.synchronous && task) {
74 synchronous_tasks.push_back(task);
75 }
76 }
77
78 return synchronous_tasks;
79}
80
81bool BufferPipeline::any_active(const std::vector<std::shared_ptr<Vruta::Routine>>& tasks)
82{
83 return std::ranges::any_of(tasks, [](const auto& task) {
84 return task && task->is_active();
85 });
86}
87
98
99Vruta::SoundRoutine BufferPipeline::execute_phased(uint64_t max_cycles, uint64_t samples_per_operation)
100{
101 auto& promise = co_await Kriya::GetAudioPromise {};
102
103 if (m_operations.empty()) {
104 co_return;
105 }
106
108 uint32_t cycles_executed = 0;
109
110 while ((max_cycles == 0 || cycles_executed < max_cycles) && (m_continuous_execution || cycles_executed < max_cycles)) {
111
112 if (promise.should_terminate) {
113 break;
114 }
115
116 start_cycle();
118
119 for (size_t i = 0; i < m_operations.size(); ++i) {
120 auto& op = m_operations[i];
121
123 continue;
124 }
125
126 const uint32_t op_iterations = operation_iterations(op);
127
128 for (uint32_t iter = 0; iter < op_iterations; ++iter) {
131 co_await BufferDelay { 1 };
132 } else if (m_capture_timing == Vruta::DelayContext::SAMPLE_BASED && samples_per_operation > 0) {
133 co_await SampleDelay { samples_per_operation };
134 }
135 }
136
138 }
139
140 for (size_t i = 0; i < m_operations.size(); ++i) {
141 auto& op = m_operations[i];
142
144 continue;
145 }
146
148 continue;
149 }
150
151 if (!operation_due(op)) {
152 continue;
153 }
154
157
159 co_await BufferDelay { 1 };
160 } else if (m_process_timing == Vruta::DelayContext::SAMPLE_BASED && samples_per_operation > 0) {
161 co_await SampleDelay { samples_per_operation };
162 }
163 }
164
165 const auto synchronous_tasks = dispatch_cycle_branches(false);
166
167 while (any_active(synchronous_tasks)) {
169 co_await BufferDelay { 1 };
170 } else {
171 co_await SampleDelay { 1 };
172 }
173 }
174
175 finish_cycle();
176
178 cycles_executed++;
179 }
180
181 if (m_on_complete)
183}
184
185Vruta::SoundRoutine BufferPipeline::execute_streaming(uint64_t max_cycles, uint64_t samples_per_operation)
186{
187 auto& promise = co_await Kriya::GetAudioPromise {};
188
189 if (m_operations.empty()) {
190 co_return;
191 }
192
194 uint32_t cycles_executed = 0;
195
196 while ((max_cycles == 0 || cycles_executed < max_cycles) && (m_continuous_execution || cycles_executed < max_cycles)) {
197
198 if (promise.should_terminate) {
199 break;
200 }
201
202 start_cycle();
203
204 for (size_t i = 0; i < m_operations.size(); ++i) {
205 auto& op = m_operations[i];
206
207 if (!operation_due(op)) {
208 continue;
209 }
210
212 continue;
213 }
214
215 const uint32_t op_iterations = operation_iterations(op);
216
217 for (uint32_t iter = 0; iter < op_iterations; ++iter) {
218
221
222 flow_through(i, m_current_cycle + iter);
223
225 co_await BufferDelay { 1 };
226 } else if (samples_per_operation > 0) {
227 co_await SampleDelay { samples_per_operation };
228 }
229 }
230 }
231
233
234 finish_cycle();
235
237 cycles_executed++;
238 }
239
240 if (m_on_complete)
242}
243
244Vruta::SoundRoutine BufferPipeline::execute_parallel(uint64_t max_cycles, uint64_t samples_per_operation)
245{
247 "PARALLEL strategy not yet implemented, using PHASED as fallback");
248 return execute_phased(max_cycles, samples_per_operation);
249}
250
251Vruta::SoundRoutine BufferPipeline::execute_reactive(uint64_t max_cycles, uint64_t samples_per_operation)
252{
254 "REACTIVE strategy not yet implemented, using PHASED as fallback");
255 return execute_phased(max_cycles, samples_per_operation);
256}
257
258Vruta::GraphicsRoutine BufferPipeline::execute_frame_phased(uint64_t max_cycles, uint64_t frames_per_operation)
259{
260 auto& promise = co_await Kriya::GetGraphicsPromise {};
261
262 if (m_operations.empty()) {
263 co_return;
264 }
265
267 uint32_t cycles_executed = 0;
268
269 while ((max_cycles == 0 || cycles_executed < max_cycles) && (m_continuous_execution || cycles_executed < max_cycles)) {
270
271 if (promise.should_terminate) {
272 break;
273 }
274
275 bool waited = false;
276
277 start_cycle();
279
280 for (size_t i = 0; i < m_operations.size(); ++i) {
281 auto& op = m_operations[i];
282
284 continue;
285 }
286
287 const uint32_t op_iterations = operation_iterations(op);
288
289 for (uint32_t iter = 0; iter < op_iterations; ++iter) {
291 waited = true;
292 co_await FrameDelay { .frames_to_wait = 1 };
293 }
294
296 }
297
298 for (size_t i = 0; i < m_operations.size(); ++i) {
299 auto& op = m_operations[i];
300
302 continue;
303 }
304
306 continue;
307 }
308
309 if (!operation_due(op)) {
310 continue;
311 }
312
315
316 if (frames_per_operation > 0) {
317 waited = true;
318 co_await FrameDelay { .frames_to_wait = frames_per_operation };
319 }
320 }
321
322 const auto synchronous_tasks = dispatch_cycle_branches(true);
323
324 while (any_active(synchronous_tasks)) {
325 waited = true;
326 co_await FrameDelay { .frames_to_wait = 1 };
327 }
328
329 finish_cycle();
330
332 cycles_executed++;
333
334 if (!waited) {
335 co_await FrameDelay { .frames_to_wait = 1 };
336 }
337 }
338
339 if (m_on_complete)
341}
342
343Vruta::GraphicsRoutine BufferPipeline::execute_frame_streaming(uint64_t max_cycles, uint64_t frames_per_operation)
344{
345 auto& promise = co_await Kriya::GetGraphicsPromise {};
346
347 if (m_operations.empty()) {
348 co_return;
349 }
350
352 uint32_t cycles_executed = 0;
353
354 while ((max_cycles == 0 || cycles_executed < max_cycles) && (m_continuous_execution || cycles_executed < max_cycles)) {
355
356 if (promise.should_terminate) {
357 break;
358 }
359
360 bool waited = false;
361
362 start_cycle();
363
364 for (size_t i = 0; i < m_operations.size(); ++i) {
365 auto& op = m_operations[i];
366
367 if (!operation_due(op)) {
368 continue;
369 }
370
372 continue;
373 }
374
375 const uint32_t op_iterations = operation_iterations(op);
376 const bool is_capture = op.get_type() == BufferOperation::OpType::CAPTURE;
377
378 for (uint32_t iter = 0; iter < op_iterations; ++iter) {
379
382
383 flow_through(i, m_current_cycle + iter);
384
385 if (is_capture) {
386 waited = true;
387 co_await FrameDelay { .frames_to_wait = 1 };
388 } else if (frames_per_operation > 0) {
389 waited = true;
390 co_await FrameDelay { .frames_to_wait = frames_per_operation };
391 }
392 }
393 }
394
396
397 finish_cycle();
398
400 cycles_executed++;
401
402 if (!waited) {
403 co_await FrameDelay { .frames_to_wait = 1 };
404 }
405 }
406
407 if (m_on_complete)
409}
410
411Vruta::GraphicsRoutine BufferPipeline::execute_frame_internal(uint64_t max_cycles, uint64_t frames_per_operation)
412{
414
415 switch (m_execution_strategy) {
417 return execute_frame_streaming(max_cycles, frames_per_operation);
418
422 "PARALLEL and REACTIVE strategies not yet implemented, using PHASED as fallback");
423 return execute_frame_phased(max_cycles, frames_per_operation);
424
426 default:
427 return execute_frame_phased(max_cycles, frames_per_operation);
428 }
429}
430
431}
#define MF_WARN(comp, ctx,...)
uint32_t index
Definition VKDevice.cpp:122
uint32_t get_cycle_count() const
Definition Capture.hpp:187
std::function< bool(uint32_t)> m_condition
static bool is_capture_phase_operation(const BufferOperation &op)
OpType get_type() const
Getters for internal state (read-only)
@ CONDITION
Conditional operation for branching logic.
@ CAPTURE
Capture data from source buffer using BufferCapture strategy.
static bool is_process_phase_operation(const BufferOperation &op)
Fundamental unit of operation in buffer processing pipelines.
@ READY
Data ready for processing.
Vruta::SoundRoutine execute_reactive(uint64_t max_cycles, uint64_t samples_per_operation)
Vruta::GraphicsRoutine execute_frame_internal(uint64_t max_cycles, uint64_t frames_per_operation)
uint32_t operation_iterations(const BufferOperation &op) const
Vruta::GraphicsRoutine execute_frame_phased(uint64_t max_cycles, uint64_t frames_per_operation)
void process_operation(BufferOperation &op, uint64_t cycle)
void flow_through(size_t index, uint64_t cycle)
std::vector< BranchInfo > m_branches
std::vector< BufferOperation > m_operations
std::vector< DataState > m_data_states
Vruta::SoundRoutine execute_streaming(uint64_t max_cycles, uint64_t samples_per_operation)
Vruta::SoundRoutine execute_parallel(uint64_t max_cycles, uint64_t samples_per_operation)
std::function< void(uint32_t)> m_cycle_end_callback
Vruta::GraphicsRoutine execute_frame_streaming(uint64_t max_cycles, uint64_t frames_per_operation)
static bool any_active(const std::vector< std::shared_ptr< Vruta::Routine > > &tasks)
std::function< void(uint32_t)> m_cycle_start_callback
std::function< void()> m_on_complete
std::shared_ptr< Vruta::GraphicsRoutine > dispatch_frame_branch(BranchInfo &branch)
Vruta::SoundRoutine execute_phased(uint64_t max_cycles, uint64_t samples_per_operation)
bool operation_due(const BufferOperation &op) const
std::shared_ptr< Vruta::SoundRoutine > dispatch_branch_async(BranchInfo &branch, uint64_t cycle)
std::vector< std::shared_ptr< Vruta::Routine > > dispatch_cycle_branches(bool frame_rate)
A C++20 coroutine-based graphics processing task with frame-accurate timing.
Definition Routine.hpp:512
A C++20 coroutine-based audio processing task with sample-accurate timing.
Definition Routine.hpp:327
@ CoroutineScheduling
Coroutine scheduling and temporal coordination (Vruta::TaskScheduler)
@ Kriya
Automatable tasks and fluent scheduling api for Nodes and Buffers.
@ PHASED
PHASED: Traditional phased execution (default)
@ STREAMING
STREAMING: Immediate flow-through execution.
@ PARALLEL
PARALLEL: Concurrent capture with synchronization.
@ REACTIVE
REACTIVE: Data-driven reactive execution.
@ SAMPLE_BASED
Sample-accurate delay (audio domain)
@ BUFFER_BASED
Buffer-cycle delay (audio hardware boundary)
Awaiter for suspending until a buffer cycle boundary.
graphics-domain awaiter for frame-accurate timing delays
Templated awaitable for accessing a coroutine's promise object.
Awaitable object for precise sample-accurate timing delays.