HLSL backend: work around FXC ignoring switch with only default case

In HLSL code, if a switch statement has only a default case, FXC will
effectively ignore the code in that case. In this change, we detect this
and work around it by emitting the code in the default block without the
switch.

Bug: tint:1188
Change-Id: I69b405cdb4c669fb093eb49aa138923419dcf8f8
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/68440
Kokoro: Antonio Maiorano <amaiorano@google.com>
Commit-Queue: Antonio Maiorano <amaiorano@google.com>
Reviewed-by: Ben Clayton <bclayton@chromium.org>
This commit is contained in:
Antonio Maiorano
2021-11-05 20:39:07 +00:00
committed by Tint LUCI CQ
parent 189dc7d3fd
commit 02acf59184
18 changed files with 278 additions and 17 deletions

View File

@@ -0,0 +1,20 @@
[[stage(compute), workgroup_size(1)]]
fn f() {
var i : i32;
var result : i32;
switch(i) {
case 0: {
result = 10;
}
case 1: {
result = 22;
}
case 2: {
result = 33;
}
default: {
result = 44;
break;
}
}
}

View File

@@ -0,0 +1,24 @@
[numthreads(1, 1, 1)]
void f() {
int i = 0;
int result = 0;
switch(i) {
case 0: {
result = 10;
break;
}
case 1: {
result = 22;
break;
}
case 2: {
result = 33;
break;
}
default: {
result = 44;
break;
}
}
return;
}

View File

@@ -0,0 +1,27 @@
#include <metal_stdlib>
using namespace metal;
kernel void f() {
int i = 0;
int result = 0;
switch(i) {
case 0: {
result = 10;
break;
}
case 1: {
result = 22;
break;
}
case 2: {
result = 33;
break;
}
default: {
result = 44;
break;
}
}
return;
}

View File

@@ -0,0 +1,43 @@
; SPIR-V
; Version: 1.3
; Generator: Google Tint Compiler; 0
; Bound: 20
; Schema: 0
OpCapability Shader
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %f "f"
OpExecutionMode %f LocalSize 1 1 1
OpName %f "f"
OpName %i "i"
OpName %result "result"
%void = OpTypeVoid
%1 = OpTypeFunction %void
%int = OpTypeInt 32 1
%_ptr_Function_int = OpTypePointer Function %int
%8 = OpConstantNull %int
%int_10 = OpConstant %int 10
%int_22 = OpConstant %int 22
%int_33 = OpConstant %int 33
%int_44 = OpConstant %int 44
%f = OpFunction %void None %1
%4 = OpLabel
%i = OpVariable %_ptr_Function_int Function %8
%result = OpVariable %_ptr_Function_int Function %8
%11 = OpLoad %int %i
OpSelectionMerge %10 None
OpSwitch %11 %12 0 %13 1 %14 2 %15
%13 = OpLabel
OpStore %result %int_10
OpBranch %10
%14 = OpLabel
OpStore %result %int_22
OpBranch %10
%15 = OpLabel
OpStore %result %int_33
OpBranch %10
%12 = OpLabel
OpStore %result %int_44
OpBranch %10
%10 = OpLabel
OpReturn
OpFunctionEnd

View File

@@ -0,0 +1,20 @@
[[stage(compute), workgroup_size(1)]]
fn f() {
var i : i32;
var result : i32;
switch(i) {
case 0: {
result = 10;
}
case 1: {
result = 22;
}
case 2: {
result = 33;
}
default: {
result = 44;
break;
}
}
}

View File

@@ -0,0 +1,12 @@
[[stage(compute), workgroup_size(1)]]
fn f() {
var i : i32;
switch(i) {
case 0: {
fallthrough;
}
default: {
break;
}
}
}

View File

@@ -0,0 +1,16 @@
[numthreads(1, 1, 1)]
void f() {
int i = 0;
switch(i) {
case 0: {
/* fallthrough */
{
break;
}
}
default: {
break;
}
}
return;
}

View File

@@ -0,0 +1,16 @@
#include <metal_stdlib>
using namespace metal;
kernel void f() {
int i = 0;
switch(i) {
case 0: {
/* fallthrough */
}
default: {
break;
}
}
return;
}

View File

@@ -0,0 +1,29 @@
; SPIR-V
; Version: 1.3
; Generator: Google Tint Compiler; 0
; Bound: 13
; Schema: 0
OpCapability Shader
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %f "f"
OpExecutionMode %f LocalSize 1 1 1
OpName %f "f"
OpName %i "i"
%void = OpTypeVoid
%1 = OpTypeFunction %void
%int = OpTypeInt 32 1
%_ptr_Function_int = OpTypePointer Function %int
%8 = OpConstantNull %int
%f = OpFunction %void None %1
%4 = OpLabel
%i = OpVariable %_ptr_Function_int Function %8
%10 = OpLoad %int %i
OpSelectionMerge %9 None
OpSwitch %10 %11 0 %12
%12 = OpLabel
OpBranch %11
%11 = OpLabel
OpBranch %9
%9 = OpLabel
OpReturn
OpFunctionEnd

View File

@@ -0,0 +1,12 @@
[[stage(compute), workgroup_size(1)]]
fn f() {
var i : i32;
switch(i) {
case 0: {
fallthrough;
}
default: {
break;
}
}
}

View File

@@ -0,0 +1,11 @@
[[stage(compute), workgroup_size(1)]]
fn f() {
var i : i32;
var result : i32;
switch(i) {
default: {
result = 44;
break;
}
}
}

View File

@@ -0,0 +1,11 @@
[numthreads(1, 1, 1)]
void f() {
int i = 0;
int result = 0;
i;
do {
result = 44;
break;
} while (false);
return;
}

View File

@@ -0,0 +1,15 @@
#include <metal_stdlib>
using namespace metal;
kernel void f() {
int i = 0;
int result = 0;
switch(i) {
default: {
result = 44;
break;
}
}
return;
}

View File

@@ -0,0 +1,31 @@
; SPIR-V
; Version: 1.3
; Generator: Google Tint Compiler; 0
; Bound: 14
; Schema: 0
OpCapability Shader
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %f "f"
OpExecutionMode %f LocalSize 1 1 1
OpName %f "f"
OpName %i "i"
OpName %result "result"
%void = OpTypeVoid
%1 = OpTypeFunction %void
%int = OpTypeInt 32 1
%_ptr_Function_int = OpTypePointer Function %int
%8 = OpConstantNull %int
%int_44 = OpConstant %int 44
%f = OpFunction %void None %1
%4 = OpLabel
%i = OpVariable %_ptr_Function_int Function %8
%result = OpVariable %_ptr_Function_int Function %8
%11 = OpLoad %int %i
OpSelectionMerge %10 None
OpSwitch %11 %12
%12 = OpLabel
OpStore %result %int_44
OpBranch %10
%10 = OpLabel
OpReturn
OpFunctionEnd

View File

@@ -0,0 +1,11 @@
[[stage(compute), workgroup_size(1)]]
fn f() {
var i : i32;
var result : i32;
switch(i) {
default: {
result = 44;
break;
}
}
}