---
title: "When the fractional part of a float fixes your shader"
slug: when-the-fractional-part-of-a-float-fixes-your-shader
url: https://listedarticles.com/articles/when-the-fractional-part-of-a-float-fixes-your-shader
canonical_url: https://crocidb.com/post/when-the-fractional-part-of-a-float-fixes-your-shader/
content_type: tutorial
language: en
published_at: 2026-09-13T12:00:00.000Z
updated_at: 2026-09-18T12:24:44.236Z
author: "Bruno Croci"
author_url: https://crocidb.com/
authored_by: human
publisher: "Bruno Croci"
publisher_url: https://crocidb.com/
topics: ["Programming", "Hardware", "Debugging", "Performance"]
license: all-rights-reserved
word_count: 288
reading_minutes: 1
citation: "Bruno Croci, Bruno Croci. \"When the fractional part of a float fixes your shader.\" 13 Sept 2026. https://crocidb.com/post/when-the-fractional-part-of-a-float-fixes-your-shader/ (all-rights-reserved)"
# The full text follows. The web page shows an extract and sends readers
# to the source above; quote the citation and link the canonical URL.
---

# When the fractional part of a float fixes your shader

> Bruno Croci debugs a Voronoi Shadertoy stutter that only appeared on a Windows RTX 4070: ANGLE/FXC optimizations dropped `fract` for integer-looking inputs, and swapping a literal to `398.1` or using `x-floor(x)` restored smooth motion.

# When the fractional part of a float fixes your shader

The other night I wanted to implement a small Voronoi-diagram shader as a music-video background. I got it looking cool, then next morning found that—on one computer only—there was a weird stutter. This is the write-up of a week debugging and disassembling shaders.

## The shader

A Worley/Voronoi noise: tile space, pick random centers, nearest of 9 centers colors a cell; UV warping via noise; palette lookup. Noise came from Inigo Quilez-style value noise using `fract` / `hash1`.

## The problem

Devices tested: Intel iGPU Linux laptops (OK), Pixel 9 Pro (OK), Linux RTX 2070 (OK), **Windows RTX 4070 (broken)** across Firefox/Chrome/Edge.

An LLM suggested replacing `fract(x)` with `x - floor(x)`. That fixed the stutter—but follow-up mini-repros failed to show `fract` returning garbage, invalidating a simple driver-bug story.

## The weird fix that taught the real bug

Changing the scalar in `vec2 v = o * 398.0 + …` to `398.1` also fixed the stutter **even with `fract` still present**. Integer-ish literals (`398.0`, `1.0`) stuttered; fractional ones (`398.1`, `1.001`) did not.

## ANGLE → HLSL → FXC

Capture via RenderDoc on Chromium showed DirectX 11 (`ps_5_0`) via ANGLE. Vulkan ANGLE path did not reproduce. Dumping translated HLSL showed near-identical GLSL→HLSL; the bug was in **FXC optimization**.

With `D3DCOMPILE_SKIP_OPTIMIZATION`, disassembly kept both `floor` and `frac`. With `/O3`, FXC effectively truncated intermediate values—losing the fractional part used as noise interpolation weights—when operands looked integral. With `398.1`, optimized code still retained `frac`.

## Takeaway

What started as a shader night became a week learning ANGLE, DXBC, and FXC quirks. Minimum repro still welcome from graphics folks. Final shader is on Shadertoy; music project: *stuffy knows*.

*Originally published at [crocidb.com](https://crocidb.com/post/when-the-fractional-part-of-a-float-fixes-your-shader/).*
