Skip to content

Commit

Permalink
fix synchronous sort tasks, change important task scheduling to be se…
Browse files Browse the repository at this point in the history
…parate from regular deferred task scheduling
  • Loading branch information
douira committed Dec 31, 2024
1 parent f76f7b1 commit b8ad5ef
Show file tree
Hide file tree
Showing 10 changed files with 191 additions and 134 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ public void setupTerrain(Camera camera,
float fogDistance = RenderSystem.getShaderFog().end();

if (this.lastCameraPos == null) {
this.lastCameraPos = new Vector3d(pos);
this.lastCameraPos = pos;
}
if (this.lastProjectionMatrix == null) {
this.lastProjectionMatrix = new Matrix4f(projectionMatrix);
Expand All @@ -218,7 +218,7 @@ public void setupTerrain(Camera camera,
profiler.popPush("translucent_triggering");

this.renderSectionManager.processGFNIMovement(new CameraMovement(this.lastCameraPos, pos));
this.lastCameraPos = new Vector3d(pos);
this.lastCameraPos = pos;
}

int maxChunkUpdates = updateChunksImmediately ? this.renderDistance : 1;
Expand All @@ -230,7 +230,7 @@ public void setupTerrain(Camera camera,
profiler.popPush("chunk_update");

this.renderSectionManager.cleanupAndFlip();
this.renderSectionManager.updateChunks(updateChunksImmediately);
this.renderSectionManager.updateChunks(viewport, updateChunksImmediately);

profiler.popPush("chunk_upload");

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package net.caffeinemc.mods.sodium.client.render.chunk;

/**
* NOTE: Update types with not-ALWAYS defer mode should be prefixed "important".
*/
public enum ChunkUpdateType {
SORT(DeferMode.ALWAYS, 2),
INITIAL_BUILD(DeferMode.ALWAYS, 0),
Expand Down Expand Up @@ -28,7 +31,7 @@ public static ChunkUpdateType getPromotionUpdateType(ChunkUpdateType prev, Chunk
}

public boolean isImportant() {
return this == IMPORTANT_REBUILD || this == IMPORTANT_SORT;
return this.deferMode != DeferMode.ALWAYS;
}

public DeferMode getDeferMode() {
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package net.caffeinemc.mods.sodium.client.render.chunk.async;

import it.unimi.dsi.fastutil.longs.LongArrayList;
import net.caffeinemc.mods.sodium.client.render.chunk.lists.TaskListCollection;
import net.caffeinemc.mods.sodium.client.render.chunk.lists.DeferredTaskList;
import net.caffeinemc.mods.sodium.client.render.chunk.occlusion.CullType;
import net.caffeinemc.mods.sodium.client.render.chunk.occlusion.OcclusionCuller;
import net.caffeinemc.mods.sodium.client.render.chunk.occlusion.RayOcclusionSectionTree;
Expand Down Expand Up @@ -46,7 +46,7 @@ public SectionTree getTree() {
}

@Override
public TaskListCollection getFrustumTaskLists() {
public DeferredTaskList getFrustumTaskLists() {
return frustumTaskLists;
}
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package net.caffeinemc.mods.sodium.client.render.chunk.async;

import net.caffeinemc.mods.sodium.client.render.chunk.lists.TaskListCollection;
import net.caffeinemc.mods.sodium.client.render.chunk.lists.DeferredTaskList;

public interface FrustumTaskListsResult {
TaskListCollection getFrustumTaskLists();
DeferredTaskList getFrustumTaskLists();
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package net.caffeinemc.mods.sodium.client.render.chunk.async;

import net.caffeinemc.mods.sodium.client.render.chunk.lists.TaskListCollection;
import net.caffeinemc.mods.sodium.client.render.chunk.lists.DeferredTaskList;
import net.caffeinemc.mods.sodium.client.render.chunk.lists.TaskSectionTree;

public interface GlobalCullResult extends FrustumTaskListsResult {
TaskSectionTree getTaskTree();

TaskListCollection getGlobalTaskLists();
DeferredTaskList getGlobalTaskLists();
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import it.unimi.dsi.fastutil.longs.LongArrayList;
import net.caffeinemc.mods.sodium.client.render.chunk.RenderSection;
import net.caffeinemc.mods.sodium.client.render.chunk.lists.FrustumTaskCollector;
import net.caffeinemc.mods.sodium.client.render.chunk.lists.TaskListCollection;
import net.caffeinemc.mods.sodium.client.render.chunk.lists.DeferredTaskList;
import net.caffeinemc.mods.sodium.client.render.chunk.lists.TaskSectionTree;
import net.caffeinemc.mods.sodium.client.render.chunk.occlusion.CullType;
import net.caffeinemc.mods.sodium.client.render.chunk.occlusion.OcclusionCuller;
Expand Down Expand Up @@ -56,12 +56,12 @@ public TaskSectionTree getTaskTree() {
}

@Override
public TaskListCollection getFrustumTaskLists() {
public DeferredTaskList getFrustumTaskLists() {
return frustumTaskLists;
}

@Override
public TaskListCollection getGlobalTaskLists() {
public DeferredTaskList getGlobalTaskLists() {
return globalTaskLists;
}
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
package net.caffeinemc.mods.sodium.client.render.chunk.lists;

import it.unimi.dsi.fastutil.longs.Long2ReferenceMap;
import it.unimi.dsi.fastutil.longs.LongArrayList;
import it.unimi.dsi.fastutil.longs.LongCollection;
import it.unimi.dsi.fastutil.longs.LongHeapPriorityQueue;
import net.caffeinemc.mods.sodium.client.render.chunk.DeferMode;
import net.caffeinemc.mods.sodium.client.render.chunk.RenderSection;
import net.minecraft.core.SectionPos;

import java.util.EnumMap;

public class TaskListCollection extends EnumMap<DeferMode, LongHeapPriorityQueue> {
public class DeferredTaskList extends LongHeapPriorityQueue {
private final long creationTime;
private final boolean isFrustumTested;
private final int baseOffsetX;
private final int baseOffsetZ;

public TaskListCollection(Class<DeferMode> keyType, long creationTime, boolean isFrustumTested, int baseOffsetX, int baseOffsetZ) {
super(keyType);
public static DeferredTaskList createHeapCopyOf(LongCollection copyFrom, long creationTime, boolean isFrustumTested, int baseOffsetX, int baseOffsetZ) {
return new DeferredTaskList(new LongArrayList(copyFrom), creationTime, isFrustumTested, baseOffsetX, baseOffsetZ);
}

private DeferredTaskList(LongArrayList copyFrom, long creationTime, boolean isFrustumTested, int baseOffsetX, int baseOffsetZ) {
super(copyFrom.elements(), copyFrom.size());
this.creationTime = creationTime;
this.isFrustumTested = isFrustumTested;
this.baseOffsetX = baseOffsetX;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public class PendingTaskCollector implements OcclusionCuller.GraphOcclusionVisit
static final float CLOSE_PROXIMITY_FACTOR = 0.6f; // penalty for being CLOSE_DISTANCE or farther away
static final float INV_MAX_DISTANCE_CLOSE = CLOSE_PROXIMITY_FACTOR / CLOSE_DISTANCE;

private final LongArrayList[] pendingTasks = new LongArrayList[DeferMode.values().length];
private final LongArrayList pendingTasks = new LongArrayList();

protected final boolean isFrustumTested;
protected final int baseOffsetX, baseOffsetY, baseOffsetZ;
Expand Down Expand Up @@ -67,7 +67,8 @@ public void visit(RenderSection section) {
protected void checkForTask(RenderSection section) {
ChunkUpdateType type = section.getPendingUpdate();

if (type != null && section.getTaskCancellationToken() == null) {
// collect non-important tasks (important tasks are handled separately)
if (type != null && !type.isImportant() && section.getTaskCancellationToken() == null) {
this.addPendingSection(section, type);
}
}
Expand All @@ -82,14 +83,8 @@ protected void addPendingSection(RenderSection section, ChunkUpdateType type) {
var localZ = section.getChunkZ() - this.baseOffsetZ;
long taskCoordinate = (long) (localX & 0b1111111111) << 20 | (long) (localY & 0b1111111111) << 10 | (long) (localZ & 0b1111111111);

var queue = this.pendingTasks[type.getDeferMode().ordinal()];
if (queue == null) {
queue = new LongArrayList();
this.pendingTasks[type.getDeferMode().ordinal()] = queue;
}

// encode the priority and the section position into a single long such that all parts can be later decoded
queue.add((long) MathUtil.floatToComparableInt(priority) << 32 | taskCoordinate);
this.pendingTasks.add((long) MathUtil.floatToComparableInt(priority) << 32 | taskCoordinate);
}

private float getSectionPriority(RenderSection section, ChunkUpdateType type) {
Expand Down Expand Up @@ -121,18 +116,8 @@ public static float decodePriority(long encoded) {
return MathUtil.comparableIntToFloat((int) (encoded >>> 32));
}

public TaskListCollection getPendingTaskLists() {
var result = new TaskListCollection(DeferMode.class, this.creationTime, this.isFrustumTested, this.baseOffsetX, this.baseOffsetZ);

for (var mode : DeferMode.values()) {
var list = this.pendingTasks[mode.ordinal()];
if (list != null) {
var queue = new LongHeapPriorityQueue(list.elements(), list.size());
result.put(mode, queue);
}
}

return result;
public DeferredTaskList getPendingTaskLists() {
return DeferredTaskList.createHeapCopyOf(this.pendingTasks, this.creationTime, this.isFrustumTested, this.baseOffsetX, this.baseOffsetZ);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ public int getFrame() {

public boolean isValidFor(Viewport viewport, float searchDistance) {
var cameraPos = viewport.getChunkCoord();
return Math.abs((this.cameraX >> 4) - cameraPos.getX()) <= this.bfsWidth &&
Math.abs((this.cameraY >> 4) - cameraPos.getY()) <= this.bfsWidth &&
Math.abs((this.cameraZ >> 4) - cameraPos.getZ()) <= this.bfsWidth &&
return Math.abs((this.cameraX >> 4) - cameraPos.getX()) <= this.bfsWidth &&
Math.abs((this.cameraY >> 4) - cameraPos.getY()) <= this.bfsWidth &&
Math.abs((this.cameraZ >> 4) - cameraPos.getZ()) <= this.bfsWidth &&
this.buildDistance >= searchDistance;
}

Expand Down Expand Up @@ -113,6 +113,11 @@ private boolean isSectionPresent(int x, int y, int z) {
return this.tree.getPresence(x, y, z) == Tree.PRESENT;
}

public boolean isSectionVisible(Viewport viewport, RenderSection section) {
return this.isSectionPresent(section.getChunkX(), section.getChunkY(), section.getChunkZ()) &&
this.isWithinFrustum(viewport, section);
}

public void traverse(VisibleSectionVisitor visitor, Viewport viewport, float distanceLimit) {
this.tree.traverse(visitor, viewport, distanceLimit);
}
Expand Down

0 comments on commit b8ad5ef

Please sign in to comment.