-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Closed
Closed
Copy link
Labels
area: naga back-endOutputs of naga shader conversionOutputs of naga shader conversion
Description
Spinning this out from #7386 as it's more important we fix the UB promptly, whereas the exact result matching the spec is less important, especially as tint also appears to get that wrong.
Description
When casting an f32 to a i32 or u32 we may encounter undefined behaviour if the value is outwith the range of the target type.
- back/hlsl does a constructor style cast
- Spec says "The behavior is undefined if the truncated value cannot be represented in the destination type"
- back/msl does a static_cast
- Spec (Item 7.6) doesn't mention what happens when it's out of range. Presumably we therefore defer to C++14 section 4.9: "The behavior is undefined if the truncated value cannot be represented in the destination type"
- back/spv emits OpConvertFToU/OpConvertFToS instructions.
- Spec says: "Behavior is undefined if Result Type is not wide enough to hold the converted value."
- back/glsl does a constructor style cast
- I think it's safe to assume this is UB as well, but we don't care as much, for Firefox/webgpu at least.
Tint handles this with a wrapper function:
fn test(f: f32) -> i32 {
return i32(f);
}translates to... (metal, for example, but they do the same for all backends apart from wgsl)
int tint_f32_to_i32(float value) {
return select(2147483647, select((-2147483647 - 1), int(value), (value >= -2147483648.0f)), (value <= 2147483520.0f));
}
int test(float f) {
return tint_f32_to_i32(f);
}Note they clamp to the range -2147483648..=2147483647, so still fall afoul of #7386, but avoid UB
Metadata
Metadata
Assignees
Labels
area: naga back-endOutputs of naga shader conversionOutputs of naga shader conversion
Type
Projects
Status
Done