MayaFlux 0.2.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
RootGraphicsBuffer.hpp
Go to the documentation of this file.
1// RootGraphicsBuffer.hpp
2#pragma once
3
6#include "RootBuffer.hpp"
7
8namespace MayaFlux::Buffers {
9
10class BufferProcessingChain;
11
12/**
13 * @class RootGraphicsBuffer
14 * @brief Root container for GPU buffer lifecycle management and batch processing
15 *
16 * RootGraphicsBuffer serves as the organizational hub for graphics buffers in a processing
17 * domain. Unlike RootAudioBuffer which accumulates and mixes sample data, RootGraphicsBuffer
18 * focuses on:
19 * - Managing the lifecycle of VKBuffer instances (GPU resources)
20 * - Coordinating batch processing across multiple GPU buffers
21 * - Tracking active GPU resources for backend queries
22 * - Providing cleanup mechanisms for marked buffers
23 *
24 * Key Differences from RootAudioBuffer:
25 * - No data accumulation or mixing (each buffer is independent)
26 * - No "final output" concept (buffers are consumed by shaders/dynamic rendering)
27 * - Focuses on resource management and batch coordination
28 * - Processing means executing BufferProcessor chains (uploads, compute, etc.)
29 *
30 * Token Compatibility:
31 * - Primary Token: GRAPHICS_BACKEND (frame-rate, GPU, parallel)
32 * - Compatible with GPU_PROCESS tokens for compute operations
33 * - Not compatible with AUDIO_BACKEND tokens (different processing model)
34 */
35
36class MAYAFLUX_API RootGraphicsBuffer : public RootBuffer<VKBuffer> {
37public:
38 /**
39 * @brief Information about a buffer that's ready to render
40 */
42 std::shared_ptr<VKBuffer> buffer;
43 std::shared_ptr<Core::Window> target_window;
46 };
47
48 /**
49 * @brief Creates a new root graphics buffer
50 *
51 * Initializes with GRAPHICS_BACKEND token preference and prepares
52 * for managing GPU buffer resources. No Vulkan resources are created
53 * until child buffers are registered and initialized by the backend.
54 */
56
57 /**
58 * @brief Virtual destructor ensuring proper cleanup
59 *
60 * Cleans up all child buffer references and ensures pending removals
61 * are processed. Actual GPU resource cleanup is handled by the backend
62 * through registered cleanup hooks.
63 */
64 ~RootGraphicsBuffer() override;
65
66 /**
67 * @brief Initializes the root buffer with default processor
68 *
69 * For graphics, this sets up a GraphicsBatchProcessor as the default
70 * processor which handles coordinating child buffer processing.
71 */
72 void initialize();
73
74 /**
75 * @brief Processes this root buffer using default processing
76 *
77 * For graphics root buffers, this:
78 * 1. Processes all child buffers through process_children()
79 * 2. Executes final processor if one is set (typically for debug/profiling)
80 * 3. Handles pending buffer operations
81 */
82 void process_default() override;
83
84 /**
85 * @brief Gets all child buffers managed by this root
86 * @return Constant reference to vector of child buffers
87 */
88 inline const std::vector<std::shared_ptr<VKBuffer>>& get_child_buffers() const
89 {
90 return m_child_buffers;
91 }
92
93 /**
94 * @brief Sets an optional final processor
95 * @param processor Processor to execute after all child buffers are processed
96 *
97 * Unlike audio where final processing is critical (limiting, normalization),
98 * graphics rarely needs final processing. This can be used for:
99 * - Debug visualization passes
100 * - Profiling/timing measurements
101 * - Resource synchronization barriers
102 */
103 void set_final_processor(std::shared_ptr<BufferProcessor> processor);
104
105 /**
106 * @brief Gets the current final processor
107 * @return Shared pointer to final processor or nullptr
108 */
109 std::shared_ptr<BufferProcessor> get_final_processor() const;
110
111 /**
112 * @brief Gets buffers filtered by usage type
113 * @param usage VKBuffer::Usage type to filter by
114 * @return Vector of buffers matching the specified usage
115 *
116 * Useful for backend queries like "get all compute buffers" or
117 * "find all staging buffers that need upload".
118 */
119 std::vector<std::shared_ptr<VKBuffer>> get_buffers_by_usage(VKBuffer::Usage usage) const;
120
121 /**
122 * @brief Removes buffers marked for deletion
123 *
124 * Performs the actual removal of buffers that have been marked with
125 * mark_for_removal(). This is called automatically during process_children()
126 * but can be called manually for immediate cleanup.
127 *
128 * The actual GPU resource cleanup is handled by the backend's cleanup hooks.
129 */
130 void cleanup_marked_buffers();
131
132 /**
133 * @brief Gets the number of child buffers
134 * @return Number of buffers currently managed
135 */
136 size_t get_buffer_count() const { return m_child_buffers.size(); }
137
138 /**
139 * @brief Checks if a specific buffer is registered
140 * @param buffer Buffer to check
141 * @return True if buffer is managed by this root, false otherwise
142 */
143 bool has_buffer(const std::shared_ptr<VKBuffer>& buffer) const;
144
145 /**
146 * @brief Activates/deactivates processing for the current token
147 * @param active Whether this buffer should process when its token is active
148 */
149 inline void set_token_active(bool active) override { m_token_active = active; }
150
151 /**
152 * @brief Checks if the buffer is active for its assigned token
153 * @return True if the buffer will process when its token is processed
154 */
155 inline bool is_token_active() const override { return m_token_active; }
156
157 /**
158 * @brief Get list of buffers ready for rendering
159 * @return Vector of renderable buffers with their associated windows and pipelines
160 *
161 * Populated by GraphicsBatchProcessor during batch processing.
162 * Consumed by PresentProcessor to perform actual rendering.
163 */
164 const std::vector<RenderableBufferInfo>& get_renderable_buffers() const
165 {
166 return m_renderable_buffers;
167 }
168
169 /**
170 * @brief Clear the renderable buffers list
171 *
172 * Called after rendering completes to prepare for next frame.
173 */
175 {
176 m_renderable_buffers.clear();
177 }
178
179private:
181
182 /**
183 * @brief Creates the default graphics batch processor
184 * @return Shared pointer to new GraphicsBatchProcessor
185 */
186 std::shared_ptr<BufferProcessor> create_default_processor();
187
188 /**
189 * @brief Add a buffer to the renderable list
190 *
191 * Called by GraphicsBatchProcessor during batch processing.
192 */
194 {
195 m_renderable_buffers.push_back(info);
196 }
197
198 std::vector<RenderableBufferInfo> m_renderable_buffers;
199
200 /**
201 * @brief Optional final processor (rarely used in graphics)
202 */
203 std::shared_ptr<BufferProcessor> m_final_processor;
204
205 /**
206 * @brief Buffers pending removal (cleaned up in next process cycle)
207 */
208 std::vector<std::shared_ptr<VKBuffer>> m_pending_removal;
209
210 /**
211 * @brief Flag indicating if this buffer is active for token processing
212 */
213 bool m_token_active {};
214};
215
216/**
217 * @class GraphicsBatchProcessor
218 * @brief Default processor for coordinating batch GPU buffer processing
219 *
220 * GraphicsBatchProcessor manages the execution of processing chains across
221 * multiple GPU buffers in a coordinated manner. Unlike ChannelProcessor which
222 * accumulates audio data, GraphicsBatchProcessor focuses on:
223 * - Coordinating buffer uploads (CPU -> GPU)
224 * - Dispatching compute shader operations
225 * - Managing resource transitions and barriers
226 * - Ensuring proper synchronization between operations
227 *
228 * Token Compatibility:
229 * - Primary Token: GRAPHICS_BACKEND (frame-rate, GPU, parallel processing)
230 * - Compatible with GPU_PROCESS tokens for compute operations
231 * - Handles parallel batch operations on GPU resources
232 */
233class MAYAFLUX_API GraphicsBatchProcessor : public BufferProcessor {
234public:
235 /**
236 * @brief Creates a new graphics batch processor
237 * @param root_buffer Shared pointer to the root buffer this processor manages
238 */
239 GraphicsBatchProcessor(std::shared_ptr<Buffer> root_buffer);
240
241 /**
242 * @brief Processes a buffer by coordinating child buffer operations
243 * @param buffer Buffer to process (should be RootGraphicsBuffer)
244 *
245 * This executes the batch processing loop:
246 * 1. Iterates through all child buffers
247 * 2. Executes each buffer's default processor
248 * 3. Runs each buffer's processing chain
249 * 4. Handles synchronization and error cases
250 */
251 void processing_function(const std::shared_ptr<Buffer>& buffer) override;
252
253 /**
254 * @brief Called when processor is attached to a buffer
255 * @param buffer Buffer being attached to
256 *
257 * Validates that the buffer is a RootGraphicsBuffer and ensures
258 * token compatibility for GPU processing.
259 */
260 void on_attach(const std::shared_ptr<Buffer>& buffer) override;
261
262 /**
263 * @brief Checks compatibility with a specific buffer type
264 * @param buffer Buffer to check compatibility with
265 * @return True if compatible (buffer is RootGraphicsBuffer), false otherwise
266 */
267 [[nodiscard]] bool is_compatible_with(const std::shared_ptr<Buffer>& buffer) const override;
268
269private:
270 /**
271 * @brief Shared pointer to the root buffer this processor manages
272 */
273 std::shared_ptr<RootGraphicsBuffer> m_root_buffer;
274};
275
276/**
277 * @class PresentProcessor
278 * @brief Final processor that executes render operations after all buffer processing
279 *
280 * PresentProcessor is designed to be set as the final processor of RootGraphicsBuffer.
281 * It's invoked after all child buffer processing chains have completed, making it
282 * the ideal point to:
283 * - Record render commands using processed GPU buffers
284 * - Coordinate rendering operations across multiple buffers
285 * - Submit command buffers to GPU queues
286 * - Present frames to the swapchain
287 *
288 * Design Philosophy:
289 * - Callback-based for maximum flexibility
290 * - Receives RootGraphicsBuffer with all processed child buffers
291 * - No assumptions about rendering strategy (forward, deferred, etc.)
292 * - Can query buffers by usage type for organized rendering
293 *
294 * Usage Pattern:
295 * ```cpp
296 * auto render_proc = std::make_shared<PresentProcessor>(
297 * [this](RootGraphicsBuffer* root) {
298 * // All buffers processed, ready for rendering
299 * auto vertex_bufs = root->get_buffers_by_usage(VKBuffer::Usage::VERTEX);
300 * auto uniform_bufs = root->get_buffers_by_usage(VKBuffer::Usage::UNIFORM);
301 *
302 * // Record render commands
303 * record_render_pass(vertex_bufs, uniform_bufs);
304 *
305 * // Submit and present
306 * submit_graphics_queue();
307 * present_frame();
308 * }
309 * );
310 *
311 * root_graphics_buffer->set_final_processor(render_proc);
312 * ```
313 *
314 * Token Compatibility:
315 * - Primary Token: GRAPHICS_BACKEND
316 * - Executes at frame rate (after all GPU buffer processing)
317 * - Should NOT perform heavy CPU computations (rendering coordination only)
318 */
319class MAYAFLUX_API PresentProcessor : public BufferProcessor {
320public:
321 /**
322 * @brief Callback signature for render operations
323 * @param root RootGraphicsBuffer with all processed child buffers
324 *
325 * The callback receives the root buffer after all child processing is complete.
326 * Child buffers are accessible via:
327 * - root->get_child_buffers() - all buffers
328 * - root->get_buffers_by_usage(usage) - filtered by usage type
329 */
330 using RenderCallback = std::function<void(const std::shared_ptr<RootGraphicsBuffer>& root)>;
331
332 /**
333 * @brief Creates a render processor with a callback function
334 * @param callback Function to execute for rendering operations
335 *
336 * The callback will be invoked during processing_function() with access
337 * to the RootGraphicsBuffer and all its processed child buffers.
338 */
340
341 /**
342 * @brief Default constructor (no callback set)
343 *
344 * Callback can be set later via set_callback().
345 * Processing will be a no-op until callback is configured.
346 */
348
349 ~PresentProcessor() override = default;
350
351 /**
352 * @brief Executes the render callback
353 * @param buffer Buffer to process (must be RootGraphicsBuffer)
354 *
355 * Validates buffer type and invokes the render callback.
356 * This is the core rendering coordination point - all child buffers
357 * have been processed by the time this executes.
358 */
359 void processing_function(const std::shared_ptr<Buffer>& buffer) override;
360
361 /**
362 * @brief Called when processor is attached to a buffer
363 * @param buffer Buffer being attached to
364 *
365 * Validates that the buffer is a RootGraphicsBuffer and ensures
366 * token compatibility for graphics rendering.
367 */
368 void on_attach(const std::shared_ptr<Buffer>& buffer) override;
369
370 /**
371 * @brief Called when processor is detached from a buffer
372 * @param buffer Buffer being detached from
373 */
374 void on_detach(const std::shared_ptr<Buffer>& buffer) override;
375
376 /**
377 * @brief Checks compatibility with a specific buffer type
378 * @param buffer Buffer to check compatibility with
379 * @return True if buffer is RootGraphicsBuffer, false otherwise
380 */
381 [[nodiscard]] bool is_compatible_with(const std::shared_ptr<Buffer>& buffer) const override;
382
383 /**
384 * @brief Sets or updates the render callback
385 * @param callback New callback function
386 *
387 * Allows runtime reconfiguration of rendering strategy.
388 * Useful for switching between different rendering modes or techniques.
389 */
390 void set_callback(RenderCallback callback);
391
392 /**
393 * @brief Checks if a callback is configured
394 * @return True if callback is set, false otherwise
395 */
396 [[nodiscard]] bool has_callback() const { return static_cast<bool>(m_callback); }
397
398 /**
399 * @brief Clears the current callback
400 *
401 * After clearing, processing will be a no-op until a new callback is set.
402 */
403 void clear_callback() { m_callback = nullptr; }
404
405private:
406 /**
407 * @brief User-provided render callback
408 */
410
411 /**
412 * @brief Reference to root buffer (for validation and callbacks)
413 *
414 * We store a raw pointer to avoid circular references, as the root
415 * buffer owns the shared_ptr to this processor.
416 */
417 std::shared_ptr<RootGraphicsBuffer> m_root_buffer;
418
419 void fallback_renderer(const std::shared_ptr<RootGraphicsBuffer>& root);
420};
421
422} // namespace MayaFlux::Buffers
Central computational transformation interface for continuous buffer processing.
std::shared_ptr< RootGraphicsBuffer > m_root_buffer
Shared pointer to the root buffer this processor manages.
Default processor for coordinating batch GPU buffer processing.
std::function< void(const std::shared_ptr< RootGraphicsBuffer > &root)> RenderCallback
Callback signature for render operations.
RenderCallback m_callback
User-provided render callback.
bool has_callback() const
Checks if a callback is configured.
~PresentProcessor() override=default
void clear_callback()
Clears the current callback.
std::shared_ptr< RootGraphicsBuffer > m_root_buffer
Reference to root buffer (for validation and callbacks)
Final processor that executes render operations after all buffer processing.
std::vector< RenderableBufferInfo > m_renderable_buffers
size_t get_buffer_count() const
Gets the number of child buffers.
const std::vector< RenderableBufferInfo > & get_renderable_buffers() const
Get list of buffers ready for rendering.
const std::vector< std::shared_ptr< VKBuffer > > & get_child_buffers() const
Gets all child buffers managed by this root.
void clear_renderable_buffers()
Clear the renderable buffers list.
void add_renderable_buffer(const RenderableBufferInfo &info)
Add a buffer to the renderable list.
void set_token_active(bool active) override
Activates/deactivates processing for the current token.
bool is_token_active() const override
Checks if the buffer is active for its assigned token.
std::shared_ptr< BufferProcessor > m_final_processor
Optional final processor (rarely used in graphics)
std::vector< std::shared_ptr< VKBuffer > > m_pending_removal
Buffers pending removal (cleaned up in next process cycle)
Root container for GPU buffer lifecycle management and batch processing.
void initialize()
Definition main.cpp:11
uint64_t RenderPipelineID
Definition VKBuffer.hpp:27
uint64_t CommandBufferID
Definition VKBuffer.hpp:28
Information about a buffer that's ready to render.