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