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) { + + } + } } } }