simvx.graphics.renderer.occlusion_cull

GPU Hi-Z occlusion cull pass (phase O3).

Patches per-instance instance_count in an indirect draw buffer IN PLACE: 0 to cull, 1 to keep. Batching guarantees one command per instance, so zeroing a command drops exactly that one object. CONSERVATIVE: an object is culled only when its nearest screen depth is strictly farther than the Hi-Z (MAX) occluder footprint; every degeneracy keeps the object. See occlusion_cull.comp.

Single-phase against LAST frame’s Hi-Z pyramid: the cull runs BEFORE the forward pass (compute is illegal inside a render pass), consuming the pyramid the prior frame built. Fully gated by Renderer._occlusion_culling_enabled and by a hiz_built_once flag (skip until a pyramid exists), so the default path allocates and dispatches nothing.

Module Contents

Classes

OcclusionTwoPhasePass

Two-phase Hi-Z occlusion cull: GPU phase-1 selection + phase-2 cull.

Data

API

simvx.graphics.renderer.occlusion_cull.__all__

[‘OcclusionTwoPhasePass’]

simvx.graphics.renderer.occlusion_cull.log

‘getLogger(…)’

class simvx.graphics.renderer.occlusion_cull.OcclusionTwoPhasePass(engine: Any, max_sets: int = 16)[source]

Two-phase Hi-Z occlusion cull: GPU phase-1 selection + phase-2 cull.

Reuses occlusion_two_phase.comp (one shader, dispatched twice). Owns a descriptor set per (indirect buffer, frame parity): bindings 4/5 (vis_prev, vis_next) swap each frame, so a fresh set is allocated for each parity and then cached. Bindings 0-3 (draws, transforms, aabbs, hi-z) match the single-phase layout. See the shader header for the conservative invariant.

Initialization

setup() None[source]
dispatch(cmd: Any, *, phase: int, skip_cull: bool, indirect_buffer: Any, draw_count: int, transform_buf: Any, aabb_buf: Any, hiz_view: Any, hiz_sampler: Any, vis_prev_buf: Any, vis_next_buf: Any, parity: int, view_proj: numpy.ndarray, base_extent: tuple[int, int], mip_count: int, max_objects: int, host_barrier: bool = False) None[source]

Record one phase of the two-phase cull.

phase 1 = selection (seed phase-1 batch + vis_next from vis_prev), 2 = cull (test set B against the fresh Hi-Z, write final instance_count + vis_next). The caller guarantees this runs OUTSIDE any render pass.

Barriers: host_barrier (phase-1 only) makes the CPU indirect/transform/ aabb/visibility uploads visible. After the dispatch a buffer barrier makes the patched instance_count visible to the indirect draw that reads it (phase 1 -> depth prepass, phase 2 -> colour pass).

cleanup() None[source]