MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches

◆ create_pipeline()

RenderPipelineID MayaFlux::Portal::Graphics::RenderFlow::create_pipeline ( const RenderPipelineConfig config,
const std::vector< vk::Format > &  color_formats,
vk::Format  depth_format = vk::Format::eUndefined 
)

Create graphics pipeline for dynamic rendering (no render pass object)

Parameters
configPipeline configuration
color_formatsColor attachment formats for dynamic rendering
depth_formatDepth attachment format
Returns
Pipeline ID or INVALID_RENDER_PIPELINE on error

Definition at line 261 of file RenderFlow.cpp.

265{
266 if (!is_initialized()) {
268 "RenderFlow not initialized");
270 }
271
272 if (config.mesh_shader == INVALID_SHADER && config.vertex_shader == INVALID_SHADER) {
274 "Pipeline requires either mesh shader or vertex shader");
276 }
277
278 if (color_formats.empty()) {
280 "At least one color format required for dynamic rendering pipeline");
282 }
283
284 Core::GraphicsPipelineConfig vk_config;
285
286 vk_config.vertex_shader = m_shader_foundry->get_vk_shader_module(config.vertex_shader);
287 if (config.fragment_shader != INVALID_SHADER) {
288 vk_config.fragment_shader = m_shader_foundry->get_vk_shader_module(config.fragment_shader);
289 }
290 if (config.geometry_shader != INVALID_SHADER) {
291 vk_config.geometry_shader = m_shader_foundry->get_vk_shader_module(config.geometry_shader);
292 }
293 if (config.tess_control_shader != INVALID_SHADER) {
294 vk_config.tess_control_shader = m_shader_foundry->get_vk_shader_module(config.tess_control_shader);
295 }
296 if (config.tess_eval_shader != INVALID_SHADER) {
297 vk_config.tess_evaluation_shader = m_shader_foundry->get_vk_shader_module(config.tess_eval_shader);
298 }
299
300 vk_config.mesh_shader = m_shader_foundry->get_vk_shader_module(config.mesh_shader);
301 if (config.task_shader != INVALID_SHADER) {
302 vk_config.task_shader = m_shader_foundry->get_vk_shader_module(config.task_shader);
303 }
304
305 if (config.fragment_shader != INVALID_SHADER) {
306 vk_config.fragment_shader = m_shader_foundry->get_vk_shader_module(config.fragment_shader);
307 }
308
309 if (config.semantic_vertex_layout.has_value()) {
311 "Pipeline using semantic VertexLayout ({} vertices, {} attributes)",
312 config.semantic_vertex_layout->vertex_count,
313 config.semantic_vertex_layout->attributes.size());
314
315 auto [vk_bindings, vk_attributes] = translate_semantic_layout(
316 config.semantic_vertex_layout.value());
317
318 vk_config.vertex_bindings = vk_bindings;
319 vk_config.vertex_attributes = vk_attributes;
320 vk_config.use_vertex_shader_reflection = false;
321
322 } else if (!config.vertex_bindings.empty() || !config.vertex_attributes.empty()) {
324 "Pipeline using explicit vertex config ({} bindings, {} attributes)",
325 config.vertex_bindings.size(), config.vertex_attributes.size());
326
327 for (const auto& binding : config.vertex_bindings) {
328 Core::VertexBinding vk_binding {};
329 vk_binding.binding = binding.binding;
330 vk_binding.stride = binding.stride;
331 vk_binding.input_rate = binding.per_instance ? vk::VertexInputRate::eInstance : vk::VertexInputRate::eVertex;
332 vk_config.vertex_bindings.push_back(vk_binding);
333 }
334
335 for (const auto& attr : config.vertex_attributes) {
336 Core::VertexAttribute vk_attr {};
337 vk_attr.location = attr.location;
338 vk_attr.binding = attr.binding;
339 vk_attr.format = attr.format;
340 vk_attr.offset = attr.offset;
341 vk_config.vertex_attributes.push_back(vk_attr);
342 }
343
344 vk_config.use_vertex_shader_reflection = false;
345 } else {
347 "Pipeline will use shader reflection for vertex input");
348 vk_config.use_vertex_shader_reflection = config.use_vertex_shader_reflection;
349 }
350
351 vk_config.topology = to_vk_topology(config.topology);
352 vk_config.primitive_restart_enable = false;
353
354 vk_config.polygon_mode = to_vk_polygon_mode(config.rasterization.polygon_mode);
355 vk_config.cull_mode = to_vk_cull_mode(config.rasterization.cull_mode);
356 vk_config.front_face = config.rasterization.front_face_ccw ? vk::FrontFace::eCounterClockwise : vk::FrontFace::eClockwise;
357 vk_config.line_width = config.rasterization.line_width;
358 vk_config.depth_clamp_enable = config.rasterization.depth_clamp;
359 vk_config.depth_bias_enable = config.rasterization.depth_bias;
360
361 vk_config.depth_test_enable = config.depth_stencil.depth_test_enable;
362 vk_config.depth_write_enable = config.depth_stencil.depth_write_enable;
363 vk_config.depth_compare_op = to_vk_compare_op(config.depth_stencil.depth_compare_op);
364 vk_config.stencil_test_enable = config.depth_stencil.stencil_test_enable;
365
366 for (const auto& blend : config.blend_attachments) {
367 Core::ColorBlendAttachment vk_blend;
368 vk_blend.blend_enable = blend.blend_enable;
369 vk_blend.src_color_blend_factor = to_vk_blend_factor(blend.src_color_factor);
370 vk_blend.dst_color_blend_factor = to_vk_blend_factor(blend.dst_color_factor);
371 vk_blend.color_blend_op = to_vk_blend_op(blend.color_blend_op);
372 vk_blend.src_alpha_blend_factor = to_vk_blend_factor(blend.src_alpha_factor);
373 vk_blend.dst_alpha_blend_factor = to_vk_blend_factor(blend.dst_alpha_factor);
374 vk_blend.alpha_blend_op = to_vk_blend_op(blend.alpha_blend_op);
375 vk_config.color_blend_attachments.push_back(vk_blend);
376 }
377
378 std::vector<vk::DescriptorSetLayout> layouts;
379 vk::DescriptorSetLayout state_vt_layout {};
380
381 {
382 std::vector<vk::DescriptorSetLayoutBinding> set0_bindings;
383
384 vk::DescriptorSetLayoutBinding vt_b;
385 vt_b.binding = 0;
386 vt_b.descriptorType = vk::DescriptorType::eUniformBuffer;
387 vt_b.descriptorCount = 1;
388 vt_b.stageFlags = vk::ShaderStageFlagBits::eVertex;
389 set0_bindings.push_back(vt_b);
390
391 if (!config.descriptor_sets.empty()) {
392 for (const auto& binding : config.descriptor_sets[0]) {
393 if (binding.set == 0 && binding.binding != 0) {
394 vk::DescriptorSetLayoutBinding vk_b;
395 vk_b.binding = binding.binding;
396 vk_b.descriptorType = binding.type;
397 vk_b.descriptorCount = binding.count > 0 ? binding.count : 1;
398 vk_b.stageFlags = vk::ShaderStageFlagBits::eVertex
399 | vk::ShaderStageFlagBits::eFragment;
400 set0_bindings.push_back(vk_b);
401 }
402 }
403 }
404
405 vk::DescriptorSetLayoutCreateInfo layout_info;
406 layout_info.bindingCount = static_cast<uint32_t>(set0_bindings.size());
407 layout_info.pBindings = set0_bindings.data();
408 vk::DescriptorSetLayout vt_layout = m_shader_foundry->get_device().createDescriptorSetLayout(layout_info);
409 layouts.push_back(vt_layout);
410 state_vt_layout = vt_layout;
411 }
412
413 for (const auto& desc_set : config.descriptor_sets) {
414 bool all_set_zero = std::ranges::all_of(desc_set,
415 [](const auto& b) { return b.set == 0; });
416 if (all_set_zero)
417 continue;
418
419 std::vector<vk::DescriptorSetLayoutBinding> bindings;
420 for (const auto& binding : desc_set) {
421 if (binding.set == 0)
422 continue;
423 vk::DescriptorSetLayoutBinding vk_b;
424 vk_b.binding = binding.binding;
425 vk_b.descriptorType = binding.type;
426 vk_b.descriptorCount = binding.count > 0 ? binding.count : 1;
427 vk_b.stageFlags = vk::ShaderStageFlagBits::eVertex
428 | vk::ShaderStageFlagBits::eFragment;
429 bindings.push_back(vk_b);
430 }
431
432 if (bindings.empty())
433 continue;
434
435 vk::DescriptorSetLayoutCreateInfo layout_info;
436 layout_info.bindingCount = static_cast<uint32_t>(bindings.size());
437 layout_info.pBindings = bindings.data();
438 layouts.push_back(
439 m_shader_foundry->get_device().createDescriptorSetLayout(layout_info));
440 }
441
442 vk_config.descriptor_set_layouts = layouts;
443
444 vk::ShaderStageFlags push_constant_stages;
445
446 if (config.mesh_shader != INVALID_SHADER) {
447 push_constant_stages = vk::ShaderStageFlagBits::eMeshEXT;
448 if (config.task_shader != INVALID_SHADER) {
449 push_constant_stages |= vk::ShaderStageFlagBits::eTaskEXT;
450 }
451 if (config.fragment_shader != INVALID_SHADER) {
452 push_constant_stages |= vk::ShaderStageFlagBits::eFragment;
453 }
454 } else {
455 push_constant_stages = vk::ShaderStageFlagBits::eVertex | vk::ShaderStageFlagBits::eFragment;
456 if (config.geometry_shader != INVALID_SHADER) {
457 push_constant_stages |= vk::ShaderStageFlagBits::eGeometry;
458 }
459 if (config.tess_control_shader != INVALID_SHADER) {
460 push_constant_stages |= vk::ShaderStageFlagBits::eTessellationControl;
461 }
462 if (config.tess_eval_shader != INVALID_SHADER) {
463 push_constant_stages |= vk::ShaderStageFlagBits::eTessellationEvaluation;
464 }
465 }
466
467 if (config.push_constant_size > 0) {
468 vk::PushConstantRange range;
469 range.stageFlags = push_constant_stages;
470 range.offset = 0;
471 range.size = static_cast<uint32_t>(config.push_constant_size);
472 vk_config.push_constant_ranges.push_back(range);
473 }
474
475 vk_config.color_attachment_formats = color_formats;
476 vk_config.depth_attachment_format = depth_format;
477
478 vk_config.dynamic_states = {
479 vk::DynamicState::eViewport,
480 vk::DynamicState::eScissor
481 };
482
483 auto pipeline = std::make_shared<Core::VKGraphicsPipeline>();
484 if (!pipeline->create(m_shader_foundry->get_device(), vk_config)) {
486 "Failed to create VKGraphicsPipeline for dynamic rendering");
487
488 for (auto layout : layouts) {
489 m_shader_foundry->get_device().destroyDescriptorSetLayout(layout);
490 }
492 }
493
494 auto pipeline_id = m_next_pipeline_id.fetch_add(1);
495 PipelineState state;
496 state.shader_ids = { config.vertex_shader, config.fragment_shader };
497 state.pipeline = pipeline;
498 state.layouts = layouts;
499 state.view_transform_layout = state_vt_layout;
500 state.layout = pipeline->get_layout();
501 state.push_constant_stages = push_constant_stages;
502 m_pipelines[pipeline_id] = std::move(state);
503
505 "Dynamic rendering pipeline created (ID: {}, {} color attachments)",
506 pipeline_id, color_formats.size());
507
508 return pipeline_id;
509}
#define MF_INFO(comp, ctx,...)
#define MF_ERROR(comp, ctx,...)
#define MF_DEBUG(comp, ctx,...)
size_t b
std::unordered_map< RenderPipelineID, PipelineState > m_pipelines
std::atomic< uint64_t > m_next_pipeline_id
vk::Device get_device() const
Get logical device handle.
std::shared_ptr< Core::VKShaderModule > get_vk_shader_module(ShaderID shader_id)
@ Rendering
GPU rendering operations (graphics pipeline, frame rendering)
@ Portal
High-level user-facing API layer.
std::vector< double > range(std::span< const double > data, size_t n_windows, uint32_t hop_size, uint32_t window_size)
Value range (max - min) per window.
Definition Analysis.cpp:452
constexpr RenderPipelineID INVALID_RENDER_PIPELINE
constexpr ShaderID INVALID_SHADER

