Skip to content

Rust and SPIR-V float rounding semantics are different #229

Open
@LegNeato

Description

@LegNeato

There is a footgun when trying to share code between CPU and GPU. Rust and SPIR-V have different semantics when rounding floats:

Rust:

  • Rust’s built-in conversion using as truncates the fractional part, effectively rounding toward zero.
  • For example, 1743028479.999... becomes 1743028479.
    Rust Language Reference

SPIR-V:

fn main() {
    let x = 1743028480i32;
    let y = (x as f64) * (1.0 / (i32::MAX as f64));

    // Without explicit rounding, differs:
    let without = (y * (i32::MAX as f64)) as i32;
    // Using `trunc()` forces Rust’s truncation:
    let with = (y * (i32::MAX as f64)).trunc() as i32;

    println!("x = {}. Without rounding = {}. With trunc() = {}.", x, without, with);
}

I'm not sure which should be the default. If it is Rust's we'll want to polyfill on the spir-v side. Might be good to have this user controlled in any case.

Originally posted by @LegNeato in #228 (comment)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions