Skip to content

Commit

Permalink
Avoid marking the section graph as dirty if state didn't change (Caff…
Browse files Browse the repository at this point in the history
…eineMC#2886)

Avoids rebuilding the render lists and doing a graph search
more often than necessary by checking if the section actually
changed in a way that's relevant to the graph search.

For worlds that update their blocks frequently (every tick or
every redstone tick) this avoids half the graph searches. Some
graph searches are still necessary to schedule rebuild tasks,
but when the task results come back, this doesn't do another
graph search unless the section's visibility data or build state
changed in a way that needs the render list to be updated.
  • Loading branch information
douira authored and ThatMG393 committed Dec 15, 2024
1 parent 0bb2046 commit 535b84e
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -139,30 +139,44 @@ public void delete() {
this.disposed = true;
}

public void setInfo(@Nullable BuiltSectionInfo info) {
public boolean setInfo(@Nullable BuiltSectionInfo info) {
if (info != null) {
this.setRenderState(info);
return this.setRenderState(info);
} else {
this.clearRenderState();
return this.clearRenderState();
}
}

private void setRenderState(@NotNull BuiltSectionInfo info) {
private boolean setRenderState(@NotNull BuiltSectionInfo info) {
var prevBuilt = this.built;
var prevFlags = this.flags;
var prevVisibilityData = this.visibilityData;

this.built = true;
this.flags = info.flags;
this.visibilityData = info.visibilityData;

this.globalBlockEntities = info.globalBlockEntities;
this.culledBlockEntities = info.culledBlockEntities;
this.animatedSprites = info.animatedSprites;

// the section is marked as having received graph-relevant changes if it's build state, flags, or connectedness has changed.
// the entities and sprites don't need to be checked since whether they exist is encoded in the flags.
return !prevBuilt || prevFlags != this.flags || prevVisibilityData != this.visibilityData;
}

private void clearRenderState() {
private boolean clearRenderState() {
var wasBuilt = this.built;

this.built = false;
this.flags = RenderSectionFlags.NONE;
this.visibilityData = VisibilityEncoding.NULL;
this.globalBlockEntities = null;
this.culledBlockEntities = null;
this.animatedSprites = null;

// changes to data if it moves from built to not built don't matter, so only build state changes matter
return wasBuilt;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ public void onSectionAdded(int x, int y, int z) {

this.connectNeighborNodes(renderSection);

// force update to schedule build task
this.needsGraphUpdate = true;
}

Expand All @@ -235,6 +236,7 @@ public void onSectionRemoved(int x, int y, int z) {

section.delete();

// force update to remove section from render lists
this.needsGraphUpdate = true;
}

Expand Down Expand Up @@ -301,7 +303,7 @@ public void uploadChunks() {
// (sort results never change the graph)
// generally there's no sort results without a camera movement, which would also trigger
// a graph update, but it can sometimes happen because of async task execution
this.needsGraphUpdate = this.needsGraphUpdate || this.processChunkBuildResults(results);
this.needsGraphUpdate |= this.processChunkBuildResults(results);

for (var result : results) {
result.destroy();
Expand All @@ -317,8 +319,7 @@ private boolean processChunkBuildResults(ArrayList<BuilderTaskOutput> results) {
for (var result : filtered) {
TranslucentData oldData = result.render.getTranslucentData();
if (result instanceof ChunkBuildOutput chunkBuildOutput) {
this.updateSectionInfo(result.render, chunkBuildOutput.info);
touchedSectionInfo = true;
touchedSectionInfo |= this.updateSectionInfo(result.render, chunkBuildOutput.info);

if (chunkBuildOutput.translucentData != null) {
this.sortTriggering.integrateTranslucentData(oldData, chunkBuildOutput.translucentData, this.cameraPosition, this::scheduleSort);
Expand Down Expand Up @@ -346,13 +347,13 @@ private boolean processChunkBuildResults(ArrayList<BuilderTaskOutput> results) {
return touchedSectionInfo;
}

private void updateSectionInfo(RenderSection render, BuiltSectionInfo info) {
render.setInfo(info);
private boolean updateSectionInfo(RenderSection render, BuiltSectionInfo info) {
var infoChanged = render.setInfo(info);

if (info == null || ArrayUtils.isEmpty(info.globalBlockEntities)) {
this.sectionsWithGlobalEntities.remove(render);
return this.sectionsWithGlobalEntities.remove(render) || infoChanged;
} else {
this.sectionsWithGlobalEntities.add(render);
return this.sectionsWithGlobalEntities.add(render) || infoChanged;
}
}

Expand Down Expand Up @@ -609,6 +610,7 @@ public void scheduleRebuild(int x, int y, int z, boolean important) {
if (pendingUpdate != null) {
section.setPendingUpdate(pendingUpdate);

// force update to schedule rebuild task on this section
this.needsGraphUpdate = true;
}
}
Expand Down

0 comments on commit 535b84e

Please sign in to comment.