References MayaFlux::Core::ColorBlendAttachment::alpha_blend_op, b, MayaFlux::Core::VertexBinding::binding, MayaFlux::Portal::Graphics::RenderPipelineConfig::blend_attachments, MayaFlux::Core::ColorBlendAttachment::blend_enable, MayaFlux::Core::GraphicsPipelineConfig::color_attachment_formats, MayaFlux::Core::GraphicsPipelineConfig::color_blend_attachments, MayaFlux::Core::ColorBlendAttachment::color_blend_op, MayaFlux::Core::GraphicsPipelineConfig::cull_mode, MayaFlux::Portal::Graphics::RasterizationConfig::cull_mode, MayaFlux::Core::GraphicsPipelineConfig::depth_attachment_format, MayaFlux::Portal::Graphics::RasterizationConfig::depth_bias, MayaFlux::Core::GraphicsPipelineConfig::depth_bias_enable, MayaFlux::Portal::Graphics::RasterizationConfig::depth_clamp, MayaFlux::Core::GraphicsPipelineConfig::depth_clamp_enable, MayaFlux::Core::GraphicsPipelineConfig::depth_compare_op, MayaFlux::Portal::Graphics::DepthStencilConfig::depth_compare_op, MayaFlux::Portal::Graphics::RenderPipelineConfig::depth_stencil, MayaFlux::Core::GraphicsPipelineConfig::depth_test_enable, MayaFlux::Portal::Graphics::DepthStencilConfig::depth_test_enable, MayaFlux::Core::GraphicsPipelineConfig::depth_write_enable, MayaFlux::Portal::Graphics::DepthStencilConfig::depth_write_enable, MayaFlux::Core::GraphicsPipelineConfig::descriptor_set_layouts, MayaFlux::Portal::Graphics::RenderPipelineConfig::descriptor_sets, MayaFlux::Core::ColorBlendAttachment::dst_alpha_blend_factor, MayaFlux::Core::ColorBlendAttachment::dst_color_blend_factor, MayaFlux::Core::GraphicsPipelineConfig::dynamic_states, MayaFlux::Core::GraphicsPipelineConfig::fragment_shader, MayaFlux::Portal::Graphics::RenderPipelineConfig::fragment_shader, MayaFlux::Core::GraphicsPipelineConfig::front_face, MayaFlux::Portal::Graphics::RasterizationConfig::front_face_ccw, MayaFlux::Core::GraphicsPipelineConfig::geometry_shader, MayaFlux::Portal::Graphics::RenderPipelineConfig::geometry_shader, MayaFlux::Portal::Graphics::ShaderFoundry::get_device(), MayaFlux::Portal::Graphics::ShaderFoundry::get_vk_shader_module(), MayaFlux::Portal::Graphics::INVALID_RENDER_PIPELINE, MayaFlux::Portal::Graphics::INVALID_SHADER, is_initialized(), MayaFlux::Portal::Graphics::RenderFlow::PipelineState::layout, MayaFlux::Portal::Graphics::RenderFlow::PipelineState::layouts, MayaFlux::Core::GraphicsPipelineConfig::line_width, MayaFlux::Portal::Graphics::RasterizationConfig::line_width, MayaFlux::Core::VertexAttribute::location, m_next_pipeline_id, m_pipelines, m_shader_foundry, MayaFlux::Core::GraphicsPipelineConfig::mesh_shader, MayaFlux::Portal::Graphics::RenderPipelineConfig::mesh_shader, MF_DEBUG, MF_ERROR, MF_INFO, MayaFlux::Portal::Graphics::RenderFlow::PipelineState::pipeline, MayaFlux::Core::GraphicsPipelineConfig::polygon_mode, MayaFlux::Portal::Graphics::RasterizationConfig::polygon_mode, MayaFlux::Journal::Portal, MayaFlux::Core::GraphicsPipelineConfig::primitive_restart_enable, MayaFlux::Core::GraphicsPipelineConfig::push_constant_ranges, MayaFlux::Portal::Graphics::RenderPipelineConfig::push_constant_size, MayaFlux::Portal::Graphics::RenderFlow::PipelineState::push_constant_stages, MayaFlux::Portal::Graphics::RenderPipelineConfig::rasterization, MayaFlux::Journal::Rendering, MayaFlux::Portal::Graphics::RenderPipelineConfig::semantic_vertex_layout, MayaFlux::Portal::Graphics::RenderFlow::PipelineState::shader_ids, MayaFlux::Core::ColorBlendAttachment::src_alpha_blend_factor, MayaFlux::Core::ColorBlendAttachment::src_color_blend_factor, MayaFlux::Core::GraphicsPipelineConfig::stencil_test_enable, MayaFlux::Portal::Graphics::DepthStencilConfig::stencil_test_enable, MayaFlux::Core::GraphicsPipelineConfig::task_shader, MayaFlux::Portal::Graphics::RenderPipelineConfig::task_shader, MayaFlux::Core::GraphicsPipelineConfig::tess_control_shader, MayaFlux::Portal::Graphics::RenderPipelineConfig::tess_control_shader, MayaFlux::Portal::Graphics::RenderPipelineConfig::tess_eval_shader, MayaFlux::Core::GraphicsPipelineConfig::tess_evaluation_shader, MayaFlux::Core::GraphicsPipelineConfig::topology, MayaFlux::Portal::Graphics::RenderPipelineConfig::topology, MayaFlux::Core::GraphicsPipelineConfig::use_vertex_shader_reflection, MayaFlux::Portal::Graphics::RenderPipelineConfig::use_vertex_shader_reflection, MayaFlux::Core::GraphicsPipelineConfig::vertex_attributes, MayaFlux::Portal::Graphics::RenderPipelineConfig::vertex_attributes, MayaFlux::Core::GraphicsPipelineConfig::vertex_bindings, MayaFlux::Portal::Graphics::RenderPipelineConfig::vertex_bindings, MayaFlux::Core::GraphicsPipelineConfig::vertex_shader, MayaFlux::Portal::Graphics::RenderPipelineConfig::vertex_shader, and MayaFlux::Portal::Graphics::RenderFlow::PipelineState::view_transform_layout.

+ Here is the call graph for this function: