diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/Arena.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/Arena.java index 101cc0013..e7aa67071 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/Arena.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/Arena.java @@ -51,4 +51,8 @@ public class Arena { public int capacity() { return top; } + + public long byteCapacity() { + return memoryBlock.size(); + } } diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/EnvironmentStorage.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/EnvironmentStorage.java index 942fc3623..2b707a3b8 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/EnvironmentStorage.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/EnvironmentStorage.java @@ -16,7 +16,8 @@ public class EnvironmentStorage { public final Arena arena = new Arena(MATRIX_SIZE_BYTES, 32); { - arena.alloc(); // Reserve the identity matrix. + // Reserve the identity matrix. Burns a few bytes but oh well. + arena.alloc(); } public void track(EmbeddedEnvironment environment) { diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/IndirectCullingGroup.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/IndirectCullingGroup.java index 5afa7c46d..9a376ab14 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/IndirectCullingGroup.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/IndirectCullingGroup.java @@ -5,7 +5,6 @@ import static org.lwjgl.opengl.GL11.GL_UNSIGNED_INT; import static org.lwjgl.opengl.GL30.glUniform1ui; import static org.lwjgl.opengl.GL42.GL_COMMAND_BARRIER_BIT; import static org.lwjgl.opengl.GL42.glMemoryBarrier; -import static org.lwjgl.opengl.GL43.GL_SHADER_STORAGE_BARRIER_BIT; import static org.lwjgl.opengl.GL43.glDispatchCompute; import java.util.ArrayList; @@ -37,8 +36,6 @@ public class IndirectCullingGroup { .thenComparing(IndirectDraw::indexOfMeshInModel) .thenComparing(IndirectDraw::material, MaterialRenderState.COMPARATOR); - private static final int DRAW_BARRIER_BITS = GL_SHADER_STORAGE_BARRIER_BIT | GL_COMMAND_BARRIER_BIT; - private final InstanceType instanceType; private final long instanceStride; private final IndirectBuffers buffers; @@ -48,7 +45,6 @@ public class IndirectCullingGroup { private final IndirectPrograms programs; private final GlProgram cullProgram; - private final GlProgram applyProgram; private boolean needsDrawBarrier; private boolean needsDrawSort; @@ -62,7 +58,6 @@ public class IndirectCullingGroup { this.programs = programs; cullProgram = programs.getCullingProgram(instanceType); - applyProgram = programs.getApplyProgram(); } public void flushInstancers() { @@ -123,7 +118,6 @@ public class IndirectCullingGroup { cullProgram.bind(); buffers.bindForCompute(); - glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); glDispatchCompute(GlCompat.getComputeGroupCount(instanceCountThisFrame), 1, 1); } @@ -132,9 +126,7 @@ public class IndirectCullingGroup { return; } - applyProgram.bind(); buffers.bindForCompute(); - glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); glDispatchCompute(GlCompat.getComputeGroupCount(indirectDraws.size()), 1, 1); } @@ -241,7 +233,9 @@ public class IndirectCullingGroup { private void drawBarrier() { if (needsDrawBarrier) { - glMemoryBarrier(DRAW_BARRIER_BITS); + // In theory all command buffer writes will be protected by + // the shader storage barrier bit, but better safe than sorry. + glMemoryBarrier(GL_COMMAND_BARRIER_BIT); needsDrawBarrier = false; } } diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/IndirectDrawManager.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/IndirectDrawManager.java index 073850193..adabbf653 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/IndirectDrawManager.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/IndirectDrawManager.java @@ -4,6 +4,8 @@ import static org.lwjgl.opengl.GL11.GL_TRIANGLES; import static org.lwjgl.opengl.GL11.GL_UNSIGNED_INT; import static org.lwjgl.opengl.GL30.glBindBufferRange; import static org.lwjgl.opengl.GL40.glDrawElementsIndirect; +import static org.lwjgl.opengl.GL42.glMemoryBarrier; +import static org.lwjgl.opengl.GL43.GL_SHADER_STORAGE_BARRIER_BIT; import static org.lwjgl.opengl.GL43.GL_SHADER_STORAGE_BUFFER; import java.util.HashMap; @@ -44,6 +46,8 @@ public class IndirectDrawManager extends DrawManager> { private final LightBuffers lightBuffers; private final MatrixBuffer matrixBuffer; + private boolean needsBarrier = false; + public IndirectDrawManager(IndirectPrograms programs) { this.programs = programs; programs.acquire(); @@ -90,6 +94,11 @@ public class IndirectDrawManager extends DrawManager> { matrixBuffer.bind(); Uniforms.bindAll(); + if (needsBarrier) { + glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); + needsBarrier = false; + } + for (var group : cullingGroups.values()) { group.submit(visualType); } @@ -127,13 +136,27 @@ public class IndirectDrawManager extends DrawManager> { stagingBuffer.flush(); + // We could probably save some driver calls here when there are + // actually zero instances, but that feels like a very rare case + + glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); + + matrixBuffer.bind(); + for (var group : cullingGroups.values()) { group.dispatchCull(); } + glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); + + programs.getApplyProgram() + .bind(); + for (var group : cullingGroups.values()) { group.dispatchApply(); } + + needsBarrier = true; } @Override diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/MatrixBuffer.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/MatrixBuffer.java index 3e17d386d..ce579c465 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/MatrixBuffer.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/MatrixBuffer.java @@ -18,8 +18,8 @@ public class MatrixBuffer { matrices.ensureCapacity(capacity); - stagingBuffer.enqueueCopy((long) arena.capacity() * EnvironmentStorage.MATRIX_SIZE_BYTES, matrices.handle(), 0, ptr -> { - MemoryUtil.memCopy(arena.indexToPointer(0), ptr, (long) arena.capacity() * EnvironmentStorage.MATRIX_SIZE_BYTES); + stagingBuffer.enqueueCopy(arena.byteCapacity(), matrices.handle(), 0, ptr -> { + MemoryUtil.memCopy(arena.indexToPointer(0), ptr, arena.byteCapacity()); }); } diff --git a/common/src/backend/resources/assets/flywheel/flywheel/internal/indirect/cull.glsl b/common/src/backend/resources/assets/flywheel/flywheel/internal/indirect/cull.glsl index 58a893cbc..65d5baae0 100644 --- a/common/src/backend/resources/assets/flywheel/flywheel/internal/indirect/cull.glsl +++ b/common/src/backend/resources/assets/flywheel/flywheel/internal/indirect/cull.glsl @@ -36,8 +36,8 @@ bool _flw_testSphere(vec3 center, float radius) { } bool _flw_isVisible(uint instanceIndex, uint modelIndex) { - BoundingSphere sphere = _flw_models[modelIndex].boundingSphere; uint matrixIndex = _flw_models[modelIndex].matrixIndex; + BoundingSphere sphere = _flw_models[modelIndex].boundingSphere; vec3 center; float radius;