MayaFlux 0.2.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
RenderFlow.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "ShaderFoundry.hpp"
4
6struct DisplayService;
7}
8
9namespace MayaFlux::Core {
10class VKGraphicsPipeline;
11class Window;
12}
13
14namespace MayaFlux::Buffers {
15class RootGraphicsBuffer;
16class VKBuffer;
17}
18
20
21/**
22 * @class RenderFlow
23 * @brief Graphics pipeline orchestration for dynamic rendering
24 *
25 * RenderFlow is the rendering counterpart to ComputePress.
26 * It manages graphics pipelines and draw command recording using Vulkan 1.3 dynamic rendering.
27 *
28 * Responsibilities:
29 * - Create graphics pipelines for dynamic rendering
30 * - Record render commands to secondary command buffers
31 * - Manage dynamic rendering state (begin/end rendering)
32 * - Coordinate with ShaderFoundry for resources
33 *
34 * Design Philosophy (parallel to ComputePress):
35 * - Uses ShaderFoundry for low-level resources
36 * - Provides high-level rendering API
37 * - Backend-agnostic interface
38 * - Integrates with RootGraphicsBuffer
39 * - No render pass objects - uses vkCmdBeginRendering/vkCmdEndRendering
40 *
41 * Usage Pattern:
42 * ```cpp
43 * auto& flow = Portal::Graphics::get_render_flow();
44 * auto& foundry = Portal::Graphics::get_shader_foundry();
45 *
46 * // Create pipeline for dynamic rendering
47 * RenderPipelineConfig config;
48 * config.vertex_shader = vertex_id;
49 * config.fragment_shader = fragment_id;
50 * config.semantic_vertex_layout = buffer->get_vertex_layout();
51 * auto pipeline_id = flow.create_pipeline(config, { swapchain_format });
52 *
53 * // In RenderProcessor - record secondary command buffer:
54 * auto cmd_id = foundry.begin_secondary_commands(swapchain_format);
55 * flow.bind_pipeline(cmd_id, pipeline_id);
56 * flow.bind_vertex_buffers(cmd_id, {buffer});
57 * flow.draw(cmd_id, vertex_count);
58 * foundry.end_commands(cmd_id);
59 *
60 * // In PresentProcessor - execute secondaries in primary:
61 * auto primary_id = foundry.begin_commands(CommandBufferType::GRAPHICS);
62 * flow.begin_rendering(primary_id, window, swapchain_image);
63 * primary_cmd.executeCommands(secondary_buffers);
64 * flow.end_rendering(primary_id, window);
65 * display_service->submit_and_present(window, primary_cmd);
66 * ```
67 */
68class MAYAFLUX_API RenderFlow {
69public:
71 {
72 static RenderFlow flow;
73 return flow;
74 }
75
76 RenderFlow(const RenderFlow&) = delete;
77 RenderFlow& operator=(const RenderFlow&) = delete;
78 RenderFlow(RenderFlow&&) noexcept = delete;
79 RenderFlow& operator=(RenderFlow&&) noexcept = delete;
80
81 bool initialize();
82 void stop();
83 void shutdown();
84
85 [[nodiscard]] bool is_initialized() const { return m_shader_foundry != nullptr; }
86
87 //==========================================================================
88 // Pipeline Creation
89 //==========================================================================
90
91 /**
92 * @brief Create graphics pipeline for dynamic rendering (no render pass object)
93 * @param config Pipeline configuration
94 * @param color_formats Color attachment formats for dynamic rendering
95 * @param depth_format Depth attachment format
96 * @return Pipeline ID or INVALID_RENDER_PIPELINE on error
97 */
98 RenderPipelineID create_pipeline(
99 const RenderPipelineConfig& config,
100 const std::vector<vk::Format>& color_formats,
101 vk::Format depth_format = vk::Format::eUndefined);
102
103 /**
104 * @brief Destroy a graphics pipeline
105 * @param pipeline_id Pipeline ID to destroy
106 */
107 void destroy_pipeline(RenderPipelineID pipeline_id);
108
109 //==========================================================================
110 // Dynamic Rendering
111 //==========================================================================
112
113 /**
114 * @brief Begin dynamic rendering to a window
115 * @param cmd_id Command buffer ID
116 * @param window Target window
117 * @param swapchain_image Swapchain image to render to
118 * @param clear_color Clear color (RGBA)
119 *
120 * Uses vkCmdBeginRendering - no render pass objects needed.
121 */
122 void begin_rendering(
123 CommandBufferID cmd_id,
124 const std::shared_ptr<Core::Window>& window,
125 vk::Image swapchain_image,
126 const std::array<float, 4>& clear_color = { 0.0F, 0.0F, 0.0F, 1.0F });
127
128 /**
129 * @brief End dynamic rendering
130 * @param cmd_id Command buffer ID
131 * @param window Target window
132 */
133 void end_rendering(CommandBufferID cmd_id, const std::shared_ptr<Core::Window>& window);
134
135 //==========================================================================
136 // Command Recording
137 //==========================================================================
138
139 /**
140 * @brief Bind graphics pipeline
141 * @param cmd_id Command buffer ID
142 * @param pipeline Pipeline ID
143 */
144 void bind_pipeline(CommandBufferID cmd_id, RenderPipelineID pipeline);
145
146 /**
147 * @brief Bind vertex buffers
148 * @param cmd_id Command buffer ID
149 * @param buffers Vertex buffers to bind
150 * @param first_binding First binding index
151 */
152 void bind_vertex_buffers(
153 CommandBufferID cmd_id,
154 const std::vector<std::shared_ptr<Buffers::VKBuffer>>& buffers,
155 uint32_t first_binding = 0);
156
157 /**
158 * @brief Bind index buffer
159 * @param cmd_id Command buffer ID
160 * @param buffer Index buffer
161 * @param index_type Index type (16-bit or 32-bit)
162 */
163 void bind_index_buffer(
164 CommandBufferID cmd_id,
165 const std::shared_ptr<Buffers::VKBuffer>& buffer,
166 vk::IndexType index_type = vk::IndexType::eUint32);
167
168 /**
169 * @brief Bind descriptor sets
170 * @param cmd_id Command buffer ID
171 * @param pipeline Pipeline ID
172 * @param descriptor_sets Descriptor set IDs
173 */
174 void bind_descriptor_sets(
175 CommandBufferID cmd_id,
176 RenderPipelineID pipeline,
177 const std::vector<DescriptorSetID>& descriptor_sets);
178
179 /**
180 * @brief Push constants
181 * @param cmd_id Command buffer ID
182 * @param pipeline Pipeline ID
183 * @param data Constant data
184 * @param size Data size in bytes
185 */
186 void push_constants(
187 CommandBufferID cmd_id,
188 RenderPipelineID pipeline,
189 const void* data,
190 size_t size);
191
192 /**
193 * @brief Draw command
194 * @param cmd_id Command buffer ID
195 * @param vertex_count Number of vertices
196 * @param instance_count Number of instances (default: 1)
197 * @param first_vertex First vertex index
198 * @param first_instance First instance index
199 */
200 void draw(
201 CommandBufferID cmd_id,
202 uint32_t vertex_count,
203 uint32_t instance_count = 1,
204 uint32_t first_vertex = 0,
205 uint32_t first_instance = 0);
206
207 /**
208 * @brief Indexed draw command
209 * @param cmd_id Command buffer ID
210 * @param index_count Number of indices
211 * @param instance_count Number of instances (default: 1)
212 * @param first_index First index
213 * @param vertex_offset Vertex offset
214 * @param first_instance First instance index
215 */
216 void draw_indexed(
217 CommandBufferID cmd_id,
218 uint32_t index_count,
219 uint32_t instance_count = 1,
220 uint32_t first_index = 0,
221 int32_t vertex_offset = 0,
222 uint32_t first_instance = 0);
223
224 //==========================================================================
225 // Window Rendering Registration
226 //==========================================================================
227
228 /**
229 * @brief Register a window for dynamic rendering
230 * @param window Target window for rendering
231 *
232 * The window must be registered with GraphicsSubsystem first
233 * (i.e., window->is_graphics_registered() must be true).
234 *
235 * This associates the window with RenderFlow for tracking.
236 * No render pass attachment - dynamic rendering handles this per-frame.
237 */
238 void register_window_for_rendering(const std::shared_ptr<Core::Window>& window);
239
240 /**
241 * @brief Unregister a window from rendering
242 * @param window Window to unregister
243 */
244 void unregister_window(const std::shared_ptr<Core::Window>& window);
245
246 /**
247 * @brief Check if a window is registered for rendering
248 */
249 [[nodiscard]] bool is_window_registered(const std::shared_ptr<Core::Window>& window) const;
250
251 /**
252 * @brief Get all registered windows
253 */
254 [[nodiscard]] std::vector<std::shared_ptr<Core::Window>> get_registered_windows() const;
255
256 //==========================================================================
257 // Convenience Methods
258 //==========================================================================
259
260 /**
261 * @brief Allocate descriptor sets for pipeline
262 * @param pipeline Pipeline ID
263 * @return Vector of allocated descriptor set IDs
264 */
265 std::vector<DescriptorSetID> allocate_pipeline_descriptors(RenderPipelineID pipeline);
266
267private:
269 std::weak_ptr<Core::Window> window;
270 vk::Image swapchain_image {};
271 };
272
274 std::vector<ShaderID> shader_ids;
275 std::shared_ptr<Core::VKGraphicsPipeline> pipeline;
276 std::vector<vk::DescriptorSetLayout> layouts;
277 vk::PipelineLayout layout;
278 };
279
280 std::unordered_map<RenderPipelineID, PipelineState> m_pipelines;
281 std::unordered_map<std::shared_ptr<Core::Window>, WindowRenderAssociation> m_window_associations;
282
283 std::atomic<uint64_t> m_next_pipeline_id { 1 };
284
285 ShaderFoundry* m_shader_foundry = nullptr;
286 Registry::Service::DisplayService* m_display_service = nullptr;
287
288 static bool s_initialized;
289
290 RenderFlow() = default;
292 void cleanup_pipelines();
293
294 /**
295 * @brief Get current image view for window
296 * @param window Target window
297 * @return vk::ImageView of current swapchain image
298 */
299 vk::ImageView get_current_image_view(const std::shared_ptr<Core::Window>& window);
300};
301
302/**
303 * @brief Get the global render flow instance
304 */
305inline MAYAFLUX_API RenderFlow& get_render_flow()
306{
307 return RenderFlow::instance();
308}
309
310} // namespace MayaFlux::Portal::Graphics
RenderFlow(RenderFlow &&) noexcept=delete
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 orchestration for dynamic rendering.
Portal-level shader compilation and caching.
void initialize()
Definition main.cpp:11
void shutdown()
Shutdown Portal::Graphics subsystem.
Definition Graphics.cpp:87
MAYAFLUX_API RenderFlow & get_render_flow()
Get the global render flow instance.
std::vector< vk::DescriptorSetLayout > layouts
std::shared_ptr< Core::VKGraphicsPipeline > pipeline
Complete render pipeline configuration.
Backend display and presentation service interface.