Skip to content

f64 ln/exp emit invalid GLSL.std.450 OpExtInst (Log/Exp) on SPIR-V backend #1316

@shimwell

Description

@shimwell

Many thanks for making this software, it looks like the best option for a project I am planning and I am super keen to give it a go but hit a bit of a road block for my specific project

Calling x.ln() or x.exp() on f64 inside a #[cube] function compiles to OpExtInst Log / OpExtInst Exp with f64 operands. That's invalid per the GLSL.std.450 extended-instruction spec:

The operand x must be a scalar or vector whose component type is 16-bit or 32-bit floating-point.

NVIDIA's Vulkan driver happens to accept it and returns roughly the right values. Mesa RADV+ACO correctly rejects it the pipeline "compiles" but emits

ACO ERROR:
    Unimplemented NIR instr bit size: div 64    %27 = fexp2 %26
ACO ERROR:
    Unimplemented NIR instr bit size: div 64    %31 = flog2 %24

and the kernel returns garbage (exp(1e-6)NaN, ln(e)0.6534…).

Confirmed with the Mesa team in https://gitlab.freedesktop.org/mesa/mesa/-/work_items/15359 they consider their behaviour correct, and the fix has to live wherever the SPIR-V is produced.

f64::sqrt is fine — no such restriction in the spec, and it works at 0 ULP drift on the same driver.

Same shape of codegen bug as #1200 (Metal MSL, bf16 transcendentals invalid). Different backend, different type, same underlying issue: codegen ignores per-backend operand-type restrictions on transcendentals.

Repro

```rust
#[cube(launch_unchecked)]
fn ln_kernel(input: &Array, output: &mut Array) {
if ABSOLUTE_POS >= input.len() { terminate!(); }
output[ABSOLUTE_POS] = input[ABSOLUTE_POS].ln();
}
```

Run on a Vulkan adapter exposing SHADER_F64 with cubecl-wgpu's spirv feature. AMD gfx1151 + Mesa 25.2.8 reproduces 100%. Full repro at https://github.com/fusion-neutronics/yamc, branch `develop-vulkan`, `crates/yamc-gpu/src/kernels/f64_transcendentals.rs`.

Suggested fix

When the SPIR-V backend lowers Float::ln / Float::exp for an f64 type, either:

  • emit a polyfill (extract exponent + mantissa, polynomial approximant) so the resulting SPIR-V uses only spec-valid ops, or
  • error at compile time so callers polyfill in their own kernels rather than getting silent NVIDIA-only correctness.

Probably worth auditing the other GLSL.std.450 ops with the same operand restriction (Sin, Cos, Pow, Tan, Asin, etc.) for the same lowering bug.

Versions: `cubecl 0.10.0-pre.4`, `cubecl-wgpu 0.10.0-pre.4` with `spirv` feature.

Can attach the SPIR-V dump if useful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions