simvx.graphics.renderer.view_occlusion¶
Per-view two-phase Hi-Z occlusion culling for offscreen views (RM-B6).
Extra views (SubViewport / RenderView) render as scene-render units
(SRUs) through :meth:SceneAdapter.render_to_target, outside the main pass’s
occlusion machinery. Setting use_occlusion=True on the node gives such a
view its own two-phase Hi-Z island: a scratch depth prepass + Hi-Z pyramid
sized to the VIEW’s target, its own cull compute pass, indirect batches, and
visibility ping-pong buffers, driven by the exact
Renderer._two_phase_occlusion sequence the main pass uses. During the
recording the renderer’s occlusion attributes are swapped to this bundle (the
same save / swap / restore isolation render_to_target applies to the
submission lists), so the main pass’s own occlusion state is untouched and the
default (flag-off) frame is byte-identical.
Scope (documented deviations, both engine decisions carried by RM-B6):
Desktop only. The web renderer’s Hi-Z cull is single-phase (TODO.md, “Web two-phase Hi-Z occlusion”) and has no per-view hook yet; the flag is a no-op on web.
Pipelined (P2) render mode defers per-view occlusion exactly like reflection-probe capture (
render_packet.py, “State intentionally NOT snapshotted”): the view renders un-culled and the owning manager logs a one-time warning. Immediate (synchronous) mode is the supported path.
Module Contents¶
Classes¶
One offscreen view’s private two-phase Hi-Z occlusion state. |
Functions¶
Return (creating on demand) the node’s occlusion bundle, or None. |
Data¶
API¶
- simvx.graphics.renderer.view_occlusion.log¶
‘getLogger(…)’
- simvx.graphics.renderer.view_occlusion.__all__¶
[‘ViewOcclusion’, ‘view_occlusion_for’]
- class simvx.graphics.renderer.view_occlusion.ViewOcclusion(engine: Any)[source]¶
One offscreen view’s private two-phase Hi-Z occlusion state.
Owns the view-sized scratch :class:
~.depth_prepass.DepthPrepass+- Class:
~.hiz_pass.HiZPasspair (created eagerly, the sizes differ from the main pass’s) and harvests the size-agnostic pieces (cull compute pass, indirect batches, visibility ping-pong buffers) from the renderer’s own lazy_ensure_*helpers on the first recorded frame. Recreated whole when the view’s target size or the renderer’s instance capacity changes (both rare: resizes are debounced, capacity growth happens at a frame boundary after a device-idle reallocation).
Initialization
- record(cmd: Any, renderer: Any, width: int, height: int) None[source]¶
Record this view’s two-phase occlusion cull into
cmd.Must run while the SRU’s state is bound (instances / viewport / slice base installed by
render_to_target) and OUTSIDE any render pass (compute is illegal inside one), i.e. between the SRU’s transform upload andtarget.begin_pass. Leaves the scene renderer’s per-frame occlusion plans pointing at THIS view’s culled batches so the SRU’srender_scene_contentconsumes them; :meth:finishmust be called after the SRU render to restore the main pass’s plan state.
- finish(renderer: Any) None[source]¶
Restore the main pass’s plan state after the SRU render consumed ours.
- simvx.graphics.renderer.view_occlusion.view_occlusion_for(store: dict[int, simvx.graphics.renderer.view_occlusion.ViewOcclusion], node: Any, engine: Any) simvx.graphics.renderer.view_occlusion.ViewOcclusion | None[source]¶
Return (creating on demand) the node’s occlusion bundle, or None.
The one gate both offscreen-view managers use: with
use_occlusionFalse (the default) this is a singlegetattrplus, at most, the destruction of a bundle whose flag was just toggled off, so the common path stays zero-cost.storeis the manager’sid(node) -> bundledict; reaping on node exit stays the manager’s responsibility.