From 4d5391f5dcad5edcc4b5aad4738035e7d034de5a Mon Sep 17 00:00:00 2001 From: Jozufozu Date: Thu, 23 Dec 2021 14:41:10 -0800 Subject: [PATCH] Contraptions and engines - Sort of get the batching engine working for contraptions but this feels wrong - TaskEngine gets passed in methods - Better naming for TaskEngines - Do BufferSource ourselves - Change BufferBuilderMixin to allow for injection into BufferBuilder objects --- .../backend/instancing/AbstractInstancer.java | 5 ++ .../backend/instancing/InstanceManager.java | 8 +- .../backend/instancing/InstanceWorld.java | 34 ++++---- .../instancing/InstancedRenderDispatcher.java | 2 +- ...hExecutor.java => ParallelTaskEngine.java} | 21 ++--- .../backend/instancing/RenderDispatcher.java | 6 +- ...ateExecutor.java => SerialTaskEngine.java} | 6 +- .../backend/instancing/SuperBufferSource.java | 79 +++++++++++++++++++ .../batching/BatchedMaterialGroup.java | 23 +----- .../instancing/batching/BatchingEngine.java | 40 +++------- .../entity/EntityInstanceManager.java | 5 +- .../instancing/InstancingEngine.java | 16 +--- .../instancing/tile/TileInstanceManager.java | 5 +- .../backend/model/BufferBuilderHack.java | 16 ++++ .../backend/model/DirectBufferBuilder.java | 20 ----- .../backend/model/DirectVertexConsumer.java | 2 +- .../crumbling/CrumblingInstanceManager.java | 3 +- .../core/crumbling/CrumblingRenderer.java | 5 +- .../flywheel/mixin/BufferBuilderMixin.java | 51 ++++++------ 19 files changed, 197 insertions(+), 150 deletions(-) rename src/main/java/com/jozufozu/flywheel/backend/instancing/{BatchExecutor.java => ParallelTaskEngine.java} (87%) rename src/main/java/com/jozufozu/flywheel/backend/instancing/{ImmediateExecutor.java => SerialTaskEngine.java} (59%) create mode 100644 src/main/java/com/jozufozu/flywheel/backend/instancing/SuperBufferSource.java create mode 100644 src/main/java/com/jozufozu/flywheel/backend/model/BufferBuilderHack.java delete mode 100644 src/main/java/com/jozufozu/flywheel/backend/model/DirectBufferBuilder.java diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/AbstractInstancer.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/AbstractInstancer.java index 3a8731f71..ef1a6824c 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/AbstractInstancer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/AbstractInstancer.java @@ -115,4 +115,9 @@ public abstract class AbstractInstancer implements Insta return instanceData; } + + @Override + public String toString() { + return "Instancer[" + modelData + ']'; + } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceManager.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceManager.java index 449c04862..6741c513c 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceManager.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceManager.java @@ -32,13 +32,11 @@ public abstract class InstanceManager implements InstancingEngine.OriginShift protected final Map instances; protected final Object2ObjectOpenHashMap tickableInstances; protected final Object2ObjectOpenHashMap dynamicInstances; - private final TaskEngine taskEngine; protected int frame; protected int tick; - public InstanceManager(TaskEngine taskEngine, MaterialManager materialManager) { - this.taskEngine = taskEngine; + public InstanceManager(MaterialManager materialManager) { this.materialManager = materialManager; this.queuedUpdates = new HashSet<>(64); this.queuedAdditions = new HashSet<>(64); @@ -78,7 +76,7 @@ public abstract class InstanceManager implements InstancingEngine.OriginShift * Queued updates are processed. *

*/ - public void tick(double cameraX, double cameraY, double cameraZ) { + public void tick(TaskEngine taskEngine, double cameraX, double cameraY, double cameraZ) { tick++; processQueuedUpdates(); @@ -120,7 +118,7 @@ public abstract class InstanceManager implements InstancingEngine.OriginShift if ((tick % getUpdateDivisor(dX, dY, dZ)) == 0) instance.tick(); } - public void beginFrame(Camera info) { + public void beginFrame(TaskEngine taskEngine, Camera info) { frame++; processQueuedAdditions(); diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceWorld.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceWorld.java index a913b442d..a6167ab24 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceWorld.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceWorld.java @@ -16,6 +16,8 @@ import com.jozufozu.flywheel.event.RenderLayerEvent; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.entity.BlockEntity; /** @@ -29,11 +31,12 @@ public class InstanceWorld { protected final InstanceManager entityInstanceManager; protected final InstanceManager tileEntityInstanceManager; - protected final BatchExecutor taskEngine; + protected final ParallelTaskEngine taskEngine; - public InstanceWorld() { + public InstanceWorld(LevelAccessor levelAccessor) { + Level world = (Level) levelAccessor; - this.taskEngine = new BatchExecutor(); + this.taskEngine = new ParallelTaskEngine("Flywheel " + world.dimension().location()); this.taskEngine.startWorkers(); FlwEngine engine = Backend.getInstance() @@ -42,19 +45,19 @@ public class InstanceWorld { switch (engine) { case INSTANCING -> { InstancingEngine manager = InstancingEngine.builder(Contexts.WORLD) - .build(this.taskEngine); + .build(); - entityInstanceManager = new EntityInstanceManager(this.taskEngine, manager); - tileEntityInstanceManager = new TileInstanceManager(this.taskEngine, manager); + entityInstanceManager = new EntityInstanceManager(manager); + tileEntityInstanceManager = new TileInstanceManager(manager); manager.addListener(entityInstanceManager); manager.addListener(tileEntityInstanceManager); this.engine = manager; } case BATCHING -> { - this.engine = new BatchingEngine(this.taskEngine); - entityInstanceManager = new EntityInstanceManager(this.taskEngine, this.engine); - tileEntityInstanceManager = new TileInstanceManager(this.taskEngine, this.engine); + this.engine = new BatchingEngine(); + entityInstanceManager = new EntityInstanceManager(this.engine); + tileEntityInstanceManager = new TileInstanceManager(this.engine); } default -> throw new IllegalArgumentException("Unknown engine type"); } @@ -91,8 +94,8 @@ public class InstanceWorld { taskEngine.syncPoint(); - tileEntityInstanceManager.beginFrame(event.getInfo()); - entityInstanceManager.beginFrame(event.getInfo()); + tileEntityInstanceManager.beginFrame(taskEngine, event.getInfo()); + entityInstanceManager.beginFrame(taskEngine, event.getInfo()); } /** @@ -107,8 +110,8 @@ public class InstanceWorld { if (renderViewEntity == null) return; - tileEntityInstanceManager.tick(renderViewEntity.getX(), renderViewEntity.getY(), renderViewEntity.getZ()); - entityInstanceManager.tick(renderViewEntity.getX(), renderViewEntity.getY(), renderViewEntity.getZ()); + tileEntityInstanceManager.tick(taskEngine, renderViewEntity.getX(), renderViewEntity.getY(), renderViewEntity.getZ()); + entityInstanceManager.tick(taskEngine, renderViewEntity.getX(), renderViewEntity.getY(), renderViewEntity.getZ()); } /** @@ -116,7 +119,10 @@ public class InstanceWorld { */ public void renderLayer(RenderLayerEvent event) { taskEngine.syncPoint(); - engine.render(event); + event.stack.pushPose(); + event.stack.translate(-event.camX, -event.camY, -event.camZ); + engine.render(taskEngine, event); + event.stack.popPose(); } /** diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java index 931908b3f..216cceebc 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java @@ -22,7 +22,7 @@ import net.minecraftforge.fml.common.Mod; @Mod.EventBusSubscriber(Dist.CLIENT) public class InstancedRenderDispatcher { - private static final WorldAttached instanceWorlds = new WorldAttached<>($ -> new InstanceWorld()); + private static final WorldAttached instanceWorlds = new WorldAttached<>(InstanceWorld::new); /** * Call this when you want to manually run {@link AbstractInstance#update()}. diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/BatchExecutor.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/ParallelTaskEngine.java similarity index 87% rename from src/main/java/com/jozufozu/flywheel/backend/instancing/BatchExecutor.java rename to src/main/java/com/jozufozu/flywheel/backend/instancing/ParallelTaskEngine.java index da856e57c..937567853 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/BatchExecutor.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/ParallelTaskEngine.java @@ -17,7 +17,7 @@ import com.jozufozu.flywheel.backend.instancing.batching.WaitGroup; import net.minecraft.util.Mth; // https://github.com/CaffeineMC/sodium-fabric/blob/5d364ed5ba63f9067fcf72a078ca310bff4db3e9/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/compile/ChunkBuilder.java -public class BatchExecutor implements TaskEngine { +public class ParallelTaskEngine implements TaskEngine { private static final Logger LOGGER = LogManager.getLogger("BatchExecutor"); private final AtomicBoolean running = new AtomicBoolean(false); @@ -30,7 +30,10 @@ public class BatchExecutor implements TaskEngine { private final int threadCount; - public BatchExecutor() { + private final String name; + + public ParallelTaskEngine(String name) { + this.name = name; threadCount = getOptimalThreadCount(); } @@ -49,7 +52,7 @@ public class BatchExecutor implements TaskEngine { for (int i = 0; i < this.threadCount; i++) { - Thread thread = new Thread(new WorkerRunnable(), "Engine Executor " + i); + Thread thread = new Thread(new WorkerRunnable(), name + " " + i); thread.setPriority(Math.max(0, Thread.NORM_PRIORITY - 2)); thread.start(); @@ -121,9 +124,9 @@ public class BatchExecutor implements TaskEngine { Runnable job = this.jobQueue.pollFirst(); if (job == null) { - synchronized (BatchExecutor.this.jobNotifier) { + synchronized (ParallelTaskEngine.this.jobNotifier) { try { - BatchExecutor.this.jobNotifier.wait(); + ParallelTaskEngine.this.jobNotifier.wait(); } catch (InterruptedException ignored) { } } @@ -138,7 +141,7 @@ public class BatchExecutor implements TaskEngine { } catch (Exception e) { Flywheel.log.error(e); } finally { - BatchExecutor.this.wg.done(); + ParallelTaskEngine.this.wg.done(); } } @@ -155,19 +158,19 @@ public class BatchExecutor implements TaskEngine { } private class WorkerRunnable implements Runnable { - private final AtomicBoolean running = BatchExecutor.this.running; + private final AtomicBoolean running = ParallelTaskEngine.this.running; @Override public void run() { // Run until the chunk builder shuts down while (this.running.get()) { - Runnable job = BatchExecutor.this.getNextTask(); + Runnable job = ParallelTaskEngine.this.getNextTask(); if (job == null) { continue; } - BatchExecutor.this.processTask(job); + ParallelTaskEngine.this.processTask(job); } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/RenderDispatcher.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/RenderDispatcher.java index ae9ccf88f..4d5cf8372 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/RenderDispatcher.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/RenderDispatcher.java @@ -3,15 +3,15 @@ package com.jozufozu.flywheel.backend.instancing; import com.jozufozu.flywheel.event.RenderLayerEvent; import net.minecraft.client.Camera; -import net.minecraft.client.renderer.MultiBufferSource; public interface RenderDispatcher { /** * Render every model for every material. * - * @param event Context for rendering. + * @param taskEngine + * @param event Context for rendering. */ - void render(RenderLayerEvent event); + void render(TaskEngine taskEngine, RenderLayerEvent event); /** * Maintain the integer origin coordinate to be within a certain distance from the camera in all directions. diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/ImmediateExecutor.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/SerialTaskEngine.java similarity index 59% rename from src/main/java/com/jozufozu/flywheel/backend/instancing/ImmediateExecutor.java rename to src/main/java/com/jozufozu/flywheel/backend/instancing/SerialTaskEngine.java index be1c2b5fd..96361a2d6 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/ImmediateExecutor.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/SerialTaskEngine.java @@ -2,11 +2,11 @@ package com.jozufozu.flywheel.backend.instancing; import org.jetbrains.annotations.NotNull; -public class ImmediateExecutor implements TaskEngine { +public class SerialTaskEngine implements TaskEngine { - public static final ImmediateExecutor INSTANCE = new ImmediateExecutor(); + public static final SerialTaskEngine INSTANCE = new SerialTaskEngine(); - private ImmediateExecutor() { + private SerialTaskEngine() { } @Override diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/SuperBufferSource.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/SuperBufferSource.java new file mode 100644 index 000000000..d4b8636f5 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/SuperBufferSource.java @@ -0,0 +1,79 @@ +package com.jozufozu.flywheel.backend.instancing; + +import java.nio.ByteBuffer; +import java.util.HashMap; +import java.util.Map; + +import com.jozufozu.flywheel.backend.model.BufferBuilderHack; +import com.jozufozu.flywheel.backend.model.DirectVertexConsumer; +import com.mojang.blaze3d.platform.MemoryTracker; +import com.mojang.blaze3d.vertex.BufferBuilder; +import com.mojang.blaze3d.vertex.VertexFormat; + +import net.minecraft.client.renderer.RenderType; + +public class SuperBufferSource { + + protected final Map buffers = new HashMap<>(); + private final BufferBuilder scratch; + + public SuperBufferSource() { + scratch = new BufferBuilder(8); + + ((BufferBuilderHack) scratch).freeBuffer(); + } + + public DirectVertexConsumer getBuffer(RenderType renderType, int vertexCount) { + return buffers.computeIfAbsent(renderType, DrawBuffer::new) + .begin(vertexCount); + } + + public void endBatch() { + // TODO: when/if this causes trouble with shaders, try to inject our BufferBuilders + // into the RenderBuffers from context. + + BufferBuilderHack hack = (BufferBuilderHack) scratch; + + for (Map.Entry entry : buffers.entrySet()) { + DrawBuffer builder = entry.getValue(); + + if (builder.expectedVertices > 0) { + RenderType type = entry.getKey(); + + hack.hackBegin(builder.backingBuffer, type.format(), builder.expectedVertices); + + type.end(scratch, 0, 0, 0); + + builder.expectedVertices = 0; + } + } + } + + private static class DrawBuffer { + + private final RenderType type; + private ByteBuffer backingBuffer; + private int expectedVertices; + + public DrawBuffer(RenderType type) { + this.type = type; + } + + public DirectVertexConsumer begin(int vertexCount) { + this.expectedVertices = vertexCount; + + VertexFormat format = type.format(); + + int byteSize = format.getVertexSize() * vertexCount; + + if (backingBuffer == null) { + backingBuffer = MemoryTracker.create(byteSize); + } if (byteSize > backingBuffer.capacity()) { + backingBuffer = MemoryTracker.resize(backingBuffer, byteSize); + } + + return new DirectVertexConsumer(backingBuffer, format, vertexCount); + } + + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchedMaterialGroup.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchedMaterialGroup.java index ba5d71105..cbeaf7c60 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchedMaterialGroup.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchedMaterialGroup.java @@ -7,13 +7,11 @@ import com.jozufozu.flywheel.api.InstanceData; import com.jozufozu.flywheel.api.MaterialGroup; import com.jozufozu.flywheel.api.struct.Batched; import com.jozufozu.flywheel.api.struct.StructType; +import com.jozufozu.flywheel.backend.instancing.SuperBufferSource; import com.jozufozu.flywheel.backend.instancing.TaskEngine; -import com.jozufozu.flywheel.backend.model.DirectBufferBuilder; import com.jozufozu.flywheel.backend.model.DirectVertexConsumer; import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; public class BatchedMaterialGroup implements MaterialGroup { @@ -36,17 +34,8 @@ public class BatchedMaterialGroup implements MaterialGroup { } } - public void render(PoseStack stack, MultiBufferSource source, TaskEngine pool) { - VertexConsumer buffer = source.getBuffer(state); + public void render(PoseStack stack, SuperBufferSource source, TaskEngine pool) { - if (buffer instanceof DirectBufferBuilder direct) { - renderParallel(stack, pool, direct); - } else { - renderSerial(stack, buffer); - } - } - - private void renderParallel(PoseStack stack, TaskEngine pool, DirectBufferBuilder direct) { int vertexCount = 0; for (BatchedMaterial material : materials.values()) { for (CPUInstancer instancer : material.models.values()) { @@ -55,7 +44,7 @@ public class BatchedMaterialGroup implements MaterialGroup { } } - DirectVertexConsumer consumer = direct.intoDirectConsumer(vertexCount); + DirectVertexConsumer consumer = source.getBuffer(state, vertexCount); // avoids rendering garbage, but doesn't fix the issue of some instances not being buffered consumer.memSetZero(); @@ -74,12 +63,6 @@ public class BatchedMaterialGroup implements MaterialGroup { } } - private void renderSerial(PoseStack stack, VertexConsumer consumer) { - for (BatchedMaterial value : materials.values()) { - value.setupAndRenderInto(stack, consumer); - } - } - public void clear() { materials.values().forEach(BatchedMaterial::clear); } 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 c8ebbed58..caec4b844 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 @@ -6,6 +6,7 @@ import java.util.Map; import com.jozufozu.flywheel.api.MaterialGroup; import com.jozufozu.flywheel.backend.RenderLayer; +import com.jozufozu.flywheel.backend.instancing.SuperBufferSource; import com.jozufozu.flywheel.backend.instancing.TaskEngine; import com.jozufozu.flywheel.backend.instancing.Engine; import com.jozufozu.flywheel.event.RenderLayerEvent; @@ -21,19 +22,17 @@ import net.minecraft.client.renderer.RenderType; import net.minecraft.core.BlockPos; import net.minecraft.core.Vec3i; -public class BatchingEngine implements Engine, MultiBufferSource { +public class BatchingEngine implements Engine { - protected final Map buffers = new HashMap<>(); - protected final Map> layers; - protected final TaskEngine taskEngine; + private final Map> layers; + private final SuperBufferSource superBufferSource = new SuperBufferSource(); - public BatchingEngine(TaskEngine taskEngine) { + public BatchingEngine() { this.layers = new EnumMap<>(RenderLayer.class); for (RenderLayer value : RenderLayer.values()) { layers.put(value, new HashMap<>()); } - this.taskEngine = taskEngine; } @Override @@ -47,21 +46,15 @@ public class BatchingEngine implements Engine, MultiBufferSource { } @Override - public void render(RenderLayerEvent event) { - PoseStack stack = event.stack; + public void render(TaskEngine taskEngine, RenderLayerEvent event) { - stack.pushPose(); - - stack.translate(-event.camX, -event.camY, -event.camZ); - - for (BatchedMaterialGroup group : layers.get(event.getLayer()).values()) { - group.render(stack, this, taskEngine); + Map groups = layers.get(event.getLayer()); + for (BatchedMaterialGroup group : groups.values()) { + group.render(event.stack, superBufferSource, taskEngine); } taskEngine.syncPoint(); - stack.popPose(); - // FIXME: this probably breaks some vanilla stuff but it works much better for flywheel Matrix4f mat = new Matrix4f(); mat.setIdentity(); @@ -71,20 +64,7 @@ public class BatchingEngine implements Engine, MultiBufferSource { Lighting.setupLevel(mat); } - // TODO: when/if this causes trouble with shaders, try to inject our BufferBuilders - // into the RenderBuffers from context. - buffers.forEach((type, builder) -> type.end(builder, 0, 0, 0)); - } - - @Override - public VertexConsumer getBuffer(RenderType renderType) { - BufferBuilder builder = buffers.computeIfAbsent(renderType, type -> new BufferBuilder(type.bufferSize())); - - if (!builder.building()) { - builder.begin(renderType.mode(), renderType.format()); - } - - return builder; + superBufferSource.endBatch(); } @Override diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/EntityInstanceManager.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/EntityInstanceManager.java index 2b3af7808..494800ae2 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/EntityInstanceManager.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/EntityInstanceManager.java @@ -3,7 +3,6 @@ package com.jozufozu.flywheel.backend.instancing.entity; import com.jozufozu.flywheel.api.MaterialManager; import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.instancing.AbstractInstance; -import com.jozufozu.flywheel.backend.instancing.BatchExecutor; import com.jozufozu.flywheel.backend.instancing.InstanceManager; import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry; import com.jozufozu.flywheel.backend.instancing.TaskEngine; @@ -15,8 +14,8 @@ import net.minecraft.world.level.Level; public class EntityInstanceManager extends InstanceManager { - public EntityInstanceManager(TaskEngine executor, MaterialManager materialManager) { - super(executor, materialManager); + public EntityInstanceManager(MaterialManager materialManager) { + super(materialManager); } @Override diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancingEngine.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancingEngine.java index 63015b349..7f30b541e 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancingEngine.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancingEngine.java @@ -10,7 +10,6 @@ import javax.annotation.Nullable; import com.jozufozu.flywheel.api.MaterialGroup; import com.jozufozu.flywheel.backend.instancing.TaskEngine; -import com.jozufozu.flywheel.backend.instancing.ImmediateExecutor; import com.jozufozu.flywheel.backend.RenderLayer; import com.jozufozu.flywheel.backend.gl.GlVertexArray; import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType; @@ -22,7 +21,6 @@ import com.jozufozu.flywheel.util.WeakHashSet; import com.mojang.math.Matrix4f; import net.minecraft.client.Camera; -import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.core.BlockPos; import net.minecraft.core.Vec3i; @@ -35,7 +33,6 @@ public class InstancingEngine

implements Engine { protected BlockPos originCoordinate = BlockPos.ZERO; - protected final TaskEngine taskEngine; protected final WorldContext

context; protected final GroupFactory

groupFactory; protected final boolean ignoreOriginCoordinate; @@ -45,15 +42,14 @@ public class InstancingEngine

implements Engine { private final WeakHashSet listeners; public InstancingEngine(WorldContext

context, TaskEngine taskEngine) { - this(taskEngine, context, InstancedMaterialGroup::new, false); + this(context, InstancedMaterialGroup::new, false); } public static

Builder

builder(WorldContext

context) { return new Builder<>(context); } - public InstancingEngine(TaskEngine taskEngine, WorldContext

context, GroupFactory

groupFactory, boolean ignoreOriginCoordinate) { - this.taskEngine = taskEngine; + public InstancingEngine(WorldContext

context, GroupFactory

groupFactory, boolean ignoreOriginCoordinate) { this.context = context; this.ignoreOriginCoordinate = ignoreOriginCoordinate; @@ -82,7 +78,7 @@ public class InstancingEngine

implements Engine { * Render every model for every material. */ @Override - public void render(RenderLayerEvent event) { + public void render(TaskEngine taskEngine, RenderLayerEvent event) { double camX; double camY; double camZ; @@ -205,11 +201,7 @@ public class InstancingEngine

implements Engine { } public InstancingEngine

build() { - return build(ImmediateExecutor.INSTANCE); - } - - public InstancingEngine

build(TaskEngine taskEngine) { - return new InstancingEngine<>(taskEngine, context, groupFactory, ignoreOriginCoordinate); + return new InstancingEngine<>(context, groupFactory, ignoreOriginCoordinate); } } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/tile/TileInstanceManager.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/tile/TileInstanceManager.java index c0b65215d..b0be524da 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/tile/TileInstanceManager.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/tile/TileInstanceManager.java @@ -3,7 +3,6 @@ package com.jozufozu.flywheel.backend.instancing.tile; import com.jozufozu.flywheel.api.MaterialManager; import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.instancing.AbstractInstance; -import com.jozufozu.flywheel.backend.instancing.BatchExecutor; import com.jozufozu.flywheel.backend.instancing.InstanceManager; import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry; import com.jozufozu.flywheel.backend.instancing.TaskEngine; @@ -15,8 +14,8 @@ import net.minecraft.world.level.block.entity.BlockEntity; public class TileInstanceManager extends InstanceManager { - public TileInstanceManager(TaskEngine executor, MaterialManager materialManager) { - super(executor, materialManager); + public TileInstanceManager(MaterialManager materialManager) { + super(materialManager); } @Override diff --git a/src/main/java/com/jozufozu/flywheel/backend/model/BufferBuilderHack.java b/src/main/java/com/jozufozu/flywheel/backend/model/BufferBuilderHack.java new file mode 100644 index 000000000..ee2dd4fb8 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/model/BufferBuilderHack.java @@ -0,0 +1,16 @@ +package com.jozufozu.flywheel.backend.model; + +import java.nio.ByteBuffer; + +import com.mojang.blaze3d.vertex.BufferBuilder; +import com.mojang.blaze3d.vertex.VertexFormat; + +/** + * Duck interface used on {@link BufferBuilder} to provide lower level access to the backing memory. + */ +public interface BufferBuilderHack { + + void freeBuffer(); + + void hackBegin(ByteBuffer buffer, VertexFormat format, int vertexCount); +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/model/DirectBufferBuilder.java b/src/main/java/com/jozufozu/flywheel/backend/model/DirectBufferBuilder.java deleted file mode 100644 index c157aed9b..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/model/DirectBufferBuilder.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.jozufozu.flywheel.backend.model; - -import com.mojang.blaze3d.vertex.BufferBuilder; - -/** - * Duck interface used on {@link BufferBuilder} to provide lower level access to the backing memory. - */ -public interface DirectBufferBuilder { - - /** - * Create a DirectVertexConsumer from this BufferBuilder. - * - *

- * After this function returns, the internal state of the BufferBuilder will be as if - * {@link BufferBuilder#endVertex()} was called vertexCount times. It is up to the callee - * to actually populate the BufferBuilder with vertices using the returned value. - *

- */ - DirectVertexConsumer intoDirectConsumer(int vertexCount); -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/model/DirectVertexConsumer.java b/src/main/java/com/jozufozu/flywheel/backend/model/DirectVertexConsumer.java index 781ad8693..8446fbfcc 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/model/DirectVertexConsumer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/model/DirectVertexConsumer.java @@ -13,7 +13,7 @@ import com.mojang.blaze3d.vertex.VertexFormatElement; /** * An unsafe vertex consumer allowing for unchecked writes into a ByteBuffer. * - * @see DirectBufferBuilder + * @see BufferBuilderHack */ public class DirectVertexConsumer implements VertexConsumer { public final VertexFormat format; diff --git a/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingInstanceManager.java b/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingInstanceManager.java index bea324fd4..30e427f6b 100644 --- a/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingInstanceManager.java +++ b/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingInstanceManager.java @@ -1,7 +1,6 @@ package com.jozufozu.flywheel.core.crumbling; import com.jozufozu.flywheel.api.MaterialManager; -import com.jozufozu.flywheel.backend.instancing.ImmediateExecutor; import com.jozufozu.flywheel.backend.instancing.tile.TileInstanceManager; import net.minecraft.core.BlockPos; @@ -9,7 +8,7 @@ import net.minecraft.core.BlockPos; public class CrumblingInstanceManager extends TileInstanceManager { public CrumblingInstanceManager(MaterialManager materialManager) { - super(ImmediateExecutor.INSTANCE, materialManager); + super(materialManager); } @Override diff --git a/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingRenderer.java b/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingRenderer.java index 42ae86e71..4aad9a96b 100644 --- a/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingRenderer.java +++ b/src/main/java/com/jozufozu/flywheel/core/crumbling/CrumblingRenderer.java @@ -6,6 +6,7 @@ import java.util.SortedSet; import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.gl.GlTextureUnit; +import com.jozufozu.flywheel.backend.instancing.SerialTaskEngine; import com.jozufozu.flywheel.backend.instancing.InstanceManager; import com.jozufozu.flywheel.backend.instancing.instancing.InstancingEngine; import com.jozufozu.flywheel.core.Contexts; @@ -74,9 +75,9 @@ public class CrumblingRenderer { if (_currentLayer != null) { stage.getValue().forEach(instanceManager::add); - instanceManager.beginFrame(info); + instanceManager.beginFrame(SerialTaskEngine.INSTANCE, info); - materials.render(event); + materials.render(SerialTaskEngine.INSTANCE, event); instanceManager.invalidate(); } diff --git a/src/main/java/com/jozufozu/flywheel/mixin/BufferBuilderMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/BufferBuilderMixin.java index 66c29bfd4..120f552c1 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/BufferBuilderMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/BufferBuilderMixin.java @@ -5,29 +5,34 @@ import java.nio.ByteBuffer; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import org.lwjgl.system.MemoryUtil; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import com.jozufozu.flywheel.backend.instancing.SuperBufferSource; import com.jozufozu.flywheel.backend.model.DirectVertexConsumer; -import com.jozufozu.flywheel.backend.model.DirectBufferBuilder; +import com.jozufozu.flywheel.backend.model.BufferBuilderHack; import com.mojang.blaze3d.vertex.BufferBuilder; import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.blaze3d.vertex.VertexFormatElement; @Mixin(BufferBuilder.class) -public abstract class BufferBuilderMixin implements DirectBufferBuilder { +public abstract class BufferBuilderMixin implements BufferBuilderHack { @Shadow private ByteBuffer buffer; + @Shadow + private boolean building; + + @Shadow + public abstract void begin(VertexFormat.Mode p_166780_, VertexFormat p_166781_); + + @Shadow + private VertexFormat.Mode mode; + @Shadow private VertexFormat format; - @Shadow - protected abstract void ensureCapacity(int p_85723_); - - @Shadow - private int vertices; - @Shadow @Nullable private VertexFormatElement currentElement; @@ -36,24 +41,26 @@ public abstract class BufferBuilderMixin implements DirectBufferBuilder { private int elementIndex; @Shadow - private int nextElementByte; + private int vertices; @Override - @Nonnull - public DirectVertexConsumer intoDirectConsumer(int vertexCount) { - int bytes = vertexCount * format.getVertexSize(); - // ensure we have capacity for one extra vertex, BufferBuilder does this on #endVertex - ensureCapacity(bytes + format.getVertexSize()); + public void freeBuffer() { + if (this.buffer != null) { + MemoryUtil.memFree(this.buffer); + this.buffer = null; + } + } - DirectVertexConsumer consumer = new DirectVertexConsumer(this.buffer, this.format, vertexCount); + @Override + public void hackBegin(@Nonnull ByteBuffer buffer, @Nonnull VertexFormat format, int vertexCount) { + this.building = true; + this.mode = VertexFormat.Mode.QUADS; - this.vertices += vertexCount; - this.currentElement = format.getElements() - .get(0); + this.buffer = buffer; + this.format = format; + this.vertices = vertexCount; + + this.currentElement = this.format.getElements().get(0); this.elementIndex = 0; - this.nextElementByte += bytes; - this.buffer.position(this.buffer.position() + bytes); - - return consumer; } }