crates/render/src/cull.rsandcull.wgsl: each frame the shared opaque runs' instances go through a compute pass per view: bounding spheres (mesh bounds computed at upload, scaled by the instance's transform) against the view frustum, then against the depth pyramid (Hi-Z) the view built last frame. Visible instances are compacted into a per-view list and counted into the runs'DrawIndexedIndirectarguments; the opaque pass draws them indirectly (per-draw vertex-buffer offsets, so no first-instance feature is needed).- Two-phase occlusion: the view's depth after phase one becomes its new pyramid (a compute copy and min-reduction mip chain, reverse-Z), and the instances phase one held back as occluded are tested against it and drawn in a second pass before the transparent geometry. Nothing visible is lost to a stale pyramid; the pyramid is kept for the next frame.
- Transparent items, per-view masked opaque runs, shadow casters and reflection captures keep the CPU path. Off where compute isn't available, or with
TASSIX_GPU_CULLING=0. - A GPU test checks the frustum and occlusion counts across frames (a wall hiding a grid, then removed) and that images match with culling off; all render, e2e and conformance tests pass with it on.
- Not yet: bindless materials (runs still bind textures), multi-draw indirect, culling shadow casters, mesh LODs selected on the GPU.
- Next: render benchmark scenes with frame-time budgets in CI.
Phase 5 · Slice 22 ·