MayaFlux 0.3.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
BufferUtils.hpp
Go to the documentation of this file.
1#pragma once
2
5
6namespace MayaFlux::Nodes {
7class Node;
8
9namespace Network {
10 class NodeNetwork;
11}
12}
13
14namespace MayaFlux::Buffers {
15
16/**
17 * @enum TokenEnforcementStrategy
18 * @brief Defines how strictly processing token requirements are enforced in buffer processing chains
19 *
20 * TokenEnforcementStrategy provides different levels of flexibility for handling processor-buffer
21 * compatibility based on processing tokens. This allows the system to balance performance optimization
22 * with operational flexibility depending on the application's requirements.
23 *
24 * The enforcement strategy affects how BufferProcessingChain handles processors with incompatible
25 * tokens, ranging from strict validation to complete flexibility. This enables different operational
26 * modes for development, production, and specialized processing scenarios.
27 */
28enum class TokenEnforcementStrategy : uint8_t {
29 /**
30 * @brief Strictly enforces token assignment with no cross-token sharing
31 *
32 * Processors must exactly match the buffer's processing token requirements.
33 * Any incompatibility results in immediate rejection. This provides maximum
34 * performance optimization by ensuring all processors in a chain can execute
35 * with the same backend configuration, but offers the least flexibility.
36 */
37 STRICT,
38
39 /**
40 * @brief Filters processors through token enumeration, allowing compatible combinations
41 *
42 * Uses the are_tokens_compatible() function to determine if processors can work
43 * together despite different token assignments. This allows some flexibility while
44 * maintaining performance optimization for compatible processor combinations.
45 * Incompatible processors are filtered out rather than rejected outright.
46 */
48
49 /**
50 * @brief Allows token overrides but skips processing for incompatible operations
51 *
52 * Permits processors with different tokens to be added to processing chains,
53 * but skips their execution when the tokens are incompatible. This maintains
54 * chain integrity while allowing dynamic processor management. Useful for
55 * conditional processing scenarios where not all processors need to execute.
56 */
58
59 /**
60 * @brief Allows token overrides but rejects incompatible processors from chains
61 *
62 * Similar to OVERRIDE_SKIP but removes incompatible processors from the chain
63 * entirely rather than skipping them. This provides a middle ground between
64 * flexibility and performance by cleaning up incompatible processors while
65 * allowing initial token mismatches during chain construction.
66 */
68
69 /**
70 * @brief Ignores token assignments completely, allowing any processing combination
71 *
72 * Disables all token validation and compatibility checking. Any processor can
73 * be added to any buffer's processing chain regardless of token compatibility.
74 * This provides maximum flexibility but may result in suboptimal performance
75 * or execution errors. Primarily useful for debugging or specialized scenarios.
76 */
77 IGNORE
78};
79
80/**
81 * @brief Validates that a processing token has a valid, non-conflicting configuration
82 * @param token Processing token to validate
83 * @throws std::invalid_argument if the token contains mutually exclusive flags
84 *
85 * This function ensures that processing tokens contain only compatible flag combinations.
86 * It validates three key mutual exclusions that are fundamental to the processing model:
87 *
88 * **Rate Mutual Exclusion**: SAMPLE_RATE and FRAME_RATE cannot be combined as they
89 * represent fundamentally different temporal processing models that cannot be executed
90 * simultaneously within the same processing context.
91 *
92 * **Device Mutual Exclusion**: CPU_PROCESS and GPU_PROCESS cannot be combined as they
93 * represent different execution environments that require different resource allocation
94 * and execution strategies.
95 *
96 * **Concurrency Mutual Exclusion**: SEQUENTIAL and PARALLEL cannot be combined as they
97 * represent incompatible execution patterns that would create undefined behavior in
98 * processing chains.
99 *
100 * This validation is essential for maintaining system stability and ensuring that
101 * processing tokens represent achievable execution configurations.
102 */
104
105/**
106 * @brief Determines if two processing tokens are compatible for joint execution
107 * @param preferred The preferred processing token configuration
108 * @param current The current processing token configuration being evaluated
109 * @return true if the tokens are compatible, false otherwise
110 *
111 * This function implements sophisticated compatibility logic that goes beyond simple equality
112 * checking to determine if processors with different token requirements can work together
113 * in the same processing pipeline. The compatibility rules are designed to maximize
114 * processing flexibility while maintaining system stability and performance.
115 *
116 * **Rate Compatibility Rules:**
117 * - FRAME_RATE processors require FRAME_RATE execution contexts (strict requirement)
118 * - SAMPLE_RATE processors can adapt to FRAME_RATE contexts (flexible upward compatibility)
119 * - Same-rate combinations are always compatible
120 *
121 * **Device Compatibility Rules:**
122 * - SAMPLE_RATE processing cannot execute on GPU hardware (hardware limitation)
123 * - GPU-preferred processors cannot fall back to CPU execution (performance requirement)
124 * - CPU-preferred processors can use GPU for FRAME_RATE processing only
125 *
126 * **Concurrency Compatibility Rules:**
127 * - Sequential/Parallel differences are acceptable if rate requirements align
128 * - Mismatched concurrency with incompatible rates is rejected
129 * - Same concurrency patterns are always compatible
130 *
131 * This flexibility enables the system to optimize processing chains by allowing compatible
132 * processors to share execution contexts while preventing configurations that would result
133 * in poor performance or execution failures.
134 */
136
137/**
138 * @brief Gets the optimal processing token for a given buffer type and system configuration
139 * @param buffer_type Type identifier for the buffer (e.g., "audio", "video", "texture")
140 * @param system_capabilities Available system capabilities (GPU, multi-core CPU, etc.)
141 * @return Recommended processing token for optimal performance
142 *
143 * This function analyzes buffer characteristics and system capabilities to recommend
144 * the most appropriate processing token configuration. It considers factors like:
145 * - Buffer data type and size characteristics
146 * - Available hardware acceleration
147 * - System performance characteristics
148 * - Current system load and resource availability
149 *
150 * The recommendations help achieve optimal performance by matching processing
151 * requirements with available system capabilities.
152 */
153ProcessingToken get_optimal_token(const std::string& buffer_type, uint32_t system_capabilities);
154
155constexpr int MAX_SPINS = 1000;
156
157/**
158 * @brief Wait for an active snapshot context to complete using exponential backoff
159 * @return true if completed, false if timeout
160 */
162 const std::shared_ptr<Nodes::Node>& node,
163 uint64_t active_context_id,
164 int max_spins = MAX_SPINS);
165
166/**
167 * @brief Extract a single sample from a node with proper snapshot management
168 * @return Extracted sample value
169 */
170double extract_single_sample(const std::shared_ptr<Nodes::Node>& node);
171
172/**
173 * @brief Extract multiple samples from a node into a vector
174 */
175std::vector<double> extract_multiple_samples(
176 const std::shared_ptr<Nodes::Node>& node,
177 size_t num_samples);
178
179/**
180 * @brief Apply node output to an existing buffer with mixing
181 */
183 const std::shared_ptr<Nodes::Node>& node,
184 std::span<double> buffer,
185 double mix = 1.0);
186
187/**
188 * @struct NetworkGpuData
189 * @brief Result of extracting GPU-ready data from a NodeNetwork operator.
190 */
192 std::span<const uint8_t> vertex_data; ///< Raw bytes ready for GPU upload
193 size_t vertex_count {}; ///< Number of vertices
194 std::optional<Kakshya::VertexLayout> layout; ///< Vertex layout, if available
195};
196
197/**
198 * @brief Extract GPU geometry data from a NodeNetwork via its GraphicsOperator.
199 *
200 * Returns empty NetworkGpuData if the network has no operator, the operator
201 * is not a GraphicsOperator, or the operator has no vertex data this frame.
202 * Logs at TRACE level for empty/missing data, WARN for operator type mismatch.
203 *
204 * @param network Network to extract from
205 * @param name Logical name used in log messages
206 * @return Populated NetworkGpuData, or empty if not available
207 */
209 const std::shared_ptr<Nodes::Network::NodeNetwork>& network,
210 std::string_view name);
211
212/**
213 * @brief Extract audio buffer data from a NodeNetwork.
214 *
215 * Returns empty span if the network has no audio buffer this cycle.
216 * Intended for networks using OutputMode::AUDIO_SINK.
217 *
218 * @param network Network to extract from
219 * @param name Logical name used in log messages
220 * @return Span of double samples, or empty
221 */
222MAYAFLUX_API std::span<const double> extract_network_audio_data(
223 const std::shared_ptr<Nodes::Network::NodeNetwork>& network,
224 std::string_view name);
225
226} // namespace MayaFlux::Buffers
227
228namespace std {
229template <>
230struct hash<std::pair<MayaFlux::Buffers::ProcessingToken, MayaFlux::Buffers::ProcessingToken>> {
231 size_t operator()(const std::pair<MayaFlux::Buffers::ProcessingToken, MayaFlux::Buffers::ProcessingToken>& pair) const
232 {
233 return hash<uint32_t>()(static_cast<uint32_t>(pair.first)) ^ (hash<uint32_t>()(static_cast<uint32_t>(pair.second)) << 1);
234 }
235};
236}
constexpr int MAX_SPINS
std::vector< double > extract_multiple_samples(const std::shared_ptr< Nodes::Node > &node, size_t num_samples)
Extract multiple samples from a node into a vector.
bool are_tokens_compatible(ProcessingToken preferred, ProcessingToken current)
Determines if two processing tokens are compatible for joint execution.
ProcessingToken
Bitfield enum defining processing characteristics and backend requirements for buffer operations.
void validate_token(ProcessingToken token)
Validates that a processing token has a valid, non-conflicting configuration.
double extract_single_sample(const std::shared_ptr< Nodes::Node > &node)
Extract a single sample from a node with proper snapshot management.
ProcessingToken get_optimal_token(const std::string &buffer_type, uint32_t system_capabilities)
Gets the optimal processing token for a given buffer type and system configuration.
void update_buffer_with_node_data(const std::shared_ptr< Nodes::Node > &node, std::span< double > buffer, double mix)
Apply node output to an existing buffer with mixing.
NetworkGpuData extract_network_gpu_data(const std::shared_ptr< Nodes::Network::NodeNetwork > &network, std::string_view name)
Extract GPU geometry data from a NodeNetwork via its GraphicsOperator.
std::span< const double > extract_network_audio_data(const std::shared_ptr< Nodes::Network::NodeNetwork > &network, std::string_view name)
Extract audio buffer data from a NodeNetwork.
bool wait_for_snapshot_completion(const std::shared_ptr< Nodes::Node > &node, uint64_t active_context_id, int max_spins)
Wait for an active snapshot context to complete using exponential backoff.
TokenEnforcementStrategy
Defines how strictly processing token requirements are enforced in buffer processing chains.
@ OVERRIDE_SKIP
Allows token overrides but skips processing for incompatible operations.
@ STRICT
Strictly enforces token assignment with no cross-token sharing.
@ OVERRIDE_REJECT
Allows token overrides but rejects incompatible processors from chains.
@ FILTERED
Filters processors through token enumeration, allowing compatible combinations.
@ IGNORE
Ignores token assignments completely, allowing any processing combination.
Contains the node-based computational processing system components.
Definition Chronie.hpp:11
std::vector< double > mix(const std::vector< std::vector< double > > &streams)
Mix multiple data streams with equal weighting.
Definition Yantra.cpp:1021
std::span< const uint8_t > vertex_data
Raw bytes ready for GPU upload.
std::optional< Kakshya::VertexLayout > layout
Vertex layout, if available.
size_t vertex_count
Number of vertices.
Result of extracting GPU-ready data from a NodeNetwork operator.
size_t operator()(const std::pair< MayaFlux::Buffers::ProcessingToken, MayaFlux::Buffers::ProcessingToken > &pair) const