Skip to content

Why the CPU and GPU share code

github-actions[bot] edited this page Sep 20, 2026 · 3 revisions

Why the CPU and GPU share code

The CPU rasterizer and the GPU kernel call the same functions for the fill rule, texture wrapping, texel blending and light falloff. Two implementations of one rule drift. One implementation cannot.

What is shared

Module Shared functions
render/fillrule.mojo Snapping, the edge function, the top-left bias, the sample position.
render/linerule.mojo Which pixel a one-pixel line lights in each column, and the dash fold.
render/pointrule.mojo Whether a point covers a pixel, its coordinate there, its size with distance and its mip level.
render/texture.mojo wrap_index, blend_texels, mix_color.
lights/lighting.mojo falloff.

Each allocates nothing, prints nothing and raises nothing. That is what lets it compile for a device.

What is not shared

The rasterizer writes pixels and the kernel writes device memory. The lighting sum has a host version, Lighting.intensity_at, and a device version, _arriving, because the kernel reads a flat float buffer. The parity tests hold those two to the same numbers.

The standards

Coverage is integer arithmetic. The two backends must agree exactly, and the tests demand it.

Shading is floating point. A GPU contracts a * b + c into a fused multiply-add that rounds once where the CPU rounds twice. A channel whose exact value lands on a quantization midpoint can fall either side. Tests that interpolate shading allow one level per channel, and say so. One level cannot hide a wrong color, a wrong depth or a wrong pixel.

What parity cannot catch

A bug inside a shared function makes both sides wrong together. tests/test_fillrule.mojo pins the fill rule against values derived from the definitions, and it found exactly such a bug once. See Why coverage uses fixed point.

The list is the contract

Renderer.prepare produces one List[RasterVertex]. rasterize_all and GpuRenderer.draw consume that same list. The whole-scene parity tests prepare once and fill twice, so they compare two rasterizers rather than two pipelines.

Home

Tutorials

How-to

Reference

Explanation

Clone this wiki locally