Shadows: the sun's floor pages are asked only over the scene box (#763) - #779
Merged
Merged
Conversation
… its views and batches (#525)
…frame, the harness a fixture (#525)
…-request pass spans the list's cap (#525)
… requestPage, and its word offset is pinned to the layout (#525)
…red only when it wraps (#525)
…s a wrap clears it (#525)
…o a dropped frame cannot lose it; an empty catalogue writes no stamp (#525)
…iew's whole reach; loops A and B reverted (#525)
…d the staling boxes (#525)
…unded along the sun's axis bounds no floor (#525)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #763
What changed
Why a page was evicted, then asked for again, while the frame's request fit the pool
The measurer's run (sponza 3456×2234,
--camera-mobile) gave about 1 670 pages requested a frame, a pool full at 4 096 of 4 096, and about 130 refetches a frame. The pool's eviction order is sound:pool.takeevicts only a page that no report since the latest one named;requests.askraisesrequestedfor every page a report names, drawn or not.What held the pool was the sun's floor. Every frame,
requests.floors()asks, as if the latest report had named them, for every last-level page within the view's far distance (sunLevels.tsfloorReach), whether or not anything lies under it:farisradius · 20≈ 356 m, and the last level has 16 m pages. That makes about 2 100 floor pages, over 30 × 14 m of scene and hundreds of metres of empty ground.The fix:
floorReachis bounded by the scene box's rectangle on the light plane, one page around it for the normal offset and the PCF (sunLevels.ts).sunBoxRect(math.ts), now shared with the staling boxes ofinvalidate.ts, which had their own copy.askFloor, unchanged).A scratch model (not committed) ran the real plan and pool under the bench's trajectory: sponza's box, receivers on its floor, walls and two galleries, 3456 × 2234, and a two-frame report lag. Results:
The pool's size is not the cause. The model's requests stay under 1 500 while the pool holds 4 096. So the pool is not resized and no MB is added.
What a "refetch" counts
pool.refetchedis cumulative. It counts a table entry mapped again after the pool evicted what it held, at any later frame. A sun entry is a ring slot of its level: when a clipmap window pans, a different absolute page takes the slot. So the counter also counts a new page landing on a slot whose earlier page was evicted. In the model, before the fix, it read 353 where 156 pages really came back. It does not count pages released because they left the window.The CTO's three points
pool.take.Loops A and B, reverted
The measurer's run on the previous round showed they did not change the stage, and they are reverted (measured first):
What each did:
LIST_FULLredraws, which the counters did not show.light-cut-redrawpages.Proof
packages/sdk-core/src/scene/light-shadow/dollyRefetch.test.ts,a dolly over a small scene whose reads fit the pool evicts nothing it reads again.develop: 880 floor pages held and 1 864 refetches.sunLevels.ts; I checked by putting it back.sunLevels.test.ts: an empty box, a plane unbounded along x, and a box unbounded along the sun's axis leave the floor the view's whole reach (reviewer).visibility/shader/spriteShadowCut.test.ts,the shadow scene box follows a pose the engine moved, with no table change(reviewer): fails on develop'ssceneBox.ts.invalidate.ts' staling through the shared rectangle.origin/develop(368d8e723):check:changedandtest:changed: 2 609 pass, 0 fail;validate --group quickand--group typescript: OK;check-pr-size.ts: 180 hand-written lines.Local review before push
simplifyskill, 4 agents (reuse, simplification, efficiency, altitude), on the whole diff againstdevelop.boxRect, notextent, which the clipmap already names; thefloorReachdoc says why no page is needed past the box (no caster there: a receiver there is lit).sunBoxRect's corner loop (about 100 ns a sun a frame); a default offset forsunBoxRect; the fixture'splanFramebox.code-review --fixskill, 6 findings.drive-a-car) bumps the scene revision alone, so an object leaving a small scene lost its pre-asked floor for the report lag. The box now followsrevisions.scenetoo (sceneBox.ts,encodeShadows.ts), with a test that fails on develop.Int32Arraystored as 0; the guard now tests both ends, with a test.shadowFactorWgsl.ts,requests.ts,sceneBox.tsandlights.tssay the floor spans the box, not the view's reach.sunPageMeetsis exactly develop's (rects[2],rects[3]are develop's-rects[3],-rects[2]), soinvalidate.tsstales the same pages; loops A and B are fully reverted (nogpu/dagfile differs fromdevelop); a receiver at the box's edge is covered, the normal offset plus the PCF reach being a few texels of a 128-texel page; transparents are selection roots, inside the box; the engine has no skinning.drive-a-car's pages a frame say whether it matters.develop(dollyRefetch.test.ts, the scene-box test); no image loss found; §Streaming, memory and shadows: no pool or MB change, the floor bound follows rule 6 (bounded by the scene, not the view's reach). Not delivered by this branch: "Shadows within 2 ms of GPU", which only the measurer's run proves;Closes #525stands on that run.simplifyskill, 4 agents (reuse, simplification, efficiency, altitude).invalidate.ts(sunRect, rows up the axis). There is now onesunBoxRectinmath.ts, rows down the axis, used by both, andsunPageMeetsis rewritten on it.floor; no scratch corner; the floor count moved after the test's loop.planFrame, which would save 3 lines.code-review --fixskill, no correctness bug.sunPageMeetssign is equivalent to the old code.sunLevels.test.tscase covers the no-box path.askFloormaps its floor as before, so the still image is unchanged.Lead verification
packages/sdk-core/src/scene/light-shadow/sunLevels.ts(floorReachbounded by the scene box's rectangle on the light plane, plus one page), withmath.tssunBoxRectshared withinvalidate.ts. The scene box also follows engine moves, inpackages/sdk-browser/src/webgpu/shadow/sceneBox.tsandencodeShadows.ts. Proved bydollyRefetch.test.ts:25"a dolly over a small scene whose reads fit the pool evicts nothing it reads again" (fails on develop), thesunLevels.test.tsunbounded-box case, andspriteShadowCut.test.ts:77"the shadow scene box follows a pose the engine moved, with no table change" (fails on develop).gpu/dagfile differs from develop.Before merge:
dollyRefetch.test.tsand the scene-box test fail on develop's sources. They use the real plan and pool, with no fixed delays.sunBoxRectreplacesinvalidate.ts's own copy;sunPageMeetsis proved equivalent (rects[2]/[3]are develop's-rects[3]/-rects[2]). There is no other new export.shadowFactorWgsl.ts,requests.ts,sceneBox.tsandlights.tsnow say the floor spans the box. This body describes this diff and closes The sun's floor shadow pages are asked only inside the scene, never across the whole far distance #763.in reviewnow,to measureat the hand-over.Not proven / left out
The measurer proves the branch before the pull request opens, sponza, branch against
develop:node bench/runner/bench.ts --moteur webgpu --apres dist --scene sponza --soleil --textures cache --pixelError 0 --vues generale --largeur 3456 --hauteur 2234 --camera-mobile --images 120Read per frame, from
ombresParImage:shadowPagesRefetchedper frame: the key number. Target: refetches per frame about equal to the newly exposed pages, near 0 on this dolly.shadowPagesDrawn(mean, p95, max);shadowPoolPagesagainst 4 096;Also:
shadowPagesDrawnsettles it.develop.If the refetches fall and the stage stays over 2 ms, the remaining exact route is per-page occlusion culling of casters, which goes to the CTO for a split.