-
Notifications
You must be signed in to change notification settings - Fork 969
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
Workaround shader compiler bugs with degenerate switch statements #5654
Conversation
I guess this is one of the nested test cases I added. |
4c594bc
to
d8a33e9
Compare
d8a33e9
to
a90271e
Compare
Found minimal case #5658 and was able to avoid the issue here without affecting the aspects I was trying to test. |
631ee78
to
4666d96
Compare
4666d96
to
9b9630d
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.
Wgpu side looks amazing, minus a nit
9b9630d
to
ce64106
Compare
Let me know if/when conflicts need to be fixed. |
@Imberflur Started reviewing this. My impression so far is that this is excellent work. I especially appreciate the execution tests and the docs. |
@Imberflur Could you check out the docs I just pushed in |
It seems like this needs a rebase. edit: I did the rebase. |
4c10a41
to
e66cbe1
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.
The new docs look great! Thanks for adding them.
I included one note for consideration.
P.S. The "forwarding" terminology is somewhat ad hoc, so feel free to suggest something else (like "deferring") if you have opinions there.
I'm somewhat curious about what conflicts came up in the rebase (in the interest of double checking them). But I can always re-run the rebase locally to find them. |
Only the absence of a |
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 looks great, and I think it's correct, but I'd like to see it simplified in two ways:
-
Don't bother counting nesting depth; just always push/pop new entries on the stack. It took me a bit to realize that the depth counters were just an optimization, not something that actually affected the code generated.
-
Eliminate
ContinueCtx::next_id
, letenter_switch
take a&mut Namer
argument, and just use the namer to generate unique names directly. It took me a while to be sure that the names you were generating couldn't conflict; if the code just uses the namer, then that question won't even arise.This means that
Nesting::Switch
will need to actually own theString
. I think it will need to be anRc<String>
, both so that nestedSwitch
variants can share it, and also so thatexit_switch
can return it regardless of whether it's been popped.ExitControl
flow will need to hold a clone of theString
.
I played with having the HLSL and GLSL writers just save the current nesting state in a local variable, and restore it on exit, so you could replace |
@Imberflur The only other suggestion I might have - and maybe this is just too hairy to be worth it - is that we might put a flag in |
Oh that sounds great! I didn't realize there was a mechanism for this. |
43c54ab
to
5c0bb2e
Compare
@jimblandy I implemented suggestions:
|
5c0bb2e
to
4a3828d
Compare
4a3828d
to
c54a7fc
Compare
Introduce a new module, `naga::back::continue_forward`, containing shared code for rendering Naga `Continue` statements as backend `break` statements and assignments to introduced `bool` locals. See the module's documentation for details. - [hlsl-out] Transform degenerate single body switches into `do-while` loops. Properly render `Continue` statements enclosed by `Switch` statements enclosed by `Loop` statements. - [glsl-out] Transform degenerate single body switches into `do-while` loops. Improve `naga xtask validate spv` error message. Fixes gfx-rs#4485. Fixes gfx-rs#4514.
c54a7fc
to
bce01db
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.
Okay, I fiddled with the docs some more, and cleaned up a bit of the control flow, and I think this ready to land.
Thanks! |
Connections
Fixes #4514
Fixes #4485
Description
As discussed in #4485, FXC has a bug when handling switches with all cases leading to one body (it deletes the switch). It was also mentioned that some glsl consumers might not handle this scenario well either (but I don't know which ones that might be).
So we lower these to
do {} while(false);
loops in hlsl-out and glsl-out.While FXC already can't handle continue statements in switches (see #4485), I ended up including logic to properly forward continue statements to the outer loop here, since there would otherwise be regressions in glsl-out and maybe hlsl-out with DXC.
An alternative solution could be to switch on a known constant and have a dummy case with an empty body that is never hit. This is a bit less cautious in terms of avoiding potential compiler bugs since we are still switching on a constant. But the implementation would be simpler and the only issues I have observed so far with FXC are when all cases lead to a single body.
Testing
Some of these scenarios are already covered by existing naga snapshot tests, I extended
naga/tests/in/control-flow.wgsl
with a few more cases.I also included some regression tests for the linked issues that will execute the shaders and assert on their output. Additionally, a new mechanism is introduced into the test framework for forcing the usage of FXC when on the Dx12 backend.
I ran
cargo xtask test
on a windows machine and a separate linux machine.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.