From 2fdc50b67790ba6e74bc0a5653456cf1f55f2cba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Capucho?= Date: Tue, 7 Jun 2022 17:06:11 +0100 Subject: [PATCH] glsl-out: Perform casts in int only math functions Some math functions in naga's IR support both signed and unsigned integers as arguments but only signed integers in GLSL, this was somewhat accounted for with casts of the result from int to uint. But the arguments weren't being cast from uint to int, causing illegal GLSL to be produced, this PR fixes it by also casting arguments. --- src/back/glsl/mod.rs | 68 ++++++++++++++++++++++++++++++-------------- 1 file changed, 46 insertions(+), 22 deletions(-) diff --git a/src/back/glsl/mod.rs b/src/back/glsl/mod.rs index 9e534df539..8764b7fbb3 100644 --- a/src/back/glsl/mod.rs +++ b/src/back/glsl/mod.rs @@ -2798,32 +2798,56 @@ impl<'a, W: Write> Writer<'a, W> { let extract_bits = fun == Mf::ExtractBits; let insert_bits = fun == Mf::InsertBits; - // we might need to cast to unsigned integers since - // GLSL's findLSB / findMSB always return signed integers - let need_extra_paren = { - (fun == Mf::FindLsb || fun == Mf::FindMsb || fun == Mf::CountOneBits) - && match *ctx.info[arg].ty.inner_with(&self.module.types) { - crate::TypeInner::Scalar { - kind: crate::ScalarKind::Uint, - .. - } => { - write!(self.out, "uint(")?; - true - } - crate::TypeInner::Vector { - kind: crate::ScalarKind::Uint, - size, - .. - } => { - write!(self.out, "uvec{}(", size as u8)?; - true - } - _ => false, + // Some GLSL functions only accept signed integers (like findMSB), + // so they need to be cast to and from int if the argument is an uint + let int_only_function = + matches!(fun, Mf::FindLsb | Mf::FindMsb | Mf::CountOneBits | Mf::Abs); + + // The int conversion to be performed in case it's needed, + // is `Some` if the conversion is needed and stores an `Option` + // with the vector size of the argument (`None` if it's a scalar) + // + // Writes the conversion from int already if that's the case + let int_conversion = if int_only_function { + match *ctx.info[arg].ty.inner_with(&self.module.types) { + crate::TypeInner::Scalar { + kind: crate::ScalarKind::Uint, + .. + } => { + write!(self.out, "uint(")?; + Some(None) } + crate::TypeInner::Vector { + kind: crate::ScalarKind::Uint, + size, + .. + } => { + write!(self.out, "uvec{}(", size as u8)?; + Some(Some(size)) + } + _ => None, + } + } else { + None }; write!(self.out, "{}(", fun_name)?; + + // Write the conversion to int if needed + if let Some(maybe_size) = int_conversion { + match maybe_size { + Some(size) => write!(self.out, "ivec{}(", size as u8)?, + None => write!(self.out, "int(")?, + } + } + self.write_expr(arg, ctx)?; + + // Close the int conversion + if int_conversion.is_some() { + write!(self.out, ")")? + } + if let Some(arg) = arg1 { write!(self.out, ", ")?; if extract_bits { @@ -2856,7 +2880,7 @@ impl<'a, W: Write> Writer<'a, W> { } write!(self.out, ")")?; - if need_extra_paren { + if int_conversion.is_some() { write!(self.out, ")")? } }