MayaFlux 0.1.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
BufferProcessor.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "BufferUtils.hpp"
4
5namespace MayaFlux::Buffers {
6
7class Buffer;
8
9/**
10 * @class BufferProcessor
11 * @brief Central computational transformation interface for continuous buffer processing
12 *
13 * BufferProcessor defines the interface for components that transform data stored in buffer objects
14 * within the continuous processing domain of the MayaFlux engine. This design follows the Strategy
15 * pattern, allowing different algorithmic transformations to be applied to buffers without changing
16 * the underlying buffer implementation, while providing processors with significant agency over
17 * processing backend selection and execution strategies.
18 *
19 * Unlike Kakshya::DataProcessor which operates on-demand for arbitrary data sources, BufferProcessor
20 * is designed for continuous, cycle-based processing within the engine's real-time processing pipeline.
21 * Processors have expanded capabilities including:
22 *
23 * **Backend Influence and Override Capabilities:**
24 * - Processors can influence or override which processing backend a buffer uses
25 * - Support for both sequential (CPU) and parallel (GPU) execution strategies
26 * - Dynamic backend selection based on data characteristics and processing requirements
27 * - Ability to leverage specialized hardware acceleration when available
28 *
29 * **Data Type Agnostic Processing:**
30 * - Can work on any data type supported by the attached buffer (audio, video, texture, etc.)
31 * - Automatic adaptation to buffer-specific data formats and layouts
32 * - Type-safe processing through buffer interface abstraction
33 * - Support for multi-modal data processing within unified pipelines
34 *
35 * **Advanced Processing Capabilities:**
36 * - Mathematical transformations (FFT, convolution, statistical analysis)
37 * - Signal processing algorithms (filtering, modulation, synthesis, effects)
38 * - Data manipulation (normalization, scaling, interpolation, format conversion)
39 * - Cross-domain mappings and transformations between different data types
40 * - Real-time analysis and feature extraction
41 * - Hardware-accelerated compute operations
42 *
43 * The processor system provides a flexible framework for block-based computational operations,
44 * complementing the sample-by-sample processing of the node system while enabling efficient
45 * parallel transformations and backend-specific optimizations. Processors maintain full
46 * compatibility with the buffer architecture while providing the agency to optimize
47 * processing strategies based on runtime conditions and hardware capabilities.
48 */
49class MAYAFLUX_API BufferProcessor {
50public:
52
53 /**
54 * @brief Virtual destructor for proper cleanup of derived classes
55 *
56 * Ensures proper cleanup of processor resources, including any backend-specific
57 * allocations, GPU contexts, or hardware acceleration resources that may have
58 * been acquired during the processor's lifetime.
59 */
60 virtual ~BufferProcessor() = default;
61
62 /**
63 * @brief Applies a computational transformation to the data in the provided buffer
64 * @param buffer Buffer to transform
65 *
66 * This is the main transformation method that must be implemented by all concrete
67 * processor classes. It applies the processor's algorithm to the data in the buffer,
68 * potentially modifying it in-place or generating derived information. The processor
69 * has full agency over how the transformation is executed, including:
70 *
71 * - **Backend Selection**: Choosing between CPU, GPU, or specialized hardware backends
72 * - **Execution Strategy**: Sequential vs parallel processing based on data characteristics
73 * - **Memory Management**: Optimizing data layout and access patterns for performance
74 * - **Resource Utilization**: Leveraging available hardware acceleration when beneficial
75 *
76 * The method works seamlessly with any data type supported by the buffer interface,
77 * automatically adapting to audio samples, video frames, texture data, or other
78 * specialized buffer contents while maintaining type safety through the buffer abstraction.
79 * This method calls the core processing function defined in derived classes, with atomic
80 * thread-safe management of processing state to ensure that concurrent access does
81 * not lead to race conditions or data corruption.
82 */
83 void process(std::shared_ptr<Buffer> buffer);
84
85 /**
86 * @brief The core processing function that must be implemented by derived classes
87 * @param buffer Buffer to process
88 *
89 * This method is where the actual transformation logic is implemented. It should
90 * contain the algorithmic details of how the buffer's data is transformed, analyzed,
91 * or processed. The implementation can utilize any backend capabilities available
92 * to the processor, including:
93 *
94 * - **Parallel Processing**: Using multi-threading or GPU compute for large datasets
95 * - **Data Transformations**: Applying mathematical operations, filters, or effects
96 * - **Feature Extraction**: Analyzing data characteristics for further processing
97 *
98 * Derived classes must override this method to provide specific processing behavior.
99 */
100 virtual void processing_function(std::shared_ptr<Buffer> buffer) = 0;
101
102 /**
103 * @brief Called when this processor is attached to a buffer
104 * @param buffer Buffer this processor is being attached to
105 *
106 * Provides an opportunity for the processor to initialize buffer-specific state,
107 * allocate resources, or perform validation. With expanded processor capabilities,
108 * this method can also:
109 *
110 * - **Analyze Buffer Characteristics**: Examine data type, size, and format requirements
111 * - **Select Optimal Backend**: Choose the most appropriate processing backend for the buffer
112 * - **Initialize Hardware Resources**: Set up GPU contexts, CUDA streams, or other acceleration
113 * - **Configure Processing Parameters**: Adapt algorithm parameters to buffer characteristics
114 * - **Establish Processing Strategy**: Determine whether to use sequential or parallel execution
115 * - **Validate Compatibility**: Ensure the processor can handle the buffer's data type and format
116 *
117 * Default implementation does nothing, but derived classes should override this method
118 * to leverage the full capabilities of the expanded processor architecture.
119 */
120 virtual void on_attach(std::shared_ptr<Buffer>) {};
121
122 /**
123 * @brief Called when this processor is detached from a buffer
124 * @param buffer Buffer this processor is being detached from
125 *
126 * Provides an opportunity for the processor to clean up buffer-specific state or
127 * release resources. With expanded processor capabilities, this method should also:
128 *
129 * - **Release Hardware Resources**: Clean up GPU memory, CUDA contexts, or other acceleration resources
130 * - **Finalize Backend Operations**: Ensure all pending backend operations are completed
131 * - **Reset Processing State**: Clear any buffer-specific optimization parameters or cached data
132 * - **Restore Default Backend**: Return to default processing backend if override was applied
133 * - **Synchronize Operations**: Ensure all parallel processing operations have completed
134 *
135 * Default implementation does nothing, but proper resource management in derived classes
136 * is crucial for optimal performance and preventing resource leaks.
137 */
138 virtual void on_detach(std::shared_ptr<Buffer>) {};
139
140 /**
141 * @brief Gets the preferred processing backend for this processor
142 * @param buffer Buffer that will be processed
143 * @return Preferred backend identifier, or default if no preference
144 *
145 * This method allows processors to influence or override the processing backend
146 * used by the buffer. Processors can analyze the buffer's characteristics and
147 * current system state to recommend the most appropriate backend:
148 *
149 * - **CPU_SEQUENTIAL**: For lightweight operations or when parallel overhead exceeds benefits
150 * - **CPU_PARALLEL**: For CPU-intensive operations that benefit from multi-threading
151 * - **GPU_COMPUTE**: For massively parallel operations suitable for GPU acceleration
152 * - **SPECIALIZED_HARDWARE**: For operations optimized for specific hardware (DSP, FPGA, etc.)
153 *
154 * The buffer management system may use this recommendation to optimize processing
155 * performance, though the final backend selection may depend on system availability
156 * and resource constraints.
157 */
159 {
161 m_processing_token = token;
162 }
163
164 /**
165 * @brief Gets the current processing token for this buffer
166 * @return Current processing domain
167 */
168 virtual ProcessingToken get_processing_token() const { return m_processing_token; }
169
170 /**
171 * @brief Checks if this processor can handle the specified buffer type
172 * @param buffer Buffer to check compatibility with
173 * @return True if the processor can process this buffer type, false otherwise
174 *
175 * This method enables dynamic processor validation and selection based on buffer
176 * characteristics. Processors can examine the buffer's data type, format, size,
177 * and other properties to determine compatibility, enabling robust error handling
178 * and automatic processor selection in complex processing pipelines.
179 */
180 virtual bool is_compatible_with(std::shared_ptr<Buffer>) const { return true; }
181
182protected:
183 ProcessingToken m_processing_token { ProcessingToken::AUDIO_BACKEND };
184
185private:
186 std::atomic<size_t> m_active_processing { 0 };
187
188 /**
189 * @brief Internal processing method for non-owning buffer contexts
190 * @param buffer Buffer to process
191 *
192 * This method is used internally by BufferProcessingChain to process buffers
193 * that are not owned by the chain itself. It ensures that the processor's
194 * processing function is called in a thread-safe manner, managing the
195 * active processing state to prevent concurrent access issues.
196 */
197 void process_non_owning(std::shared_ptr<Buffer> buffer);
198};
199
200/** * @struct ProcessorTokenInfo
201 * @brief Holds information about a processor's compatibility with a buffer's processing token
202 *
203 * This structure encapsulates the relationship between a buffer processor and its processing token,
204 * including whether the processor is compatible with the buffer's preferred processing token,
205 * and how it will be handled based on the token enforcement strategy.
206 */
208 std::shared_ptr<BufferProcessor> processor;
211 bool will_be_skipped; // For OVERRIDE_SKIP strategy
212 bool pending_removal; // For OVERRIDE_REJECT strategy
213};
214
215/** * @struct TokenCompatibilityReport
216 * @brief Holds the results of token compatibility analysis for a buffer processing chain
217 *
218 * This structure provides a comprehensive report on the compatibility of processors within a
219 * buffer processing chain, including the preferred processing token, enforcement strategy,
220 * and detailed information about each processor's compatibility status.
221 */
223 std::shared_ptr<Buffer> buffer;
226 std::vector<ProcessorTokenInfo> processor_infos;
227
228 size_t total_processors() const { return processor_infos.size(); }
230 {
231 return std::count_if(processor_infos.begin(), processor_infos.end(),
232 [](const auto& info) { return info.is_compatible; });
233 }
234 size_t skipped_processors() const
235 {
236 return std::count_if(processor_infos.begin(), processor_infos.end(),
237 [](const auto& info) { return info.will_be_skipped; });
238 }
240 {
241 return std::count_if(processor_infos.begin(), processor_infos.end(),
242 [](const auto& info) { return info.pending_removal; });
243 }
244};
245
246}
static MayaFlux::Nodes::ProcessingToken token
Definition Timers.cpp:8
Advanced pipeline manager for multi-stage buffer transformations with backend optimization.
virtual bool is_compatible_with(std::shared_ptr< Buffer >) const
Checks if this processor can handle the specified buffer type.
virtual ProcessingToken get_processing_token() const
Gets the current processing token for this buffer.
virtual void on_attach(std::shared_ptr< Buffer >)
Called when this processor is attached to a buffer.
virtual void set_processing_token(ProcessingToken token)
Gets the preferred processing backend for this processor.
virtual ~BufferProcessor()=default
Virtual destructor for proper cleanup of derived classes.
virtual void on_detach(std::shared_ptr< Buffer >)
Called when this processor is detached from a buffer.
virtual void processing_function(std::shared_ptr< Buffer > buffer)=0
The core processing function that must be implemented by derived classes.
Central computational transformation interface for continuous buffer processing.
ProcessingToken
Bitfield enum defining processing characteristics and backend requirements for buffer operations.
TokenEnforcementStrategy
Defines how strictly processing token requirements are enforced in buffer processing chains.
void validate_token(ProcessingToken token)
Validates that a processing token has a valid, non-conflicting configuration.
std::shared_ptr< BufferProcessor > processor
Holds information about a processor's compatibility with a buffer's processing token.
std::vector< ProcessorTokenInfo > processor_infos
Holds the results of token compatibility analysis for a buffer processing chain.