From ae945f6aced1ee9614e171bf3f1d259a9fb5277e Mon Sep 17 00:00:00 2001 From: Jozufozu Date: Sat, 16 Jul 2022 21:38:22 -0400 Subject: [PATCH] Finish porting to 1.19 (mostly) - Terrible, terrible mixins to ChunkRenderDispatcher and its subclasses - Index buffers may break chunk rendering sometimes, needs debugging --- .editorconfig | 11 ++ .../backend/gl/buffer/MappedBuffer.java | 2 +- .../backend/instancing/InstanceManager.java | 11 ++ .../flywheel/backend/model/ElementBuffer.java | 6 +- .../flywheel/backend/model/IndexedModel.java | 4 +- .../flywheel/backend/model/ModelPool.java | 4 +- .../jozufozu/flywheel/core/QuadConverter.java | 177 ++++++------------ .../flywheel/core/hardcoded/ModelPart.java | 8 + .../flywheel/core/model/BlockModel.java | 74 +++++++- .../jozufozu/flywheel/core/model/Model.java | 5 +- .../model/ShadeSeparatedBufferBuilder.java | 11 +- .../flywheel/core/model/WorldModel.java | 37 ---- .../core/model/WorldModelBuilder.java | 4 +- .../core/vertex/AbstractVertexList.java | 9 - .../flywheel/core/vertex/BlockVertex.java | 13 +- .../flywheel/core/vertex/BlockVertexList.java | 15 +- .../flywheel/mixin/BufferUploaderMixin.java | 5 +- .../mixin/ChunkRebuildHooksMixin.java | 33 ---- .../ChunkRebuildHooksMixin.java | 82 ++++++++ .../ChunkRenderDispatcherAccessor.java | 14 ++ .../InstanceAddMixin.java | 2 +- .../InstanceRemoveMixin.java | 2 +- .../instancemanage/RenderChunkAccessor.java | 19 ++ .../instancemanage/RenderChunkMixin.java | 21 +++ .../flywheel/util/RenderChunkExtension.java | 7 + src/main/resources/META-INF/mods.toml | 4 +- src/main/resources/flywheel.mixins.json | 9 +- 27 files changed, 349 insertions(+), 240 deletions(-) delete mode 100644 src/main/java/com/jozufozu/flywheel/core/model/WorldModel.java delete mode 100644 src/main/java/com/jozufozu/flywheel/mixin/ChunkRebuildHooksMixin.java create mode 100644 src/main/java/com/jozufozu/flywheel/mixin/instancemanage/ChunkRebuildHooksMixin.java create mode 100644 src/main/java/com/jozufozu/flywheel/mixin/instancemanage/ChunkRenderDispatcherAccessor.java rename src/main/java/com/jozufozu/flywheel/mixin/{ => instancemanage}/InstanceAddMixin.java (95%) rename src/main/java/com/jozufozu/flywheel/mixin/{ => instancemanage}/InstanceRemoveMixin.java (96%) create mode 100644 src/main/java/com/jozufozu/flywheel/mixin/instancemanage/RenderChunkAccessor.java create mode 100644 src/main/java/com/jozufozu/flywheel/mixin/instancemanage/RenderChunkMixin.java create mode 100644 src/main/java/com/jozufozu/flywheel/util/RenderChunkExtension.java diff --git a/.editorconfig b/.editorconfig index 1eeca6433..f1abc2e0c 100644 --- a/.editorconfig +++ b/.editorconfig @@ -13,6 +13,17 @@ insert_final_newline = true [*.json] indent_style = space indent_size = 2 +max_line_length = 500 +ij_json_keep_blank_lines_in_code = 0 +ij_json_keep_indents_on_empty_lines = false +ij_json_keep_line_breaks = true +ij_json_space_after_colon = true +ij_json_space_after_comma = true +ij_json_space_before_colon = true +ij_json_space_before_comma = false +ij_json_spaces_within_braces = true +ij_json_spaces_within_brackets = false +ij_json_wrap_long_lines = false [*.java] indent_style = tab diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/MappedBuffer.java b/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/MappedBuffer.java index 25155a1d0..c95a398cb 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/MappedBuffer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/MappedBuffer.java @@ -39,7 +39,7 @@ public class MappedBuffer extends VecBuffer implements AutoCloseable { } @Override - public void close() throws Exception { + public void close() { flush(); } } 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 1f8310d1e..7743fb0b8 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceManager.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceManager.java @@ -1,6 +1,7 @@ package com.jozufozu.flywheel.backend.instancing; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -359,4 +360,14 @@ public abstract class InstanceManager implements InstancingEngine.OriginShift LightUpdater.get(value.world).removeListener(value); } } + + public void queueAddAll(Collection objects) { + if (!Backend.isOn() || objects.isEmpty()) { + return; + } + + synchronized (queuedAdditions) { + queuedAdditions.addAll(objects); + } + } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/model/ElementBuffer.java b/src/main/java/com/jozufozu/flywheel/backend/model/ElementBuffer.java index 8227ad019..aba15457b 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/model/ElementBuffer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/model/ElementBuffer.java @@ -2,14 +2,16 @@ package com.jozufozu.flywheel.backend.model; import com.jozufozu.flywheel.backend.gl.GlNumericType; import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer; +import com.mojang.blaze3d.vertex.VertexBuffer; +import com.mojang.blaze3d.vertex.VertexFormat; public class ElementBuffer { private final GlBuffer buffer; public final int elementCount; - public final GlNumericType eboIndexType; + public final VertexFormat.IndexType eboIndexType; - public ElementBuffer(GlBuffer backing, int elementCount, GlNumericType indexType) { + public ElementBuffer(GlBuffer backing, int elementCount, VertexFormat.IndexType indexType) { this.buffer = backing; this.eboIndexType = indexType; this.elementCount = elementCount; diff --git a/src/main/java/com/jozufozu/flywheel/backend/model/IndexedModel.java b/src/main/java/com/jozufozu/flywheel/backend/model/IndexedModel.java index 7a372b0c8..4052e569e 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/model/IndexedModel.java +++ b/src/main/java/com/jozufozu/flywheel/backend/model/IndexedModel.java @@ -60,7 +60,7 @@ public class IndexedModel implements BufferedModel { @Override public void drawCall() { ebo.bind(); - GL20.glDrawElements(primitiveMode.glEnum, ebo.elementCount, ebo.eboIndexType.getGlEnum(), 0); + GL20.glDrawElements(primitiveMode.glEnum, ebo.elementCount, ebo.eboIndexType.asGLType, 0); } /** @@ -72,7 +72,7 @@ public class IndexedModel implements BufferedModel { ebo.bind(); - GL31.glDrawElementsInstanced(primitiveMode.glEnum, ebo.elementCount, ebo.eboIndexType.getGlEnum(), 0, instanceCount); + GL31.glDrawElementsInstanced(primitiveMode.glEnum, ebo.elementCount, ebo.eboIndexType.asGLType, 0, instanceCount); } public boolean isDeleted() { diff --git a/src/main/java/com/jozufozu/flywheel/backend/model/ModelPool.java b/src/main/java/com/jozufozu/flywheel/backend/model/ModelPool.java index 5c1d426c7..d9ce70838 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/model/ModelPool.java +++ b/src/main/java/com/jozufozu/flywheel/backend/model/ModelPool.java @@ -189,7 +189,7 @@ public class ModelPool implements ModelAllocator { @Override public void drawCall() { - GL32.glDrawElementsBaseVertex(GlPrimitive.TRIANGLES.glEnum, ebo.elementCount, ebo.eboIndexType.getGlEnum(), 0, first); + GL32.glDrawElementsBaseVertex(GlPrimitive.TRIANGLES.glEnum, ebo.elementCount, ebo.eboIndexType.asGLType, 0, first); } @Override @@ -200,7 +200,7 @@ public class ModelPool implements ModelAllocator { //Backend.log.info(StringUtil.args("drawElementsInstancedBaseVertex", GlPrimitive.TRIANGLES, ebo.elementCount, ebo.eboIndexType, 0, instanceCount, first)); - GL32.glDrawElementsInstancedBaseVertex(GlPrimitive.TRIANGLES.glEnum, ebo.elementCount, ebo.eboIndexType.getGlEnum(), 0, instanceCount, first); + GL32.glDrawElementsInstancedBaseVertex(GlPrimitive.TRIANGLES.glEnum, ebo.elementCount, ebo.eboIndexType.asGLType, 0, instanceCount, first); } @Override diff --git a/src/main/java/com/jozufozu/flywheel/core/QuadConverter.java b/src/main/java/com/jozufozu/flywheel/core/QuadConverter.java index d1871224b..6e461b019 100644 --- a/src/main/java/com/jozufozu/flywheel/core/QuadConverter.java +++ b/src/main/java/com/jozufozu/flywheel/core/QuadConverter.java @@ -3,41 +3,30 @@ package com.jozufozu.flywheel.core; import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.ByteOrder; -import java.util.EnumMap; -import java.util.Map; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -import org.lwjgl.system.MemoryStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.lwjgl.system.MemoryUtil; import com.jozufozu.flywheel.backend.gl.GlNumericType; -import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer; import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType; +import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer; import com.jozufozu.flywheel.backend.gl.buffer.MappedGlBuffer; import com.jozufozu.flywheel.backend.model.ElementBuffer; import com.jozufozu.flywheel.event.ReloadRenderersEvent; - -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.eventbus.api.EventPriority; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; +import com.mojang.blaze3d.vertex.VertexFormat; /** * A class to manage EBOs that index quads as triangles. */ -@Mod.EventBusSubscriber(Dist.CLIENT) public class QuadConverter { - public static final int STARTING_CAPACITY = 42; // 255 / 6 = 42 - private static QuadConverter INSTANCE; - @Nonnull + @NotNull public static QuadConverter getInstance() { if (INSTANCE == null) { - INSTANCE = new QuadConverter(STARTING_CAPACITY); + INSTANCE = new QuadConverter(); } return INSTANCE; @@ -48,130 +37,80 @@ public class QuadConverter { return INSTANCE; } - Map ebos; - int[] capacities; + private final MappedGlBuffer ebo; + private int quadCapacity; - public QuadConverter(int initialCapacity) { - this.ebos = new EnumMap<>(GlNumericType.class); - initCapacities(); - - fillBuffer(initialCapacity); + public QuadConverter() { + this.ebo = new MappedGlBuffer(GlBufferType.ELEMENT_ARRAY_BUFFER); + this.quadCapacity = 0; } public ElementBuffer quads2Tris(int quads) { int indexCount = quads * 6; - GlNumericType type = getSmallestIndexType(indexCount); - if (quads > getCapacity(type)) { - fillBuffer(quads, indexCount, type); + if (quads > quadCapacity) { + ebo.bind(); + ebo.ensureCapacity((long) indexCount * GlNumericType.UINT.getByteWidth()); + + try (MappedBuffer map = ebo.getBuffer()) { + ByteBuffer indices = map.unwrap(); + + fillBuffer(indices, quads); + } + ebo.unbind(); + + this.quadCapacity = quads; } - return new ElementBuffer(getBuffer(type), indexCount, type); - } - - private void initCapacities() { - this.capacities = new int[GlNumericType.values().length]; - } - - private int getCapacity(GlNumericType type) { - return capacities[type.ordinal()]; - } - - private void updateCapacity(GlNumericType type, int capacity) { - if (getCapacity(type) < capacity) { - capacities[type.ordinal()] = capacity; - } + return new ElementBuffer(ebo, indexCount, VertexFormat.IndexType.INT); } public void delete() { - ebos.values() - .forEach(GlBuffer::delete); - ebos.clear(); - initCapacities(); + ebo.delete(); + this.quadCapacity = 0; } - private void fillBuffer(int quads) { - int indexCount = quads * 6; + private void fillBuffer(ByteBuffer indices, int quads) { + long addr = MemoryUtil.memAddress(indices); + int numVertices = 4 * quads; + int baseVertex = 0; + while (baseVertex < numVertices) { + // writeQuadIndices(indices, baseVertex); + writeQuadIndicesUnsafe(addr, baseVertex); - fillBuffer(quads, indexCount, getSmallestIndexType(indexCount)); - } - - private void fillBuffer(int quads, int indexCount, GlNumericType type) { - MemoryStack stack = MemoryStack.stackPush(); - int bytes = indexCount * type.getByteWidth(); - - ByteBuffer indices; - if (bytes > stack.getSize()) { - indices = MemoryUtil.memAlloc(bytes); // not enough space on the preallocated stack - } else { - stack.push(); - indices = stack.malloc(bytes); + baseVertex += 4; + addr += 6 * 4; } - - indices.order(ByteOrder.nativeOrder()); - - fillBuffer(indices, type, quads); - - GlBuffer buffer = getBuffer(type); - - buffer.bind(); - buffer.upload(indices); - buffer.unbind(); - - if (bytes > stack.getSize()) { - MemoryUtil.memFree(indices); - } else { - stack.pop(); - } - - updateCapacity(type, quads); + // ((Buffer) indices).flip(); } - private void fillBuffer(ByteBuffer indices, GlNumericType type, int quads) { - for (int i = 0, max = 4 * quads; i < max; i += 4) { - // triangle a - type.castAndBuffer(indices, i); - type.castAndBuffer(indices, i + 1); - type.castAndBuffer(indices, i + 2); - // triangle b - type.castAndBuffer(indices, i); - type.castAndBuffer(indices, i + 2); - type.castAndBuffer(indices, i + 3); - } - ((Buffer) indices).flip(); + private void writeQuadIndices(ByteBuffer indices, int baseVertex) { + // triangle a + indices.putInt(baseVertex); + indices.putInt(baseVertex + 1); + indices.putInt(baseVertex + 2); + // triangle b + indices.putInt(baseVertex); + indices.putInt(baseVertex + 2); + indices.putInt(baseVertex + 3); } - private GlBuffer getBuffer(GlNumericType type) { - return ebos.computeIfAbsent(type, $ -> new MappedGlBuffer(GlBufferType.ELEMENT_ARRAY_BUFFER)); - } - - /** - * Given the needed number of indices, what is the smallest bit width type that can index everything?
- * - *
-	 * | indexCount   | type  |
-	 * |--------------|-------|
-	 * | [0, 255)     | byte  |
-	 * | [256, 65536)	| short	|
-	 * | [65537, )	| int	|
-	 * 
- */ - private static GlNumericType getSmallestIndexType(int indexCount) { -// indexCount = indexCount >>> 8; -// if (indexCount == 0) { -// return GlNumericType.UBYTE; -// } -// indexCount = indexCount >>> 8; -// if (indexCount == 0) { -// return GlNumericType.USHORT; -// } - - return GlNumericType.UINT; + private void writeQuadIndicesUnsafe(long addr, int baseVertex) { + // triangle a + MemoryUtil.memPutInt(addr, baseVertex); + MemoryUtil.memPutInt(addr + 4, baseVertex + 1); + MemoryUtil.memPutInt(addr + 8, baseVertex + 2); + // triangle b + MemoryUtil.memPutInt(addr + 12, baseVertex); + MemoryUtil.memPutInt(addr + 16, baseVertex + 2); + MemoryUtil.memPutInt(addr + 20, baseVertex + 3); } // make sure this gets reset first so it has a chance to repopulate - @SubscribeEvent(priority = EventPriority.HIGHEST) public static void onRendererReload(ReloadRenderersEvent event) { - if (INSTANCE != null) INSTANCE.delete(); + if (INSTANCE != null) { + INSTANCE.delete(); + INSTANCE = null; + } } } 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 67bdeb798..d67ca22d3 100644 --- a/src/main/java/com/jozufozu/flywheel/core/hardcoded/ModelPart.java +++ b/src/main/java/com/jozufozu/flywheel/core/hardcoded/ModelPart.java @@ -3,7 +3,9 @@ package com.jozufozu.flywheel.core.hardcoded; import java.util.List; import com.jozufozu.flywheel.api.vertex.VertexList; +import com.jozufozu.flywheel.backend.model.ElementBuffer; import com.jozufozu.flywheel.core.Formats; +import com.jozufozu.flywheel.core.QuadConverter; import com.jozufozu.flywheel.core.model.Model; import com.jozufozu.flywheel.core.vertex.PosTexNormalWriterUnsafe; import com.mojang.blaze3d.platform.MemoryTracker; @@ -51,4 +53,10 @@ public class ModelPart implements Model { public VertexList getReader() { return reader; } + + @Override + public ElementBuffer createEBO() { + return QuadConverter.getInstance() + .quads2Tris(vertices / 4); + } } diff --git a/src/main/java/com/jozufozu/flywheel/core/model/BlockModel.java b/src/main/java/com/jozufozu/flywheel/core/model/BlockModel.java index 8c527bea6..45b2e6f1a 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/BlockModel.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/BlockModel.java @@ -1,8 +1,25 @@ package com.jozufozu.flywheel.core.model; +import java.lang.management.MemoryUsage; +import java.nio.ByteBuffer; +import java.util.function.Supplier; + +import org.lwjgl.system.MemoryUtil; + import com.jozufozu.flywheel.api.vertex.VertexList; +import com.jozufozu.flywheel.api.vertex.VertexType; +import com.jozufozu.flywheel.backend.gl.GlNumericType; +import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer; +import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType; +import com.jozufozu.flywheel.backend.gl.buffer.GlBufferUsage; +import com.jozufozu.flywheel.backend.gl.buffer.MappedGlBuffer; +import com.jozufozu.flywheel.backend.model.ElementBuffer; import com.jozufozu.flywheel.core.Formats; +import com.jozufozu.flywheel.core.QuadConverter; +import com.mojang.blaze3d.platform.MemoryTracker; +import com.mojang.blaze3d.vertex.BufferBuilder; import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexBuffer; import net.minecraft.client.Minecraft; import net.minecraft.client.resources.model.BakedModel; @@ -12,12 +29,12 @@ import net.minecraft.world.level.block.state.BlockState; * A model of a single block. */ public class BlockModel implements Model { - private static final PoseStack IDENTITY = new PoseStack(); - private final VertexList reader; private final String name; + private final Supplier eboSupplier; + public BlockModel(BlockState state) { this(Minecraft.getInstance() .getBlockRenderer() @@ -25,12 +42,49 @@ public class BlockModel implements Model { } public BlockModel(BakedModel model, BlockState referenceState) { - this(model, referenceState, IDENTITY); + this(new BakedModelBuilder(model).withReferenceState(referenceState), referenceState.toString()); } public BlockModel(BakedModel model, BlockState referenceState, PoseStack ms) { - reader = Formats.BLOCK.createReader(ModelUtil.getBufferBuilder(model, referenceState, ms)); - name = referenceState.toString(); + this(new BakedModelBuilder(model).withReferenceState(referenceState) + .withPoseStack(ms), referenceState.toString()); + } + + public BlockModel(Bufferable bufferable, String name) { + this(bufferable.build(), name); + } + + public BlockModel(ShadeSeparatedBufferBuilder buffer, String name) { + this.name = name; + + BufferBuilder.RenderedBuffer renderedBuffer = buffer.endOrDiscardIfEmpty(); + + if (renderedBuffer == null) { + reader = null; + eboSupplier = () -> null; + return; + } + + BufferBuilder.DrawState drawState = renderedBuffer.drawState(); + + reader = Formats.BLOCK.createReader(renderedBuffer, buffer.getUnshadedStartVertex()); + + if (drawState.sequentialIndex()) { + ByteBuffer src = renderedBuffer.indexBuffer(); + ByteBuffer indexBuffer = MemoryTracker.create(src.capacity()); + MemoryUtil.memCopy(src, indexBuffer); + eboSupplier = () -> { + + MappedGlBuffer vbo = new MappedGlBuffer(GlBufferType.ELEMENT_ARRAY_BUFFER, GlBufferUsage.STATIC_DRAW); + + vbo.upload(indexBuffer); + + return new ElementBuffer(vbo, drawState.indexCount(), drawState.indexType()); + }; + } else { + eboSupplier = () -> QuadConverter.getInstance() + .quads2Tris(vertexCount() / 4); + } } @Override @@ -47,4 +101,14 @@ public class BlockModel implements Model { public VertexList getReader() { return reader; } + + @Override + public ElementBuffer createEBO() { + return eboSupplier.get(); + } + + @Override + public VertexType getType() { + return Formats.BLOCK; + } } diff --git a/src/main/java/com/jozufozu/flywheel/core/model/Model.java b/src/main/java/com/jozufozu/flywheel/core/model/Model.java index eacfd3394..c93e1df84 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/Model.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/Model.java @@ -56,10 +56,7 @@ public interface Model { *

* @return an element buffer object indexing this model's vertices. */ - default ElementBuffer createEBO() { - return QuadConverter.getInstance() - .quads2Tris(vertexCount() / 4); - } + ElementBuffer createEBO(); /** * The size in bytes that this model's data takes up. diff --git a/src/main/java/com/jozufozu/flywheel/core/model/ShadeSeparatedBufferBuilder.java b/src/main/java/com/jozufozu/flywheel/core/model/ShadeSeparatedBufferBuilder.java index 38043702b..71a05d70f 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/ShadeSeparatedBufferBuilder.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/ShadeSeparatedBufferBuilder.java @@ -14,9 +14,16 @@ public class ShadeSeparatedBufferBuilder extends BufferBuilder { } public void appendUnshadedVertices(BufferBuilder unshadedBuilder) { - Pair data = unshadedBuilder.popNextBuffer(); + RenderedBuffer renderedBuffer = unshadedBuilder.endOrDiscardIfEmpty(); + + if (renderedBuffer == null) { + return; + } + + // FIXME: Unshaded indices + ByteBuffer buffer = renderedBuffer.vertexBuffer(); unshadedStartVertex = ((BufferBuilderExtension) this).flywheel$getVertices(); - ((BufferBuilderExtension) this).flywheel$appendBufferUnsafe(data.getSecond()); + ((BufferBuilderExtension) this).flywheel$appendBufferUnsafe(buffer); } public int getUnshadedStartVertex() { diff --git a/src/main/java/com/jozufozu/flywheel/core/model/WorldModel.java b/src/main/java/com/jozufozu/flywheel/core/model/WorldModel.java deleted file mode 100644 index c144f43c6..000000000 --- a/src/main/java/com/jozufozu/flywheel/core/model/WorldModel.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.jozufozu.flywheel.core.model; - -import com.jozufozu.flywheel.api.vertex.VertexList; -import com.jozufozu.flywheel.api.vertex.VertexType; -import com.jozufozu.flywheel.core.Formats; -import com.mojang.blaze3d.vertex.BufferBuilder; - -public class WorldModel implements Model { - - private final VertexList reader; - private final String name; - - public WorldModel(BufferBuilder bufferBuilder, String name) { - this.reader = Formats.BLOCK.createReader(bufferBuilder); - this.name = name; - } - - @Override - public String name() { - return name; - } - - @Override - public VertexType getType() { - return Formats.BLOCK; - } - - @Override - public int vertexCount() { - return reader.getVertexCount(); - } - - @Override - public VertexList getReader() { - return reader; - } -} diff --git a/src/main/java/com/jozufozu/flywheel/core/model/WorldModelBuilder.java b/src/main/java/com/jozufozu/flywheel/core/model/WorldModelBuilder.java index 03a145dfd..614bb0e9d 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/WorldModelBuilder.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/WorldModelBuilder.java @@ -77,7 +77,7 @@ public final class WorldModelBuilder implements Bufferable { return this; } - public WorldModel intoMesh(String name) { - return new WorldModel(ModelUtil.getBufferBuilder(this), name); + public BlockModel intoMesh(String name) { + return new BlockModel(this, name); } } 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 a68e0c943..24ec1eeab 100644 --- a/src/main/java/com/jozufozu/flywheel/core/vertex/AbstractVertexList.java +++ b/src/main/java/com/jozufozu/flywheel/core/vertex/AbstractVertexList.java @@ -22,15 +22,6 @@ public abstract class AbstractVertexList implements VertexList, AutoCloseable { init(copyFrom); } - public AbstractVertexList(BufferBuilder builder) { - var pair = builder.popNextBuffer(); - ByteBuffer copyFrom = pair.getSecond(); - this.contents = MemoryTracker.create(copyFrom.capacity()); - this.vertexCount = pair.getFirst().vertexCount(); - this.base = MemoryUtil.memAddress(this.contents); - init(copyFrom); - } - private void init(ByteBuffer copyFrom) { this.contents.order(copyFrom.order()); this.contents.put(copyFrom); diff --git a/src/main/java/com/jozufozu/flywheel/core/vertex/BlockVertex.java b/src/main/java/com/jozufozu/flywheel/core/vertex/BlockVertex.java index d74dde894..1ac22ae94 100644 --- a/src/main/java/com/jozufozu/flywheel/core/vertex/BlockVertex.java +++ b/src/main/java/com/jozufozu/flywheel/core/vertex/BlockVertex.java @@ -62,19 +62,20 @@ Vertex FLWCreateVertex() { return new BlockVertexListUnsafe.Shaded(buffer, vertexCount, unshadedStartVertex); } - public VertexList createReader(BufferBuilder bufferBuilder) { + public VertexList createReader(BufferBuilder.RenderedBuffer renderedBuffer, int unshadedStartVertex) { + // TODO: try to avoid virtual model rendering - Pair pair = bufferBuilder.popNextBuffer(); - BufferBuilder.DrawState drawState = pair.getFirst(); + BufferBuilder.DrawState drawState = renderedBuffer.drawState(); if (drawState.format() != DefaultVertexFormat.BLOCK) { throw new RuntimeException("Cannot use BufferBuilder with " + drawState.format()); } + ByteBuffer vertexBuffer = renderedBuffer.vertexBuffer(); - if (bufferBuilder instanceof ShadeSeparatedBufferBuilder separated) { - return createReader(pair.getSecond(), drawState.vertexCount(), separated.getUnshadedStartVertex()); + if (unshadedStartVertex > 0) { + return createReader(vertexBuffer, drawState.vertexCount(), unshadedStartVertex); } else { - return createReader(pair.getSecond(), drawState.vertexCount()); + return createReader(vertexBuffer, drawState.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 f84385f78..654f94865 100644 --- a/src/main/java/com/jozufozu/flywheel/core/vertex/BlockVertexList.java +++ b/src/main/java/com/jozufozu/flywheel/core/vertex/BlockVertexList.java @@ -1,5 +1,7 @@ package com.jozufozu.flywheel.core.vertex; +import java.nio.ByteBuffer; + import com.jozufozu.flywheel.api.vertex.ShadedVertexList; import com.jozufozu.flywheel.core.model.ShadeSeparatedBufferBuilder; import com.jozufozu.flywheel.util.RenderMath; @@ -9,10 +11,9 @@ public class BlockVertexList extends AbstractVertexList { private final int stride; - public BlockVertexList(BufferBuilder builder) { - super(builder); - this.stride = builder.getVertexFormat() - .getVertexSize(); + public BlockVertexList(ByteBuffer copyFrom, int vertexCount, int stride) { + super(copyFrom, vertexCount); + this.stride = stride; } @Override @@ -93,9 +94,9 @@ public class BlockVertexList extends AbstractVertexList { private final int unshadedStartVertex; - public Shaded(ShadeSeparatedBufferBuilder builder) { - super(builder); - unshadedStartVertex = builder.getUnshadedStartVertex(); + public Shaded(ByteBuffer copyFrom, int vertexCount, int stride, int unshadedStartVertex) { + super(copyFrom, vertexCount, stride); + this.unshadedStartVertex = unshadedStartVertex; } @Override diff --git a/src/main/java/com/jozufozu/flywheel/mixin/BufferUploaderMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/BufferUploaderMixin.java index 7cd63581c..92058feb9 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/BufferUploaderMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/BufferUploaderMixin.java @@ -10,6 +10,7 @@ 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.VertexBuffer; import com.mojang.blaze3d.vertex.VertexFormat; @Mixin(BufferUploader.class) @@ -17,13 +18,13 @@ public class BufferUploaderMixin { @Shadow @Nullable - private static VertexFormat lastFormat; + private static VertexBuffer lastImmediateBuffer; @Inject(method = "reset", at = @At("HEAD")) private static void stopBufferUploaderFromClearingBufferStateIfNothingIsBound(CallbackInfo ci) { // Trust our tracker over BufferUploader's. if (GlStateTracker.getVertexArray() == 0) { - lastFormat = null; + lastImmediateBuffer = null; } } } diff --git a/src/main/java/com/jozufozu/flywheel/mixin/ChunkRebuildHooksMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/ChunkRebuildHooksMixin.java deleted file mode 100644 index a4accbe24..000000000 --- a/src/main/java/com/jozufozu/flywheel/mixin/ChunkRebuildHooksMixin.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.jozufozu.flywheel.mixin; - -import java.util.Set; - -import org.spongepowered.asm.mixin.Mixin; -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.Backend; -import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; -import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry; - -import net.minecraft.client.renderer.chunk.ChunkRenderDispatcher; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -@OnlyIn(Dist.CLIENT) -@Mixin(targets = "net.minecraft.client.renderer.chunk.ChunkRenderDispatcher$RenderChunk$RebuildTask") -public class ChunkRebuildHooksMixin { - - @Inject(method = "handleBlockEntity", at = @At("HEAD"), cancellable = true) - private void addAndFilterBEs(ChunkRenderDispatcher.CompiledChunk compiledChunk, Set set, E be, CallbackInfo ci) { - if (Backend.canUseInstancing(be.getLevel())) { - if (InstancedRenderRegistry.canInstance(be.getType())) - InstancedRenderDispatcher.getBlockEntities(be.getLevel()).queueAdd(be); - - if (InstancedRenderRegistry.shouldSkipRender(be)) - ci.cancel(); - } - } -} diff --git a/src/main/java/com/jozufozu/flywheel/mixin/instancemanage/ChunkRebuildHooksMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/instancemanage/ChunkRebuildHooksMixin.java new file mode 100644 index 000000000..599c7fc9a --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/mixin/instancemanage/ChunkRebuildHooksMixin.java @@ -0,0 +1,82 @@ +package com.jozufozu.flywheel.mixin.instancemanage; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; +import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry; +import com.jozufozu.flywheel.util.RenderChunkExtension; + +import net.minecraft.client.renderer.chunk.ChunkRenderDispatcher; +import net.minecraft.client.renderer.chunk.RenderChunkRegion; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +@OnlyIn(Dist.CLIENT) +@Mixin(targets = "net.minecraft.client.renderer.chunk.ChunkRenderDispatcher$RenderChunk$RebuildTask") +public abstract class ChunkRebuildHooksMixin { + @Unique + private Level flywheel$level; + + @Inject(method = "(Lnet/minecraft/client/renderer/chunk/ChunkRenderDispatcher$RenderChunk;Lnet/minecraft/world/level/ChunkPos;DLnet/minecraft/client/renderer/chunk/RenderChunkRegion;Z)V", at = @At("RETURN")) + private void setLevel(ChunkRenderDispatcher.RenderChunk this$1, ChunkPos pos, double p_194427_, RenderChunkRegion region, boolean p_194429_, CallbackInfo ci) { + flywheel$level = ((RenderChunkExtension) this$1).flywheel$getLevel(); + } + + @Redirect(method = "doTask", at = @At(value = "INVOKE", target = "Ljava/util/List;addAll(Ljava/util/Collection;)Z")) + private boolean addAndFilterBEs(List self, Collection es) { + if (!Backend.canUseInstancing(flywheel$level)) { + return self.addAll(es); + } + + boolean added = false; + var instanced = new ArrayList(); + for (E be : es) { + if (InstancedRenderRegistry.canInstance(be.getType())) { + instanced.add(be); + } + + if (!InstancedRenderRegistry.shouldSkipRender(be)) { + self.add(be); + added = true; + } + } + InstancedRenderDispatcher.getBlockEntities(flywheel$level).queueAddAll(instanced); + return added; + } + + @Redirect(method = "doTask", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/chunk/ChunkRenderDispatcher$RenderChunk;updateGlobalBlockEntities(Ljava/util/Collection;)V")) + private void addAndFilterBEs(ChunkRenderDispatcher.RenderChunk self, Collection bes) { + if (!Backend.canUseInstancing(flywheel$level)) { + ((RenderChunkAccessor) self).flywheel$updateGlobalBlockEntities(bes); + return; + } + + var global = new ArrayList(); + var instanced = new ArrayList(); + for (BlockEntity be : bes) { + if (InstancedRenderRegistry.canInstance(be.getType())) { + instanced.add(be); + } + + if (!InstancedRenderRegistry.shouldSkipRender(be)) { + global.add(be); + } + } + + InstancedRenderDispatcher.getBlockEntities(flywheel$level).queueAddAll(instanced); + ((RenderChunkAccessor) self).flywheel$updateGlobalBlockEntities(global); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/mixin/instancemanage/ChunkRenderDispatcherAccessor.java b/src/main/java/com/jozufozu/flywheel/mixin/instancemanage/ChunkRenderDispatcherAccessor.java new file mode 100644 index 000000000..7e8e0de6d --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/mixin/instancemanage/ChunkRenderDispatcherAccessor.java @@ -0,0 +1,14 @@ +package com.jozufozu.flywheel.mixin.instancemanage; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.renderer.chunk.ChunkRenderDispatcher; + +@Mixin(ChunkRenderDispatcher.class) +public interface ChunkRenderDispatcherAccessor { + + @Accessor + ClientLevel getLevel(); +} diff --git a/src/main/java/com/jozufozu/flywheel/mixin/InstanceAddMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/instancemanage/InstanceAddMixin.java similarity index 95% rename from src/main/java/com/jozufozu/flywheel/mixin/InstanceAddMixin.java rename to src/main/java/com/jozufozu/flywheel/mixin/instancemanage/InstanceAddMixin.java index b28fbfa84..7568c28e9 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/InstanceAddMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/instancemanage/InstanceAddMixin.java @@ -1,4 +1,4 @@ -package com.jozufozu.flywheel.mixin; +package com.jozufozu.flywheel.mixin.instancemanage; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/main/java/com/jozufozu/flywheel/mixin/InstanceRemoveMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/instancemanage/InstanceRemoveMixin.java similarity index 96% rename from src/main/java/com/jozufozu/flywheel/mixin/InstanceRemoveMixin.java rename to src/main/java/com/jozufozu/flywheel/mixin/instancemanage/InstanceRemoveMixin.java index 0ee0fd088..1d115cfda 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/InstanceRemoveMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/instancemanage/InstanceRemoveMixin.java @@ -1,4 +1,4 @@ -package com.jozufozu.flywheel.mixin; +package com.jozufozu.flywheel.mixin.instancemanage; import javax.annotation.Nullable; diff --git a/src/main/java/com/jozufozu/flywheel/mixin/instancemanage/RenderChunkAccessor.java b/src/main/java/com/jozufozu/flywheel/mixin/instancemanage/RenderChunkAccessor.java new file mode 100644 index 000000000..9bd5a2d3a --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/mixin/instancemanage/RenderChunkAccessor.java @@ -0,0 +1,19 @@ +package com.jozufozu.flywheel.mixin.instancemanage; + +import java.util.Collection; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +import net.minecraft.client.renderer.chunk.ChunkRenderDispatcher; +import net.minecraft.world.level.block.entity.BlockEntity; + +/** + * For use in {@link ChunkRebuildHooksMixin#addAndFilterBEs(ChunkRenderDispatcher.RenderChunk, Collection)} + */ +@Mixin(ChunkRenderDispatcher.RenderChunk.class) +public interface RenderChunkAccessor { + + @Invoker("updateGlobalBlockEntities") + void flywheel$updateGlobalBlockEntities(Collection blockEntities); +} diff --git a/src/main/java/com/jozufozu/flywheel/mixin/instancemanage/RenderChunkMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/instancemanage/RenderChunkMixin.java new file mode 100644 index 000000000..987d7e8e7 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/mixin/instancemanage/RenderChunkMixin.java @@ -0,0 +1,21 @@ +package com.jozufozu.flywheel.mixin.instancemanage; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.renderer.chunk.ChunkRenderDispatcher; + +@Mixin(ChunkRenderDispatcher.RenderChunk.class) +public class RenderChunkMixin implements com.jozufozu.flywheel.util.RenderChunkExtension { + + @Shadow + @Final + private ChunkRenderDispatcher this$0; + + @Override + public ClientLevel flywheel$getLevel() { + return ((ChunkRenderDispatcherAccessor) this$0).getLevel(); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/util/RenderChunkExtension.java b/src/main/java/com/jozufozu/flywheel/util/RenderChunkExtension.java new file mode 100644 index 000000000..acaa7faff --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/util/RenderChunkExtension.java @@ -0,0 +1,7 @@ +package com.jozufozu.flywheel.util; + +import net.minecraft.client.multiplayer.ClientLevel; + +public interface RenderChunkExtension { + ClientLevel flywheel$getLevel(); +} diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml index 2f6649f40..4c6b69b3c 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/mods.toml @@ -17,13 +17,13 @@ A modern engine for modded minecraft.''' [[dependencies.flywheel]] modId = "forge" mandatory = true -versionRange = "[40.0.0,)" +versionRange = "[41.0.0,)" ordering = "NONE" side = "CLIENT" [[dependencies.flywheel]] modId = "minecraft" mandatory = true -versionRange = "[1.18.2,1.19)" +versionRange = "[1.19,1.20)" ordering = "NONE" side = "CLIENT" diff --git a/src/main/resources/flywheel.mixins.json b/src/main/resources/flywheel.mixins.json index cccc7ef58..284039b65 100644 --- a/src/main/resources/flywheel.mixins.json +++ b/src/main/resources/flywheel.mixins.json @@ -10,17 +10,20 @@ "BufferBuilderMixin", "BufferUploaderMixin", "CameraMixin", + "instancemanage.ChunkRebuildHooksMixin", + "instancemanage.ChunkRenderDispatcherAccessor", "ClientLevelMixin", - "ChunkRebuildHooksMixin", "EntityTypeMixin", "FixFabulousDepthMixin", "FrustumMixin", "GlStateManagerMixin", - "InstanceAddMixin", - "InstanceRemoveMixin", + "instancemanage.InstanceAddMixin", + "instancemanage.InstanceRemoveMixin", "LevelRendererAccessor", "LevelRendererMixin", "PausedPartialTickAccessor", + "instancemanage.RenderChunkAccessor", + "instancemanage.RenderChunkMixin", "RenderTexturesMixin", "RenderTypeMixin", "atlas.AtlasDataMixin",