From e79f6bcbf60ef4030ffbc50c2e48a02d1ca22e8c Mon Sep 17 00:00:00 2001 From: PepperCode1 <44146161+PepperCode1@users.noreply.github.com> Date: Mon, 3 Jul 2023 13:19:37 -0700 Subject: [PATCH] Fix poor design choices resulting in memory leaks - Add ShadeSeparatedBufferedData which is returned by buffering utilities and can be released - Remove ShadeSeparatedBufferBuilder and add ModelUtil#endAndCombine - Add VertexList#delete - Replace all usage of MemoryTracker with MemoryUtil - Add FlwUtil#copyBuffer - Turn most BlockModel constructors into static methods - Add BakedModelBuilder#toModel --- .../com/jozufozu/flywheel/api/Material.java | 8 +- .../flywheel/api/vertex/VertexList.java | 3 + .../backend/instancing/DrawBuffer.java | 6 +- .../flywheel/core/hardcoded/ModelPart.java | 11 +-- .../core/model/BakedModelBuilder.java | 10 ++- .../flywheel/core/model/BlockModel.java | 75 ++++++++++++------- .../flywheel/core/model/Bufferable.java | 8 +- .../flywheel/core/model/ModelUtil.java | 47 ++++++++---- .../model/ShadeSeparatedBufferBuilder.java | 25 ------- .../model/ShadeSeparatedBufferedData.java | 51 +++++++++++++ .../core/model/WorldModelBuilder.java | 6 +- .../core/vertex/AbstractVertexList.java | 24 ++---- .../flywheel/core/vertex/BlockVertex.java | 29 +------ .../com/jozufozu/flywheel/util/FlwUtil.java | 16 ++++ 14 files changed, 188 insertions(+), 131 deletions(-) delete mode 100644 src/main/java/com/jozufozu/flywheel/core/model/ShadeSeparatedBufferBuilder.java create mode 100644 src/main/java/com/jozufozu/flywheel/core/model/ShadeSeparatedBufferedData.java diff --git a/src/main/java/com/jozufozu/flywheel/api/Material.java b/src/main/java/com/jozufozu/flywheel/api/Material.java index 69956a8e0..d43b0c86f 100644 --- a/src/main/java/com/jozufozu/flywheel/api/Material.java +++ b/src/main/java/com/jozufozu/flywheel/api/Material.java @@ -25,11 +25,11 @@ public interface Material { Instancer model(Object key, Supplier modelSupplier); default Instancer getModel(PartialModel partial, BlockState referenceState) { - return model(partial, () -> new BlockModel(partial.get(), referenceState)); + return model(partial, () -> BlockModel.of(partial.get(), referenceState)); } default Instancer getModel(PartialModel partial) { - return model(partial, () -> new BlockModel(partial.get(), Blocks.AIR.defaultBlockState())); + return model(partial, () -> BlockModel.of(partial.get(), Blocks.AIR.defaultBlockState())); } default Instancer getModel(PartialModel partial, BlockState referenceState, Direction dir) { @@ -37,10 +37,10 @@ public interface Material { } default Instancer getModel(PartialModel partial, BlockState referenceState, Direction dir, Supplier modelTransform) { - return model(Pair.of(dir, partial), () -> new BlockModel(partial.get(), referenceState, modelTransform.get())); + return model(Pair.of(dir, partial), () -> BlockModel.of(partial.get(), referenceState, modelTransform.get())); } default Instancer getModel(BlockState toRender) { - return model(toRender, () -> new BlockModel(toRender)); + return model(toRender, () -> BlockModel.of(toRender)); } } 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 939f42731..62e9904d5 100644 --- a/src/main/java/com/jozufozu/flywheel/api/vertex/VertexList.java +++ b/src/main/java/com/jozufozu/flywheel/api/vertex/VertexList.java @@ -41,4 +41,7 @@ public interface VertexList { default boolean isEmpty() { return getVertexCount() == 0; } + + default void delete() { + } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/DrawBuffer.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/DrawBuffer.java index f9c6ab051..841e4de25 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/DrawBuffer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/DrawBuffer.java @@ -3,10 +3,10 @@ package com.jozufozu.flywheel.backend.instancing; import java.nio.ByteBuffer; import org.jetbrains.annotations.ApiStatus; +import org.lwjgl.system.MemoryUtil; import com.jozufozu.flywheel.backend.model.BufferBuilderExtension; import com.jozufozu.flywheel.backend.model.DirectVertexConsumer; -import com.mojang.blaze3d.platform.MemoryTracker; import com.mojang.blaze3d.vertex.VertexFormat; import net.minecraft.client.renderer.RenderType; @@ -48,10 +48,10 @@ public class DrawBuffer { int byteSize = format.getVertexSize() * (vertexCount + 1); if (backingBuffer == null) { - backingBuffer = MemoryTracker.create(byteSize); + backingBuffer = MemoryUtil.memAlloc(byteSize); } if (byteSize > backingBuffer.capacity()) { - backingBuffer = MemoryTracker.resize(backingBuffer, byteSize); + backingBuffer = MemoryUtil.memRealloc(backingBuffer, byteSize); } return new DirectVertexConsumer(backingBuffer, format, vertexCount); 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 b58f4ec7b..1adf8526a 100644 --- a/src/main/java/com/jozufozu/flywheel/core/hardcoded/ModelPart.java +++ b/src/main/java/com/jozufozu/flywheel/core/hardcoded/ModelPart.java @@ -10,7 +10,6 @@ import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.core.Formats; import com.jozufozu.flywheel.core.model.Model; import com.jozufozu.flywheel.core.vertex.PosTexNormalWriterUnsafe; -import com.mojang.blaze3d.platform.MemoryTracker; public class ModelPart implements Model { @@ -29,7 +28,7 @@ public class ModelPart implements Model { this.vertices = vertices; } - ByteBuffer buffer = MemoryTracker.create(size()); + ByteBuffer buffer = MemoryUtil.memAlloc(size()); PosTexNormalWriterUnsafe writer = Formats.POS_TEX_NORMAL.createWriter(buffer); for (PartBuilder.CuboidBuilder cuboid : cuboids) { cuboid.buffer(writer); @@ -65,12 +64,6 @@ public class ModelPart implements Model { @Override public void delete() { - if (reader instanceof AutoCloseable closeable) { - try { - closeable.close(); - } catch (Exception e) { - // - } - } + reader.delete(); } } diff --git a/src/main/java/com/jozufozu/flywheel/core/model/BakedModelBuilder.java b/src/main/java/com/jozufozu/flywheel/core/model/BakedModelBuilder.java index 70631ebea..1e91baaa2 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/BakedModelBuilder.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/BakedModelBuilder.java @@ -42,7 +42,15 @@ public final class BakedModelBuilder implements Bufferable { } @Override - public void bufferInto(ModelBlockRenderer blockRenderer, VertexConsumer consumer, Random random) { + public void bufferInto(VertexConsumer consumer, ModelBlockRenderer blockRenderer, Random random) { blockRenderer.tesselateBlock(renderWorld, model, referenceState, BlockPos.ZERO, poseStack, consumer, false, random, 42, OverlayTexture.NO_OVERLAY, VirtualEmptyModelData.INSTANCE); } + + public BlockModel toModel(String name) { + return BlockModel.of(this, name); + } + + public BlockModel toModel() { + return toModel(referenceState.toString()); + } } 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 76e23da8f..2fea4a493 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,12 @@ package com.jozufozu.flywheel.core.model; +import java.nio.ByteBuffer; + 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; +import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.blaze3d.vertex.PoseStack; import net.minecraft.client.Minecraft; @@ -17,28 +21,55 @@ public class BlockModel implements Model { private final VertexList reader; private final String name; - public BlockModel(BlockState state) { - this(Minecraft.getInstance() + public BlockModel(ByteBuffer vertexBuffer, BufferBuilder.DrawState drawState, int unshadedStartVertex, String name) { + if (drawState.format() != DefaultVertexFormat.BLOCK) { + throw new RuntimeException("Cannot use buffered data with non-block format '" + drawState.format() + "'"); + } + + reader = Formats.BLOCK.createReader(vertexBuffer, drawState.vertexCount(), unshadedStartVertex); + + this.name = name; + } + + public BlockModel(ByteBuffer vertexBuffer, BufferBuilder.DrawState drawState, String name) { + if (drawState.format() != DefaultVertexFormat.BLOCK) { + throw new RuntimeException("Cannot use buffered data with non-block format '" + drawState.format() + "'"); + } + + reader = Formats.BLOCK.createReader(vertexBuffer, drawState.vertexCount()); + + this.name = name; + } + + public BlockModel(ShadeSeparatedBufferedData data, String name) { + this(data.vertexBuffer(), data.drawState(), data.unshadedStartVertex(), name); + } + + public static BlockModel of(Bufferable bufferable, String name) { + ShadeSeparatedBufferedData data = bufferable.build(); + BlockModel model = new BlockModel(data, name); + data.release(); + return model; + } + + public static BlockModel of(BakedModel model, BlockState referenceState) { + ShadeSeparatedBufferedData data = ModelUtil.getBufferedData(model, referenceState); + BlockModel blockModel = new BlockModel(data, referenceState.toString()); + data.release(); + return blockModel; + } + + public static BlockModel of(BlockState state) { + return of(Minecraft.getInstance() .getBlockRenderer() .getBlockModel(state), state); } - public BlockModel(BakedModel model, BlockState referenceState) { - this(new BakedModelBuilder(model).withReferenceState(referenceState), referenceState.toString()); - } - - public BlockModel(BakedModel model, BlockState referenceState, PoseStack ms) { - this(new BakedModelBuilder(model).withReferenceState(referenceState) - .withPoseStack(ms), referenceState.toString()); - } - - public BlockModel(Bufferable bufferable, String name) { - this(bufferable.build(), name); - } - - public BlockModel(ShadeSeparatedBufferBuilder bufferBuilder, String name) { - this.name = name; - reader = Formats.BLOCK.createReader(bufferBuilder); + public static BlockModel of(BakedModel model, BlockState referenceState, PoseStack ms) { + ShadeSeparatedBufferedData data = ModelUtil.getBufferedData(model, referenceState, ms); + BlockModel blockModel = new BlockModel(data, referenceState.toString()); + data.release(); + return blockModel; } @Override @@ -63,12 +94,6 @@ public class BlockModel implements Model { @Override public void delete() { - if (reader instanceof AutoCloseable closeable) { - try { - closeable.close(); - } catch (Exception e) { - // - } - } + reader.delete(); } } diff --git a/src/main/java/com/jozufozu/flywheel/core/model/Bufferable.java b/src/main/java/com/jozufozu/flywheel/core/model/Bufferable.java index ee78333ad..5e0618dd6 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/Bufferable.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/Bufferable.java @@ -8,12 +8,12 @@ import com.mojang.blaze3d.vertex.VertexConsumer; import net.minecraft.client.renderer.block.ModelBlockRenderer; /** - * An interface for objects that can "rendered" into a BufferBuilder. + * An interface for objects that can buffered into a VertexConsumer. */ public interface Bufferable { - void bufferInto(ModelBlockRenderer renderer, VertexConsumer consumer, Random random); + void bufferInto(VertexConsumer consumer, ModelBlockRenderer renderer, Random random); - default ShadeSeparatedBufferBuilder build() { - return ModelUtil.getBufferBuilder(this); + default ShadeSeparatedBufferedData build() { + return ModelUtil.getBufferedData(this); } } 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 1cd4f903c..8b236e21b 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/ModelUtil.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/ModelUtil.java @@ -1,16 +1,20 @@ package com.jozufozu.flywheel.core.model; import java.lang.reflect.Field; +import java.nio.ByteBuffer; import java.util.Collection; import java.util.Random; import java.util.function.Supplier; import com.jozufozu.flywheel.Flywheel; +import com.jozufozu.flywheel.backend.model.BufferBuilderExtension; import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.vertex.BufferBuilder; import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexFormat; +import com.mojang.blaze3d.vertex.BufferBuilder.DrawState; +import com.mojang.datafixers.util.Pair; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.RenderType; @@ -48,39 +52,52 @@ public class ModelUtil { return dispatcher; } - public static ShadeSeparatedBufferBuilder getBufferBuilder(Bufferable bufferable) { + public static ShadeSeparatedBufferedData endAndCombine(BufferBuilder shadedBuilder, BufferBuilder unshadedBuilder) { + int unshadedStartVertex = ((BufferBuilderExtension) shadedBuilder).flywheel$getVertices(); + unshadedBuilder.end(); + Pair unshadedData = unshadedBuilder.popNextBuffer(); + ((BufferBuilderExtension) shadedBuilder).flywheel$appendBufferUnsafe(unshadedData.getSecond()); + shadedBuilder.end(); + Pair data = shadedBuilder.popNextBuffer(); + return new ShadeSeparatedBufferedData.NativeImpl(data.getSecond(), data.getFirst(), unshadedStartVertex); + } + + public static ShadeSeparatedBufferedData getBufferedData(Bufferable bufferable) { ModelBlockRenderer blockRenderer = VANILLA_RENDERER.getModelRenderer(); ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get(); objects.begin(); - bufferable.bufferInto(blockRenderer, objects.shadeSeparatingWrapper, objects.random); + bufferable.bufferInto(objects.shadeSeparatingWrapper, blockRenderer, objects.random); - objects.end(); - - return objects.separatedBufferBuilder; + return objects.end(); } - public static ShadeSeparatedBufferBuilder getBufferBuilder(BakedModel model, BlockState referenceState, PoseStack poseStack) { + public static ShadeSeparatedBufferedData getBufferedData(BakedModel model, BlockState referenceState) { + return new BakedModelBuilder(model).withReferenceState(referenceState) + .build(); + } + + public static ShadeSeparatedBufferedData getBufferedData(BakedModel model, BlockState referenceState, PoseStack poseStack) { return new BakedModelBuilder(model).withReferenceState(referenceState) .withPoseStack(poseStack) .build(); } - public static ShadeSeparatedBufferBuilder getBufferBuilder(BlockAndTintGetter renderWorld, BakedModel model, BlockState referenceState, PoseStack poseStack) { + public static ShadeSeparatedBufferedData getBufferedData(BlockAndTintGetter renderWorld, BakedModel model, BlockState referenceState, PoseStack poseStack) { return new BakedModelBuilder(model).withReferenceState(referenceState) .withPoseStack(poseStack) .withRenderWorld(renderWorld) .build(); } - public static ShadeSeparatedBufferBuilder getBufferBuilderFromTemplate(BlockAndTintGetter renderWorld, RenderType layer, Collection blocks) { + public static ShadeSeparatedBufferedData getBufferedDataFromTemplate(BlockAndTintGetter renderWorld, RenderType layer, Collection blocks) { return new WorldModelBuilder(layer).withRenderWorld(renderWorld) .withBlocks(blocks) .build(); } - public static ShadeSeparatedBufferBuilder getBufferBuilderFromTemplate(BlockAndTintGetter renderWorld, RenderType layer, Collection blocks, PoseStack poseStack) { + public static ShadeSeparatedBufferedData getBufferedDataFromTemplate(BlockAndTintGetter renderWorld, RenderType layer, Collection blocks, PoseStack poseStack) { return new WorldModelBuilder(layer).withRenderWorld(renderWorld) .withBlocks(blocks) .withPoseStack(poseStack) @@ -101,20 +118,18 @@ public class ModelUtil { private static class ThreadLocalObjects { public final Random random = new Random(); public final ShadeSeparatingVertexConsumer shadeSeparatingWrapper = new ShadeSeparatingVertexConsumer(); - public final ShadeSeparatedBufferBuilder separatedBufferBuilder = new ShadeSeparatedBufferBuilder(512); + public final BufferBuilder shadedBuilder = new BufferBuilder(512); public final BufferBuilder unshadedBuilder = new BufferBuilder(512); private void begin() { - this.separatedBufferBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK); + this.shadedBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK); this.unshadedBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK); - this.shadeSeparatingWrapper.prepare(this.separatedBufferBuilder, this.unshadedBuilder); + this.shadeSeparatingWrapper.prepare(this.shadedBuilder, this.unshadedBuilder); } - private void end() { + private ShadeSeparatedBufferedData end() { this.shadeSeparatingWrapper.clear(); - this.unshadedBuilder.end(); - this.separatedBufferBuilder.appendUnshadedVertices(this.unshadedBuilder); - this.separatedBufferBuilder.end(); + return ModelUtil.endAndCombine(shadedBuilder, unshadedBuilder); } } } diff --git a/src/main/java/com/jozufozu/flywheel/core/model/ShadeSeparatedBufferBuilder.java b/src/main/java/com/jozufozu/flywheel/core/model/ShadeSeparatedBufferBuilder.java deleted file mode 100644 index 38043702b..000000000 --- a/src/main/java/com/jozufozu/flywheel/core/model/ShadeSeparatedBufferBuilder.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.jozufozu.flywheel.core.model; - -import java.nio.ByteBuffer; - -import com.jozufozu.flywheel.backend.model.BufferBuilderExtension; -import com.mojang.blaze3d.vertex.BufferBuilder; -import com.mojang.datafixers.util.Pair; - -public class ShadeSeparatedBufferBuilder extends BufferBuilder { - protected int unshadedStartVertex; - - public ShadeSeparatedBufferBuilder(int capacity) { - super(capacity); - } - - public void appendUnshadedVertices(BufferBuilder unshadedBuilder) { - Pair data = unshadedBuilder.popNextBuffer(); - unshadedStartVertex = ((BufferBuilderExtension) this).flywheel$getVertices(); - ((BufferBuilderExtension) this).flywheel$appendBufferUnsafe(data.getSecond()); - } - - public int getUnshadedStartVertex() { - return unshadedStartVertex; - } -} diff --git a/src/main/java/com/jozufozu/flywheel/core/model/ShadeSeparatedBufferedData.java b/src/main/java/com/jozufozu/flywheel/core/model/ShadeSeparatedBufferedData.java new file mode 100644 index 000000000..6a843cb02 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/core/model/ShadeSeparatedBufferedData.java @@ -0,0 +1,51 @@ +package com.jozufozu.flywheel.core.model; + +import java.nio.ByteBuffer; + +import org.lwjgl.system.MemoryUtil; + +import com.jozufozu.flywheel.util.FlwUtil; +import com.mojang.blaze3d.vertex.BufferBuilder; +import com.mojang.blaze3d.vertex.BufferBuilder.DrawState; + +public interface ShadeSeparatedBufferedData { + ByteBuffer vertexBuffer(); + + BufferBuilder.DrawState drawState(); + + int unshadedStartVertex(); + + void release(); + + static final class NativeImpl implements ShadeSeparatedBufferedData { + private final ByteBuffer vertexBuffer; + private final BufferBuilder.DrawState drawState; + private final int unshadedStartVertex; + + public NativeImpl(ByteBuffer vertexBuffer, BufferBuilder.DrawState drawState, int unshadedStartVertex) { + this.vertexBuffer = FlwUtil.copyBuffer(vertexBuffer); + this.drawState = drawState; + this.unshadedStartVertex = unshadedStartVertex; + } + + @Override + public ByteBuffer vertexBuffer() { + return vertexBuffer; + } + + @Override + public DrawState drawState() { + return drawState; + } + + @Override + public int unshadedStartVertex() { + return unshadedStartVertex; + } + + @Override + public void release() { + MemoryUtil.memFree(vertexBuffer); + } + } +} 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 f4b8f1912..0f33c9bac 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/WorldModelBuilder.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/WorldModelBuilder.java @@ -35,7 +35,7 @@ public final class WorldModelBuilder implements Bufferable { } @Override - public void bufferInto(ModelBlockRenderer modelRenderer, VertexConsumer consumer, Random random) { + public void bufferInto(VertexConsumer consumer, ModelBlockRenderer modelRenderer, Random random) { ForgeHooksClient.setRenderType(this.layer); ModelBlockRenderer.enableCaching(); for (StructureTemplate.StructureBlockInfo info : this.blocks) { @@ -80,7 +80,7 @@ public final class WorldModelBuilder implements Bufferable { return this; } - public BlockModel intoMesh(String name) { - return new BlockModel(this, name); + public BlockModel toModel(String name) { + return BlockModel.of(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 97475da4c..17ea35a37 100644 --- a/src/main/java/com/jozufozu/flywheel/core/vertex/AbstractVertexList.java +++ b/src/main/java/com/jozufozu/flywheel/core/vertex/AbstractVertexList.java @@ -1,39 +1,31 @@ package com.jozufozu.flywheel.core.vertex; -import java.nio.Buffer; import java.nio.ByteBuffer; import org.lwjgl.system.MemoryUtil; import com.jozufozu.flywheel.api.vertex.VertexList; -import com.mojang.blaze3d.platform.MemoryTracker; +import com.jozufozu.flywheel.util.FlwUtil; -public abstract class AbstractVertexList implements VertexList, AutoCloseable { +public abstract class AbstractVertexList implements VertexList { protected final ByteBuffer contents; protected final long base; protected final int vertexCount; protected AbstractVertexList(ByteBuffer copyFrom, int vertexCount) { - this.contents = MemoryTracker.create(copyFrom.capacity()); + this.contents = FlwUtil.copyBuffer(copyFrom); this.vertexCount = vertexCount; this.base = MemoryUtil.memAddress(this.contents); - init(copyFrom); - } - - private void init(ByteBuffer copyFrom) { - this.contents.order(copyFrom.order()); - this.contents.put(copyFrom); - ((Buffer) this.contents).flip(); - } - - @Override - public void close() { - MemoryUtil.memFree(contents); } @Override public int getVertexCount() { return vertexCount; } + + @Override + public void delete() { + MemoryUtil.memFree(contents); + } } 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..15e75ecda 100644 --- a/src/main/java/com/jozufozu/flywheel/core/vertex/BlockVertex.java +++ b/src/main/java/com/jozufozu/flywheel/core/vertex/BlockVertex.java @@ -2,14 +2,9 @@ package com.jozufozu.flywheel.core.vertex; import java.nio.ByteBuffer; -import com.jozufozu.flywheel.api.vertex.VertexList; import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.core.layout.BufferLayout; import com.jozufozu.flywheel.core.layout.CommonItems; -import com.jozufozu.flywheel.core.model.ShadeSeparatedBufferBuilder; -import com.mojang.blaze3d.vertex.BufferBuilder; -import com.mojang.blaze3d.vertex.DefaultVertexFormat; -import com.mojang.datafixers.util.Pair; public class BlockVertex implements VertexType { @@ -37,6 +32,10 @@ public class BlockVertex implements VertexType { return new BlockVertexListUnsafe(buffer, vertexCount); } + public BlockVertexListUnsafe.Shaded createReader(ByteBuffer buffer, int vertexCount, int unshadedStartVertex) { + return new BlockVertexListUnsafe.Shaded(buffer, vertexCount, unshadedStartVertex); + } + @Override public String getShaderHeader() { return """ @@ -57,24 +56,4 @@ Vertex FLWCreateVertex() { } """; } - - public BlockVertexListUnsafe.Shaded createReader(ByteBuffer buffer, int vertexCount, int unshadedStartVertex) { - return new BlockVertexListUnsafe.Shaded(buffer, vertexCount, unshadedStartVertex); - } - - public VertexList createReader(BufferBuilder bufferBuilder) { - // TODO: try to avoid virtual model rendering - Pair pair = bufferBuilder.popNextBuffer(); - BufferBuilder.DrawState drawState = pair.getFirst(); - - if (drawState.format() != DefaultVertexFormat.BLOCK) { - throw new RuntimeException("Cannot use BufferBuilder with " + drawState.format()); - } - - if (bufferBuilder instanceof ShadeSeparatedBufferBuilder separated) { - return createReader(pair.getSecond(), drawState.vertexCount(), separated.getUnshadedStartVertex()); - } else { - return createReader(pair.getSecond(), drawState.vertexCount()); - } - } } diff --git a/src/main/java/com/jozufozu/flywheel/util/FlwUtil.java b/src/main/java/com/jozufozu/flywheel/util/FlwUtil.java index beed0590a..2520c1d22 100644 --- a/src/main/java/com/jozufozu/flywheel/util/FlwUtil.java +++ b/src/main/java/com/jozufozu/flywheel/util/FlwUtil.java @@ -1,9 +1,12 @@ package com.jozufozu.flywheel.util; +import java.nio.ByteBuffer; import java.util.Arrays; import java.util.Map; import java.util.stream.Stream; +import org.lwjgl.system.MemoryUtil; + import com.jozufozu.flywheel.mixin.BlockEntityRenderDispatcherAccessor; import net.minecraft.client.Minecraft; @@ -73,4 +76,17 @@ public class FlwUtil { public static Stream mapValues(Map map) { return map.values().stream(); } + + /** + * The returned buffer is backed by native memory and will cause a memory leak if not freed using {@link MemoryUtil#memFree(java.nio.Buffer)}. + */ + public static ByteBuffer copyBuffer(ByteBuffer buffer) { + int pos = buffer.position(); + ByteBuffer copy = MemoryUtil.memAlloc(buffer.remaining()); + copy.order(buffer.order()); + copy.put(buffer); + buffer.position(pos); + copy.flip(); + return copy; + } }