From 6dc3b7186c3b520d98e982604bb4805598b268ae Mon Sep 17 00:00:00 2001 From: Jamie Nicol Date: Thu, 10 Apr 2025 09:03:43 +0100 Subject: [PATCH] [naga hlsl-out] Emit most-negative integer value literals as 2nd-most-negative value minus one As we did for MSL in #7437. eg `-2147483648` becomes `-2147483647 - 1`. Neither FXC nor DXC currently have any issues parsing the most negative value literals. However, we have been informed this is not guaranteed to always be the case, so are making this change as a precaution. --- naga/src/back/hlsl/writer.rs | 12 ++++++++++++ .../tests/out/hlsl/wgsl-conversion-float-to-int.hlsl | 10 +++++----- naga/tests/out/hlsl/wgsl-int64.hlsl | 2 +- naga/tests/out/hlsl/wgsl-operators.hlsl | 2 +- 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/naga/src/back/hlsl/writer.rs b/naga/src/back/hlsl/writer.rs index a0d25e1d0d..9895dee97d 100644 --- a/naga/src/back/hlsl/writer.rs +++ b/naga/src/back/hlsl/writer.rs @@ -2620,11 +2620,23 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { crate::Literal::F32(value) => write!(self.out, "{value:?}")?, crate::Literal::F16(value) => write!(self.out, "{value:?}h")?, crate::Literal::U32(value) => write!(self.out, "{value}u")?, + // `-2147483648` is parsed by some compilers as unary negation of + // positive 2147483648, which is too large for an int, causing + // issues for some compilers. Neither DXC nor FXC appear to have + // this problem, but this is not specified and could change. We + // therefore use `-2147483647 - 1` as a precaution. + crate::Literal::I32(value) if value == i32::MIN => { + write!(self.out, "int({} - 1)", value + 1)? + } // HLSL has no suffix for explicit i32 literals, but not using any suffix // makes the type ambiguous which prevents overload resolution from // working. So we explicitly use the int() constructor syntax. crate::Literal::I32(value) => write!(self.out, "int({value})")?, crate::Literal::U64(value) => write!(self.out, "{value}uL")?, + // I64 version of the minimum I32 value issue described above. + crate::Literal::I64(value) if value == i64::MIN => { + write!(self.out, "({}L - 1L)", value + 1)?; + } crate::Literal::I64(value) => write!(self.out, "{value}L")?, crate::Literal::Bool(value) => write!(self.out, "{value}")?, crate::Literal::AbstractInt(_) | crate::Literal::AbstractFloat(_) => { diff --git a/naga/tests/out/hlsl/wgsl-conversion-float-to-int.hlsl b/naga/tests/out/hlsl/wgsl-conversion-float-to-int.hlsl index ca0a79ce69..aa599b8242 100644 --- a/naga/tests/out/hlsl/wgsl-conversion-float-to-int.hlsl +++ b/naga/tests/out/hlsl/wgsl-conversion-float-to-int.hlsl @@ -15,23 +15,23 @@ void test_const_eval() int64_t max_f16_to_i64_ = 65504L; uint64_t min_f16_to_u64_ = 0uL; uint64_t max_f16_to_u64_ = 65504uL; - int min_f32_to_i32_ = int(-2147483648); + int min_f32_to_i32_ = int(-2147483647 - 1); int max_f32_to_i32_ = int(2147483520); uint min_f32_to_u32_ = 0u; uint max_f32_to_u32_ = 4294967040u; - int64_t min_f32_to_i64_ = -9223372036854775808L; + int64_t min_f32_to_i64_ = (-9223372036854775807L - 1L); int64_t max_f32_to_i64_ = 9223371487098961920L; uint64_t min_f32_to_u64_ = 0uL; uint64_t max_f32_to_u64_ = 18446742974197923840uL; - int64_t min_f64_to_i64_ = -9223372036854775808L; + int64_t min_f64_to_i64_ = (-9223372036854775807L - 1L); int64_t max_f64_to_i64_ = 9223372036854774784L; uint64_t min_f64_to_u64_ = 0uL; uint64_t max_f64_to_u64_ = 18446744073709549568uL; - int min_abstract_float_to_i32_ = int(-2147483648); + int min_abstract_float_to_i32_ = int(-2147483647 - 1); int max_abstract_float_to_i32_ = int(2147483647); uint min_abstract_float_to_u32_ = 0u; uint max_abstract_float_to_u32_ = 4294967295u; - int64_t min_abstract_float_to_i64_ = -9223372036854775808L; + int64_t min_abstract_float_to_i64_ = (-9223372036854775807L - 1L); int64_t max_abstract_float_to_i64_ = 9223372036854774784L; uint64_t min_abstract_float_to_u64_ = 0uL; uint64_t max_abstract_float_to_u64_ = 18446744073709549568uL; diff --git a/naga/tests/out/hlsl/wgsl-int64.hlsl b/naga/tests/out/hlsl/wgsl-int64.hlsl index 6705e77e71..75fc5cb089 100644 --- a/naga/tests/out/hlsl/wgsl-int64.hlsl +++ b/naga/tests/out/hlsl/wgsl-int64.hlsl @@ -100,7 +100,7 @@ int64_t int64_function(int64_t x) int64_t _e74 = val; val = (_e74 + _e71.w); int64_t _e77 = val; - val = (_e77 + -9223372036854775808L); + val = (_e77 + (-9223372036854775807L - 1L)); int64_t _e83 = input_uniform.val_i64_; int64_t _e86 = input_storage.Load(128); output.Store(128, (_e83 + _e86)); diff --git a/naga/tests/out/hlsl/wgsl-operators.hlsl b/naga/tests/out/hlsl/wgsl-operators.hlsl index b19e526ff0..3dbec43451 100644 --- a/naga/tests/out/hlsl/wgsl-operators.hlsl +++ b/naga/tests/out/hlsl/wgsl-operators.hlsl @@ -197,7 +197,7 @@ void arithmetic() float4 mul_vector1_ = mul(ZeroValuefloat4x3(), (2.0).xxx); float3x3 mul_ = mul(ZeroValuefloat3x4(), ZeroValuefloat4x3()); int _e175 = prevent_const_eval; - wgpu_7437_ = asint(asuint(_e175) + asuint(int(-2147483648))); + wgpu_7437_ = asint(asuint(_e175) + asuint(int(-2147483647 - 1))); return; }