MayaFlux 1.0.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(const 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(const 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(const 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(const 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 {
160 validate_token(token);
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(const 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(const 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}
std::shared_ptr< NetworkGeometryBuffer > buffer
Advanced pipeline manager for multi-stage buffer transformations with backend optimization.
virtual ProcessingToken get_processing_token() const
Gets the current processing token for this 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 bool is_compatible_with(const std::shared_ptr< Buffer > &) const
Checks if this processor can handle the specified buffer type.
virtual void on_attach(const std::shared_ptr< Buffer > &)
Called when this processor is attached to a buffer.
virtual void on_detach(const std::shared_ptr< Buffer > &)
Called when this processor is detached from a buffer.
virtual void processing_function(const 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.
void validate_token(ProcessingToken token)
Validates that a processing token has a valid, non-conflicting configuration.
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.
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.