From 8bea4674099db36de196c55eebf94d41ddf9b9fe Mon Sep 17 00:00:00 2001 From: PepperCode1 <44146161+PepperCode1@users.noreply.github.com> Date: Sat, 20 Aug 2022 19:12:44 -0700 Subject: [PATCH] BatchingTransformManager - Rename BatchingDrawManager to BatchingTransformManager - Rename BatchDrawingTracker to BatchingDrawTracker - Move BatchDrawingTracker from BatchingTransformManager to BatchingEngine - Do not prepare DrawBuffer if number of vertices is 0 - Add DrawBuffer#isPrepared - Add checks to DrawBuffer methods - Remove commented code from CPUInstancerFactory --- ...gTracker.java => BatchingDrawTracker.java} | 52 +++++++++---------- .../instancing/batching/BatchingEngine.java | 35 +++++++------ ...ger.java => BatchingTransformManager.java} | 17 +++--- .../batching/CPUInstancerFactory.java | 8 --- .../instancing/batching/DrawBuffer.java | 31 ++++++++--- .../instancing/instancing/GPUInstancer.java | 1 - 6 files changed, 78 insertions(+), 66 deletions(-) rename src/main/java/com/jozufozu/flywheel/backend/instancing/batching/{BatchDrawingTracker.java => BatchingDrawTracker.java} (67%) rename src/main/java/com/jozufozu/flywheel/backend/instancing/batching/{BatchingDrawManager.java => BatchingTransformManager.java} (81%) diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchDrawingTracker.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchingDrawTracker.java similarity index 67% rename from src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchDrawingTracker.java rename to src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchingDrawTracker.java index fb47ba6d3..57909678b 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchDrawingTracker.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchingDrawTracker.java @@ -9,12 +9,12 @@ import com.mojang.blaze3d.vertex.BufferBuilder; import net.minecraft.client.renderer.RenderType; -public class BatchDrawingTracker { +public class BatchingDrawTracker { - protected final Set activeTypes = new HashSet<>(); + private final Set activeTypes = new HashSet<>(); private final BufferBuilder scratch; - public BatchDrawingTracker() { + public BatchingDrawTracker() { scratch = new BufferBuilder(8); ((BufferBuilderExtension) scratch).flywheel$freeBuffer(); @@ -25,13 +25,20 @@ public class BatchDrawingTracker { return RenderTypeExtension.getDrawBuffer(renderType); } + /** + * Draw and reset the DrawBuffer for the given RenderType. + * @param renderType The RenderType to draw. + */ + public void draw(RenderType renderType) { + _draw(renderType); + + activeTypes.remove(renderType); + } + /** * Draws all active DrawBuffers and reset them. */ - public void endBatch() { - // TODO: when/if this causes trouble with shaders, try to inject our BufferBuilders - // into the RenderBuffers from context. - + public void drawAll() { for (RenderType renderType : activeTypes) { _draw(renderType); } @@ -39,38 +46,27 @@ public class BatchDrawingTracker { activeTypes.clear(); } - /** - * Draw and reset the DrawBuffer for the given RenderType. - * @param renderType The RenderType to draw. - */ - public void endBatch(RenderType renderType) { - _draw(renderType); + private void _draw(RenderType renderType) { + DrawBuffer buffer = RenderTypeExtension.getDrawBuffer(renderType); - activeTypes.remove(renderType); + if (buffer.hasVertices()) { + BufferBuilderExtension scratch = (BufferBuilderExtension) this.scratch; + buffer.inject(scratch); + renderType.end(this.scratch, 0, 0, 0); + buffer.reset(); + } } /** * Resets all DrawBuffers to 0 vertices. */ - public void clear() { + public void reset() { for (RenderType type : activeTypes) { RenderTypeExtension.getDrawBuffer(type) .reset(); } + activeTypes.clear(); } - private void _draw(RenderType renderType) { - DrawBuffer drawBuffer = RenderTypeExtension.getDrawBuffer(renderType); - - BufferBuilderExtension scratch = (BufferBuilderExtension) this.scratch; - if (drawBuffer.hasVertices()) { - drawBuffer.inject(scratch); - - renderType.end(this.scratch, 0, 0, 0); - - drawBuffer.reset(); - } - } - } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchingEngine.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchingEngine.java index 4de89d6fd..728ceeaf5 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchingEngine.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchingEngine.java @@ -24,7 +24,8 @@ import net.minecraft.world.phys.Vec3; public class BatchingEngine implements Engine { - protected final BatchingDrawManager drawManager = new BatchingDrawManager(); + protected final BatchingTransformManager transformManager = new BatchingTransformManager(); + protected final BatchingDrawTracker drawTracker = new BatchingDrawTracker(); protected final Map, CPUInstancerFactory> factories = new HashMap<>(); @SuppressWarnings("unchecked") @@ -36,12 +37,12 @@ public class BatchingEngine implements Engine { @NotNull private CPUInstancerFactory createFactory(StructType type) { - return new CPUInstancerFactory<>(type, drawManager::create); + return new CPUInstancerFactory<>(type, transformManager::create); } @Override public void beginFrame(TaskEngine taskEngine, RenderContext context) { - drawManager.flush(); + transformManager.flush(); Vec3 cameraPos = context.camera().getPosition(); var stack = FlwUtil.copyPoseStack(context.stack()); @@ -51,25 +52,29 @@ public class BatchingEngine implements Engine { } public void submitTasks(TaskEngine taskEngine, PoseStack stack, ClientLevel level) { - BatchingDrawManager.TransformSet drawSet = drawManager.get(RenderStage.AFTER_FINAL_END_BATCH); - for (var entry : drawSet) { + BatchingTransformManager.TransformSet transformSet = transformManager.get(RenderStage.AFTER_FINAL_END_BATCH); + for (var entry : transformSet) { var renderType = entry.getKey(); - var renderList = entry.getValue(); + var transformCalls = entry.getValue(); int vertices = 0; - for (var transformSet : renderList) { - vertices += transformSet.getTotalVertexCount(); + for (var transformCall : transformCalls) { + vertices += transformCall.getTotalVertexCount(); } - DrawBuffer buffer = drawManager.batchTracker.getBuffer(renderType); + if (vertices == 0) { + continue; + } + + DrawBuffer buffer = drawTracker.getBuffer(renderType); buffer.prepare(vertices); int startVertex = 0; - for (var transformSet : renderList) { - transformSet.submitTasks(taskEngine, buffer, startVertex, stack, level); - startVertex += transformSet.getTotalVertexCount(); + for (var transformCall : transformCalls) { + transformCall.submitTasks(taskEngine, buffer, startVertex, stack, level); + startVertex += transformCall.getTotalVertexCount(); } - }; + } } @Override @@ -81,7 +86,7 @@ public class BatchingEngine implements Engine { return; } - drawManager.batchTracker.endBatch(); + drawTracker.drawAll(); } @Override @@ -103,7 +108,7 @@ public class BatchingEngine implements Engine { @Override public void delete() { factories.clear(); - drawManager.delete(); + transformManager.delete(); } @Override diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchingDrawManager.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchingTransformManager.java similarity index 81% rename from src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchingDrawManager.java rename to src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchingTransformManager.java index 482fec72a..9c7fc8888 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchingDrawManager.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchingTransformManager.java @@ -2,6 +2,7 @@ package com.jozufozu.flywheel.backend.instancing.batching; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.EnumMap; import java.util.Iterator; import java.util.List; @@ -17,15 +18,19 @@ import com.jozufozu.flywheel.core.model.Model; import net.minecraft.client.renderer.RenderType; -public class BatchingDrawManager { +public class BatchingTransformManager { private final List uninitializedModels = new ArrayList<>(); private final List> allInstancers = new ArrayList<>(); - public final Map renderLists = new EnumMap<>(RenderStage.class); - public final BatchDrawingTracker batchTracker = new BatchDrawingTracker(); + private final Map transformSets = new EnumMap<>(RenderStage.class); + private final Map transformSetsView = Collections.unmodifiableMap(transformSets); public TransformSet get(RenderStage stage) { - return renderLists.getOrDefault(stage, TransformSet.EMPTY); + return transformSets.getOrDefault(stage, TransformSet.EMPTY); + } + + public Map getTransformSetsView() { + return transformSetsView; } public void create(CPUInstancer instancer, Model model) { @@ -55,8 +60,8 @@ public class BatchingDrawManager { var material = transformCall.getMaterial(); var renderType = material.getBatchingRenderType(); -// renderLists.computeIfAbsent(material.getRenderStage(), TransformSet::new) - renderLists.computeIfAbsent(RenderStage.AFTER_FINAL_END_BATCH, TransformSet::new) +// transformSets.computeIfAbsent(material.getRenderStage(), TransformSet::new) + transformSets.computeIfAbsent(RenderStage.AFTER_FINAL_END_BATCH, TransformSet::new) .put(renderType, transformCall); } allInstancers.add(instancer); diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/CPUInstancerFactory.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/CPUInstancerFactory.java index aad4049d6..65afe705c 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/CPUInstancerFactory.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/CPUInstancerFactory.java @@ -26,14 +26,6 @@ public class CPUInstancerFactory implements InstancerFa return models.computeIfAbsent(modelKey, this::createInstancer); } -// /** -// * Clear all instance data without freeing resources. -// */ -// public void clear() { -// models.values() -// .forEach(BatchedModel::clear); -// } - private CPUInstancer createInstancer(Model model) { var instancer = new CPUInstancer<>(type); creationListener.accept(instancer, model); diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/DrawBuffer.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/DrawBuffer.java index 8137ae7a8..52675cdfb 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/DrawBuffer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/DrawBuffer.java @@ -28,7 +28,8 @@ public class DrawBuffer { private MemoryBlock memory; private ByteBuffer buffer; - private int expectedVertices; + private boolean prepared; + private int vertexCount; @ApiStatus.Internal public DrawBuffer(VertexFormat format) { @@ -45,11 +46,11 @@ public class DrawBuffer { * @throws IllegalStateException If the buffer is already in use. */ public void prepare(int vertexCount) { - if (expectedVertices != 0) { - throw new IllegalStateException("Already drawing!"); + if (prepared) { + throw new IllegalStateException("Cannot prepare DrawBuffer twice!"); } - this.expectedVertices = vertexCount; + this.vertexCount = vertexCount; // Add one extra vertex to uphold the vanilla assumption that BufferBuilders have at least // enough buffer space for one more vertex. Rubidium checks for this extra space when popNextBuffer @@ -65,9 +66,14 @@ public class DrawBuffer { } memory.clear(); + prepared = true; } public ReusableVertexList slice(int startVertex, int vertexCount) { + if (!prepared) { + throw new IllegalStateException("Cannot slice DrawBuffer that is not prepared!"); + } + ReusableVertexList vertexList = provider.createVertexList(); vertexList.ptr(memory.ptr()); vertexList.shiftPtr(startVertex); @@ -80,19 +86,27 @@ public class DrawBuffer { * @param bufferBuilder The buffer builder to inject into. */ public void inject(BufferBuilderExtension bufferBuilder) { + if (!prepared) { + throw new IllegalStateException("Cannot inject DrawBuffer that is not prepared!"); + } + buffer.clear(); - bufferBuilder.flywheel$injectForRender(buffer, format, expectedVertices); + bufferBuilder.flywheel$injectForRender(buffer, format, vertexCount); + } + + public boolean isPrepared() { + return prepared; } public int getVertexCount() { - return expectedVertices; + return vertexCount; } /** * @return {@code true} if the buffer has any vertices. */ public boolean hasVertices() { - return expectedVertices > 0; + return vertexCount > 0; } /** @@ -101,7 +115,8 @@ public class DrawBuffer { * Does not clear the backing buffer. */ public void reset() { - this.expectedVertices = 0; + prepared = false; + vertexCount = 0; } public void free() { diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/GPUInstancer.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/GPUInstancer.java index d3e51e58e..520976482 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/GPUInstancer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/GPUInstancer.java @@ -25,7 +25,6 @@ public class GPUInstancer extends AbstractInstancer boolean anyToUpdate; - public GPUInstancer(StructType type) { super(type); this.instanceFormat = type.getLayout();