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

◆ reflect_spirv()

bool MayaFlux::Core::VKShaderModule::reflect_spirv ( const std::vector< uint32_t > &  spirv_code)
private

Perform reflection on SPIR-V bytecode.

Parameters
spirv_codeSPIR-V bytecode
Returns
true if reflection succeeded

Uses SPIRV-Cross library to extract bindings, push constants, workgroup sizes, etc. Falls back to basic parsing if library unavailable.

Definition at line 515 of file VKShaderModule.cpp.

516{
517 try {
518 spirv_cross::Compiler compiler(spirv_code);
519 spirv_cross::ShaderResources resources = compiler.get_shader_resources();
520
521 auto reflect_resources = [&](const spirv_cross::SmallVector<spirv_cross::Resource>& res_vec,
522 bool is_storage = false) {
523 for (const auto& resource : res_vec) {
524 ShaderReflection::DescriptorBinding desc;
525 desc.set = compiler.get_decoration(resource.id, spv::DecorationDescriptorSet);
526 desc.binding = compiler.get_decoration(resource.id, spv::DecorationBinding);
527 desc.stage = m_stage;
528 desc.name = resource.name;
529
530 const auto& type = compiler.get_type(resource.type_id);
531 desc.count = type.array.empty() ? 1 : type.array[0];
532 desc.type = spirv_to_vk_descriptor_type(type.basetype, type, is_storage);
533
534 m_reflection.bindings.push_back(desc);
535 }
536 };
537
538 reflect_resources(resources.uniform_buffers, false);
539
540 reflect_resources(resources.storage_buffers, true);
541
542 reflect_resources(resources.sampled_images, false);
543
544 reflect_resources(resources.storage_images, true);
545
546 reflect_resources(resources.separate_images, false);
547 reflect_resources(resources.separate_samplers, false);
548
549 try {
550 const spirv_cross::ShaderResources used = compiler.get_shader_resources(
551 compiler.get_active_interface_variables());
552
553 auto collect_active = [&](const spirv_cross::SmallVector<spirv_cross::Resource>& res_vec,
554 bool is_storage) {
555 for (const auto& resource : res_vec) {
556 ShaderReflection::DescriptorBinding desc;
557 desc.set = compiler.get_decoration(resource.id, spv::DecorationDescriptorSet);
558 desc.binding = compiler.get_decoration(resource.id, spv::DecorationBinding);
559 desc.stage = m_stage;
560 const std::string block_name = compiler.get_name(resource.base_type_id);
561 desc.name = block_name.empty() ? resource.name : block_name;
562
563 const auto& type = compiler.get_type(resource.type_id);
564 desc.count = type.array.empty() ? 1 : type.array[0];
565 desc.type = spirv_to_vk_descriptor_type(type.basetype, type, is_storage);
566
567 m_active_bindings.push_back(desc);
568 }
569 };
570
571 collect_active(used.uniform_buffers, false);
572 collect_active(used.storage_buffers, true);
573 collect_active(used.sampled_images, false);
574 collect_active(used.storage_images, true);
575 collect_active(used.separate_images, false);
576 collect_active(used.separate_samplers, false);
577 } catch (const std::exception& e) {
578 m_active_bindings.clear();
580 "Active descriptor binding analysis failed: {}", e.what());
581 }
582
583 if (!m_reflection.bindings.empty()) {
585 "Reflected {} descriptor bindings", m_reflection.bindings.size());
586 }
587
588 for (const auto& pc_buffer : resources.push_constant_buffers) {
589 const auto& type = compiler.get_type(pc_buffer.type_id);
590
591 ShaderReflection::PushConstantRange range;
592 range.stage = m_stage;
593 range.offset = 0;
594 range.size = static_cast<uint32_t>(compiler.get_declared_struct_size(type));
595
596 m_reflection.push_constants.push_back(range);
597 }
598
599 if (!m_reflection.push_constants.empty()) {
601 "Reflected {} push constant blocks", m_reflection.push_constants.size());
602 }
603
604 auto spec_constants = compiler.get_specialization_constants();
605 for (const auto& spec : spec_constants) {
606 ShaderReflection::SpecializationConstant sc;
607 sc.constant_id = spec.constant_id;
608 sc.name = compiler.get_name(spec.id);
609
610 const auto& type = compiler.get_type(compiler.get_constant(spec.id).constant_type);
611 sc.size = type.basetype == spirv_cross::SPIRType::Boolean
612 ? static_cast<uint32_t>(sizeof(vk::Bool32))
613 : type.width / 8;
614
616 }
617
620 "Reflected {} specialization constants",
622 }
623
624 if (m_stage == vk::ShaderStageFlagBits::eCompute
625 || m_stage == vk::ShaderStageFlagBits::eMeshEXT
626 || m_stage == vk::ShaderStageFlagBits::eTaskEXT) {
627 auto entry_points = compiler.get_entry_points_and_stages();
628
629 for (const auto& ep : entry_points) {
630 if (ep.name == m_entry_point && ep.execution_model == spv::ExecutionModelGLCompute) {
631
632 std::array<uint32_t, 3> workgroup_size {
633 compiler.get_execution_mode_argument(spv::ExecutionModeLocalSize, 0),
634 compiler.get_execution_mode_argument(spv::ExecutionModeLocalSize, 1),
635 compiler.get_execution_mode_argument(spv::ExecutionModeLocalSize, 2)
636 };
637
638 if (!workgroup_size.empty() && workgroup_size.size() >= 3) {
639 m_reflection.workgroup_size = std::array<uint32_t, 3> {
640 workgroup_size[0],
641 workgroup_size[1],
642 workgroup_size[2]
643 };
644
646 "Compute shader workgroup size: [{}, {}, {}]",
647 workgroup_size[0], workgroup_size[1], workgroup_size[2]);
648 }
649 break;
650 }
651 }
652 }
653
654 if (m_stage == vk::ShaderStageFlagBits::eVertex) {
655 for (const auto& input : resources.stage_inputs) {
656 uint32_t location = compiler.get_decoration(input.id, spv::DecorationLocation);
657 const auto& type = compiler.get_type(input.type_id);
658
659 vk::VertexInputAttributeDescription attr;
660 attr.location = location;
661 attr.binding = 0;
662 attr.format = spirv_type_to_vk_format(type);
663 attr.offset = 0;
664
665 m_reflection.vertex_attributes.push_back(attr);
666 }
667
668 if (!m_reflection.vertex_attributes.empty()) {
670 "Reflected {} vertex input attributes",
672 }
673 }
674
675 return true;
676
677 } catch (const spirv_cross::CompilerError& e) {
679 "SPIRV-Cross reflection failed: {}", e.what());
680 return false;
681 }
682}
#define MF_ERROR(comp, ctx,...)
#define MF_WARN(comp, ctx,...)
#define MF_DEBUG(comp, ctx,...)
Core::GlobalInputConfig input
Definition Config.cpp:42
vk::PhysicalDeviceType type
Definition VKDevice.cpp:126
uint32_t width
vk::ShaderStageFlagBits m_stage
static vk::Format spirv_type_to_vk_format(const spirv_cross::SPIRType &type)
Convert SPIRV-Cross type to Vulkan vertex attribute format.
std::vector< ShaderReflection::DescriptorBinding > m_active_bindings
@ GraphicsBackend
Graphics/visual rendering backend (Vulkan, OpenGL)
@ Core
Core engine, backend, subsystems.
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
std::vector< SpecializationConstant > specialization_constants
std::vector< DescriptorBinding > bindings
std::vector< PushConstantRange > push_constants
std::vector< vk::VertexInputAttributeDescription > vertex_attributes
std::optional< std::array< uint32_t, 3 > > workgroup_size
local_size_x/y/z

