Specifications / Runtime libraries
Graphics Backends
Status: partially implemented. The Metal backend renders the three graphics scenes on macOS; the Direct3D 12 bridge compiles, links and draws every scene in software on Windows (2026-10-28). No hardware adapter has drawn a scene yet, no frame has been compared with the Mac's at matched uniforms, and the convergence with gpu* is not implemented. Plan 0023 owns delivery; until then src/osprey/examples/graphics/README.md is the operating contract.
Graphics in Osprey is a host boundary, not the gpu* compute surface (0034): an Osprey host program drives a window through six extern C functions, and a hand-written fragment shader shades every pixel from the parameter slots Osprey pushes into it. The Osprey sources are byte-identical on every platform.
One ABI declaration — [GFX-ABI]
The Osprey-facing C contract is declared once, in ospgfx_abi.h: OSP_GFX_SLOTS, the two fixed-point scales, the OspGfxUniforms block, the window-extent and scale validation, the fragment-entry default, the slot store and the elapsed-time helper. Both bridges include it and restate none of it; the drift guard fails if either bridge grows its own #define OSP_GFX_SLOTS or typedef struct OspGfxUniforms again.
The uniform-slot protocol both bridges implement is declared once, in src/osprey/examples/graphics/ospgfx_abi.h, and a kernel's leading uniform parameters are exactly a slot vector — that header is the seam the gpu* convergence attaches to (GPU-KERNEL-EXTRACT).
Shader library — [GFX-SHADER-LIB]
Pixel-for-pixel identity across platforms is not claimed and must not be. The arithmetic is transcribed operation for operation, but the shader compilers fold, reassociate and schedule independently: "indistinguishable", never "bit-equal".
Authored grade lives in Osprey, not the shader. An offscreen A/B render at matched uniforms was byte-identical when the grade moved out of the shader; that is the bar the gpu* convergence inherits.
Uniform transcription hazards — [GFX-UNIFORMS]
Two transcription hazards are load-bearing, and each carries a dedicated test and comment because each compiles cleanly when wrong.
- HLSL cbuffer packing. A
float slot[24]inside an HLSL constant buffer gets one 16-byte register per element and would readslot[1]out of the bridge'sslot[4]. It is declaredfloat4 uniformSlotPack[OSP_GFX_SLOTS / 4]and unpacked once byloadUniforms(); a#if (OSP_GFX_SLOTS % 4) != 0 / #errorguards the divisibility, andthe_hlsl_constant_buffer_cannot_quietly_unpack_itselfguards the guard. - Matrix convention. Metal's
float2x2takes columns; HLSL's takes rows and needsmul.rotationFromTurnsis transposed accordingly; get it wrong and every scene spins backwards at full frame rate.
Only a frame compared with the Mac's at matched uniforms settles either hazard; that comparison is not implemented yet.