diff --git a/src/front/glsl/parser/functions.rs b/src/front/glsl/parser/functions.rs index 8a9487917b..549b73045b 100644 --- a/src/front/glsl/parser/functions.rs +++ b/src/front/glsl/parser/functions.rs @@ -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 diff --git a/tests/in/glsl/statements.frag b/tests/in/glsl/statements.frag new file mode 100644 index 0000000000..c9e276c87b --- /dev/null +++ b/tests/in/glsl/statements.frag @@ -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() {} diff --git a/tests/out/wgsl/statements-frag.wgsl b/tests/out/wgsl/statements-frag.wgsl new file mode 100644 index 0000000000..b799959320 --- /dev/null +++ b/tests/out/wgsl/statements-frag.wgsl @@ -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; +}