mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
glsl-in: Fix last case falltrough and empty switch
GLSL allows the last case of a switch statement to not have a `break` statement causing it to be marked as fall-trough, naga's IR on the other hand doesn't allow the last case to be fall-trough, this is fixed by force marking it in the glsl frontend as not fall-trough. GLSL also allows empty switch statements and without default cases, naga's IR requires there be a default case, this is fixed by adding an empty default case in the glsl frontend if no default case was present in the switch statement.
This commit is contained in:
@@ -177,6 +177,8 @@ impl<'source> ParsingContext<'source> {
|
||||
ctx.emit_restart(body);
|
||||
|
||||
let mut cases = Vec::new();
|
||||
// Track if any default case is present in the switch statement.
|
||||
let mut default_present = false;
|
||||
|
||||
self.expect(parser, TokenValue::LeftBrace)?;
|
||||
loop {
|
||||
@@ -215,6 +217,7 @@ impl<'source> ParsingContext<'source> {
|
||||
}
|
||||
TokenValue::Default => {
|
||||
self.bump(parser)?;
|
||||
default_present = true;
|
||||
crate::SwitchValue::Default
|
||||
}
|
||||
TokenValue::RightBrace => {
|
||||
@@ -273,6 +276,28 @@ impl<'source> ParsingContext<'source> {
|
||||
|
||||
meta.subsume(end_meta);
|
||||
|
||||
// GLSL allows the last case to not have any `break` statement,
|
||||
// this would mark it as fall trough but naga's IR requires that
|
||||
// the last case must not be fall trough, so we mark need to mark
|
||||
// the last case as not fall trough always.
|
||||
//
|
||||
// NOTE: do not unwrap here since a switch statement isn't required
|
||||
// to have any cases.
|
||||
if let Some(case) = cases.last_mut() {
|
||||
case.fall_through = false;
|
||||
}
|
||||
|
||||
// Add an empty default case in case non was present, this is needed because
|
||||
// naga's IR requires that all switch statements must have a default case but
|
||||
// GLSL doesn't require that, so we might need to add an empty default case.
|
||||
if !default_present {
|
||||
cases.push(SwitchCase {
|
||||
value: crate::SwitchValue::Default,
|
||||
body: Block::new(),
|
||||
fall_through: false,
|
||||
})
|
||||
}
|
||||
|
||||
body.push(Statement::Switch { selector, cases }, meta);
|
||||
|
||||
meta
|
||||
|
||||
27
tests/in/glsl/statements.frag
Normal file
27
tests/in/glsl/statements.frag
Normal file
@@ -0,0 +1,27 @@
|
||||
#version 460 core
|
||||
|
||||
void switchEmpty(int a) {
|
||||
switch (a) {}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void switchNoDefault(int a) {
|
||||
switch (a) {
|
||||
case 0:
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void switchNoLastBreak(int a) {
|
||||
switch (a) {
|
||||
default:
|
||||
int b = a;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void main() {}
|
||||
50
tests/out/wgsl/statements-frag.wgsl
Normal file
50
tests/out/wgsl/statements-frag.wgsl
Normal file
@@ -0,0 +1,50 @@
|
||||
fn switchEmpty(a: i32) {
|
||||
var a_1: i32;
|
||||
|
||||
a_1 = a;
|
||||
let _e2 = a_1;
|
||||
switch _e2 {
|
||||
default: {
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
fn switchNoDefault(a_2: i32) {
|
||||
var a_3: i32;
|
||||
|
||||
a_3 = a_2;
|
||||
let _e2 = a_3;
|
||||
switch _e2 {
|
||||
case 0: {
|
||||
}
|
||||
default: {
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
fn switchNoLastBreak(a_4: i32) {
|
||||
var a_5: i32;
|
||||
var b: i32;
|
||||
|
||||
a_5 = a_4;
|
||||
let _e2 = a_5;
|
||||
switch _e2 {
|
||||
default: {
|
||||
let _e3 = a_5;
|
||||
b = _e3;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
fn main_1() {
|
||||
return;
|
||||
}
|
||||
|
||||
@fragment
|
||||
fn main() {
|
||||
main_1();
|
||||
return;
|
||||
}
|
||||
Reference in New Issue
Block a user