Skip to content

Commit

Permalink
Who's counting?
Browse files Browse the repository at this point in the history
- Atomically count instances in indirect instancer
- Fixes indirect draws/instancers never being deleted
- Fix baseDraw being set incorrectly on intel
- Handle setting baseDraw in GlCompat#safeMultiDrawElementsIndirect
  • Loading branch information
Jozufozu committed Nov 16, 2024
1 parent 3811da1 commit 00bd05a
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
}
}

Expand Down Expand Up @@ -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);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ public class IndirectInstancer<I extends Instance> extends AbstractInstancer<I>
private final Vector4fc boundingSphere;

private final AtomicReference<InstancePage<I>[]> 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.
*/
Expand Down Expand Up @@ -145,6 +148,8 @@ public boolean add(I instance, InstanceHandleImpl<I> handle) {
// We just filled the 17th instance, so we are no longer mergeable.
parent.mergeablePages.clear(pageNo);
}

parent.instanceCount.incrementAndGet();
return true;
}
}
Expand Down Expand Up @@ -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;
}
}
Expand Down Expand Up @@ -538,9 +544,7 @@ private void addInner(I instance, InstanceHandleImpl<I> 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();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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);
}
}

Expand Down

0 comments on commit 00bd05a

Please sign in to comment.