Search code examples
glslshadervulkanspir-v

when do i need GL_EXT_nonuniform_qualifier?



I want to compile the following code into SPIR-V
#version 450 core
#define BATCH_ID (PushConstants.Indices.x >> 16)
#define MATERIAL_ID (PushConstants.Indices.x & 0xFFFF)

layout (push_constant) uniform constants {
    ivec2 Indices;
} PushConstants;

layout (constant_id = 1) const int MATERIAL_SIZE = 32;

in Vertex_Fragment {
    layout(location = 0) vec4 VertexColor;
    layout(location = 1) vec2 TexCoord;
} inData;

struct ParameterFrequence_3 {
    int ColorMap;
};
layout (set = 3, binding = 0, std140) uniform ParameterFrequence_3 {
    ParameterFrequence_3[MATERIAL_SIZE] data;
} Frequence_3;

layout (location = 0) out vec4 out_Color;

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


void main(void) {
    vec4 color = vec4(1.0);
    color *= texture(Sampler2DResources[Frequence_3.data[MATERIAL_ID].ColorMap], inData.TexCoord);
    color *= inData.VertexColor;
    out_Color = color;
}

(The code is generated by a program I am developing which is why the code might look a little strange, but it should make the problem clear)
When trying to do so, I am told

error: 'variable index' : required extension not requested: GL_EXT_nonuniform_qualifier

(for the third last line where the texture lookup also happens)
After I followed a lot of discussion around how dynamically uniform is specified and that the shading language spec basically says the scope is specified by the API while neither OpenGL nor Vulkan really do so (maybe that changed), I am confused why i get that error.
Initially I wanted to use instanced vertex attributes for the indices, those however are not dynamically uniform which is what I thought the PushConstants would be.
So when PushConstants are constant during the draw call (which is the max scope for dynamically uniform requirement), how can the above shader end up in any dynamically non-uniform state?

Edit: Does it have to do with the fact that the buffer backing the storage for the "ColorMap" could be aliased by another buffer via which the content might be modified during the invocation? Or is there a way to tell the compiler this is a "restricted" storage so it knows it is constant?

Thanks


Solution

  • It is 3 am in the morning over here, I should just go to sleep.
    Chances anyone end up having the same problem are small, but I'd still rather answer it myself than delete it:
    I simply had to add a SpecializationConstant to set the size of the sampler2D array, now it works without requiring any extension.
    Good night