diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancedInstancer.java b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancedInstancer.java index 99ffbd455..36d1f8e0d 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancedInstancer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancedInstancer.java @@ -7,7 +7,6 @@ import java.util.Set; import org.jetbrains.annotations.Nullable; -import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.api.context.Context; import com.jozufozu.flywheel.api.instance.Instance; import com.jozufozu.flywheel.api.instance.InstanceType; @@ -18,7 +17,7 @@ import com.jozufozu.flywheel.backend.gl.array.GlVertexArray; import com.jozufozu.flywheel.backend.gl.array.VertexAttribute; import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer; import com.jozufozu.flywheel.backend.gl.buffer.GlBufferUsage; -import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer; +import com.jozufozu.flywheel.lib.memory.MemoryBlock; public class InstancedInstancer extends AbstractInstancer { private final List instanceAttributes; @@ -45,7 +44,6 @@ public class InstancedInstancer extends AbstractInstancer } vbo = new GlBuffer(GlBufferUsage.DYNAMIC_DRAW); - vbo.growthFunction(l -> Math.max(l + (long) instanceStride * 16, (long) (l * 1.6))); } public void update() { @@ -59,28 +57,61 @@ public class InstancedInstancer extends AbstractInstancer } int byteSize = instanceStride * instances.size(); - if (vbo.ensureCapacity(byteSize)) { - // The vbo has moved, so we need to re-bind attributes - boundTo.clear(); + if (needsToGrow(byteSize)) { + // TODO: Should this memory block be persistent? + var temp = MemoryBlock.malloc(increaseSize(byteSize)); + + writeAll(temp.ptr()); + + vbo.upload(temp); + + temp.free(); + } else { + writeChanged(); } - try (MappedBuffer buf = vbo.map()) { - writeChanged(buf.ptr()); - - changed.clear(); - } catch (Exception e) { - Flywheel.LOGGER.error("Error updating InstancedInstancer:", e); - } + changed.clear(); } - private void writeChanged(long ptr) { + private void writeChanged() { changed.forEachSetSpan((startInclusive, endInclusive) -> { + var temp = MemoryBlock.malloc((long) instanceStride * (endInclusive - startInclusive + 1)); + long ptr = temp.ptr(); for (int i = startInclusive; i <= endInclusive; i++) { - writer.write(ptr + (long) instanceStride * i, instances.get(i)); + writer.write(ptr, instances.get(i)); + ptr += instanceStride; } + + vbo.uploadSpan((long) startInclusive * instanceStride, temp); + + temp.free(); }); } + private void writeAll(long ptr) { + for (I instance : instances) { + writer.write(ptr, instance); + ptr += instanceStride; + } + } + + private long increaseSize(long capacity) { + return Math.max(capacity + (long) instanceStride * 16, (long) (capacity * 1.6)); + } + + public boolean needsToGrow(long capacity) { + if (capacity < 0) { + throw new IllegalArgumentException("Size " + capacity + " < 0"); + } + + if (capacity == 0) { + return false; + } + + return capacity > vbo.size(); + } + + /** * Bind this instancer's vbo to the given vao if it hasn't already been bound. * @param vao The vao to bind to. diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/Buffer.java b/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/Buffer.java index 9f5432ec3..04b052c40 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/Buffer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/Buffer.java @@ -1,8 +1,6 @@ package com.jozufozu.flywheel.backend.gl.buffer; import org.lwjgl.opengl.GL15; -import org.lwjgl.opengl.GL30; -import org.lwjgl.opengl.GL31; import org.lwjgl.opengl.GL45C; import org.lwjgl.system.Checks; @@ -15,11 +13,7 @@ public interface Buffer { void data(int vbo, long size, long ptr, int glEnum); - void copyData(int src, int dst, long srcOffset, long dstOffset, long size); - - long mapRange(int handle, int offset, long size, int access); - - void unmap(int handle); + void subData(int vbo, long offset, long size, long ptr); class DSA implements Buffer { @Override @@ -33,18 +27,8 @@ public interface Buffer { } @Override - public void copyData(int src, int dst, long srcOffset, long dstOffset, long size) { - GL45C.glCopyNamedBufferSubData(src, dst, srcOffset, dstOffset, size); - } - - @Override - public long mapRange(int handle, int offset, long size, int access) { - return GL45C.nglMapNamedBufferRange(handle, offset, size, access); - } - - @Override - public void unmap(int handle) { - GL45C.glUnmapNamedBuffer(handle); + public void subData(int vbo, long offset, long size, long ptr) { + GL45C.nglNamedBufferSubData(vbo, offset, size, ptr); } public Buffer fallback() { @@ -73,23 +57,9 @@ public interface Buffer { } @Override - public void copyData(int src, int dst, long size, long srcOffset, long dstOffset) { - GlBufferType.COPY_READ_BUFFER.bind(src); - GlBufferType.COPY_WRITE_BUFFER.bind(dst); - - GL31.glCopyBufferSubData(GlBufferType.COPY_READ_BUFFER.glEnum, GlBufferType.COPY_WRITE_BUFFER.glEnum, srcOffset, dstOffset, size); - } - - @Override - public long mapRange(int handle, int offset, long size, int access) { - GlBufferType.COPY_READ_BUFFER.bind(handle); - return GL30.nglMapBufferRange(GlBufferType.COPY_READ_BUFFER.glEnum, 0, size, access); - } - - @Override - public void unmap(int handle) { - GlBufferType.COPY_READ_BUFFER.bind(handle); - GL15.glUnmapBuffer(GlBufferType.COPY_READ_BUFFER.glEnum); + public void subData(int vbo, long offset, long size, long ptr) { + GlBufferType.COPY_WRITE_BUFFER.bind(vbo); + GL15.nglBufferSubData(GlBufferType.COPY_WRITE_BUFFER.glEnum, offset, size, ptr); } } } 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 7566635bf..2fc185bac 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,24 +1,16 @@ package com.jozufozu.flywheel.backend.gl.buffer; -import org.lwjgl.system.MemoryUtil; - import com.jozufozu.flywheel.backend.gl.GlObject; import com.jozufozu.flywheel.lib.memory.FlwMemoryTracker; import com.jozufozu.flywheel.lib.memory.MemoryBlock; import com.mojang.blaze3d.platform.GlStateManager; -import it.unimi.dsi.fastutil.longs.LongUnaryOperator; - public class GlBuffer extends GlObject { protected final GlBufferUsage usage; /** * The size (in bytes) of the buffer on the GPU. */ protected long size; - /** - * A mapping to adjust the size of the buffer when allocating. - */ - protected LongUnaryOperator growthFunction = LongUnaryOperator.identity(); public GlBuffer() { this(GlBufferUsage.STATIC_DRAW); @@ -29,63 +21,9 @@ public class GlBuffer extends GlObject { this.usage = usage; } - /** - * @return true if the buffer was recreated. - */ - public boolean ensureCapacity(long capacity) { - if (capacity < 0) { - throw new IllegalArgumentException("Size " + capacity + " < 0"); - } - - if (capacity == 0) { - return false; - } - - if (size == 0) { - alloc(capacity); - return true; - } - - if (capacity > size) { - realloc(capacity); - return true; - } - - return false; - } - - private void alloc(long capacity) { - increaseSize(capacity); - Buffer.IMPL.data(handle(), size, MemoryUtil.NULL, usage.glEnum); - FlwMemoryTracker._allocGPUMemory(size); - } - - private void realloc(long capacity) { - FlwMemoryTracker._freeGPUMemory(size); - var oldSize = size; - increaseSize(capacity); - - int oldHandle = handle(); - int newHandle = Buffer.IMPL.create(); - Buffer.IMPL.data(newHandle, size, MemoryUtil.NULL, usage.glEnum); - Buffer.IMPL.copyData(oldHandle, newHandle, 0, 0, oldSize); - GlStateManager._glDeleteBuffers(oldHandle); - handle(newHandle); - - FlwMemoryTracker._allocGPUMemory(size); - } - - /** - * Increase the size of the buffer to at least the given capacity. - */ - private void increaseSize(long capacity) { - size = growthFunction.apply(capacity); - } - public void upload(MemoryBlock memoryBlock) { upload(memoryBlock.ptr(), memoryBlock.size()); } - public void upload(long ptr, long size) { FlwMemoryTracker._freeGPUMemory(this.size); Buffer.IMPL.data(handle(), size, ptr, usage.glEnum); @@ -93,12 +31,12 @@ public class GlBuffer extends GlObject { FlwMemoryTracker._allocGPUMemory(this.size); } - public MappedBuffer map() { - return new MappedBuffer(handle(), size); + public void uploadSpan(long offset, MemoryBlock memoryBlock) { + uploadSpan(offset, memoryBlock.ptr(), memoryBlock.size()); } - public void growthFunction(LongUnaryOperator growthFunction) { - this.growthFunction = growthFunction; + public void uploadSpan(long offset, long ptr, long size) { + Buffer.IMPL.subData(handle(), offset, size, ptr); } public long size() { 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 deleted file mode 100644 index 5328ba85e..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/MappedBuffer.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.jozufozu.flywheel.backend.gl.buffer; - -import static org.lwjgl.opengl.GL30.GL_MAP_WRITE_BIT; -import static org.lwjgl.system.MemoryUtil.NULL; - -import org.lwjgl.system.MemoryUtil; - -import com.jozufozu.flywheel.backend.gl.error.GlError; -import com.jozufozu.flywheel.backend.gl.error.GlException; - -public class MappedBuffer implements AutoCloseable { - private final int glBuffer; - private long ptr; - - public MappedBuffer(int glBuffer, long size) { - this.glBuffer = glBuffer; - - ptr = Buffer.IMPL.mapRange(glBuffer, 0, size, GL_MAP_WRITE_BIT); - - if (ptr == MemoryUtil.NULL) { - throw new GlException(GlError.poll(), "Could not map buffer"); - } - } - - public long ptr() { - return ptr; - } - - @Override - public void close() { - if (ptr == NULL) { - return; - } - - Buffer.IMPL.unmap(glBuffer); - ptr = NULL; - } -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/MappedBufferUsage.java b/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/MappedBufferUsage.java deleted file mode 100644 index 30e60a348..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/buffer/MappedBufferUsage.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.jozufozu.flywheel.backend.gl.buffer; - -import org.lwjgl.opengl.GL15C; - -public enum MappedBufferUsage { - READ_ONLY(GL15C.GL_READ_ONLY), - WRITE_ONLY(GL15C.GL_WRITE_ONLY), - READ_WRITE(GL15C.GL_READ_WRITE), - ; - - int glEnum; - - MappedBufferUsage(int glEnum) { - this.glEnum = glEnum; - } -}