From 7d0c8b1e2f76223e9debcc7a6789bf0c53e0c43a Mon Sep 17 00:00:00 2001 From: douira Date: Wed, 20 Nov 2024 17:58:56 +0100 Subject: [PATCH] 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 --- .../client/render/chunk/RenderSection.java | 24 +++++++++++++++---- .../render/chunk/RenderSectionManager.java | 16 +++++++------ 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/RenderSection.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/RenderSection.java index 0103850155..9c8e9f8d28 100644 --- a/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/RenderSection.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/RenderSection.java @@ -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; } /** diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/RenderSectionManager.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/RenderSectionManager.java index 516255ecac..8cbfe8ed70 100644 --- a/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/RenderSectionManager.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/RenderSectionManager.java @@ -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; } @@ -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; } @@ -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(); @@ -317,8 +319,7 @@ private boolean processChunkBuildResults(ArrayList 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); @@ -346,13 +347,13 @@ private boolean processChunkBuildResults(ArrayList 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; } } @@ -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; } }