perf(light): seed the sky from the heightmap instead of every open cell - #41
Merged
Conversation
seedSky queued every position that sees the sky. On a chunk of 24 sections that is up to 98 304 entries, each popped again and expanded six ways to establish that all six neighbours are already at the full level. Lighting a position and queueing it are two different things, and this is where the difference is largest. A position whose four horizontal neighbours are open at the same height can raise nobody: above and below it the column is at the full level or blocked, and so is every neighbour. It still has to be lit, because the output and the border exchange read the levels, but it has no business in the queue. The walk down each column already finds where the sky stops, so it now keeps that per column. The positions that need queueing then fall out as a range rather than a test: a neighbouring column is dark below its own sky bottom, so a column has to queue from its own bottom up to the deepest bottom among its four neighbours. Above that line every neighbour is open. On an open chunk nothing is queued at all. The heightmap is one int per column, so it does not grow with the height of the chunk and is allocated once with the propagator. ChunkLightState#skyTopOf computes the same heightmap a second time, after the propagation. Handing this one over instead is a separate change and is not made here.
Contributor
Test results 201 files 201 suites 4m 5s ⏱️ Results for commit 153d31b. |
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.
From Project Status → Open → Smaller items:
seedSkyqueued every position that sees the sky — up to 98 304 entries for a 24-section chunk, eachpopped again and expanded six ways only to find that all six neighbours are already at the full
level.
Lighting a position and queueing it are two different things, and this is where the difference is
largest. A position whose four horizontal neighbours are open at the same height can raise nobody:
above and below it the column is at the full level or blocked, and so is every neighbour. It still
has to be lit — the output and the border exchange read the levels — but it has no business in the
queue.
The walk down each column already finds where the sky stops, so it now keeps that. The positions that
need queueing then fall out as a range rather than a per-position test: a neighbouring column is
dark below its own sky bottom, so a column queues from its own bottom up to the deepest bottom among
its four neighbours. Above that line every neighbour is open. On a fully open chunk nothing is
queued at all.
The heightmap is one
intper column, so it does not grow with the height of the chunk and isallocated once with the propagator.
The part worth reading: it took three attempts to build a test that could fail
The first check of this change was that all 212 tests passed. They also passed with the queued range
deliberately shortened by one position — the plainest way to get this wrong. So the suite proved
nothing about it, and the change had no coverage at all.
The second and third failures have the same cause and it is not obvious. The position where a
column's sky stops is the blocker, and a blocker that occludes every face takes no light from the
side either. So the topmost position of the queued range has nowhere to give its light, and getting
that edge wrong is invisible against solid stone no matter how varied the terrain is.
A slab stops the sky from above and accepts light from its four sides. That is the only shape that
separates a correct range from one position short of it — and it is exactly the case
SectionOpacitystores occlusion per face for.SkyHeightmapSeedTest(new, 6 tests) compares against the algorithm this commit replaces, writtenout in the test rather than called, so the oracle shares no code with what it checks. Four
configurations use stone and two use slabs; only the slab ones catch the off-by-one, and the class
javadoc says so, because the next person to add a case here will otherwise reach for stone.
./gradlew buildis green.What I expect the measurement to say, so it can be wrong
Running the same pair of classes through the
Benchmarkworkflow, three forks,mainagainst thisbranch, with
falcoReadStatesandminestomFullas untouched controls in the same job.Two predictions, stated before the numbers arrive:
propagateSkyimproves at every height, andpropagate— block light, which does not gothrough
seedSky— does not move. That second half is a control with an expected answer of zero.flat column plus
seedSky, and only the queueing goes away here; the walk down each columnstill reads the flat array. If the regression survives, that attribution was half right and the
walk is the remaining half.