[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.
This commit is contained in:
Jamie Nicol 2025-04-10 09:03:43 +01:00 committed by Erich Gubler
parent 8010203281
commit 6dc3b7186c
4 changed files with 19 additions and 7 deletions

View File

@ -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(_) => {

View File

@ -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;

View File

@ -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<int64_t>(128);
output.Store(128, (_e83 + _e86));

View File

@ -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;
}