diff --git a/src/main/java/com/jozufozu/flywheel/Flywheel.java b/src/main/java/com/jozufozu/flywheel/Flywheel.java index 2f347b16b..28366c73b 100644 --- a/src/main/java/com/jozufozu/flywheel/Flywheel.java +++ b/src/main/java/com/jozufozu/flywheel/Flywheel.java @@ -97,7 +97,7 @@ public class Flywheel { forgeEventBus.addListener(ForgeEvents::unloadWorld); forgeEventBus.addListener(ForgeEvents::tickLight); - forgeEventBus.addListener(EventPriority.LOWEST, RenderWork::onRenderWorldLast); + forgeEventBus.addListener(EventPriority.LOWEST, RenderWork::onRenderLevelLast); modEventBus.addListener(PartialModel::onModelRegistry); modEventBus.addListener(PartialModel::onModelBake); diff --git a/src/main/java/com/jozufozu/flywheel/api/FlywheelWorld.java b/src/main/java/com/jozufozu/flywheel/api/FlywheelLevel.java similarity index 61% rename from src/main/java/com/jozufozu/flywheel/api/FlywheelWorld.java rename to src/main/java/com/jozufozu/flywheel/api/FlywheelLevel.java index 968535ed0..de4e0c3ed 100644 --- a/src/main/java/com/jozufozu/flywheel/api/FlywheelWorld.java +++ b/src/main/java/com/jozufozu/flywheel/api/FlywheelLevel.java @@ -1,13 +1,13 @@ package com.jozufozu.flywheel.api; /** - * A marker interface custom worlds can override to indicate - * that block entities and entities inside the world should + * A marker interface custom levels can override to indicate + * that block entities and entities inside the level should * render with Flywheel. * * {@link net.minecraft.client.Minecraft#level Minecraft#level} is special cased and will support Flywheel by default. */ -public interface FlywheelWorld { +public interface FlywheelLevel { default boolean supportsFlywheel() { return true; } diff --git a/src/main/java/com/jozufozu/flywheel/api/vertex/ReusableVertexList.java b/src/main/java/com/jozufozu/flywheel/api/vertex/ReusableVertexList.java index c4f9c4b70..6cff3b6d5 100644 --- a/src/main/java/com/jozufozu/flywheel/api/vertex/ReusableVertexList.java +++ b/src/main/java/com/jozufozu/flywheel/api/vertex/ReusableVertexList.java @@ -5,7 +5,7 @@ public interface ReusableVertexList extends MutableVertexList { void ptr(long ptr); - void shiftPtr(int vertices); + int vertexStride(); - void setVertexCount(int vertexCount); + void vertexCount(int vertexCount); } diff --git a/src/main/java/com/jozufozu/flywheel/api/vertex/VertexList.java b/src/main/java/com/jozufozu/flywheel/api/vertex/VertexList.java index b8edf82a9..d30ad7ce3 100644 --- a/src/main/java/com/jozufozu/flywheel/api/vertex/VertexList.java +++ b/src/main/java/com/jozufozu/flywheel/api/vertex/VertexList.java @@ -72,18 +72,18 @@ public interface VertexList extends PointSet { } default void writeAll(MutableVertexList dst) { - write(dst, 0, 0, getVertexCount()); + write(dst, 0, 0, vertexCount()); } - int getVertexCount(); + int vertexCount(); default boolean isEmpty() { - return getVertexCount() == 0; + return vertexCount() == 0; } @Override default int size() { - return getVertexCount(); + return vertexCount(); } @Override diff --git a/src/main/java/com/jozufozu/flywheel/backend/Backend.java b/src/main/java/com/jozufozu/flywheel/backend/Backend.java index 90f44788b..9aa80daa9 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/Backend.java +++ b/src/main/java/com/jozufozu/flywheel/backend/Backend.java @@ -3,7 +3,7 @@ package com.jozufozu.flywheel.backend; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; -import com.jozufozu.flywheel.api.FlywheelWorld; +import com.jozufozu.flywheel.api.FlywheelLevel; import com.jozufozu.flywheel.backend.instancing.ParallelTaskEngine; import com.jozufozu.flywheel.config.FlwConfig; import com.jozufozu.flywheel.core.BackendTypes; @@ -60,21 +60,21 @@ public class Backend { return TYPE != BackendTypes.OFF; } - public static boolean canUseInstancing(@Nullable Level world) { - return isOn() && isFlywheelWorld(world); + public static boolean canUseInstancing(@Nullable Level level) { + return isOn() && isFlywheelLevel(level); } /** - * Used to avoid calling Flywheel functions on (fake) worlds that don't specifically support it. + * Used to avoid calling Flywheel functions on (fake) levels that don't specifically support it. */ - public static boolean isFlywheelWorld(@Nullable LevelAccessor world) { - if (world == null) return false; + public static boolean isFlywheelLevel(@Nullable LevelAccessor level) { + if (level == null) return false; - if (!world.isClientSide()) return false; + if (!level.isClientSide()) return false; - if (world instanceof FlywheelWorld && ((FlywheelWorld) world).supportsFlywheel()) return true; + if (level instanceof FlywheelLevel && ((FlywheelLevel) level).supportsFlywheel()) return true; - return world == Minecraft.getInstance().level; + return level == Minecraft.getInstance().level; } public static boolean isGameActive() { diff --git a/src/main/java/com/jozufozu/flywheel/backend/Loader.java b/src/main/java/com/jozufozu/flywheel/backend/Loader.java index 588ee8bbb..2524be426 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/Loader.java +++ b/src/main/java/com/jozufozu/flywheel/backend/Loader.java @@ -109,9 +109,9 @@ public class Loader implements ResourceManagerReloadListener { throw new ShaderLoadingException("Compilation failed"); } - ClientLevel world = Minecraft.getInstance().level; - if (Backend.canUseInstancing(world)) { - InstancedRenderDispatcher.resetInstanceWorld(world); + ClientLevel level = Minecraft.getInstance().level; + if (Backend.canUseInstancing(level)) { + InstancedRenderDispatcher.resetInstanceLevel(level); } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/RenderWork.java b/src/main/java/com/jozufozu/flywheel/backend/RenderWork.java index 48b5061ef..afa364056 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/RenderWork.java +++ b/src/main/java/com/jozufozu/flywheel/backend/RenderWork.java @@ -6,12 +6,11 @@ import java.util.concurrent.ConcurrentLinkedQueue; import net.minecraftforge.client.event.RenderLevelLastEvent; public class RenderWork { - private static final Queue runs = new ConcurrentLinkedQueue<>(); + private static final Queue RUNS = new ConcurrentLinkedQueue<>(); - - public static void onRenderWorldLast(RenderLevelLastEvent event) { - while (!runs.isEmpty()) { - runs.remove() + public static void onRenderLevelLast(RenderLevelLastEvent event) { + while (!RUNS.isEmpty()) { + RUNS.remove() .run(); } } @@ -20,6 +19,6 @@ public class RenderWork { * Queue work to be executed at the end of a frame */ public static void enqueue(Runnable run) { - runs.add(run); + RUNS.add(run); } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/GlStateTracker.java b/src/main/java/com/jozufozu/flywheel/backend/gl/GlStateTracker.java index 500537425..0dc4f4076 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/GlStateTracker.java +++ b/src/main/java/com/jozufozu/flywheel/backend/gl/GlStateTracker.java @@ -7,13 +7,12 @@ import com.mojang.blaze3d.platform.GlStateManager; * Tracks bound buffers/vbos because GlStateManager doesn't do that for us. */ public class GlStateTracker { - - private static final int[] buffers = new int[GlBufferType.values().length]; + private static final int[] BUFFERS = new int[GlBufferType.values().length]; private static int vao; private static int program; public static int getBuffer(GlBufferType type) { - return buffers[type.ordinal()]; + return BUFFERS[type.ordinal()]; } public static int getVertexArray() { @@ -25,7 +24,7 @@ public class GlStateTracker { } public static void _setBuffer(GlBufferType type, int buffer) { - buffers[type.ordinal()] = buffer; + BUFFERS[type.ordinal()] = buffer; } public static void _setProgram(int id) { @@ -37,7 +36,7 @@ public class GlStateTracker { } public static State getRestoreState() { - return new State(buffers.clone(), vao, program); + return new State(BUFFERS.clone(), vao, program); } public record State(int[] buffers, int vao, int program) implements AutoCloseable { @@ -53,7 +52,7 @@ public class GlStateTracker { GlBufferType[] values = GlBufferType.values(); for (int i = 0; i < values.length; i++) { - if (buffers[i] != GlStateTracker.buffers[i]) { + if (buffers[i] != GlStateTracker.BUFFERS[i]) { GlStateManager._glBindBuffer(values[i].glEnum, buffers[i]); } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/GlBufferType.java b/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/GlBufferType.java index ead96fb03..9592ef241 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/GlBufferType.java +++ b/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/GlBufferType.java @@ -12,25 +12,27 @@ import com.jozufozu.flywheel.backend.gl.GlStateTracker; import com.mojang.blaze3d.platform.GlStateManager; public enum GlBufferType { - ARRAY_BUFFER(GL15C.GL_ARRAY_BUFFER), - ELEMENT_ARRAY_BUFFER(GL15C.GL_ELEMENT_ARRAY_BUFFER), - PIXEL_PACK_BUFFER(GL21.GL_PIXEL_PACK_BUFFER), - PIXEL_UNPACK_BUFFER(GL21.GL_PIXEL_UNPACK_BUFFER), - TRANSFORM_FEEDBACK_BUFFER(GL30.GL_TRANSFORM_FEEDBACK_BUFFER), - UNIFORM_BUFFER(GL31.GL_UNIFORM_BUFFER), - TEXTURE_BUFFER(GL31.GL_TEXTURE_BUFFER), - COPY_READ_BUFFER(GL31.GL_COPY_READ_BUFFER), - COPY_WRITE_BUFFER(GL31.GL_COPY_WRITE_BUFFER), - DRAW_INDIRECT_BUFFER(GL40.GL_DRAW_INDIRECT_BUFFER), - ATOMIC_COUNTER_BUFFER(GL42.GL_ATOMIC_COUNTER_BUFFER), - DISPATCH_INDIRECT_BUFFER(GL43.GL_DISPATCH_INDIRECT_BUFFER), - SHADER_STORAGE_BUFFER(GL43.GL_SHADER_STORAGE_BUFFER), + ARRAY_BUFFER(GL15C.GL_ARRAY_BUFFER, GL15C.GL_ARRAY_BUFFER_BINDING), + ELEMENT_ARRAY_BUFFER(GL15C.GL_ELEMENT_ARRAY_BUFFER, GL15C.GL_ELEMENT_ARRAY_BUFFER_BINDING), + PIXEL_PACK_BUFFER(GL21.GL_PIXEL_PACK_BUFFER, GL21.GL_PIXEL_PACK_BUFFER_BINDING), + PIXEL_UNPACK_BUFFER(GL21.GL_PIXEL_UNPACK_BUFFER, GL21.GL_PIXEL_UNPACK_BUFFER_BINDING), + TRANSFORM_FEEDBACK_BUFFER(GL30.GL_TRANSFORM_FEEDBACK_BUFFER, GL30.GL_TRANSFORM_FEEDBACK_BUFFER_BINDING), + UNIFORM_BUFFER(GL31.GL_UNIFORM_BUFFER, GL31.GL_UNIFORM_BUFFER_BINDING), + TEXTURE_BUFFER(GL31.GL_TEXTURE_BUFFER, GL31.GL_TEXTURE_BUFFER), + COPY_READ_BUFFER(GL31.GL_COPY_READ_BUFFER, GL31.GL_COPY_READ_BUFFER), + COPY_WRITE_BUFFER(GL31.GL_COPY_WRITE_BUFFER, GL31.GL_COPY_WRITE_BUFFER), + DRAW_INDIRECT_BUFFER(GL40.GL_DRAW_INDIRECT_BUFFER, GL40.GL_DRAW_INDIRECT_BUFFER_BINDING), + ATOMIC_COUNTER_BUFFER(GL42.GL_ATOMIC_COUNTER_BUFFER, GL42.GL_ATOMIC_COUNTER_BUFFER_BINDING), + DISPATCH_INDIRECT_BUFFER(GL43.GL_DISPATCH_INDIRECT_BUFFER, GL43.GL_DISPATCH_INDIRECT_BUFFER_BINDING), + SHADER_STORAGE_BUFFER(GL43.GL_SHADER_STORAGE_BUFFER, GL43.GL_SHADER_STORAGE_BUFFER_BINDING), ; public final int glEnum; + public final int glBindingEnum; - GlBufferType(int glEnum) { + GlBufferType(int glEnum, int glBindingEnum) { this.glEnum = glEnum; + this.glBindingEnum = glBindingEnum; } public static GlBufferType fromTarget(int pTarget) { 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 69ac4e759..621a5153e 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceWorld.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceWorld.java @@ -133,10 +133,10 @@ public class InstanceWorld implements AutoCloseable { /** * Instantiate all the necessary instances to render the given world. */ - public void loadEntities(ClientLevel world) { + public void loadEntities(ClientLevel level) { // Block entities are loaded while chunks are baked. - // Entities are loaded with the world, so when chunks are reloaded they need to be re-added. - ClientLevelExtension.getAllLoadedEntities(world) + // Entities are loaded with the level, so when chunks are reloaded they need to be re-added. + ClientLevelExtension.getAllLoadedEntities(level) .forEach(entities::add); } 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 f58abbb2a..2695ac4d2 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java @@ -3,6 +3,7 @@ package com.jozufozu.flywheel.backend.instancing; import java.util.List; import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.backend.gl.GlStateTracker; import com.jozufozu.flywheel.backend.instancing.effect.Effect; import com.jozufozu.flywheel.config.FlwCommands; import com.jozufozu.flywheel.config.FlwConfig; @@ -77,11 +78,11 @@ public class InstancedRenderDispatcher { return; } Minecraft mc = Minecraft.getInstance(); - ClientLevel world = mc.level; + ClientLevel level = mc.level; AnimationTickHolder.tick(); if (Backend.isOn()) { - instanceWorlds.get(world) + instanceWorlds.get(level) .tick(); } } @@ -94,22 +95,22 @@ public class InstancedRenderDispatcher { } public static void onRenderStage(RenderStageEvent event) { - ClientLevel world = event.getContext().level(); - if (!Backend.canUseInstancing(world)) return; + ClientLevel level = event.getContext().level(); + if (!Backend.canUseInstancing(level)) return; - instanceWorlds.get(world).renderStage(event.getContext(), event.getStage()); + instanceWorlds.get(level).renderStage(event.getContext(), event.getStage()); } public static void onReloadRenderers(ReloadRenderersEvent event) { - ClientLevel world = event.getWorld(); - if (Backend.isOn() && world != null) { - resetInstanceWorld(world); + ClientLevel level = event.getLevel(); + if (Backend.isOn() && level != null) { + resetInstanceLevel(level); } } - public static void resetInstanceWorld(ClientLevel world) { - instanceWorlds.replace(world, InstanceWorld::delete) - .loadEntities(world); + public static void resetInstanceLevel(ClientLevel level) { + instanceWorlds.replace(level, InstanceWorld::delete) + .loadEntities(level); } public static void getDebugString(List debug) { 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 deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchedMeshPool.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchedMeshPool.java new file mode 100644 index 000000000..896077b4d --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchedMeshPool.java @@ -0,0 +1,208 @@ +package com.jozufozu.flywheel.backend.instancing.batching; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.jetbrains.annotations.Nullable; +import org.lwjgl.system.MemoryUtil; + +import com.jozufozu.flywheel.Flywheel; +import com.jozufozu.flywheel.api.vertex.ReusableVertexList; +import com.jozufozu.flywheel.api.vertex.VertexListProvider; +import com.jozufozu.flywheel.backend.memory.MemoryBlock; +import com.jozufozu.flywheel.core.model.Mesh; +import com.mojang.blaze3d.vertex.VertexFormat; + +public class BatchedMeshPool { + private final VertexFormat vertexFormat; + private final ReusableVertexList vertexList; + private final int growthMargin; + + private final Map meshes = new HashMap<>(); + private final List allBuffered = new ArrayList<>(); + private final List pendingUpload = new ArrayList<>(); + + private MemoryBlock memory; + private long byteSize; + + private boolean dirty; + private boolean anyToRemove; + + /** + * Create a new mesh pool. + */ + public BatchedMeshPool(VertexFormat vertexFormat) { + this.vertexFormat = vertexFormat; + vertexList = VertexListProvider.get(vertexFormat).createVertexList(); + growthMargin = vertexList.vertexStride() * 32; + } + + /** + * Allocate a mesh in the arena. + * + * @param mesh The mesh to allocate. + * @return A handle to the allocated mesh. + */ + public BufferedMesh alloc(Mesh mesh) { + return meshes.computeIfAbsent(mesh, m -> { + BufferedMesh bufferedMesh = new BufferedMesh(m, byteSize, m.getVertexCount() * vertexList.vertexStride()); + byteSize += bufferedMesh.size(); + allBuffered.add(bufferedMesh); + pendingUpload.add(bufferedMesh); + + dirty = true; + return bufferedMesh; + }); + } + + @Nullable + public BufferedMesh get(Mesh mesh) { + return meshes.get(mesh); + } + + public void flush() { + if (dirty) { + if (anyToRemove) { + processDeletions(); + } + + realloc(); + uploadPending(); + + dirty = false; + pendingUpload.clear(); + } + } + + private void processDeletions() { + // remove deleted meshes + allBuffered.removeIf(bufferedMesh -> { + boolean deleted = bufferedMesh.isDeleted(); + if (deleted) { + meshes.remove(bufferedMesh.mesh); + } + return deleted; + }); + + // re-evaluate first vertex for each mesh + int byteIndex = 0; + for (BufferedMesh mesh : allBuffered) { + if (mesh.byteIndex != byteIndex) { + pendingUpload.add(mesh); + } + + mesh.byteIndex = byteIndex; + + byteIndex += mesh.size(); + } + + this.byteSize = byteIndex; + this.anyToRemove = false; + } + + private void realloc() { + if (byteSize < 0) { + throw new IllegalArgumentException("Size " + byteSize + " < 0"); + } + + if (byteSize == 0) { + return; + } + + if (memory == null) { + memory = MemoryBlock.malloc(byteSize); + } else if (byteSize > memory.size()) { + memory = memory.realloc(byteSize + growthMargin); + } + } + + private void uploadPending() { + try { + for (BufferedMesh mesh : pendingUpload) { + mesh.buffer(vertexList); + } + + pendingUpload.clear(); + } catch (Exception e) { + Flywheel.LOGGER.error("Error uploading pooled meshes:", e); + } + } + + public void delete() { + if (memory != null) { + memory.free(); + } + meshes.clear(); + allBuffered.clear(); + pendingUpload.clear(); + } + + public VertexFormat getVertexFormat() { + return vertexFormat; + } + + @Override + public String toString() { + return "BatchedMeshPool{" + "vertexFormat=" + vertexFormat + ", byteSize=" + byteSize + ", meshCount=" + meshes.size() + '}'; + } + + public class BufferedMesh { + private final Mesh mesh; + private long byteIndex; + private int byteSize; + private boolean deleted; + + private BufferedMesh(Mesh mesh, long byteIndex, int byteSize) { + this.mesh = mesh; + this.byteIndex = byteIndex; + this.byteSize = byteSize; + } + + private void buffer(ReusableVertexList vertexList) { + vertexList.ptr(ptr()); + vertexList.vertexCount(mesh.getVertexCount()); + + mesh.write(vertexList); + } + + public void copyTo(long ptr) { + if (isEmpty()) { + return; + } + + MemoryUtil.memCopy(ptr(), ptr, byteSize); + } + + private boolean isEmpty() { + return mesh.isEmpty() || isDeleted(); + } + + private long ptr() { + return BatchedMeshPool.this.memory.ptr() + byteIndex; + } + + public void delete() { + deleted = true; + BatchedMeshPool.this.dirty = true; + BatchedMeshPool.this.anyToRemove = true; + } + + public Mesh getMesh() { + return mesh; + } + + public int size() { + return byteSize; + } + + public VertexFormat getVertexFormat() { + return vertexFormat; + } + + public boolean isDeleted() { + return deleted; + } + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchingDrawTracker.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchingDrawTracker.java index 97afc1e3b..a36dfc59a 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchingDrawTracker.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchingDrawTracker.java @@ -1,8 +1,10 @@ package com.jozufozu.flywheel.backend.instancing.batching; import java.util.HashSet; +import java.util.Iterator; import java.util.Set; +import com.jozufozu.flywheel.api.RenderStage; import com.jozufozu.flywheel.extension.BufferBuilderExtension; import com.jozufozu.flywheel.extension.RenderTypeExtension; import com.mojang.blaze3d.vertex.BufferBuilder; @@ -10,7 +12,6 @@ import com.mojang.blaze3d.vertex.BufferBuilder; import net.minecraft.client.renderer.RenderType; public class BatchingDrawTracker { - private final Set activeTypes = new HashSet<>(); private final BufferBuilder scratch; @@ -20,13 +21,17 @@ public class BatchingDrawTracker { ((BufferBuilderExtension) scratch).flywheel$freeBuffer(); } - public DrawBuffer getBuffer(RenderType renderType) { + public DrawBuffer getBuffer(RenderType renderType, RenderStage stage) { + return getBufferSet(renderType).getBuffer(stage); + } + + public DrawBufferSet getBufferSet(RenderType renderType) { activeTypes.add(renderType); - return RenderTypeExtension.getDrawBuffer(renderType); + return RenderTypeExtension.getDrawBufferSet(renderType); } /** - * Draw and reset the DrawBuffer for the given RenderType. + * Draw and reset all DrawBuffers for the given RenderType. * @param renderType The RenderType to draw. */ public void draw(RenderType renderType) { @@ -36,7 +41,27 @@ public class BatchingDrawTracker { } /** - * Draws all active DrawBuffers and reset them. + * Draw and reset all DrawBuffers for the given RenderStage. + * @param stage The RenderStage to draw. + */ + public void draw(RenderStage stage) { + Iterator iterator = activeTypes.iterator(); + while (iterator.hasNext()) { + RenderType renderType = iterator.next(); + DrawBufferSet bufferSet = RenderTypeExtension.getDrawBufferSet(renderType); + DrawBuffer buffer = bufferSet.deactivateBuffer(stage); + if (buffer == null) { + continue; + } + if (bufferSet.getActiveStagesView().isEmpty()) { + iterator.remove(); + } + _draw(buffer, renderType); + } + } + + /** + * Draw and reset all active DrawBuffers. */ public void drawAll() { for (RenderType renderType : activeTypes) { @@ -47,8 +72,14 @@ public class BatchingDrawTracker { } private void _draw(RenderType renderType) { - DrawBuffer buffer = RenderTypeExtension.getDrawBuffer(renderType); + DrawBufferSet bufferSet = RenderTypeExtension.getDrawBufferSet(renderType); + for (RenderStage stage : bufferSet.getActiveStagesView()) { + DrawBuffer buffer = bufferSet.deactivateBuffer(stage); + _draw(buffer, renderType); + } + } + private void _draw(DrawBuffer buffer, RenderType renderType) { if (buffer.hasVertices()) { BufferBuilderExtension scratch = (BufferBuilderExtension) this.scratch; buffer.inject(scratch); @@ -59,15 +90,14 @@ public class BatchingDrawTracker { } /** - * Resets all DrawBuffers to 0 vertices. + * Reset all active DrawBuffers. */ public void reset() { for (RenderType type : activeTypes) { - RenderTypeExtension.getDrawBuffer(type) + RenderTypeExtension.getDrawBufferSet(type) .reset(); } activeTypes.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 1ce22ab22..994489382 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 @@ -23,7 +23,6 @@ import net.minecraft.core.Vec3i; import net.minecraft.world.phys.Vec3; public class BatchingEngine implements Engine { - protected final BatchingTransformManager transformManager = new BatchingTransformManager(); protected final BatchingDrawTracker drawTracker = new BatchingDrawTracker(); protected final Map, CPUInstancerFactory> factories = new HashMap<>(); @@ -54,41 +53,38 @@ public class BatchingEngine implements Engine { } public void submitTasks(TaskEngine taskEngine, PoseStack stack, ClientLevel level) { - BatchingTransformManager.TransformSet transformSet = transformManager.get(RenderStage.AFTER_FINAL_END_BATCH); - for (var entry : transformSet) { - var renderType = entry.getKey(); - var transformCalls = entry.getValue(); + for (var transformSetEntry : transformManager.getTransformSetsView().entrySet()) { + var stage = transformSetEntry.getKey(); + var transformSet = transformSetEntry.getValue(); - int vertices = 0; - for (var transformCall : transformCalls) { - vertices += transformCall.getTotalVertexCount(); - } + for (var entry : transformSet) { + var renderType = entry.getKey(); + var transformCalls = entry.getValue(); - if (vertices == 0) { - continue; - } + int vertices = 0; + for (var transformCall : transformCalls) { + vertices += transformCall.getTotalVertexCount(); + } - DrawBuffer buffer = drawTracker.getBuffer(renderType); - buffer.prepare(vertices); + if (vertices == 0) { + continue; + } - int startVertex = 0; - for (var transformCall : transformCalls) { - transformCall.submitTasks(taskEngine, buffer, startVertex, stack, level); - startVertex += transformCall.getTotalVertexCount(); + DrawBuffer buffer = drawTracker.getBuffer(renderType, stage); + buffer.prepare(vertices); + + int startVertex = 0; + for (var transformCall : transformCalls) { + transformCall.submitTasks(taskEngine, buffer, startVertex, stack, level); + startVertex += transformCall.getTotalVertexCount(); + } } } } @Override public void renderStage(TaskEngine taskEngine, RenderContext context, RenderStage stage) { - // FIXME: properly support material stages - // This also breaks block outlines on batched block entities - // and makes translucent blocks occlude everything Flywheel renders - if (stage != RenderStage.AFTER_FINAL_END_BATCH) { - return; - } - - drawTracker.drawAll(); + drawTracker.draw(stage); } @Override diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchingTransformManager.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchingTransformManager.java index 9c7fc8888..7452b7da3 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchingTransformManager.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchingTransformManager.java @@ -4,6 +4,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.EnumMap; +import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -14,16 +15,18 @@ import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ImmutableListMultimap; import com.google.common.collect.ListMultimap; import com.jozufozu.flywheel.api.RenderStage; +import com.jozufozu.flywheel.core.model.Mesh; import com.jozufozu.flywheel.core.model.Model; +import com.mojang.blaze3d.vertex.VertexFormat; import net.minecraft.client.renderer.RenderType; public class BatchingTransformManager { - private final List uninitializedModels = new ArrayList<>(); private final List> allInstancers = new ArrayList<>(); private final Map transformSets = new EnumMap<>(RenderStage.class); private final Map transformSetsView = Collections.unmodifiableMap(transformSets); + private final Map meshPools = new HashMap<>(); public TransformSet get(RenderStage stage) { return transformSets.getOrDefault(stage, TransformSet.EMPTY); @@ -42,9 +45,17 @@ public class BatchingTransformManager { add(model.instancer(), model.model()); } uninitializedModels.clear(); + + for (var pool : meshPools.values()) { + pool.flush(); + } } public void delete() { + meshPools.values() + .forEach(BatchedMeshPool::delete); + meshPools.clear(); + allInstancers.forEach(CPUInstancer::delete); allInstancers.clear(); } @@ -56,19 +67,22 @@ public class BatchingTransformManager { private void add(CPUInstancer instancer, Model model) { var meshes = model.getMeshes(); for (var entry : meshes.entrySet()) { - TransformCall transformCall = new TransformCall<>(instancer, entry.getKey(), entry.getValue()); - var material = transformCall.getMaterial(); + var material = entry.getKey(); var renderType = material.getBatchingRenderType(); + TransformCall transformCall = new TransformCall<>(instancer, material, alloc(entry.getValue(), renderType.format())); -// transformSets.computeIfAbsent(material.getRenderStage(), TransformSet::new) - transformSets.computeIfAbsent(RenderStage.AFTER_FINAL_END_BATCH, TransformSet::new) + transformSets.computeIfAbsent(material.getRenderStage(), TransformSet::new) .put(renderType, transformCall); } allInstancers.add(instancer); } - public static class TransformSet implements Iterable>>> { + private BatchedMeshPool.BufferedMesh alloc(Mesh mesh, VertexFormat format) { + return meshPools.computeIfAbsent(format, BatchedMeshPool::new) + .alloc(mesh); + } + public static class TransformSet implements Iterable>>> { public static final TransformSet EMPTY = new TransformSet(ImmutableListMultimap.of()); final ListMultimap> transformCalls; 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 053b9d52c..534fd687c 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 @@ -4,8 +4,6 @@ import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; -import org.jetbrains.annotations.ApiStatus; - import com.jozufozu.flywheel.api.vertex.ReusableVertexList; import com.jozufozu.flywheel.api.vertex.VertexListProvider; import com.jozufozu.flywheel.backend.memory.MemoryBlock; @@ -31,11 +29,10 @@ public class DrawBuffer { private boolean prepared; private int vertexCount; - @ApiStatus.Internal - public DrawBuffer(VertexFormat format) { + DrawBuffer(VertexFormat format, int stride, VertexListProvider provider) { this.format = format; - stride = format.getVertexSize(); - provider = VertexListProvider.get(format); + this.stride = stride; + this.provider = provider; ALL.add(this); } @@ -75,9 +72,8 @@ public class DrawBuffer { } ReusableVertexList vertexList = provider.createVertexList(); - vertexList.ptr(memory.ptr()); - vertexList.shiftPtr(startVertex); - vertexList.setVertexCount(vertexCount); + vertexList.ptr(memory.ptr() + startVertex * vertexList.vertexStride()); + vertexList.vertexCount(vertexCount); return vertexList; } @@ -94,6 +90,10 @@ public class DrawBuffer { bufferBuilder.flywheel$injectForRender(buffer, format, vertexCount); } + public VertexFormat getVertexFormat() { + return format; + } + public boolean isPrepared() { return prepared; } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/DrawBufferSet.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/DrawBufferSet.java new file mode 100644 index 000000000..15b66b33d --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/DrawBufferSet.java @@ -0,0 +1,66 @@ +package com.jozufozu.flywheel.backend.instancing.batching; + +import java.util.Collections; +import java.util.EnumMap; +import java.util.EnumSet; +import java.util.Map; +import java.util.Set; + +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; + +import com.jozufozu.flywheel.api.RenderStage; +import com.jozufozu.flywheel.api.vertex.VertexListProvider; +import com.mojang.blaze3d.vertex.VertexFormat; + +public class DrawBufferSet { + private final VertexFormat format; + private final int stride; + private final VertexListProvider provider; + + private final Map buffers = new EnumMap<>(RenderStage.class); + private final Set activeStages = EnumSet.noneOf(RenderStage.class); + private final Set activeStagesView = Collections.unmodifiableSet(activeStages); + + @ApiStatus.Internal + public DrawBufferSet(VertexFormat format) { + this.format = format; + stride = format.getVertexSize(); + provider = VertexListProvider.get(format); + } + + public Set getActiveStagesView() { + return activeStagesView; + } + + public DrawBuffer getBuffer(RenderStage stage) { + activeStages.add(stage); + return buffers.computeIfAbsent(stage, $ -> createBuffer()); + } + + @Nullable + public DrawBuffer deactivateBuffer(RenderStage stage) { + if (activeStages.remove(stage)) { + return buffers.get(stage); + } + return null; + } + + public void reset(RenderStage stage) { + if (activeStages.remove(stage)) { + buffers.get(stage).reset(); + } + } + + public void reset() { + for (RenderStage stage : activeStages) { + buffers.get(stage).reset(); + } + + activeStages.clear(); + } + + private DrawBuffer createBuffer() { + return new DrawBuffer(format, stride, provider); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/TransformCall.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/TransformCall.java index 8060cb176..caac1a4f4 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/TransformCall.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/TransformCall.java @@ -8,8 +8,8 @@ import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.api.vertex.MutableVertexList; import com.jozufozu.flywheel.api.vertex.ReusableVertexList; import com.jozufozu.flywheel.backend.instancing.TaskEngine; -import com.jozufozu.flywheel.core.model.Mesh; import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.math.Matrix3f; import com.mojang.math.Matrix4f; import com.mojang.math.Vector3f; @@ -18,23 +18,22 @@ import com.mojang.math.Vector4f; import net.minecraft.client.multiplayer.ClientLevel; public class TransformCall { - private final CPUInstancer instancer; private final Material material; - private final Mesh mesh; + private final BatchedMeshPool.BufferedMesh bufferedMesh; - public TransformCall(CPUInstancer instancer, Material material, Mesh mesh) { + public TransformCall(CPUInstancer instancer, Material material, BatchedMeshPool.BufferedMesh mesh) { this.instancer = instancer; this.material = material; - this.mesh = mesh; + this.bufferedMesh = mesh; } public Material getMaterial() { return material; } - public Mesh getMesh() { - return mesh; + public VertexFormat getVertexFormat() { + return bufferedMesh.getVertexFormat(); } void submitTasks(TaskEngine pool, DrawBuffer buffer, int startVertex, PoseStack stack, ClientLevel level) { @@ -47,7 +46,7 @@ public class TransformCall { instances -= 512; int start = Math.max(instances, 0); - int vertexCount = mesh.getVertexCount() * (end - start); + int vertexCount = bufferedMesh.getMesh().getVertexCount() * (end - start); ReusableVertexList sub = buffer.slice(startVertex, vertexCount); startVertex += vertexCount; @@ -65,23 +64,24 @@ public class TransformCall { private void transformList(ReusableVertexList vertexList, List parts, PoseStack stack, ClientLevel level) { long anchorPtr = vertexList.ptr(); - int totalVertexCount = vertexList.getVertexCount(); + int totalVertexCount = vertexList.vertexCount(); - int meshVertexCount = mesh.getVertexCount(); - vertexList.setVertexCount(meshVertexCount); + int meshVertexCount = bufferedMesh.getMesh().getVertexCount(); + int meshByteSize = bufferedMesh.size(); + vertexList.vertexCount(meshVertexCount); StructType.VertexTransformer structVertexTransformer = instancer.type.getVertexTransformer(); for (D d : parts) { - mesh.write(vertexList); + bufferedMesh.copyTo(vertexList.ptr()); structVertexTransformer.transform(vertexList, d, level); - vertexList.shiftPtr(meshVertexCount); + vertexList.ptr(vertexList.ptr() + meshByteSize); } vertexList.ptr(anchorPtr); - vertexList.setVertexCount(totalVertexCount); + vertexList.vertexCount(totalVertexCount); material.getVertexTransformer().transform(vertexList, level); applyPoseStack(vertexList, stack); } @@ -93,7 +93,7 @@ public class TransformCall { Matrix4f modelMatrix = stack.last().pose(); Matrix3f normalMatrix = stack.last().normal(); - for (int i = 0; i < vertexList.getVertexCount(); i++) { + for (int i = 0; i < vertexList.vertexCount(); i++) { pos.set( vertexList.x(i), vertexList.y(i), @@ -119,6 +119,6 @@ public class TransformCall { } public int getTotalVertexCount() { - return mesh.getVertexCount() * instancer.getInstanceCount(); + return bufferedMesh.getMesh().getVertexCount() * instancer.getInstanceCount(); } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/blockentity/BlockEntityInstanceManager.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/blockentity/BlockEntityInstanceManager.java index 7059e4763..7daf01429 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/blockentity/BlockEntityInstanceManager.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/blockentity/BlockEntityInstanceManager.java @@ -47,20 +47,20 @@ public class BlockEntityInstanceManager extends InstanceManager { return false; } - Level world = blockEntity.getLevel(); + Level level = blockEntity.getLevel(); - if (world == null) { + if (level == null) { return false; } - if (world.isEmptyBlock(blockEntity.getBlockPos())) { + if (level.isEmptyBlock(blockEntity.getBlockPos())) { return false; } - if (Backend.isFlywheelWorld(world)) { + if (Backend.isFlywheelLevel(level)) { BlockPos pos = blockEntity.getBlockPos(); - BlockGetter existingChunk = world.getChunkForCollisions(pos.getX() >> 4, pos.getZ() >> 4); + BlockGetter existingChunk = level.getChunkForCollisions(pos.getX() >> 4, pos.getZ() >> 4); return existingChunk != null; } 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 8a729a559..33e42b155 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 @@ -42,12 +42,12 @@ public class EntityInstanceManager extends InstanceManager { return false; } - Level world = entity.level; + Level level = entity.level; - if (Backend.isFlywheelWorld(world)) { + if (Backend.isFlywheelLevel(level)) { BlockPos pos = entity.blockPosition(); - BlockGetter existingChunk = world.getChunkForCollisions(pos.getX() >> 4, pos.getZ() >> 4); + BlockGetter existingChunk = level.getChunkForCollisions(pos.getX() >> 4, pos.getZ() >> 4); return existingChunk != null; } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectEngine.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectEngine.java index f6585868f..5cbe78050 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectEngine.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/indirect/IndirectEngine.java @@ -12,6 +12,7 @@ import com.jozufozu.flywheel.api.RenderStage; import com.jozufozu.flywheel.api.context.ContextShader; import com.jozufozu.flywheel.api.instancer.InstancedPart; import com.jozufozu.flywheel.api.struct.StructType; +import com.jozufozu.flywheel.backend.gl.GlStateTracker; import com.jozufozu.flywheel.backend.gl.GlTextureUnit; import com.jozufozu.flywheel.backend.instancing.Engine; import com.jozufozu.flywheel.backend.instancing.InstanceManager; @@ -65,10 +66,12 @@ public class IndirectEngine implements Engine { @Override public void renderStage(TaskEngine taskEngine, RenderContext context, RenderStage stage) { - setup(); - - for (var list : indirectDrawManager.lists.values()) { - list.submit(stage); + try (var restoreState = GlStateTracker.getRestoreState()) { + setup(); + + for (var list : indirectDrawManager.lists.values()) { + list.submit(stage); + } } } @@ -121,13 +124,15 @@ public class IndirectEngine implements Engine { @Override public void beginFrame(TaskEngine taskEngine, RenderContext context) { - for (var model : uninitializedModels) { - model.init(indirectDrawManager); - } - uninitializedModels.clear(); - - for (IndirectCullingGroup value : indirectDrawManager.lists.values()) { - value.beginFrame(); + try (var restoreState = GlStateTracker.getRestoreState()) { + for (var model : uninitializedModels) { + model.init(indirectDrawManager); + } + uninitializedModels.clear(); + + for (IndirectCullingGroup value : indirectDrawManager.lists.values()) { + value.beginFrame(); + } } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/DrawCall.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/DrawCall.java index 37db2049b..19362548c 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/DrawCall.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/DrawCall.java @@ -10,10 +10,10 @@ public class DrawCall { final GPUInstancer instancer; final Material material; private final int meshAttributes; - MeshPool.BufferedMesh bufferedMesh; + InstancedMeshPool.BufferedMesh bufferedMesh; GlVertexArray vao; - DrawCall(GPUInstancer instancer, Material material, MeshPool.BufferedMesh mesh) { + DrawCall(GPUInstancer instancer, Material material, InstancedMeshPool.BufferedMesh mesh) { this.instancer = instancer; this.material = material; this.vao = new GlVertexArray(); diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/MeshPool.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancedMeshPool.java similarity index 68% rename from src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/MeshPool.java rename to src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancedMeshPool.java index 739eda2f9..3fd0ad738 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/MeshPool.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancedMeshPool.java @@ -19,16 +19,14 @@ import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType; import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer; import com.jozufozu.flywheel.core.model.Mesh; -public class MeshPool { - +public class InstancedMeshPool { private final VertexType vertexType; + private final Map meshes = new HashMap<>(); private final List allBuffered = new ArrayList<>(); - private final List pendingUpload = new ArrayList<>(); private final GlBuffer vbo; - private long byteSize; private boolean dirty; @@ -37,7 +35,7 @@ public class MeshPool { /** * Create a new mesh pool. */ - public MeshPool(VertexType vertexType) { + public InstancedMeshPool(VertexType vertexType) { this.vertexType = vertexType; int stride = vertexType.getStride(); this.vbo = new GlBuffer(GlBufferType.ARRAY_BUFFER); @@ -46,10 +44,10 @@ public class MeshPool { } /** - * Allocate a model in the arena. + * Allocate a mesh in the arena. * - * @param mesh The model to allocate. - * @return A handle to the allocated model. + * @param mesh The mesh to allocate. + * @return A handle to the allocated mesh. */ public BufferedMesh alloc(Mesh mesh) { return meshes.computeIfAbsent(mesh, m -> { @@ -57,13 +55,13 @@ public class MeshPool { throw new IllegalArgumentException("Mesh has wrong vertex type"); } - BufferedMesh bufferedModel = new BufferedMesh(m, byteSize); - byteSize += m.size(); - allBuffered.add(bufferedModel); - pendingUpload.add(bufferedModel); + BufferedMesh bufferedMesh = new BufferedMesh(m, byteSize); + byteSize += bufferedMesh.size(); + allBuffered.add(bufferedMesh); + pendingUpload.add(bufferedMesh); dirty = true; - return bufferedModel; + return bufferedMesh; }); } @@ -90,7 +88,6 @@ public class MeshPool { } private void processDeletions() { - // remove deleted meshes allBuffered.removeIf(bufferedMesh -> { boolean deleted = bufferedMesh.isDeleted(); @@ -100,16 +97,16 @@ public class MeshPool { return deleted; }); - // re-evaluate first vertex for each model + // re-evaluate first vertex for each mesh int byteIndex = 0; - for (BufferedMesh model : allBuffered) { - if (model.byteIndex != byteIndex) { - pendingUpload.add(model); + for (BufferedMesh mesh : allBuffered) { + if (mesh.byteIndex != byteIndex) { + pendingUpload.add(mesh); } - model.byteIndex = byteIndex; + mesh.byteIndex = byteIndex; - byteIndex += model.mesh.size(); + byteIndex += mesh.size(); } this.byteSize = byteIndex; @@ -130,14 +127,13 @@ public class MeshPool { long ptr = mapped.getPtr(); int byteIndex = 0; - for (BufferedMesh model : allBuffered) { - model.byteIndex = byteIndex; + for (BufferedMesh mesh : allBuffered) { + mesh.byteIndex = byteIndex; - model.buffer(ptr); + mesh.buffer(ptr); - byteIndex += model.mesh.size(); + byteIndex += mesh.size(); } - } catch (Exception e) { Flywheel.LOGGER.error("Error uploading pooled meshes:", e); } @@ -145,10 +141,12 @@ public class MeshPool { private void uploadPending() { try (MappedBuffer mapped = vbo.map()) { - long buffer = mapped.getPtr(); - for (BufferedMesh model : pendingUpload) { - model.buffer(buffer); + long ptr = mapped.getPtr(); + + for (BufferedMesh mesh : pendingUpload) { + mesh.buffer(ptr); } + pendingUpload.clear(); } catch (Exception e) { Flywheel.LOGGER.error("Error uploading pooled meshes:", e); @@ -162,32 +160,41 @@ public class MeshPool { pendingUpload.clear(); } + public VertexType getVertexType() { + return vertexType; + } + @Override public String toString() { - return "MeshPool{" + "vertexType=" + vertexType + ", byteSize=" + byteSize + ", meshCount=" + meshes.size() + '}'; + return "InstancedMeshPool{" + "vertexType=" + vertexType + ", byteSize=" + byteSize + ", meshCount=" + meshes.size() + '}'; } public class BufferedMesh { - - private final ElementBuffer ebo; private final Mesh mesh; + private final ElementBuffer ebo; private long byteIndex; private boolean deleted; private final Set boundTo = new HashSet<>(); - public BufferedMesh(Mesh mesh, long byteIndex) { + private BufferedMesh(Mesh mesh, long byteIndex) { this.mesh = mesh; this.byteIndex = byteIndex; this.ebo = mesh.createEBO(); } + private void buffer(long ptr) { + mesh.write(ptr + byteIndex); + + boundTo.clear(); + } + public void drawCall(GlVertexArray vao) { drawInstances(vao, 1); } public void drawInstances(GlVertexArray vao, int instanceCount) { - if (hasAnythingToRender()) { + if (isEmpty()) { return; } @@ -196,50 +203,51 @@ public class MeshPool { draw(instanceCount); } - private boolean hasAnythingToRender() { + private boolean isEmpty() { return mesh.isEmpty() || isDeleted(); } + private void setup(GlVertexArray vao) { + if (boundTo.add(vao)) { + vao.enableArrays(getAttributeCount()); + vao.bindAttributes(InstancedMeshPool.this.vbo, 0, vertexType.getLayout(), byteIndex); + } + vao.bindElementArray(ebo.buffer); + vao.bind(); + } + private void draw(int instanceCount) { if (instanceCount > 1) { - GL32.glDrawElementsInstanced(GlPrimitive.TRIANGLES.glEnum, this.ebo.elementCount, this.ebo.eboIndexType.getGlEnum(), 0, instanceCount); + GL32.glDrawElementsInstanced(GlPrimitive.TRIANGLES.glEnum, ebo.elementCount, ebo.eboIndexType.getGlEnum(), 0, instanceCount); } else { - GL32.glDrawElements(GlPrimitive.TRIANGLES.glEnum, this.ebo.elementCount, this.ebo.eboIndexType.getGlEnum(), 0); + GL32.glDrawElements(GlPrimitive.TRIANGLES.glEnum, ebo.elementCount, ebo.eboIndexType.getGlEnum(), 0); } } - private void setup(GlVertexArray vao) { - if (this.boundTo.add(vao)) { - vao.enableArrays(getAttributeCount()); - vao.bindAttributes(MeshPool.this.vbo, 0, vertexType.getLayout(), this.byteIndex); - } - vao.bindElementArray(this.ebo.buffer); - vao.bind(); - } - - public boolean isDeleted() { - return this.deleted; - } - public void delete() { - MeshPool.this.dirty = true; - MeshPool.this.anyToRemove = true; - this.deleted = true; + deleted = true; + InstancedMeshPool.this.dirty = true; + InstancedMeshPool.this.anyToRemove = true; } - private void buffer(long ptr) { - this.mesh.write(ptr + byteIndex); + public Mesh getMesh() { + return mesh; + } - this.boundTo.clear(); + public int size() { + return mesh.size(); + } + + public VertexType getVertexType() { + return vertexType; } public int getAttributeCount() { return vertexType.getLayout().getAttributeCount(); } - public VertexType getVertexType() { - return vertexType; + public boolean isDeleted() { + return deleted; } } - } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancingDrawManager.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancingDrawManager.java index d790be99a..27afd6743 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancingDrawManager.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancingDrawManager.java @@ -23,7 +23,7 @@ public class InstancingDrawManager { private final List uninitializedModels = new ArrayList<>(); private final List> allInstancers = new ArrayList<>(); private final Map renderLists = new EnumMap<>(RenderStage.class); - private final Map meshPools = new HashMap<>(); + private final Map meshPools = new HashMap<>(); public DrawSet get(RenderStage stage) { return renderLists.getOrDefault(stage, DrawSet.EMPTY); @@ -49,7 +49,7 @@ public class InstancingDrawManager { public void delete() { meshPools.values() - .forEach(MeshPool::delete); + .forEach(InstancedMeshPool::delete); meshPools.clear(); renderLists.values() @@ -77,8 +77,8 @@ public class InstancingDrawManager { allInstancers.add(instancer); } - private MeshPool.BufferedMesh alloc(Mesh mesh) { - return meshPools.computeIfAbsent(mesh.getVertexType(), MeshPool::new) + private InstancedMeshPool.BufferedMesh alloc(Mesh mesh) { + return meshPools.computeIfAbsent(mesh.getVertexType(), InstancedMeshPool::new) .alloc(mesh); } 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 a3bd99d58..ed5a7fe55 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 @@ -12,6 +12,7 @@ import com.jozufozu.flywheel.api.RenderStage; import com.jozufozu.flywheel.api.context.ContextShader; import com.jozufozu.flywheel.api.instancer.InstancedPart; import com.jozufozu.flywheel.api.struct.StructType; +import com.jozufozu.flywheel.backend.gl.GlStateTracker; import com.jozufozu.flywheel.backend.gl.GlTextureUnit; import com.jozufozu.flywheel.backend.instancing.Engine; import com.jozufozu.flywheel.backend.instancing.InstanceManager; @@ -64,7 +65,9 @@ public class InstancingEngine implements Engine { @Override public void beginFrame(TaskEngine taskEngine, RenderContext context) { - drawManager.flush(); + try (var restoreState = GlStateTracker.getRestoreState()) { + drawManager.flush(); + } } @Override @@ -75,9 +78,11 @@ public class InstancingEngine implements Engine { return; } - setup(); - - render(drawSet); + try (var restoreState = GlStateTracker.getRestoreState()) { + setup(); + + render(drawSet); + } } protected void setup() { diff --git a/src/main/java/com/jozufozu/flywheel/config/FlwCommands.java b/src/main/java/com/jozufozu/flywheel/config/FlwCommands.java index b66a6a707..393a0872d 100644 --- a/src/main/java/com/jozufozu/flywheel/config/FlwCommands.java +++ b/src/main/java/com/jozufozu/flywheel/config/FlwCommands.java @@ -59,23 +59,6 @@ public class FlwCommands { return Command.SINGLE_SUCCESS; }))); - commandBuilder.addValue(config.client.debugNormals, "debugNormals", (builder, value) -> booleanValueCommand(builder, value, - (source, bool) -> { - LocalPlayer player = Minecraft.getInstance().player; - if (player == null) return; - - Component text = new TextComponent("Normal debug mode is currently: ").append(boolToText(bool)); - player.displayClientMessage(text, false); - }, - (source, bool) -> { - LocalPlayer player = Minecraft.getInstance().player; - if (player == null) return; - - Component text = boolToText(bool).append(new TextComponent(" normal debug mode").withStyle(ChatFormatting.WHITE)); - player.displayClientMessage(text, false); - } - )); - commandBuilder.addValue(config.client.limitUpdates, "limitUpdates", (builder, value) -> booleanValueCommand(builder, value, (source, bool) -> { LocalPlayer player = Minecraft.getInstance().player; @@ -95,7 +78,18 @@ public class FlwCommands { } )); - commandBuilder.command.then(Commands.literal("debugCrumble") + // TODO + commandBuilder.command.then(Commands.literal("debugNormals")) + .executes(context -> { + LocalPlayer player = Minecraft.getInstance().player; + if (player == null) return 0; + + player.displayClientMessage(new TextComponent("This command is not yet implemented."), false); + + return Command.SINGLE_SUCCESS; + }); + + commandBuilder.command.then(Commands.literal("debugCrumbling") .then(Commands.argument("pos", BlockPosArgument.blockPos()) .then(Commands.argument("stage", IntegerArgumentType.integer(0, 9)) .executes(context -> { @@ -111,7 +105,7 @@ public class FlwCommands { executor.level.destroyBlockProgress(executor.getId(), pos, value); - return 1; + return Command.SINGLE_SUCCESS; })))); commandBuilder.command.then(Commands.literal("debugFrustum") diff --git a/src/main/java/com/jozufozu/flywheel/config/FlwConfig.java b/src/main/java/com/jozufozu/flywheel/config/FlwConfig.java index f9318e3c3..611b1fbec 100644 --- a/src/main/java/com/jozufozu/flywheel/config/FlwConfig.java +++ b/src/main/java/com/jozufozu/flywheel/config/FlwConfig.java @@ -35,10 +35,6 @@ public class FlwConfig { return BackendTypes.getBackendType(client.backend.get()); } - public boolean debugNormals() { - return client.debugNormals.get(); - } - public boolean limitUpdates() { return client.limitUpdates.get(); } @@ -48,7 +44,6 @@ public class FlwConfig { public static class ClientConfig { public final ForgeConfigSpec.ConfigValue backend; - public final BooleanValue debugNormals; public final BooleanValue limitUpdates; public ClientConfig(ForgeConfigSpec.Builder builder) { @@ -56,9 +51,6 @@ public class FlwConfig { .define("backend", BackendTypes.defaultForCurrentPC() .getShortName()); - debugNormals = builder.comment("Enable or disable a debug overlay that colors pixels by their normal.") - .define("debugNormals", false); - limitUpdates = builder.comment("Enable or disable instance update limiting with distance.") .define("limitUpdates", true); } diff --git a/src/main/java/com/jozufozu/flywheel/core/Materials.java b/src/main/java/com/jozufozu/flywheel/core/Materials.java index 393ee2126..fcc72a3cc 100644 --- a/src/main/java/com/jozufozu/flywheel/core/Materials.java +++ b/src/main/java/com/jozufozu/flywheel/core/Materials.java @@ -25,7 +25,7 @@ public final class Materials { } DiffuseLightCalculator diffuseCalc = DiffuseLightCalculator.forLevel(level); - for (int i = 0; i < vertexList.getVertexCount(); i++) { + for (int i = 0; i < vertexList.vertexCount(); i++) { float diffuse = diffuseCalc.getDiffuse(vertexList.normalX(i), vertexList.normalY(i), vertexList.normalZ(i), true); vertexList.r(i, (byte) Mth.clamp((int) (Byte.toUnsignedInt(vertexList.r(i)) * diffuse), 0, 255)); vertexList.g(i, (byte) Mth.clamp((int) (Byte.toUnsignedInt(vertexList.g(i)) * diffuse), 0, 255)); diff --git a/src/main/java/com/jozufozu/flywheel/core/hardcoded/ModelPart.java b/src/main/java/com/jozufozu/flywheel/core/hardcoded/ModelPart.java index b381d859b..176610cbb 100644 --- a/src/main/java/com/jozufozu/flywheel/core/hardcoded/ModelPart.java +++ b/src/main/java/com/jozufozu/flywheel/core/hardcoded/ModelPart.java @@ -33,7 +33,7 @@ public class ModelPart implements Mesh { vertexList = getVertexType().createVertexList(); vertexList.ptr(ptr); - vertexList.setVertexCount(vertexCount); + vertexList.vertexCount(vertexCount); boundingSphere = ModelUtil.computeBoundingSphere(vertexList); } diff --git a/src/main/java/com/jozufozu/flywheel/core/model/ModelUtil.java b/src/main/java/com/jozufozu/flywheel/core/model/ModelUtil.java index edfbf2ca2..9466abff0 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/ModelUtil.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/ModelUtil.java @@ -66,8 +66,8 @@ public class ModelUtil { ReusableVertexList dstList = dstVertexType.createVertexList(); srcList.ptr(srcPtr); dstList.ptr(dstPtr); - srcList.setVertexCount(vertexCount); - dstList.setVertexCount(vertexCount); + srcList.vertexCount(vertexCount); + dstList.vertexCount(vertexCount); srcList.writeAll(dstList); diff --git a/src/main/java/com/jozufozu/flywheel/core/model/SimpleMesh.java b/src/main/java/com/jozufozu/flywheel/core/model/SimpleMesh.java index 95ce7d8bf..8dcb3f9bd 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/SimpleMesh.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/SimpleMesh.java @@ -29,7 +29,7 @@ public class SimpleMesh implements Mesh { vertexList = getVertexType().createVertexList(); vertexList.ptr(contents.ptr()); - vertexList.setVertexCount(vertexCount); + vertexList.vertexCount(vertexCount); boundingSphere = ModelUtil.computeBoundingSphere(vertexList); } diff --git a/src/main/java/com/jozufozu/flywheel/core/structs/oriented/OrientedType.java b/src/main/java/com/jozufozu/flywheel/core/structs/oriented/OrientedType.java index f03134e8e..166231bf9 100644 --- a/src/main/java/com/jozufozu/flywheel/core/structs/oriented/OrientedType.java +++ b/src/main/java/com/jozufozu/flywheel/core/structs/oriented/OrientedType.java @@ -59,7 +59,7 @@ public class OrientedType implements StructType { Matrix3f normalMatrix = new Matrix3f(q); int light = struct.getPackedLight(); - for (int i = 0; i < vertexList.getVertexCount(); i++) { + for (int i = 0; i < vertexList.vertexCount(); i++) { pos.set( vertexList.x(i), vertexList.y(i), diff --git a/src/main/java/com/jozufozu/flywheel/core/structs/transformed/TransformedType.java b/src/main/java/com/jozufozu/flywheel/core/structs/transformed/TransformedType.java index 683f9bbaa..2138e8743 100644 --- a/src/main/java/com/jozufozu/flywheel/core/structs/transformed/TransformedType.java +++ b/src/main/java/com/jozufozu/flywheel/core/structs/transformed/TransformedType.java @@ -45,7 +45,7 @@ public class TransformedType implements StructType { Vector3f normal = new Vector3f(); int light = struct.getPackedLight(); - for (int i = 0; i < vertexList.getVertexCount(); i++) { + for (int i = 0; i < vertexList.vertexCount(); i++) { pos.set( vertexList.x(i), vertexList.y(i), diff --git a/src/main/java/com/jozufozu/flywheel/core/vertex/AbstractVertexList.java b/src/main/java/com/jozufozu/flywheel/core/vertex/AbstractVertexList.java index 3319f7a1e..75f679a19 100644 --- a/src/main/java/com/jozufozu/flywheel/core/vertex/AbstractVertexList.java +++ b/src/main/java/com/jozufozu/flywheel/core/vertex/AbstractVertexList.java @@ -17,12 +17,12 @@ public abstract class AbstractVertexList implements ReusableVertexList { } @Override - public int getVertexCount() { + public int vertexCount() { return vertexCount; } @Override - public void setVertexCount(int vertexCount) { + public void vertexCount(int vertexCount) { this.vertexCount = vertexCount; } } diff --git a/src/main/java/com/jozufozu/flywheel/core/vertex/BlockVertexList.java b/src/main/java/com/jozufozu/flywheel/core/vertex/BlockVertexList.java index ecfa8f277..2b8129ae5 100644 --- a/src/main/java/com/jozufozu/flywheel/core/vertex/BlockVertexList.java +++ b/src/main/java/com/jozufozu/flywheel/core/vertex/BlockVertexList.java @@ -153,7 +153,7 @@ public class BlockVertexList extends AbstractVertexList { } @Override - public void shiftPtr(int vertices) { - ptr += vertices * STRIDE; + public int vertexStride() { + return STRIDE; } } diff --git a/src/main/java/com/jozufozu/flywheel/core/vertex/InferredVertexListImpl.java b/src/main/java/com/jozufozu/flywheel/core/vertex/InferredVertexListImpl.java index 0b18204ff..f4d1a0353 100644 --- a/src/main/java/com/jozufozu/flywheel/core/vertex/InferredVertexListImpl.java +++ b/src/main/java/com/jozufozu/flywheel/core/vertex/InferredVertexListImpl.java @@ -203,7 +203,7 @@ public class InferredVertexListImpl extends AbstractVertexList implements Reusab } @Override - public void shiftPtr(int vertices) { - ptr += vertices * stride; + public int vertexStride() { + return stride; } } diff --git a/src/main/java/com/jozufozu/flywheel/core/vertex/PosTexNormalVertexList.java b/src/main/java/com/jozufozu/flywheel/core/vertex/PosTexNormalVertexList.java index 4ac841c04..52506ac66 100644 --- a/src/main/java/com/jozufozu/flywheel/core/vertex/PosTexNormalVertexList.java +++ b/src/main/java/com/jozufozu/flywheel/core/vertex/PosTexNormalVertexList.java @@ -148,7 +148,7 @@ public class PosTexNormalVertexList extends AbstractVertexList { } @Override - public void shiftPtr(int vertices) { - ptr += vertices * STRIDE; + public int vertexStride() { + return STRIDE; } } diff --git a/src/main/java/com/jozufozu/flywheel/core/virtual/VirtualRenderWorld.java b/src/main/java/com/jozufozu/flywheel/core/virtual/VirtualRenderWorld.java index 68dd97d71..e11b0e118 100644 --- a/src/main/java/com/jozufozu/flywheel/core/virtual/VirtualRenderWorld.java +++ b/src/main/java/com/jozufozu/flywheel/core/virtual/VirtualRenderWorld.java @@ -11,7 +11,7 @@ import java.util.function.Predicate; import org.jetbrains.annotations.Nullable; -import com.jozufozu.flywheel.api.FlywheelWorld; +import com.jozufozu.flywheel.api.FlywheelLevel; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -43,7 +43,7 @@ import net.minecraft.world.level.storage.WritableLevelData; import net.minecraft.world.scores.Scoreboard; import net.minecraft.world.ticks.LevelTickAccess; -public class VirtualRenderWorld extends Level implements FlywheelWorld { +public class VirtualRenderWorld extends Level implements FlywheelLevel { public final Map blocksAdded = new HashMap<>(); public final Map besAdded = new HashMap<>(); public final Set spannedSections = new HashSet<>(); diff --git a/src/main/java/com/jozufozu/flywheel/event/ReloadRenderersEvent.java b/src/main/java/com/jozufozu/flywheel/event/ReloadRenderersEvent.java index 6187ae578..01e90a44f 100644 --- a/src/main/java/com/jozufozu/flywheel/event/ReloadRenderersEvent.java +++ b/src/main/java/com/jozufozu/flywheel/event/ReloadRenderersEvent.java @@ -6,14 +6,14 @@ import net.minecraft.client.multiplayer.ClientLevel; import net.minecraftforge.eventbus.api.Event; public class ReloadRenderersEvent extends Event { - private final ClientLevel world; + private final ClientLevel level; - public ReloadRenderersEvent(ClientLevel world) { - this.world = world; + public ReloadRenderersEvent(ClientLevel level) { + this.level = level; } @Nullable - public ClientLevel getWorld() { - return world; + public ClientLevel getLevel() { + return level; } } diff --git a/src/main/java/com/jozufozu/flywheel/extension/RenderTypeExtension.java b/src/main/java/com/jozufozu/flywheel/extension/RenderTypeExtension.java index dbf31df06..9d361f1a7 100644 --- a/src/main/java/com/jozufozu/flywheel/extension/RenderTypeExtension.java +++ b/src/main/java/com/jozufozu/flywheel/extension/RenderTypeExtension.java @@ -1,27 +1,26 @@ package com.jozufozu.flywheel.extension; -import com.jozufozu.flywheel.backend.instancing.batching.DrawBuffer; +import com.jozufozu.flywheel.backend.instancing.batching.DrawBufferSet; import net.minecraft.client.renderer.RenderType; /** - * Duck interface to make RenderType store a DrawBuffer. + * Duck interface to make RenderType store a DrawBufferSet. * * @see RenderType */ public interface RenderTypeExtension { + /** + * @return The DrawBufferSet associated with this RenderType. + */ + DrawBufferSet flywheel$getDrawBufferSet(); /** - * @return The DrawBuffer associated with this RenderType. + * Helper function to cast a RenderType to a RenderTypeExtension and get its DrawBufferSet. + * @param type The RenderType to get the DrawBufferSet from. + * @return The DrawBufferSet associated with the given RenderType. */ - DrawBuffer flywheel$getDrawBuffer(); - - /** - * Helper function to cast a RenderType to a RenderTypeExtension and get its DrawBuffer. - * @param type The RenderType to get the DrawBuffer from. - * @return The DrawBuffer associated with the given RenderType. - */ - static DrawBuffer getDrawBuffer(RenderType type) { - return ((RenderTypeExtension) type).flywheel$getDrawBuffer(); + static DrawBufferSet getDrawBufferSet(RenderType type) { + return ((RenderTypeExtension) type).flywheel$getDrawBufferSet(); } } diff --git a/src/main/java/com/jozufozu/flywheel/mixin/BufferUploaderMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/BufferUploaderMixin.java deleted file mode 100644 index 4eac80524..000000000 --- a/src/main/java/com/jozufozu/flywheel/mixin/BufferUploaderMixin.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.jozufozu.flywheel.mixin; - -import org.jetbrains.annotations.Nullable; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import com.jozufozu.flywheel.backend.gl.GlStateTracker; -import com.mojang.blaze3d.vertex.BufferUploader; -import com.mojang.blaze3d.vertex.VertexFormat; - -@Mixin(BufferUploader.class) -public class BufferUploaderMixin { - @Shadow - @Nullable - private static VertexFormat lastFormat; - - // Stop BufferUploader from clearing buffer state if nothing is bound - @Inject(method = "reset", at = @At("HEAD")) - private static void flywheel$onReset(CallbackInfo ci) { - // Trust our tracker over BufferUploader's. - if (GlStateTracker.getVertexArray() == 0) { - lastFormat = null; - } - } -} diff --git a/src/main/java/com/jozufozu/flywheel/mixin/LevelRendererMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/LevelRendererMixin.java index e248e1f59..6357f7639 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/LevelRendererMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/LevelRendererMixin.java @@ -12,7 +12,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import com.jozufozu.flywheel.api.RenderStage; import com.jozufozu.flywheel.backend.Backend; -import com.jozufozu.flywheel.backend.gl.GlStateTracker; import com.jozufozu.flywheel.core.RenderContext; import com.jozufozu.flywheel.event.BeginFrameEvent; import com.jozufozu.flywheel.event.ReloadRenderersEvent; @@ -48,9 +47,7 @@ public class LevelRendererMixin { var culler = RenderContext.createCuller(viewProjection, (float) -cameraPos.x, (float) -cameraPos.y, (float) -cameraPos.z); flywheel$renderContext = new RenderContext((LevelRenderer) (Object) this, level, pPoseStack, viewProjection, pProjectionMatrix, renderBuffers, pCamera, culler); - try (var restoreState = GlStateTracker.getRestoreState()) { - MinecraftForge.EVENT_BUS.post(new BeginFrameEvent(flywheel$renderContext)); - } + MinecraftForge.EVENT_BUS.post(new BeginFrameEvent(flywheel$renderContext)); } @Inject(at = @At("TAIL"), method = "renderLevel") @@ -78,9 +75,7 @@ public class LevelRendererMixin { @Unique private void flywheel$dispatch(RenderStage stage) { if (flywheel$renderContext != null) { - try (var restoreState = GlStateTracker.getRestoreState()) { - MinecraftForge.EVENT_BUS.post(new RenderStageEvent(flywheel$renderContext, stage)); - } + MinecraftForge.EVENT_BUS.post(new RenderStageEvent(flywheel$renderContext, stage)); } } diff --git a/src/main/java/com/jozufozu/flywheel/mixin/RenderTypeMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/RenderTypeMixin.java index 4b11dad88..09e380de1 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/RenderTypeMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/RenderTypeMixin.java @@ -4,7 +4,7 @@ import org.jetbrains.annotations.NotNull; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; -import com.jozufozu.flywheel.backend.instancing.batching.DrawBuffer; +import com.jozufozu.flywheel.backend.instancing.batching.DrawBufferSet; import com.jozufozu.flywheel.extension.RenderTypeExtension; import net.minecraft.client.renderer.RenderType; @@ -12,14 +12,14 @@ import net.minecraft.client.renderer.RenderType; @Mixin(RenderType.class) public class RenderTypeMixin implements RenderTypeExtension { @Unique - private DrawBuffer flywheel$drawBuffer; + private DrawBufferSet flywheel$drawBufferSet; @Override @NotNull - public DrawBuffer flywheel$getDrawBuffer() { - if (flywheel$drawBuffer == null) { - flywheel$drawBuffer = new DrawBuffer(((RenderType) (Object) this).format()); + public DrawBufferSet flywheel$getDrawBufferSet() { + if (flywheel$drawBufferSet == null) { + flywheel$drawBufferSet = new DrawBufferSet(((RenderType) (Object) this).format()); } - return flywheel$drawBuffer; + return flywheel$drawBufferSet; } } diff --git a/src/main/java/com/jozufozu/flywheel/mixin/light/NetworkLightUpdateMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/light/NetworkLightUpdateMixin.java index 5352e21b5..4c6ae7a8d 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/light/NetworkLightUpdateMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/light/NetworkLightUpdateMixin.java @@ -18,14 +18,14 @@ public class NetworkLightUpdateMixin { @Inject(at = @At("TAIL"), method = "handleLightUpdatePacket") private void flywheel$onLightPacket(ClientboundLightUpdatePacket packet, CallbackInfo ci) { RenderWork.enqueue(() -> { - ClientLevel world = Minecraft.getInstance().level; + ClientLevel level = Minecraft.getInstance().level; - if (world == null) return; + if (level == null) return; int chunkX = packet.getX(); int chunkZ = packet.getZ(); - LightUpdater.get(world) + LightUpdater.get(level) .onLightPacket(chunkX, chunkZ); }); } diff --git a/src/main/resources/flywheel.mixins.json b/src/main/resources/flywheel.mixins.json index 1d26183e7..e190d6a30 100644 --- a/src/main/resources/flywheel.mixins.json +++ b/src/main/resources/flywheel.mixins.json @@ -8,7 +8,6 @@ "BlockEntityRenderDispatcherAccessor", "BlockEntityTypeMixin", "BufferBuilderMixin", - "BufferUploaderMixin", "ChunkRebuildHooksMixin", "ClientLevelMixin", "ClientMainMixin",