diff --git a/src/back/glsl/mod.rs b/src/back/glsl/mod.rs index de0d83febf..19302f790e 100644 --- a/src/back/glsl/mod.rs +++ b/src/back/glsl/mod.rs @@ -2580,6 +2580,18 @@ impl<'a, W: Write> Writer<'a, W> { write!(self.out, ")")?; } + // TODO: handle undefined behavior of BinaryOperator::Modulo + // + // sint: + // if right == 0 return 0 + // if left == min(type_of(left)) && right == -1 return 0 + // if sign(left) == -1 || sign(right) == -1 return result as defined by WGSL + // + // uint: + // if right == 0 return 0 + // + // float: + // if right == 0 return ? see https://github.com/gpuweb/gpuweb/issues/2798 BinaryOperation::Modulo => { write!(self.out, "(")?; diff --git a/src/back/hlsl/writer.rs b/src/back/hlsl/writer.rs index 3701d0002a..2c1837761d 100644 --- a/src/back/hlsl/writer.rs +++ b/src/back/hlsl/writer.rs @@ -1795,6 +1795,20 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { self.write_expr(module, left, func_ctx)?; write!(self.out, ")")?; } + + // TODO: handle undefined behavior of BinaryOperator::Modulo + // + // sint: + // if right == 0 return 0 + // if left == min(type_of(left)) && right == -1 return 0 + // if sign(left) != sign(right) return result as defined by WGSL + // + // uint: + // if right == 0 return 0 + // + // float: + // if right == 0 return ? see https://github.com/gpuweb/gpuweb/issues/2798 + // While HLSL supports float operands with the % operator it is only // defined in cases where both sides are either positive or negative. Expression::Binary { diff --git a/src/back/msl/writer.rs b/src/back/msl/writer.rs index 3448d0c002..2dd256afb8 100644 --- a/src/back/msl/writer.rs +++ b/src/back/msl/writer.rs @@ -1482,6 +1482,20 @@ impl Writer { .resolve_type(left) .scalar_kind() .ok_or(Error::UnsupportedBinaryOp(op))?; + + // TODO: handle undefined behavior of BinaryOperator::Modulo + // + // sint: + // if right == 0 return 0 + // if left == min(type_of(left)) && right == -1 return 0 + // if sign(left) == -1 || sign(right) == -1 return result as defined by WGSL + // + // uint: + // if right == 0 return 0 + // + // float: + // if right == 0 return ? see https://github.com/gpuweb/gpuweb/issues/2798 + if op == crate::BinaryOperator::Modulo && kind == crate::ScalarKind::Float { write!(self.out, "{}::fmod(", NAMESPACE)?; self.put_expression(left, context, true)?; diff --git a/src/back/spv/block.rs b/src/back/spv/block.rs index d492ddf53c..d302811db3 100644 --- a/src/back/spv/block.rs +++ b/src/back/spv/block.rs @@ -529,8 +529,15 @@ impl<'w> BlockContext<'w> { _ => unimplemented!(), }, crate::BinaryOperator::Modulo => match left_ty_inner.scalar_kind() { + // TODO: handle undefined behavior + // if right == 0 return 0 + // if left == min(type_of(left)) && right == -1 return 0 Some(crate::ScalarKind::Sint) => spirv::Op::SRem, + // TODO: handle undefined behavior + // if right == 0 return 0 Some(crate::ScalarKind::Uint) => spirv::Op::UMod, + // TODO: handle undefined behavior + // if right == 0 return ? see https://github.com/gpuweb/gpuweb/issues/2798 Some(crate::ScalarKind::Float) => spirv::Op::FRem, _ => unimplemented!(), },