glslang
glslang copied to clipboard
Array with size using specialization constant passed as function parameter.
Following code compiled with glslangValidator, the spirv will make a shadow copy of the function parameter and call the function, but glsl can't use with types containing arrays sized with a specialization constant for initializer,
#version 460
#extension GL_EXT_shader_explicit_arithmetic_types : enable
layout(constant_id = 0) const uint32_t RANK_OUT = 4;
layout(local_size_x = 64) in;
void outputOffsetToIndex(uint[RANK_OUT] shape, uint offset, out uint[RANK_OUT] index) {
for(uint32_t i = RANK_OUT - 1; i >= 0; i--) {
index[i] = offset % shape[i];
offset /= shape[i];
}
}
void main() {
uint offset = gl_GlobalInvocationID.x;
uint[RANK_OUT] shape;
uint[RANK_OUT] index;
outputOffsetToIndex(shape, offset, index);
}
if use spirv-cross to decompile the spv to glsl, code will be like this, compile again using glslang will print: 'initializer' : can't use with types containing arrays sized with a specialization constant
#version 460
layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
layout(constant_id = 0) const uint RANK_OUT = 4u;
const uint _19 = (RANK_OUT - 1u);
void outputOffsetToIndex(uint shape[RANK_OUT], uint offset, out uint index[RANK_OUT])
{
for (uint i = _19; i >= 0u; i--)
{
index[i] = offset % shape[i];
offset /= shape[i];
}
}
void main()
{
uint offset = gl_GlobalInvocationID.x;
uint shape[RANK_OUT];
uint param[RANK_OUT] = shape;
uint param_1 = offset;
uint index[RANK_OUT];
uint param_2[RANK_OUT] = index;
outputOffsetToIndex(param, param_1, param_2);
shape = param;
offset = param_1;
index = param_2;
}
The spir-v produced from the original shader appears to be valid. We do not support roundtripping with spirv-cross (i.e., glsl -> spv -> spirv-cross -> glsl). It seems like this is a case that spirv-cross does not support?
I look at look at the GL_KHR_vulkan_glsl spec and it seems like there is a bit of ambiguity in the spec around arrays sized with specialization constants. In particular, the spec says "Types containing arrays sized with a specialization constant cannot be compared, assigned as aggregates, declared with an initializer, or used as an initializer. They can, however, be passed as arguments to functions having formal parameters of the same type." This seems to be the text that is used as justification for the error that glslang produces, but it can also be read to mean that the restriction would apply to e.g. a struct containing a spec-constant-sized array and not to variables of the array type itself.