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
Allow unconsumed inputs in fragment shaders #5531
base: trunk
Are you sure you want to change the base?
Conversation
1ed945e
to
f226525
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here are some questions and notes for reviewers.
naga/src/back/hlsl/writer.rs
Outdated
// TODO: log error if binding is none? | ||
// technically, this should always be `Some` | ||
binding: Option<crate::Binding>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a note to remind myself here and in several places below.
Should this log an error? Are there cases where we actually expect None
?
I can:
- Remove these notes if logging isn't desired.
- Otherwise, add some logging (and remove notes).
- Or, remove notes and defer question/implementation to a separate issue/PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm adding a debug_assert!(member.binding.is_some())
into write_interface_struct
naga/src/back/hlsl/writer.rs
Outdated
TypeInner::Struct { ref members, .. } => { | ||
// TODO: what about nested structs? Is that possible? Maybe try an unwrap on | ||
// the binding? | ||
for member in members.iter() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like I saw something about it being possible to nest structs here. Is this possible? Should we open an issue for handling that? I could also attempt handling it in this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You cannot nest - should probably note this in the code
Each user-defined input and output must have an explicitly specified IO location. Each structure member in the entry point IO must be one of either a built-in value (see § 12.3.1.1 Built-in Inputs and Outputs), or assigned a location.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And looks like this is checked when validating the Module
by VaryingContext::validate
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This also implies that binding
is always Some
... I'm tempted to add at least a debug assertion for this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a note
// Uses separate wgsl files to make sure the tested code doesn't accidentally rely on | ||
// the fragment entry point being from the same parsed content (e.g. accidentally using the | ||
// wrong `Module` when looking up info). We also don't just create a module from the same file | ||
// twice since everything would probably be stored behind the same keys. | ||
let (input, mut module) = load_and_parse("unconsumed_vertex_outputs_vert"); | ||
let (frag_input, mut frag_module) = load_and_parse("unconsumed_vertex_outputs_frag"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding this was a bit awkward since it didn't align very well with the existing tests. I needed a new parameter on check_targets
. It looks like I could have added a new field to the Parameters
struct to specify the fragment entry point. However, I wanted to specifically test the case of the fragment shader being from a separate Module
.
c3caa2d
to
0a04bf3
Compare
Great to see work here! Marking un-draft so it gets added to the review queue |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wgpu side looks fine, added some comments some of the naga things
naga/src/back/hlsl/writer.rs
Outdated
TypeInner::Struct { ref members, .. } => { | ||
// TODO: what about nested structs? Is that possible? Maybe try an unwrap on | ||
// the binding? | ||
for member in members.iter() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You cannot nest - should probably note this in the code
Each user-defined input and output must have an explicitly specified IO location. Each structure member in the entry point IO must be one of either a built-in value (see § 12.3.1.1 Built-in Inputs and Outputs), or assigned a location.
9ae8bb7
to
3f11d08
Compare
outputs when generating HLSL. Fixes gfx-rs#3748 * Add naga::back::hlsl::FragmentEntryPoint for providing information about the fragment entry point when generating vertex entry points via naga::back::hlsl::Writer::write. Vertex outputs not consumed by the fragment entry point are omitted in the final output struct. * Add naga snapshot test for this new feature, * Remove Features::SHADER_UNUSED_VERTEX_OUTPUT, StageError::InputNotConsumed, and associated validation logic. * Make wgpu dx12 backend pass fragment shader info when generating vertex HLSL. * Add wgpu regression test for allowing unconsumed inputs.
3f11d08
to
03f0bba
Compare
* Add note that nesting structs for the inter-stage interface can't happen. * Remove new TODO notes (some addressed and some transferred to an issue gfx-rs#5577) * Changed issue that regression test refers to 3748 -> 5553 * Add debug_assert that binding.is_some() in hlsl writer * Fix typos caught in CI Also, fix compiling snapshot test when hlsl-out feature is not enabled.
03f0bba
to
de5faaf
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just clearing from my review queue, need someone from naga to look at this
By removing them from vertex outputs when generating HLSL.
naga::back::hlsl::FragmentEntryPoint
for providing information about the fragment entry point when generating vertex entry points vianaga::back::hlsl::Writer::write
. Vertex outputs not consumed by the fragment entry point are omitted in the final output struct.naga
snapshot test for this new feature,Features::SHADER_UNUSED_VERTEX_OUTPUT
,StageError::InputNotConsumed
, and associated validation logic.Connections
Fixes #3748
Description
My case affected by this is passing in SPIRV from
shaderc
which can optimize out unused inputs from the fragment shader. The shaders are dynamically configured with a pre-processor based on various settings from the user so it can be hard to predict when certain inter-stage variables are unused, and my attempt at configuring out particular outputs from vertex shaders quickly became overly verbose.As noted in the linked issue, this validation was originally in the WebGPU spec but was removed. The validation was necessary for generating HLSL with matching inter-stage interfaces but we can work around that by adjusting the HLSL generation to account for any unconsumed inputs.
After investigating this I found two potential ways to account for this in the generated HLSL:
I went with the second option since it seemed simpler to implement than generating new fields and nicely removed unnecessary work passing unused values (although I assume drivers can probably optimize this out).
Note: This is a breaking change.
Testing
I added a test to for whether the wgpu validation logic now allows unconsumed inputs and a naga snapshot test for removing the unconsumed vertex outputs when generating HLSL.
I have not tested on a windows machine with the dx12 backend!So here are some testing TODOs:cargo xtask test
on machine with dx12.Checklist
cargo fmt
.cargo clippy
. If applicable, add:--target wasm32-unknown-unknown
--target wasm32-unknown-emscripten
cargo xtask test
to run tests.CHANGELOG.md
. See simple instructions inside file.