Allow pipeline-overridable constants in structs with fixed sized arrays
Hello, it appears that pipeline-overridable constants cannot be used in structs / type definitions.
Is your feature request related to a problem? Please describe.
Given the following code:
override TEST: u32 = 8;
struct Test {
test: array<u32, TEST>,
}
The following error is produced:
Shader validation error: Type [10] 'Test' is invalid
┌─ compute:300:1
│
300 │ ╭ struct Test {
301 │ │ test: array<u32, TEST>,
│ ╰──────────────────────────^ naga::Type [10]
│
= Expected data type, found [9]
Type [10] 'Test' is invalid
Expected data type, found [9]
Describe the solution you'd like I'd like to be able to use pipeline-overridable constants in struct definitions. I'm not sure if this is expected or not considering I can see it working differently underneath; you'd have to recompile all of the types depending on the "source" type. But it seems to be a bug considering they can be used elsewhere, and I couldn't find any other issues about this. If I declare a constant sized array in a function with a let statement it works as expected.
Describe alternatives you've considered Find and replacing does work, but it seems weird to only have to do it for struct definitions; this would be more convenient.
Additional context wgpu version is 24.0.1
Thanks for adding more support for them recently!
We think the WGSL spec doesn't actually support override-sized arrays in structs... right???
Marking "out of scope" for Firefox's purposes, but if you think this is wrong, please let us know.
After looking into it, I believe you're correct. It says that arrays in structs must have a "creation-fixed footprint", which means it must have "a size that is fully determined at shader creation time". And override declarations are fixed at pipeline creation time, which is after shader creation time, so later than they'd need to be fixed. Considering that, I think it's perfectly reasonable to leave it as is, it would just be convenient to have a method to recreate the shader to change a struct. Assuming this is not implemented, I think a more clear error would be nice, like "Type array<u32, TEST> does not have a creation-fixed footprint, but is used in a struct". Although it seems like naga's error reporting could use other improvement first. Thanks for the response!
Moving this to a diagnostics issue then :)
We think the WGSL spec doesn't actually support override-sized arrays in structs... right???
After looking into it, I believe you're correct. It says that arrays in structs must have a "creation-fixed footprint", which means it must have "a size that is fully determined at shader creation time". And override declarations are fixed at pipeline creation time, which is after shader creation time, so later than they'd need to be fixed.
Regardless of whether WebGPU requires that array lengths be resolved to constants (and not overrides) at shader creation time, which is clearly problematic, this does not mean that WGSL doesn't support representing them.
The primary use case for specialized array lengths is variables in the workgroup address space. Overriding this at runtime offers greater flexibility and reduces compile time and bloat that would be added compiling several similar shaders.
While this may not be relevant for Firefox if WebGPU requires array lengths to be resolved prior to shader creation time, it is useful for applications using wgpu or naga to validate, override, or convert their shaders, whether natively or on the web. Since naga does support overriding constants, it is inconsistent to error when consuming overridable array lengths in the spirv frontend, simply because WebGPU forces these to be resolved at shader creation time.