From 6913a3444306b21dadb060beb9c9fefd0235b802 Mon Sep 17 00:00:00 2001 From: PepperCode1 <44146161+PepperCode1@users.noreply.github.com> Date: Tue, 9 Aug 2022 11:25:26 -0700 Subject: [PATCH 1/5] Vertex format refactor - Use memCopy for instanced mesh buffering - Remove VertexWriter - Add VertexListProvider - Add VertexListProviderRegistry to allow vanilla VertexFormats to create VertexLists - Add ReusableVertexList that allows setting the pointer and vertex count --- .../api/vertex/ReusableVertexList.java | 11 + .../flywheel/api/vertex/VertexList.java | 31 +++ .../api/vertex/VertexListProvider.java | 5 + .../flywheel/api/vertex/VertexType.java | 22 +- .../flywheel/api/vertex/VertexWriter.java | 15 -- .../instancing/batching/BatchingEngine.java | 1 + .../instancing/batching/DrawBuffer.java | 27 ++- .../batching/MutableVertexListImpl.java | 206 ----------------- .../instancing/batching/TransformSet.java | 52 ++--- .../instancing/instancing/MeshPool.java | 6 +- .../flywheel/core/hardcoded/ModelPart.java | 57 +++-- .../flywheel/core/hardcoded/PartBuilder.java | 40 ++-- .../flywheel/core/hardcoded/VertexWriter.java | 5 + .../core/hardcoded/VertexWriterImpl.java | 27 +++ .../flywheel/core/layout/CommonItems.java | 37 ++- .../flywheel/core/layout/PrimitiveItem.java | 10 - .../jozufozu/flywheel/core/model/Mesh.java | 37 ++- .../flywheel/core/model/ModelUtil.java | 36 ++- .../flywheel/core/model/SimpleMesh.java | 55 ++++- .../model/buffering/BakedModelBuilder.java | 23 +- .../model/buffering/BlockModelBuilder.java | 23 +- .../buffering/MultiBlockModelBuilder.java | 19 +- .../core/vertex/AbstractVertexList.java | 59 ++--- .../flywheel/core/vertex/BlockVertex.java | 18 +- .../flywheel/core/vertex/BlockVertexList.java | 120 +++++++--- .../core/vertex/BlockVertexListUnsafe.java | 91 -------- .../core/vertex/BlockWriterUnsafe.java | 56 ----- .../vertex/InferredVertexFormatInfo.java} | 8 +- .../core/vertex/InferredVertexListImpl.java | 214 ++++++++++++++++++ .../InferredVertexListProviderImpl.java | 20 ++ .../core/vertex/PosTexNormalVertex.java | 18 +- .../core/vertex/PosTexNormalVertexList.java | 154 +++++++++++++ .../vertex/PosTexNormalVertexListUnsafe.java | 90 -------- .../core/vertex/PosTexNormalWriterUnsafe.java | 44 ---- .../core/vertex/TrackedVertexList.java | 41 ---- .../vertex/VertexListProviderRegistry.java | 55 +++++ .../core/vertex/VertexWriterUnsafe.java | 33 --- 37 files changed, 877 insertions(+), 889 deletions(-) create mode 100644 src/main/java/com/jozufozu/flywheel/api/vertex/ReusableVertexList.java create mode 100644 src/main/java/com/jozufozu/flywheel/api/vertex/VertexListProvider.java delete mode 100644 src/main/java/com/jozufozu/flywheel/api/vertex/VertexWriter.java delete mode 100644 src/main/java/com/jozufozu/flywheel/backend/instancing/batching/MutableVertexListImpl.java create mode 100644 src/main/java/com/jozufozu/flywheel/core/hardcoded/VertexWriter.java create mode 100644 src/main/java/com/jozufozu/flywheel/core/hardcoded/VertexWriterImpl.java delete mode 100644 src/main/java/com/jozufozu/flywheel/core/vertex/BlockVertexListUnsafe.java delete mode 100644 src/main/java/com/jozufozu/flywheel/core/vertex/BlockWriterUnsafe.java rename src/main/java/com/jozufozu/flywheel/{backend/instancing/batching/VertexFormatInfo.java => core/vertex/InferredVertexFormatInfo.java} (88%) create mode 100644 src/main/java/com/jozufozu/flywheel/core/vertex/InferredVertexListImpl.java create mode 100644 src/main/java/com/jozufozu/flywheel/core/vertex/InferredVertexListProviderImpl.java create mode 100644 src/main/java/com/jozufozu/flywheel/core/vertex/PosTexNormalVertexList.java delete mode 100644 src/main/java/com/jozufozu/flywheel/core/vertex/PosTexNormalVertexListUnsafe.java delete mode 100644 src/main/java/com/jozufozu/flywheel/core/vertex/PosTexNormalWriterUnsafe.java delete mode 100644 src/main/java/com/jozufozu/flywheel/core/vertex/TrackedVertexList.java create mode 100644 src/main/java/com/jozufozu/flywheel/core/vertex/VertexListProviderRegistry.java delete mode 100644 src/main/java/com/jozufozu/flywheel/core/vertex/VertexWriterUnsafe.java diff --git a/src/main/java/com/jozufozu/flywheel/api/vertex/ReusableVertexList.java b/src/main/java/com/jozufozu/flywheel/api/vertex/ReusableVertexList.java new file mode 100644 index 000000000..c4f9c4b70 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/api/vertex/ReusableVertexList.java @@ -0,0 +1,11 @@ +package com.jozufozu.flywheel.api.vertex; + +public interface ReusableVertexList extends MutableVertexList { + long ptr(); + + void ptr(long ptr); + + void shiftPtr(int vertices); + + void setVertexCount(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 519ef671f..ec47c17c8 100644 --- a/src/main/java/com/jozufozu/flywheel/api/vertex/VertexList.java +++ b/src/main/java/com/jozufozu/flywheel/api/vertex/VertexList.java @@ -42,6 +42,37 @@ public interface VertexList { float normalZ(int index); + default void write(MutableVertexList dst, int srcIndex, int dstIndex) { + dst.x(dstIndex, x(srcIndex)); + dst.y(dstIndex, y(srcIndex)); + dst.z(dstIndex, z(srcIndex)); + + dst.r(dstIndex, r(srcIndex)); + dst.g(dstIndex, g(srcIndex)); + dst.b(dstIndex, b(srcIndex)); + dst.a(dstIndex, a(srcIndex)); + + dst.u(dstIndex, u(srcIndex)); + dst.v(dstIndex, v(srcIndex)); + + dst.overlay(dstIndex, overlay(srcIndex)); + dst.light(dstIndex, light(srcIndex)); + + dst.normalX(dstIndex, normalX(srcIndex)); + dst.normalY(dstIndex, normalY(srcIndex)); + dst.normalZ(dstIndex, normalZ(srcIndex)); + } + + default void write(MutableVertexList dst, int srcStartIndex, int dstStartIndex, int vertexCount) { + for (int i = 0; i < vertexCount; i++) { + write(dst, srcStartIndex + i, dstStartIndex + i); + } + } + + default void writeAll(MutableVertexList dst) { + write(dst, 0, 0, getVertexCount()); + } + int getVertexCount(); default boolean isEmpty() { diff --git a/src/main/java/com/jozufozu/flywheel/api/vertex/VertexListProvider.java b/src/main/java/com/jozufozu/flywheel/api/vertex/VertexListProvider.java new file mode 100644 index 000000000..a200e03ad --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/api/vertex/VertexListProvider.java @@ -0,0 +1,5 @@ +package com.jozufozu.flywheel.api.vertex; + +public interface VertexListProvider { + ReusableVertexList createVertexList(); +} diff --git a/src/main/java/com/jozufozu/flywheel/api/vertex/VertexType.java b/src/main/java/com/jozufozu/flywheel/api/vertex/VertexType.java index 1ae89d406..72dab420d 100644 --- a/src/main/java/com/jozufozu/flywheel/api/vertex/VertexType.java +++ b/src/main/java/com/jozufozu/flywheel/api/vertex/VertexType.java @@ -1,38 +1,18 @@ package com.jozufozu.flywheel.api.vertex; -import java.nio.ByteBuffer; - import com.jozufozu.flywheel.core.layout.BufferLayout; import com.jozufozu.flywheel.core.source.FileResolution; /** * A vertex type containing metadata about a specific vertex layout. */ -public interface VertexType { +public interface VertexType extends VertexListProvider { /** * The layout of this type of vertex when buffered. */ BufferLayout getLayout(); - /** - * Create a writer backed by the given ByteBuffer. - * - *

- * Implementors are encouraged to override the return type for ergonomics. - *

- */ - VertexWriter createWriter(ByteBuffer buffer); - - /** - * Create a view of the given ByteBuffer as if it were already filled with vertices. - * - *

- * Implementors are encouraged to override the return type for ergonomics. - *

- */ - VertexList createReader(ByteBuffer buffer, int vertexCount); - FileResolution getLayoutShader(); default int getStride() { diff --git a/src/main/java/com/jozufozu/flywheel/api/vertex/VertexWriter.java b/src/main/java/com/jozufozu/flywheel/api/vertex/VertexWriter.java deleted file mode 100644 index a16f0eec5..000000000 --- a/src/main/java/com/jozufozu/flywheel/api/vertex/VertexWriter.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.jozufozu.flywheel.api.vertex; - -public interface VertexWriter { - void writeVertex(VertexList list, int index); - - void seek(long offset); - - VertexList intoReader(int vertices); - - default void writeVertexList(VertexList list) { - for (int i = 0; i < list.getVertexCount(); i++) { - this.writeVertex(list, i); - } - } -} 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 00fb68cd6..1d68c6617 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 @@ -68,6 +68,7 @@ public class BatchingEngine implements Engine { @Override public void renderStage(TaskEngine taskEngine, RenderContext context, RenderStage stage) { // FIXME: properly support material stages + // This also breaks block outlines on batched block entities if (stage != RenderStage.AFTER_FINAL_END_BATCH) { return; } 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 e583f85e1..50a099bae 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,18 +4,24 @@ import java.nio.ByteBuffer; import org.lwjgl.system.MemoryUtil; +import com.jozufozu.flywheel.api.vertex.ReusableVertexList; +import com.jozufozu.flywheel.api.vertex.VertexListProvider; +import com.jozufozu.flywheel.core.vertex.VertexListProviderRegistry; import com.mojang.blaze3d.platform.MemoryTracker; +import com.mojang.blaze3d.vertex.VertexFormat; import net.minecraft.client.renderer.RenderType; /** - * A byte buffer that can be used to draw vertices through multiple {@link MutableVertexListImpl}s. + * A byte buffer that can be used to draw vertices through multiple {@link ReusableVertexList}s. * * The number of vertices needs to be known ahead of time. */ public class DrawBuffer { private final RenderType parent; - private final VertexFormatInfo formatInfo; + private final VertexFormat format; + private final int stride; + private final VertexListProvider provider; private ByteBuffer backingBuffer; private int expectedVertices; @@ -23,7 +29,9 @@ public class DrawBuffer { public DrawBuffer(RenderType parent) { this.parent = parent; - formatInfo = new VertexFormatInfo(parent.format()); + format = parent.format(); + stride = format.getVertexSize(); + provider = VertexListProviderRegistry.getOrInfer(format); } /** @@ -39,9 +47,9 @@ public class DrawBuffer { this.expectedVertices = vertexCount; // Add one extra vertex to uphold the vanilla assumption that BufferBuilders have at least - // enough buffer space for one more vertex. Sodium checks for this extra space when popNextBuffer + // enough buffer space for one more vertex. Rubidium checks for this extra space when popNextBuffer // is called and reallocates the buffer if there is not space for one more vertex. - int byteSize = formatInfo.stride * (vertexCount + 1); + int byteSize = stride * (vertexCount + 1); if (backingBuffer == null) { backingBuffer = MemoryTracker.create(byteSize); @@ -54,8 +62,11 @@ public class DrawBuffer { MemoryUtil.memSet(ptr, 0, byteSize); } - public MutableVertexListImpl slice(int startVertex, int vertexCount) { - return new MutableVertexListImpl(ptr + startVertex * formatInfo.stride, formatInfo, vertexCount); + public ReusableVertexList slice(int startVertex, int vertexCount) { + ReusableVertexList vertexList = provider.createVertexList(); + vertexList.ptr(ptr + startVertex * stride); + vertexList.setVertexCount(vertexCount); + return vertexList; } /** @@ -63,7 +74,7 @@ public class DrawBuffer { * @param bufferBuilder The buffer builder to inject into. */ public void inject(BufferBuilderExtension bufferBuilder) { - bufferBuilder.flywheel$injectForRender(backingBuffer, formatInfo.format, expectedVertices); + bufferBuilder.flywheel$injectForRender(backingBuffer, format, expectedVertices); } public int getVertexCount() { diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/MutableVertexListImpl.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/MutableVertexListImpl.java deleted file mode 100644 index 410da67af..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/MutableVertexListImpl.java +++ /dev/null @@ -1,206 +0,0 @@ -package com.jozufozu.flywheel.backend.instancing.batching; - -import org.lwjgl.system.MemoryUtil; - -import com.jozufozu.flywheel.api.vertex.MutableVertexList; -import com.jozufozu.flywheel.util.RenderMath; - -public class MutableVertexListImpl extends VertexFormatInfo implements MutableVertexList { - private final long anchorPtr; - private final int totalVertexCount; - - private long ptr; - private int vertexCount; - - public MutableVertexListImpl(long ptr, VertexFormatInfo formatInfo, int vertexCount) { - super(formatInfo); - - anchorPtr = ptr; - totalVertexCount = vertexCount; - - setFullRange(); - } - - public void setRange(int startVertex, int vertexCount) { - ptr = anchorPtr + startVertex * stride; - this.vertexCount = vertexCount; - } - - public void setFullRange() { - ptr = anchorPtr; - vertexCount = totalVertexCount; - } - - @Override - public float x(int index) { - if (positionOffset < 0) return 0; - return MemoryUtil.memGetFloat(ptr + index * stride + positionOffset); - } - - @Override - public float y(int index) { - if (positionOffset < 0) return 0; - return MemoryUtil.memGetFloat(ptr + index * stride + positionOffset + 4); - } - - @Override - public float z(int index) { - if (positionOffset < 0) return 0; - return MemoryUtil.memGetFloat(ptr + index * stride + positionOffset + 8); - } - - @Override - public byte r(int index) { - if (colorOffset < 0) return 0; - return MemoryUtil.memGetByte(ptr + index * stride + colorOffset); - } - - @Override - public byte g(int index) { - if (colorOffset < 0) return 0; - return MemoryUtil.memGetByte(ptr + index * stride + colorOffset + 1); - } - - @Override - public byte b(int index) { - if (colorOffset < 0) return 0; - return MemoryUtil.memGetByte(ptr + index * stride + colorOffset + 2); - } - - @Override - public byte a(int index) { - if (colorOffset < 0) return 0; - return MemoryUtil.memGetByte(ptr + index * stride + colorOffset + 3); - } - - @Override - public float u(int index) { - if (textureOffset < 0) return 0; - return MemoryUtil.memGetFloat(ptr + index * stride + textureOffset); - } - - @Override - public float v(int index) { - if (textureOffset < 0) return 0; - return MemoryUtil.memGetFloat(ptr + index * stride + textureOffset + 4); - } - - @Override - public int overlay(int index) { - if (overlayOffset < 0) return 0; - return MemoryUtil.memGetInt(ptr + index * stride + overlayOffset); - } - - @Override - public int light(int index) { - if (lightOffset < 0) return 0; - return MemoryUtil.memGetInt(ptr + index * stride + lightOffset); - } - - @Override - public float normalX(int index) { - if (normalOffset < 0) return 0; - return RenderMath.f(MemoryUtil.memGetByte(ptr + index * stride + normalOffset)); - } - - @Override - public float normalY(int index) { - if (normalOffset < 0) return 0; - return RenderMath.f(MemoryUtil.memGetByte(ptr + index * stride + normalOffset + 1)); - } - - @Override - public float normalZ(int index) { - if (normalOffset < 0) return 0; - return RenderMath.f(MemoryUtil.memGetByte(ptr + index * stride + normalOffset + 2)); - } - - @Override - public int getVertexCount() { - return vertexCount; - } - - @Override - public void x(int index, float x) { - if (positionOffset < 0) return; - MemoryUtil.memPutFloat(ptr + index * stride + positionOffset, x); - } - - @Override - public void y(int index, float y) { - if (positionOffset < 0) return; - MemoryUtil.memPutFloat(ptr + index * stride + positionOffset + 4, y); - } - - @Override - public void z(int index, float z) { - if (positionOffset < 0) return; - MemoryUtil.memPutFloat(ptr + index * stride + positionOffset + 8, z); - } - - @Override - public void r(int index, byte r) { - if (colorOffset < 0) return; - MemoryUtil.memPutByte(ptr + index * stride + colorOffset, r); - } - - @Override - public void g(int index, byte g) { - if (colorOffset < 0) return; - MemoryUtil.memPutByte(ptr + index * stride + colorOffset + 1, g); - } - - @Override - public void b(int index, byte b) { - if (colorOffset < 0) return; - MemoryUtil.memPutByte(ptr + index * stride + colorOffset + 2, b); - } - - @Override - public void a(int index, byte a) { - if (colorOffset < 0) return; - MemoryUtil.memPutByte(ptr + index * stride + colorOffset + 3, a); - } - - @Override - public void u(int index, float u) { - if (textureOffset < 0) return; - MemoryUtil.memPutFloat(ptr + index * stride + textureOffset, u); - } - - @Override - public void v(int index, float v) { - if (textureOffset < 0) return; - MemoryUtil.memPutFloat(ptr + index * stride + textureOffset + 4, v); - } - - @Override - public void overlay(int index, int overlay) { - if (overlayOffset < 0) return; - MemoryUtil.memPutInt(ptr + index * stride + overlayOffset, overlay); - } - - @Override - public void light(int index, int light) { - if (lightOffset < 0) return; - MemoryUtil.memPutInt(ptr + index * stride + lightOffset, light); - } - - @Override - public void normalX(int index, float normalX) { - if (normalOffset < 0) return; - MemoryUtil.memPutByte(ptr + index * stride + normalOffset, RenderMath.nb(normalX)); - } - - @Override - public void normalY(int index, float normalY) { - if (normalOffset < 0) return; - MemoryUtil.memPutByte(ptr + index * stride + normalOffset + 1, RenderMath.nb(normalY)); - } - - @Override - public void normalZ(int index, float normalZ) { - if (normalOffset < 0) return; - MemoryUtil.memPutByte(ptr + index * stride + normalOffset + 2, RenderMath.nb(normalZ)); - } -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/TransformSet.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/TransformSet.java index 642fea29f..4dc4a1bef 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/TransformSet.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/TransformSet.java @@ -7,7 +7,7 @@ import com.jozufozu.flywheel.api.material.Material; import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.api.struct.StructType.VertexTransformer; import com.jozufozu.flywheel.api.vertex.MutableVertexList; -import com.jozufozu.flywheel.api.vertex.VertexList; +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; @@ -49,69 +49,45 @@ public class TransformSet { int start = Math.max(instances, 0); int vertexCount = mesh.getVertexCount() * (end - start); - MutableVertexListImpl sub = buffer.slice(startVertex, vertexCount); + ReusableVertexList sub = buffer.slice(startVertex, vertexCount); startVertex += vertexCount; pool.submit(() -> drawRange(sub, start, end, stack, level)); } } - private void drawRange(MutableVertexListImpl vertexList, int from, int to, PoseStack stack, ClientLevel level) { + private void drawRange(ReusableVertexList vertexList, int from, int to, PoseStack stack, ClientLevel level) { drawList(vertexList, instancer.getRange(from, to), stack, level); } - void drawAll(MutableVertexListImpl vertexList, PoseStack stack, ClientLevel level) { + void drawAll(ReusableVertexList vertexList, PoseStack stack, ClientLevel level) { drawList(vertexList, instancer.getAll(), stack, level); } - private void drawList(MutableVertexListImpl vertexList, List list, PoseStack stack, ClientLevel level) { - int startVertex = 0; - int meshVertexCount = mesh.getVertexCount(); + private void drawList(ReusableVertexList vertexList, List list, PoseStack stack, ClientLevel level) { + long anchorPtr = vertexList.ptr(); + int totalVertexCount = vertexList.getVertexCount(); + + int meshVertexCount = mesh.getVertexCount(); + vertexList.setVertexCount(meshVertexCount); - VertexList meshReader = mesh.getReader(); @SuppressWarnings("unchecked") StructType.VertexTransformer structVertexTransformer = (VertexTransformer) instancer.type.getVertexTransformer(); for (D d : list) { - vertexList.setRange(startVertex, meshVertexCount); - - writeMesh(vertexList, meshReader); + mesh.writeInto(vertexList); structVertexTransformer.transform(vertexList, d, level); - startVertex += meshVertexCount; + vertexList.shiftPtr(meshVertexCount); } - vertexList.setFullRange(); + vertexList.ptr(anchorPtr); + vertexList.setVertexCount(totalVertexCount); material.getVertexTransformer().transform(vertexList, level); applyPoseStack(vertexList, stack, false); } - // TODO: remove this - // The VertexWriter API and VertexFormat conversion needs to be rewritten to make this unnecessary - private static void writeMesh(MutableVertexList vertexList, VertexList meshReader) { - for (int i = 0; i < meshReader.getVertexCount(); i++) { - vertexList.x(i, meshReader.x(i)); - vertexList.y(i, meshReader.y(i)); - vertexList.z(i, meshReader.z(i)); - - vertexList.r(i, meshReader.r(i)); - vertexList.g(i, meshReader.g(i)); - vertexList.b(i, meshReader.b(i)); - vertexList.a(i, meshReader.a(i)); - - vertexList.u(i, meshReader.u(i)); - vertexList.v(i, meshReader.v(i)); - - vertexList.overlay(i, meshReader.overlay(i)); - vertexList.light(i, meshReader.light(i)); - - vertexList.normalX(i, meshReader.normalX(i)); - vertexList.normalY(i, meshReader.normalY(i)); - vertexList.normalZ(i, meshReader.normalZ(i)); - } - } - private static void applyPoseStack(MutableVertexList vertexList, PoseStack stack, boolean applyNormalMatrix) { Vector4f pos = new Vector4f(); Vector3f normal = new Vector3f(); diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/MeshPool.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/MeshPool.java index 145f90ec3..39a0b4a48 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/MeshPool.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/MeshPool.java @@ -152,7 +152,7 @@ public class MeshPool { } } catch (Exception e) { - Flywheel.LOGGER.error("Error uploading pooled models:", e); + Flywheel.LOGGER.error("Error uploading pooled meshes:", e); } } @@ -164,7 +164,7 @@ public class MeshPool { } pendingUpload.clear(); } catch (Exception e) { - Flywheel.LOGGER.error("Error uploading pooled models:", e); + Flywheel.LOGGER.error("Error uploading pooled meshes:", e); } } @@ -209,7 +209,7 @@ public class MeshPool { } private boolean hasAnythingToRender() { - return mesh.getVertexCount() <= 0 || isDeleted(); + return mesh.isEmpty() || isDeleted(); } private void draw(int instanceCount) { 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 b639d64e0..7369df882 100644 --- a/src/main/java/com/jozufozu/flywheel/core/hardcoded/ModelPart.java +++ b/src/main/java/com/jozufozu/flywheel/core/hardcoded/ModelPart.java @@ -1,20 +1,22 @@ package com.jozufozu.flywheel.core.hardcoded; +import java.nio.ByteBuffer; import java.util.List; -import org.lwjgl.system.MemoryStack; +import org.lwjgl.system.MemoryUtil; -import com.jozufozu.flywheel.api.vertex.VertexList; +import com.jozufozu.flywheel.api.vertex.MutableVertexList; +import com.jozufozu.flywheel.api.vertex.ReusableVertexList; import com.jozufozu.flywheel.core.model.Mesh; import com.jozufozu.flywheel.core.vertex.Formats; import com.jozufozu.flywheel.core.vertex.PosTexNormalVertex; -import com.jozufozu.flywheel.core.vertex.PosTexNormalWriterUnsafe; +import com.mojang.blaze3d.platform.MemoryTracker; public class ModelPart implements Mesh { - - private final int vertices; + private final int vertexCount; + private final ByteBuffer contents; + private final ReusableVertexList vertexList; private final String name; - private final VertexList reader; public ModelPart(List cuboids, String name) { this.name = name; @@ -24,17 +26,19 @@ public class ModelPart implements Mesh { for (PartBuilder.CuboidBuilder cuboid : cuboids) { vertices += cuboid.vertices(); } - this.vertices = vertices; + this.vertexCount = vertices; } - try (var stack = MemoryStack.stackPush()) { - PosTexNormalWriterUnsafe writer = getVertexType().createWriter(stack.malloc(size())); - for (PartBuilder.CuboidBuilder cuboid : cuboids) { - cuboid.buffer(writer); - } - - reader = writer.intoReader(this.vertices); + contents = MemoryTracker.create(size()); + long ptr = MemoryUtil.memAddress(contents); + VertexWriter writer = new VertexWriterImpl(ptr); + for (PartBuilder.CuboidBuilder cuboid : cuboids) { + cuboid.write(writer); } + + vertexList = getVertexType().createVertexList(); + vertexList.ptr(ptr); + vertexList.setVertexCount(vertexCount); } public static PartBuilder builder(String name, int sizeU, int sizeV) { @@ -42,22 +46,33 @@ public class ModelPart implements Mesh { } @Override - public String name() { - return name; + public PosTexNormalVertex getVertexType() { + return Formats.POS_TEX_NORMAL; } @Override public int getVertexCount() { - return vertices; + return vertexCount; } @Override - public VertexList getReader() { - return reader; + public void writeInto(ByteBuffer buffer, long byteIndex) { + buffer.position((int) byteIndex); + MemoryUtil.memCopy(contents, buffer); } @Override - public PosTexNormalVertex getVertexType() { - return Formats.POS_TEX_NORMAL; + public void writeInto(MutableVertexList dst) { + vertexList.writeAll(dst); + } + + @Override + public void close() { + MemoryUtil.memFree(contents); + } + + @Override + public String name() { + return name; } } diff --git a/src/main/java/com/jozufozu/flywheel/core/hardcoded/PartBuilder.java b/src/main/java/com/jozufozu/flywheel/core/hardcoded/PartBuilder.java index 3747fbe62..945607a47 100644 --- a/src/main/java/com/jozufozu/flywheel/core/hardcoded/PartBuilder.java +++ b/src/main/java/com/jozufozu/flywheel/core/hardcoded/PartBuilder.java @@ -5,7 +5,6 @@ import java.util.EnumSet; import java.util.List; import java.util.Set; -import com.jozufozu.flywheel.core.vertex.PosTexNormalWriterUnsafe; import com.mojang.math.Matrix3f; import com.mojang.math.Quaternion; import com.mojang.math.Vector3f; @@ -160,8 +159,7 @@ public class PartBuilder { return visibleFaces.size() * 4; } - public void buffer(PosTexNormalWriterUnsafe buffer) { - + public void write(VertexWriter writer) { float sizeX = posX2 - posX1; float sizeY = posY2 - posY1; float sizeZ = posZ2 - posZ1; @@ -219,28 +217,27 @@ public class PartBuilder { float f12 = getV((float)textureOffsetV + sizeZ + sizeY); if (invertYZ) { - quad(buffer, new Vector3f[]{hlh, llh, lll, hll}, f6, f11, f7, f10, down); - quad(buffer, new Vector3f[]{hhl, lhl, lhh, hhh}, f5, f10, f6, f11, up); - quad(buffer, new Vector3f[]{lll, llh, lhh, lhl}, f5, f12, f4, f11, west); - quad(buffer, new Vector3f[]{hll, lll, lhl, hhl}, f9, f12, f8, f11, north); - quad(buffer, new Vector3f[]{hlh, hll, hhl, hhh}, f8, f12, f6, f11, east); - quad(buffer, new Vector3f[]{llh, hlh, hhh, lhh}, f6, f12, f5, f11, south); + quad(writer, new Vector3f[]{hlh, llh, lll, hll}, f6, f11, f7, f10, down); + quad(writer, new Vector3f[]{hhl, lhl, lhh, hhh}, f5, f10, f6, f11, up); + quad(writer, new Vector3f[]{lll, llh, lhh, lhl}, f5, f12, f4, f11, west); + quad(writer, new Vector3f[]{hll, lll, lhl, hhl}, f9, f12, f8, f11, north); + quad(writer, new Vector3f[]{hlh, hll, hhl, hhh}, f8, f12, f6, f11, east); + quad(writer, new Vector3f[]{llh, hlh, hhh, lhh}, f6, f12, f5, f11, south); } else { - quad(buffer, new Vector3f[]{hlh, llh, lll, hll}, f5, f10, f6, f11, down); - quad(buffer, new Vector3f[]{hhl, lhl, lhh, hhh}, f6, f11, f7, f10, up); - quad(buffer, new Vector3f[]{lll, llh, lhh, lhl}, f4, f11, f5, f12, west); - quad(buffer, new Vector3f[]{hll, lll, lhl, hhl}, f5, f11, f6, f12, north); - quad(buffer, new Vector3f[]{hlh, hll, hhl, hhh}, f6, f11, f8, f12, east); - quad(buffer, new Vector3f[]{llh, hlh, hhh, lhh}, f8, f11, f9, f12, south); + quad(writer, new Vector3f[]{hlh, llh, lll, hll}, f5, f10, f6, f11, down); + quad(writer, new Vector3f[]{hhl, lhl, lhh, hhh}, f6, f11, f7, f10, up); + quad(writer, new Vector3f[]{lll, llh, lhh, lhl}, f4, f11, f5, f12, west); + quad(writer, new Vector3f[]{hll, lll, lhl, hhl}, f5, f11, f6, f12, north); + quad(writer, new Vector3f[]{hlh, hll, hhl, hhh}, f6, f11, f8, f12, east); + quad(writer, new Vector3f[]{llh, hlh, hhh, lhh}, f8, f11, f9, f12, south); } } - public void quad(PosTexNormalWriterUnsafe buffer, Vector3f[] vertices, float minU, float minV, float maxU, float maxV, Vector3f normal) { - buffer.putVertex(vertices[0].x(), vertices[0].y(), vertices[0].z(), normal.x(), normal.y(), normal.z(), maxU, minV); - buffer.putVertex(vertices[1].x(), vertices[1].y(), vertices[1].z(), normal.x(), normal.y(), normal.z(), minU, minV); - buffer.putVertex(vertices[2].x(), vertices[2].y(), vertices[2].z(), normal.x(), normal.y(), normal.z(), minU, maxV); - buffer.putVertex(vertices[3].x(), vertices[3].y(), vertices[3].z(), normal.x(), normal.y(), normal.z(), maxU, maxV); - + public void quad(VertexWriter writer, Vector3f[] vertices, float minU, float minV, float maxU, float maxV, Vector3f normal) { + writer.putVertex(vertices[0].x(), vertices[0].y(), vertices[0].z(), maxU, minV, normal.x(), normal.y(), normal.z()); + writer.putVertex(vertices[1].x(), vertices[1].y(), vertices[1].z(), minU, minV, normal.x(), normal.y(), normal.z()); + writer.putVertex(vertices[2].x(), vertices[2].y(), vertices[2].z(), minU, maxV, normal.x(), normal.y(), normal.z()); + writer.putVertex(vertices[3].x(), vertices[3].y(), vertices[3].z(), maxU, maxV, normal.x(), normal.y(), normal.z()); } public float getU(float u) { @@ -258,5 +255,4 @@ public class PartBuilder { } } - } diff --git a/src/main/java/com/jozufozu/flywheel/core/hardcoded/VertexWriter.java b/src/main/java/com/jozufozu/flywheel/core/hardcoded/VertexWriter.java new file mode 100644 index 000000000..7e031c58b --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/core/hardcoded/VertexWriter.java @@ -0,0 +1,5 @@ +package com.jozufozu.flywheel.core.hardcoded; + +public interface VertexWriter { + void putVertex(float x, float y, float z, float u, float v, float nX, float nY, float nZ); +} diff --git a/src/main/java/com/jozufozu/flywheel/core/hardcoded/VertexWriterImpl.java b/src/main/java/com/jozufozu/flywheel/core/hardcoded/VertexWriterImpl.java new file mode 100644 index 000000000..3b8b617cd --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/core/hardcoded/VertexWriterImpl.java @@ -0,0 +1,27 @@ +package com.jozufozu.flywheel.core.hardcoded; + +import org.lwjgl.system.MemoryUtil; + +import com.jozufozu.flywheel.util.RenderMath; + +public class VertexWriterImpl implements VertexWriter { + private long ptr; + + public VertexWriterImpl(long ptr) { + this.ptr = ptr; + } + + @Override + public void putVertex(float x, float y, float z, float u, float v, float nX, float nY, float nZ) { + MemoryUtil.memPutFloat(ptr, x); + MemoryUtil.memPutFloat(ptr + 4, y); + MemoryUtil.memPutFloat(ptr + 8, z); + MemoryUtil.memPutFloat(ptr + 12, u); + MemoryUtil.memPutFloat(ptr + 16, v); + MemoryUtil.memPutByte(ptr + 20, RenderMath.nb(nX)); + MemoryUtil.memPutByte(ptr + 21, RenderMath.nb(nY)); + MemoryUtil.memPutByte(ptr + 22, RenderMath.nb(nZ)); + + ptr += 23; + } +} diff --git a/src/main/java/com/jozufozu/flywheel/core/layout/CommonItems.java b/src/main/java/com/jozufozu/flywheel/core/layout/CommonItems.java index e8d51f557..488d16489 100644 --- a/src/main/java/com/jozufozu/flywheel/core/layout/CommonItems.java +++ b/src/main/java/com/jozufozu/flywheel/core/layout/CommonItems.java @@ -1,26 +1,39 @@ package com.jozufozu.flywheel.core.layout; import com.jozufozu.flywheel.backend.gl.GlNumericType; +import com.jozufozu.flywheel.backend.gl.array.VertexAttributeF; import com.jozufozu.flywheel.backend.gl.array.VertexAttributeI; public class CommonItems { - public static final PrimitiveItem VEC4 = new PrimitiveItem(GlNumericType.FLOAT, 4); - public static final PrimitiveItem VEC3 = new PrimitiveItem(GlNumericType.FLOAT, 3); - public static final PrimitiveItem VEC2 = new PrimitiveItem(GlNumericType.FLOAT, 2); - public static final PrimitiveItem FLOAT = new PrimitiveItem(GlNumericType.FLOAT, 1); + public static final PrimitiveItem VEC4 = primitiveF(GlNumericType.FLOAT, 4); + public static final PrimitiveItem VEC3 = primitiveF(GlNumericType.FLOAT, 3); + public static final PrimitiveItem VEC2 = primitiveF(GlNumericType.FLOAT, 2); + public static final PrimitiveItem FLOAT = primitiveF(GlNumericType.FLOAT, 1); - public static final PrimitiveItem QUATERNION = new PrimitiveItem(GlNumericType.FLOAT, 4); - public static final PrimitiveItem NORMAL = new PrimitiveItem(GlNumericType.BYTE, 3, true); - public static final PrimitiveItem UV = new PrimitiveItem(GlNumericType.FLOAT, 2); + public static final PrimitiveItem QUATERNION = primitiveF(GlNumericType.FLOAT, 4); + public static final PrimitiveItem NORMAL = primitiveF(GlNumericType.BYTE, 3, true); + public static final PrimitiveItem UV = primitiveF(GlNumericType.FLOAT, 2); - public static final PrimitiveItem RGBA = new PrimitiveItem(GlNumericType.UBYTE, 4, true); - public static final PrimitiveItem RGB = new PrimitiveItem(GlNumericType.UBYTE, 3, true); - public static final PrimitiveItem LIGHT = new PrimitiveItem(new VertexAttributeI(GlNumericType.UBYTE, 2)); - public static final PrimitiveItem LIGHT_SHORT = new PrimitiveItem(new VertexAttributeI(GlNumericType.USHORT, 2)); + public static final PrimitiveItem RGBA = primitiveF(GlNumericType.UBYTE, 4, true); + public static final PrimitiveItem RGB = primitiveF(GlNumericType.UBYTE, 3, true); + public static final PrimitiveItem LIGHT = primitiveI(GlNumericType.UBYTE, 2); + public static final PrimitiveItem LIGHT_SHORT = primitiveI(GlNumericType.USHORT, 2); - public static final PrimitiveItem NORMALIZED_BYTE = new PrimitiveItem(GlNumericType.BYTE, 1, true); + public static final PrimitiveItem NORMALIZED_BYTE = primitiveF(GlNumericType.BYTE, 1, true); public static final MatrixItem MAT3 = new MatrixItem(3, 3); public static final MatrixItem MAT4 = new MatrixItem(4, 4); + + private static PrimitiveItem primitiveF(GlNumericType type, int count, boolean normalized) { + return new PrimitiveItem(new VertexAttributeF(type, count, normalized)); + } + + private static PrimitiveItem primitiveF(GlNumericType type, int count) { + return primitiveF(type, count, false); + } + + private static PrimitiveItem primitiveI(GlNumericType type, int count) { + return new PrimitiveItem(new VertexAttributeI(type, count)); + } } diff --git a/src/main/java/com/jozufozu/flywheel/core/layout/PrimitiveItem.java b/src/main/java/com/jozufozu/flywheel/core/layout/PrimitiveItem.java index bc6423e17..d26fc4a16 100644 --- a/src/main/java/com/jozufozu/flywheel/core/layout/PrimitiveItem.java +++ b/src/main/java/com/jozufozu/flywheel/core/layout/PrimitiveItem.java @@ -2,22 +2,12 @@ package com.jozufozu.flywheel.core.layout; import java.util.function.Consumer; -import com.jozufozu.flywheel.backend.gl.GlNumericType; import com.jozufozu.flywheel.backend.gl.array.VertexAttribute; -import com.jozufozu.flywheel.backend.gl.array.VertexAttributeF; public class PrimitiveItem implements LayoutItem { private final VertexAttribute attribute; - public PrimitiveItem(GlNumericType type, int count) { - this(type, count, false); - } - - public PrimitiveItem(GlNumericType type, int count, boolean normalized) { - this(new VertexAttributeF(type, count, normalized)); - } - public PrimitiveItem(VertexAttribute attribute) { this.attribute = attribute; } diff --git a/src/main/java/com/jozufozu/flywheel/core/model/Mesh.java b/src/main/java/com/jozufozu/flywheel/core/model/Mesh.java index c382211c7..f09c5ec58 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/Mesh.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/Mesh.java @@ -2,9 +2,8 @@ package com.jozufozu.flywheel.core.model; import java.nio.ByteBuffer; -import com.jozufozu.flywheel.api.vertex.VertexList; +import com.jozufozu.flywheel.api.vertex.MutableVertexList; import com.jozufozu.flywheel.api.vertex.VertexType; -import com.jozufozu.flywheel.api.vertex.VertexWriter; import com.jozufozu.flywheel.backend.instancing.instancing.ElementBuffer; import com.jozufozu.flywheel.core.QuadConverter; @@ -30,39 +29,34 @@ import com.jozufozu.flywheel.core.QuadConverter; */ public interface Mesh { - /** - * A name uniquely identifying this model. - */ - String name(); - VertexType getVertexType(); - VertexList getReader(); - /** - * @return The number of vertices the model has. + * @return The number of vertices this mesh has. */ - default int getVertexCount() { - return getReader().getVertexCount(); - } + int getVertexCount(); /** * Is there nothing to render? * @return true if there are no vertices. */ default boolean isEmpty() { - return getReader().isEmpty(); + return getVertexCount() == 0; } /** - * The size in bytes that this model's data takes up. + * The size in bytes that this mesh's data takes up. */ default int size() { return getVertexType().byteOffset(getVertexCount()); } + void writeInto(ByteBuffer buffer, long byteIndex); + + void writeInto(MutableVertexList vertexList); + /** - * Create an element buffer object that indexes the vertices of this model. + * Create an element buffer object that indexes the vertices of this mesh. * *

* Very often models in minecraft are made up of sequential quads, which is a very predictable pattern. @@ -76,9 +70,10 @@ public interface Mesh { .quads2Tris(getVertexCount() / 4); } - default void writeInto(ByteBuffer buffer, long byteIndex) { - VertexWriter writer = getVertexType().createWriter(buffer); - writer.seek(byteIndex); - writer.writeVertexList(getReader()); - } + void close(); + + /** + * A name uniquely identifying this mesh. + */ + String name(); } 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 b74a35989..dfcd1435a 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/ModelUtil.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/ModelUtil.java @@ -4,14 +4,18 @@ import java.lang.reflect.Field; import java.nio.ByteBuffer; import org.jetbrains.annotations.Nullable; +import org.lwjgl.system.MemoryUtil; import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.api.material.Material; -import com.jozufozu.flywheel.api.vertex.VertexList; +import com.jozufozu.flywheel.api.vertex.ReusableVertexList; +import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.core.Materials; import com.jozufozu.flywheel.core.vertex.Formats; -import com.mojang.blaze3d.vertex.BufferBuilder; -import com.mojang.blaze3d.vertex.DefaultVertexFormat; +import com.jozufozu.flywheel.core.vertex.VertexListProviderRegistry; +import com.mojang.blaze3d.platform.MemoryTracker; +import com.mojang.blaze3d.vertex.BufferBuilder.DrawState; +import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.datafixers.util.Pair; import net.minecraft.client.Minecraft; @@ -43,15 +47,27 @@ public class ModelUtil { return dispatcher; } - public static VertexList createVertexList(BufferBuilder bufferBuilder) { - Pair pair = bufferBuilder.popNextBuffer(); - BufferBuilder.DrawState drawState = pair.getFirst(); + public static Pair convertBlockBuffer(Pair pair) { + DrawState drawState = pair.getFirst(); + int vertexCount = drawState.vertexCount(); + VertexFormat srcFormat = drawState.format(); + VertexType dstVertexType = Formats.BLOCK; - if (drawState.format() != DefaultVertexFormat.BLOCK) { - throw new RuntimeException("Cannot use BufferBuilder with " + drawState.format()); - } + ByteBuffer src = pair.getSecond(); + ByteBuffer dst = MemoryTracker.create(src.capacity()); + long srcPtr = MemoryUtil.memAddress(src); + long dstPtr = MemoryUtil.memAddress(dst); - return Formats.BLOCK.createReader(pair.getSecond(), drawState.vertexCount()); + ReusableVertexList srcList = VertexListProviderRegistry.getOrInfer(srcFormat).createVertexList(); + ReusableVertexList dstList = dstVertexType.createVertexList(); + srcList.ptr(srcPtr); + dstList.ptr(dstPtr); + srcList.setVertexCount(vertexCount); + dstList.setVertexCount(vertexCount); + + srcList.writeAll(dstList); + + return Pair.of(dstVertexType, dst); } @Nullable 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 55f76ef44..f95423005 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/SimpleMesh.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/SimpleMesh.java @@ -1,22 +1,36 @@ package com.jozufozu.flywheel.core.model; -import com.jozufozu.flywheel.api.vertex.VertexList; +import java.nio.ByteBuffer; + +import org.lwjgl.system.MemoryUtil; + +import com.jozufozu.flywheel.api.vertex.MutableVertexList; +import com.jozufozu.flywheel.api.vertex.ReusableVertexList; import com.jozufozu.flywheel.api.vertex.VertexType; public class SimpleMesh implements Mesh { - private final VertexList reader; private final VertexType vertexType; + private final int vertexCount; + private final ByteBuffer contents; + private final ReusableVertexList vertexList; private final String name; - public SimpleMesh(VertexList reader, VertexType vertexType, String name) { - this.reader = reader; + public SimpleMesh(VertexType vertexType, ByteBuffer contents, String name) { this.vertexType = vertexType; + this.contents = contents; this.name = name; - } - @Override - public String name() { - return name; + contents.clear(); + int bytes = contents.remaining(); + int stride = vertexType.getStride(); + if (bytes % stride != 0) { + throw new IllegalArgumentException("Buffer contains non-whole amount of vertices!"); + } + vertexCount = bytes / stride; + + vertexList = getVertexType().createVertexList(); + vertexList.ptr(MemoryUtil.memAddress(contents)); + vertexList.setVertexCount(vertexCount); } @Override @@ -25,8 +39,29 @@ public class SimpleMesh implements Mesh { } @Override - public VertexList getReader() { - return reader; + public int getVertexCount() { + return vertexCount; + } + + @Override + public void writeInto(ByteBuffer buffer, long byteIndex) { + buffer.position((int) byteIndex); + MemoryUtil.memCopy(contents, buffer); + } + + @Override + public void writeInto(MutableVertexList dst) { + vertexList.writeAll(dst); + } + + @Override + public void close() { + MemoryUtil.memFree(contents); + } + + @Override + public String name() { + return name; } @Override diff --git a/src/main/java/com/jozufozu/flywheel/core/model/buffering/BakedModelBuilder.java b/src/main/java/com/jozufozu/flywheel/core/model/buffering/BakedModelBuilder.java index 7393ac14b..d7c138d00 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/buffering/BakedModelBuilder.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/buffering/BakedModelBuilder.java @@ -1,9 +1,11 @@ package com.jozufozu.flywheel.core.model.buffering; +import java.nio.ByteBuffer; import java.util.function.BiFunction; import com.google.common.collect.ImmutableMap; import com.jozufozu.flywheel.api.material.Material; +import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.core.model.Mesh; import com.jozufozu.flywheel.core.model.ModelUtil; import com.jozufozu.flywheel.core.model.SimpleMesh; @@ -12,13 +14,13 @@ import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.BufferFacto import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ResultConsumer; import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ShadeSeparatedBufferFactory; import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ShadeSeparatedResultConsumer; -import com.jozufozu.flywheel.core.vertex.Formats; import com.jozufozu.flywheel.core.virtual.VirtualEmptyBlockGetter; import com.jozufozu.flywheel.core.virtual.VirtualEmptyModelData; 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.datafixers.util.Pair; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.resources.model.BakedModel; @@ -30,7 +32,6 @@ import net.minecraftforge.client.model.data.IModelData; public class BakedModelBuilder { private final BakedModel bakedModel; private boolean shadeSeparated = true; - private VertexFormat vertexFormat; private BlockAndTintGetter renderWorld; private BlockState blockState; private PoseStack poseStack; @@ -46,11 +47,6 @@ public class BakedModelBuilder { return this; } - public BakedModelBuilder vertexFormat(VertexFormat vertexFormat) { - this.vertexFormat = vertexFormat; - return this; - } - public BakedModelBuilder renderWorld(BlockAndTintGetter renderWorld) { this.renderWorld = renderWorld; return this; @@ -80,9 +76,6 @@ public class BakedModelBuilder { public TessellatedModel build() { ModelBufferingObjects objects = ModelBufferingObjects.THREAD_LOCAL.get(); - if (vertexFormat == null) { - vertexFormat = DefaultVertexFormat.BLOCK; - } if (renderWorld == null) { renderWorld = VirtualEmptyBlockGetter.INSTANCE; } @@ -104,28 +97,30 @@ public class BakedModelBuilder { if (shadeSeparated) { ShadeSeparatedBufferFactory bufferFactory = (renderType, shaded) -> { BufferBuilder buffer = new BufferBuilder(64); - buffer.begin(VertexFormat.Mode.QUADS, vertexFormat); + buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK); return buffer; }; ShadeSeparatedResultConsumer resultConsumer = (renderType, shaded, buffer) -> { buffer.end(); Material material = materialFunc.apply(renderType, shaded); if (material != null) { - meshMapBuilder.put(material, new SimpleMesh(ModelUtil.createVertexList(buffer), Formats.BLOCK, "bakedModel=" + bakedModel.toString() + ",renderType=" + renderType.toString() + ",shaded=" + shaded)); + Pair pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer()); + meshMapBuilder.put(material, new SimpleMesh(pair.getFirst(), pair.getSecond(), "bakedModel=" + bakedModel.toString() + ",renderType=" + renderType.toString() + ",shaded=" + shaded)); } }; ModelBufferingUtil.bufferSingleShadeSeparated(ModelUtil.VANILLA_RENDERER.getModelRenderer(), renderWorld, bakedModel, blockState, poseStack, bufferFactory, objects.shadeSeparatingBufferWrapper, objects.random, modelData, resultConsumer); } else { BufferFactory bufferFactory = (renderType) -> { BufferBuilder buffer = new BufferBuilder(64); - buffer.begin(VertexFormat.Mode.QUADS, vertexFormat); + buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK); return buffer; }; ResultConsumer resultConsumer = (renderType, buffer) -> { buffer.end(); Material material = materialFunc.apply(renderType, false); if (material != null) { - meshMapBuilder.put(material, new SimpleMesh(ModelUtil.createVertexList(buffer), Formats.BLOCK, "bakedModel=" + bakedModel.toString() + ",renderType=" + renderType.toString())); + Pair pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer()); + meshMapBuilder.put(material, new SimpleMesh(pair.getFirst(), pair.getSecond(), "bakedModel=" + bakedModel.toString() + ",renderType=" + renderType.toString())); } }; ModelBufferingUtil.bufferSingle(ModelUtil.VANILLA_RENDERER.getModelRenderer(), renderWorld, bakedModel, blockState, poseStack, bufferFactory, objects.bufferWrapper, objects.random, modelData, resultConsumer); diff --git a/src/main/java/com/jozufozu/flywheel/core/model/buffering/BlockModelBuilder.java b/src/main/java/com/jozufozu/flywheel/core/model/buffering/BlockModelBuilder.java index 022e948b9..f5d0c485e 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/buffering/BlockModelBuilder.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/buffering/BlockModelBuilder.java @@ -1,9 +1,11 @@ package com.jozufozu.flywheel.core.model.buffering; +import java.nio.ByteBuffer; import java.util.function.BiFunction; import com.google.common.collect.ImmutableMap; import com.jozufozu.flywheel.api.material.Material; +import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.core.model.Mesh; import com.jozufozu.flywheel.core.model.ModelUtil; import com.jozufozu.flywheel.core.model.SimpleMesh; @@ -12,13 +14,13 @@ import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.BufferFacto import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ResultConsumer; import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ShadeSeparatedBufferFactory; import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ShadeSeparatedResultConsumer; -import com.jozufozu.flywheel.core.vertex.Formats; import com.jozufozu.flywheel.core.virtual.VirtualEmptyBlockGetter; import com.jozufozu.flywheel.core.virtual.VirtualEmptyModelData; 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.datafixers.util.Pair; import net.minecraft.client.renderer.RenderType; import net.minecraft.world.level.BlockAndTintGetter; @@ -28,7 +30,6 @@ import net.minecraftforge.client.model.data.IModelData; public class BlockModelBuilder { private final BlockState state; private boolean shadeSeparated = true; - private VertexFormat vertexFormat; private BlockAndTintGetter renderWorld; private PoseStack poseStack; private IModelData modelData; @@ -43,11 +44,6 @@ public class BlockModelBuilder { return this; } - public BlockModelBuilder vertexFormat(VertexFormat vertexFormat) { - this.vertexFormat = vertexFormat; - return this; - } - public BlockModelBuilder renderWorld(BlockAndTintGetter renderWorld) { this.renderWorld = renderWorld; return this; @@ -72,9 +68,6 @@ public class BlockModelBuilder { public TessellatedModel build() { ModelBufferingObjects objects = ModelBufferingObjects.THREAD_LOCAL.get(); - if (vertexFormat == null) { - vertexFormat = DefaultVertexFormat.BLOCK; - } if (renderWorld == null) { renderWorld = VirtualEmptyBlockGetter.INSTANCE; } @@ -93,28 +86,30 @@ public class BlockModelBuilder { if (shadeSeparated) { ShadeSeparatedBufferFactory bufferFactory = (renderType, shaded) -> { BufferBuilder buffer = new BufferBuilder(64); - buffer.begin(VertexFormat.Mode.QUADS, vertexFormat); + buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK); return buffer; }; ShadeSeparatedResultConsumer resultConsumer = (renderType, shaded, buffer) -> { buffer.end(); Material material = materialFunc.apply(renderType, shaded); if (material != null) { - meshMapBuilder.put(material, new SimpleMesh(ModelUtil.createVertexList(buffer), Formats.BLOCK, "state=" + state.toString() + ",renderType=" + renderType.toString() + ",shaded=" + shaded)); + Pair pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer()); + meshMapBuilder.put(material, new SimpleMesh(pair.getFirst(), pair.getSecond(), "state=" + state.toString() + ",renderType=" + renderType.toString() + ",shaded=" + shaded)); } }; ModelBufferingUtil.bufferBlockShadeSeparated(ModelUtil.VANILLA_RENDERER, renderWorld, state, poseStack, bufferFactory, objects.shadeSeparatingBufferWrapper, objects.random, modelData, resultConsumer); } else { BufferFactory bufferFactory = (renderType) -> { BufferBuilder buffer = new BufferBuilder(64); - buffer.begin(VertexFormat.Mode.QUADS, vertexFormat); + buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK); return buffer; }; ResultConsumer resultConsumer = (renderType, buffer) -> { buffer.end(); Material material = materialFunc.apply(renderType, false); if (material != null) { - meshMapBuilder.put(material, new SimpleMesh(ModelUtil.createVertexList(buffer), Formats.BLOCK, "state=" + state.toString() + ",renderType=" + renderType.toString())); + Pair pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer()); + meshMapBuilder.put(material, new SimpleMesh(pair.getFirst(), pair.getSecond(), "state=" + state.toString() + ",renderType=" + renderType.toString())); } }; ModelBufferingUtil.bufferBlock(ModelUtil.VANILLA_RENDERER, renderWorld, state, poseStack, bufferFactory, objects.bufferWrapper, objects.random, modelData, resultConsumer); diff --git a/src/main/java/com/jozufozu/flywheel/core/model/buffering/MultiBlockModelBuilder.java b/src/main/java/com/jozufozu/flywheel/core/model/buffering/MultiBlockModelBuilder.java index 33acbcdab..c951acfbd 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/buffering/MultiBlockModelBuilder.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/buffering/MultiBlockModelBuilder.java @@ -1,5 +1,6 @@ package com.jozufozu.flywheel.core.model.buffering; +import java.nio.ByteBuffer; import java.util.Collection; import java.util.Collections; import java.util.Map; @@ -7,6 +8,7 @@ import java.util.function.BiFunction; import com.google.common.collect.ImmutableMap; import com.jozufozu.flywheel.api.material.Material; +import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.core.model.Mesh; import com.jozufozu.flywheel.core.model.ModelUtil; import com.jozufozu.flywheel.core.model.SimpleMesh; @@ -15,12 +17,12 @@ import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.BufferFacto import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ResultConsumer; import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ShadeSeparatedBufferFactory; import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ShadeSeparatedResultConsumer; -import com.jozufozu.flywheel.core.vertex.Formats; import com.jozufozu.flywheel.core.virtual.VirtualEmptyBlockGetter; 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.datafixers.util.Pair; import net.minecraft.client.renderer.RenderType; import net.minecraft.core.BlockPos; @@ -46,11 +48,6 @@ public class MultiBlockModelBuilder { return this; } - public MultiBlockModelBuilder vertexFormat(VertexFormat vertexFormat) { - this.vertexFormat = vertexFormat; - return this; - } - public MultiBlockModelBuilder renderWorld(BlockAndTintGetter renderWorld) { this.renderWorld = renderWorld; return this; @@ -96,28 +93,30 @@ public class MultiBlockModelBuilder { if (shadeSeparated) { ShadeSeparatedBufferFactory bufferFactory = (renderType, shaded) -> { BufferBuilder buffer = new BufferBuilder(1024); - buffer.begin(VertexFormat.Mode.QUADS, vertexFormat); + buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK); return buffer; }; ShadeSeparatedResultConsumer resultConsumer = (renderType, shaded, buffer) -> { buffer.end(); Material material = materialFunc.apply(renderType, shaded); if (material != null) { - meshMapBuilder.put(material, new SimpleMesh(ModelUtil.createVertexList(buffer), Formats.BLOCK, "renderType=" + renderType.toString() + ",shaded=" + shaded)); + Pair pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer()); + meshMapBuilder.put(material, new SimpleMesh(pair.getFirst(), pair.getSecond(), "renderType=" + renderType.toString() + ",shaded=" + shaded)); } }; ModelBufferingUtil.bufferMultiBlockShadeSeparated(blocks, ModelUtil.VANILLA_RENDERER, renderWorld, poseStack, bufferFactory, objects.shadeSeparatingBufferWrapper, objects.random, modelDataMap, resultConsumer); } else { BufferFactory bufferFactory = (renderType) -> { BufferBuilder buffer = new BufferBuilder(1024); - buffer.begin(VertexFormat.Mode.QUADS, vertexFormat); + buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK); return buffer; }; ResultConsumer resultConsumer = (renderType, buffer) -> { buffer.end(); Material material = materialFunc.apply(renderType, false); if (material != null) { - meshMapBuilder.put(material, new SimpleMesh(ModelUtil.createVertexList(buffer), Formats.BLOCK, "renderType=" + renderType.toString())); + Pair pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer()); + meshMapBuilder.put(material, new SimpleMesh(pair.getFirst(), pair.getSecond(), "renderType=" + renderType.toString())); } }; ModelBufferingUtil.bufferMultiBlock(blocks, ModelUtil.VANILLA_RENDERER, renderWorld, poseStack, bufferFactory, objects.bufferWrapper, objects.random, modelDataMap, resultConsumer); 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..d1524cac2 100644 --- a/src/main/java/com/jozufozu/flywheel/core/vertex/AbstractVertexList.java +++ b/src/main/java/com/jozufozu/flywheel/core/vertex/AbstractVertexList.java @@ -1,49 +1,28 @@ package com.jozufozu.flywheel.core.vertex; -import java.nio.Buffer; -import java.nio.ByteBuffer; +import com.jozufozu.flywheel.api.vertex.ReusableVertexList; -import org.lwjgl.system.MemoryUtil; - -import com.jozufozu.flywheel.api.vertex.VertexList; -import com.mojang.blaze3d.platform.MemoryTracker; -import com.mojang.blaze3d.vertex.BufferBuilder; - -public abstract class AbstractVertexList implements VertexList, AutoCloseable { - - 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.vertexCount = vertexCount; - this.base = MemoryUtil.memAddress(this.contents); - 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); - ((Buffer) this.contents).flip(); - } - - @Override - public void close() { - MemoryUtil.memFree(contents); - } +public abstract class AbstractVertexList implements ReusableVertexList { + protected long ptr; + protected int vertexCount; @Override public int getVertexCount() { return vertexCount; } + + @Override + public void setVertexCount(int vertexCount) { + this.vertexCount = vertexCount; + } + + @Override + public long ptr() { + return ptr; + } + + @Override + public void ptr(long ptr) { + this.ptr = ptr; + } } 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 9f37d06b8..e916d5ce3 100644 --- a/src/main/java/com/jozufozu/flywheel/core/vertex/BlockVertex.java +++ b/src/main/java/com/jozufozu/flywheel/core/vertex/BlockVertex.java @@ -1,7 +1,5 @@ package com.jozufozu.flywheel.core.vertex; -import java.nio.ByteBuffer; - import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.core.Components; import com.jozufozu.flywheel.core.layout.BufferLayout; @@ -9,7 +7,6 @@ import com.jozufozu.flywheel.core.layout.CommonItems; import com.jozufozu.flywheel.core.source.FileResolution; public class BlockVertex implements VertexType { - public static final BufferLayout FORMAT = BufferLayout.builder() .addItems(CommonItems.VEC3, CommonItems.RGBA, @@ -24,18 +21,13 @@ public class BlockVertex implements VertexType { return FORMAT; } - @Override - public BlockWriterUnsafe createWriter(ByteBuffer buffer) { - return new BlockWriterUnsafe(this, buffer); - } - - @Override - public BlockVertexListUnsafe createReader(ByteBuffer buffer, int vertexCount) { - return new BlockVertexListUnsafe(buffer, vertexCount); - } - @Override public FileResolution getLayoutShader() { return Components.Files.BLOCK_LAYOUT; } + + @Override + public BlockVertexList createVertexList() { + return new BlockVertexList(); + } } 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 a0423246a..ecfa8f277 100644 --- a/src/main/java/com/jozufozu/flywheel/core/vertex/BlockVertexList.java +++ b/src/main/java/com/jozufozu/flywheel/core/vertex/BlockVertexList.java @@ -1,72 +1,61 @@ package com.jozufozu.flywheel.core.vertex; +import org.lwjgl.system.MemoryUtil; + import com.jozufozu.flywheel.util.RenderMath; -import com.mojang.blaze3d.vertex.BufferBuilder; import net.minecraft.client.renderer.texture.OverlayTexture; public class BlockVertexList extends AbstractVertexList { + protected static final int STRIDE = 32; - private final int stride; - - public BlockVertexList(BufferBuilder builder) { - super(builder); - this.stride = builder.getVertexFormat() - .getVertexSize(); - } - - @Override - public boolean isEmpty() { - return vertexCount == 0; - } - - private int vertIdx(int vertexIndex) { - return vertexIndex * stride; + protected long idxPtr(int index) { + return ptr + index * STRIDE; } @Override public float x(int index) { - return contents.getFloat(vertIdx(index)); + return MemoryUtil.memGetFloat(idxPtr(index)); } @Override public float y(int index) { - return contents.getFloat(vertIdx(index) + 4); + return MemoryUtil.memGetFloat(idxPtr(index) + 4); } @Override public float z(int index) { - return contents.getFloat(vertIdx(index) + 8); + return MemoryUtil.memGetFloat(idxPtr(index) + 8); } @Override public byte r(int index) { - return contents.get(vertIdx(index) + 12); + return MemoryUtil.memGetByte(idxPtr(index) + 12); } @Override public byte g(int index) { - return contents.get(vertIdx(index) + 13); + return MemoryUtil.memGetByte(idxPtr(index) + 13); } @Override public byte b(int index) { - return contents.get(vertIdx(index) + 14); + return MemoryUtil.memGetByte(idxPtr(index) + 14); } @Override public byte a(int index) { - return contents.get(vertIdx(index) + 15); + return MemoryUtil.memGetByte(idxPtr(index) + 15); } @Override public float u(int index) { - return contents.getFloat(vertIdx(index) + 16); + return MemoryUtil.memGetFloat(idxPtr(index) + 16); } @Override public float v(int index) { - return contents.getFloat(vertIdx(index) + 20); + return MemoryUtil.memGetFloat(idxPtr(index) + 20); } @Override @@ -76,22 +65,95 @@ public class BlockVertexList extends AbstractVertexList { @Override public int light(int index) { - return contents.getInt(vertIdx(index) + 24); + return MemoryUtil.memGetInt(idxPtr(index) + 24) << 4; } @Override public float normalX(int index) { - return RenderMath.f(contents.get(vertIdx(index) + 28)); + return RenderMath.f(MemoryUtil.memGetByte(idxPtr(index) + 28)); } @Override public float normalY(int index) { - return RenderMath.f(contents.get(vertIdx(index) + 29)); + return RenderMath.f(MemoryUtil.memGetByte(idxPtr(index) + 29)); } @Override public float normalZ(int index) { - return RenderMath.f(contents.get(vertIdx(index) + 30)); + return RenderMath.f(MemoryUtil.memGetByte(idxPtr(index) + 30)); } + @Override + public void x(int index, float x) { + MemoryUtil.memPutFloat(idxPtr(index), x); + } + + @Override + public void y(int index, float y) { + MemoryUtil.memPutFloat(idxPtr(index) + 4, y); + } + + @Override + public void z(int index, float z) { + MemoryUtil.memPutFloat(idxPtr(index) + 8, z); + } + + @Override + public void r(int index, byte r) { + MemoryUtil.memPutByte(idxPtr(index) + 12, r); + } + + @Override + public void g(int index, byte g) { + MemoryUtil.memPutByte(idxPtr(index) + 13, g); + } + + @Override + public void b(int index, byte b) { + MemoryUtil.memPutByte(idxPtr(index) + 14, b); + } + + @Override + public void a(int index, byte a) { + MemoryUtil.memPutByte(idxPtr(index) + 15, a); + } + + @Override + public void u(int index, float u) { + MemoryUtil.memPutFloat(idxPtr(index) + 16, u); + } + + @Override + public void v(int index, float v) { + MemoryUtil.memPutFloat(idxPtr(index) + 20, v); + } + + @Override + public void overlay(int index, int overlay) { + } + + @Override + public void light(int index, int light) { + MemoryUtil.memPutInt(idxPtr(index) + 24, light >> 4); + } + + @Override + public void normalX(int index, float normalX) { + MemoryUtil.memPutByte(idxPtr(index) + 28, RenderMath.nb(normalX)); + } + + @Override + public void normalY(int index, float normalY) { + MemoryUtil.memPutByte(idxPtr(index) + 29, RenderMath.nb(normalY)); + } + + @Override + public void normalZ(int index, float normalZ) { + MemoryUtil.memPutByte(idxPtr(index) + 30, RenderMath.nb(normalZ)); + } + + @Override + public void shiftPtr(int vertices) { + ptr += vertices * STRIDE; + } } diff --git a/src/main/java/com/jozufozu/flywheel/core/vertex/BlockVertexListUnsafe.java b/src/main/java/com/jozufozu/flywheel/core/vertex/BlockVertexListUnsafe.java deleted file mode 100644 index 2b272f76e..000000000 --- a/src/main/java/com/jozufozu/flywheel/core/vertex/BlockVertexListUnsafe.java +++ /dev/null @@ -1,91 +0,0 @@ -package com.jozufozu.flywheel.core.vertex; - -import java.nio.ByteBuffer; - -import org.lwjgl.system.MemoryUtil; - -import com.jozufozu.flywheel.util.RenderMath; - -import net.minecraft.client.renderer.texture.OverlayTexture; - -public class BlockVertexListUnsafe extends AbstractVertexList { - - public BlockVertexListUnsafe(ByteBuffer copyFrom, int vertexCount) { - super(copyFrom, vertexCount); - } - - private long ptr(long index) { - return base + index * 32; - } - - @Override - public float x(int index) { - return MemoryUtil.memGetFloat(ptr(index)); - } - - @Override - public float y(int index) { - return MemoryUtil.memGetFloat(ptr(index) + 4); - } - - @Override - public float z(int index) { - return MemoryUtil.memGetFloat(ptr(index) + 8); - } - - @Override - public byte r(int index) { - return MemoryUtil.memGetByte(ptr(index) + 12); - } - - @Override - public byte g(int index) { - return MemoryUtil.memGetByte(ptr(index) + 13); - } - - @Override - public byte b(int index) { - return MemoryUtil.memGetByte(ptr(index) + 14); - } - - @Override - public byte a(int index) { - return MemoryUtil.memGetByte(ptr(index) + 15); - } - - @Override - public float u(int index) { - return MemoryUtil.memGetFloat(ptr(index) + 16); - } - - @Override - public float v(int index) { - return MemoryUtil.memGetFloat(ptr(index) + 20); - } - - @Override - public int overlay(int index) { - return OverlayTexture.NO_OVERLAY; - } - - @Override - public int light(int index) { - return MemoryUtil.memGetInt(ptr(index) + 24); - } - - @Override - public float normalX(int index) { - return RenderMath.f(MemoryUtil.memGetByte(ptr(index) + 28)); - } - - @Override - public float normalY(int index) { - return RenderMath.f(MemoryUtil.memGetByte(ptr(index) + 29)); - } - - @Override - public float normalZ(int index) { - return RenderMath.f(MemoryUtil.memGetByte(ptr(index) + 30)); - } - -} diff --git a/src/main/java/com/jozufozu/flywheel/core/vertex/BlockWriterUnsafe.java b/src/main/java/com/jozufozu/flywheel/core/vertex/BlockWriterUnsafe.java deleted file mode 100644 index 556e352d9..000000000 --- a/src/main/java/com/jozufozu/flywheel/core/vertex/BlockWriterUnsafe.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.jozufozu.flywheel.core.vertex; - -import java.nio.ByteBuffer; - -import org.lwjgl.system.MemoryUtil; - -import com.jozufozu.flywheel.api.vertex.VertexList; -import com.jozufozu.flywheel.util.RenderMath; - -public class BlockWriterUnsafe extends VertexWriterUnsafe { - - public BlockWriterUnsafe(BlockVertex type, ByteBuffer buffer) { - super(type, buffer); - } - - @Override - public void writeVertex(VertexList list, int i) { - float x = list.x(i); - float y = list.y(i); - float z = list.z(i); - - float xN = list.normalX(i); - float yN = list.normalY(i); - float zN = list.normalZ(i); - - float u = list.u(i); - float v = list.v(i); - - byte r = list.r(i); - byte g = list.g(i); - byte b = list.b(i); - byte a = list.a(i); - - int light = list.light(i); - - putVertex(x, y, z, u, v, r, g, b, a, light, xN, yN, zN); - } - - public void putVertex(float x, float y, float z, float u, float v, byte r, byte g, byte b, byte a, int light, float nX, float nY, float nZ) { - MemoryUtil.memPutFloat(ptr, x); - MemoryUtil.memPutFloat(ptr + 4, y); - MemoryUtil.memPutFloat(ptr + 8, z); - MemoryUtil.memPutByte(ptr + 12, r); - MemoryUtil.memPutByte(ptr + 13, g); - MemoryUtil.memPutByte(ptr + 14, b); - MemoryUtil.memPutByte(ptr + 15, a); - MemoryUtil.memPutFloat(ptr + 16, u); - MemoryUtil.memPutFloat(ptr + 20, v); - MemoryUtil.memPutInt(ptr + 24, (light >> 4) & 0xF000F); - MemoryUtil.memPutByte(ptr + 28, RenderMath.nb(nX)); - MemoryUtil.memPutByte(ptr + 29, RenderMath.nb(nY)); - MemoryUtil.memPutByte(ptr + 30, RenderMath.nb(nZ)); - - ptr += 32; - } -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/VertexFormatInfo.java b/src/main/java/com/jozufozu/flywheel/core/vertex/InferredVertexFormatInfo.java similarity index 88% rename from src/main/java/com/jozufozu/flywheel/backend/instancing/batching/VertexFormatInfo.java rename to src/main/java/com/jozufozu/flywheel/core/vertex/InferredVertexFormatInfo.java index 35f273508..c47cb837e 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/VertexFormatInfo.java +++ b/src/main/java/com/jozufozu/flywheel/core/vertex/InferredVertexFormatInfo.java @@ -1,9 +1,9 @@ -package com.jozufozu.flywheel.backend.instancing.batching; +package com.jozufozu.flywheel.core.vertex; import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.blaze3d.vertex.VertexFormatElement; -public class VertexFormatInfo { +public class InferredVertexFormatInfo { public final VertexFormat format; public final int stride; @@ -14,7 +14,7 @@ public class VertexFormatInfo { public final int lightOffset; public final int normalOffset; - public VertexFormatInfo(VertexFormat format) { + public InferredVertexFormatInfo(VertexFormat format) { this.format = format; stride = format.getVertexSize(); @@ -51,7 +51,7 @@ public class VertexFormatInfo { this.normalOffset = normalOffset; } - protected VertexFormatInfo(VertexFormatInfo formatInfo) { + protected InferredVertexFormatInfo(InferredVertexFormatInfo formatInfo) { format = formatInfo.format; stride = formatInfo.stride; positionOffset = formatInfo.positionOffset; diff --git a/src/main/java/com/jozufozu/flywheel/core/vertex/InferredVertexListImpl.java b/src/main/java/com/jozufozu/flywheel/core/vertex/InferredVertexListImpl.java new file mode 100644 index 000000000..c074e37bf --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/core/vertex/InferredVertexListImpl.java @@ -0,0 +1,214 @@ +package com.jozufozu.flywheel.core.vertex; + +import org.lwjgl.system.MemoryUtil; + +import com.jozufozu.flywheel.api.vertex.ReusableVertexList; +import com.jozufozu.flywheel.util.RenderMath; + +import net.minecraft.client.renderer.texture.OverlayTexture; + +public final class InferredVertexListImpl extends InferredVertexFormatInfo implements ReusableVertexList { + private long ptr; + private int vertexCount; + + public InferredVertexListImpl(InferredVertexFormatInfo formatInfo) { + super(formatInfo); + } + + private long idxPtr(int index) { + return ptr + index * stride; + } + + @Override + public float x(int index) { + if (positionOffset < 0) return 0; + return MemoryUtil.memGetFloat(idxPtr(index) + positionOffset); + } + + @Override + public float y(int index) { + if (positionOffset < 0) return 0; + return MemoryUtil.memGetFloat(idxPtr(index) + positionOffset + 4); + } + + @Override + public float z(int index) { + if (positionOffset < 0) return 0; + return MemoryUtil.memGetFloat(idxPtr(index) + positionOffset + 8); + } + + @Override + public byte r(int index) { + if (colorOffset < 0) return 0; + return MemoryUtil.memGetByte(idxPtr(index) + colorOffset); + } + + @Override + public byte g(int index) { + if (colorOffset < 0) return 0; + return MemoryUtil.memGetByte(idxPtr(index) + colorOffset + 1); + } + + @Override + public byte b(int index) { + if (colorOffset < 0) return 0; + return MemoryUtil.memGetByte(idxPtr(index) + colorOffset + 2); + } + + @Override + public byte a(int index) { + if (colorOffset < 0) return 0; + return MemoryUtil.memGetByte(idxPtr(index) + colorOffset + 3); + } + + @Override + public float u(int index) { + if (textureOffset < 0) return 0; + return MemoryUtil.memGetFloat(idxPtr(index) + textureOffset); + } + + @Override + public float v(int index) { + if (textureOffset < 0) return 0; + return MemoryUtil.memGetFloat(idxPtr(index) + textureOffset + 4); + } + + @Override + public int overlay(int index) { + if (overlayOffset < 0) return OverlayTexture.NO_OVERLAY; + return MemoryUtil.memGetInt(idxPtr(index) + overlayOffset); + } + + @Override + public int light(int index) { + if (lightOffset < 0) return 0; + return MemoryUtil.memGetInt(idxPtr(index) + lightOffset); + } + + @Override + public float normalX(int index) { + if (normalOffset < 0) return 0; + return RenderMath.f(MemoryUtil.memGetByte(idxPtr(index) + normalOffset)); + } + + @Override + public float normalY(int index) { + if (normalOffset < 0) return 0; + return RenderMath.f(MemoryUtil.memGetByte(idxPtr(index) + normalOffset + 1)); + } + + @Override + public float normalZ(int index) { + if (normalOffset < 0) return 0; + return RenderMath.f(MemoryUtil.memGetByte(idxPtr(index) + normalOffset + 2)); + } + + @Override + public void x(int index, float x) { + if (positionOffset < 0) return; + MemoryUtil.memPutFloat(idxPtr(index) + positionOffset, x); + } + + @Override + public void y(int index, float y) { + if (positionOffset < 0) return; + MemoryUtil.memPutFloat(idxPtr(index) + positionOffset + 4, y); + } + + @Override + public void z(int index, float z) { + if (positionOffset < 0) return; + MemoryUtil.memPutFloat(idxPtr(index) + positionOffset + 8, z); + } + + @Override + public void r(int index, byte r) { + if (colorOffset < 0) return; + MemoryUtil.memPutByte(idxPtr(index) + colorOffset, r); + } + + @Override + public void g(int index, byte g) { + if (colorOffset < 0) return; + MemoryUtil.memPutByte(idxPtr(index) + colorOffset + 1, g); + } + + @Override + public void b(int index, byte b) { + if (colorOffset < 0) return; + MemoryUtil.memPutByte(idxPtr(index) + colorOffset + 2, b); + } + + @Override + public void a(int index, byte a) { + if (colorOffset < 0) return; + MemoryUtil.memPutByte(idxPtr(index) + colorOffset + 3, a); + } + + @Override + public void u(int index, float u) { + if (textureOffset < 0) return; + MemoryUtil.memPutFloat(idxPtr(index) + textureOffset, u); + } + + @Override + public void v(int index, float v) { + if (textureOffset < 0) return; + MemoryUtil.memPutFloat(idxPtr(index) + textureOffset + 4, v); + } + + @Override + public void overlay(int index, int overlay) { + if (overlayOffset < 0) return; + MemoryUtil.memPutInt(idxPtr(index) + overlayOffset, overlay); + } + + @Override + public void light(int index, int light) { + if (lightOffset < 0) return; + MemoryUtil.memPutInt(idxPtr(index) + lightOffset, light); + } + + @Override + public void normalX(int index, float normalX) { + if (normalOffset < 0) return; + MemoryUtil.memPutByte(idxPtr(index) + normalOffset, RenderMath.nb(normalX)); + } + + @Override + public void normalY(int index, float normalY) { + if (normalOffset < 0) return; + MemoryUtil.memPutByte(idxPtr(index) + normalOffset + 1, RenderMath.nb(normalY)); + } + + @Override + public void normalZ(int index, float normalZ) { + if (normalOffset < 0) return; + MemoryUtil.memPutByte(idxPtr(index) + normalOffset + 2, RenderMath.nb(normalZ)); + } + + @Override + public int getVertexCount() { + return vertexCount; + } + + @Override + public long ptr() { + return ptr; + } + + @Override + public void ptr(long ptr) { + this.ptr = ptr; + } + + @Override + public void shiftPtr(int vertices) { + ptr += vertices * stride; + } + + @Override + public void setVertexCount(int vertexCount) { + this.vertexCount = vertexCount; + } +} diff --git a/src/main/java/com/jozufozu/flywheel/core/vertex/InferredVertexListProviderImpl.java b/src/main/java/com/jozufozu/flywheel/core/vertex/InferredVertexListProviderImpl.java new file mode 100644 index 000000000..fd976aa6b --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/core/vertex/InferredVertexListProviderImpl.java @@ -0,0 +1,20 @@ +package com.jozufozu.flywheel.core.vertex; + +import com.jozufozu.flywheel.api.vertex.ReusableVertexList; +import com.jozufozu.flywheel.api.vertex.VertexListProvider; +import com.mojang.blaze3d.vertex.VertexFormat; + +public class InferredVertexListProviderImpl implements VertexListProvider { + private final VertexFormat format; + private final InferredVertexFormatInfo formatInfo; + + public InferredVertexListProviderImpl(VertexFormat format) { + this.format = format; + formatInfo = new InferredVertexFormatInfo(format); + } + + @Override + public ReusableVertexList createVertexList() { + return new InferredVertexListImpl(formatInfo); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/core/vertex/PosTexNormalVertex.java b/src/main/java/com/jozufozu/flywheel/core/vertex/PosTexNormalVertex.java index 2c115041c..131bfc6e6 100644 --- a/src/main/java/com/jozufozu/flywheel/core/vertex/PosTexNormalVertex.java +++ b/src/main/java/com/jozufozu/flywheel/core/vertex/PosTexNormalVertex.java @@ -1,7 +1,5 @@ package com.jozufozu.flywheel.core.vertex; -import java.nio.ByteBuffer; - import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.core.Components; import com.jozufozu.flywheel.core.layout.BufferLayout; @@ -9,7 +7,6 @@ import com.jozufozu.flywheel.core.layout.CommonItems; import com.jozufozu.flywheel.core.source.FileResolution; public class PosTexNormalVertex implements VertexType { - public static final BufferLayout FORMAT = BufferLayout.builder() .addItems(CommonItems.VEC3, CommonItems.UV, CommonItems.NORMAL) .build(); @@ -19,18 +16,13 @@ public class PosTexNormalVertex implements VertexType { return FORMAT; } - @Override - public PosTexNormalWriterUnsafe createWriter(ByteBuffer buffer) { - return new PosTexNormalWriterUnsafe(this, buffer); - } - - @Override - public PosTexNormalVertexListUnsafe createReader(ByteBuffer buffer, int vertexCount) { - return new PosTexNormalVertexListUnsafe(buffer, vertexCount); - } - @Override public FileResolution getLayoutShader() { return Components.Files.POS_TEX_NORMAL_LAYOUT; } + + @Override + public PosTexNormalVertexList createVertexList() { + return new PosTexNormalVertexList(); + } } diff --git a/src/main/java/com/jozufozu/flywheel/core/vertex/PosTexNormalVertexList.java b/src/main/java/com/jozufozu/flywheel/core/vertex/PosTexNormalVertexList.java new file mode 100644 index 000000000..4ac841c04 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/core/vertex/PosTexNormalVertexList.java @@ -0,0 +1,154 @@ +package com.jozufozu.flywheel.core.vertex; + +import org.lwjgl.system.MemoryUtil; + +import com.jozufozu.flywheel.util.RenderMath; + +import net.minecraft.client.renderer.texture.OverlayTexture; + +public class PosTexNormalVertexList extends AbstractVertexList { + protected static final int STRIDE = 23; + + protected long idxPtr(long idx) { + return ptr + idx * STRIDE; + } + + @Override + public float x(int index) { + return MemoryUtil.memGetFloat(idxPtr(index)); + } + + @Override + public float y(int index) { + return MemoryUtil.memGetFloat(idxPtr(index) + 4); + } + + @Override + public float z(int index) { + return MemoryUtil.memGetFloat(idxPtr(index) + 8); + } + + @Override + public byte r(int index) { + return (byte) 0xFF; + } + + @Override + public byte g(int index) { + return (byte) 0xFF; + } + + @Override + public byte b(int index) { + return (byte) 0xFF; + } + + @Override + public byte a(int index) { + return (byte) 0xFF; + } + + @Override + public float u(int index) { + return MemoryUtil.memGetFloat(idxPtr(index) + 12); + } + + @Override + public float v(int index) { + return MemoryUtil.memGetFloat(idxPtr(index) + 16); + } + + @Override + public int overlay(int index) { + return OverlayTexture.NO_OVERLAY; + } + + @Override + public int light(int index) { + return 0; + } + + @Override + public float normalX(int index) { + return RenderMath.f(MemoryUtil.memGetByte(idxPtr(index) + 20)); + } + + @Override + public float normalY(int index) { + return RenderMath.f(MemoryUtil.memGetByte(idxPtr(index) + 21)); + } + + @Override + public float normalZ(int index) { + return RenderMath.f(MemoryUtil.memGetByte(idxPtr(index) + 22)); + } + + @Override + public void x(int index, float x) { + MemoryUtil.memPutFloat(idxPtr(index), x); + } + + @Override + public void y(int index, float y) { + MemoryUtil.memPutFloat(idxPtr(index) + 4, y); + } + + @Override + public void z(int index, float z) { + MemoryUtil.memPutFloat(idxPtr(index) + 8, z); + } + + @Override + public void r(int index, byte r) { + } + + @Override + public void g(int index, byte g) { + } + + @Override + public void b(int index, byte b) { + } + + @Override + public void a(int index, byte a) { + } + + @Override + public void u(int index, float u) { + MemoryUtil.memPutFloat(idxPtr(index) + 12, u); + } + + @Override + public void v(int index, float v) { + MemoryUtil.memPutFloat(idxPtr(index) + 16, v); + } + + @Override + public void overlay(int index, int overlay) { + } + + @Override + public void light(int index, int light) { + } + + @Override + public void normalX(int index, float normalX) { + MemoryUtil.memPutByte(idxPtr(index) + 20, RenderMath.nb(normalX)); + } + + @Override + public void normalY(int index, float normalY) { + MemoryUtil.memPutByte(idxPtr(index) + 21, RenderMath.nb(normalY)); + } + + @Override + public void normalZ(int index, float normalZ) { + MemoryUtil.memPutByte(idxPtr(index) + 22, RenderMath.nb(normalZ)); + } + + @Override + public void shiftPtr(int vertices) { + ptr += vertices * STRIDE; + } +} diff --git a/src/main/java/com/jozufozu/flywheel/core/vertex/PosTexNormalVertexListUnsafe.java b/src/main/java/com/jozufozu/flywheel/core/vertex/PosTexNormalVertexListUnsafe.java deleted file mode 100644 index df1091a97..000000000 --- a/src/main/java/com/jozufozu/flywheel/core/vertex/PosTexNormalVertexListUnsafe.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.jozufozu.flywheel.core.vertex; - -import java.nio.ByteBuffer; - -import org.lwjgl.system.MemoryUtil; - -import com.jozufozu.flywheel.util.RenderMath; - -import net.minecraft.client.renderer.texture.OverlayTexture; - -public class PosTexNormalVertexListUnsafe extends AbstractVertexList { - - public PosTexNormalVertexListUnsafe(ByteBuffer copyFrom, int vertexCount) { - super(copyFrom, vertexCount); - } - - private long ptr(long idx) { - return base + idx * 23; - } - - @Override - public float x(int index) { - return MemoryUtil.memGetFloat(ptr(index)); - } - - @Override - public float y(int index) { - return MemoryUtil.memGetFloat(ptr(index) + 4); - } - - @Override - public float z(int index) { - return MemoryUtil.memGetFloat(ptr(index) + 8); - } - - @Override - public byte r(int index) { - return (byte) 0xFF; - } - - @Override - public byte g(int index) { - return (byte) 0xFF; - } - - @Override - public byte b(int index) { - return (byte) 0xFF; - } - - @Override - public byte a(int index) { - return (byte) 0xFF; - } - - @Override - public float u(int index) { - return MemoryUtil.memGetFloat(ptr(index) + 12); - } - - @Override - public float v(int index) { - return MemoryUtil.memGetFloat(ptr(index) + 16); - } - - @Override - public int overlay(int index) { - return OverlayTexture.NO_OVERLAY; - } - - @Override - public int light(int index) { - return 0; - } - - @Override - public float normalX(int index) { - return RenderMath.f(MemoryUtil.memGetByte(ptr(index) + 20)); - } - - @Override - public float normalY(int index) { - return RenderMath.f(MemoryUtil.memGetByte(ptr(index) + 21)); - } - - @Override - public float normalZ(int index) { - return RenderMath.f(MemoryUtil.memGetByte(ptr(index) + 22)); - } -} diff --git a/src/main/java/com/jozufozu/flywheel/core/vertex/PosTexNormalWriterUnsafe.java b/src/main/java/com/jozufozu/flywheel/core/vertex/PosTexNormalWriterUnsafe.java deleted file mode 100644 index 7e97962bc..000000000 --- a/src/main/java/com/jozufozu/flywheel/core/vertex/PosTexNormalWriterUnsafe.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.jozufozu.flywheel.core.vertex; - -import java.nio.ByteBuffer; - -import org.lwjgl.system.MemoryUtil; - -import com.jozufozu.flywheel.api.vertex.VertexList; -import com.jozufozu.flywheel.util.RenderMath; - -public class PosTexNormalWriterUnsafe extends VertexWriterUnsafe { - - public PosTexNormalWriterUnsafe(PosTexNormalVertex type, ByteBuffer buffer) { - super(type, buffer); - } - - @Override - public void writeVertex(VertexList list, int i) { - float x = list.x(i); - float y = list.y(i); - float z = list.z(i); - - float u = list.u(i); - float v = list.v(i); - - float xN = list.normalX(i); - float yN = list.normalY(i); - float zN = list.normalZ(i); - - putVertex(x, y, z, xN, yN, zN, u, v); - } - - public void putVertex(float x, float y, float z, float nX, float nY, float nZ, float u, float v) { - MemoryUtil.memPutFloat(ptr, x); - MemoryUtil.memPutFloat(ptr + 4, y); - MemoryUtil.memPutFloat(ptr + 8, z); - MemoryUtil.memPutFloat(ptr + 12, u); - MemoryUtil.memPutFloat(ptr + 16, v); - MemoryUtil.memPutByte(ptr + 20, RenderMath.nb(nX)); - MemoryUtil.memPutByte(ptr + 21, RenderMath.nb(nY)); - MemoryUtil.memPutByte(ptr + 22, RenderMath.nb(nZ)); - - ptr += 23; - } -} diff --git a/src/main/java/com/jozufozu/flywheel/core/vertex/TrackedVertexList.java b/src/main/java/com/jozufozu/flywheel/core/vertex/TrackedVertexList.java deleted file mode 100644 index 00cb24eec..000000000 --- a/src/main/java/com/jozufozu/flywheel/core/vertex/TrackedVertexList.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.jozufozu.flywheel.core.vertex; - -import java.lang.ref.Cleaner; -import java.nio.Buffer; -import java.nio.ByteBuffer; - -import org.lwjgl.system.MemoryUtil; - -import com.jozufozu.flywheel.api.vertex.VertexList; -import com.jozufozu.flywheel.backend.FlywheelMemory; -import com.mojang.blaze3d.platform.MemoryTracker; - -public abstract class TrackedVertexList implements VertexList, AutoCloseable { - - protected final ByteBuffer contents; - protected final long base; - protected final int vertexCount; - private final Cleaner.Cleanable cleanable; - - protected TrackedVertexList(ByteBuffer copyFrom, int vertexCount) { - this.contents = MemoryTracker.create(copyFrom.capacity()); - this.contents.order(copyFrom.order()); - this.contents.put(copyFrom); - ((Buffer) this.contents).flip(); - - this.cleanable = FlywheelMemory.track(this, this.contents); - - this.base = MemoryUtil.memAddress(this.contents); - this.vertexCount = vertexCount; - } - - @Override - public void close() { - cleanable.clean(); - } - - @Override - public int getVertexCount() { - return vertexCount; - } -} diff --git a/src/main/java/com/jozufozu/flywheel/core/vertex/VertexListProviderRegistry.java b/src/main/java/com/jozufozu/flywheel/core/vertex/VertexListProviderRegistry.java new file mode 100644 index 000000000..3a597d8db --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/core/vertex/VertexListProviderRegistry.java @@ -0,0 +1,55 @@ +package com.jozufozu.flywheel.core.vertex; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.jetbrains.annotations.Nullable; + +import com.jozufozu.flywheel.api.vertex.VertexListProvider; +import com.mojang.blaze3d.vertex.VertexFormat; + +public class VertexListProviderRegistry { + private static final Map HOLDERS = new ConcurrentHashMap<>(); + + private static Holder getOrCreateHolder(VertexFormat format) { + return HOLDERS.computeIfAbsent(format, Holder::new); + } + + public static void register(VertexFormat format, VertexListProvider provider) { + getOrCreateHolder(format).registeredProvider = provider; + } + + @Nullable + public static VertexListProvider get(VertexFormat format) { + return getOrCreateHolder(format).get(); + } + + public static VertexListProvider getOrInfer(VertexFormat format) { + return getOrCreateHolder(format).getOrInfer(); + } + + private static class Holder { + public final VertexFormat format; + public VertexListProvider registeredProvider; + public VertexListProvider inferredProvider; + + public Holder(VertexFormat format) { + this.format = format; + } + + @Nullable + public VertexListProvider get() { + return registeredProvider; + } + + public VertexListProvider getOrInfer() { + if (registeredProvider != null) { + return registeredProvider; + } + if (inferredProvider == null) { + inferredProvider = new InferredVertexListProviderImpl(format); + } + return inferredProvider; + } + } +} diff --git a/src/main/java/com/jozufozu/flywheel/core/vertex/VertexWriterUnsafe.java b/src/main/java/com/jozufozu/flywheel/core/vertex/VertexWriterUnsafe.java deleted file mode 100644 index f4f31c7d0..000000000 --- a/src/main/java/com/jozufozu/flywheel/core/vertex/VertexWriterUnsafe.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.jozufozu.flywheel.core.vertex; - -import java.nio.ByteBuffer; - -import org.lwjgl.system.MemoryUtil; - -import com.jozufozu.flywheel.api.vertex.VertexList; -import com.jozufozu.flywheel.api.vertex.VertexType; -import com.jozufozu.flywheel.api.vertex.VertexWriter; - -public abstract class VertexWriterUnsafe implements VertexWriter { - - public final V type; - protected final ByteBuffer buffer; - protected long ptr; - - protected VertexWriterUnsafe(V type, ByteBuffer buffer) { - this.type = type; - this.buffer = buffer; - this.ptr = MemoryUtil.memAddress(buffer); - } - - @Override - public void seek(long offset) { - buffer.position((int) offset); - ptr = MemoryUtil.memAddress(buffer); - } - - @Override - public VertexList intoReader(int vertices) { - return type.createReader(buffer, vertices); - } -} From f0823af00f109158efcde7bbe267ae1917f4bb0d Mon Sep 17 00:00:00 2001 From: PepperCode1 <44146161+PepperCode1@users.noreply.github.com> Date: Wed, 10 Aug 2022 20:47:53 -0700 Subject: [PATCH 2/5] Wait, it's all unsafe? Always has been. - Create MemoryBlock utility for easier management of memory allocation - Replace most usage of direct ByteBuffer with MemoryBlock - Remove all usage of Mojang's MemoryTracker - Simplifier StructWriter - Rename some classes and packages --- .../flywheel/api/struct/StructType.java | 11 +- .../flywheel/api/struct/StructWriter.java | 14 +- .../flywheel/backend/FlywheelMemory.java | 57 ------- .../backend/gl/versioned/GlCompat.java | 14 +- .../instancing/batching/DrawBuffer.java | 35 +++-- .../instancing/batching/TransformSet.java | 6 +- .../blockentity/BlockEntityInstance.java | 2 +- .../instancing/instancing/GPUInstancer.java | 16 +- .../instancing/instancing/MeshPool.java | 5 +- .../backend/memory/FlwMemoryTracker.java | 141 ++++++++++++++++++ .../flywheel/backend/memory/MemoryBlock.java | 45 ++++++ .../backend/memory/MemoryBlockImpl.java | 76 ++++++++++ .../memory/TrackedMemoryBlockImpl.java | 38 +++++ .../flywheel/backend/struct/BufferWriter.java | 40 ----- .../backend/struct/UnsafeBufferWriter.java | 45 ------ .../flywheel/backend/struct/package-info.java | 6 - .../flywheel/core/hardcoded/ModelPart.java | 20 +-- .../jozufozu/flywheel/core/model/Mesh.java | 6 +- .../flywheel/core/model/ModelUtil.java | 8 +- .../flywheel/core/model/SimpleMesh.java | 25 ++-- .../model/buffering/BakedModelBuilder.java | 6 +- .../model/buffering/BlockModelBuilder.java | 6 +- .../buffering/MultiBlockModelBuilder.java | 6 +- .../core/structs/ColoredLitWriter.java | 17 +++ .../core/structs/ColoredLitWriterUnsafe.java | 26 ---- .../flywheel/core/structs/StructTypes.java | 4 +- .../model/TransformedWriterUnsafe.java | 23 --- .../core/structs/oriented/OrientedType.java | 8 +- ...dWriterUnsafe.java => OrientedWriter.java} | 16 +- .../TransformedPart.java | 2 +- .../TransformedType.java | 10 +- .../transformed/TransformedWriter.java | 17 +++ .../{model => transformed}/package-info.java | 2 +- .../flywheel/core/uniform/FogProvider.java | 2 - .../flywheel/core/uniform/UniformBuffer.java | 4 +- .../jozufozu/flywheel/event/ForgeEvents.java | 7 +- .../jozufozu/flywheel/light/LightVolume.java | 9 +- .../jozufozu/flywheel/util/StringUtil.java | 12 +- .../flywheel/vanilla/ChestInstance.java | 2 +- .../flywheel/vanilla/MinecartInstance.java | 2 +- .../flywheel/vanilla/ShulkerBoxInstance.java | 2 +- .../vanilla/effect/ExampleEffect.java | 2 +- 42 files changed, 445 insertions(+), 350 deletions(-) delete mode 100644 src/main/java/com/jozufozu/flywheel/backend/FlywheelMemory.java create mode 100644 src/main/java/com/jozufozu/flywheel/backend/memory/FlwMemoryTracker.java create mode 100644 src/main/java/com/jozufozu/flywheel/backend/memory/MemoryBlock.java create mode 100644 src/main/java/com/jozufozu/flywheel/backend/memory/MemoryBlockImpl.java create mode 100644 src/main/java/com/jozufozu/flywheel/backend/memory/TrackedMemoryBlockImpl.java delete mode 100644 src/main/java/com/jozufozu/flywheel/backend/struct/BufferWriter.java delete mode 100644 src/main/java/com/jozufozu/flywheel/backend/struct/UnsafeBufferWriter.java delete mode 100644 src/main/java/com/jozufozu/flywheel/backend/struct/package-info.java create mode 100644 src/main/java/com/jozufozu/flywheel/core/structs/ColoredLitWriter.java delete mode 100644 src/main/java/com/jozufozu/flywheel/core/structs/ColoredLitWriterUnsafe.java delete mode 100644 src/main/java/com/jozufozu/flywheel/core/structs/model/TransformedWriterUnsafe.java rename src/main/java/com/jozufozu/flywheel/core/structs/oriented/{OrientedWriterUnsafe.java => OrientedWriter.java} (54%) rename src/main/java/com/jozufozu/flywheel/core/structs/{model => transformed}/TransformedPart.java (97%) rename src/main/java/com/jozufozu/flywheel/core/structs/{model => transformed}/TransformedType.java (86%) create mode 100644 src/main/java/com/jozufozu/flywheel/core/structs/transformed/TransformedWriter.java rename src/main/java/com/jozufozu/flywheel/core/structs/{model => transformed}/package-info.java (75%) diff --git a/src/main/java/com/jozufozu/flywheel/api/struct/StructType.java b/src/main/java/com/jozufozu/flywheel/api/struct/StructType.java index 7841f92de..7bdeab3a0 100644 --- a/src/main/java/com/jozufozu/flywheel/api/struct/StructType.java +++ b/src/main/java/com/jozufozu/flywheel/api/struct/StructType.java @@ -1,7 +1,5 @@ package com.jozufozu.flywheel.api.struct; -import java.nio.ByteBuffer; - import com.jozufozu.flywheel.api.instancer.InstancedPart; import com.jozufozu.flywheel.api.vertex.MutableVertexList; import com.jozufozu.flywheel.core.layout.BufferLayout; @@ -25,16 +23,11 @@ public interface StructType { */ BufferLayout getLayout(); - /** - * Create a {@link StructWriter} that will consume instances of S and write them to the given buffer. - * - * @param backing The buffer that the StructWriter will write to. - */ - StructWriter getWriter(ByteBuffer backing); + StructWriter getWriter(); FileResolution getInstanceShader(); - VertexTransformer getVertexTransformer(); + VertexTransformer getVertexTransformer(); public interface VertexTransformer { void transform(MutableVertexList vertexList, S struct, ClientLevel level); diff --git a/src/main/java/com/jozufozu/flywheel/api/struct/StructWriter.java b/src/main/java/com/jozufozu/flywheel/api/struct/StructWriter.java index abebee807..beb89d025 100644 --- a/src/main/java/com/jozufozu/flywheel/api/struct/StructWriter.java +++ b/src/main/java/com/jozufozu/flywheel/api/struct/StructWriter.java @@ -1,17 +1,13 @@ package com.jozufozu.flywheel.api.struct; +import com.jozufozu.flywheel.api.instancer.InstancedPart; + /** * StructWriters can quickly consume many instances of S and write them to some backing buffer. */ -public interface StructWriter { - +public interface StructWriter { /** - * Write the given struct to the backing array. + * Write the given struct to given memory address. */ - void write(S struct); - - /** - * Seek to the given position. The next write will occur there. - */ - void seek(int pos); + void write(long ptr, S struct); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/FlywheelMemory.java b/src/main/java/com/jozufozu/flywheel/backend/FlywheelMemory.java deleted file mode 100644 index 3d3f8bd60..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/FlywheelMemory.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.jozufozu.flywheel.backend; - -import java.lang.ref.Cleaner; -import java.nio.ByteBuffer; - -import org.lwjgl.system.MemoryUtil; - -public class FlywheelMemory { - - public static final Cleaner CLEANER = Cleaner.create(); - - private static int gpuMemory = 0; - private static int cpuMemory = 0; - - public static void _freeCPUMemory(long size) { - cpuMemory -= size; - } - - public static void _allocCPUMemory(long size) { - cpuMemory += size; - } - - public static void _freeGPUMemory(long size) { - gpuMemory -= size; - } - - public static void _allocGPUMemory(long size) { - gpuMemory += size; - } - - public static int getGPUMemory() { - return gpuMemory; - } - - public static int getCPUMemory() { - return cpuMemory; - } - - public static Cleaner.Cleanable track(Object owner, ByteBuffer buffer) { - return CLEANER.register(owner, new Tracked(buffer)); - } - - public static class Tracked implements Runnable { - - private final ByteBuffer buffer; - - public Tracked(ByteBuffer buffer) { - this.buffer = buffer; - _allocCPUMemory(buffer.capacity()); - } - - public void run() { - _freeCPUMemory(buffer.capacity()); - MemoryUtil.memFree(buffer); - } - } -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/versioned/GlCompat.java b/src/main/java/com/jozufozu/flywheel/backend/gl/versioned/GlCompat.java index 059dd15b1..97a9f6850 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/versioned/GlCompat.java +++ b/src/main/java/com/jozufozu/flywheel/backend/gl/versioned/GlCompat.java @@ -8,7 +8,6 @@ import org.lwjgl.opengl.GL; import org.lwjgl.opengl.GL20C; import org.lwjgl.opengl.GLCapabilities; import org.lwjgl.system.MemoryStack; -import org.lwjgl.system.MemoryUtil; import net.minecraft.Util; @@ -75,7 +74,7 @@ public class GlCompat { } /** - * Copied from: + * Modified from: *
canvas * *

Identical in function to {@link GL20C#glShaderSource(int, CharSequence)} but @@ -87,18 +86,11 @@ public class GlCompat { *

Hat tip to fewizz for the find and the fix. */ public static void safeShaderSource(int glId, CharSequence source) { - final MemoryStack stack = MemoryStack.stackGet(); - final int stackPointer = stack.getPointer(); - - try { - final ByteBuffer sourceBuffer = MemoryUtil.memUTF8(source, true); + try (MemoryStack stack = MemoryStack.stackPush()) { + final ByteBuffer sourceBuffer = stack.UTF8(source, true); final PointerBuffer pointers = stack.mallocPointer(1); pointers.put(sourceBuffer); - GL20C.nglShaderSource(glId, 1, pointers.address0(), 0); - org.lwjgl.system.APIUtil.apiArrayFree(pointers.address0(), 1); - } finally { - stack.setPointer(stackPointer); } } 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 50a099bae..8559680ea 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 @@ -2,12 +2,10 @@ package com.jozufozu.flywheel.backend.instancing.batching; import java.nio.ByteBuffer; -import org.lwjgl.system.MemoryUtil; - 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.vertex.VertexListProviderRegistry; -import com.mojang.blaze3d.platform.MemoryTracker; import com.mojang.blaze3d.vertex.VertexFormat; import net.minecraft.client.renderer.RenderType; @@ -23,9 +21,10 @@ public class DrawBuffer { private final int stride; private final VertexListProvider provider; - private ByteBuffer backingBuffer; + private MemoryBlock memory; + private ByteBuffer buffer; + private int expectedVertices; - private long ptr; public DrawBuffer(RenderType parent) { this.parent = parent; @@ -41,7 +40,7 @@ public class DrawBuffer { */ public void prepare(int vertexCount) { if (expectedVertices != 0) { - throw new IllegalStateException("Already drawing"); + throw new IllegalStateException("Already drawing!"); } this.expectedVertices = vertexCount; @@ -51,20 +50,20 @@ public class DrawBuffer { // is called and reallocates the buffer if there is not space for one more vertex. int byteSize = stride * (vertexCount + 1); - if (backingBuffer == null) { - backingBuffer = MemoryTracker.create(byteSize); - } else if (byteSize > backingBuffer.capacity()) { - backingBuffer = MemoryTracker.resize(backingBuffer, byteSize); + if (memory == null) { + memory = MemoryBlock.malloc(byteSize); + buffer = memory.asBuffer(); + } else if (byteSize > memory.size()) { + memory = memory.realloc(byteSize); + buffer = memory.asBuffer(); } - backingBuffer.clear(); - ptr = MemoryUtil.memAddress(backingBuffer); - MemoryUtil.memSet(ptr, 0, byteSize); + memory.clear(); } public ReusableVertexList slice(int startVertex, int vertexCount) { ReusableVertexList vertexList = provider.createVertexList(); - vertexList.ptr(ptr + startVertex * stride); + vertexList.ptr(memory.ptr() + startVertex * stride); vertexList.setVertexCount(vertexCount); return vertexList; } @@ -74,7 +73,8 @@ public class DrawBuffer { * @param bufferBuilder The buffer builder to inject into. */ public void inject(BufferBuilderExtension bufferBuilder) { - bufferBuilder.flywheel$injectForRender(backingBuffer, format, expectedVertices); + buffer.clear(); + bufferBuilder.flywheel$injectForRender(buffer, format, expectedVertices); } public int getVertexCount() { @@ -96,4 +96,9 @@ public class DrawBuffer { public void reset() { this.expectedVertices = 0; } + + public void free() { + buffer = null; + memory.free(); + } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/TransformSet.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/TransformSet.java index 4dc4a1bef..8b27d389d 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/TransformSet.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/TransformSet.java @@ -5,7 +5,6 @@ import java.util.List; import com.jozufozu.flywheel.api.instancer.InstancedPart; import com.jozufozu.flywheel.api.material.Material; import com.jozufozu.flywheel.api.struct.StructType; -import com.jozufozu.flywheel.api.struct.StructType.VertexTransformer; import com.jozufozu.flywheel.api.vertex.MutableVertexList; import com.jozufozu.flywheel.api.vertex.ReusableVertexList; import com.jozufozu.flywheel.backend.instancing.TaskEngine; @@ -71,11 +70,10 @@ public class TransformSet { int meshVertexCount = mesh.getVertexCount(); vertexList.setVertexCount(meshVertexCount); - @SuppressWarnings("unchecked") - StructType.VertexTransformer structVertexTransformer = (VertexTransformer) instancer.type.getVertexTransformer(); + StructType.VertexTransformer structVertexTransformer = instancer.type.getVertexTransformer(); for (D d : list) { - mesh.writeInto(vertexList); + mesh.write(vertexList); structVertexTransformer.transform(vertexList, d, level); diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/blockentity/BlockEntityInstance.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/blockentity/BlockEntityInstance.java index 39a53e444..add54b13b 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/blockentity/BlockEntityInstance.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/blockentity/BlockEntityInstance.java @@ -10,8 +10,8 @@ import com.jozufozu.flywheel.api.instancer.InstancerFactory; import com.jozufozu.flywheel.api.instancer.InstancerManager; import com.jozufozu.flywheel.backend.instancing.AbstractInstance; import com.jozufozu.flywheel.core.structs.StructTypes; -import com.jozufozu.flywheel.core.structs.model.TransformedPart; import com.jozufozu.flywheel.core.structs.oriented.OrientedPart; +import com.jozufozu.flywheel.core.structs.transformed.TransformedPart; import com.jozufozu.flywheel.util.box.GridAlignedBB; import com.jozufozu.flywheel.util.box.ImmutableBox; diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/GPUInstancer.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/GPUInstancer.java index 759afd2c0..95015766a 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/GPUInstancer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/GPUInstancer.java @@ -3,6 +3,8 @@ package com.jozufozu.flywheel.backend.instancing.instancing; import java.util.HashSet; import java.util.Set; +import org.lwjgl.system.MemoryUtil; + import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.api.instancer.InstancedPart; import com.jozufozu.flywheel.api.struct.StructType; @@ -89,20 +91,14 @@ public class GPUInstancer extends AbstractInstancer buf.clear(clearStart, clearLength); if (size > 0) { + final long ptr = MemoryUtil.memAddress(buf.unwrap()); + final int stride = structType.getLayout().getStride(); + final StructWriter writer = structType.getWriter(); - final StructWriter writer = structType.getWriter(buf.unwrap()); - - boolean sequential = true; for (int i = 0; i < size; i++) { final D element = data.get(i); if (element.checkDirtyAndClear()) { - if (!sequential) { - writer.seek(i); - } - writer.write(element); - sequential = true; - } else { - sequential = false; + writer.write(ptr + i * stride, element); } } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/MeshPool.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/MeshPool.java index 39a0b4a48..a5d7b6051 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/MeshPool.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/MeshPool.java @@ -10,6 +10,7 @@ import java.util.Set; import org.jetbrains.annotations.Nullable; import org.lwjgl.opengl.GL32; +import org.lwjgl.system.MemoryUtil; import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.api.vertex.VertexType; @@ -240,7 +241,9 @@ public class MeshPool { } private void buffer(ByteBuffer buffer) { - this.mesh.writeInto(buffer, this.byteIndex); + buffer.position((int) this.byteIndex); + long ptr = MemoryUtil.memAddress(buffer); + this.mesh.write(ptr); this.boundTo.clear(); this.gpuResident = true; diff --git a/src/main/java/com/jozufozu/flywheel/backend/memory/FlwMemoryTracker.java b/src/main/java/com/jozufozu/flywheel/backend/memory/FlwMemoryTracker.java new file mode 100644 index 000000000..c398eb223 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/memory/FlwMemoryTracker.java @@ -0,0 +1,141 @@ +package com.jozufozu.flywheel.backend.memory; + +import java.lang.ref.Cleaner; +import java.nio.ByteBuffer; + +import org.lwjgl.system.MemoryUtil; + +public class FlwMemoryTracker { + private static final Cleaner CLEANER = Cleaner.create(); + + private static long cpuMemory = 0; + private static long gpuMemory = 0; + + public static long malloc(long size) { + long ptr = MemoryUtil.nmemAlloc(size); + if (ptr == MemoryUtil.NULL) { + throw new OutOfMemoryError("Failed to allocate " + size + " bytes"); + } + return ptr; + } + + public static MemoryBlock mallocBlock(long size) { + MemoryBlock block = new MemoryBlockImpl(malloc(size), size); + cpuMemory += block.size(); + return block; + } + + public static MemoryBlock mallocBlockTracked(long size) { + TrackedMemoryBlockImpl block = new TrackedMemoryBlockImpl(malloc(size), size); + block.cleanable = CLEANER.register(block, () -> { + if (!block.isFreed()) { + block.free(); + } + }); + cpuMemory += block.size(); + return block; + } + + @Deprecated + public static ByteBuffer mallocBuffer(int size) { + ByteBuffer buffer = MemoryUtil.memByteBuffer(malloc(size), size); + cpuMemory += buffer.capacity(); + return buffer; + } + + public static long calloc(long num, long size) { + long ptr = MemoryUtil.nmemCalloc(num, size); + if (ptr == MemoryUtil.NULL) { + throw new OutOfMemoryError("Failed to allocate " + num + " blocks of size " + size + " bytes"); + } + return ptr; + } + + public static MemoryBlock callocBlock(long num, long size) { + MemoryBlock block = new MemoryBlockImpl(calloc(num, size), num * size); + cpuMemory += block.size(); + return block; + } + + public static MemoryBlock callocBlockTracked(long num, long size) { + TrackedMemoryBlockImpl block = new TrackedMemoryBlockImpl(calloc(num, size), num * size); + block.cleanable = CLEANER.register(block, () -> { + if (!block.isFreed()) { + block.free(); + } + }); + cpuMemory += block.size(); + return block; + } + + public static long realloc(long ptr, long size) { + ptr = MemoryUtil.nmemRealloc(ptr, size); + if (ptr == MemoryUtil.NULL) { + throw new OutOfMemoryError("Failed to reallocate " + size + " bytes for address 0x" + Long.toHexString(ptr)); + } + return ptr; + } + + public static MemoryBlock reallocBlock(MemoryBlock block, long size) { + MemoryBlock newBlock = new MemoryBlockImpl(realloc(block.ptr(), size), size); + cpuMemory += -block.size() + newBlock.size(); + return newBlock; + } + + public static MemoryBlock reallocBlockTracked(MemoryBlock block, long size) { + TrackedMemoryBlockImpl newBlock = new TrackedMemoryBlockImpl(realloc(block.ptr(), size), size); + newBlock.cleanable = CLEANER.register(newBlock, () -> { + if (!newBlock.isFreed()) { + newBlock.free(); + } + }); + cpuMemory += -block.size() + newBlock.size(); + return newBlock; + } + + @Deprecated + public static ByteBuffer reallocBuffer(ByteBuffer buffer, int size) { + ByteBuffer newBuffer = MemoryUtil.memByteBuffer(realloc(MemoryUtil.memAddress(buffer), size), size); + cpuMemory += -buffer.capacity() + newBuffer.capacity(); + return newBuffer; + } + + public static void free(long ptr) { + MemoryUtil.nmemFree(ptr); + } + + public static void freeBlock(MemoryBlock block) { + free(block.ptr()); + cpuMemory -= block.size(); + } + + @Deprecated + public static void freeBuffer(ByteBuffer buffer) { + free(MemoryUtil.memAddress(buffer)); + cpuMemory -= buffer.capacity(); + } + + public static void _allocCPUMemory(long size) { + cpuMemory += size; + } + + public static void _freeCPUMemory(long size) { + cpuMemory -= size; + } + + public static void _allocGPUMemory(long size) { + gpuMemory += size; + } + + public static void _freeGPUMemory(long size) { + gpuMemory -= size; + } + + public static long getCPUMemory() { + return cpuMemory; + } + + public static long getGPUMemory() { + return gpuMemory; + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/memory/MemoryBlock.java b/src/main/java/com/jozufozu/flywheel/backend/memory/MemoryBlock.java new file mode 100644 index 000000000..c78b8c193 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/memory/MemoryBlock.java @@ -0,0 +1,45 @@ +package com.jozufozu.flywheel.backend.memory; + +import java.nio.ByteBuffer; + +public sealed interface MemoryBlock permits MemoryBlockImpl { + long ptr(); + + long size(); + + boolean isFreed(); + + boolean isTracked(); + + void copyTo(long ptr, long bytes); + + default void copyTo(long ptr) { + copyTo(ptr, size()); + } + + void clear(); + + ByteBuffer asBuffer(); + + MemoryBlock realloc(long size); + + MemoryBlock reallocTracked(long size); + + void free(); + + static MemoryBlock malloc(long size) { + return FlwMemoryTracker.mallocBlock(size); + } + + static MemoryBlock calloc(long num, long size) { + return FlwMemoryTracker.callocBlock(num, size); + } + + static MemoryBlock mallocTracked(long size) { + return FlwMemoryTracker.mallocBlockTracked(size); + } + + static MemoryBlock callocTracked(long num, long size) { + return FlwMemoryTracker.callocBlockTracked(num, size); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/memory/MemoryBlockImpl.java b/src/main/java/com/jozufozu/flywheel/backend/memory/MemoryBlockImpl.java new file mode 100644 index 000000000..1b6d984a6 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/memory/MemoryBlockImpl.java @@ -0,0 +1,76 @@ +package com.jozufozu.flywheel.backend.memory; + +import java.nio.ByteBuffer; + +import org.lwjgl.system.MemoryUtil; + +sealed class MemoryBlockImpl implements MemoryBlock permits TrackedMemoryBlockImpl { + final long ptr; + final long size; + + boolean freed; + + MemoryBlockImpl(long ptr, long size) { + this.ptr = ptr; + this.size = size; + } + + @Override + public long ptr() { + return ptr; + } + + @Override + public long size() { + return size; + } + + @Override + public boolean isFreed() { + return freed; + } + + @Override + public boolean isTracked() { + return false; + } + + @Override + public void copyTo(long ptr, long bytes) { + MemoryUtil.memCopy(this.ptr, ptr, bytes); + } + + @Override + public void clear() { + MemoryUtil.memSet(ptr, 0, size); + } + + @Override + public ByteBuffer asBuffer() { + int intSize = (int) size; + if (intSize != size) { + throw new UnsupportedOperationException("Cannot create buffer with long capacity!"); + } + return MemoryUtil.memByteBuffer(ptr, intSize); + } + + @Override + public MemoryBlock realloc(long size) { + MemoryBlock block = FlwMemoryTracker.reallocBlock(this, size); + freed = true; + return block; + } + + @Override + public MemoryBlock reallocTracked(long size) { + MemoryBlock block = FlwMemoryTracker.reallocBlockTracked(this, size); + freed = true; + return block; + } + + @Override + public void free() { + FlwMemoryTracker.freeBlock(this); + freed = true; + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/memory/TrackedMemoryBlockImpl.java b/src/main/java/com/jozufozu/flywheel/backend/memory/TrackedMemoryBlockImpl.java new file mode 100644 index 000000000..40b1a15eb --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/memory/TrackedMemoryBlockImpl.java @@ -0,0 +1,38 @@ +package com.jozufozu.flywheel.backend.memory; + +import java.lang.ref.Cleaner; + +final class TrackedMemoryBlockImpl extends MemoryBlockImpl { + Cleaner.Cleanable cleanable; + + TrackedMemoryBlockImpl(long ptr, long size) { + super(ptr, size); + } + + @Override + public boolean isTracked() { + return true; + } + + @Override + public MemoryBlock realloc(long size) { + MemoryBlock block = FlwMemoryTracker.reallocBlock(this, size); + freed = true; + cleanable.clean(); + return block; + } + + @Override + public MemoryBlock reallocTracked(long size) { + MemoryBlock block = FlwMemoryTracker.reallocBlockTracked(this, size); + freed = true; + cleanable.clean(); + return block; + } + + @Override + public void free() { + cleanable.clean(); + freed = true; + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/struct/BufferWriter.java b/src/main/java/com/jozufozu/flywheel/backend/struct/BufferWriter.java deleted file mode 100644 index 49ce4969d..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/struct/BufferWriter.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.jozufozu.flywheel.backend.struct; - -import java.nio.ByteBuffer; - -import com.jozufozu.flywheel.api.instancer.InstancedPart; -import com.jozufozu.flywheel.api.struct.StructType; -import com.jozufozu.flywheel.api.struct.StructWriter; - -public abstract class BufferWriter implements StructWriter { - protected final ByteBuffer backingBuffer; - - protected final int stride; - - protected BufferWriter(StructType structType, ByteBuffer byteBuffer) { - this.backingBuffer = byteBuffer; - - this.stride = structType.getLayout().getStride(); - } - - @Override - public final void write(S struct) { - writeInternal(struct); - advance(); - } - - /** - * Advances the write pointer forward by the stride of one vertex. - * This will always be called after a struct is written, implementors need not call it themselves. - * - * @see #write - */ - protected abstract void advance(); - - protected abstract void writeInternal(S s); - - @Override - public void seek(int pos) { - backingBuffer.position(pos * stride); - } -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/struct/UnsafeBufferWriter.java b/src/main/java/com/jozufozu/flywheel/backend/struct/UnsafeBufferWriter.java deleted file mode 100644 index 7aa852de1..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/struct/UnsafeBufferWriter.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.jozufozu.flywheel.backend.struct; - -import java.nio.ByteBuffer; - -import org.lwjgl.system.MemoryUtil; - -import com.jozufozu.flywheel.api.instancer.InstancedPart; -import com.jozufozu.flywheel.api.struct.StructType; - -/** - * This class copied/adapted from jellysquid's - * - * An unsafe {@link BufferWriter} implementation which uses direct memory operations to enable fast blitting of - * data into memory buffers. Only available on JVMs which support {@link sun.misc.Unsafe}, but generally produces much - * better optimized code than other implementations. The implementation does not check for invalid memory accesses, - * meaning that errors can corrupt process memory. - */ -public abstract class UnsafeBufferWriter extends BufferWriter { - /** - * The write pointer into the buffer storage. This is advanced by the stride every time - * {@link UnsafeBufferWriter#advance()} is called. - */ - protected long writePointer; - - protected UnsafeBufferWriter(StructType structType, ByteBuffer byteBuffer) { - super(structType, byteBuffer); - - acquireWritePointer(); - } - - @Override - public void seek(int pos) { - super.seek(pos); - acquireWritePointer(); - } - - @Override - protected void advance() { - this.writePointer += this.stride; - } - - private void acquireWritePointer() { - this.writePointer = MemoryUtil.memAddress(this.backingBuffer, this.backingBuffer.position()); - } -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/struct/package-info.java b/src/main/java/com/jozufozu/flywheel/backend/struct/package-info.java deleted file mode 100644 index d4cbaadf2..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/struct/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault -package com.jozufozu.flywheel.backend.struct; - -import javax.annotation.ParametersAreNonnullByDefault; - -import net.minecraft.MethodsReturnNonnullByDefault; 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 7369df882..4dc301213 100644 --- a/src/main/java/com/jozufozu/flywheel/core/hardcoded/ModelPart.java +++ b/src/main/java/com/jozufozu/flywheel/core/hardcoded/ModelPart.java @@ -1,20 +1,17 @@ package com.jozufozu.flywheel.core.hardcoded; -import java.nio.ByteBuffer; import java.util.List; -import org.lwjgl.system.MemoryUtil; - import com.jozufozu.flywheel.api.vertex.MutableVertexList; import com.jozufozu.flywheel.api.vertex.ReusableVertexList; +import com.jozufozu.flywheel.backend.memory.MemoryBlock; import com.jozufozu.flywheel.core.model.Mesh; import com.jozufozu.flywheel.core.vertex.Formats; import com.jozufozu.flywheel.core.vertex.PosTexNormalVertex; -import com.mojang.blaze3d.platform.MemoryTracker; public class ModelPart implements Mesh { private final int vertexCount; - private final ByteBuffer contents; + private final MemoryBlock contents; private final ReusableVertexList vertexList; private final String name; @@ -29,8 +26,8 @@ public class ModelPart implements Mesh { this.vertexCount = vertices; } - contents = MemoryTracker.create(size()); - long ptr = MemoryUtil.memAddress(contents); + contents = MemoryBlock.malloc(size()); + long ptr = contents.ptr(); VertexWriter writer = new VertexWriterImpl(ptr); for (PartBuilder.CuboidBuilder cuboid : cuboids) { cuboid.write(writer); @@ -56,19 +53,18 @@ public class ModelPart implements Mesh { } @Override - public void writeInto(ByteBuffer buffer, long byteIndex) { - buffer.position((int) byteIndex); - MemoryUtil.memCopy(contents, buffer); + public void write(long ptr) { + contents.copyTo(ptr); } @Override - public void writeInto(MutableVertexList dst) { + public void write(MutableVertexList dst) { vertexList.writeAll(dst); } @Override public void close() { - MemoryUtil.memFree(contents); + contents.free(); } @Override diff --git a/src/main/java/com/jozufozu/flywheel/core/model/Mesh.java b/src/main/java/com/jozufozu/flywheel/core/model/Mesh.java index f09c5ec58..a1a4f10c2 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/Mesh.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/Mesh.java @@ -1,7 +1,5 @@ package com.jozufozu.flywheel.core.model; -import java.nio.ByteBuffer; - import com.jozufozu.flywheel.api.vertex.MutableVertexList; import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.backend.instancing.instancing.ElementBuffer; @@ -51,9 +49,9 @@ public interface Mesh { return getVertexType().byteOffset(getVertexCount()); } - void writeInto(ByteBuffer buffer, long byteIndex); + void write(long ptr); - void writeInto(MutableVertexList vertexList); + void write(MutableVertexList vertexList); /** * Create an element buffer object that indexes the vertices of this mesh. 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 dfcd1435a..9a68168ff 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/ModelUtil.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/ModelUtil.java @@ -10,10 +10,10 @@ import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.api.material.Material; import com.jozufozu.flywheel.api.vertex.ReusableVertexList; import com.jozufozu.flywheel.api.vertex.VertexType; +import com.jozufozu.flywheel.backend.memory.MemoryBlock; import com.jozufozu.flywheel.core.Materials; import com.jozufozu.flywheel.core.vertex.Formats; import com.jozufozu.flywheel.core.vertex.VertexListProviderRegistry; -import com.mojang.blaze3d.platform.MemoryTracker; import com.mojang.blaze3d.vertex.BufferBuilder.DrawState; import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.datafixers.util.Pair; @@ -47,16 +47,16 @@ public class ModelUtil { return dispatcher; } - public static Pair convertBlockBuffer(Pair pair) { + public static Pair convertBlockBuffer(Pair pair) { DrawState drawState = pair.getFirst(); int vertexCount = drawState.vertexCount(); VertexFormat srcFormat = drawState.format(); VertexType dstVertexType = Formats.BLOCK; ByteBuffer src = pair.getSecond(); - ByteBuffer dst = MemoryTracker.create(src.capacity()); + MemoryBlock dst = MemoryBlock.malloc(src.capacity()); long srcPtr = MemoryUtil.memAddress(src); - long dstPtr = MemoryUtil.memAddress(dst); + long dstPtr = dst.ptr(); ReusableVertexList srcList = VertexListProviderRegistry.getOrInfer(srcFormat).createVertexList(); ReusableVertexList dstList = dstVertexType.createVertexList(); 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 f95423005..d184a05d6 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/SimpleMesh.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/SimpleMesh.java @@ -1,35 +1,31 @@ package com.jozufozu.flywheel.core.model; -import java.nio.ByteBuffer; - -import org.lwjgl.system.MemoryUtil; - import com.jozufozu.flywheel.api.vertex.MutableVertexList; import com.jozufozu.flywheel.api.vertex.ReusableVertexList; import com.jozufozu.flywheel.api.vertex.VertexType; +import com.jozufozu.flywheel.backend.memory.MemoryBlock; public class SimpleMesh implements Mesh { private final VertexType vertexType; private final int vertexCount; - private final ByteBuffer contents; + private final MemoryBlock contents; private final ReusableVertexList vertexList; private final String name; - public SimpleMesh(VertexType vertexType, ByteBuffer contents, String name) { + public SimpleMesh(VertexType vertexType, MemoryBlock contents, String name) { this.vertexType = vertexType; this.contents = contents; this.name = name; - contents.clear(); - int bytes = contents.remaining(); + int bytes = (int) contents.size(); int stride = vertexType.getStride(); if (bytes % stride != 0) { - throw new IllegalArgumentException("Buffer contains non-whole amount of vertices!"); + throw new IllegalArgumentException("MemoryBlock contains non-whole amount of vertices!"); } vertexCount = bytes / stride; vertexList = getVertexType().createVertexList(); - vertexList.ptr(MemoryUtil.memAddress(contents)); + vertexList.ptr(contents.ptr()); vertexList.setVertexCount(vertexCount); } @@ -44,19 +40,18 @@ public class SimpleMesh implements Mesh { } @Override - public void writeInto(ByteBuffer buffer, long byteIndex) { - buffer.position((int) byteIndex); - MemoryUtil.memCopy(contents, buffer); + public void write(long ptr) { + contents.copyTo(ptr); } @Override - public void writeInto(MutableVertexList dst) { + public void write(MutableVertexList dst) { vertexList.writeAll(dst); } @Override public void close() { - MemoryUtil.memFree(contents); + contents.free(); } @Override diff --git a/src/main/java/com/jozufozu/flywheel/core/model/buffering/BakedModelBuilder.java b/src/main/java/com/jozufozu/flywheel/core/model/buffering/BakedModelBuilder.java index d7c138d00..e0ca37b16 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/buffering/BakedModelBuilder.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/buffering/BakedModelBuilder.java @@ -1,11 +1,11 @@ package com.jozufozu.flywheel.core.model.buffering; -import java.nio.ByteBuffer; import java.util.function.BiFunction; import com.google.common.collect.ImmutableMap; import com.jozufozu.flywheel.api.material.Material; import com.jozufozu.flywheel.api.vertex.VertexType; +import com.jozufozu.flywheel.backend.memory.MemoryBlock; import com.jozufozu.flywheel.core.model.Mesh; import com.jozufozu.flywheel.core.model.ModelUtil; import com.jozufozu.flywheel.core.model.SimpleMesh; @@ -104,7 +104,7 @@ public class BakedModelBuilder { buffer.end(); Material material = materialFunc.apply(renderType, shaded); if (material != null) { - Pair pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer()); + Pair pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer()); meshMapBuilder.put(material, new SimpleMesh(pair.getFirst(), pair.getSecond(), "bakedModel=" + bakedModel.toString() + ",renderType=" + renderType.toString() + ",shaded=" + shaded)); } }; @@ -119,7 +119,7 @@ public class BakedModelBuilder { buffer.end(); Material material = materialFunc.apply(renderType, false); if (material != null) { - Pair pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer()); + Pair pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer()); meshMapBuilder.put(material, new SimpleMesh(pair.getFirst(), pair.getSecond(), "bakedModel=" + bakedModel.toString() + ",renderType=" + renderType.toString())); } }; diff --git a/src/main/java/com/jozufozu/flywheel/core/model/buffering/BlockModelBuilder.java b/src/main/java/com/jozufozu/flywheel/core/model/buffering/BlockModelBuilder.java index f5d0c485e..84686aa74 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/buffering/BlockModelBuilder.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/buffering/BlockModelBuilder.java @@ -1,11 +1,11 @@ package com.jozufozu.flywheel.core.model.buffering; -import java.nio.ByteBuffer; import java.util.function.BiFunction; import com.google.common.collect.ImmutableMap; import com.jozufozu.flywheel.api.material.Material; import com.jozufozu.flywheel.api.vertex.VertexType; +import com.jozufozu.flywheel.backend.memory.MemoryBlock; import com.jozufozu.flywheel.core.model.Mesh; import com.jozufozu.flywheel.core.model.ModelUtil; import com.jozufozu.flywheel.core.model.SimpleMesh; @@ -93,7 +93,7 @@ public class BlockModelBuilder { buffer.end(); Material material = materialFunc.apply(renderType, shaded); if (material != null) { - Pair pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer()); + Pair pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer()); meshMapBuilder.put(material, new SimpleMesh(pair.getFirst(), pair.getSecond(), "state=" + state.toString() + ",renderType=" + renderType.toString() + ",shaded=" + shaded)); } }; @@ -108,7 +108,7 @@ public class BlockModelBuilder { buffer.end(); Material material = materialFunc.apply(renderType, false); if (material != null) { - Pair pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer()); + Pair pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer()); meshMapBuilder.put(material, new SimpleMesh(pair.getFirst(), pair.getSecond(), "state=" + state.toString() + ",renderType=" + renderType.toString())); } }; diff --git a/src/main/java/com/jozufozu/flywheel/core/model/buffering/MultiBlockModelBuilder.java b/src/main/java/com/jozufozu/flywheel/core/model/buffering/MultiBlockModelBuilder.java index c951acfbd..b329a46c6 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/buffering/MultiBlockModelBuilder.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/buffering/MultiBlockModelBuilder.java @@ -1,6 +1,5 @@ package com.jozufozu.flywheel.core.model.buffering; -import java.nio.ByteBuffer; import java.util.Collection; import java.util.Collections; import java.util.Map; @@ -9,6 +8,7 @@ import java.util.function.BiFunction; import com.google.common.collect.ImmutableMap; import com.jozufozu.flywheel.api.material.Material; import com.jozufozu.flywheel.api.vertex.VertexType; +import com.jozufozu.flywheel.backend.memory.MemoryBlock; import com.jozufozu.flywheel.core.model.Mesh; import com.jozufozu.flywheel.core.model.ModelUtil; import com.jozufozu.flywheel.core.model.SimpleMesh; @@ -100,7 +100,7 @@ public class MultiBlockModelBuilder { buffer.end(); Material material = materialFunc.apply(renderType, shaded); if (material != null) { - Pair pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer()); + Pair pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer()); meshMapBuilder.put(material, new SimpleMesh(pair.getFirst(), pair.getSecond(), "renderType=" + renderType.toString() + ",shaded=" + shaded)); } }; @@ -115,7 +115,7 @@ public class MultiBlockModelBuilder { buffer.end(); Material material = materialFunc.apply(renderType, false); if (material != null) { - Pair pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer()); + Pair pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer()); meshMapBuilder.put(material, new SimpleMesh(pair.getFirst(), pair.getSecond(), "renderType=" + renderType.toString())); } }; diff --git a/src/main/java/com/jozufozu/flywheel/core/structs/ColoredLitWriter.java b/src/main/java/com/jozufozu/flywheel/core/structs/ColoredLitWriter.java new file mode 100644 index 000000000..dcd23aca0 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/core/structs/ColoredLitWriter.java @@ -0,0 +1,17 @@ +package com.jozufozu.flywheel.core.structs; + +import org.lwjgl.system.MemoryUtil; + +import com.jozufozu.flywheel.api.struct.StructWriter; + +public abstract class ColoredLitWriter implements StructWriter { + @Override + public void write(long ptr, D d) { + MemoryUtil.memPutByte(ptr, d.blockLight); + MemoryUtil.memPutByte(ptr + 1, d.skyLight); + MemoryUtil.memPutByte(ptr + 2, d.r); + MemoryUtil.memPutByte(ptr + 3, d.g); + MemoryUtil.memPutByte(ptr + 4, d.b); + MemoryUtil.memPutByte(ptr + 5, d.a); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/core/structs/ColoredLitWriterUnsafe.java b/src/main/java/com/jozufozu/flywheel/core/structs/ColoredLitWriterUnsafe.java deleted file mode 100644 index 985fc7046..000000000 --- a/src/main/java/com/jozufozu/flywheel/core/structs/ColoredLitWriterUnsafe.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.jozufozu.flywheel.core.structs; - -import java.nio.ByteBuffer; - -import org.lwjgl.system.MemoryUtil; - -import com.jozufozu.flywheel.api.struct.StructType; -import com.jozufozu.flywheel.backend.struct.UnsafeBufferWriter; - -public abstract class ColoredLitWriterUnsafe extends UnsafeBufferWriter { - - public ColoredLitWriterUnsafe(StructType structType, ByteBuffer byteBuffer) { - super(structType, byteBuffer); - } - - @Override - protected void writeInternal(D d) { - long ptr = writePointer; - MemoryUtil.memPutByte(ptr, d.blockLight); - MemoryUtil.memPutByte(ptr + 1, d.skyLight); - MemoryUtil.memPutByte(ptr + 2, d.r); - MemoryUtil.memPutByte(ptr + 3, d.g); - MemoryUtil.memPutByte(ptr + 4, d.b); - MemoryUtil.memPutByte(ptr + 5, d.a); - } -} diff --git a/src/main/java/com/jozufozu/flywheel/core/structs/StructTypes.java b/src/main/java/com/jozufozu/flywheel/core/structs/StructTypes.java index 96015bf27..597a2a43c 100644 --- a/src/main/java/com/jozufozu/flywheel/core/structs/StructTypes.java +++ b/src/main/java/com/jozufozu/flywheel/core/structs/StructTypes.java @@ -2,10 +2,10 @@ package com.jozufozu.flywheel.core.structs; import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.core.ComponentRegistry; -import com.jozufozu.flywheel.core.structs.model.TransformedPart; -import com.jozufozu.flywheel.core.structs.model.TransformedType; import com.jozufozu.flywheel.core.structs.oriented.OrientedPart; import com.jozufozu.flywheel.core.structs.oriented.OrientedType; +import com.jozufozu.flywheel.core.structs.transformed.TransformedPart; +import com.jozufozu.flywheel.core.structs.transformed.TransformedType; public class StructTypes { public static final StructType TRANSFORMED = ComponentRegistry.register(new TransformedType()); diff --git a/src/main/java/com/jozufozu/flywheel/core/structs/model/TransformedWriterUnsafe.java b/src/main/java/com/jozufozu/flywheel/core/structs/model/TransformedWriterUnsafe.java deleted file mode 100644 index 8634e0db7..000000000 --- a/src/main/java/com/jozufozu/flywheel/core/structs/model/TransformedWriterUnsafe.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.jozufozu.flywheel.core.structs.model; - -import java.nio.ByteBuffer; - -import com.jozufozu.flywheel.api.struct.StructType; -import com.jozufozu.flywheel.core.structs.ColoredLitWriterUnsafe; -import com.jozufozu.flywheel.util.MatrixWrite; - -public class TransformedWriterUnsafe extends ColoredLitWriterUnsafe { - - public TransformedWriterUnsafe(StructType structType, ByteBuffer byteBuffer) { - super(structType, byteBuffer); - } - - @Override - protected void writeInternal(TransformedPart d) { - super.writeInternal(d); - long ptr = writePointer + 6; - - ((MatrixWrite) (Object) d.model).flywheel$writeUnsafe(ptr); - ((MatrixWrite) (Object) d.normal).flywheel$writeUnsafe(ptr + 4 * 16); - } -} 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 93a0226ef..66f2653f5 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 @@ -1,7 +1,5 @@ package com.jozufozu.flywheel.core.structs.oriented; -import java.nio.ByteBuffer; - import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.api.struct.StructWriter; import com.jozufozu.flywheel.core.Components; @@ -32,8 +30,8 @@ public class OrientedType implements StructType { } @Override - public StructWriter getWriter(ByteBuffer backing) { - return new OrientedWriterUnsafe(this, backing); + public StructWriter getWriter() { + return OrientedWriter.INSTANCE; } @Override @@ -42,7 +40,7 @@ public class OrientedType implements StructType { } @Override - public VertexTransformer getVertexTransformer() { + public VertexTransformer getVertexTransformer() { return (vertexList, struct, level) -> { Vector4f pos = new Vector4f(); Vector3f normal = new Vector3f(); diff --git a/src/main/java/com/jozufozu/flywheel/core/structs/oriented/OrientedWriterUnsafe.java b/src/main/java/com/jozufozu/flywheel/core/structs/oriented/OrientedWriter.java similarity index 54% rename from src/main/java/com/jozufozu/flywheel/core/structs/oriented/OrientedWriterUnsafe.java rename to src/main/java/com/jozufozu/flywheel/core/structs/oriented/OrientedWriter.java index fb03c4d1e..8aa99cef4 100644 --- a/src/main/java/com/jozufozu/flywheel/core/structs/oriented/OrientedWriterUnsafe.java +++ b/src/main/java/com/jozufozu/flywheel/core/structs/oriented/OrientedWriter.java @@ -1,21 +1,15 @@ package com.jozufozu.flywheel.core.structs.oriented; -import java.nio.ByteBuffer; - import org.lwjgl.system.MemoryUtil; -import com.jozufozu.flywheel.api.struct.StructType; -import com.jozufozu.flywheel.core.structs.ColoredLitWriterUnsafe; +import com.jozufozu.flywheel.core.structs.ColoredLitWriter; -public class OrientedWriterUnsafe extends ColoredLitWriterUnsafe { - public OrientedWriterUnsafe(StructType structType, ByteBuffer byteBuffer) { - super(structType, byteBuffer); - } +public class OrientedWriter extends ColoredLitWriter { + public static final OrientedWriter INSTANCE = new OrientedWriter(); @Override - protected void writeInternal(OrientedPart d) { - long ptr = writePointer; - super.writeInternal(d); + public void write(long ptr, OrientedPart d) { + super.write(ptr, d); MemoryUtil.memPutFloat(ptr + 6, d.posX); MemoryUtil.memPutFloat(ptr + 10, d.posY); diff --git a/src/main/java/com/jozufozu/flywheel/core/structs/model/TransformedPart.java b/src/main/java/com/jozufozu/flywheel/core/structs/transformed/TransformedPart.java similarity index 97% rename from src/main/java/com/jozufozu/flywheel/core/structs/model/TransformedPart.java rename to src/main/java/com/jozufozu/flywheel/core/structs/transformed/TransformedPart.java index 865f5bccd..215bfd913 100644 --- a/src/main/java/com/jozufozu/flywheel/core/structs/model/TransformedPart.java +++ b/src/main/java/com/jozufozu/flywheel/core/structs/transformed/TransformedPart.java @@ -1,4 +1,4 @@ -package com.jozufozu.flywheel.core.structs.model; +package com.jozufozu.flywheel.core.structs.transformed; import com.jozufozu.flywheel.core.structs.ColoredLitPart; import com.jozufozu.flywheel.core.structs.StructTypes; diff --git a/src/main/java/com/jozufozu/flywheel/core/structs/model/TransformedType.java b/src/main/java/com/jozufozu/flywheel/core/structs/transformed/TransformedType.java similarity index 86% rename from src/main/java/com/jozufozu/flywheel/core/structs/model/TransformedType.java rename to src/main/java/com/jozufozu/flywheel/core/structs/transformed/TransformedType.java index 30d750672..8eb36eeb6 100644 --- a/src/main/java/com/jozufozu/flywheel/core/structs/model/TransformedType.java +++ b/src/main/java/com/jozufozu/flywheel/core/structs/transformed/TransformedType.java @@ -1,6 +1,4 @@ -package com.jozufozu.flywheel.core.structs.model; - -import java.nio.ByteBuffer; +package com.jozufozu.flywheel.core.structs.transformed; import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.api.struct.StructWriter; @@ -29,8 +27,8 @@ public class TransformedType implements StructType { } @Override - public StructWriter getWriter(ByteBuffer backing) { - return new TransformedWriterUnsafe(this, backing); + public StructWriter getWriter() { + return TransformedWriter.INSTANCE; } @Override @@ -39,7 +37,7 @@ public class TransformedType implements StructType { } @Override - public VertexTransformer getVertexTransformer() { + public VertexTransformer getVertexTransformer() { return (vertexList, struct, level) -> { Vector4f pos = new Vector4f(); Vector3f normal = new Vector3f(); diff --git a/src/main/java/com/jozufozu/flywheel/core/structs/transformed/TransformedWriter.java b/src/main/java/com/jozufozu/flywheel/core/structs/transformed/TransformedWriter.java new file mode 100644 index 000000000..eb910d6fb --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/core/structs/transformed/TransformedWriter.java @@ -0,0 +1,17 @@ +package com.jozufozu.flywheel.core.structs.transformed; + +import com.jozufozu.flywheel.core.structs.ColoredLitWriter; +import com.jozufozu.flywheel.util.MatrixWrite; + +public class TransformedWriter extends ColoredLitWriter { + public static final TransformedWriter INSTANCE = new TransformedWriter(); + + @Override + public void write(long ptr, TransformedPart d) { + super.write(ptr, d); + ptr += 6; + + ((MatrixWrite) (Object) d.model).flywheel$writeUnsafe(ptr); + ((MatrixWrite) (Object) d.normal).flywheel$writeUnsafe(ptr + 4 * 16); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/core/structs/model/package-info.java b/src/main/java/com/jozufozu/flywheel/core/structs/transformed/package-info.java similarity index 75% rename from src/main/java/com/jozufozu/flywheel/core/structs/model/package-info.java rename to src/main/java/com/jozufozu/flywheel/core/structs/transformed/package-info.java index 759c3a038..2ca2a5ed4 100644 --- a/src/main/java/com/jozufozu/flywheel/core/structs/model/package-info.java +++ b/src/main/java/com/jozufozu/flywheel/core/structs/transformed/package-info.java @@ -1,5 +1,5 @@ @ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault -package com.jozufozu.flywheel.core.structs.model; +package com.jozufozu.flywheel.core.structs.transformed; import javax.annotation.ParametersAreNonnullByDefault; diff --git a/src/main/java/com/jozufozu/flywheel/core/uniform/FogProvider.java b/src/main/java/com/jozufozu/flywheel/core/uniform/FogProvider.java index 9a7586c41..9bea01220 100644 --- a/src/main/java/com/jozufozu/flywheel/core/uniform/FogProvider.java +++ b/src/main/java/com/jozufozu/flywheel/core/uniform/FogProvider.java @@ -9,8 +9,6 @@ import com.mojang.blaze3d.systems.RenderSystem; public class FogProvider extends UniformProvider { - - @Override public int getSize() { return 16 + 8 + 4; diff --git a/src/main/java/com/jozufozu/flywheel/core/uniform/UniformBuffer.java b/src/main/java/com/jozufozu/flywheel/core/uniform/UniformBuffer.java index 5f3b10bb7..068fbc4c0 100644 --- a/src/main/java/com/jozufozu/flywheel/core/uniform/UniformBuffer.java +++ b/src/main/java/com/jozufozu/flywheel/core/uniform/UniformBuffer.java @@ -12,9 +12,9 @@ import com.google.common.collect.ImmutableList; import com.jozufozu.flywheel.api.uniform.UniformProvider; import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType; import com.jozufozu.flywheel.backend.gl.buffer.MappedGlBuffer; +import com.jozufozu.flywheel.backend.memory.FlwMemoryTracker; import com.jozufozu.flywheel.core.ComponentRegistry; import com.jozufozu.flywheel.util.RenderMath; -import com.mojang.blaze3d.platform.MemoryTracker; public class UniformBuffer { @@ -57,7 +57,7 @@ public class UniformBuffer { allocatedProviders = builder.build(); - data = MemoryTracker.create(totalBytes); + data = FlwMemoryTracker.mallocBuffer(totalBytes); changedBytes = new BitSet(totalBytes); for (Allocated p : allocatedProviders) { diff --git a/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java b/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java index 1310235f7..26bc79290 100644 --- a/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java +++ b/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java @@ -4,8 +4,8 @@ import java.util.ArrayList; import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.backend.Backend; -import com.jozufozu.flywheel.backend.FlywheelMemory; import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; +import com.jozufozu.flywheel.backend.memory.FlwMemoryTracker; import com.jozufozu.flywheel.light.LightUpdater; import com.jozufozu.flywheel.util.WorldAttached; @@ -24,10 +24,7 @@ public class ForgeEvents { InstancedRenderDispatcher.getDebugString(debug); - // TODO: compress into one line - debug.add("Memory used:"); - debug.add("GPU: " + FlywheelMemory.getGPUMemory()); - debug.add("CPU: " + FlywheelMemory.getCPUMemory()); + debug.add("Memory Usage: CPU: " + FlwMemoryTracker.getCPUMemory() / 1024 + "KiB GPU: " + FlwMemoryTracker.getGPUMemory() / 1024 + "KiB"); } } diff --git a/src/main/java/com/jozufozu/flywheel/light/LightVolume.java b/src/main/java/com/jozufozu/flywheel/light/LightVolume.java index 31245dea9..cf4abacb1 100644 --- a/src/main/java/com/jozufozu/flywheel/light/LightVolume.java +++ b/src/main/java/com/jozufozu/flywheel/light/LightVolume.java @@ -2,8 +2,7 @@ package com.jozufozu.flywheel.light; import java.nio.ByteBuffer; -import org.lwjgl.system.MemoryUtil; - +import com.jozufozu.flywheel.backend.memory.FlwMemoryTracker; import com.jozufozu.flywheel.util.box.GridAlignedBB; import com.jozufozu.flywheel.util.box.ImmutableBox; @@ -21,7 +20,7 @@ public class LightVolume implements ImmutableBox, LightListener { this.level = level; this.setBox(sampleVolume); - this.lightData = MemoryUtil.memAlloc(this.box.volume() * 2); + this.lightData = FlwMemoryTracker.mallocBuffer(this.box.volume() * 2); } protected void setBox(ImmutableBox box) { @@ -66,7 +65,7 @@ public class LightVolume implements ImmutableBox, LightListener { setBox(newSampleVolume); int neededCapacity = box.volume() * 2; if (neededCapacity > lightData.capacity()) { - lightData = MemoryUtil.memRealloc(lightData, neededCapacity); + lightData = FlwMemoryTracker.reallocBuffer(lightData, neededCapacity); } initialize(); } @@ -168,7 +167,7 @@ public class LightVolume implements ImmutableBox, LightListener { } public void delete() { - MemoryUtil.memFree(lightData); + FlwMemoryTracker.freeBuffer(lightData); lightData = null; } diff --git a/src/main/java/com/jozufozu/flywheel/util/StringUtil.java b/src/main/java/com/jozufozu/flywheel/util/StringUtil.java index 054bf0f43..4b7049b74 100644 --- a/src/main/java/com/jozufozu/flywheel/util/StringUtil.java +++ b/src/main/java/com/jozufozu/flywheel/util/StringUtil.java @@ -15,6 +15,8 @@ import java.util.stream.Collectors; import org.lwjgl.system.MemoryUtil; +import com.jozufozu.flywheel.backend.memory.FlwMemoryTracker; + public class StringUtil { private static final NumberFormat timeFormat = new DecimalFormat("#0.000"); @@ -56,11 +58,11 @@ public class StringUtil { ((Buffer) bytebuffer).rewind(); return MemoryUtil.memASCII(bytebuffer, i); } catch (IOException ignored) { + // } finally { if (bytebuffer != null) { - MemoryUtil.memFree(bytebuffer); + FlwMemoryTracker.freeBuffer(bytebuffer); } - } return null; @@ -75,12 +77,12 @@ public class StringUtil { } private static ByteBuffer readInputStream(InputStream is) throws IOException { - ByteBuffer bytebuffer = MemoryUtil.memAlloc(8192); + ByteBuffer bytebuffer = FlwMemoryTracker.mallocBuffer(8192); ReadableByteChannel readablebytechannel = Channels.newChannel(is); while (readablebytechannel.read(bytebuffer) != -1) { if (bytebuffer.remaining() == 0) { - bytebuffer = MemoryUtil.memRealloc(bytebuffer, bytebuffer.capacity() * 2); + bytebuffer = FlwMemoryTracker.reallocBuffer(bytebuffer, bytebuffer.capacity() * 2); } } return bytebuffer; @@ -88,7 +90,7 @@ public class StringUtil { private static ByteBuffer readFileInputStream(FileInputStream fileinputstream) throws IOException { FileChannel filechannel = fileinputstream.getChannel(); - ByteBuffer bytebuffer = MemoryUtil.memAlloc((int) filechannel.size() + 1); + ByteBuffer bytebuffer = FlwMemoryTracker.mallocBuffer((int) filechannel.size() + 1); while (filechannel.read(bytebuffer) != -1) { } diff --git a/src/main/java/com/jozufozu/flywheel/vanilla/ChestInstance.java b/src/main/java/com/jozufozu/flywheel/vanilla/ChestInstance.java index 39e6650fb..0089766d2 100644 --- a/src/main/java/com/jozufozu/flywheel/vanilla/ChestInstance.java +++ b/src/main/java/com/jozufozu/flywheel/vanilla/ChestInstance.java @@ -15,8 +15,8 @@ import com.jozufozu.flywheel.core.Materials; import com.jozufozu.flywheel.core.hardcoded.ModelPart; import com.jozufozu.flywheel.core.model.SimpleLazyModel; import com.jozufozu.flywheel.core.structs.StructTypes; -import com.jozufozu.flywheel.core.structs.model.TransformedPart; import com.jozufozu.flywheel.core.structs.oriented.OrientedPart; +import com.jozufozu.flywheel.core.structs.transformed.TransformedPart; import com.jozufozu.flywheel.util.AnimationTickHolder; import com.mojang.math.Quaternion; import com.mojang.math.Vector3f; diff --git a/src/main/java/com/jozufozu/flywheel/vanilla/MinecartInstance.java b/src/main/java/com/jozufozu/flywheel/vanilla/MinecartInstance.java index e12f6d37e..d1ae67501 100644 --- a/src/main/java/com/jozufozu/flywheel/vanilla/MinecartInstance.java +++ b/src/main/java/com/jozufozu/flywheel/vanilla/MinecartInstance.java @@ -12,7 +12,7 @@ import com.jozufozu.flywheel.core.model.Mesh; import com.jozufozu.flywheel.core.model.Models; import com.jozufozu.flywheel.core.model.SimpleLazyModel; import com.jozufozu.flywheel.core.structs.StructTypes; -import com.jozufozu.flywheel.core.structs.model.TransformedPart; +import com.jozufozu.flywheel.core.structs.transformed.TransformedPart; import com.jozufozu.flywheel.util.AnimationTickHolder; import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.vertex.PoseStack; diff --git a/src/main/java/com/jozufozu/flywheel/vanilla/ShulkerBoxInstance.java b/src/main/java/com/jozufozu/flywheel/vanilla/ShulkerBoxInstance.java index cc9aadb8a..cfe63f41d 100644 --- a/src/main/java/com/jozufozu/flywheel/vanilla/ShulkerBoxInstance.java +++ b/src/main/java/com/jozufozu/flywheel/vanilla/ShulkerBoxInstance.java @@ -12,7 +12,7 @@ import com.jozufozu.flywheel.core.Materials; import com.jozufozu.flywheel.core.hardcoded.ModelPart; import com.jozufozu.flywheel.core.model.SimpleLazyModel; import com.jozufozu.flywheel.core.structs.StructTypes; -import com.jozufozu.flywheel.core.structs.model.TransformedPart; +import com.jozufozu.flywheel.core.structs.transformed.TransformedPart; import com.jozufozu.flywheel.util.AnimationTickHolder; import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.vertex.PoseStack; diff --git a/src/main/java/com/jozufozu/flywheel/vanilla/effect/ExampleEffect.java b/src/main/java/com/jozufozu/flywheel/vanilla/effect/ExampleEffect.java index 5c583534c..c0adede2e 100644 --- a/src/main/java/com/jozufozu/flywheel/vanilla/effect/ExampleEffect.java +++ b/src/main/java/com/jozufozu/flywheel/vanilla/effect/ExampleEffect.java @@ -13,7 +13,7 @@ import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import com.jozufozu.flywheel.backend.instancing.effect.Effect; import com.jozufozu.flywheel.core.model.Models; import com.jozufozu.flywheel.core.structs.StructTypes; -import com.jozufozu.flywheel.core.structs.model.TransformedPart; +import com.jozufozu.flywheel.core.structs.transformed.TransformedPart; import com.jozufozu.flywheel.event.ReloadRenderersEvent; import com.jozufozu.flywheel.util.AnimationTickHolder; import com.jozufozu.flywheel.util.box.GridAlignedBB; From 293d6ee59c11f5d946927c4ef95b742c02d7da48 Mon Sep 17 00:00:00 2001 From: PepperCode1 <44146161+PepperCode1@users.noreply.github.com> Date: Thu, 11 Aug 2022 15:48:08 -0700 Subject: [PATCH 3/5] Fix tracked MemoryBlocks --- .../flywheel/api/struct/StructWriter.java | 4 +- .../backend/memory/FlwMemoryTracker.java | 46 +++++++------------ .../flywheel/backend/memory/MemoryBlock.java | 4 +- .../backend/memory/MemoryBlockImpl.java | 5 ++ .../memory/TrackedMemoryBlockImpl.java | 43 +++++++++++++---- 5 files changed, 60 insertions(+), 42 deletions(-) diff --git a/src/main/java/com/jozufozu/flywheel/api/struct/StructWriter.java b/src/main/java/com/jozufozu/flywheel/api/struct/StructWriter.java index beb89d025..5b1e0bd33 100644 --- a/src/main/java/com/jozufozu/flywheel/api/struct/StructWriter.java +++ b/src/main/java/com/jozufozu/flywheel/api/struct/StructWriter.java @@ -3,11 +3,11 @@ package com.jozufozu.flywheel.api.struct; import com.jozufozu.flywheel.api.instancer.InstancedPart; /** - * StructWriters can quickly consume many instances of S and write them to some backing buffer. + * StructWriters can quickly consume many instances of S and write them to some memory address. */ public interface StructWriter { /** - * Write the given struct to given memory address. + * Write the given struct to the given memory address. */ void write(long ptr, S struct); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/memory/FlwMemoryTracker.java b/src/main/java/com/jozufozu/flywheel/backend/memory/FlwMemoryTracker.java index c398eb223..80d1c486b 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/memory/FlwMemoryTracker.java +++ b/src/main/java/com/jozufozu/flywheel/backend/memory/FlwMemoryTracker.java @@ -21,50 +21,40 @@ public class FlwMemoryTracker { public static MemoryBlock mallocBlock(long size) { MemoryBlock block = new MemoryBlockImpl(malloc(size), size); - cpuMemory += block.size(); + _allocCPUMemory(block.size()); return block; } public static MemoryBlock mallocBlockTracked(long size) { - TrackedMemoryBlockImpl block = new TrackedMemoryBlockImpl(malloc(size), size); - block.cleanable = CLEANER.register(block, () -> { - if (!block.isFreed()) { - block.free(); - } - }); - cpuMemory += block.size(); + MemoryBlock block = new TrackedMemoryBlockImpl(malloc(size), size, CLEANER); + _allocCPUMemory(block.size()); return block; } @Deprecated public static ByteBuffer mallocBuffer(int size) { ByteBuffer buffer = MemoryUtil.memByteBuffer(malloc(size), size); - cpuMemory += buffer.capacity(); + _allocCPUMemory(buffer.capacity()); return buffer; } public static long calloc(long num, long size) { long ptr = MemoryUtil.nmemCalloc(num, size); if (ptr == MemoryUtil.NULL) { - throw new OutOfMemoryError("Failed to allocate " + num + " blocks of size " + size + " bytes"); + throw new OutOfMemoryError("Failed to allocate " + num + " elements of size " + size + " bytes"); } return ptr; } public static MemoryBlock callocBlock(long num, long size) { MemoryBlock block = new MemoryBlockImpl(calloc(num, size), num * size); - cpuMemory += block.size(); + _allocCPUMemory(block.size()); return block; } public static MemoryBlock callocBlockTracked(long num, long size) { - TrackedMemoryBlockImpl block = new TrackedMemoryBlockImpl(calloc(num, size), num * size); - block.cleanable = CLEANER.register(block, () -> { - if (!block.isFreed()) { - block.free(); - } - }); - cpuMemory += block.size(); + MemoryBlock block = new TrackedMemoryBlockImpl(calloc(num, size), num * size, CLEANER); + _allocCPUMemory(block.size()); return block; } @@ -78,25 +68,23 @@ public class FlwMemoryTracker { public static MemoryBlock reallocBlock(MemoryBlock block, long size) { MemoryBlock newBlock = new MemoryBlockImpl(realloc(block.ptr(), size), size); - cpuMemory += -block.size() + newBlock.size(); + _freeCPUMemory(block.size()); + _allocCPUMemory(newBlock.size()); return newBlock; } public static MemoryBlock reallocBlockTracked(MemoryBlock block, long size) { - TrackedMemoryBlockImpl newBlock = new TrackedMemoryBlockImpl(realloc(block.ptr(), size), size); - newBlock.cleanable = CLEANER.register(newBlock, () -> { - if (!newBlock.isFreed()) { - newBlock.free(); - } - }); - cpuMemory += -block.size() + newBlock.size(); + MemoryBlock newBlock = new TrackedMemoryBlockImpl(realloc(block.ptr(), size), size, CLEANER); + _freeCPUMemory(block.size()); + _allocCPUMemory(newBlock.size()); return newBlock; } @Deprecated public static ByteBuffer reallocBuffer(ByteBuffer buffer, int size) { ByteBuffer newBuffer = MemoryUtil.memByteBuffer(realloc(MemoryUtil.memAddress(buffer), size), size); - cpuMemory += -buffer.capacity() + newBuffer.capacity(); + _freeCPUMemory(buffer.capacity()); + _allocCPUMemory(newBuffer.capacity()); return newBuffer; } @@ -106,13 +94,13 @@ public class FlwMemoryTracker { public static void freeBlock(MemoryBlock block) { free(block.ptr()); - cpuMemory -= block.size(); + _freeCPUMemory(block.size()); } @Deprecated public static void freeBuffer(ByteBuffer buffer) { free(MemoryUtil.memAddress(buffer)); - cpuMemory -= buffer.capacity(); + _freeCPUMemory(buffer.capacity()); } public static void _allocCPUMemory(long size) { diff --git a/src/main/java/com/jozufozu/flywheel/backend/memory/MemoryBlock.java b/src/main/java/com/jozufozu/flywheel/backend/memory/MemoryBlock.java index c78b8c193..9b6ad2cea 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/memory/MemoryBlock.java +++ b/src/main/java/com/jozufozu/flywheel/backend/memory/MemoryBlock.java @@ -13,9 +13,7 @@ public sealed interface MemoryBlock permits MemoryBlockImpl { void copyTo(long ptr, long bytes); - default void copyTo(long ptr) { - copyTo(ptr, size()); - } + void copyTo(long ptr); void clear(); diff --git a/src/main/java/com/jozufozu/flywheel/backend/memory/MemoryBlockImpl.java b/src/main/java/com/jozufozu/flywheel/backend/memory/MemoryBlockImpl.java index 1b6d984a6..a3fb15a60 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/memory/MemoryBlockImpl.java +++ b/src/main/java/com/jozufozu/flywheel/backend/memory/MemoryBlockImpl.java @@ -40,6 +40,11 @@ sealed class MemoryBlockImpl implements MemoryBlock permits TrackedMemoryBlockIm MemoryUtil.memCopy(this.ptr, ptr, bytes); } + @Override + public void copyTo(long ptr) { + copyTo(ptr, size); + } + @Override public void clear() { MemoryUtil.memSet(ptr, 0, size); diff --git a/src/main/java/com/jozufozu/flywheel/backend/memory/TrackedMemoryBlockImpl.java b/src/main/java/com/jozufozu/flywheel/backend/memory/TrackedMemoryBlockImpl.java index 40b1a15eb..a37ba3590 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/memory/TrackedMemoryBlockImpl.java +++ b/src/main/java/com/jozufozu/flywheel/backend/memory/TrackedMemoryBlockImpl.java @@ -3,10 +3,13 @@ package com.jozufozu.flywheel.backend.memory; import java.lang.ref.Cleaner; final class TrackedMemoryBlockImpl extends MemoryBlockImpl { - Cleaner.Cleanable cleanable; + final CleaningAction cleaningAction; + final Cleaner.Cleanable cleanable; - TrackedMemoryBlockImpl(long ptr, long size) { + TrackedMemoryBlockImpl(long ptr, long size, Cleaner cleaner) { super(ptr, size); + cleaningAction = new CleaningAction(ptr, size); + cleanable = cleaner.register(this, cleaningAction); } @Override @@ -14,25 +17,49 @@ final class TrackedMemoryBlockImpl extends MemoryBlockImpl { return true; } + void freeInner() { + freed = true; + cleaningAction.freed = true; + cleanable.clean(); + } + @Override public MemoryBlock realloc(long size) { MemoryBlock block = FlwMemoryTracker.reallocBlock(this, size); - freed = true; - cleanable.clean(); + freeInner(); return block; } @Override public MemoryBlock reallocTracked(long size) { MemoryBlock block = FlwMemoryTracker.reallocBlockTracked(this, size); - freed = true; - cleanable.clean(); + freeInner(); return block; } @Override public void free() { - cleanable.clean(); - freed = true; + FlwMemoryTracker.freeBlock(this); + freeInner(); + } + + static class CleaningAction implements Runnable { + final long ptr; + final long size; + + boolean freed; + + CleaningAction(long ptr, long size) { + this.ptr = ptr; + this.size = size; + } + + @Override + public void run() { + if (!freed) { + FlwMemoryTracker.free(ptr); + FlwMemoryTracker._freeCPUMemory(size); + } + } } } From a1553b04e72b88e17e9e5db8bddda8b646db7034 Mon Sep 17 00:00:00 2001 From: Jozufozu Date: Sat, 13 Aug 2022 23:18:44 -0700 Subject: [PATCH 4/5] So unsafe it wrapped back around - Convert buffer mapping to unsafe - Implement gpu memory tracking - Fix massive gl resource leak - Fix GPU memory leak caused by not deleting gl resources - Fix CPU memory leak caused by not deleting meshes in Models - Remove PersistentGlBuffer, merge GlBuffer and MappedGlBuffer --- .../flywheel/api/uniform/UniformProvider.java | 6 +- .../backend/gl/array/GlVertexArray.java | 2 +- .../flywheel/backend/gl/buffer/GlBuffer.java | 130 ++++++++++++------ .../backend/gl/buffer/MappedBuffer.java | 30 ++-- .../backend/gl/buffer/MappedGlBuffer.java | 91 ------------ .../backend/gl/buffer/PersistentGlBuffer.java | 124 ----------------- .../backend/instancing/InstanceWorld.java | 6 +- .../instancing/batching/DrawBuffer.java | 2 +- .../instancing/instancing/GPUInstancer.java | 11 +- .../instancing/instancing/MeshPool.java | 19 +-- .../flywheel/core/FullscreenQuad.java | 14 +- .../jozufozu/flywheel/core/QuadConverter.java | 34 ++--- .../jozufozu/flywheel/core/model/Model.java | 2 + .../jozufozu/flywheel/core/model/Models.java | 9 ++ .../flywheel/core/model/SimpleLazyModel.java | 5 + .../flywheel/core/model/TessellatedModel.java | 6 + .../flywheel/core/uniform/FogProvider.java | 4 +- .../flywheel/core/uniform/UniformBuffer.java | 17 ++- .../flywheel/core/uniform/ViewProvider.java | 4 +- .../jozufozu/flywheel/event/ForgeEvents.java | 3 +- .../jozufozu/flywheel/util/StringUtil.java | 20 ++- .../jozufozu/flywheel/util/WorldAttached.java | 11 +- 22 files changed, 191 insertions(+), 359 deletions(-) delete mode 100644 src/main/java/com/jozufozu/flywheel/backend/gl/buffer/MappedGlBuffer.java delete mode 100644 src/main/java/com/jozufozu/flywheel/backend/gl/buffer/PersistentGlBuffer.java diff --git a/src/main/java/com/jozufozu/flywheel/api/uniform/UniformProvider.java b/src/main/java/com/jozufozu/flywheel/api/uniform/UniformProvider.java index 2e189f452..62890b521 100644 --- a/src/main/java/com/jozufozu/flywheel/api/uniform/UniformProvider.java +++ b/src/main/java/com/jozufozu/flywheel/api/uniform/UniformProvider.java @@ -6,13 +6,13 @@ import com.jozufozu.flywheel.core.source.FileResolution; public abstract class UniformProvider { - protected ByteBuffer buffer; + protected long ptr; protected Notifier notifier; public abstract int getSize(); - public void updatePtr(ByteBuffer backing, Notifier notifier) { - this.buffer = backing; + public void updatePtr(long ptr, Notifier notifier) { + this.ptr = ptr; this.notifier = notifier; } diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/array/GlVertexArray.java b/src/main/java/com/jozufozu/flywheel/backend/gl/array/GlVertexArray.java index 3abf7a7d0..69efb178f 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/array/GlVertexArray.java +++ b/src/main/java/com/jozufozu/flywheel/backend/gl/array/GlVertexArray.java @@ -5,8 +5,8 @@ import org.lwjgl.opengl.GL32; import com.jozufozu.flywheel.backend.gl.GlObject; import com.jozufozu.flywheel.backend.gl.GlStateTracker; -import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer; import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType; +import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer; import com.jozufozu.flywheel.backend.gl.versioned.GlCompat; import com.jozufozu.flywheel.core.layout.BufferLayout; import com.mojang.blaze3d.platform.GlStateManager; diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/GlBuffer.java b/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/GlBuffer.java index 395c514ec..edfff94d3 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/GlBuffer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/GlBuffer.java @@ -1,49 +1,105 @@ package com.jozufozu.flywheel.backend.gl.buffer; -import java.nio.ByteBuffer; +import static org.lwjgl.opengl.GL32.*; -import org.lwjgl.opengl.GL20; +import org.lwjgl.system.MemoryUtil; import com.jozufozu.flywheel.backend.gl.GlObject; -import com.jozufozu.flywheel.backend.gl.versioned.GlCompat; +import com.jozufozu.flywheel.backend.gl.error.GlError; +import com.jozufozu.flywheel.backend.gl.error.GlException; +import com.jozufozu.flywheel.backend.memory.FlwMemoryTracker; +import com.jozufozu.flywheel.backend.memory.MemoryBlock; -public abstract class GlBuffer extends GlObject { - - /** - * Request a Persistent mapped buffer. - * - *

- * If Persistent buffers are supported, this will provide one. Otherwise it will fall back to a classic mapped - * buffer. - *

- * - * @param type The type of buffer you want. - * @return A buffer that will be persistent if the driver supports it. - */ - public static GlBuffer requestPersistent(GlBufferType type) { - if (GlCompat.getInstance() - .bufferStorageSupported()) { - return new PersistentGlBuffer(type); - } else { - return new MappedGlBuffer(type); - } - } +public class GlBuffer extends GlObject { public final GlBufferType type; - + protected final GlBufferUsage usage; /** * The size (in bytes) of the buffer on the GPU. */ protected long size; - /** * How much extra room to give the buffer when we reallocate. */ protected int growthMargin; public GlBuffer(GlBufferType type) { - setHandle(GL20.glGenBuffers()); + this(type, GlBufferUsage.STATIC_DRAW); + } + + public GlBuffer(GlBufferType type, GlBufferUsage usage) { + setHandle(glGenBuffers()); this.type = type; + this.usage = usage; + } + + public boolean ensureCapacity(long size) { + if (size < 0) { + throw new IllegalArgumentException("Size " + size + " < 0"); + } + + if (size == 0) { + return false; + } + + if (this.size == 0) { + this.size = size; + bind(); + glBufferData(type.glEnum, size, usage.glEnum); + FlwMemoryTracker._allocGPUMemory(size); + + return true; + } + + if (size > this.size) { + var oldSize = this.size; + this.size = size + growthMargin; + + realloc(oldSize, this.size); + + return true; + } + + return false; + } + + private void realloc(long oldSize, long newSize) { + FlwMemoryTracker._freeGPUMemory(oldSize); + FlwMemoryTracker._allocGPUMemory(newSize); + var oldHandle = handle(); + var newHandle = glGenBuffers(); + + GlBufferType.COPY_READ_BUFFER.bind(oldHandle); + type.bind(newHandle); + + glBufferData(type.glEnum, newSize, usage.glEnum); + glCopyBufferSubData(GlBufferType.COPY_READ_BUFFER.glEnum, type.glEnum, 0, 0, oldSize); + + glDeleteBuffers(oldHandle); + setHandle(newHandle); + } + + public void upload(MemoryBlock directBuffer) { + bind(); + FlwMemoryTracker._freeGPUMemory(size); + nglBufferData(type.glEnum, directBuffer.size(), directBuffer.ptr(), usage.glEnum); + this.size = directBuffer.size(); + FlwMemoryTracker._allocGPUMemory(size); + } + + public MappedBuffer map() { + bind(); + long ptr = nglMapBufferRange(type.glEnum, 0, size, GL_MAP_WRITE_BIT); + + if (ptr == MemoryUtil.NULL) { + throw new GlException(GlError.poll(), "Could not map buffer"); + } + + return new MappedBuffer(this, ptr, 0, size); + } + + public boolean isPersistent() { + return false; } public void setGrowthMargin(int growthMargin) { @@ -66,24 +122,8 @@ public abstract class GlBuffer extends GlObject { type.unbind(); } - public abstract void upload(ByteBuffer directBuffer); - - public abstract MappedBuffer map(); - - /** - * Ensure that the buffer has at least enough room to store {@code size} bytes. - * - * @return {@code true} if the buffer moved. - */ - public abstract boolean ensureCapacity(long size); - protected void deleteInternal(int handle) { - GL20.glDeleteBuffers(handle); + glDeleteBuffers(handle); + FlwMemoryTracker._freeGPUMemory(size); } - - /** - * Indicates that this buffer need not be #flush()'d for its contents to sync. - * @return true if this buffer is persistently mapped. - */ - public abstract boolean isPersistent(); } 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 4ccdbe721..4b2da8992 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 @@ -1,6 +1,6 @@ package com.jozufozu.flywheel.backend.gl.buffer; -import java.nio.ByteBuffer; +import static org.lwjgl.system.MemoryUtil.NULL; import org.lwjgl.opengl.GL15; import org.lwjgl.system.MemoryUtil; @@ -11,10 +11,10 @@ public class MappedBuffer implements AutoCloseable { private final long length; private final GlBuffer owner; private final boolean persistent; - private ByteBuffer internal; + private long ptr; - public MappedBuffer(GlBuffer owner, ByteBuffer internal, long offset, long length) { - this.internal = internal; + public MappedBuffer(GlBuffer owner, long ptr, long offset, long length) { + this.ptr = ptr; this.owner = owner; this.offset = offset; this.length = length; @@ -27,19 +27,11 @@ public class MappedBuffer implements AutoCloseable { public void flush() { if (persistent) return; - if (internal == null) return; + if (ptr == NULL) return; owner.bind(); GL15.glUnmapBuffer(owner.getType().glEnum); - internal = null; - } - - public MappedBuffer position(int p) { - if (p < offset || p >= offset + length) { - throw new IndexOutOfBoundsException("Index " + p + " is not mapped"); - } - internal.position(p - (int) offset); - return this; + ptr = NULL; } @Override @@ -47,12 +39,8 @@ public class MappedBuffer implements AutoCloseable { flush(); } - public ByteBuffer unwrap() { - return internal; - } - - public long getMemAddress() { - return MemoryUtil.memAddress(internal); + public long getPtr() { + return ptr; } public void clear(long clearStart, long clearLength) { @@ -64,7 +52,7 @@ public class MappedBuffer implements AutoCloseable { throw new IndexOutOfBoundsException("Clear range [" + clearStart + "," + (clearStart + clearLength) + "] is not mapped"); } - long addr = MemoryUtil.memAddress(unwrap()) + clearStart; + long addr = ptr + clearStart; MemoryUtil.memSet(addr, 0, clearLength); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/MappedGlBuffer.java b/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/MappedGlBuffer.java deleted file mode 100644 index 6d0e5956b..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/MappedGlBuffer.java +++ /dev/null @@ -1,91 +0,0 @@ -package com.jozufozu.flywheel.backend.gl.buffer; - -import java.nio.ByteBuffer; - -import org.lwjgl.opengl.GL30; -import org.lwjgl.opengl.GL32; - -import com.jozufozu.flywheel.backend.gl.error.GlError; -import com.jozufozu.flywheel.backend.gl.error.GlException; - -public class MappedGlBuffer extends GlBuffer { - - protected final GlBufferUsage usage; - - public MappedGlBuffer(GlBufferType type) { - this(type, GlBufferUsage.STATIC_DRAW); - } - - public MappedGlBuffer(GlBufferType type, GlBufferUsage usage) { - super(type); - this.usage = usage; - } - - @Override - public boolean ensureCapacity(long size) { - if (size < 0) { - throw new IllegalArgumentException("Size " + size + " < 0"); - } - - if (size == 0) { - return false; - } - - if (this.size == 0) { - this.size = size; - bind(); - GL32.glBufferData(type.glEnum, size, usage.glEnum); - - return true; - } - - if (size > this.size) { - var oldSize = this.size; - this.size = size + growthMargin; - - realloc(oldSize, this.size); - - return true; - } - - return false; - } - - private void realloc(long oldSize, long newSize) { - var oldHandle = handle(); - var newHandle = GL32.glGenBuffers(); - - GlBufferType.COPY_READ_BUFFER.bind(oldHandle); - type.bind(newHandle); - - GL32.glBufferData(type.glEnum, newSize, usage.glEnum); - GL32.glCopyBufferSubData(GlBufferType.COPY_READ_BUFFER.glEnum, type.glEnum, 0, 0, oldSize); - - delete(); - setHandle(newHandle); - } - - @Override - public void upload(ByteBuffer directBuffer) { - bind(); - GL32.glBufferData(type.glEnum, directBuffer, usage.glEnum); - this.size = directBuffer.capacity(); - } - - @Override - public MappedBuffer map() { - bind(); - ByteBuffer byteBuffer = GL30.glMapBufferRange(type.glEnum, 0, size, GL30.GL_MAP_WRITE_BIT); - - if (byteBuffer == null) { - throw new GlException(GlError.poll(), "Could not map buffer"); - } - - return new MappedBuffer(this, byteBuffer, 0, size); - } - - @Override - public boolean isPersistent() { - return false; - } -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/PersistentGlBuffer.java b/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/PersistentGlBuffer.java deleted file mode 100644 index e0ffa6c26..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/PersistentGlBuffer.java +++ /dev/null @@ -1,124 +0,0 @@ -package com.jozufozu.flywheel.backend.gl.buffer; - -import static org.lwjgl.opengl.GL30.GL_MAP_WRITE_BIT; -import static org.lwjgl.opengl.GL44.GL_MAP_COHERENT_BIT; -import static org.lwjgl.opengl.GL44.GL_MAP_PERSISTENT_BIT; - -import java.nio.ByteBuffer; - -import org.jetbrains.annotations.Nullable; -import org.lwjgl.opengl.GL32; -import org.lwjgl.system.MemoryUtil; - -import com.jozufozu.flywheel.backend.gl.error.GlError; -import com.jozufozu.flywheel.backend.gl.error.GlException; -import com.jozufozu.flywheel.backend.gl.versioned.GlCompat; - -public class PersistentGlBuffer extends GlBuffer { - - @Nullable - private MappedBuffer access; - private final int storageFlags; - - public PersistentGlBuffer(GlBufferType type) { - super(type); - - storageFlags = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT; - } - - @Override - public boolean ensureCapacity(long size) { - if (size < 0) { - throw new IllegalArgumentException("Size " + size + " < 0"); - } - - if (size == 0) { - return false; - } - - if (this.size == 0) { - this.size = size; - bind(); - GlCompat.getInstance().bufferStorage.bufferStorage(type, this.size, storageFlags); - return true; - } - - if (size > this.size) { - var oldSize = this.size; - this.size = size + growthMargin; - - realloc(this.size, oldSize); - - access = null; - return true; - } - - return false; - } - - @Override - public void upload(ByteBuffer directBuffer) { - ensureCapacity(directBuffer.capacity()); - - var access = getWriteAccess(); - - ByteBuffer ourBuffer = access.unwrap(); - - ourBuffer.reset(); - - MemoryUtil.memCopy(directBuffer, ourBuffer); - - int uploadSize = directBuffer.remaining(); - int ourSize = ourBuffer.capacity(); - - if (uploadSize < ourSize) { - long clearFrom = access.getMemAddress() + uploadSize; - MemoryUtil.memSet(clearFrom, 0, ourSize - uploadSize); - } - } - - private void mapToClientMemory() { - bind(); - ByteBuffer byteBuffer = GL32.glMapBufferRange(type.glEnum, 0, size, storageFlags); - - if (byteBuffer == null) { - throw new GlException(GlError.poll(), "Could not map buffer"); - } - - access = new MappedBuffer(this, byteBuffer, 0, size); - } - - private void realloc(long newSize, long oldSize) { - int oldHandle = handle(); - int newHandle = GL32.glGenBuffers(); - - GlBufferType.COPY_READ_BUFFER.bind(oldHandle); - type.bind(newHandle); - - GlCompat.getInstance().bufferStorage.bufferStorage(type, newSize, storageFlags); - - GL32.glCopyBufferSubData(GlBufferType.COPY_READ_BUFFER.glEnum, type.glEnum, 0, 0, oldSize); - - delete(); - setHandle(newHandle); - } - - @Override - public MappedBuffer map() { - return getWriteAccess() - .position(0); - } - - private MappedBuffer getWriteAccess() { - if (access == null) { - mapToClientMemory(); - } - - return access; - } - - @Override - public boolean isPersistent() { - return true; - } -} 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 3962d4d1a..1f48ec759 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceWorld.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceWorld.java @@ -27,7 +27,7 @@ import net.minecraft.world.level.block.entity.BlockEntity; * The instancer manager is shared between the different instance managers. *

*/ -public class InstanceWorld { +public class InstanceWorld implements AutoCloseable { protected final Engine engine; protected final InstanceManager entities; protected final InstanceManager blockEntities; @@ -149,4 +149,8 @@ public class InstanceWorld { .forEach(entities::add); } + @Override + public void close() { + delete(); + } } 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 8559680ea..4e2cd4fc9 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 @@ -89,7 +89,7 @@ public class DrawBuffer { } /** - * Reset the draw buffer to have no vertices. + * Reset the draw buffer to have no vertices.

* * Does not clear the backing buffer. */ diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/GPUInstancer.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/GPUInstancer.java index 95015766a..cfce702fb 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/GPUInstancer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/GPUInstancer.java @@ -3,18 +3,15 @@ package com.jozufozu.flywheel.backend.instancing.instancing; import java.util.HashSet; import java.util.Set; -import org.lwjgl.system.MemoryUtil; - import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.api.instancer.InstancedPart; import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.api.struct.StructWriter; import com.jozufozu.flywheel.backend.gl.array.GlVertexArray; -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.MappedBuffer; -import com.jozufozu.flywheel.backend.gl.buffer.MappedGlBuffer; +import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer; import com.jozufozu.flywheel.backend.instancing.AbstractInstancer; import com.jozufozu.flywheel.core.layout.BufferLayout; @@ -45,7 +42,7 @@ public class GPUInstancer extends AbstractInstancer public void init() { if (vbo != null) return; - vbo = new MappedGlBuffer(GlBufferType.ARRAY_BUFFER, GlBufferUsage.DYNAMIC_DRAW); + vbo = new GlBuffer(GlBufferType.ARRAY_BUFFER, GlBufferUsage.DYNAMIC_DRAW); vbo.setGrowthMargin(instanceFormat.getStride() * 16); } @@ -91,8 +88,8 @@ public class GPUInstancer extends AbstractInstancer buf.clear(clearStart, clearLength); if (size > 0) { - final long ptr = MemoryUtil.memAddress(buf.unwrap()); - final int stride = structType.getLayout().getStride(); + final long ptr = buf.getPtr(); + final long stride = structType.getLayout().getStride(); final StructWriter writer = structType.getWriter(); for (int i = 0; i < size; i++) { diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/MeshPool.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/MeshPool.java index a5d7b6051..c43a49fc9 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/MeshPool.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/MeshPool.java @@ -1,6 +1,5 @@ package com.jozufozu.flywheel.backend.instancing.instancing; -import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -10,16 +9,14 @@ import java.util.Set; import org.jetbrains.annotations.Nullable; import org.lwjgl.opengl.GL32; -import org.lwjgl.system.MemoryUtil; import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.backend.gl.GlPrimitive; import com.jozufozu.flywheel.backend.gl.array.GlVertexArray; -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.gl.buffer.GlBuffer; import com.jozufozu.flywheel.core.layout.BufferLayout; import com.jozufozu.flywheel.core.model.Mesh; import com.jozufozu.flywheel.event.ReloadRenderersEvent; @@ -58,7 +55,7 @@ public class MeshPool { * Create a new mesh pool. */ public MeshPool() { - vbo = new MappedGlBuffer(GlBufferType.ARRAY_BUFFER); + vbo = new GlBuffer(GlBufferType.ARRAY_BUFFER); vbo.setGrowthMargin(2048); } @@ -141,13 +138,13 @@ public class MeshPool { private void uploadAll() { try (MappedBuffer mapped = vbo.map()) { - ByteBuffer buffer = mapped.unwrap(); + long ptr = mapped.getPtr(); int byteIndex = 0; for (BufferedMesh model : allBuffered) { model.byteIndex = byteIndex; - model.buffer(buffer); + model.buffer(ptr); byteIndex += model.mesh.size(); } @@ -159,7 +156,7 @@ public class MeshPool { private void uploadPending() { try (MappedBuffer mapped = vbo.map()) { - ByteBuffer buffer = mapped.unwrap(); + long buffer = mapped.getPtr(); for (BufferedMesh model : pendingUpload) { model.buffer(buffer); } @@ -240,10 +237,8 @@ public class MeshPool { this.deleted = true; } - private void buffer(ByteBuffer buffer) { - buffer.position((int) this.byteIndex); - long ptr = MemoryUtil.memAddress(buffer); - this.mesh.write(ptr); + private void buffer(long ptr) { + this.mesh.write(ptr + byteIndex); this.boundTo.clear(); this.gpuResident = true; diff --git a/src/main/java/com/jozufozu/flywheel/core/FullscreenQuad.java b/src/main/java/com/jozufozu/flywheel/core/FullscreenQuad.java index c3282c2ae..79b49df58 100644 --- a/src/main/java/com/jozufozu/flywheel/core/FullscreenQuad.java +++ b/src/main/java/com/jozufozu/flywheel/core/FullscreenQuad.java @@ -3,13 +3,14 @@ package com.jozufozu.flywheel.core; import static org.lwjgl.opengl.GL11.GL_TRIANGLES; import static org.lwjgl.opengl.GL11.glDrawArrays; +import org.lwjgl.system.MemoryUtil; + import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.backend.gl.GlStateTracker; import com.jozufozu.flywheel.backend.gl.array.GlVertexArray; -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.gl.buffer.GlBuffer; import com.jozufozu.flywheel.core.layout.BufferLayout; import com.jozufozu.flywheel.core.layout.CommonItems; import com.jozufozu.flywheel.util.Lazy; @@ -34,13 +35,14 @@ public class FullscreenQuad { private FullscreenQuad() { try (var restoreState = GlStateTracker.getRestoreState()) { - vbo = new MappedGlBuffer(GlBufferType.ARRAY_BUFFER); + vbo = new GlBuffer(GlBufferType.ARRAY_BUFFER); vbo.ensureCapacity(bufferSize); try (MappedBuffer buffer = vbo.map()) { + var ptr = buffer.getPtr(); - buffer.unwrap() - .asFloatBuffer() - .put(vertices); + for (var i = 0; i < vertices.length; i++) { + MemoryUtil.memPutFloat(ptr + i * Float.BYTES, vertices[i]); + } } catch (Exception e) { Flywheel.LOGGER.error("Could not create fullscreen quad.", e); diff --git a/src/main/java/com/jozufozu/flywheel/core/QuadConverter.java b/src/main/java/com/jozufozu/flywheel/core/QuadConverter.java index 0b2477214..93427f829 100644 --- a/src/main/java/com/jozufozu/flywheel/core/QuadConverter.java +++ b/src/main/java/com/jozufozu/flywheel/core/QuadConverter.java @@ -1,7 +1,5 @@ package com.jozufozu.flywheel.core; -import java.nio.ByteBuffer; - import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.lwjgl.system.MemoryUtil; @@ -9,7 +7,7 @@ import org.lwjgl.system.MemoryUtil; import com.jozufozu.flywheel.backend.gl.GlNumericType; 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.gl.buffer.GlBuffer; import com.jozufozu.flywheel.backend.instancing.instancing.ElementBuffer; import com.jozufozu.flywheel.event.ReloadRenderersEvent; @@ -34,11 +32,11 @@ public class QuadConverter { return INSTANCE; } - private final MappedGlBuffer ebo; + private final GlBuffer ebo; private int quadCapacity; public QuadConverter() { - this.ebo = new MappedGlBuffer(GlBufferType.ELEMENT_ARRAY_BUFFER); + this.ebo = new GlBuffer(GlBufferType.ELEMENT_ARRAY_BUFFER); this.quadCapacity = 0; } @@ -49,9 +47,7 @@ public class QuadConverter { ebo.ensureCapacity((long) indexCount * GlNumericType.UINT.getByteWidth()); try (MappedBuffer map = ebo.map()) { - ByteBuffer indices = map.unwrap(); - - fillBuffer(indices, quads); + fillBuffer(map.getPtr(), quads); } ebo.unbind(); @@ -66,32 +62,18 @@ public class QuadConverter { this.quadCapacity = 0; } - private void fillBuffer(ByteBuffer indices, int quads) { - long addr = MemoryUtil.memAddress(indices); + private void fillBuffer(long addr, int quads) { int numVertices = 4 * quads; int baseVertex = 0; while (baseVertex < numVertices) { - // writeQuadIndices(indices, baseVertex); - writeQuadIndicesUnsafe(addr, baseVertex); + writeQuadIndices(addr, baseVertex); baseVertex += 4; addr += 6 * 4; } - // ((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 void writeQuadIndicesUnsafe(long addr, int baseVertex) { + private void writeQuadIndices(long addr, int baseVertex) { // triangle a MemoryUtil.memPutInt(addr, baseVertex); MemoryUtil.memPutInt(addr + 4, baseVertex + 1); @@ -102,7 +84,7 @@ public class QuadConverter { MemoryUtil.memPutInt(addr + 20, baseVertex + 3); } - // make sure this gets reset first so it has a chance to repopulate + // make sure this gets reset first, so it has a chance to repopulate public static void onRendererReload(ReloadRenderersEvent event) { if (INSTANCE != null) { INSTANCE.delete(); 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 e0d247387..092c4a3cd 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/Model.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/Model.java @@ -7,6 +7,8 @@ import com.jozufozu.flywheel.api.material.Material; public interface Model { Map getMeshes(); + void delete(); + default int getVertexCount() { int size = 0; for (Mesh mesh : getMeshes().values()) { diff --git a/src/main/java/com/jozufozu/flywheel/core/model/Models.java b/src/main/java/com/jozufozu/flywheel/core/model/Models.java index 4891a3cd6..d327abc34 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/Models.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/Models.java @@ -1,5 +1,6 @@ package com.jozufozu.flywheel.core.model; +import java.util.Collection; import java.util.HashMap; import java.util.Map; @@ -41,8 +42,16 @@ public class Models { } public static void onReload(ReloadRenderersEvent event) { + deleteAll(BLOCK_STATE.values()); + deleteAll(PARTIAL.values()); + deleteAll(PARTIAL_DIR.values()); + BLOCK_STATE.clear(); PARTIAL.clear(); PARTIAL_DIR.clear(); } + + private static void deleteAll(Collection values) { + values.forEach(Model::delete); + } } diff --git a/src/main/java/com/jozufozu/flywheel/core/model/SimpleLazyModel.java b/src/main/java/com/jozufozu/flywheel/core/model/SimpleLazyModel.java index 7933854d2..3af609e4f 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/SimpleLazyModel.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/SimpleLazyModel.java @@ -28,6 +28,11 @@ public class SimpleLazyModel implements Model { return ImmutableMap.of(material, supplier.get()); } + @Override + public void delete() { + supplier.ifPresent(Mesh::close); + } + public int getVertexCount() { return supplier.map(Mesh::getVertexCount) .orElse(0); diff --git a/src/main/java/com/jozufozu/flywheel/core/model/TessellatedModel.java b/src/main/java/com/jozufozu/flywheel/core/model/TessellatedModel.java index 0f987bb71..d1986dc6e 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/TessellatedModel.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/TessellatedModel.java @@ -19,6 +19,12 @@ public class TessellatedModel implements Model { return meshes; } + @Override + public void delete() { + meshes.values() + .forEach(Mesh::close); + } + public boolean isShadeSeparated() { return shadeSeparated; } diff --git a/src/main/java/com/jozufozu/flywheel/core/uniform/FogProvider.java b/src/main/java/com/jozufozu/flywheel/core/uniform/FogProvider.java index 9bea01220..29873074b 100644 --- a/src/main/java/com/jozufozu/flywheel/core/uniform/FogProvider.java +++ b/src/main/java/com/jozufozu/flywheel/core/uniform/FogProvider.java @@ -15,14 +15,12 @@ public class FogProvider extends UniformProvider { } public void update() { - if (buffer == null) { + if (ptr == MemoryUtil.NULL) { return; } var color = RenderSystem.getShaderFogColor(); - long ptr = MemoryUtil.memAddress(buffer); - MemoryUtil.memPutFloat(ptr, color[0]); MemoryUtil.memPutFloat(ptr + 4, color[1]); MemoryUtil.memPutFloat(ptr + 8, color[2]); diff --git a/src/main/java/com/jozufozu/flywheel/core/uniform/UniformBuffer.java b/src/main/java/com/jozufozu/flywheel/core/uniform/UniformBuffer.java index 068fbc4c0..e1c88b815 100644 --- a/src/main/java/com/jozufozu/flywheel/core/uniform/UniformBuffer.java +++ b/src/main/java/com/jozufozu/flywheel/core/uniform/UniformBuffer.java @@ -1,6 +1,5 @@ package com.jozufozu.flywheel.core.uniform; -import java.nio.ByteBuffer; import java.util.BitSet; import java.util.Collection; import java.util.List; @@ -11,8 +10,8 @@ import org.lwjgl.system.MemoryUtil; import com.google.common.collect.ImmutableList; import com.jozufozu.flywheel.api.uniform.UniformProvider; import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType; -import com.jozufozu.flywheel.backend.gl.buffer.MappedGlBuffer; -import com.jozufozu.flywheel.backend.memory.FlwMemoryTracker; +import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer; +import com.jozufozu.flywheel.backend.memory.MemoryBlock; import com.jozufozu.flywheel.core.ComponentRegistry; import com.jozufozu.flywheel.util.RenderMath; @@ -33,13 +32,13 @@ public class UniformBuffer { return instance; } - private final MappedGlBuffer buffer; - private final ByteBuffer data; + private final GlBuffer buffer; + private final MemoryBlock data; private final BitSet changedBytes; private UniformBuffer() { - buffer = new MappedGlBuffer(GlBufferType.UNIFORM_BUFFER); + buffer = new GlBuffer(GlBufferType.UNIFORM_BUFFER); Collection providers = ComponentRegistry.getAllUniformProviders(); @@ -57,7 +56,7 @@ public class UniformBuffer { allocatedProviders = builder.build(); - data = FlwMemoryTracker.mallocBuffer(totalBytes); + data = MemoryBlock.mallocTracked(totalBytes); changedBytes = new BitSet(totalBytes); for (Allocated p : allocatedProviders) { @@ -108,8 +107,8 @@ public class UniformBuffer { changedBytes.set(offset, offset + size); } - private void updatePtr(ByteBuffer bufferBase) { - provider.updatePtr(MemoryUtil.memSlice(bufferBase, offset, size), this); + private void updatePtr(MemoryBlock bufferBase) { + provider.updatePtr(bufferBase.ptr() + offset, this); } public UniformProvider provider() { diff --git a/src/main/java/com/jozufozu/flywheel/core/uniform/ViewProvider.java b/src/main/java/com/jozufozu/flywheel/core/uniform/ViewProvider.java index 1d5535b6d..437b5cdcd 100644 --- a/src/main/java/com/jozufozu/flywheel/core/uniform/ViewProvider.java +++ b/src/main/java/com/jozufozu/flywheel/core/uniform/ViewProvider.java @@ -31,7 +31,7 @@ public class ViewProvider extends UniformProvider { } public void update(RenderContext context) { - if (buffer == null) { + if (ptr == MemoryUtil.NULL) { return; } @@ -52,8 +52,6 @@ public class ViewProvider extends UniformProvider { var vp = context.viewProjection().copy(); vp.multiplyWithTranslation(-camX, -camY, -camZ); - long ptr = MemoryUtil.memAddress(buffer); - MatrixWrite.writeUnsafe(vp, ptr); MemoryUtil.memPutFloat(ptr + 64, camX); MemoryUtil.memPutFloat(ptr + 68, camY); diff --git a/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java b/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java index 26bc79290..793f519ca 100644 --- a/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java +++ b/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java @@ -7,6 +7,7 @@ import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import com.jozufozu.flywheel.backend.memory.FlwMemoryTracker; import com.jozufozu.flywheel.light.LightUpdater; +import com.jozufozu.flywheel.util.StringUtil; import com.jozufozu.flywheel.util.WorldAttached; import net.minecraft.client.Minecraft; @@ -24,7 +25,7 @@ public class ForgeEvents { InstancedRenderDispatcher.getDebugString(debug); - debug.add("Memory Usage: CPU: " + FlwMemoryTracker.getCPUMemory() / 1024 + "KiB GPU: " + FlwMemoryTracker.getGPUMemory() / 1024 + "KiB"); + debug.add("Memory Usage: CPU: " + StringUtil.formatBytes(FlwMemoryTracker.getCPUMemory()) + ", GPU: " + StringUtil.formatBytes(FlwMemoryTracker.getGPUMemory())); } } diff --git a/src/main/java/com/jozufozu/flywheel/util/StringUtil.java b/src/main/java/com/jozufozu/flywheel/util/StringUtil.java index 4b7049b74..cdf8c6952 100644 --- a/src/main/java/com/jozufozu/flywheel/util/StringUtil.java +++ b/src/main/java/com/jozufozu/flywheel/util/StringUtil.java @@ -19,17 +19,29 @@ import com.jozufozu.flywheel.backend.memory.FlwMemoryTracker; public class StringUtil { - private static final NumberFormat timeFormat = new DecimalFormat("#0.000"); + private static final NumberFormat THREE_DECIMAL_PLACES = new DecimalFormat("#0.000"); + + public static String formatBytes(long bytes) { + if (bytes < 1024) { + return bytes + " B"; + } else if (bytes < 1024 * 1024) { + return THREE_DECIMAL_PLACES.format(bytes / 1024f) + " KB"; + } else if (bytes < 1024 * 1024 * 1024) { + return THREE_DECIMAL_PLACES.format(bytes / 1024f / 1024f) + " MB"; + } else { + return THREE_DECIMAL_PLACES.format(bytes / 1024f / 1024f / 1024f) + " GB"; + } + } public static String formatTime(long ns) { if (ns < 1000) { return ns + " ns"; } else if (ns < 1000000) { - return timeFormat.format(ns / 1000.) + " μs"; + return THREE_DECIMAL_PLACES.format(ns / 1000f) + " μs"; } else if (ns < 1000000000) { - return timeFormat.format(ns / 1000000.) + " ms"; + return THREE_DECIMAL_PLACES.format(ns / 1000000f) + " ms"; } else { - return timeFormat.format(ns / 1000000000.) + " s"; + return THREE_DECIMAL_PLACES.format(ns / 1000000000f) + " s"; } } diff --git a/src/main/java/com/jozufozu/flywheel/util/WorldAttached.java b/src/main/java/com/jozufozu/flywheel/util/WorldAttached.java index cb41e9fd1..93b79a310 100644 --- a/src/main/java/com/jozufozu/flywheel/util/WorldAttached.java +++ b/src/main/java/com/jozufozu/flywheel/util/WorldAttached.java @@ -36,7 +36,16 @@ public class WorldAttached { i.remove(); } else { // Prevent leaks - map.remove(world); + Object attached = map.remove(world); + + // No, *really* prevent leaks + if (attached instanceof AutoCloseable closeable) { + try { + closeable.close(); + } catch (Exception ignored) { + + } + } } } } From 9b39ba6c32bf03f4acafd1c3047f902b0491533e Mon Sep 17 00:00:00 2001 From: PepperCode1 <44146161+PepperCode1@users.noreply.github.com> Date: Sun, 14 Aug 2022 21:42:44 -0700 Subject: [PATCH 5/5] Hazardous light - BatchingEngine no longer resets the light matrices - Fix flw_constantAmbientLight always being 0 - Move code from FlwMemoryTracker#*Block methods into MemoryBlockImpl and TrackedMemoryBlockImpl - Convert LightVolume to use MemoryBlock - Add FlwMemoryTracker#callocBuffer - Add javadoc to deprecated FlwMemoryTracker#*Buffer methods - Update Mesh javadoc - Organize imports --- .../flywheel/api/material/Material.java | 2 +- .../flywheel/api/struct/StructType.java | 2 +- .../flywheel/api/uniform/UniformProvider.java | 2 - .../backend/gl/array/GlVertexArray.java | 2 +- .../flywheel/backend/gl/buffer/GlBuffer.java | 8 +- .../instancing/batching/BatchingEngine.java | 11 - .../instancing/batching/TransformSet.java | 33 +- .../instancing/instancing/GPUInstancer.java | 2 +- .../instancing/instancing/MeshPool.java | 2 +- .../backend/memory/FlwMemoryTracker.java | 66 ++-- .../flywheel/backend/memory/MemoryBlock.java | 14 +- .../backend/memory/MemoryBlockImpl.java | 31 +- .../memory/TrackedMemoryBlockImpl.java | 23 +- .../flywheel/core/FullscreenQuad.java | 2 +- .../jozufozu/flywheel/core/QuadConverter.java | 2 +- .../jozufozu/flywheel/core/model/Mesh.java | 29 +- .../model/buffering/BakedModelBuilder.java | 6 +- .../model/buffering/BlockModelBuilder.java | 6 +- .../buffering/MultiBlockModelBuilder.java | 6 +- .../flywheel/core/uniform/UniformBuffer.java | 3 +- .../flywheel/core/uniform/ViewProvider.java | 2 +- .../flywheel/light/GPULightVolume.java | 4 +- .../jozufozu/flywheel/light/LightVolume.java | 320 +++++++++--------- .../jozufozu/flywheel/util/StringUtil.java | 6 +- 24 files changed, 288 insertions(+), 296 deletions(-) diff --git a/src/main/java/com/jozufozu/flywheel/api/material/Material.java b/src/main/java/com/jozufozu/flywheel/api/material/Material.java index a93091d89..dc0db130f 100644 --- a/src/main/java/com/jozufozu/flywheel/api/material/Material.java +++ b/src/main/java/com/jozufozu/flywheel/api/material/Material.java @@ -22,7 +22,7 @@ public interface Material { VertexTransformer getVertexTransformer(); - public interface VertexTransformer { + interface VertexTransformer { void transform(MutableVertexList vertexList, ClientLevel level); } } diff --git a/src/main/java/com/jozufozu/flywheel/api/struct/StructType.java b/src/main/java/com/jozufozu/flywheel/api/struct/StructType.java index 7bdeab3a0..ef14279de 100644 --- a/src/main/java/com/jozufozu/flywheel/api/struct/StructType.java +++ b/src/main/java/com/jozufozu/flywheel/api/struct/StructType.java @@ -29,7 +29,7 @@ public interface StructType { VertexTransformer getVertexTransformer(); - public interface VertexTransformer { + interface VertexTransformer { void transform(MutableVertexList vertexList, S struct, ClientLevel level); } diff --git a/src/main/java/com/jozufozu/flywheel/api/uniform/UniformProvider.java b/src/main/java/com/jozufozu/flywheel/api/uniform/UniformProvider.java index 62890b521..982be51be 100644 --- a/src/main/java/com/jozufozu/flywheel/api/uniform/UniformProvider.java +++ b/src/main/java/com/jozufozu/flywheel/api/uniform/UniformProvider.java @@ -1,7 +1,5 @@ package com.jozufozu.flywheel.api.uniform; -import java.nio.ByteBuffer; - import com.jozufozu.flywheel.core.source.FileResolution; public abstract class UniformProvider { diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/array/GlVertexArray.java b/src/main/java/com/jozufozu/flywheel/backend/gl/array/GlVertexArray.java index 69efb178f..3abf7a7d0 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/array/GlVertexArray.java +++ b/src/main/java/com/jozufozu/flywheel/backend/gl/array/GlVertexArray.java @@ -5,8 +5,8 @@ import org.lwjgl.opengl.GL32; import com.jozufozu.flywheel.backend.gl.GlObject; import com.jozufozu.flywheel.backend.gl.GlStateTracker; -import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType; import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer; +import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType; import com.jozufozu.flywheel.backend.gl.versioned.GlCompat; import com.jozufozu.flywheel.core.layout.BufferLayout; import com.mojang.blaze3d.platform.GlStateManager; diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/GlBuffer.java b/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/GlBuffer.java index edfff94d3..ef8eaa6df 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/GlBuffer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/GlBuffer.java @@ -1,6 +1,12 @@ package com.jozufozu.flywheel.backend.gl.buffer; -import static org.lwjgl.opengl.GL32.*; +import static org.lwjgl.opengl.GL15.glBufferData; +import static org.lwjgl.opengl.GL15.glDeleteBuffers; +import static org.lwjgl.opengl.GL15.glGenBuffers; +import static org.lwjgl.opengl.GL15.nglBufferData; +import static org.lwjgl.opengl.GL30.GL_MAP_WRITE_BIT; +import static org.lwjgl.opengl.GL30.nglMapBufferRange; +import static org.lwjgl.opengl.GL31.glCopyBufferSubData; import org.lwjgl.system.MemoryUtil; 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 1d68c6617..65ea1cab7 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 @@ -13,9 +13,7 @@ import com.jozufozu.flywheel.backend.instancing.InstanceManager; import com.jozufozu.flywheel.backend.instancing.TaskEngine; import com.jozufozu.flywheel.core.RenderContext; import com.jozufozu.flywheel.util.FlwUtil; -import com.mojang.blaze3d.platform.Lighting; import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.math.Matrix4f; import net.minecraft.client.Camera; import net.minecraft.client.multiplayer.ClientLevel; @@ -73,15 +71,6 @@ public class BatchingEngine implements Engine { return; } - // FIXME: this probably breaks some vanilla stuff but it works much better for flywheel - Matrix4f mat = new Matrix4f(); - mat.setIdentity(); - if (context.level().effects().constantAmbientLight()) { - Lighting.setupNetherLevel(mat); - } else { - Lighting.setupLevel(mat); - } - batchTracker.endBatch(); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/TransformSet.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/TransformSet.java index 8b27d389d..bb1fb6185 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/TransformSet.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/TransformSet.java @@ -83,20 +83,15 @@ public class TransformSet { vertexList.ptr(anchorPtr); vertexList.setVertexCount(totalVertexCount); material.getVertexTransformer().transform(vertexList, level); - applyPoseStack(vertexList, stack, false); + applyPoseStack(vertexList, stack); } - private static void applyPoseStack(MutableVertexList vertexList, PoseStack stack, boolean applyNormalMatrix) { + private static void applyPoseStack(MutableVertexList vertexList, PoseStack stack) { Vector4f pos = new Vector4f(); Vector3f normal = new Vector3f(); Matrix4f modelMatrix = stack.last().pose(); - Matrix3f normalMatrix; - if (applyNormalMatrix) { - normalMatrix = stack.last().normal(); - } else { - normalMatrix = null; - } + Matrix3f normalMatrix = stack.last().normal(); for (int i = 0; i < vertexList.getVertexCount(); i++) { pos.set( @@ -110,18 +105,16 @@ public class TransformSet { vertexList.y(i, pos.y()); vertexList.z(i, pos.z()); - if (applyNormalMatrix) { - normal.set( - vertexList.normalX(i), - vertexList.normalY(i), - vertexList.normalZ(i) - ); - normal.transform(normalMatrix); - normal.normalize(); - vertexList.normalX(i, normal.x()); - vertexList.normalY(i, normal.y()); - vertexList.normalZ(i, normal.z()); - } + normal.set( + vertexList.normalX(i), + vertexList.normalY(i), + vertexList.normalZ(i) + ); + normal.transform(normalMatrix); + normal.normalize(); + vertexList.normalX(i, normal.x()); + vertexList.normalY(i, normal.y()); + vertexList.normalZ(i, normal.z()); } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/GPUInstancer.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/GPUInstancer.java index cfce702fb..a2fc2da05 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/GPUInstancer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/GPUInstancer.java @@ -8,10 +8,10 @@ import com.jozufozu.flywheel.api.instancer.InstancedPart; import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.api.struct.StructWriter; import com.jozufozu.flywheel.backend.gl.array.GlVertexArray; +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.MappedBuffer; -import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer; import com.jozufozu.flywheel.backend.instancing.AbstractInstancer; import com.jozufozu.flywheel.core.layout.BufferLayout; diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/MeshPool.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/MeshPool.java index c43a49fc9..f23b647d1 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/MeshPool.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/MeshPool.java @@ -14,9 +14,9 @@ import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.backend.gl.GlPrimitive; import com.jozufozu.flywheel.backend.gl.array.GlVertexArray; +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.GlBuffer; import com.jozufozu.flywheel.core.layout.BufferLayout; import com.jozufozu.flywheel.core.model.Mesh; import com.jozufozu.flywheel.event.ReloadRenderersEvent; diff --git a/src/main/java/com/jozufozu/flywheel/backend/memory/FlwMemoryTracker.java b/src/main/java/com/jozufozu/flywheel/backend/memory/FlwMemoryTracker.java index 80d1c486b..165b441f3 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/memory/FlwMemoryTracker.java +++ b/src/main/java/com/jozufozu/flywheel/backend/memory/FlwMemoryTracker.java @@ -6,7 +6,7 @@ import java.nio.ByteBuffer; import org.lwjgl.system.MemoryUtil; public class FlwMemoryTracker { - private static final Cleaner CLEANER = Cleaner.create(); + static final Cleaner CLEANER = Cleaner.create(); private static long cpuMemory = 0; private static long gpuMemory = 0; @@ -19,18 +19,11 @@ public class FlwMemoryTracker { return ptr; } - public static MemoryBlock mallocBlock(long size) { - MemoryBlock block = new MemoryBlockImpl(malloc(size), size); - _allocCPUMemory(block.size()); - return block; - } - - public static MemoryBlock mallocBlockTracked(long size) { - MemoryBlock block = new TrackedMemoryBlockImpl(malloc(size), size, CLEANER); - _allocCPUMemory(block.size()); - return block; - } - + /** + * @deprecated Use {@link MemoryBlock#malloc(long)} or {@link MemoryBlock#mallocTracked(long)} and + * {@link MemoryBlock#asBuffer()} instead. This method should only be used if specifically a {@linkplain ByteBuffer} is needed and it is + * short-lived. + */ @Deprecated public static ByteBuffer mallocBuffer(int size) { ByteBuffer buffer = MemoryUtil.memByteBuffer(malloc(size), size); @@ -46,16 +39,16 @@ public class FlwMemoryTracker { return ptr; } - public static MemoryBlock callocBlock(long num, long size) { - MemoryBlock block = new MemoryBlockImpl(calloc(num, size), num * size); - _allocCPUMemory(block.size()); - return block; - } - - public static MemoryBlock callocBlockTracked(long num, long size) { - MemoryBlock block = new TrackedMemoryBlockImpl(calloc(num, size), num * size, CLEANER); - _allocCPUMemory(block.size()); - return block; + /** + * @deprecated Use {@link MemoryBlock#calloc(long, long)} or {@link MemoryBlock#callocTracked(long, long)} and + * {@link MemoryBlock#asBuffer()} instead. This method should only be used if specifically a {@linkplain ByteBuffer} is needed and it is + * short-lived. + */ + @Deprecated + public static ByteBuffer callocBuffer(int num, int size) { + ByteBuffer buffer = MemoryUtil.memByteBuffer(calloc(num, size), num * size); + _allocCPUMemory(buffer.capacity()); + return buffer; } public static long realloc(long ptr, long size) { @@ -66,20 +59,10 @@ public class FlwMemoryTracker { return ptr; } - public static MemoryBlock reallocBlock(MemoryBlock block, long size) { - MemoryBlock newBlock = new MemoryBlockImpl(realloc(block.ptr(), size), size); - _freeCPUMemory(block.size()); - _allocCPUMemory(newBlock.size()); - return newBlock; - } - - public static MemoryBlock reallocBlockTracked(MemoryBlock block, long size) { - MemoryBlock newBlock = new TrackedMemoryBlockImpl(realloc(block.ptr(), size), size, CLEANER); - _freeCPUMemory(block.size()); - _allocCPUMemory(newBlock.size()); - return newBlock; - } - + /** + * @deprecated Use {@link MemoryBlock#realloc(long)} or {@link MemoryBlock#reallocTracked(long)} instead. This method + * should only be used if specifically a {@linkplain ByteBuffer} is needed and it is short-lived. + */ @Deprecated public static ByteBuffer reallocBuffer(ByteBuffer buffer, int size) { ByteBuffer newBuffer = MemoryUtil.memByteBuffer(realloc(MemoryUtil.memAddress(buffer), size), size); @@ -92,11 +75,10 @@ public class FlwMemoryTracker { MemoryUtil.nmemFree(ptr); } - public static void freeBlock(MemoryBlock block) { - free(block.ptr()); - _freeCPUMemory(block.size()); - } - + /** + * @deprecated Use {@link MemoryBlock#free} instead. This method should only be used if specifically a {@linkplain ByteBuffer} is needed and + * it is short-lived. + */ @Deprecated public static void freeBuffer(ByteBuffer buffer) { free(MemoryUtil.memAddress(buffer)); diff --git a/src/main/java/com/jozufozu/flywheel/backend/memory/MemoryBlock.java b/src/main/java/com/jozufozu/flywheel/backend/memory/MemoryBlock.java index 9b6ad2cea..1b28bdbe2 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/memory/MemoryBlock.java +++ b/src/main/java/com/jozufozu/flywheel/backend/memory/MemoryBlock.java @@ -26,18 +26,18 @@ public sealed interface MemoryBlock permits MemoryBlockImpl { void free(); static MemoryBlock malloc(long size) { - return FlwMemoryTracker.mallocBlock(size); - } - - static MemoryBlock calloc(long num, long size) { - return FlwMemoryTracker.callocBlock(num, size); + return MemoryBlockImpl.mallocBlock(size); } static MemoryBlock mallocTracked(long size) { - return FlwMemoryTracker.mallocBlockTracked(size); + return TrackedMemoryBlockImpl.mallocBlockTracked(size); + } + + static MemoryBlock calloc(long num, long size) { + return MemoryBlockImpl.callocBlock(num, size); } static MemoryBlock callocTracked(long num, long size) { - return FlwMemoryTracker.callocBlockTracked(num, size); + return TrackedMemoryBlockImpl.callocBlockTracked(num, size); } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/memory/MemoryBlockImpl.java b/src/main/java/com/jozufozu/flywheel/backend/memory/MemoryBlockImpl.java index a3fb15a60..d37b61ded 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/memory/MemoryBlockImpl.java +++ b/src/main/java/com/jozufozu/flywheel/backend/memory/MemoryBlockImpl.java @@ -59,23 +59,42 @@ sealed class MemoryBlockImpl implements MemoryBlock permits TrackedMemoryBlockIm return MemoryUtil.memByteBuffer(ptr, intSize); } + void freeInner() { + FlwMemoryTracker._freeCPUMemory(size); + freed = true; + } + @Override public MemoryBlock realloc(long size) { - MemoryBlock block = FlwMemoryTracker.reallocBlock(this, size); - freed = true; + MemoryBlock block = new MemoryBlockImpl(FlwMemoryTracker.realloc(ptr, size), size); + FlwMemoryTracker._allocCPUMemory(block.size()); + freeInner(); return block; } @Override public MemoryBlock reallocTracked(long size) { - MemoryBlock block = FlwMemoryTracker.reallocBlockTracked(this, size); - freed = true; + MemoryBlock block = new TrackedMemoryBlockImpl(FlwMemoryTracker.realloc(ptr, size), size, FlwMemoryTracker.CLEANER); + FlwMemoryTracker._allocCPUMemory(block.size()); + freeInner(); return block; } @Override public void free() { - FlwMemoryTracker.freeBlock(this); - freed = true; + FlwMemoryTracker.free(ptr); + freeInner(); + } + + static MemoryBlock mallocBlock(long size) { + MemoryBlock block = new MemoryBlockImpl(FlwMemoryTracker.malloc(size), size); + FlwMemoryTracker._allocCPUMemory(block.size()); + return block; + } + + static MemoryBlock callocBlock(long num, long size) { + MemoryBlock block = new MemoryBlockImpl(FlwMemoryTracker.calloc(num, size), num * size); + FlwMemoryTracker._allocCPUMemory(block.size()); + return block; } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/memory/TrackedMemoryBlockImpl.java b/src/main/java/com/jozufozu/flywheel/backend/memory/TrackedMemoryBlockImpl.java index a37ba3590..57b7730c5 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/memory/TrackedMemoryBlockImpl.java +++ b/src/main/java/com/jozufozu/flywheel/backend/memory/TrackedMemoryBlockImpl.java @@ -17,32 +17,25 @@ final class TrackedMemoryBlockImpl extends MemoryBlockImpl { return true; } + @Override void freeInner() { - freed = true; + super.freeInner(); cleaningAction.freed = true; cleanable.clean(); } - @Override - public MemoryBlock realloc(long size) { - MemoryBlock block = FlwMemoryTracker.reallocBlock(this, size); - freeInner(); + static MemoryBlock mallocBlockTracked(long size) { + MemoryBlock block = new TrackedMemoryBlockImpl(FlwMemoryTracker.malloc(size), size, FlwMemoryTracker.CLEANER); + FlwMemoryTracker._allocCPUMemory(block.size()); return block; } - @Override - public MemoryBlock reallocTracked(long size) { - MemoryBlock block = FlwMemoryTracker.reallocBlockTracked(this, size); - freeInner(); + static MemoryBlock callocBlockTracked(long num, long size) { + MemoryBlock block = new TrackedMemoryBlockImpl(FlwMemoryTracker.calloc(num, size), num * size, FlwMemoryTracker.CLEANER); + FlwMemoryTracker._allocCPUMemory(block.size()); return block; } - @Override - public void free() { - FlwMemoryTracker.freeBlock(this); - freeInner(); - } - static class CleaningAction implements Runnable { final long ptr; final long size; diff --git a/src/main/java/com/jozufozu/flywheel/core/FullscreenQuad.java b/src/main/java/com/jozufozu/flywheel/core/FullscreenQuad.java index 79b49df58..7280641fa 100644 --- a/src/main/java/com/jozufozu/flywheel/core/FullscreenQuad.java +++ b/src/main/java/com/jozufozu/flywheel/core/FullscreenQuad.java @@ -8,9 +8,9 @@ import org.lwjgl.system.MemoryUtil; import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.backend.gl.GlStateTracker; import com.jozufozu.flywheel.backend.gl.array.GlVertexArray; +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.GlBuffer; import com.jozufozu.flywheel.core.layout.BufferLayout; import com.jozufozu.flywheel.core.layout.CommonItems; import com.jozufozu.flywheel.util.Lazy; diff --git a/src/main/java/com/jozufozu/flywheel/core/QuadConverter.java b/src/main/java/com/jozufozu/flywheel/core/QuadConverter.java index 93427f829..71e9d27ce 100644 --- a/src/main/java/com/jozufozu/flywheel/core/QuadConverter.java +++ b/src/main/java/com/jozufozu/flywheel/core/QuadConverter.java @@ -5,9 +5,9 @@ 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.GlBuffer; import com.jozufozu.flywheel.backend.instancing.instancing.ElementBuffer; import com.jozufozu.flywheel.event.ReloadRenderersEvent; diff --git a/src/main/java/com/jozufozu/flywheel/core/model/Mesh.java b/src/main/java/com/jozufozu/flywheel/core/model/Mesh.java index a1a4f10c2..ecf138451 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/Mesh.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/Mesh.java @@ -6,24 +6,7 @@ import com.jozufozu.flywheel.backend.instancing.instancing.ElementBuffer; import com.jozufozu.flywheel.core.QuadConverter; /** - * A mesh that can be rendered by flywheel. - * - *

- * It is expected that the following assertion will not fail: - *

- * - *
{@code
- * Mesh mesh = ...;
- * VecBuffer into = ...;
- *
- * int initial = VecBuffer.unwrap().position();
- *
- * mesh.buffer(into);
- *
- * int final = VecBuffer.unwrap().position();
- *
- * assert mesh.size() == final - initial;
- * }
+ * A holder for arbitrary vertex data that can be written to memory or a vertex list. */ public interface Mesh { @@ -49,8 +32,18 @@ public interface Mesh { return getVertexType().byteOffset(getVertexCount()); } + /** + * Write this mesh into memory. The written data will use the format defined by {@link #getVertexType()} and the amount of + * bytes written will be the same as the return value of {@link #size()}. + * @param ptr The address to which data is written to. + */ void write(long ptr); + /** + * Write this mesh into a vertex list. Vertices with index {@literal <}0 or {@literal >=}{@link #getVertexCount()} will not be + * modified. + * @param vertexList The vertex list to which data is written to. + */ void write(MutableVertexList vertexList); /** diff --git a/src/main/java/com/jozufozu/flywheel/core/model/buffering/BakedModelBuilder.java b/src/main/java/com/jozufozu/flywheel/core/model/buffering/BakedModelBuilder.java index e0ca37b16..b86ec43f7 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/buffering/BakedModelBuilder.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/buffering/BakedModelBuilder.java @@ -30,6 +30,8 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraftforge.client.model.data.IModelData; public class BakedModelBuilder { + private static final int STARTING_CAPACITY = 64; + private final BakedModel bakedModel; private boolean shadeSeparated = true; private BlockAndTintGetter renderWorld; @@ -96,7 +98,7 @@ public class BakedModelBuilder { if (shadeSeparated) { ShadeSeparatedBufferFactory bufferFactory = (renderType, shaded) -> { - BufferBuilder buffer = new BufferBuilder(64); + BufferBuilder buffer = new BufferBuilder(STARTING_CAPACITY); buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK); return buffer; }; @@ -111,7 +113,7 @@ public class BakedModelBuilder { ModelBufferingUtil.bufferSingleShadeSeparated(ModelUtil.VANILLA_RENDERER.getModelRenderer(), renderWorld, bakedModel, blockState, poseStack, bufferFactory, objects.shadeSeparatingBufferWrapper, objects.random, modelData, resultConsumer); } else { BufferFactory bufferFactory = (renderType) -> { - BufferBuilder buffer = new BufferBuilder(64); + BufferBuilder buffer = new BufferBuilder(STARTING_CAPACITY); buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK); return buffer; }; diff --git a/src/main/java/com/jozufozu/flywheel/core/model/buffering/BlockModelBuilder.java b/src/main/java/com/jozufozu/flywheel/core/model/buffering/BlockModelBuilder.java index 84686aa74..b69549c6c 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/buffering/BlockModelBuilder.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/buffering/BlockModelBuilder.java @@ -28,6 +28,8 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraftforge.client.model.data.IModelData; public class BlockModelBuilder { + private static final int STARTING_CAPACITY = 64; + private final BlockState state; private boolean shadeSeparated = true; private BlockAndTintGetter renderWorld; @@ -85,7 +87,7 @@ public class BlockModelBuilder { if (shadeSeparated) { ShadeSeparatedBufferFactory bufferFactory = (renderType, shaded) -> { - BufferBuilder buffer = new BufferBuilder(64); + BufferBuilder buffer = new BufferBuilder(STARTING_CAPACITY); buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK); return buffer; }; @@ -100,7 +102,7 @@ public class BlockModelBuilder { ModelBufferingUtil.bufferBlockShadeSeparated(ModelUtil.VANILLA_RENDERER, renderWorld, state, poseStack, bufferFactory, objects.shadeSeparatingBufferWrapper, objects.random, modelData, resultConsumer); } else { BufferFactory bufferFactory = (renderType) -> { - BufferBuilder buffer = new BufferBuilder(64); + BufferBuilder buffer = new BufferBuilder(STARTING_CAPACITY); buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK); return buffer; }; diff --git a/src/main/java/com/jozufozu/flywheel/core/model/buffering/MultiBlockModelBuilder.java b/src/main/java/com/jozufozu/flywheel/core/model/buffering/MultiBlockModelBuilder.java index b329a46c6..dd0342e5f 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/buffering/MultiBlockModelBuilder.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/buffering/MultiBlockModelBuilder.java @@ -31,6 +31,8 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemp import net.minecraftforge.client.model.data.IModelData; public class MultiBlockModelBuilder { + private static final int STARTING_CAPACITY = 1024; + private final Collection blocks; private boolean shadeSeparated = true; private VertexFormat vertexFormat; @@ -92,7 +94,7 @@ public class MultiBlockModelBuilder { if (shadeSeparated) { ShadeSeparatedBufferFactory bufferFactory = (renderType, shaded) -> { - BufferBuilder buffer = new BufferBuilder(1024); + BufferBuilder buffer = new BufferBuilder(STARTING_CAPACITY); buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK); return buffer; }; @@ -107,7 +109,7 @@ public class MultiBlockModelBuilder { ModelBufferingUtil.bufferMultiBlockShadeSeparated(blocks, ModelUtil.VANILLA_RENDERER, renderWorld, poseStack, bufferFactory, objects.shadeSeparatingBufferWrapper, objects.random, modelDataMap, resultConsumer); } else { BufferFactory bufferFactory = (renderType) -> { - BufferBuilder buffer = new BufferBuilder(1024); + BufferBuilder buffer = new BufferBuilder(STARTING_CAPACITY); buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK); return buffer; }; diff --git a/src/main/java/com/jozufozu/flywheel/core/uniform/UniformBuffer.java b/src/main/java/com/jozufozu/flywheel/core/uniform/UniformBuffer.java index e1c88b815..39ce69a94 100644 --- a/src/main/java/com/jozufozu/flywheel/core/uniform/UniformBuffer.java +++ b/src/main/java/com/jozufozu/flywheel/core/uniform/UniformBuffer.java @@ -5,12 +5,11 @@ import java.util.Collection; import java.util.List; import org.lwjgl.opengl.GL32; -import org.lwjgl.system.MemoryUtil; import com.google.common.collect.ImmutableList; import com.jozufozu.flywheel.api.uniform.UniformProvider; -import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType; import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer; +import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType; import com.jozufozu.flywheel.backend.memory.MemoryBlock; import com.jozufozu.flywheel.core.ComponentRegistry; import com.jozufozu.flywheel.util.RenderMath; diff --git a/src/main/java/com/jozufozu/flywheel/core/uniform/ViewProvider.java b/src/main/java/com/jozufozu/flywheel/core/uniform/ViewProvider.java index 437b5cdcd..5a785ec70 100644 --- a/src/main/java/com/jozufozu/flywheel/core/uniform/ViewProvider.java +++ b/src/main/java/com/jozufozu/flywheel/core/uniform/ViewProvider.java @@ -56,7 +56,7 @@ public class ViewProvider extends UniformProvider { MemoryUtil.memPutFloat(ptr + 64, camX); MemoryUtil.memPutFloat(ptr + 68, camY); MemoryUtil.memPutFloat(ptr + 72, camZ); - MemoryUtil.memPutInt(ptr + 76, constantAmbientLight); + MemoryUtil.memPutInt(ptr + 80, constantAmbientLight); notifier.signalChanged(); } diff --git a/src/main/java/com/jozufozu/flywheel/light/GPULightVolume.java b/src/main/java/com/jozufozu/flywheel/light/GPULightVolume.java index 673670973..233b84504 100644 --- a/src/main/java/com/jozufozu/flywheel/light/GPULightVolume.java +++ b/src/main/java/com/jozufozu/flywheel/light/GPULightVolume.java @@ -73,7 +73,7 @@ public class GPULightVolume extends LightVolume { public void bind() { // just in case something goes wrong, or we accidentally call this before this volume is properly disposed of. - if (lightData == null || lightData.capacity() == 0) return; + if (lightData == null || lightData.size() == 0) return; textureUnit.makeActive(); glTexture.bind(); @@ -93,7 +93,7 @@ public class GPULightVolume extends LightVolume { int sizeY = box.sizeY(); int sizeZ = box.sizeZ(); - glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, sizeX, sizeY, sizeZ, GL30.GL_RG, GL_UNSIGNED_BYTE, lightData); + glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, sizeX, sizeY, sizeZ, GL30.GL_RG, GL_UNSIGNED_BYTE, lightData.ptr()); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // 4 is the default bufferDirty = false; diff --git a/src/main/java/com/jozufozu/flywheel/light/LightVolume.java b/src/main/java/com/jozufozu/flywheel/light/LightVolume.java index cf4abacb1..ef1dc4f88 100644 --- a/src/main/java/com/jozufozu/flywheel/light/LightVolume.java +++ b/src/main/java/com/jozufozu/flywheel/light/LightVolume.java @@ -1,8 +1,8 @@ package com.jozufozu.flywheel.light; -import java.nio.ByteBuffer; +import org.lwjgl.system.MemoryUtil; -import com.jozufozu.flywheel.backend.memory.FlwMemoryTracker; +import com.jozufozu.flywheel.backend.memory.MemoryBlock; import com.jozufozu.flywheel.util.box.GridAlignedBB; import com.jozufozu.flywheel.util.box.ImmutableBox; @@ -14,13 +14,53 @@ public class LightVolume implements ImmutableBox, LightListener { protected final BlockAndTintGetter level; protected final GridAlignedBB box = new GridAlignedBB(); - protected ByteBuffer lightData; + protected MemoryBlock lightData; public LightVolume(BlockAndTintGetter level, ImmutableBox sampleVolume) { this.level = level; this.setBox(sampleVolume); - this.lightData = FlwMemoryTracker.mallocBuffer(this.box.volume() * 2); + this.lightData = MemoryBlock.malloc(this.box.volume() * 2); + } + + @Override + public ImmutableBox getVolume() { + return box; + } + + @Override + public int getMinX() { + return box.getMinX(); + } + + @Override + public int getMinY() { + return box.getMinY(); + } + + @Override + public int getMinZ() { + return box.getMinZ(); + } + + @Override + public int getMaxX() { + return box.getMaxX(); + } + + @Override + public int getMaxY() { + return box.getMaxY(); + } + + @Override + public int getMaxZ() { + return box.getMaxZ(); + } + + @Override + public boolean isListenerInvalid() { + return lightData == null; } protected void setBox(ImmutableBox box) { @@ -29,47 +69,143 @@ public class LightVolume implements ImmutableBox, LightListener { public short getPackedLight(int x, int y, int z) { if (box.contains(x, y, z)) { - return lightData.getShort(worldPosToBufferIndex(x, y, z)); + return MemoryUtil.memGetShort(worldPosToPtr(x, y, z)); } else { return 0; } } - public int getMinX() { - return box.getMinX(); - } - - public int getMinY() { - return box.getMinY(); - } - - public int getMinZ() { - return box.getMinZ(); - } - - public int getMaxX() { - return box.getMaxX(); - } - - public int getMaxY() { - return box.getMaxY(); - } - - public int getMaxZ() { - return box.getMaxZ(); - } - public void move(ImmutableBox newSampleVolume) { if (lightData == null) return; setBox(newSampleVolume); int neededCapacity = box.volume() * 2; - if (neededCapacity > lightData.capacity()) { - lightData = FlwMemoryTracker.reallocBuffer(lightData, neededCapacity); + if (neededCapacity > lightData.size()) { + lightData = lightData.realloc(neededCapacity); } initialize(); } + /** + * Completely (re)populate this volume with block and sky lighting data. + * This is expensive and should be avoided. + */ + public void initialize() { + if (lightData == null) return; + + copyLight(getVolume()); + markDirty(); + } + + protected void markDirty() { + // noop + } + + public void delete() { + lightData.free(); + lightData = null; + } + + /** + * Copy all light from the world into this volume. + * + * @param worldVolume the region in the world to copy data from. + */ + public void copyLight(ImmutableBox worldVolume) { + BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(); + + int xShift = box.getMinX(); + int yShift = box.getMinY(); + int zShift = box.getMinZ(); + + worldVolume.forEachContained((x, y, z) -> { + pos.set(x, y, z); + + int block = this.level.getBrightness(LightLayer.BLOCK, pos); + int sky = this.level.getBrightness(LightLayer.SKY, pos); + + writeLight(x - xShift, y - yShift, z - zShift, block, sky); + }); + } + + protected void writeLight(int x, int y, int z, int block, int sky) { + byte b = (byte) ((block & 0xF) << 4); + byte s = (byte) ((sky & 0xF) << 4); + + long ptr = boxPosToPtr(x, y, z); + MemoryUtil.memPutByte(ptr, b); + MemoryUtil.memPutByte(ptr + 1, s); + } + + /** + * Copy block light from the world into this volume. + * + * @param worldVolume the region in the world to copy data from. + */ + public void copyBlock(ImmutableBox worldVolume) { + var pos = new BlockPos.MutableBlockPos(); + + int xShift = box.getMinX(); + int yShift = box.getMinY(); + int zShift = box.getMinZ(); + + worldVolume.forEachContained((x, y, z) -> { + int light = this.level.getBrightness(LightLayer.BLOCK, pos.set(x, y, z)); + + writeBlock(x - xShift, y - yShift, z - zShift, light); + }); + } + + protected void writeBlock(int x, int y, int z, int block) { + byte b = (byte) ((block & 0xF) << 4); + + MemoryUtil.memPutByte(boxPosToPtr(x, y, z), b); + } + + /** + * Copy sky light from the world into this volume. + * + * @param worldVolume the region in the world to copy data from. + */ + public void copySky(ImmutableBox worldVolume) { + var pos = new BlockPos.MutableBlockPos(); + + int xShift = box.getMinX(); + int yShift = box.getMinY(); + int zShift = box.getMinZ(); + + worldVolume.forEachContained((x, y, z) -> { + int light = this.level.getBrightness(LightLayer.SKY, pos.set(x, y, z)); + + writeSky(x - xShift, y - yShift, z - zShift, light); + }); + } + + protected void writeSky(int x, int y, int z, int sky) { + byte s = (byte) ((sky & 0xF) << 4); + + MemoryUtil.memPutByte(boxPosToPtr(x, y, z) + 1, s); + } + + protected long worldPosToPtr(int x, int y, int z) { + return lightData.ptr() + worldPosToPtrOffset(x, y, z); + } + + protected long boxPosToPtr(int x, int y, int z) { + return lightData.ptr() + boxPosToPtrOffset(x, y, z); + } + + protected int worldPosToPtrOffset(int x, int y, int z) { + x -= box.getMinX(); + y -= box.getMinY(); + z -= box.getMinZ(); + return boxPosToPtrOffset(x, y, z); + } + + protected int boxPosToPtrOffset(int x, int y, int z) { + return (x + box.sizeX() * (y + z * box.sizeY())) * 2; + } + @Override public void onLightUpdate(LightLayer type, ImmutableBox changedVolume) { if (lightData == null) return; @@ -95,126 +231,4 @@ public class LightVolume implements ImmutableBox, LightListener { markDirty(); } - /** - * Completely (re)populate this volume with block and sky lighting data. - * This is expensive and should be avoided. - */ - public void initialize() { - if (lightData == null) return; - - copyLight(getVolume()); - markDirty(); - } - - /** - * Copy block light from the world into this volume. - * - * @param worldVolume the region in the world to copy data from. - */ - public void copyBlock(ImmutableBox worldVolume) { - var pos = new BlockPos.MutableBlockPos(); - - int xShift = box.getMinX(); - int yShift = box.getMinY(); - int zShift = box.getMinZ(); - - worldVolume.forEachContained((x, y, z) -> { - int light = this.level.getBrightness(LightLayer.BLOCK, pos.set(x, y, z)); - - writeBlock(x - xShift, y - yShift, z - zShift, light); - }); - } - - /** - * Copy sky light from the world into this volume. - * - * @param worldVolume the region in the world to copy data from. - */ - public void copySky(ImmutableBox worldVolume) { - var pos = new BlockPos.MutableBlockPos(); - - int xShift = box.getMinX(); - int yShift = box.getMinY(); - int zShift = box.getMinZ(); - - worldVolume.forEachContained((x, y, z) -> { - int light = this.level.getBrightness(LightLayer.SKY, pos.set(x, y, z)); - - writeSky(x - xShift, y - yShift, z - zShift, light); - }); - } - - /** - * Copy all light from the world into this volume. - * - * @param worldVolume the region in the world to copy data from. - */ - public void copyLight(ImmutableBox worldVolume) { - BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(); - - int xShift = box.getMinX(); - int yShift = box.getMinY(); - int zShift = box.getMinZ(); - - worldVolume.forEachContained((x, y, z) -> { - pos.set(x, y, z); - - int block = this.level.getBrightness(LightLayer.BLOCK, pos); - int sky = this.level.getBrightness(LightLayer.SKY, pos); - - writeLight(x - xShift, y - yShift, z - zShift, block, sky); - }); - } - - public void delete() { - FlwMemoryTracker.freeBuffer(lightData); - lightData = null; - } - - protected void markDirty() { - // noop - } - - protected void writeLight(int x, int y, int z, int block, int sky) { - byte b = (byte) ((block & 0xF) << 4); - byte s = (byte) ((sky & 0xF) << 4); - - int i = boxPosToBufferIndex(x, y, z); - lightData.put(i, b); - lightData.put(i + 1, s); - } - - protected void writeBlock(int x, int y, int z, int block) { - byte b = (byte) ((block & 0xF) << 4); - - lightData.put(boxPosToBufferIndex(x, y, z), b); - } - - protected void writeSky(int x, int y, int z, int sky) { - byte b = (byte) ((sky & 0xF) << 4); - - lightData.put(boxPosToBufferIndex(x, y, z) + 1, b); - } - - protected int worldPosToBufferIndex(int x, int y, int z) { - x -= box.getMinX(); - y -= box.getMinY(); - z -= box.getMinZ(); - return boxPosToBufferIndex(x, y, z); - } - - protected int boxPosToBufferIndex(int x, int y, int z) { - return (x + box.sizeX() * (y + z * box.sizeY())) * 2; - } - - @Override - public ImmutableBox getVolume() { - return box; - } - - @Override - public boolean isListenerInvalid() { - return lightData == null; - } - } diff --git a/src/main/java/com/jozufozu/flywheel/util/StringUtil.java b/src/main/java/com/jozufozu/flywheel/util/StringUtil.java index cdf8c6952..7af4a9c5f 100644 --- a/src/main/java/com/jozufozu/flywheel/util/StringUtil.java +++ b/src/main/java/com/jozufozu/flywheel/util/StringUtil.java @@ -25,11 +25,11 @@ public class StringUtil { if (bytes < 1024) { return bytes + " B"; } else if (bytes < 1024 * 1024) { - return THREE_DECIMAL_PLACES.format(bytes / 1024f) + " KB"; + return THREE_DECIMAL_PLACES.format(bytes / 1024f) + " KiB"; } else if (bytes < 1024 * 1024 * 1024) { - return THREE_DECIMAL_PLACES.format(bytes / 1024f / 1024f) + " MB"; + return THREE_DECIMAL_PLACES.format(bytes / 1024f / 1024f) + " MiB"; } else { - return THREE_DECIMAL_PLACES.format(bytes / 1024f / 1024f / 1024f) + " GB"; + return THREE_DECIMAL_PLACES.format(bytes / 1024f / 1024f / 1024f) + " GiB"; } }