References MayaFlux::Core::ShaderReflection::DescriptorBinding::binding, MayaFlux::Core::ShaderReflection::bindings, MayaFlux::Core::ShaderReflection::SpecializationConstant::constant_id, MayaFlux::Journal::Core, MayaFlux::Core::ShaderReflection::DescriptorBinding::count, MayaFlux::Journal::GraphicsBackend, input, m_active_bindings, m_entry_point, m_reflection, m_stage, MF_DEBUG, MF_ERROR, MF_WARN, MayaFlux::Core::ShaderReflection::DescriptorBinding::name, MayaFlux::Core::ShaderReflection::SpecializationConstant::name, MayaFlux::Core::ShaderReflection::push_constants, MayaFlux::Core::ShaderReflection::DescriptorBinding::set, MayaFlux::Core::ShaderReflection::SpecializationConstant::size, MayaFlux::Core::ShaderReflection::specialization_constants, spirv_type_to_vk_format(), MayaFlux::Core::ShaderReflection::DescriptorBinding::stage, type, MayaFlux::Core::ShaderReflection::DescriptorBinding::type, MayaFlux::Core::ShaderReflection::vertex_attributes, and MayaFlux::Core::ShaderReflection::workgroup_size.

Referenced by create_from_spirv().

+ Here is the call graph for this function:
+ Here is the caller graph for this function: