MayaFlux 1.0.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 263 of file RenderFlow.cpp.

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