diff --git a/src/front/glsl/context.rs b/src/front/glsl/context.rs index dd2f738747..fa29b5ceb9 100644 --- a/src/front/glsl/context.rs +++ b/src/front/glsl/context.rs @@ -418,6 +418,69 @@ impl Context { Ok((expr, meta)) } + fn lower_store( + &mut self, + pointer: Handle, + value: Handle, + meta: Span, + body: &mut Block, + ) { + if let Expression::Swizzle { + size, + mut vector, + pattern, + } = self.expressions[pointer] + { + // Stores to swizzled values are not directly supported, + // lower them as series of per-component stores. + let size = match size { + VectorSize::Bi => 2, + VectorSize::Tri => 3, + VectorSize::Quad => 4, + }; + + if let Expression::Load { pointer } = self.expressions[vector] { + vector = pointer; + } + + #[allow(clippy::needless_range_loop)] + for index in 0..size { + let dst = self.add_expression( + Expression::AccessIndex { + base: vector, + index: pattern[index].index(), + }, + meta, + body, + ); + let src = self.add_expression( + Expression::AccessIndex { + base: value, + index: index as u32, + }, + meta, + body, + ); + + self.emit_flush(body); + self.emit_start(); + + body.push( + Statement::Store { + pointer: dst, + value: src, + }, + meta, + ); + } + } else { + self.emit_flush(body); + self.emit_start(); + + body.push(Statement::Store { pointer, value }, meta); + } + } + /// Internal implementation of [`lower`](Self::lower) fn lower_inner( &mut self, @@ -694,68 +757,18 @@ impl Context { self.implicit_conversion(parser, &mut value, value_meta, kind, width)?; } - if let Expression::Swizzle { - size, - mut vector, - pattern, - } = self.expressions[pointer] - { - // Stores to swizzled values are not directly supported, - // lower them as series of per-component stores. - let size = match size { - VectorSize::Bi => 2, - VectorSize::Tri => 3, - VectorSize::Quad => 4, - }; - - if let Expression::Load { pointer } = self.expressions[vector] { - vector = pointer; - } - - #[allow(clippy::needless_range_loop)] - for index in 0..size { - let dst = self.add_expression( - Expression::AccessIndex { - base: vector, - index: pattern[index].index(), - }, - meta, - body, - ); - let src = self.add_expression( - Expression::AccessIndex { - base: value, - index: index as u32, - }, - meta, - body, - ); - - self.emit_flush(body); - self.emit_start(); - - body.push( - Statement::Store { - pointer: dst, - value: src, - }, - meta, - ); - } - } else { - self.emit_flush(body); - self.emit_start(); - - body.push(Statement::Store { pointer, value }, meta); - } + self.lower_store(pointer, value, meta, body); value } HirExprKind::PrePostfix { op, postfix, expr } if ExprPos::Lhs != pos => { - let pointer = self - .lower_expect_inner(stmt, parser, expr, ExprPos::Lhs, body)? - .0; - let left = self.add_expression(Expression::Load { pointer }, meta, body); + let (pointer, _) = + self.lower_expect_inner(stmt, parser, expr, ExprPos::Lhs, body)?; + let left = if let Expression::Swizzle { .. } = self.expressions[pointer] { + pointer + } else { + self.add_expression(Expression::Load { pointer }, meta, body) + }; let make_constant_inner = |kind, width| { let value = match kind { @@ -844,10 +857,7 @@ impl Context { let value = self.add_expression(Expression::Binary { op, left, right }, meta, body); - self.emit_flush(body); - self.emit_start(); - - body.push(Statement::Store { pointer, value }, meta); + self.lower_store(pointer, value, meta, body); if postfix { left diff --git a/tests/in/glsl/swizzle_write.frag b/tests/in/glsl/swizzle_write.frag index 9f11d7e5f3..a554c94e12 100644 --- a/tests/in/glsl/swizzle_write.frag +++ b/tests/in/glsl/swizzle_write.frag @@ -5,4 +5,5 @@ void main() { vec3 x = vec3(2.0); x.zxy.xy = vec2(3.0, 4.0); x.rg *= 5.0; + x.zy++; } diff --git a/tests/out/wgsl/swizzle_write-frag.wgsl b/tests/out/wgsl/swizzle_write-frag.wgsl index 81888740a2..48ca0a1996 100644 --- a/tests/out/wgsl/swizzle_write-frag.wgsl +++ b/tests/out/wgsl/swizzle_write-frag.wgsl @@ -10,6 +10,10 @@ fn main_1() { let _e18 = (_e15.xy * 5.0); x.x = _e18.x; x.y = _e18.y; + let _e23 = x; + let _e27 = (_e23.zy + vec2(1.0)); + x.z = _e27.x; + x.y = _e27.y; return; }