"Constness" of specialization constants doesn't propagate to all types of expressions
Hi,
It seems there are some issues with specialization constants where the compiler fails to understand that specific expressions are constexpr. The compiler fails with global const initializers must be constant type of errors.
This is a shader that exhibits the problem:
#version 460
layout(constant_id = 0) const int TILE_SIZE = 0;
const float f = float(TILE_SIZE); // Fails
const int i[1] = int[](TILE_SIZE); // Fails
const uint u = TILE_SIZE * 10 + 1; // Passes
layout (location = 0) out vec4 fragColor;
void main()
{
fragColor = vec4(0.4, 0.4, 0.8, 1.0);
}
It's practically impossible to initialize the contents of constexpr arrays with specialization constants.
Sounds similar to #2025.
OK. I will try to get to this soon. If someone else wants to contribute a solution, please let me know before you start to avoid duplicate effort.
I am now looking at this. I will have a fix ASAP.
Re the following:
const float f = float(TILE_SIZE);
The current GLSL spec seems to allow this statement, but after some communication with the author and the SPIR-V working group, it appears that the spec intended to disallow int-to-float conversion of a spec constant as a constant expression. Float-to-int is disallowed as well.
Frankly, I am not quite sure why this was decided. To me it seems counter-intuitive to treat spec constants differently than regular constants and a continuing source of confusion and frustration. There is apparently a fairly lengthy philosophical reason which I didn't insist on being given during our meeting today. If you want to know what it is, I can try and ask for it.
I think the other statement is valid and am pressing on to fix that.
Thanks for looking into this Greg.
I'm not sure what's the reasoning for disallowing this as well. As you said, and I agree, people intuitively expect for these things to work so having an explanation from the working group would be great.
But I'll also argue that since GLSL allowed that and SPIR-V as well (unless I missed something in the spec) then going back and restricting it now might not be the best idea. There might be software out there that relies in such behaviour.
Well, glslang never allowed it, so folks should not see any regressions here.
There are some other restrictions that make more sense, for example, the trig functions are allowed for constants, but not for spec constants. So constructors like float() are not the only outliers, which softens the blow a bit.
Looking at const int i[1] = int[](TILE_SIZE); // Fails now.
glslang has commented code and a commented test which holds to the policy that constant arrays containing specialization constants are not allowed, although I can find no such policy in the Vulkan, SPIR-V or GLSL specs. The aforementioned test's file name seems to imply that the policy comes from Vulkan.
I will check with the SPIR-V WG to see if they know more about this policy.
Once I have a go-ahead from them I should be posting a fix shortly after.
According to the SPIR-V WG, the construct const int i[1] = int[](TILE_SIZE); is legal in SPIR-V, GLSL and Vulkan. It is only generating an error because support has not yet been implemented in glslang.
I will add support shortly.