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 9060b5363..0f6e8ef57 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 @@ -199,7 +199,6 @@ public void submit(VisualType visualType) { drawBarrier(); GlProgram lastProgram = null; - int baseDrawUniformLoc = -1; for (var multiDraw : multiDraws.get(visualType)) { var drawProgram = programs.getIndirectProgram(instanceType, multiDraw.embedded ? ContextShader.EMBEDDED : ContextShader.DEFAULT, multiDraw.material); @@ -208,14 +207,11 @@ public void submit(VisualType visualType) { // Don't need to do this unless the program changes. drawProgram.bind(); - baseDrawUniformLoc = drawProgram.getUniformLocation("_flw_baseDraw"); } - glUniform1ui(baseDrawUniformLoc, multiDraw.start); - MaterialRenderState.setup(multiDraw.material); - multiDraw.submit(); + multiDraw.submit(drawProgram); } } @@ -290,8 +286,8 @@ public boolean checkEmptyAndDelete() { } private record MultiDraw(Material material, boolean embedded, int start, int end) { - private void submit() { - GlCompat.safeMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, this.start * IndirectBuffers.DRAW_COMMAND_STRIDE, this.end - this.start, (int) IndirectBuffers.DRAW_COMMAND_STRIDE); + private void submit(GlProgram drawProgram) { + GlCompat.safeMultiDrawElementsIndirect(drawProgram, GL_TRIANGLES, GL_UNSIGNED_INT, this.start, this.end, IndirectBuffers.DRAW_COMMAND_STRIDE); } } } diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/IndirectInstancer.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/IndirectInstancer.java index 1291e9a77..aa9b372f1 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/IndirectInstancer.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/IndirectInstancer.java @@ -25,6 +25,9 @@ public class IndirectInstancer extends AbstractInstancer private final Vector4fc boundingSphere; private final AtomicReference[]> pages = new AtomicReference<>(pageArray(0)); + + private final AtomicInteger instanceCount = new AtomicInteger(0); + /** * The set of pages whose count changed and thus need their descriptor re-uploaded. */ @@ -145,6 +148,8 @@ public boolean add(I instance, InstanceHandleImpl handle) { // We just filled the 17th instance, so we are no longer mergeable. parent.mergeablePages.clear(pageNo); } + + parent.instanceCount.incrementAndGet(); return true; } } @@ -203,6 +208,7 @@ private void clear(int localIndex) { } // Set full page last so that other threads don't race to set the other bitsets. parent.fullPages.clear(pageNo); + parent.instanceCount.decrementAndGet(); break; } } @@ -538,9 +544,7 @@ private void addInner(I instance, InstanceHandleImpl handle) { } public int instanceCount() { - // Not exactly accurate but it's an upper bound. - // TODO: maybe this could be tracked with an AtomicInteger? - return pages.get().length << ObjectStorage.LOG_2_PAGE_SIZE; + return instanceCount.get(); } /** diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/gl/GlCompat.java b/common/src/backend/java/dev/engine_room/flywheel/backend/gl/GlCompat.java index b7efa23ed..636b9ac4c 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/gl/GlCompat.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/gl/GlCompat.java @@ -16,6 +16,7 @@ import dev.engine_room.flywheel.backend.FlwBackend; import dev.engine_room.flywheel.backend.compile.core.Compilation; +import dev.engine_room.flywheel.backend.gl.shader.GlProgram; import dev.engine_room.flywheel.backend.glsl.GlslVersion; import dev.engine_room.flywheel.lib.math.MoreMath; @@ -78,15 +79,20 @@ public static void safeShaderSource(int glId, CharSequence source) { * but uses consecutive DI instead of MDI if MDI is known to not work well with the current driver. * Unlike the original function, stride cannot be equal to 0. */ - public static void safeMultiDrawElementsIndirect(int mode, int type, long indirect, int drawcount, int stride) { + public static void safeMultiDrawElementsIndirect(GlProgram drawProgram, int mode, int type, int start, int end, long stride) { + var count = end - start; + long indirect = start * stride; + if (GlCompat.DRIVER == Driver.INTEL) { - // Intel renders garbage with MDI, but consecutive DI works fine. - for (int i = 0; i < drawcount; i++) { + // Intel renders garbage with MDI, but consecutive DI works "fine". + for (int i = 0; i < count; i++) { + drawProgram.setUInt("_flw_baseDraw", start + i); GL40.glDrawElementsIndirect(mode, type, indirect); indirect += stride; } } else { - GL43.glMultiDrawElementsIndirect(mode, type, indirect, drawcount, stride); + drawProgram.setUInt("_flw_baseDraw", start); + GL43.glMultiDrawElementsIndirect(mode, type, indirect, count, (int) stride); } }