MayaFlux 0.1.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
RenderFlow.hpp
Go to the documentation of this file.
1#pragma once
2
4
5#include "ShaderFoundry.hpp"
6
8struct DisplayService;
9}
10
11namespace MayaFlux::Core {
12class VKGraphicsPipeline;
13class VKRenderPass;
14class VKFramebuffer;
15class Window;
16struct VertexBinding;
17struct VertexAttribute;
18}
19
20namespace MayaFlux::Buffers {
21class RootGraphicsBuffer;
22class VKBuffer;
23}
24
26
27using RenderPipelineID = uint64_t;
28using RenderPassID = uint64_t;
29using FramebufferID = uint64_t;
30
34
35/**
36 * @struct RasterizationConfig
37 * @brief Rasterization state configuration
38 */
49
50/**
51 * @struct DepthStencilConfig
52 * @brief Depth and stencil test configuration
53 */
62
63/**
64 * @struct BlendAttachmentConfig
65 * @brief Per-attachment blend configuration
66 */
90
91/**
92 * @struct RenderPipelineConfig
93 * @brief Complete render pipeline configuration
94 */
96 // Shader stages
102
103 // Vertex input
104 std::vector<Core::VertexBinding> vertex_bindings;
105 std::vector<Core::VertexAttribute> vertex_attributes;
106
107 // Input assembly
109
110 // Optional semantic vertex layout
111 std::optional<Kakshya::VertexLayout> semantic_vertex_layout;
112
113 // Use reflection to auto-configure from vertex shader
115
116 // Rasterization
118
119 // Depth/stencil
121
122 // Blend
123 std::vector<BlendAttachmentConfig> blend_attachments;
124
125 // Descriptor sets (similar to compute)
126 std::vector<std::vector<DescriptorBindingConfig>> descriptor_sets;
127
128 // Push constants
130
131 // Render pass compatibility
133 uint32_t subpass = 0;
134
136};
137
138/**
139 * @struct RenderPassAttachment
140 * @brief Render pass attachment configuration
141 */
143 vk::Format format = vk::Format::eB8G8R8A8Unorm;
144 vk::SampleCountFlagBits samples = vk::SampleCountFlagBits::e1;
145 vk::AttachmentLoadOp load_op = vk::AttachmentLoadOp::eClear;
146 vk::AttachmentStoreOp store_op = vk::AttachmentStoreOp::eStore;
147 vk::ImageLayout initial_layout = vk::ImageLayout::eUndefined;
148 vk::ImageLayout final_layout = vk::ImageLayout::ePresentSrcKHR;
149
151};
152
153/**
154 * @class RenderFlow
155 * @brief Graphics pipeline and render pass orchestration
156 *
157 * RenderFlow is the rendering counterpart to ComputePress.
158 * It manages graphics pipelines, render passes, and draw command recording.
159 *
160 * Responsibilities:
161 * - Create graphics pipelines
162 * - Create render passes
163 * - Record render commands
164 * - Manage rendering state
165 * - Coordinate with ShaderFoundry for resources
166 *
167 * Design Philosophy (parallel to ComputePress):
168 * - Uses ShaderFoundry for low-level resources
169 * - Provides high-level rendering API
170 * - Backend-agnostic interface
171 * - Integrates with RootGraphicsBuffer
172 *
173 * Usage Pattern:
174 * ```cpp
175 * auto& flow = Portal::Graphics::get_render_flow();
176 *
177 * // Create pipeline
178 * RenderPipelineConfig config;
179 * config.vertex_shader = vertex_id;
180 * config.fragment_shader = fragment_id;
181 * config.vertex_bindings = {{0, sizeof(Vertex)}};
182 * config.vertex_attributes = {{0, 0, vk::Format::eR32G32B32Sfloat, 0}};
183 * auto pipeline_id = flow.create_pipeline(config);
184 *
185 * // In RenderProcessor callback:
186 * auto cmd_id = foundry.begin_commands(CommandBufferType::GRAPHICS);
187 * flow.begin_render_pass(cmd_id, render_pass_id, framebuffer_id);
188 * flow.bind_pipeline(cmd_id, pipeline_id);
189 * flow.bind_vertex_buffers(cmd_id, {vertex_buffer});
190 * flow.draw(cmd_id, vertex_count);
191 * flow.end_render_pass(cmd_id);
192 * foundry.submit_and_present(cmd_id);
193 * ```
194 */
195class MAYAFLUX_API RenderFlow {
196public:
198 {
199 static RenderFlow flow;
200 return flow;
201 }
202
203 RenderFlow(const RenderFlow&) = delete;
204 RenderFlow& operator=(const RenderFlow&) = delete;
205 RenderFlow(RenderFlow&&) noexcept = delete;
206 RenderFlow& operator=(RenderFlow&&) noexcept = delete;
207
208 bool initialize();
209 void shutdown();
210
211 [[nodiscard]] bool is_initialized() const { return m_shader_foundry != nullptr; }
212
213 //==========================================================================
214 // Render Pass Management
215 //==========================================================================
216
217 /**
218 * @brief Create a render pass
219 * @param attachments Attachment descriptions
220 * @return Render pass ID
221 */
222 RenderPassID create_render_pass(
223 const std::vector<RenderPassAttachment>& attachments);
224
225 /**
226 * @brief Create a simple single-color render pass
227 * @param format Color attachment format
228 * @param load_clear Whether to clear on load
229 * @return Render pass ID
230 */
231 RenderPassID create_simple_render_pass(
232 vk::Format format = vk::Format::eB8G8R8A8Unorm,
233 bool load_clear = true);
234
235 void destroy_render_pass(RenderPassID render_pass_id);
236
237 //==========================================================================
238 // Pipeline Creation
239 //==========================================================================
240
241 /**
242 * @brief Create graphics pipeline with full configuration
243 * @param config Complete pipeline configuration
244 * @return Pipeline ID or INVALID_RENDER_PIPELINE on error
245 */
246 RenderPipelineID create_pipeline(const RenderPipelineConfig& config);
247
248 /**
249 * @brief Create simple graphics pipeline (auto-configure most settings)
250 * @param vertex_shader Vertex shader ID
251 * @param fragment_shader Fragment shader ID
252 * @param render_pass Render pass ID
253 * @return Pipeline ID or INVALID_RENDER_PIPELINE on error
254 */
255 RenderPipelineID create_simple_pipeline(
256 ShaderID vertex_shader,
257 ShaderID fragment_shader,
258 RenderPassID render_pass);
259
260 void destroy_pipeline(RenderPipelineID pipeline_id);
261
262 //==========================================================================
263 // Command Recording
264 //==========================================================================
265
266 /**
267 * @brief Begin render pass
268 * @param cmd_id Command buffer ID
269 * @param window Target window for rendering
270 * @param clear_color Clear color (if load op is clear)
271 */
272 void begin_render_pass(
273 CommandBufferID cmd_id,
274 const std::shared_ptr<Core::Window>& window,
275 const std::array<float, 4>& clear_color = { 0.0F, 0.0F, 0.0F, 1.0F });
276
277 /**
278 * @brief End current render pass
279 * @param cmd_id Command buffer ID
280 */
281 void end_render_pass(CommandBufferID cmd_id);
282
283 /**
284 * @brief Bind graphics pipeline
285 * @param cmd_id Command buffer ID
286 * @param pipeline Pipeline ID
287 */
288 void bind_pipeline(CommandBufferID cmd_id, RenderPipelineID pipeline);
289
290 /**
291 * @brief Bind vertex buffers
292 * @param cmd_id Command buffer ID
293 * @param buffers Vertex buffers to bind
294 * @param first_binding First binding index
295 */
296 void bind_vertex_buffers(
297 CommandBufferID cmd_id,
298 const std::vector<std::shared_ptr<Buffers::VKBuffer>>& buffers,
299 uint32_t first_binding = 0);
300
301 /**
302 * @brief Bind index buffer
303 * @param cmd_id Command buffer ID
304 * @param buffer Index buffer
305 * @param index_type Index type (16-bit or 32-bit)
306 */
307 void bind_index_buffer(
308 CommandBufferID cmd_id,
309 const std::shared_ptr<Buffers::VKBuffer>& buffer,
310 vk::IndexType index_type = vk::IndexType::eUint32);
311
312 /**
313 * @brief Bind descriptor sets
314 * @param cmd_id Command buffer ID
315 * @param pipeline Pipeline ID
316 * @param descriptor_sets Descriptor set IDs
317 */
318 void bind_descriptor_sets(
319 CommandBufferID cmd_id,
320 RenderPipelineID pipeline,
321 const std::vector<DescriptorSetID>& descriptor_sets);
322
323 /**
324 * @brief Push constants
325 * @param cmd_id Command buffer ID
326 * @param pipeline Pipeline ID
327 * @param data Constant data
328 * @param size Data size in bytes
329 */
330 void push_constants(
331 CommandBufferID cmd_id,
332 RenderPipelineID pipeline,
333 const void* data,
334 size_t size);
335
336 /**
337 * @brief Draw command
338 * @param cmd_id Command buffer ID
339 * @param vertex_count Number of vertices
340 * @param instance_count Number of instances (default: 1)
341 * @param first_vertex First vertex index
342 * @param first_instance First instance index
343 */
344 void draw(
345 CommandBufferID cmd_id,
346 uint32_t vertex_count,
347 uint32_t instance_count = 1,
348 uint32_t first_vertex = 0,
349 uint32_t first_instance = 0);
350
351 /**
352 * @brief Indexed draw command
353 * @param cmd_id Command buffer ID
354 * @param index_count Number of indices
355 * @param instance_count Number of instances (default: 1)
356 * @param first_index First index
357 * @param vertex_offset Vertex offset
358 * @param first_instance First instance index
359 */
360 void draw_indexed(
361 CommandBufferID cmd_id,
362 uint32_t index_count,
363 uint32_t instance_count = 1,
364 uint32_t first_index = 0,
365 int32_t vertex_offset = 0,
366 uint32_t first_instance = 0);
367
368 /**
369 * @brief Present rendered image to window
370 * @param cmd_id Command buffer ID
371 * @param window Target window for presentation
372 */
373 void present_rendered_image(CommandBufferID cmd_id, const std::shared_ptr<Core::Window>& window);
374
375 //==========================================================================
376 // Window Rendering Registration
377 //==========================================================================
378
379 /**
380 * @brief Associate a window with a render pass for rendering
381 * @param window Target window for rendering
382 * @param render_pass_id Render pass to use for this window
383 *
384 * The window must be registered with GraphicsSubsystem first.
385 * RenderFlow will query framebuffer/extent from DisplayService when needed.
386 *
387 * Usage:
388 * auto rp = flow.create_simple_render_pass();
389 * flow.register_window_for_rendering(my_window, rp);
390 */
391 void register_window_for_rendering(
392 const std::shared_ptr<Core::Window>& window,
393 RenderPassID render_pass_id);
394
395 /**
396 * @brief Unregister a window from rendering
397 * @param window Window to unregister
398 */
399 void unregister_window(const std::shared_ptr<Core::Window>& window);
400
401 /**
402 * @brief Check if a window is registered for rendering
403 */
404 [[nodiscard]] bool is_window_registered(const std::shared_ptr<Core::Window>& window) const;
405
406 /**
407 * @brief Get all registered windows
408 */
409 [[nodiscard]] std::vector<std::shared_ptr<Core::Window>> get_registered_windows() const;
410
411 //==========================================================================
412 // Convenience Methods
413 //==========================================================================
414
415 /**
416 * @brief Allocate descriptor sets for pipeline
417 * @param pipeline Pipeline ID
418 * @return Vector of allocated descriptor set IDs
419 */
420 std::vector<DescriptorSetID> allocate_pipeline_descriptors(RenderPipelineID pipeline);
421
422private:
424 std::weak_ptr<Core::Window> window;
426 };
427
428 RenderFlow() = default;
430
432 std::vector<ShaderID> shader_ids;
433 std::shared_ptr<Core::VKGraphicsPipeline> pipeline;
434 std::vector<vk::DescriptorSetLayout> layouts;
435 vk::PipelineLayout layout;
437 };
438
440 std::shared_ptr<Core::VKRenderPass> render_pass;
441 std::vector<RenderPassAttachment> attachments;
442 };
443
444 std::unordered_map<RenderPipelineID, PipelineState> m_pipelines;
445 std::unordered_map<RenderPassID, RenderPassState> m_render_passes;
446 std::unordered_map<std::shared_ptr<Core::Window>, WindowRenderAssociation> m_window_associations;
447
448 std::atomic<uint64_t> m_next_pipeline_id { 1 };
449 std::atomic<uint64_t> m_next_render_pass_id { 1 };
450
451 ShaderFoundry* m_shader_foundry = nullptr;
452 Registry::Service::DisplayService* m_display_service = nullptr;
453
454 static bool s_initialized;
455};
456
457/**
458 * @brief Get the global render flow instance
459 */
460inline MAYAFLUX_API RenderFlow& get_render_flow()
461{
462 return RenderFlow::instance();
463}
464
465} // namespace MayaFlux::Portal::Graphics
RenderFlow(RenderFlow &&) noexcept=delete
std::unordered_map< RenderPassID, RenderPassState > m_render_passes
std::unordered_map< std::shared_ptr< Core::Window >, WindowRenderAssociation > m_window_associations
RenderFlow & operator=(const RenderFlow &)=delete
std::unordered_map< RenderPipelineID, PipelineState > m_pipelines
RenderFlow(const RenderFlow &)=delete
Graphics pipeline and render pass orchestration.
Portal-level shader compilation and caching.
void initialize()
Definition main.cpp:11
PolygonMode
Rasterization polygon mode.
constexpr RenderPipelineID INVALID_RENDER_PIPELINE
void shutdown()
Shutdown Portal::Graphics subsystem.
Definition Graphics.cpp:69
constexpr RenderPassID INVALID_RENDER_PASS
constexpr ShaderID INVALID_SHADER
MAYAFLUX_API RenderFlow & get_render_flow()
Get the global render flow instance.
constexpr FramebufferID INVALID_FRAMEBUFFER
BlendOp
Blending operation.
PrimitiveTopology
Vertex assembly primitive topology.
CompareOp
Depth/stencil comparison operation.
static BlendAttachmentConfig alpha_blend()
Create standard alpha blending configuration.
Per-attachment blend configuration.
Depth and stencil test configuration.
Rasterization state configuration.
std::vector< vk::DescriptorSetLayout > layouts
std::shared_ptr< Core::VKGraphicsPipeline > pipeline
std::shared_ptr< Core::VKRenderPass > render_pass
std::vector< RenderPassAttachment > attachments
Render pass attachment configuration.
std::vector< Core::VertexAttribute > vertex_attributes
std::vector< Core::VertexBinding > vertex_bindings
std::optional< Kakshya::VertexLayout > semantic_vertex_layout
std::vector< std::vector< DescriptorBindingConfig > > descriptor_sets
std::vector< BlendAttachmentConfig > blend_attachments
Complete render pipeline configuration.
Backend display and presentation service interface.