From 4b796b157cb2b67b0ab166a2238fe4e9473bfd52 Mon Sep 17 00:00:00 2001 From: Evan Mark Hopkins <85699459+evahop@users.noreply.github.com> Date: Thu, 2 Feb 2023 16:11:09 -0500 Subject: [PATCH] [glsl-out] Version check countLeadingZeros (#2238) --- src/back/glsl/mod.rs | 109 +++++++++++------- .../out/glsl/math-functions.main.Vertex.glsl | 9 +- 2 files changed, 74 insertions(+), 44 deletions(-) diff --git a/src/back/glsl/mod.rs b/src/back/glsl/mod.rs index 838b323441..aaed745f26 100644 --- a/src/back/glsl/mod.rs +++ b/src/back/glsl/mod.rs @@ -181,6 +181,10 @@ impl Version { fn supports_fma_function(&self) -> bool { *self >= Version::Desktop(400) || *self >= Version::new_gles(320) } + + fn supports_integer_functions(&self) -> bool { + *self >= Version::Desktop(400) || *self >= Version::new_gles(310) + } } impl PartialOrd for Version { @@ -1128,12 +1132,13 @@ impl<'a, W: Write> Writer<'a, W> { self.need_bake_expressions.insert(fun_handle); } + let inner = expr_info.ty.inner_with(&self.module.types); + if let Expression::Math { fun, arg, arg1, .. } = *expr { match fun { crate::MathFunction::Dot => { // if the expression is a Dot product with integer arguments, // then the args needs baking as well - let inner = info[fun_handle].ty.inner_with(&self.module.types); if let TypeInner::Scalar { kind, .. } = *inner { match kind { crate::ScalarKind::Sint | crate::ScalarKind::Uint => { @@ -1145,7 +1150,9 @@ impl<'a, W: Write> Writer<'a, W> { } } crate::MathFunction::CountLeadingZeros => { - self.need_bake_expressions.insert(arg); + if let Some(crate::ScalarKind::Sint) = inner.scalar_kind() { + self.need_bake_expressions.insert(arg); + } } _ => {} } @@ -2954,50 +2961,74 @@ impl<'a, W: Write> Writer<'a, W> { Mf::Determinant => "determinant", // bits Mf::CountLeadingZeros => { - match *ctx.info[arg].ty.inner_with(&self.module.types) { - crate::TypeInner::Vector { size, kind, .. } => { - let s = back::vector_size_str(size); + if self.options.version.supports_integer_functions() { + match *ctx.info[arg].ty.inner_with(&self.module.types) { + crate::TypeInner::Vector { size, kind, .. } => { + let s = back::vector_size_str(size); - if let crate::ScalarKind::Uint = kind { - write!(self.out, "uvec{s}(")?; - } else { - write!(self.out, "ivec{s}(")?; + if let crate::ScalarKind::Uint = kind { + write!(self.out, "uvec{s}(ivec{s}(31) - findMSB(")?; + self.write_expr(arg, ctx)?; + write!(self.out, "))")?; + } else { + write!(self.out, "mix(ivec{s}(31) - findMSB(")?; + self.write_expr(arg, ctx)?; + write!(self.out, "), ivec{s}(0), lessThan(")?; + self.write_expr(arg, ctx)?; + write!(self.out, ", ivec{s}(0)))")?; + } } + crate::TypeInner::Scalar { kind, .. } => { + if let crate::ScalarKind::Uint = kind { + write!(self.out, "uint(31 - findMSB(")?; + } else { + write!(self.out, "(")?; + self.write_expr(arg, ctx)?; + write!(self.out, " < 0 ? 0 : 31 - findMSB(")?; + } - write!(self.out, "mix(vec{s}(31.0) - floor(log2(vec{s}(")?; - self.write_expr(arg, ctx)?; - write!(self.out, ") + 0.5)), ")?; - - if let crate::ScalarKind::Uint = kind { - write!(self.out, "vec{s}(32.0), lessThanEqual(")?; self.write_expr(arg, ctx)?; - write!(self.out, ", uvec{s}(0u))))")?; - } else { - write!(self.out, "mix(vec{s}(0.0), vec{s}(32.0), equal(")?; - self.write_expr(arg, ctx)?; - write!(self.out, ", ivec{s}(0))), lessThanEqual(")?; - self.write_expr(arg, ctx)?; - write!(self.out, ", ivec{s}(0))))")?; + write!(self.out, "))")?; } - } - crate::TypeInner::Scalar { kind, .. } => { - write!(self.out, "(")?; - self.write_expr(arg, ctx)?; + _ => unreachable!(), + }; + } else { + match *ctx.info[arg].ty.inner_with(&self.module.types) { + crate::TypeInner::Vector { size, kind, .. } => { + let s = back::vector_size_str(size); - if let crate::ScalarKind::Uint = kind { - write!(self.out, " == 0u ? 32u : uint(")?; - } else { - write!(self.out, " <= 0 ? (")?; - self.write_expr(arg, ctx)?; - write!(self.out, " == 0 ? 32 : 0) : int(")?; + if let crate::ScalarKind::Uint = kind { + write!(self.out, "uvec{s}(")?; + write!(self.out, "vec{s}(31.0) - floor(log2(vec{s}(")?; + self.write_expr(arg, ctx)?; + write!(self.out, ") + 0.5)))")?; + } else { + write!(self.out, "ivec{s}(")?; + write!(self.out, "mix(vec{s}(31.0) - floor(log2(vec{s}(")?; + self.write_expr(arg, ctx)?; + write!(self.out, ") + 0.5)), ")?; + write!(self.out, "vec{s}(0.0), lessThan(")?; + self.write_expr(arg, ctx)?; + write!(self.out, ", ivec{s}(0u))))")?; + } } - - write!(self.out, "31.0 - floor(log2(float(")?; - self.write_expr(arg, ctx)?; - write!(self.out, ") + 0.5))))")?; - } - _ => unreachable!(), - }; + crate::TypeInner::Scalar { kind, .. } => { + if let crate::ScalarKind::Uint = kind { + write!(self.out, "uint(31.0 - floor(log2(float(")?; + self.write_expr(arg, ctx)?; + write!(self.out, ") + 0.5)))")?; + } else { + write!(self.out, "(")?; + self.write_expr(arg, ctx)?; + write!(self.out, " < 0 ? 0 : int(")?; + write!(self.out, "31.0 - floor(log2(float(")?; + self.write_expr(arg, ctx)?; + write!(self.out, ") + 0.5))))")?; + } + } + _ => unreachable!(), + }; + } return Ok(()); } diff --git a/tests/out/glsl/math-functions.main.Vertex.glsl b/tests/out/glsl/math-functions.main.Vertex.glsl index d863ada72b..8cfa6a10b5 100644 --- a/tests/out/glsl/math-functions.main.Vertex.glsl +++ b/tests/out/glsl/math-functions.main.Vertex.glsl @@ -14,11 +14,10 @@ void main() { vec4 g = refract(v, v, 1.0); int const_dot = ( + ivec2(0, 0).x * ivec2(0, 0).x + ivec2(0, 0).y * ivec2(0, 0).y); uint first_leading_bit_abs = uint(findMSB(uint(abs(int(0u))))); - int clz_a = (-1 <= 0 ? (-1 == 0 ? 32 : 0) : int(31.0 - floor(log2(float(-1) + 0.5)))); - uint clz_b = (1u == 0u ? 32u : uint(31.0 - floor(log2(float(1u) + 0.5)))); + int clz_a = (-1 < 0 ? 0 : 31 - findMSB(-1)); + uint clz_b = uint(31 - findMSB(1u)); ivec2 _e20 = ivec2(-1); - ivec2 clz_c = ivec2(mix(vec2(31.0) - floor(log2(vec2(_e20) + 0.5)), mix(vec2(0.0), vec2(32.0), equal(_e20, ivec2(0))), lessThanEqual(_e20, ivec2(0)))); - uvec2 _e23 = uvec2(1u); - uvec2 clz_d = uvec2(mix(vec2(31.0) - floor(log2(vec2(_e23) + 0.5)), vec2(32.0), lessThanEqual(_e23, uvec2(0u)))); + ivec2 clz_c = mix(ivec2(31) - findMSB(_e20), ivec2(0), lessThan(_e20, ivec2(0))); + uvec2 clz_d = uvec2(ivec2(31) - findMSB(uvec2(1u))); }