forked from daniel-keitel/wgpu
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[naga spv-out] Don't emit unreachable blocks that jump into loops.
When generating SPIR-V, avoid generating unreachable blocks following statements like `break`, `return`, and so on that cause non-local exits. These unreachable blocks can cause SPIR-V validation to fail. Fixes gfx-rs#6220.
- Loading branch information
Showing
5 changed files
with
176 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
( | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// #6220: Don't generate unreachable SPIR-V blocks that branch into | ||
// structured control flow constructs. | ||
// | ||
// Suppose we have Naga code like this: | ||
// | ||
// Block { | ||
// ... prelude | ||
// Block { ... nested } | ||
// ... postlude | ||
// } | ||
// | ||
// The SPIR-V back end used to always generate three separate SPIR-V | ||
// blocks for the sections labeled "prelude", "nested", and | ||
// "postlude", each block ending with a branch to the next, even if | ||
// they were empty. | ||
// | ||
// However, the function below generates code that includes the | ||
// following structure: | ||
// | ||
// Loop { | ||
// body: Block { | ||
// ... prelude | ||
// Block { Break } | ||
// ... postlude | ||
// } | ||
// continuing: ... | ||
// } | ||
// | ||
// In this case, even though the `Break` renders the "postlude" | ||
// unreachable, we used to generate a SPIR-V block for it anyway, | ||
// ending with a branch to the `Loop`'s "continuing" block. However, | ||
// SPIR-V's structured control flow rules forbid branches to a loop | ||
// construct's continue target from outside the loop, so the SPIR-V | ||
// module containing the unreachable block didn't pass validation. | ||
// | ||
// One might assume that unreachable blocks shouldn't affect | ||
// validation, but the spec doesn't clearly agree, and this doesn't | ||
// seem to be the way validation has been implemented. | ||
fn break_from_loop() { | ||
for (var i = 0; i < 4; i += 1) { | ||
break; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
; SPIR-V | ||
; Version: 1.1 | ||
; Generator: rspirv | ||
; Bound: 26 | ||
OpCapability Shader | ||
OpCapability Linkage | ||
%1 = OpExtInstImport "GLSL.std.450" | ||
OpMemoryModel Logical GLSL450 | ||
%2 = OpTypeVoid | ||
%3 = OpTypeInt 32 1 | ||
%6 = OpTypeFunction %2 | ||
%7 = OpConstant %3 0 | ||
%8 = OpConstant %3 4 | ||
%9 = OpConstant %3 1 | ||
%11 = OpTypePointer Function %3 | ||
%18 = OpTypeBool | ||
%5 = OpFunction %2 None %6 | ||
%4 = OpLabel | ||
%10 = OpVariable %11 Function %7 | ||
OpBranch %12 | ||
%12 = OpLabel | ||
OpBranch %13 | ||
%13 = OpLabel | ||
OpLoopMerge %14 %16 None | ||
OpBranch %15 | ||
%15 = OpLabel | ||
%17 = OpLoad %3 %10 | ||
%19 = OpSLessThan %18 %17 %8 | ||
OpSelectionMerge %20 None | ||
OpBranchConditional %19 %20 %21 | ||
%21 = OpLabel | ||
OpBranch %14 | ||
%20 = OpLabel | ||
OpBranch %22 | ||
%22 = OpLabel | ||
OpBranch %14 | ||
%16 = OpLabel | ||
%24 = OpLoad %3 %10 | ||
%25 = OpIAdd %3 %24 %9 | ||
OpStore %10 %25 | ||
OpBranch %13 | ||
%14 = OpLabel | ||
OpReturn | ||
OpFunctionEnd |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters