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 8dc56707c3..671c094829 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 @@ -106,6 +106,7 @@ public class RenderSectionManager { private boolean needsGraphUpdate = true; private boolean needsRenderListUpdate = true; private boolean cameraChanged = false; + private boolean needsFrustumTaskListUpdate = true; private @Nullable BlockPos cameraBlockPos; private @Nullable Vector3dc cameraPosition; @@ -154,6 +155,7 @@ public void updateRenderLists(Camera camera, Viewport viewport, boolean spectato this.frame += 1; this.needsRenderListUpdate |= this.cameraChanged; + this.needsFrustumTaskListUpdate |= this.needsRenderListUpdate; // do sync bfs based on update immediately (flawless frames) or if the camera moved too much var shouldRenderSync = this.cameraTimingControl.getShouldRenderSync(camera); @@ -186,11 +188,15 @@ public void updateRenderLists(Camera camera, Viewport viewport, boolean spectato this.scheduleAsyncWork(camera, viewport, spectator); + if (this.needsFrustumTaskListUpdate) { + this.updateFrustumTaskList(viewport); + } if (this.needsRenderListUpdate) { processRenderListUpdate(viewport); } this.needsRenderListUpdate = false; + this.needsFrustumTaskListUpdate = false; this.needsGraphUpdate = false; this.cameraChanged = false; } @@ -341,7 +347,7 @@ private CullType[] getScheduleOrder() { private static final LongArrayList timings = new LongArrayList(); - private void processRenderListUpdate(Viewport viewport) { + private void updateFrustumTaskList(Viewport viewport) { // schedule generating a frustum task list if there's no frustum tree task running if (this.globalTaskTree != null) { var frustumTaskListPending = false; @@ -359,7 +365,9 @@ private void processRenderListUpdate(Viewport viewport) { this.pendingTasks.add(task); } } + } + private void processRenderListUpdate(Viewport viewport) { // pick the narrowest up-to-date tree, if this tree is insufficiently up to date we would've switched to sync bfs earlier SectionTree bestTree = null; boolean bestTreeValid = false; @@ -907,7 +915,6 @@ public int getVisibleChunkCount() { // TODO: this fixes very delayed tasks, but it still regresses on same-frame tasks that don't get to run in time because the frustum task collection task takes at least one (and usually only one) frame to run // maybe intercept tasks that are scheduled in zero- or one-frame defer mode? // collect and prioritize regardless of visibility if it's an important defer mode? - // TODO: vertical sorting seems to be broken? private ChunkUpdateType upgradePendingUpdate(RenderSection section, ChunkUpdateType type) { var current = section.getPendingUpdate(); type = ChunkUpdateType.getPromotionUpdateType(current, type); @@ -917,6 +924,7 @@ private ChunkUpdateType upgradePendingUpdate(RenderSection section, ChunkUpdateT // if the section received a new task, mark in the task tree so an update can happen before a global cull task runs if (this.globalTaskTree != null && type != null && current == null) { this.globalTaskTree.markSectionTask(section); + this.needsFrustumTaskListUpdate = true; } return type; @@ -955,13 +963,7 @@ public void scheduleRebuild(int x, int y, int z, boolean important) { pendingUpdate = ChunkUpdateType.REBUILD; } - pendingUpdate = ChunkUpdateType.getPromotionUpdateType(section.getPendingUpdate(), pendingUpdate); - if (pendingUpdate != null) { - section.setPendingUpdate(pendingUpdate, this.lastFrameAtTime); - - // force update to schedule rebuild task on this section - this.markGraphDirty(); - } + this.upgradePendingUpdate(section, pendingUpdate); } } diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/lists/PendingTaskCollector.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/lists/PendingTaskCollector.java index 7aba4099a8..ba3ae036f7 100644 --- a/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/lists/PendingTaskCollector.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/lists/PendingTaskCollector.java @@ -41,12 +41,11 @@ public PendingTaskCollector(Viewport viewport, float buildDistance, boolean frus this.isFrustumTested = frustumTested; var offsetDistance = Mth.ceil(buildDistance / 16.0f) + 1; - var transform = viewport.getTransform(); - // the offset applied to section coordinates to encode their position in the octree - var cameraSectionX = transform.intX >> 4; - var cameraSectionY = transform.intY >> 4; - var cameraSectionZ = transform.intZ >> 4; + var sectionPos = viewport.getChunkCoord(); + var cameraSectionX = sectionPos.getX(); + var cameraSectionY = sectionPos.getY(); + var cameraSectionZ = sectionPos.getZ(); this.baseOffsetX = cameraSectionX - offsetDistance; this.baseOffsetY = cameraSectionY - offsetDistance; this.baseOffsetZ = cameraSectionZ - offsetDistance; @@ -54,9 +53,10 @@ public PendingTaskCollector(Viewport viewport, float buildDistance, boolean frus this.invMaxDistance = PROXIMITY_FACTOR / buildDistance; if (frustumTested) { - this.cameraX = transform.intX; - this.cameraY = transform.intY; - this.cameraZ = transform.intZ; + var blockPos = viewport.getBlockCoord(); + this.cameraX = blockPos.getX(); + this.cameraY = blockPos.getY(); + this.cameraZ = blockPos.getZ(); } else { this.cameraX = (cameraSectionX << 4); this.cameraY = (cameraSectionY << 4); diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/occlusion/SectionTree.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/occlusion/SectionTree.java index 4132111d85..3721a298ed 100644 --- a/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/occlusion/SectionTree.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/occlusion/SectionTree.java @@ -42,13 +42,10 @@ public int getFrame() { } public boolean isValidFor(Viewport viewport, float searchDistance) { - var transform = viewport.getTransform(); - var cameraSectionX = transform.intX >> 4; - var cameraSectionY = transform.intY >> 4; - var cameraSectionZ = transform.intZ >> 4; - return this.cameraX >> 4 == cameraSectionX && - this.cameraY >> 4 == cameraSectionY && - this.cameraZ >> 4 == cameraSectionZ && + var cameraPos = viewport.getChunkCoord(); + return this.cameraX >> 4 == cameraPos.getX() && + this.cameraY >> 4 == cameraPos.getY() && + this.cameraZ >> 4 == cameraPos.getZ() && this.buildDistance >= searchDistance; } diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/tree/AbstractTraversableMultiForest.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/tree/AbstractTraversableMultiForest.java index eb758d8e36..b8673fc5a7 100644 --- a/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/tree/AbstractTraversableMultiForest.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/tree/AbstractTraversableMultiForest.java @@ -20,10 +20,10 @@ public void calculateReduced() { @Override public void traverse(SectionTree.VisibleSectionVisitor visitor, Viewport viewport, float distanceLimit) { - var transform = viewport.getTransform(); - var cameraSectionX = transform.intX >> 4; - var cameraSectionY = transform.intY >> 4; - var cameraSectionZ = transform.intZ >> 4; + var cameraPos = viewport.getChunkCoord(); + var cameraSectionX = cameraPos.getX(); + var cameraSectionY = cameraPos.getY(); + var cameraSectionZ = cameraPos.getZ(); // sort the trees by distance from the camera by sorting a packed index array. var items = new int[this.trees.length]; diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/tree/TraversableTree.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/tree/TraversableTree.java index a1dda59668..26fb9b227d 100644 --- a/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/tree/TraversableTree.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/tree/TraversableTree.java @@ -61,13 +61,12 @@ public void traverse(SectionTree.VisibleSectionVisitor visitor, Viewport viewpor this.viewport = viewport; this.distanceLimit = distanceLimit; - var transform = viewport.getTransform(); - // + 1 to offset section position to compensate for shifted global offset // adjust camera block position to account for fractional part of camera position - this.cameraOffsetX = ((transform.intX + (int) Math.signum(transform.fracX)) >> 4) - this.offsetX + 1; - this.cameraOffsetY = ((transform.intY + (int) Math.signum(transform.fracY)) >> 4) - this.offsetY + 1; - this.cameraOffsetZ = ((transform.intZ + (int) Math.signum(transform.fracZ)) >> 4) - this.offsetZ + 1; + var sectionPos = viewport.getChunkCoord(); + this.cameraOffsetX = sectionPos.getX() - this.offsetX + 1; + this.cameraOffsetY = sectionPos.getY() - this.offsetY + 1; + this.cameraOffsetZ = sectionPos.getZ() - this.offsetZ + 1; // everything is already inside the distance limit if the build distance is smaller var initialInside = this.distanceLimit >= buildDistance ? INSIDE_DISTANCE : 0;