continue_forward.rs |
Workarounds for platform bugs and limitations in switches and loops.
In these docs, we use CamelCase links for Naga IR concepts, and ordinary
`code` formatting for HLSL or GLSL concepts.
## Avoiding `continue` within `switch`
As described in <https://github.com/gfx-rs/wgpu/issues/4485>, the FXC HLSL
compiler doesn't allow `continue` statements within `switch` statements, but
Naga IR does. We work around this by introducing synthetic boolean local
variables and branches.
Specifically:
- We generate code for [`Continue`] statements within [`SwitchCase`]s that
sets an introduced `bool` local to `true` and does a `break`, jumping to
immediately after the generated `switch`.
- When generating code for a [`Switch`] statement, we conservatively assume
it might contain such a [`Continue`] statement, so:
- If it's the outermost such [`Switch`] within a [`Loop`], we declare the
`bool` local ahead of the switch, initialized to `false`. Immediately
after the `switch`, we check the local and do a `continue` if it's set.
- If the [`Switch`] is nested within other [`Switch`]es, then after the
generated `switch`, we check the local (which we know was declared
before the surrounding `switch`) and do a `break` if it's set.
- As an optimization, we only generate the check of the local if a
[`Continue`] statement is encountered within the [`Switch`]. This may
help drivers more easily identify that the `bool` is unused.
So while we "weaken" the [`Continue`] statement by rendering it as a `break`
statement, we also place checks immediately at the locations to which those
`break` statements will jump, until we can be sure we've reached the
intended target of the original [`Continue`].
In the case of nested [`Loop`] and [`Switch`] statements, there may be
multiple introduced `bool` locals in scope, but there's no problem knowing
which one to operate on. At any point, there is at most one [`Loop`]
statement that could be targeted by a [`Continue`] statement, so the correct
`bool` local to set and test is always the one introduced for the innermost
enclosing [`Loop`]'s outermost [`Switch`].
# Avoiding single body `switch` statements
As described in <https://github.com/gfx-rs/wgpu/issues/4514>, some language
front ends miscompile `switch` statements where all cases branch to the same
body. Our HLSL and GLSL backends render [`Switch`] statements with a single
[`SwitchCase`] as `do {} while(false);` loops.
However, this rewriting introduces a new loop that could "capture"
`continue` statements in its body. To avoid doing so, we apply the
[`Continue`]-to-`break` transformation described above.
[`Continue`]: crate::Statement::Continue
[`Loop`]: crate::Statement::Loop
[`Switch`]: crate::Statement::Switch
[`SwitchCase`]: crate::SwitchCase |
12721 |
dot |
|
|
glsl |
|
|
hlsl |
|
|
mod.rs |
!
Backend functions that export shader [`Module`](super::Module)s into binary and text formats.
|
11287 |
msl |
|
|
pipeline_constants.rs |
|
36666 |
spv |
|
|
wgsl |
|
|