MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
BufferPipeline.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "BufferOperation.hpp"
5
6#include <map>
7
8namespace MayaFlux::Buffers {
9class DataReadProcessor;
10}
11
12namespace MayaFlux::Kriya {
13
14/**
15 * @class BufferPipeline
16 * @brief Coroutine-based execution engine for composable, multi-strategy buffer processing.
17 *
18 * BufferPipeline provides a flexible framework for orchestrating complex data flow patterns
19 * through declarative operation chains. It supports multiple execution strategies (phased,
20 * streaming, parallel, reactive), sophisticated data accumulation modes, and sample-accurate
21 * timing coordination via the coroutine scheduler.
22 *
23 * **Core Concepts:**
24 * - **Operations**: Composable units (capture, transform, route, modify, fuse) chained via >>
25 * - **Execution Strategies**: PHASED (capture-then-process), STREAMING (immediate flow-through),
26 * PARALLEL (concurrent captures), REACTIVE (data-driven)
27 * - **Capture Modes**: TRANSIENT (single), ACCUMULATE (concatenate), CIRCULAR (rolling buffer),
28 * WINDOWED (overlapping windows), TRIGGERED (conditional)
29 * - **Timing Control**: Buffer-rate synchronization, sample-accurate delays, or immediate execution
30 *
31 * **Simple Capture & Route:**
32 * ```cpp
33 * auto pipeline = BufferPipeline::create(*scheduler, buffer_manager);
34 * *pipeline
35 * >> BufferOperation::capture_from(input_buffer)
36 * .for_cycles(1)
37 * >> BufferOperation::route_to_buffer(output_buffer);
38 *
39 * pipeline->execute_buffer_rate(100); // Run for 100 audio buffer cycles
40 * ```
41 *
42 * **Accumulation & Batch Processing (PHASED strategy):**
43 * ```cpp
44 * auto pipeline = BufferPipeline::create(*scheduler, buffer_manager)
45 * ->with_strategy(ExecutionStrategy::PHASED)
46 * ->capture_timing(Vruta::DelayContext::BUFFER_BASED);
47 *
48 * *pipeline
49 * >> BufferOperation::capture_from(audio_buffer)
50 * .for_cycles(20) // Captures 20 times, concatenates into single buffer
51 * >> BufferOperation::transform([](const auto& data, uint32_t cycle) {
52 * const auto& accumulated = std::get<std::vector<double>>(data);
53 * // Process 20 * buffer_size samples as one batch
54 * return apply_batch_fft(accumulated);
55 * })
56 * >> BufferOperation::route_to_container(output_stream);
57 *
58 * pipeline->execute_buffer_rate();
59 * ```
60 *
61 * **Real-Time Streaming Modification (STREAMING strategy):**
62 * ```cpp
63 * auto pipeline = BufferPipeline::create(*scheduler, buffer_manager)
64 * ->with_strategy(ExecutionStrategy::STREAMING);
65 *
66 * *pipeline
67 * >> BufferOperation::capture_from(audio_buffer).for_cycles(1)
68 * >> BufferOperation::modify_buffer(audio_buffer, [noise](auto buf) {
69 * auto& data = buf->get_data();
70 * for (auto& sample : data) {
71 * sample *= noise->process_sample(); // Apply effect in-place
72 * }
73 * }).as_streaming(); // Processor stays attached across cycles
74 *
75 * pipeline->execute_buffer_rate(); // Runs continuously
76 * ```
77 *
78 * **Circular Buffer for Rolling Analysis:**
79 * ```cpp
80 * *pipeline
81 * >> BufferOperation::capture_from(input_buffer)
82 * .for_cycles(100)
83 * .as_circular(2048) // Maintains last 2048 samples
84 * >> BufferOperation::transform([](const auto& data, uint32_t cycle) {
85 * const auto& history = std::get<std::vector<double>>(data);
86 * return analyze_recent_trends(history); // Always sees last 2048 samples
87 * });
88 * ```
89 *
90 * **Windowed Capture with Overlap:**
91 * ```cpp
92 * *pipeline
93 * >> BufferOperation::capture_from(input_buffer)
94 * .for_cycles(50)
95 * .with_window(1024, 0.5f) // 1024 samples, 50% overlap
96 * >> BufferOperation::transform([](const auto& data, uint32_t cycle) {
97 * const auto& window = std::get<std::vector<double>>(data);
98 * return apply_hann_window_and_fft(window);
99 * });
100 * ```
101 *
102 * **Multi-Source Fusion:**
103 * ```cpp
104 * *pipeline
105 * >> BufferOperation::fuse_data(
106 * {mic_buffer, synth_buffer, file_buffer},
107 * [](std::vector<Kakshya::DataVariant>& sources, uint32_t cycle) {
108 * // Combine three audio sources with custom mixing
109 * return mix_sources(sources, {0.5, 0.3, 0.2});
110 * },
111 * output_buffer);
112 * ```
113 *
114 * **Conditional Branching:**
115 * ```cpp
116 * pipeline->branch_if(
117 * [](uint32_t cycle) { return cycle % 16 == 0; }, // Every 16 cycles
118 * [](BufferPipeline& branch) {
119 * branch >> BufferOperation::dispatch_to([](const auto& data, uint32_t cycle) {
120 * save_analysis_snapshot(data, cycle);
121 * });
122 * },
123 * true // Synchronous - wait for branch to complete
124 * );
125 * ```
126 *
127 * **Per-Iteration Routing (Immediate Routing):**
128 * ```cpp
129 * // ROUTE directly after CAPTURE → routes each iteration immediately
130 * *pipeline
131 * >> BufferOperation::capture_from(input_buffer).for_cycles(20)
132 * >> BufferOperation::route_to_container(stream); // Writes 20 times (streaming output)
133 *
134 * // ROUTE after TRANSFORM → routes accumulated result once
135 * *pipeline
136 * >> BufferOperation::capture_from(input_buffer).for_cycles(20)
137 * >> BufferOperation::transform(process_fn)
138 * >> BufferOperation::route_to_container(stream); // Writes 1 time (batch output)
139 * ```
140 *
141 * **Lifecycle Callbacks:**
142 * ```cpp
143 * pipeline->with_lifecycle(
144 * [](uint32_t cycle) { std::cout << "Cycle " << cycle << " start\n"; },
145 * [](uint32_t cycle) { std::cout << "Cycle " << cycle << " end\n"; }
146 * );
147 * ```
148 *
149 * **Execution Modes:**
150 * - `execute_buffer_rate(N)`: Synchronized to audio buffer boundaries for N cycles
151 * - `execute_continuous()`: Runs indefinitely until stopped
152 * - `execute_for_cycles(N)`: Runs exactly N cycles then stops
153 * - `execute_once()`: Single cycle execution
154 * - `execute_scheduled(N, samples)`: With sample-accurate delays between operations
155 *
156 * **Strategy Selection:**
157 * - **PHASED** (default): Capture phase completes, then process phase runs
158 * - Best for: batch analysis, accumulation, FFT processing
159 * - **STREAMING**: Operations flow through immediately, minimal latency
160 * - Best for: real-time effects, low-latency processing, modify_buffer
161 * - **PARALLEL**: Multiple captures run concurrently (TODO)
162 * - Best for: multi-source synchronized capture
163 * - **REACTIVE**: Data-driven execution when inputs available (TODO)
164 * - Best for: event-driven workflows, complex dependencies
165 *
166 * @see BufferOperation For operation types and configuration
167 * @see BufferCapture For capture modes and data accumulation strategies
168 * @see Vruta::TaskScheduler For coroutine scheduling and timing
169 * @see ExecutionStrategy For execution coordination patterns
170 */
171class MAYAFLUX_API BufferPipeline : public std::enable_shared_from_this<BufferPipeline> {
172public:
173 static std::shared_ptr<BufferPipeline> create(
174 Vruta::TaskScheduler& scheduler,
175 std::shared_ptr<Buffers::BufferManager> buffer_manager = nullptr,
176 std::shared_ptr<IO::IOManager> io_manager = nullptr)
177 {
178 return std::make_shared<BufferPipeline>(scheduler, std::move(buffer_manager), std::move(io_manager));
179 }
180
181 BufferPipeline() = default;
182 explicit BufferPipeline(
183 Vruta::TaskScheduler& scheduler,
184 std::shared_ptr<Buffers::BufferManager> buffer_manager = nullptr,
185 std::shared_ptr<IO::IOManager> io_manager = nullptr);
186
188
189 /**
190 * @brief Chain an operation to the pipeline.
191 * @param operation BufferOperation to add to the processing chain
192 * @return Reference to this pipeline for continued chaining
193 */
195 {
196 m_operations.emplace_back(std::move(operation));
197 return *this;
198 }
199
200 /**
201 * @brief Add conditional branch to the pipeline.
202 * @param condition Function that determines if branch should execute
203 * @param branch_builder Function that configures the branch pipeline
204 * @param synchronous If true, branch executes within main cycle (default: false)
205 * @param samples_per_operation Number of samples per operation in branch (default: 1)
206 * @return Reference to this pipeline for continued chaining
207 */
208 BufferPipeline& branch_if(std::function<bool(uint32_t)> condition,
209 const std::function<void(BufferPipeline&)>& branch_builder,
210 bool synchronous = false, uint64_t samples_per_operation = 1);
211
212 /**
213 * @brief Execute operations in parallel within the current cycle.
214 * @param operations List of operations to execute concurrently
215 * @return Reference to this pipeline for continued chaining
216 */
217 BufferPipeline& parallel(std::initializer_list<BufferOperation> operations);
218
219 /**
220 * @brief Set lifecycle callbacks for cycle management.
221 * @param on_cycle_start Function called at the beginning of each cycle
222 * @param on_cycle_end Function called at the end of each cycle
223 * @return Reference to this pipeline for continued chaining
224 */
225 BufferPipeline& with_lifecycle(
226 std::function<void(uint32_t)> on_cycle_start,
227 std::function<void(uint32_t)> on_cycle_end);
228
229 /**
230 * @brief Set the execution strategy for this pipeline
231 * @param strategy Execution coordination strategy
232 * @return Reference to this pipeline for chaining
233 */
235 {
236 m_execution_strategy = strategy;
237 return *this;
238 }
239
240 /**
241 * @brief Set timing mode for capture phase
242 * @param mode Timing synchronization mode
243 * @return Reference to this pipeline for chaining
244 */
246 {
247 m_capture_timing = mode;
248 return *this;
249 }
250
251 /**
252 * @brief Set timing mode for process phase
253 * @param mode Timing synchronization mode
254 * @return Reference to this pipeline for chaining
255 */
257 {
258 m_process_timing = mode;
259 return *this;
260 }
261
262 /**
263 * @brief Get current execution strategy
264 */
265 inline ExecutionStrategy get_strategy() const { return m_execution_strategy; }
266
267 // Update execute_buffer_rate to use new infrastructure:
268 /**
269 * @brief Execute pipeline synchronized to audio hardware cycle boundaries
270 *
271 * This now respects the configured execution strategy and timing modes.
272 * Default strategy is PHASED with BUFFER_RATE timing.
273 *
274 * @param max_cycles Maximum number of audio cycles to process (0 = infinite)
275 */
276 void execute_buffer_rate(uint64_t max_cycles = 0);
277
278 /**
279 * @brief Execute the pipeline for a single cycle.
280 *
281 * Schedules the pipeline to run once through all operations. The execution
282 * happens asynchronously via the scheduler's coroutine system. The pipeline
283 * must have a scheduler and will be kept alive via shared_ptr until execution
284 * completes.
285 *
286 * @throws std::runtime_error if pipeline has no scheduler
287 *
288 * @note This is asynchronous - the function returns immediately and execution
289 * happens when the scheduler processes the coroutine.
290 */
291 void execute_once();
292
293 /**
294 * @brief Execute the pipeline for a specified number of cycles.
295 * @param cycles Number of processing cycles to execute
296 *
297 * Schedules the pipeline to run for the given number of cycles. Each cycle
298 * processes all operations once. Execution is asynchronous via the scheduler.
299 * The pipeline remains alive until all cycles complete.
300 *
301 * @throws std::runtime_error if pipeline has no scheduler
302 *
303 * @note Execution happens asynchronously - this function returns immediately.
304 */
305 void execute_for_cycles(uint64_t cycles = 0);
306
307 /**
308 * @brief Start continuous execution of the pipeline.
309 *
310 * Schedules the pipeline to run indefinitely until stop_continuous() is called.
311 * The pipeline processes all operations in each cycle and automatically
312 * advances to the next cycle. The pipeline keeps itself alive via shared_ptr
313 * during continuous execution.
314 *
315 * @throws std::runtime_error if pipeline has no scheduler
316 *
317 * @note Execution is asynchronous. Call stop_continuous() to halt execution.
318 * @see stop_continuous()
319 */
320 void execute_continuous();
321
322 /**
323 * @brief Stop continuous execution of the pipeline.
324 *
325 * Signals the pipeline to stop after completing the current cycle. The
326 * pipeline will gracefully terminate its execution loop. Has no effect
327 * if the pipeline is not currently executing continuously.
328 *
329 * @note This only sets a flag - actual termination happens at the end of
330 * the current cycle.
331 */
332 inline void stop_continuous() { m_continuous_execution = false; }
333
334 /**
335 * @brief End a running pipeline now.
336 *
337 * Cancels the pipeline's routine, releases the reference it holds to itself and
338 * fires the on_complete callback once. Nothing runs after the cycle in progress.
339 * Does nothing if the pipeline is not running.
340 */
341 void end();
342
343 /** @brief True from an execute call until the pipeline ends or runs out of cycles. */
344 [[nodiscard]] bool is_running() const;
345
346 /**
347 * @brief Execute pipeline with sample-accurate timing between operations.
348 * @param max_cycles Maximum number of cycles to execute (0 = infinite)
349 * @param samples_per_operation Number of samples to wait between operations (default: 1)
350 *
351 * Schedules pipeline execution with precise timing control. After each operation
352 * within a cycle, the pipeline waits for the specified number of samples before
353 * proceeding. Useful for rate-limiting operations or creating timed sequences.
354 *
355 * @throws std::runtime_error if pipeline has no scheduler
356 *
357 * @note Execution is asynchronous. The pipeline keeps itself alive until completion.
358 */
359 void execute_scheduled(uint64_t max_cycles = 0, uint64_t samples_per_operation = 1);
360
361 /**
362 * @brief Execute pipeline with real-time rate control.
363 * @param max_cycles Maximum number of cycles to execute
364 * @param seconds_per_operation Duration between operations in seconds
365 *
366 * Convenience wrapper around execute_scheduled() that converts time intervals
367 * to sample counts based on the scheduler's sample rate. Enables natural
368 * specification of timing in seconds rather than samples.
369 *
370 * @throws std::runtime_error if pipeline has no scheduler
371 *
372 * Example:
373 * ```cpp
374 * // Execute 10 cycles with 0.5 seconds between operations
375 * pipeline->execute_scheduled_at_rate(10, 0.5);
376 * ```
377 */
378 void execute_scheduled_at_rate(uint32_t max_cycles = 0, double seconds_per_operation = 1);
379
380 /**
381 * @brief Execute the pipeline at graphics frame rate.
382 * @param max_cycles Maximum number of cycles to execute (0 = infinite)
383 * @param frames_per_operation Frames to wait after each processing operation (0 = none)
384 *
385 * Runs the configured strategy on a GraphicsRoutine. Each capture iteration
386 * takes one frame, so a graphics capture armed in one frame resolves in the
387 * next. The capture and process timing modes apply only to buffer and sample
388 * rate execution. A pipeline with no waiting operation still advances one
389 * cycle per frame.
390 *
391 * @throws std::runtime_error if pipeline has no scheduler
392 *
393 * @note Execution is asynchronous. The pipeline keeps itself alive until completion.
394 */
395 void execute_frame_rate(uint64_t max_cycles = 0, uint64_t frames_per_operation = 0);
396
397 /**
398 * @brief Execute pipeline synchronized to audio hardware cycle boundaries
399 *
400 * Creates a coroutine and registers it with the scheduler using the processing hook
401 * for timing synchronization. The pipeline will be added to the scheduler at the
402 * start of each audio cycle, ensuring buffer operations complete before the buffer
403 * manager reads data.
404 *
405 * @param max_cycles Maximum number of audio cycles to process (0 = infinite)
406 */
407 // void execute_buffer_rate(uint32_t max_cycles = 0);
408
409 // State management
410
411 /**
412 * @brief Mark operation data as consumed for cleanup.
413 * @param operation_index Index of the operation in the pipeline
414 *
415 * Manually marks an operation's data state as consumed, allowing it to be
416 * cleaned up in the next cleanup cycle. Useful for manual data lifecycle
417 * management in custom processing scenarios.
418 *
419 * @note Out-of-range indices are silently ignored.
420 */
421 void mark_data_consumed(uint32_t operation_index);
422
423 /**
424 * @brief Check if any operations have pending data ready for processing.
425 * @return true if any operation has data in READY state, false otherwise
426 *
427 * Queries the data states of all operations to determine if there is
428 * unprocessed data available. Useful for synchronization and debugging.
429 */
430 bool has_pending_data() const;
431
432 /**
433 * @brief Get the current cycle number.
434 * @return Current cycle count since pipeline creation or last reset
435 *
436 * Returns the internal cycle counter that increments with each complete
437 * cycle execution. Useful for cycle-dependent logic and debugging.
438 */
439 uint32_t get_current_cycle() const { return m_current_cycle; }
440
441 /**
442 * @brief The dynamic video stream of the first operation that writes one.
443 *
444 * An operation chained with >> is moved into the pipeline, so this is how to
445 * reach the stream that capture_to_stream created, for example to set up
446 * playback with lag_behind_head. Null if no operation has a stream.
447 */
448 [[nodiscard]] std::shared_ptr<Kakshya::DynamicVideoStream> get_graphics_stream() const
449 {
450 for (const auto& op : m_operations) {
451 if (auto stream = op.get_graphics_stream()) {
452 return stream;
453 }
454 }
455 return nullptr;
456 }
457
458 /**
459 * @brief Register a callback fired once when pipeline execution ends.
460 *
461 * Fires when the cycle limit exhausts or stop_continuous() terminates the loop.
462 * Not fired if the pipeline is destroyed mid-execution.
463 *
464 * @param cb Callback with no arguments.
465 * @return Reference to this pipeline for chaining.
466 */
467 BufferPipeline& on_complete(std::function<void()> cb);
468
469private:
470 enum class DataState : uint8_t {
471 EMPTY, ///< No data available
472 READY, ///< Data ready for processing
473 CONSUMED, ///< Data has been processed
474 EXPIRED ///< Data has expired and should be cleaned up
475 };
476
477 struct BranchInfo {
478 std::function<bool(uint32_t)> condition;
479 std::shared_ptr<BufferPipeline> pipeline;
482 };
483
484 std::shared_ptr<BufferPipeline> m_active_self;
485 std::shared_ptr<Vruta::Routine> m_routine;
486 std::shared_ptr<Buffers::BufferManager> m_buffer_manager;
487 std::shared_ptr<IO::IOManager> m_io_manager;
488 Vruta::TaskScheduler* m_scheduler = nullptr;
489
490 std::vector<BufferOperation> m_operations;
491 std::vector<DataState> m_data_states;
492 std::unordered_map<BufferOperation*, Kakshya::DataVariant> m_operation_data;
494 std::shared_ptr<Buffers::VKBuffer> buffer;
495 std::shared_ptr<Buffers::DataReadProcessor> processor;
496 };
497
498 std::map<std::pair<const BufferOperation*, const Buffers::VKBuffer*>, GraphicsReader> m_readers;
499 std::vector<BranchInfo> m_branches;
500 std::vector<std::shared_ptr<Vruta::Routine>> m_branch_tasks;
501 std::function<void(uint32_t)> m_cycle_start_callback;
502 std::function<void(uint32_t)> m_cycle_end_callback;
503 std::function<void()> m_on_complete;
504
505 uint64_t m_current_cycle { 0 };
506 uint64_t m_max_cycles { 0 };
507 bool m_continuous_execution { false };
508 ExecutionStrategy m_execution_strategy { ExecutionStrategy::PHASED };
509 Vruta::DelayContext m_capture_timing { Vruta::DelayContext::BUFFER_BASED };
510 Vruta::DelayContext m_process_timing { Vruta::DelayContext::SAMPLE_BASED };
511
512 void capture_operation(BufferOperation& op, uint64_t cycle);
513 bool route_image(BufferOperation& op);
514 std::optional<Kakshya::DataVariant> read_graphics_buffer(BufferOperation& op, const std::shared_ptr<Buffers::VKBuffer>& buffer);
515 void reset_accumulated_data();
516 bool has_immediate_routing(const BufferOperation& op) const;
517
518 void process_operation(BufferOperation& op, uint64_t cycle);
519 void process_transform(BufferOperation& op, uint64_t cycle);
520 void process_route(BufferOperation& op);
521 void process_load(BufferOperation& op);
522 void process_fuse(BufferOperation& op, uint64_t cycle);
523 void process_dispatch(BufferOperation& op, uint64_t cycle);
524 void process_modify(BufferOperation& op, uint64_t cycle);
525 void prepare_displays();
526 void queue_graphics_write(BufferOperation& op, const std::shared_ptr<Buffers::VKBuffer>& target, const Kakshya::DataVariant& data);
527 std::shared_ptr<Vruta::SoundRoutine> dispatch_branch_async(BranchInfo& branch, uint64_t cycle);
528 std::shared_ptr<Vruta::GraphicsRoutine> dispatch_frame_branch(BranchInfo& branch);
529 std::vector<std::shared_ptr<Vruta::Routine>> dispatch_cycle_branches(bool frame_rate);
530 static bool any_active(const std::vector<std::shared_ptr<Vruta::Routine>>& tasks);
531
532 bool operation_due(const BufferOperation& op) const;
533 uint32_t operation_iterations(const BufferOperation& op) const;
534 void start_cycle();
535 void reset_cycle_state();
536 void flow_through(size_t index, uint64_t cycle);
537 void finish_cycle();
538 void await_timing(Vruta::DelayContext mode, uint64_t units);
539
540 void cleanup_expired_data();
541 void cleanup_completed_branches();
542
543 Vruta::SoundRoutine execute_internal(uint64_t max_cycles, uint64_t samples_per_operation);
544 Vruta::SoundRoutine execute_phased(uint64_t max_cycles, uint64_t samples_per_operation);
545 Vruta::SoundRoutine execute_streaming(uint64_t max_cycles, uint64_t samples_per_operation);
546 Vruta::SoundRoutine execute_parallel(uint64_t max_cycles, uint64_t samples_per_operation);
547 Vruta::SoundRoutine execute_reactive(uint64_t max_cycles, uint64_t samples_per_operation);
548
549 Vruta::GraphicsRoutine execute_frame_internal(uint64_t max_cycles, uint64_t frames_per_operation);
550 Vruta::GraphicsRoutine execute_frame_phased(uint64_t max_cycles, uint64_t frames_per_operation);
551 Vruta::GraphicsRoutine execute_frame_streaming(uint64_t max_cycles, uint64_t frames_per_operation);
552
553 void execute_capture_phase(uint64_t cycle_base);
554 void execute_process_phase(uint64_t cycle);
555};
556
557inline std::shared_ptr<BufferPipeline> operator>>(
558 std::shared_ptr<BufferPipeline> pipeline,
559 BufferOperation&& operation)
560{
561 *pipeline >> std::move(operation);
562 return pipeline;
563}
564
565inline std::shared_ptr<BufferPipeline> operator>>(
566 std::shared_ptr<BufferPipeline> pipeline,
567 BufferOperation& operation) // <-- Accepts lvalue
568{
569 *pipeline >> std::move(operation);
570 return pipeline;
571}
572
573}
Core::GlobalStreamInfo stream
Definition Config.cpp:40
std::shared_ptr< NetworkGeometryBuffer > buffer
uint32_t mode
uint32_t index
Definition VKDevice.cpp:122
Fundamental unit of operation in buffer processing pipelines.
std::unordered_map< BufferOperation *, Kakshya::DataVariant > m_operation_data
std::vector< std::shared_ptr< Vruta::Routine > > m_branch_tasks
BufferPipeline & process_timing(Vruta::DelayContext mode)
Set timing mode for process phase.
std::shared_ptr< IO::IOManager > m_io_manager
BufferPipeline & capture_timing(Vruta::DelayContext mode)
Set timing mode for capture phase.
BufferPipeline & operator>>(BufferOperation &&operation)
Chain an operation to the pipeline.
void stop_continuous()
Stop continuous execution of the pipeline.
BufferPipeline & with_strategy(ExecutionStrategy strategy)
Set the execution strategy for this pipeline.
static std::shared_ptr< BufferPipeline > create(Vruta::TaskScheduler &scheduler, std::shared_ptr< Buffers::BufferManager > buffer_manager=nullptr, std::shared_ptr< IO::IOManager > io_manager=nullptr)
void await_timing(Vruta::DelayContext mode, uint64_t units)
uint32_t get_current_cycle() const
Get the current cycle number.
std::map< std::pair< const BufferOperation *, const Buffers::VKBuffer * >, GraphicsReader > m_readers
std::vector< BranchInfo > m_branches
std::shared_ptr< BufferPipeline > m_active_self
std::vector< BufferOperation > m_operations
std::vector< DataState > m_data_states
std::shared_ptr< Kakshya::DynamicVideoStream > get_graphics_stream() const
The dynamic video stream of the first operation that writes one.
std::function< void(uint32_t)> m_cycle_end_callback
std::shared_ptr< Vruta::Routine > m_routine
std::function< void(uint32_t)> m_cycle_start_callback
std::function< void()> m_on_complete
void execute_capture_phase(uint64_t cycle_base)
std::shared_ptr< Buffers::BufferManager > m_buffer_manager
void execute_process_phase(uint64_t cycle)
ExecutionStrategy get_strategy() const
Get current execution strategy.
Coroutine-based execution engine for composable, multi-strategy buffer processing.
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
Token-based multimodal task scheduling system for unified coroutine processing.
Definition Scheduler.hpp:51
std::variant< std::vector< double >, std::vector< float >, std::vector< uint8_t >, std::vector< uint16_t >, std::vector< uint32_t >, std::vector< std::complex< float > >, std::vector< std::complex< double > >, std::vector< glm::vec2 >, std::vector< glm::vec3 >, std::vector< glm::vec4 >, std::vector< glm::mat4 > > DataVariant
Multi-type data storage for different precision needs.
Definition NDData.hpp:70
ExecutionStrategy
Defines how operations in a pipeline are coordinated and executed.
std::shared_ptr< BufferPipeline > operator>>(std::shared_ptr< BufferPipeline > pipeline, BufferOperation &&operation)
DelayContext
Discriminator for different temporal delay mechanisms.
std::shared_ptr< BufferPipeline > pipeline
std::function< bool(uint32_t)> condition
std::shared_ptr< Buffers::VKBuffer > buffer
std::shared_ptr< Buffers::DataReadProcessor > processor