Perform reflection on SPIR-V bytecode.
Uses SPIRV-Reflect library to extract bindings, push constants, workgroup sizes, etc. Falls back to basic parsing if library unavailable.
344{
345#ifdef MAYAFLUX_USE_SPIRV_REFLECT
346 SpvReflectShaderModule module;
347 SpvReflectResult result = spvReflectCreateShaderModule(
348 spirv_code.size() * sizeof(uint32_t),
349 spirv_code.data(),
350 &module);
351
352 if (result != SPV_REFLECT_RESULT_SUCCESS) {
354 "SPIRV-Reflect failed: {}", static_cast<int>(result));
355 return false;
356 }
357
358 uint32_t binding_count = 0;
359 result = spvReflectEnumerateDescriptorBindings(&module, &binding_count, nullptr);
360 if (result == SPV_REFLECT_RESULT_SUCCESS && binding_count > 0) {
361 std::vector<SpvReflectDescriptorBinding*> bindings(binding_count);
362 spvReflectEnumerateDescriptorBindings(&module, &binding_count, bindings.data());
363
364 for (const auto* binding : bindings) {
365 ShaderReflection::DescriptorBinding desc;
366 desc.set = binding->set;
367 desc.binding = binding->binding;
368 desc.type = static_cast<vk::DescriptorType>(binding->descriptor_type);
370 desc.count = binding->count;
371 desc.name = binding->name ? binding->name : "";
372
374 }
375
377 "Reflected {} descriptor bindings", binding_count);
378 }
379
380 uint32_t push_constant_count = 0;
381 result = spvReflectEnumeratePushConstantBlocks(&module, &push_constant_count, nullptr);
382 if (result == SPV_REFLECT_RESULT_SUCCESS && push_constant_count > 0) {
383 std::vector<SpvReflectBlockVariable*> push_constants(push_constant_count);
384 spvReflectEnumeratePushConstantBlocks(&module, &push_constant_count, push_constants.data());
385
386 for (const auto* block : push_constants) {
387 ShaderReflection::PushConstantRange range;
389 range.offset = block->offset;
390 range.size = block->size;
391
393 }
394
396 "Reflected {} push constant blocks", push_constant_count);
397 }
398
399 if (
m_stage == vk::ShaderStageFlagBits::eCompute) {
401 module.entry_points[0].local_size.x,
402 module.entry_points[0].local_size.y,
403 module.entry_points[0].local_size.z
404 };
405
407 "Compute shader workgroup size: [{}, {}, {}]",
411 }
412
413 spvReflectDestroyShaderModule(&module);
414 return true;
415
416#else
418 "SPIRV-Reflect not available - shader reflection disabled");
419
420 if (
m_stage == vk::ShaderStageFlagBits::eCompute) {
421
422
423 for (size_t i = 0; i < spirv_code.size() - 4; ++i) {
424 if ((spirv_code[i] & 0xFFFF) == 17) {
425 uint32_t mode = spirv_code[i + 2];
426 if (mode == 17) {
428 spirv_code[i + 3],
429 spirv_code[i + 4],
430 spirv_code[i + 5]
431 };
432
434 "Extracted compute workgroup size: [{}, {}, {}]",
438 break;
439 }
440 }
441 }
442 }
443
444 return false;
445#endif
446}
#define MF_WARN(comp, ctx,...)
#define MF_DEBUG(comp, ctx,...)
vk::ShaderStageFlagBits m_stage
ShaderReflection m_reflection
@ GraphicsBackend
Graphics/visual rendering backend (Vulkan, OpenGL)
@ Core
Core engine, backend, subsystems.
std::vector< DescriptorBinding > bindings
std::vector< PushConstantRange > push_constants
std::optional< std::array< uint32_t, 3 > > workgroup_size
local_size_x/y/z