Home

HomeChapter 05 / 8Swift · Metal · Python

Implemented

338 words · 2 min read · Arsh Shah

Implementation

Engineering the illusion

The visual effect depends on disciplined resource ownership. Every texture has a role, every pass has an order, and every architecture has an explicit path. Half-float ping-pong slabs, a memoised MetalDevice pipeline cache, and a three-buffer uniform ring are the engineering choices that keep sixty-frame-per-second floor projection honest rather than magical.

The floor is the display

The hull cutout is generated from the scull’s own taper. Profile and plan set the lines; the mask is the unlit region the projectors leave as boat.

Fig. 05.1

(a) Profile and plan of a racing scull. (b) Hull lines that set the taper. (c) The mask the projectors leave unlit.

Read ping, write pong, then swap

Every simulation field lives in a paired half-float slab. A pass reads ping, writes pong, then the pair swaps, so ownership is visible in the resource itself rather than in a comment.[004] The pressure solve is the one in-place exception on Apple Silicon — a deliberate departure, not an accident of the API. Stam’s ping-pong fields are the ancestry.[113]

pingrg16Floatpongrg16FloatinoutPasskernelsample ping · write pong

GPU memory

Names stay. Roles flip.

Two fixed textures. A pass samples one and writes the other; swap() then trades the roles.

01 · PassSample READ into the kernel, then write the result into WRITE — never the same texture.

Fig. 05.2

Sample READ into a pass, write to WRITE, then swap() flips the roles. Semaphore(3) caps in-flight frames.

Allocate once, stretch later

The simulation grid is built on the first resize. Later window changes stretch that grid through UV rather than reallocating it. Host points stay coherent because they scale with the same ratio.

Simulation gridDrawable / viewallocate onceUV stretchfirst sizeUnitMappingtexPos = point × texSize / viewSize

Domain & resize

Fixed grid. Live window.

Fluid state survives resize because the slabs never move — only the view mapping does.

01 · AllocateFirst resize builds the simulation grid once. After that, resolution stays fixed.

Fig. 05.3

Slabs allocate once; later resizes stretch via UV. UnitMapping keeps host input coherent.

Build once, dispatch often

Metal pipeline states are memoised on the shared device. Repeated passes do not pay construction cost twice. Crane, Llamas and Tariq’s real-time fluids on the GPU already treated the pipeline as a scarce object;[031] the same discipline is what keeps a sixty-hertz floor from hitching when a kernel is asked for the second time.[Th.]

askreuse0 taxcompileoncePass key"Advect"MetalDevicePSO cacheDispatchevery frame

Pipeline cache

Lookup. Hit or miss. Dispatch.

MetalDevice memoises pipeline states so the seventeen-stage graph never recompiles hot.

01 · AskA pass asks MetalDevice for a pipeline by name — never builds one inline.

Fig. 05.4

Pass asks MetalDevice: hit reuses a memoised PSO; miss compiles once, then dispatches.

Uniforms are a contract

A three-buffer uniform ring carries host state to the GPU without stalling the previous frame. The ring is the seam between Swift and Metal: what the host has decided a stroke means, written once, read by every pass that needs it.

Research toolingHostFluid corePythonnormalizeUDPhost vocabularyHost sinkmain threadMetalowns the fieldHost is the only writer into Metal

Python bridge

One legal path.

Research tooling may emit packets. Only the host may write the fluid field.

01 · EmitPython normalizes sensors and emits host-shaped packets. It never opens a Metal texture.

Fig. 05.5

Python → UDP → host → Metal. One legal path; the host is the only writer into the fluid core.

Explicit branches beat silent fallbacks

Apple Silicon and Intel are different machines: solver, bloom, particles, ripple radius. Infer the branch from the host and name it. A silent fallback would make two sessions incomparable; an explicit one makes the comparison possible.

Apple Siliconcompute branchPressureRBGSBloomOnParticlesOnRipple r16Intel / fallbackfragment branchPressureJacobiBloomOffParticlesOffRipple r8Infer architecture from host · not a manifest field

Reproducibility

Name the branch.

Compile-time paths are honest machines — not one binary quietly degrading.

01 · SiliconApple Silicon compute: RBGS pressure, bloom, particles, ripple radius 16.

Fig. 05.6

Apple Silicon vs Intel: different solver, bloom, particles, and ripple radius. Infer the branch from the host.

Works cited

Superscripts use the thesis bibliography number. Click a number to return to the first mention.

  1. [004]

    Apple Inc. (2024).

    Metal: Documentation and programming guide.

    Apple Developer Documentation.

    Link

  2. [031]

    Keenan Crane, Ignacio Llamas, and Sarah Tariq (2007).

    Real-time simulation and rendering of 3D fluids.

    GPU Gems 3, ch. 30. Addison-Wesley.

  3. [113]

    Jos Stam (1999).

    Stable fluids.

    Proceedings of SIGGRAPH ’99, pp. 121–128. ACM.

    doi:10.1145/311535.311548

  4. [Th.]

    Arsh Shah (2026).

    RowSim: Designing and Evaluating Ambient Interaction in Mixed-Reality Rowing.

    Master’s thesis, Dalhousie University, Halifax, NS.

    ch. 3hdl.handle.net/10222/86331PDF