truncation¶
Counters for the render path’s silent truncations.
Each of these is a fixed ceiling that degrades the image when it binds –
transport that should have reached the pixel does not – and every one of them
used to pass without a word. DESIGN_mesh_identity_open.md §Y states the
rule they broke: an instrument that reports zero may not be looking. So the
counters here are unconditional; a zero is a measurement, not an absence of
one.
The ceilings, and what each costs when it binds:
surfaces_per_raymax_surfaces_per_ray(256) surfaces composited along one primary ray. The walk stops and the ray’s leftover weight is handed to the background, so a deep translucent stack goes see-through at the 257th layer.shadow_lightsmax_shadow_lights(16,ALGAN_MAX_SHADOW_LIGHTS) shadowed lights per fragment. A compile-time vector length, so the surplus lights are still lit – they simply never cast. EachRectAreaLightemitter sample spends one slot, so a 4x4 area light fills the default cap alone.sheet_layers16 overlapping layers of one surface in one pixel (the conflict rank the sheet compaction packs into the sheet key). Layers past the 16th merge into the last sub-band and attenuate once between them instead of once each, so a self-overlapping morph renders too light.
dropped_continuationsA reflection/refraction continuation that could not reserve a slot in the tile’s shared ray pool. A splitting batch (
pool_ratio > 1) discards and retries the tile, so it never loses one; a batch atpool_ratio == 1has no spare slots at all and the reservation simply fails, dropping that branch’s contribution.closed_shell_ring4 declared closed shells simultaneously entered along one path-traced camera ray (
pt_shade’s per-ray ring, thesolid_shell_alphaceiling’s per-ray form). The surplus shell’s exit crossing composites again instead of being suppressed, so translucent solids nested more than four deep render slightly too opaque.medium_stackFour simultaneously tracked closed physical interiors. An overflowing path or visibility query is absorbed (fail-closed), never leaked to the sky.
medium_queryA containment/extinction query exhausted
max_surfaces_per_ray. Its result is absorbed rather than pretending unknown geometry was vacuum.
Reporting. Truncation is a correctness event, not a budgeting one, so the
first occurrence of each ceiling in a render is a WARNING – unlike the
wavefront’s pool retries and batch splits, which are the memory model working
as designed and log at PERF. Later batches of
the same render log their counts at PERF instead of repeating the warning,
because a scene that truncates one frame truncates all of them and a warning
per batch would be noise. The running totals ride on
RenderPlan either way, so a script
can assert on them without parsing logs.
Scope: one render job. _TruncationRecorder.reset() is called by
RenderLoopMixin.get_frames, which is the boundary of a
save_video / save_frame.
One non-truncation statistic rides here too: the path tracer’s mean samples
per pixel (record_path_samples()). It is not a ceiling and never
warns – adaptive sampling stopping a converged pixel is the sampler working
as designed, so it logs at PERF like the budget events – but it wants
exactly this module’s three properties: render-job scope, the same
snapshot/restore so a chunk discarded for memory does not count twice, and a
graft onto the frozen RenderPlan afterwards.
Classes
How many times each render ceiling bound during a render. |
Functions
- attach_render_stats(plan)[source]¶
Return
plancarrying the render job’s non-ceiling statistics.Today that is the path tracer’s mean samples per pixel, which adaptive sampling makes a measurement rather than an echo of
samples_per_pixel. Grafted like the truncations, and for the same reason:RenderPlanis frozen and is built before the batch renders.
- attach_truncations(plan)[source]¶
Return
plancarrying the render job’s truncation counts.RenderPlanis frozen and is built before the batch renders, so the counts are grafted on afterwards rather than mutated in place.
- path_samples_mean()[source]¶
Mean samples per pixel the path tracer took this render job (0 = none).
- Return type:
float
- record_path_samples(sample_sum, cells)[source]¶
Record one path-traced chunk’s samples:
sum(n_p)overcells.
- record_truncation(ceiling, count, cap=None)[source]¶
Count
countoccurrences of one ceiling binding.
- report_truncations()[source]¶
Log this batch’s truncations and return the running totals.
- Return type:
- reset_truncations()[source]¶
Begin a render job’s truncation accounting.
Called by
RenderLoopMixin.get_frames, so everysave_video/save_framereports its own render rather than inheriting the last one’s counts and its already-spent warnings.
- restore_truncations(counts)[source]¶
Roll the counts back to a snapshot (used by the OOM chunk retry).
- Parameters:
counts (TruncationCounts)