From 70743ee7dc379f6c22fd25da8bd581a03f73f1d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Capucho?= Date: Tue, 7 Jun 2022 21:22:34 +0100 Subject: [PATCH] glsl-in: Perform casts in int only math functions Some functions like abs only accept signed integers while naga's IR accepts both signed and unsigned integers, this wasn't accounted for in the glsl backend causing it to produce code that wouldn't type check. This commit addresses it by performing casts from uint to int of the function argument and then back from int to uint for the function return. --- src/back/glsl/mod.rs | 74 ++++++++++++++++++++++++++++++-------------- 1 file changed, 51 insertions(+), 23 deletions(-) diff --git a/src/back/glsl/mod.rs b/src/back/glsl/mod.rs index cba3b3ca0a..134b4e2417 100644 --- a/src/back/glsl/mod.rs +++ b/src/back/glsl/mod.rs @@ -2808,32 +2808,59 @@ 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 always return signed integers (like findMSB), + // so they need to be cast to uint if the argument is also an uint. + let needs_int_to_uint = + matches!(fun, Mf::FindLsb | Mf::FindMsb | Mf::CountOneBits | Mf::Abs); + + // Some GLSL functions only accept signed integers (like abs), + // so they need their argument cast from uint to int. + let needs_uint_to_int = matches!(fun, Mf::Abs); + + // Check if the argument is an unsigned integer and return the vector size + // in case it's a vector + let maybe_uint_size = match *ctx.info[arg].ty.inner_with(&self.module.types) { + crate::TypeInner::Scalar { + kind: crate::ScalarKind::Uint, + .. + } => Some(None), + crate::TypeInner::Vector { + kind: crate::ScalarKind::Uint, + size, + .. + } => Some(Some(size)), + _ => None, }; + if let Some(maybe_size) = maybe_uint_size { + // Cast to uint if the function needs it + if needs_int_to_uint { + match maybe_size { + Some(size) => write!(self.out, "uvec{}(", size as u8)?, + None => write!(self.out, "uint(")?, + } + } + } + write!(self.out, "{}(", fun_name)?; + + if let Some(maybe_size) = maybe_uint_size { + // Cast to int if the function needs it + if needs_uint_to_int { + match maybe_size { + Some(size) => write!(self.out, "ivec{}(", size as u8)?, + None => write!(self.out, "int(")?, + } + } + } + self.write_expr(arg, ctx)?; + + // Close the cast from uint to int + if needs_uint_to_int && maybe_uint_size.is_some() { + write!(self.out, ")")? + } + if let Some(arg) = arg1 { write!(self.out, ", ")?; if extract_bits { @@ -2866,7 +2893,8 @@ impl<'a, W: Write> Writer<'a, W> { } write!(self.out, ")")?; - if need_extra_paren { + // Close the cast from int to uint + if needs_int_to_uint && maybe_uint_size.is_some() { write!(self.out, ")")? } }