GPU Backend Interface
The M13 layer: interface only, in include/tess/gpu/. GPU execution is
optional and unimplemented in the current pre-1.0 release -- CPU stays
authoritative for every
gameplay-exact result, GPU products are derived/cached/versioned by a
future backend, and the acceptance bar is that a real backend can be
added later without redesigning core. Nothing here touches a GPU API or
adds a dependency; descriptors are byte-level facts about storage tess
already owns, and the backend seam is compile-time polymorphic (a
concept, never virtual dispatch). Everything lives in tess::gpu.
Public Surface
GpuFieldFormatis the storage format of one field's per-tile value, derived from the schema's value type (unsigned/signed 8-64 bit and F32; bool maps to U8, its storage size).FieldMirrorDescdescribes one field mirrored to the GPU:field_index,format,value_bytes,tiles_per_chunk,bytes_per_chunk,chunk_count, andtotal_bytes(). tess pages are SoA per chunk, so a chunk's field values are one contiguous run and a mirror buffer ischunk_countchunk-key-major slices.field_mirror_desc<World, Tag>()computes the mirror description entirely from compile-time layout facts (constexpr). Value types are integral or float32 (adoublefield fails to compile rather than receive a lying format), and the dense mirror's byte counts are compile-time proven to fitstd::uint64_t-- shapes whose dense mirror cannot be described fail to compile instead of wrapping. The description is the MAXIMAL dense mirror for dense/bounded worlds (the current consumer's case); selective sparse mirrors -- the TDD's GpuMirror tracking chosen chunk copies -- are future work that reuses these structs with differently-computed offsets.UploadDescstages one chunk's worth of one field: the live page span (data/byte_size, valid until the world mutates or evicts the chunk) and the destinationbuffer_offsetin the chunk-key-major mirror.upload_desc<Tag>(world, chunk_key)derives it; sparse worlds pass resident keys only, the standing accessor contract.DispatchDescis one kernel dispatch over a mirrored product (product_key,input_field_index,chunk_count,workgroups_per_chunk) -- deliberately abstraction-free; a real backend maps it onto its own pipeline and binding model.ReadbackPolicy/ReadbackDescmake readback explicit:None,Summary(the steady-state shape),SelectedTiles,SelectedPath, andFullField(debug/explicit only). No full readback by default.GpuCapabilitiesis what the device can do (compute,async_dispatch,async_readback,max_buffer_bytes,max_dispatch_chunks,buffer_alignment); a planner checks these before ever selecting GPU. All-false/zero means never-choose-GPU.GpuBackendis the backend concept: noexceptcapabilities(), plusupload/dispatch/readbackreturningbool--falseis a refusal (missing capability, exhausted budget, lost device) and the caller falls back to the authoritative CPU path.NoGpuBackendis the default backend: reports no capabilities and refuses every operation, so CPU-only builds compile untouched and carry zero GPU obligations.
The current concept is deliberately synchronous-bool only: the fence and
completion-collection surface named by the TDD arrives with the first
real backend, as a non-breaking refinement of this concept (the
async_dispatch/async_readback capability flags reserve the space).
Testing
tests/gpu_mock_backend.h provides the test-only MockGpuBackend: it
satisfies the concept, enforces its configured capabilities, and records
the call sequence so tests assert upload -> dispatch -> readback
ordering and payloads. Benchmarks are deliberately absent while no real
backend exists (the
benchmark plan's mock-backend note): there is no execution to measure,
and gating descriptor construction would gate arithmetic.