Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[naga] Permit only structs as binding array elements. #6333

Merged

Conversation

jimblandy
Copy link
Member

Require T to be a struct in binding_array<T, ...>; do not permit arrays.

In #5428, the validator was changed to accept binding array types that the SPIR-V backend couldn't properly emit. Specifically, the validator was changed to accept binding_array<array<T>>, but the SPIR-V backend wasn't changed to wrap the binding array elements in a SPIR-V struct type, as Vulkan requires. So the type would be accepted by the validator, and then rejected by the backend.

Require `T` to be a struct in `binding_array<T, ...>`; do not permit
arrays.

In gfx-rs#5428, the validator was changed to accept binding array types that
the SPIR-V backend couldn't properly emit. Specifically, the validator
was changed to accept `binding_array<array<T>>`, but the SPIR-V
backend wasn't changed to wrap the binding array elements in a SPIR-V
struct type, as Vulkan requires. So the type would be accepted by the
validator, and then rejected by the backend.
@jimblandy jimblandy requested a review from a team as a code owner September 27, 2024 00:39
@jimblandy jimblandy added area: validation Issues related to validation, diagnostics, and error handling naga Shader Translator type: bug Something isn't working labels Sep 27, 2024
jimblandy added a commit to jimblandy/wgpu that referenced this pull request Sep 27, 2024
Document and refactor
`naga::back::spv::BlockContext::write_runtime_array_length`.

Don't try to handle finding the length of a particular element of a
`binding_array<array<T>>`. The SPIR-V backend doesn't wrap that type
correctly anyway; gfx-rs#6333 changes the validator to forbid such types.
Instead, assume that the elements of a `binding_array<T>` are always
structs whose final members may be a runtime-sized array.

Pull out consistency checks after the analysis of the array
expression, so that we always carry out all the checks regardless of
what path we took to produce the information.
jimblandy added a commit to jimblandy/wgpu that referenced this pull request Sep 27, 2024
Document and refactor
`naga::back::spv::BlockContext::write_runtime_array_length`.

Don't try to handle finding the length of a particular element of a
`binding_array<array<T>>`. The SPIR-V backend doesn't wrap that type
correctly anyway; gfx-rs#6333 changes the validator to forbid such types.
Instead, assume that the elements of a `binding_array<T>` are always
structs whose final members may be a runtime-sized array.

Pull out consistency checks after the analysis of the array
expression, so that we always carry out all the checks regardless of
what path we took to produce the information.
@ErichDonGubler
Copy link
Member

CC @teoxoy as reviewer and @kvark as author of the regressor being fixed here.

Copy link
Member

@ErichDonGubler ErichDonGubler left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

question: Are there plans in the future to relax this restriction, since the OP implies it's possible?

@JMS55
Copy link
Contributor

JMS55 commented Sep 27, 2024

Wait, so can you no longer do binding_array<array<T>>? That's very unfortunate. I was using that with ray tracing (soon to be merged...) to bind multiple vertex data buffers easily. I can switch to a single uberbuffer of all mesh data, but it's a lot more annoying to manage.

jimblandy added a commit to jimblandy/wgpu that referenced this pull request Sep 27, 2024
Document and refactor
`naga::back::spv::BlockContext::write_runtime_array_length`.

Don't try to handle finding the length of a particular element of a
`binding_array<array<T>>`. The SPIR-V backend doesn't wrap that type
correctly anyway; gfx-rs#6333 changes the validator to forbid such types.
Instead, assume that the elements of a `binding_array<T>` are always
structs whose final members may be a runtime-sized array.

Pull out consistency checks after the analysis of the array
expression, so that we always carry out all the checks regardless of
what path we took to produce the information.
jimblandy added a commit to jimblandy/wgpu that referenced this pull request Sep 27, 2024
Document and refactor
`naga::back::spv::BlockContext::write_runtime_array_length`.

Don't try to handle finding the length of a particular element of a
`binding_array<array<T>>`. The SPIR-V backend doesn't wrap that type
correctly anyway; gfx-rs#6333 changes the validator to forbid such types.
Instead, assume that the elements of a `binding_array<T>` are always
structs whose final members may be a runtime-sized array.

Pull out consistency checks after the analysis of the array
expression, so that we always carry out all the checks regardless of
what path we took to produce the information.
jimblandy added a commit to jimblandy/wgpu that referenced this pull request Sep 27, 2024
Document and refactor
`naga::back::spv::BlockContext::write_runtime_array_length`.

Don't try to handle finding the length of a particular element of a
`binding_array<array<T>>`. The SPIR-V backend doesn't wrap that type
correctly anyway; gfx-rs#6333 changes the validator to forbid such types.
Instead, assume that the elements of a `binding_array<T>` are always
structs whose final members may be a runtime-sized array.

Pull out consistency checks after the analysis of the array
expression, so that we always carry out all the checks regardless of
what path we took to produce the information.
@jimblandy
Copy link
Member Author

@JMS55 wrote:

Wait, so can you no longer do binding_array<array<T>>? That's very unfortunate. I was using that with ray tracing (soon to be merged...) to bind multiple vertex data buffers easily. I can switch to a single uberbuffer of all mesh data, but it's a lot more annoying to manage.

I'm confused. That has never worked:

$ cat in.wgsl
@group(0) @binding(0)
var<storage> a: binding_array<array<u32>>;

fn f(i: i32, j: i32) -> u32 {
   return a[i][j];
}
$ naga in.wgsl out.spv
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.11s
     Running `/home/jimb/rust/wgpu/target/debug/naga in.wgsl out.spv`
$ spirv-val out.spv
error: line 16: Block decoration on target <id> '4[%_runtimearr_uint]' must be a structure type
  OpDecorate %_runtimearr_uint Block

$ 

As the commit message and PR message explains, Naga fails to wrap the array<u32> in a struct, so this doesn't validate.

And this restriction is easy to work around: just put the runtime-sized array in a struct in the WGSL:

$ cat fixed.wgsl
struct S {
  arr: array<u32>,
}

@group(0) @binding(0)
var<storage> a: binding_array<S>;

fn f(i: i32, j: i32) -> u32 {
   return a[i].arr[j];
}
$ naga fixed.wgsl fixed.spv
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.11s
     Running `/home/jimb/rust/wgpu/target/debug/naga fixed.wgsl fixed.spv`
$ spirv-val fixed.spv
$ 

@JMS55
Copy link
Contributor

JMS55 commented Sep 27, 2024

Oh I see, yeah wrapping it in a struct is what I was doing. Didn't realize that still worked, thanks!

@jimblandy jimblandy merged commit 98c4d6f into gfx-rs:trunk Sep 28, 2024
27 checks passed
@jimblandy jimblandy deleted the naga-binding-array-element-type-validation branch September 28, 2024 00:00
jimblandy added a commit that referenced this pull request Sep 28, 2024
Document and refactor
`naga::back::spv::BlockContext::write_runtime_array_length`.

Don't try to handle finding the length of a particular element of a
`binding_array<array<T>>`. The SPIR-V backend doesn't wrap that type
correctly anyway; #6333 changes the validator to forbid such types.
Instead, assume that the elements of a `binding_array<T>` are always
structs whose final members may be a runtime-sized array.

Pull out consistency checks after the analysis of the array
expression, so that we always carry out all the checks regardless of
what path we took to produce the information.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: validation Issues related to validation, diagnostics, and error handling naga Shader Translator type: bug Something isn't working
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

3 participants