MayaFlux 0.1.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
VKGraphicsPipeline.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "VKShaderModule.hpp"
4
5namespace MayaFlux::Core {
6
8 uint32_t binding;
9 uint32_t stride;
11 vk::VertexInputRate input_rate;
12
13 VertexBinding() = default;
14 VertexBinding(uint32_t b, uint32_t s, bool instanced = false, vk::VertexInputRate rate = vk::VertexInputRate::eVertex)
15 : binding(b)
16 , stride(s)
17 , per_instance(instanced)
18 , input_rate(rate)
19 {
20 }
21};
22
24 uint32_t location;
25 uint32_t binding;
26 vk::Format format;
27 uint32_t offset;
28
29 VertexAttribute() = default;
30 VertexAttribute(uint32_t loc, uint32_t bind, vk::Format fmt, uint32_t off)
31 : location(loc)
32 , binding(bind)
33 , format(fmt)
34 , offset(off)
35 {
36 }
37};
38
40 bool blend_enable = false;
41 vk::BlendFactor src_color_blend_factor = vk::BlendFactor::eSrcAlpha;
42 vk::BlendFactor dst_color_blend_factor = vk::BlendFactor::eOneMinusSrcAlpha;
43 vk::BlendOp color_blend_op = vk::BlendOp::eAdd;
44 vk::BlendFactor src_alpha_blend_factor = vk::BlendFactor::eOne;
45 vk::BlendFactor dst_alpha_blend_factor = vk::BlendFactor::eZero;
46 vk::BlendOp alpha_blend_op = vk::BlendOp::eAdd;
47 vk::ColorComponentFlags color_write_mask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA;
48};
49
50/**
51 * @struct GraphicsPipelineConfig
52 * @brief Configuration for creating a graphics pipeline
53 *
54 * Comprehensive graphics pipeline state. Vulkan requires ALL fixed-function
55 * state to be specified at pipeline creation time.
56 */
58 //==========================================================================
59 // SHADER STAGES
60 //==========================================================================
61
62 std::shared_ptr<VKShaderModule> vertex_shader = nullptr; // Required
63 std::shared_ptr<VKShaderModule> fragment_shader = nullptr; // Optional (depth-only passes)
64 std::shared_ptr<VKShaderModule> geometry_shader = nullptr; // Optional
65 std::shared_ptr<VKShaderModule> tess_control_shader = nullptr; // Optional
66 std::shared_ptr<VKShaderModule> tess_evaluation_shader = nullptr; // Optional
67
68 //==========================================================================
69 // VERTEX INPUT STATE
70 //==========================================================================
71
72 std::vector<VertexBinding> vertex_bindings;
73 std::vector<VertexAttribute> vertex_attributes;
74
76
77 //==========================================================================
78 // INPUT ASSEMBLY STATE
79 //==========================================================================
80
81 vk::PrimitiveTopology topology = vk::PrimitiveTopology::eTriangleList;
83
84 //==========================================================================
85 // TESSELLATION STATE
86 //==========================================================================
87
89
90 //==========================================================================
91 // VIEWPORT STATE
92 //==========================================================================
93
94 bool dynamic_viewport = true;
95 bool dynamic_scissor = true;
96
97 vk::Viewport static_viewport {};
98 vk::Rect2D static_scissor {};
99
100 //==========================================================================
101 // RASTERIZATION STATE
102 //==========================================================================
103
104 bool depth_clamp_enable = false;
106 vk::PolygonMode polygon_mode = vk::PolygonMode::eFill;
107 vk::CullModeFlags cull_mode = vk::CullModeFlagBits::eBack;
108 vk::FrontFace front_face = vk::FrontFace::eCounterClockwise;
109
110 bool depth_bias_enable = false;
112 float depth_bias_clamp = 0.0f;
114
115 float line_width = 1.0f;
116
117 //==========================================================================
118 // MULTISAMPLE STATE
119 //==========================================================================
120
121 vk::SampleCountFlagBits rasterization_samples = vk::SampleCountFlagBits::e1;
123 float min_sample_shading = 1.0f;
124 std::vector<vk::SampleMask> sample_mask;
127
128 //==========================================================================
129 // DEPTH STENCIL STATE
130 //==========================================================================
131
132 bool depth_test_enable = true;
134 vk::CompareOp depth_compare_op = vk::CompareOp::eLess;
136 float min_depth_bounds = 0.0f;
137 float max_depth_bounds = 1.0f;
138
140 vk::StencilOpState front_stencil {};
141 vk::StencilOpState back_stencil {};
142
143 //==========================================================================
144 // COLOR BLEND STATE
145 //==========================================================================
146
147 bool logic_op_enable = false;
148 vk::LogicOp logic_op = vk::LogicOp::eCopy;
149
150 std::vector<ColorBlendAttachment> color_blend_attachments;
151 std::array<float, 4> blend_constants = { 0.0f, 0.0f, 0.0f, 0.0f };
152
153 //==========================================================================
154 // DYNAMIC STATE
155 //==========================================================================
156
157 std::vector<vk::DynamicState> dynamic_states = {
158 vk::DynamicState::eViewport,
159 vk::DynamicState::eScissor
160 };
161
162 //==========================================================================
163 // PIPELINE LAYOUT (descriptors + push constants)
164 //==========================================================================
165
166 std::vector<vk::DescriptorSetLayout> descriptor_set_layouts;
167 std::vector<vk::PushConstantRange> push_constant_ranges;
168
169 //==========================================================================
170 // RENDER PASS / DYNAMIC RENDERING
171 //==========================================================================
172
173 vk::RenderPass render_pass = nullptr;
174 uint32_t subpass = 0;
175
177 std::vector<vk::Format> color_attachment_formats;
178 vk::Format depth_attachment_format = vk::Format::eUndefined;
179 vk::Format stencil_attachment_format = vk::Format::eUndefined;
180
181 //==========================================================================
182 // PIPELINE CACHE
183 //==========================================================================
184
185 vk::PipelineCache cache = nullptr;
186
187 //==========================================================================
188 // HELPER METHODS
189 //==========================================================================
190
196
199 void disable_depth_test();
200 void enable_wireframe();
202 void disable_culling();
203};
204
205/**
206 * @class VKGraphicsPipeline
207 * @brief Vulkan graphics pipeline wrapper
208 *
209 * Handles the complex graphics pipeline state machine. Unlike compute pipelines,
210 * graphics pipelines require extensive fixed-function configuration.
211 *
212 * Responsibilities:
213 * - Create graphics pipeline from config
214 * - Manage pipeline layout
215 * - Bind pipeline to command buffer
216 * - Bind vertex/index buffers
217 * - Bind descriptor sets
218 * - Push constants
219 * - Dynamic state updates (viewport, scissor, etc.)
220 * - Draw commands
221 *
222 * Thread Safety:
223 * - NOT thread-safe
224 * - Create on main thread, use on render thread
225 */
227public:
230
234 VKGraphicsPipeline& operator=(VKGraphicsPipeline&&) noexcept;
235
236 //==========================================================================
237 // PIPELINE CREATION
238 //==========================================================================
239
240 /**
241 * @brief Create graphics pipeline from configuration
242 * @param device Logical device
243 * @param config Pipeline configuration
244 * @return true if creation succeeded
245 *
246 * Validates shaders, creates pipeline layout, and creates pipeline.
247 */
248 bool create(vk::Device device, const GraphicsPipelineConfig& config);
249
250 /**
251 * @brief Cleanup pipeline resources
252 */
253 void cleanup(vk::Device device);
254
255 //==========================================================================
256 // PIPELINE BINDING
257 //==========================================================================
258
259 /**
260 * @brief Bind pipeline to command buffer
261 * @param cmd Command buffer
262 */
263 void bind(vk::CommandBuffer cmd);
264
265 /**
266 * @brief Bind descriptor sets
267 * @param cmd Command buffer
268 * @param sets Descriptor sets to bind
269 * @param first_set First set index (for multiple sets)
270 */
271 void bind_descriptor_sets(vk::CommandBuffer cmd,
272 std::span<vk::DescriptorSet> sets,
273 uint32_t first_set = 0);
274
275 /**
276 * @brief Push constants
277 * @param cmd Command buffer
278 * @param stages Shader stages
279 * @param offset Offset in push constant block
280 * @param size Size of data
281 * @param data Pointer to data
282 */
283 void push_constants(vk::CommandBuffer cmd,
284 vk::ShaderStageFlags stages,
285 uint32_t offset, uint32_t size,
286 const void* data);
287
288 /**
289 * @brief Typed push constants
290 */
291 template <typename T>
292 void push_constants_typed(vk::CommandBuffer cmd,
293 vk::ShaderStageFlags stages,
294 const T& data)
295 {
296 push_constants(cmd, stages, 0, sizeof(T), &data);
297 }
298
299 //==========================================================================
300 // VERTEX/INDEX BUFFER BINDING
301 //==========================================================================
302
303 /**
304 * @brief Bind vertex buffers
305 * @param cmd Command buffer
306 * @param first_binding First binding index
307 * @param buffers Vertex buffers
308 * @param offsets Offsets in buffers
309 */
310 void bind_vertex_buffers(vk::CommandBuffer cmd,
311 uint32_t first_binding,
312 std::span<vk::Buffer> buffers,
313 std::span<vk::DeviceSize> offsets);
314
315 /**
316 * @brief Bind single vertex buffer (common case)
317 */
318 void bind_vertex_buffer(vk::CommandBuffer cmd,
319 vk::Buffer buffer,
320 vk::DeviceSize offset = 0,
321 uint32_t binding = 0);
322
323 /**
324 * @brief Bind index buffer
325 * @param cmd Command buffer
326 * @param buffer Index buffer
327 * @param offset Offset in buffer
328 * @param index_type Index type (uint16 or uint32)
329 */
330 void bind_index_buffer(vk::CommandBuffer cmd,
331 vk::Buffer buffer,
332 vk::DeviceSize offset = 0,
333 vk::IndexType index_type = vk::IndexType::eUint32);
334
335 //==========================================================================
336 // DYNAMIC STATE
337 //==========================================================================
338
339 /**
340 * @brief Set viewport (if dynamic)
341 * @param cmd Command buffer
342 * @param viewport Viewport to set
343 */
344 void set_viewport(vk::CommandBuffer cmd, const vk::Viewport& viewport);
345
346 /**
347 * @brief Set scissor (if dynamic)
348 * @param cmd Command buffer
349 * @param scissor Scissor rectangle
350 */
351 void set_scissor(vk::CommandBuffer cmd, const vk::Rect2D& scissor);
352
353 /**
354 * @brief Set line width (if dynamic)
355 */
356 void set_line_width(vk::CommandBuffer cmd, float width);
357
358 /**
359 * @brief Set depth bias (if dynamic)
360 */
361 void set_depth_bias(vk::CommandBuffer cmd,
362 float constant_factor,
363 float clamp,
364 float slope_factor);
365
366 /**
367 * @brief Set blend constants (if dynamic)
368 */
369 void set_blend_constants(vk::CommandBuffer cmd, const float constants[4]);
370
371 //==========================================================================
372 // DRAW COMMANDS
373 //==========================================================================
374
375 /**
376 * @brief Draw vertices
377 * @param cmd Command buffer
378 * @param vertex_count Number of vertices
379 * @param instance_count Number of instances
380 * @param first_vertex First vertex index
381 * @param first_instance First instance index
382 */
383 void draw(vk::CommandBuffer cmd,
384 uint32_t vertex_count,
385 uint32_t instance_count = 1,
386 uint32_t first_vertex = 0,
387 uint32_t first_instance = 0);
388
389 /**
390 * @brief Draw indexed vertices
391 * @param cmd Command buffer
392 * @param index_count Number of indices
393 * @param instance_count Number of instances
394 * @param first_index First index
395 * @param vertex_offset Vertex offset added to index
396 * @param first_instance First instance index
397 */
398 void draw_indexed(vk::CommandBuffer cmd,
399 uint32_t index_count,
400 uint32_t instance_count = 1,
401 uint32_t first_index = 0,
402 int32_t vertex_offset = 0,
403 uint32_t first_instance = 0);
404
405 /**
406 * @brief Draw indirect (dispatch from GPU buffer)
407 * @param cmd Command buffer
408 * @param buffer Buffer containing vk::DrawIndirectCommand
409 * @param offset Offset in buffer
410 * @param draw_count Number of draws
411 * @param stride Stride between commands
412 */
413 void draw_indirect(vk::CommandBuffer cmd,
414 vk::Buffer buffer,
415 vk::DeviceSize offset,
416 uint32_t draw_count,
417 uint32_t stride);
418
419 /**
420 * @brief Draw indexed indirect
421 */
422 void draw_indexed_indirect(vk::CommandBuffer cmd,
423 vk::Buffer buffer,
424 vk::DeviceSize offset,
425 uint32_t draw_count,
426 uint32_t stride);
427
428 //==========================================================================
429 // ACCESSORS
430 //==========================================================================
431
432 [[nodiscard]] vk::Pipeline get() const { return m_pipeline; }
433 [[nodiscard]] vk::PipelineLayout get_layout() const { return m_layout; }
434 [[nodiscard]] bool is_valid() const { return m_pipeline != nullptr; }
435
436 /**
437 * @brief Get shader reflections (for introspection)
438 */
439 [[nodiscard]] const GraphicsPipelineConfig& get_config() const
440 {
441 return m_config;
442 }
443
444private:
445 vk::Device m_device;
446 vk::Pipeline m_pipeline;
447 vk::PipelineLayout m_layout;
448 GraphicsPipelineConfig m_config; // Keep for reference
449
450 /**
451 * @brief Create pipeline layout from config
452 */
453 vk::PipelineLayout create_pipeline_layout(
454 vk::Device device,
455 const GraphicsPipelineConfig& config);
456
457 /**
458 * @brief Validate shader stages
459 */
460 bool validate_shaders(const GraphicsPipelineConfig& config);
461
462 /**
463 * @brief Build vertex input state from config
464 */
465 vk::PipelineVertexInputStateCreateInfo build_vertex_input_state(
466 const GraphicsPipelineConfig& config,
467 std::vector<vk::VertexInputBindingDescription>& bindings,
468 std::vector<vk::VertexInputAttributeDescription>& attributes);
469
470 /**
471 * @brief Build input assembly state
472 */
473 vk::PipelineInputAssemblyStateCreateInfo build_input_assembly_state(
474 const GraphicsPipelineConfig& config);
475
476 /**
477 * @brief Build tessellation state
478 */
479 vk::PipelineTessellationStateCreateInfo build_tessellation_state(
480 const GraphicsPipelineConfig& config);
481
482 /**
483 * @brief Build viewport state
484 */
485 vk::PipelineViewportStateCreateInfo build_viewport_state(
486 const GraphicsPipelineConfig& config,
487 std::vector<vk::Viewport>& viewports,
488 std::vector<vk::Rect2D>& scissors);
489
490 /**
491 * @brief Build rasterization state
492 */
493 vk::PipelineRasterizationStateCreateInfo build_rasterization_state(
494 const GraphicsPipelineConfig& config);
495
496 /**
497 * @brief Build multisample state
498 */
499 vk::PipelineMultisampleStateCreateInfo build_multisample_state(
500 const GraphicsPipelineConfig& config);
501
502 /**
503 * @brief Build depth stencil state
504 */
505 vk::PipelineDepthStencilStateCreateInfo build_depth_stencil_state(
506 const GraphicsPipelineConfig& config);
507
508 /**
509 * @brief Build color blend state
510 */
511 vk::PipelineColorBlendStateCreateInfo build_color_blend_state(
512 const GraphicsPipelineConfig& config,
513 std::vector<vk::PipelineColorBlendAttachmentState>& attachments);
514
515 /**
516 * @brief Build dynamic state
517 */
518 vk::PipelineDynamicStateCreateInfo build_dynamic_state(
519 const GraphicsPipelineConfig& config);
520};
521
522} // namespace MayaFlux::Core
bool validate_shaders(const GraphicsPipelineConfig &config)
Validate shader stages.
void cleanup(vk::Device device)
Cleanup pipeline resources.
void bind(vk::CommandBuffer cmd)
Bind pipeline to command buffer.
void set_line_width(vk::CommandBuffer cmd, float width)
Set line width (if dynamic)
void set_scissor(vk::CommandBuffer cmd, const vk::Rect2D &scissor)
Set scissor (if dynamic)
void bind_descriptor_sets(vk::CommandBuffer cmd, std::span< vk::DescriptorSet > sets, uint32_t first_set=0)
Bind descriptor sets.
vk::PipelineDepthStencilStateCreateInfo build_depth_stencil_state(const GraphicsPipelineConfig &config)
Build depth stencil state.
void draw(vk::CommandBuffer cmd, uint32_t vertex_count, uint32_t instance_count=1, uint32_t first_vertex=0, uint32_t first_instance=0)
Draw vertices.
void set_depth_bias(vk::CommandBuffer cmd, float constant_factor, float clamp, float slope_factor)
Set depth bias (if dynamic)
vk::PipelineInputAssemblyStateCreateInfo build_input_assembly_state(const GraphicsPipelineConfig &config)
Build input assembly state.
VKGraphicsPipeline & operator=(const VKGraphicsPipeline &)=delete
void bind_vertex_buffers(vk::CommandBuffer cmd, uint32_t first_binding, std::span< vk::Buffer > buffers, std::span< vk::DeviceSize > offsets)
Bind vertex buffers.
void set_blend_constants(vk::CommandBuffer cmd, const float constants[4])
Set blend constants (if dynamic)
void push_constants(vk::CommandBuffer cmd, vk::ShaderStageFlags stages, uint32_t offset, uint32_t size, const void *data)
Push constants.
const GraphicsPipelineConfig & get_config() const
Get shader reflections (for introspection)
vk::PipelineMultisampleStateCreateInfo build_multisample_state(const GraphicsPipelineConfig &config)
Build multisample state.
void bind_vertex_buffer(vk::CommandBuffer cmd, vk::Buffer buffer, vk::DeviceSize offset=0, uint32_t binding=0)
Bind single vertex buffer (common case)
vk::PipelineRasterizationStateCreateInfo build_rasterization_state(const GraphicsPipelineConfig &config)
Build rasterization state.
vk::PipelineVertexInputStateCreateInfo build_vertex_input_state(const GraphicsPipelineConfig &config, std::vector< vk::VertexInputBindingDescription > &bindings, std::vector< vk::VertexInputAttributeDescription > &attributes)
Build vertex input state from config.
vk::PipelineTessellationStateCreateInfo build_tessellation_state(const GraphicsPipelineConfig &config)
Build tessellation state.
bool create(vk::Device device, const GraphicsPipelineConfig &config)
Create graphics pipeline from configuration.
vk::PipelineLayout get_layout() const
void push_constants_typed(vk::CommandBuffer cmd, vk::ShaderStageFlags stages, const T &data)
Typed push constants.
VKGraphicsPipeline(const VKGraphicsPipeline &)=delete
void set_viewport(vk::CommandBuffer cmd, const vk::Viewport &viewport)
Set viewport (if dynamic)
void draw_indexed_indirect(vk::CommandBuffer cmd, vk::Buffer buffer, vk::DeviceSize offset, uint32_t draw_count, uint32_t stride)
Draw indexed indirect.
vk::PipelineLayout create_pipeline_layout(vk::Device device, const GraphicsPipelineConfig &config)
Create pipeline layout from config.
void draw_indexed(vk::CommandBuffer cmd, uint32_t index_count, uint32_t instance_count=1, uint32_t first_index=0, int32_t vertex_offset=0, uint32_t first_instance=0)
Draw indexed vertices.
vk::PipelineColorBlendStateCreateInfo build_color_blend_state(const GraphicsPipelineConfig &config, std::vector< vk::PipelineColorBlendAttachmentState > &attachments)
Build color blend state.
vk::PipelineDynamicStateCreateInfo build_dynamic_state(const GraphicsPipelineConfig &config)
Build dynamic state.
vk::PipelineViewportStateCreateInfo build_viewport_state(const GraphicsPipelineConfig &config, std::vector< vk::Viewport > &viewports, std::vector< vk::Rect2D > &scissors)
Build viewport state.
void bind_index_buffer(vk::CommandBuffer cmd, vk::Buffer buffer, vk::DeviceSize offset=0, vk::IndexType index_type=vk::IndexType::eUint32)
Bind index buffer.
void draw_indirect(vk::CommandBuffer cmd, vk::Buffer buffer, vk::DeviceSize offset, uint32_t draw_count, uint32_t stride)
Draw indirect (dispatch from GPU buffer)
Vulkan graphics pipeline wrapper.
std::vector< ColorBlendAttachment > color_blend_attachments
std::vector< vk::Format > color_attachment_formats
static GraphicsPipelineConfig default_3d()
std::shared_ptr< VKShaderModule > fragment_shader
static GraphicsPipelineConfig alpha_blended()
std::vector< vk::DynamicState > dynamic_states
std::vector< vk::PushConstantRange > push_constant_ranges
static GraphicsPipelineConfig additive_blended()
std::shared_ptr< VKShaderModule > vertex_shader
std::vector< vk::DescriptorSetLayout > descriptor_set_layouts
std::vector< vk::SampleMask > sample_mask
std::vector< VertexBinding > vertex_bindings
static GraphicsPipelineConfig depth_only()
std::vector< VertexAttribute > vertex_attributes
static GraphicsPipelineConfig default_2d()
std::shared_ptr< VKShaderModule > geometry_shader
std::shared_ptr< VKShaderModule > tess_evaluation_shader
std::shared_ptr< VKShaderModule > tess_control_shader
Configuration for creating a graphics pipeline.
VertexAttribute(uint32_t loc, uint32_t bind, vk::Format fmt, uint32_t off)
VertexBinding(uint32_t b, uint32_t s, bool instanced=false, vk::VertexInputRate rate=vk::VertexInputRate::eVertex)