Skip to content

Commit ecdd040

Browse files
committed
fix some issues with very delayed section sorting. There are still other issues with (at least vertical) sorting though and even important zero-frame blocking tasks are not scheduled within the same frame
1 parent f969cbb commit ecdd040

File tree

3 files changed

+47
-26
lines changed

3 files changed

+47
-26
lines changed

common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/RenderSectionManager.java

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -110,11 +110,7 @@ public class RenderSectionManager {
110110
private @Nullable BlockPos cameraBlockPos;
111111
private @Nullable Vector3dc cameraPosition;
112112

113-
private final ExecutorService asyncCullExecutor = Executors.newSingleThreadExecutor(runnable -> {
114-
Thread thread = new Thread(runnable);
115-
thread.setName("Sodium Async Cull Thread");
116-
return thread;
117-
});
113+
private final ExecutorService asyncCullExecutor = Executors.newSingleThreadExecutor(RenderSectionManager::makeAsyncCullThread);
118114
private final ObjectArrayList<AsyncRenderTask<?>> pendingTasks = new ObjectArrayList<>();
119115
private SectionTree renderTree = null;
120116
private TaskSectionTree globalTaskTree = null;
@@ -277,6 +273,12 @@ private SectionTree unpackTaskResults(boolean wait) {
277273
return latestTree;
278274
}
279275

276+
private static Thread makeAsyncCullThread(Runnable runnable) {
277+
Thread thread = new Thread(runnable);
278+
thread.setName("Sodium Async Cull Thread");
279+
return thread;
280+
}
281+
280282
private void scheduleAsyncWork(Camera camera, Viewport viewport, boolean spectator) {
281283
// submit tasks of types that are applicable and not yet running
282284
AsyncRenderTask<?> currentRunningTask = null;
@@ -902,6 +904,24 @@ public int getVisibleChunkCount() {
902904
return sections;
903905
}
904906

907+
// 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
908+
// maybe intercept tasks that are scheduled in zero- or one-frame defer mode?
909+
// collect and prioritize regardless of visibility if it's an important defer mode?
910+
// TODO: vertical sorting seems to be broken?
911+
private ChunkUpdateType upgradePendingUpdate(RenderSection section, ChunkUpdateType type) {
912+
var current = section.getPendingUpdate();
913+
type = ChunkUpdateType.getPromotionUpdateType(current, type);
914+
915+
section.setPendingUpdate(type, this.lastFrameAtTime);
916+
917+
// if the section received a new task, mark in the task tree so an update can happen before a global cull task runs
918+
if (this.globalTaskTree != null && type != null && current == null) {
919+
this.globalTaskTree.markSectionTask(section);
920+
}
921+
922+
return type;
923+
}
924+
905925
public void scheduleSort(long sectionPos, boolean isDirectTrigger) {
906926
RenderSection section = this.sectionByPosition.get(sectionPos);
907927

@@ -912,9 +932,8 @@ public void scheduleSort(long sectionPos, boolean isDirectTrigger) {
912932
|| priorityMode == PriorityMode.NEARBY && this.shouldPrioritizeTask(section, NEARBY_SORT_DISTANCE)) {
913933
pendingUpdate = ChunkUpdateType.IMPORTANT_SORT;
914934
}
915-
pendingUpdate = ChunkUpdateType.getPromotionUpdateType(section.getPendingUpdate(), pendingUpdate);
916-
if (pendingUpdate != null) {
917-
section.setPendingUpdate(pendingUpdate, this.lastFrameAtTime);
935+
936+
if (this.upgradePendingUpdate(section, pendingUpdate) != null) {
918937
section.prepareTrigger(isDirectTrigger);
919938
}
920939
}
@@ -936,10 +955,7 @@ public void scheduleRebuild(int x, int y, int z, boolean important) {
936955
pendingUpdate = ChunkUpdateType.REBUILD;
937956
}
938957

939-
pendingUpdate = ChunkUpdateType.getPromotionUpdateType(section.getPendingUpdate(), pendingUpdate);
940-
if (pendingUpdate != null) {
941-
section.setPendingUpdate(pendingUpdate, this.lastFrameAtTime);
942-
958+
if (this.upgradePendingUpdate(section, pendingUpdate) != null) {
943959
this.markGraphDirty();
944960
}
945961
}

common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/lists/TaskSectionTree.java

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,27 +10,32 @@
1010

1111
public class TaskSectionTree extends RayOcclusionSectionTree {
1212
private final TraversableForest taskTree;
13+
private boolean taskTreeFinalized = false;
1314

1415
public TaskSectionTree(Viewport viewport, float buildDistance, int frame, CullType cullType, Level level) {
1516
super(viewport, buildDistance, frame, cullType, level);
1617

1718
this.taskTree = TraversableForest.createTraversableForest(this.baseOffsetX, this.baseOffsetY, this.baseOffsetZ, buildDistance, level);
1819
}
1920

20-
@Override
21-
protected void addPendingSection(RenderSection section, ChunkUpdateType type) {
22-
super.addPendingSection(section, type);
23-
21+
public void markSectionTask(RenderSection section) {
2422
this.taskTree.add(section.getChunkX(), section.getChunkY(), section.getChunkZ());
23+
this.taskTreeFinalized = false;
2524
}
2625

2726
@Override
28-
public void finalizeTrees() {
29-
super.finalizeTrees();
30-
this.taskTree.calculateReduced();
27+
protected void addPendingSection(RenderSection section, ChunkUpdateType type) {
28+
super.addPendingSection(section, type);
29+
30+
this.markSectionTask(section);
3131
}
3232

3333
public void traverseVisiblePendingTasks(VisibleSectionVisitor visitor, Viewport viewport, float distanceLimit) {
34+
if (!this.taskTreeFinalized) {
35+
this.taskTree.calculateReduced();
36+
this.taskTreeFinalized = true;
37+
}
38+
3439
this.taskTree.traverse(visitor, viewport, distanceLimit);
3540
}
3641
}

common/src/main/java/net/caffeinemc/mods/sodium/client/render/chunk/tree/BaseBiForest.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,14 @@ protected T makeSecondaryTree() {
2424

2525
@Override
2626
public void add(int x, int y, int z) {
27-
if (!this.mainTree.add(x, y, z)) {
28-
if (this.secondaryTree == null) {
29-
this.secondaryTree = this.makeSecondaryTree();
30-
}
31-
if (!this.secondaryTree.add(x, y, z)) {
32-
throw new IllegalStateException("Failed to add section to trees");
33-
}
27+
if (this.mainTree.add(x, y, z)) {
28+
return;
3429
}
30+
31+
if (this.secondaryTree == null) {
32+
this.secondaryTree = this.makeSecondaryTree();
33+
}
34+
this.secondaryTree.add(x, y, z);
3535
}
3636

3737
@Override

0 commit comments

Comments
 (0)