Skip to content

Implement SPIR-V shader reflection #579

@IAmNotHanni

Description

@IAmNotHanni

Is your feature request related to a problem?

We currently just load shaders into memory and create VkShaderModule from it. When using a shader, we have to specify manually which shader type it is, and we can't do any error checking about whether the shader type is correct or if the shader fits the descriptor set layout.

There is already an pull request with work in progress by yeetari #418, but it would have to be rebased on the new code base introduced by rendergraph2, and we have to further work on the wrapper for the reflection code itself as well.

Description

  • We can use SPIR-V for shader reflection because I really wouldn't want to write a parser myself
  • We load the shader code, and parse the information about it using SPIR-V reflect
  • This will give us more capabilities for error checks and reasoning of shader use inside rendergraph
  • Maybe in the far future, we can compose the rendergraph in ImGui at runtime directly, and the shader inputs can be displayed in there because we use reflection? This is a very advanced idea for the future. It would be very cool to do this.

Alternatives

If we don't use shader reflection, we can't do any error checks or advanced reasoning about shaders in rendergraph!

Affected Code

Example code using SPIR-V reflect library:

#include "spirv_reflect.h"

int SpirvReflectExample(const void* spirv_code, size_t spirv_nbytes)
{
  // Generate reflection data for a shader
  SpvReflectShaderModule module;
  SpvReflectResult result = spvReflectCreateShaderModule(spirv_nbytes, spirv_code, &module);
  assert(result == SPV_REFLECT_RESULT_SUCCESS);

  // Enumerate and extract shader's input variables
  uint32_t var_count = 0;
  result = spvReflectEnumerateInputVariables(&module, &var_count, NULL);
  assert(result == SPV_REFLECT_RESULT_SUCCESS);
  SpvReflectInterfaceVariable** input_vars =
    (SpvReflectInterfaceVariable**)malloc(var_count * sizeof(SpvReflectInterfaceVariable*));
  result = spvReflectEnumerateInputVariables(&module, &var_count, input_vars);
  assert(result == SPV_REFLECT_RESULT_SUCCESS);

  // Output variables, descriptor bindings, descriptor sets, and push constants
  // can be enumerated and extracted using a similar mechanism.

  // Destroy the reflection data when no longer required.
  spvReflectDestroyShaderModule(&module);
}

Operating System

All

Additional Context

None

Metadata

Metadata

Assignees

Projects

Status

Todo

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions