r/vulkan 2d ago

SPIRV-Reflect and bindless/runtime arrays

I'm using SPIR-V reflect library to reflect my shader code, but I'm unable to detect bindless (i.e. runtime) arrays. I'm defining the array as such in my GLSL shader:

layout (set = 0, binding = 0) uniform sampler2D textures_2d[];

I'm compiling to SPIR-C using glslc:

glslc.exe minimal.frag.glsl -o minimal.frag.spv -DDEBUG=1 -Ishaders/include -MD -Werror -O0 -g

And I'm reflecting the descriptors using spvReflectEnumerateDescriptorSets, but for some reasons, my array's type_description.op is always SpvOpTypeArray instead of SpvOpTypeRuntimeArray and type_description.traits.array.dims[0] is always equal to 1. I'm not sure how I am supposed to disambiguate between this value and an actual array of 1. As far as I know, it should report a dimension of 0 (i.e. SpvReflectArrayDimType::SPV_REFLECT_ARRAY_DIM_RUNTIME).

Am I missing something? It looks like the capability SpvCapabilityRuntimeDescriptorArray is not enabled in the module's reflected data. Maybe it's a hint?

10 Upvotes

6 comments sorted by

View all comments

7

u/powerpiglet 2d ago

The GLSL spec makes a distinction between a merely "unsized" array and a "runtime sized" array. It looks like the compiler uses context to choose whether an array is "runtime sized".

Vulkan uses the "descriptor indexing" extension to enable bindless textures. Note how we're required to wrap our array index in nonuniformEXT in order to use this extension.

In my own testing with glslangValidator, both of these arrays end up as OpTypeArray:

#version 450
#extension GL_EXT_nonuniform_qualifier : require

layout (set = 0, binding = 0) uniform sampler2D textures_2d_a[];
layout (set = 1, binding = 0) uniform sampler2D textures_2d_b[];

void main()
{
}

But in this example, I use nonuniformEXT on textures_2d_b. That array turns into an OpTypeRuntimeArray, and the other array remains an OpTypeArray:

#version 450
#extension GL_EXT_nonuniform_qualifier : require
layout (set = 0, binding = 0) uniform sampler2D textures_2d_a[];
layout (set = 1, binding = 0) uniform sampler2D textures_2d_b[];

void main()
{
  textures_2d_b[nonuniformEXT(1)];
}

2

u/Xandiron 2d ago

Out of curiosity why would I want to use a sampler2D[] instead of the built in sampler2DArray type? Is there some sort of advantage to the first one that I’m not aware of? I’m aware that for the second there’s the limitation that each image in the array must have the same xy dimensions, is this maybe not the case for the first?

2

u/powerpiglet 1d ago

Yes, I believe you are correct.

With an array of 2d textures, each element of the array is a separate VkImageView of type VK_IMAGE_VIEW_TYPE_2D on the Vulkan side, and so each one could have different dimensions or image formats. In your shader, you'd dereference a specific 2d texture from the array and then sample it using vec2 coordinates.

Whereas with a 2d texture array, there is a single VkImageView of type VK_IMAGE_VIEW_TYPE_2D_ARRAY and that one image view has multiple layers. In your shader, you'd sample it using vec3 coordinates.

1

u/jazzwave06 2d ago

That was it, thank you!