diff --git a/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/ChunkRenderManager.java b/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/ChunkRenderManager.java index 9af8bfb29..5a9e5d605 100644 --- a/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/ChunkRenderManager.java +++ b/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/ChunkRenderManager.java @@ -552,25 +552,39 @@ public void updateChunks() { continue; } - // Do not allow distant chunks to block rendering - if (this.alwaysDeferChunkUpdates || !this.isChunkPrioritized(render)) { - this.builder.deferRebuild(render); + CompletableFuture> futureTask = this.builder.scheduleRebuildTaskAsync(render); + + if (futureTask != null) { + this.dirty = true; + + // Do not allow distant chunks to block rendering + if (this.alwaysDeferChunkUpdates || !this.isChunkPrioritized(render)) { + this.builder.handleCompletion(futureTask); + } else { + futures.add(futureTask); + } + + submitted++; + // Limit quantity of updates submitted if we are deferring all important builds + if (this.alwaysDeferChunkUpdates && submitted >= budget) + break; } else { - futures.add(this.builder.scheduleRebuildTaskAsync(render)); + // Immediately submit empty data to the queue and do not count this against the budget + this.builder.enqueueUpload(new ChunkBuildResult<>(render, ChunkRenderData.EMPTY)); } - - this.dirty = true; - submitted++; - // Limit quantity of updates submitted if we are deferring all important builds - if (this.alwaysDeferChunkUpdates && submitted >= budget) - break; } while (submitted < budget && !this.rebuildQueue.isEmpty()) { ChunkRenderContainer render = this.rebuildQueue.dequeue(); - this.builder.deferRebuild(render); - submitted++; + CompletableFuture> futureTask = this.builder.scheduleRebuildTaskAsync(render); + if(futureTask != null) { + this.builder.handleCompletion(futureTask); + submitted++; + } else { + // Immediately submit empty data to the queue and do not count this against the budget + this.builder.enqueueUpload(new ChunkBuildResult<>(render, ChunkRenderData.EMPTY)); + } } // always do at least one sort diff --git a/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/compile/ChunkBuilder.java b/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/compile/ChunkBuilder.java index cfea0069c..e3a839259 100644 --- a/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/compile/ChunkBuilder.java +++ b/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/compile/ChunkBuilder.java @@ -10,7 +10,6 @@ import me.jellysquid.mods.sodium.client.render.chunk.ChunkRenderBackend; import me.jellysquid.mods.sodium.client.render.chunk.ChunkRenderContainer; import me.jellysquid.mods.sodium.client.render.chunk.tasks.ChunkRenderBuildTask; -import me.jellysquid.mods.sodium.client.render.chunk.tasks.ChunkRenderEmptyBuildTask; import me.jellysquid.mods.sodium.client.render.chunk.tasks.ChunkRenderRebuildTask; import me.jellysquid.mods.sodium.client.render.chunk.tasks.ChunkRenderTranslucencySortTask; import me.jellysquid.mods.sodium.client.render.pipeline.context.ChunkRenderCacheLocal; @@ -26,6 +25,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.joml.Vector3d; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Deque; @@ -294,7 +294,10 @@ private static int getMaxThreadCount() { return Runtime.getRuntime().availableProcessors(); } - private void handleCompletion(CompletableFuture> future) { + /** + * Add a completion handler to the given future task so that the result will be processed on the main thread. + */ + public void handleCompletion(CompletableFuture> future) { future.whenComplete((res, ex) -> { if (ex != null) { this.failureQueue.add(ex); @@ -304,16 +307,6 @@ private void handleCompletion(CompletableFuture> future) { }); } - /** - * Creates a rebuild task and defers it to the work queue. When the task is completed, it will be moved onto the - * completed uploads queued which will then be drained during the next available synchronization point with the - * main thread. - * @param render The render to rebuild - */ - public void deferRebuild(ChunkRenderContainer render) { - handleCompletion(this.scheduleRebuildTaskAsync(render)); - } - /** * Creates a rebuild task and defers it to the work queue. When the task is completed, it will be moved onto the * completed uploads queued which will then be drained during the next available synchronization point with the @@ -330,16 +323,24 @@ public void deferSort(ChunkRenderContainer render) { * synchronization point on the main thread. * @param result The build task's result */ - private void enqueueUpload(ChunkBuildResult result) { + public void enqueueUpload(ChunkBuildResult result) { this.uploadQueue.add(result); } /** * Schedules the rebuild task asynchronously on the worker pool, returning a future wrapping the task. * @param render The render to rebuild + * @return a future representing the rebuild task, or null if the chunk section is empty */ + @Nullable public CompletableFuture> scheduleRebuildTaskAsync(ChunkRenderContainer render) { - return this.schedule(this.createRebuildTask(render)); + ChunkRenderBuildTask task = this.createRebuildTask(render); + + if(task != null) { + return this.schedule(task); + } else { + return null; + } } /** @@ -360,7 +361,7 @@ private ChunkRenderBuildTask createRebuildTask(ChunkRenderContainer render ChunkRenderContext context = WorldSlice.prepare(this.world, render.getChunkPos(), this.sectionCache); if (context == null) { - return new ChunkRenderEmptyBuildTask<>(render); + return null; } else { return new ChunkRenderRebuildTask<>(render, context, render.getRenderOrigin()).withCameraPosition(this.cameraPosition); } diff --git a/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/tasks/ChunkRenderEmptyBuildTask.java b/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/tasks/ChunkRenderEmptyBuildTask.java deleted file mode 100644 index b91532f62..000000000 --- a/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/tasks/ChunkRenderEmptyBuildTask.java +++ /dev/null @@ -1,33 +0,0 @@ -package me.jellysquid.mods.sodium.client.render.chunk.tasks; - -import me.jellysquid.mods.sodium.client.render.chunk.ChunkGraphicsState; -import me.jellysquid.mods.sodium.client.render.chunk.ChunkRenderContainer; -import me.jellysquid.mods.sodium.client.render.chunk.compile.ChunkBuildBuffers; -import me.jellysquid.mods.sodium.client.render.chunk.compile.ChunkBuildResult; -import me.jellysquid.mods.sodium.client.render.chunk.data.ChunkRenderData; -import me.jellysquid.mods.sodium.client.render.pipeline.context.ChunkRenderCacheLocal; -import me.jellysquid.mods.sodium.client.util.task.CancellationSource; - -/** - * A build task which does no computation and always return an empty build result. These tasks are created whenever - * chunk meshes need to be deleted as the only way to change graphics state is to send a message to the main - * actor thread. In cases where new chunk renders are being created and scheduled, the scheduler will prefer to just - * synchronously update the render's data to an empty state to speed things along. - */ -public class ChunkRenderEmptyBuildTask extends ChunkRenderBuildTask { - private final ChunkRenderContainer render; - - public ChunkRenderEmptyBuildTask(ChunkRenderContainer render) { - this.render = render; - } - - @Override - public ChunkBuildResult performBuild(ChunkRenderCacheLocal cache, ChunkBuildBuffers buffers, CancellationSource cancellationSource) { - return new ChunkBuildResult<>(this.render, ChunkRenderData.EMPTY); - } - - @Override - public void releaseResources() { - - } -}