diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/StagingBuffer.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/StagingBuffer.java index 59a8c3e0a..efe107f92 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/StagingBuffer.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/StagingBuffer.java @@ -10,6 +10,7 @@ import org.lwjgl.system.MemoryUtil; import dev.engine_room.flywheel.backend.compile.IndirectPrograms; import dev.engine_room.flywheel.backend.gl.GlFence; import dev.engine_room.flywheel.backend.gl.buffer.GlBuffer; +import dev.engine_room.flywheel.backend.gl.buffer.GlBufferUsage; import dev.engine_room.flywheel.lib.memory.FlwMemoryTracker; import dev.engine_room.flywheel.lib.memory.MemoryBlock; import it.unimi.dsi.fastutil.PriorityQueue; @@ -22,6 +23,8 @@ public class StagingBuffer { private static final int STORAGE_FLAGS = GL45C.GL_MAP_PERSISTENT_BIT | GL45C.GL_MAP_WRITE_BIT | GL45C.GL_CLIENT_STORAGE_BIT; private static final int MAP_FLAGS = GL45C.GL_MAP_PERSISTENT_BIT | GL45C.GL_MAP_WRITE_BIT | GL45C.GL_MAP_FLUSH_EXPLICIT_BIT | GL45C.GL_MAP_INVALIDATE_BUFFER_BIT; + private static final int SSBO_ALIGNMENT = GL45.glGetInteger(GL45.GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT); + private final int vbo; private final long map; private final long capacity; @@ -30,7 +33,7 @@ public class StagingBuffer { private final OverflowStagingBuffer overflow = new OverflowStagingBuffer(); private final TransferList transfers = new TransferList(); private final PriorityQueue fencedRegions = new ObjectArrayFIFOQueue<>(); - private final GlBuffer scatterBuffer = new GlBuffer(); + private final GlBuffer scatterBuffer = new GlBuffer(GlBufferUsage.STREAM_COPY); private final ScatterList scatterList = new ScatterList(); /** @@ -252,7 +255,6 @@ public class StagingBuffer { .bind(); // These bindings don't change between dstVbos. - GL45.glBindBufferBase(GL45C.GL_SHADER_STORAGE_BUFFER, 0, scatterBuffer.handle()); GL45.glBindBufferBase(GL45C.GL_SHADER_STORAGE_BUFFER, 1, vbo); int dstVbo; @@ -274,7 +276,25 @@ public class StagingBuffer { } private void dispatchScatter(int dstVbo) { - scatterBuffer.upload(scatterList.ptr(), scatterList.usedBytes()); + var scatterSize = scatterList.usedBytes(); + + // If there's enough space in the staging buffer still, lets write the scatter in it directly. + long alignedPos = pos + SSBO_ALIGNMENT - 1 - (pos + SSBO_ALIGNMENT - 1) % SSBO_ALIGNMENT; + + long remaining = capacity - alignedPos; + if (scatterSize <= remaining && scatterSize <= totalAvailable) { + MemoryUtil.memCopy(scatterList.ptr(), map + alignedPos, scatterSize); + GL45.glBindBufferRange(GL45C.GL_SHADER_STORAGE_BUFFER, 0, vbo, alignedPos, scatterSize); + + long alignmentCost = alignedPos - pos; + + usedCapacity += scatterSize + alignmentCost; + totalAvailable -= scatterSize + alignmentCost; + pos += scatterSize + alignmentCost; + } else { + scatterBuffer.upload(scatterList.ptr(), scatterSize); + GL45.glBindBufferBase(GL45C.GL_SHADER_STORAGE_BUFFER, 0, scatterBuffer.handle()); + } GL45.glBindBufferBase(GL45C.GL_SHADER_STORAGE_BUFFER, 2, dstVbo);