Is is possible to have an array of specialization constants such that the glsl code looks similar to the following:
layout(constant_id = 0) const vec2 arr[2] = vec2[] (
vec2(2.0f, 2.0f),
vec2(4.0f, 4.0f)
);
or, alternatively:
layout(constant_id = 0) const float arr[4] = float[] (
2.0f, 2.0f,
4.0f, 4.0f
);
As far as I have read there is no limit to the number of specialization constants that can be used so it feels strange that it wouldn't be possible but when I attempt the above the SPIR-V compiler notifies me that 'constant_id' can only be applied to a scalar. Currently I am using a uniform buffer to provide the data but I would like to eliminate the backed buffer and the need to bind the buffer before drawing as well as allow the system to optimize the code during pipeline creation if its possible.
The shading languages (both Vulkan-GLSL and SPIR-V) makes something of a distinction between the definition of a specialization constant within the shader and the interface for specializing those constants. But they go about this process in different ways.
In both languages, the external interface to a specialization constant only works on scalar values. That is, though you can set multiple constants to values, the constants you're setting are each a single scalar.
SPIR-V allows you to declare a specialization constant which is a composite (array/vector/matrix). However, the components of this composite must be either specialization constants or constant values. If those components are scalar specialization constants, you can OpDecorate
them with an ID, which the external code will access.
Vulkan (and OpenGL) GLSL go about this slightly differently from raw SPIR-V. In GLSL, a const
-qualified value with a constant_id
is a specialization constant. These must be scalars.
However, you can also have a const
-qualified value that is initialized by values that are either constant expressions or specialization constants. You don't qualify these with a constant_id
, but you built them from things that are so qualified:
layout(constant_id = 18) const int scX = 1;
layout(constant_id = 19) const int scZ = 1;
const vec3 scVec = vec3(scX, 1, scZ); // partially specialized vector
const
-qualified values that are initialized from specialization constants are called "partially specialized". When this GLSL is converted into SPIR-V, these are converted into OpSpecConstantComposite
values.