mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
If it is undefined behaviour for loops to be infinite, then, when encountering an infinite loop, downstream compilers are able to make certain optimizations that may be unsafe. For example, omitting bounds checks. To prevent this, we must ensure that any loops emitted by our backends are provably bounded. We already do this for both the MSL and HLSL backends. This patch makes us do so for SPIRV as well. The construct used is the same as for HLSL and MSL backends: use a vec2<u32> to emulate a 64-bit counter, which is incremented every iteration and breaks after 2^64 iterations. While the implementation is fairly verbose for the SPIRV backend, the logic is simple enough. The one point of note is that SPIRV requires `OpVariable` instructions with a `Function` storage class to be located at the start of the first block of the function. We therefore remember the IDs generated for each loop counter variable in a function whilst generating the function body's code. The instructions to declare these variables are then emitted in `Function::to_words()` prior to emitting the function's body. As this may negatively impact shader performance, this workaround can be disabled using the same mechanism as for other backends: eg calling Device::create_shader_module_trusted() and setting the ShaderRuntimeChecks::force_loop_bounding flag to false.