- Use way fewer memory barriers
- I didn't realize that GL_SHADER_STORAGE_BARRIER_BIT was global instead
  of operating only on the currently bound buffers. Oh, well
- Move apply program binding to IndirectDrawManager
- Fix embedded instances flickering when first loading a world. Need to
  actually bind the matrix buffer for the cull shader. Not sure how it
  worked at all before
- Minor styling/cleanup
This commit is contained in:
Jozufozu 2024-08-15 20:57:28 -07:00
parent 7a7d58adf2
commit a5f49c6738
6 changed files with 35 additions and 13 deletions

View File

@ -51,4 +51,8 @@ public class Arena {
public int capacity() {
return top;
}
public long byteCapacity() {
return memoryBlock.size();
}
}

View File

@ -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) {

View File

@ -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<I extends Instance> {
.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<I> instanceType;
private final long instanceStride;
private final IndirectBuffers buffers;
@ -48,7 +45,6 @@ public class IndirectCullingGroup<I extends Instance> {
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<I extends Instance> {
this.programs = programs;
cullProgram = programs.getCullingProgram(instanceType);
applyProgram = programs.getApplyProgram();
}
public void flushInstancers() {
@ -123,7 +118,6 @@ public class IndirectCullingGroup<I extends Instance> {
cullProgram.bind();
buffers.bindForCompute();
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
glDispatchCompute(GlCompat.getComputeGroupCount(instanceCountThisFrame), 1, 1);
}
@ -132,9 +126,7 @@ public class IndirectCullingGroup<I extends Instance> {
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<I extends Instance> {
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;
}
}

View File

@ -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<IndirectInstancer<?>> {
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<IndirectInstancer<?>> {
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<IndirectInstancer<?>> {
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

View File

@ -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());
});
}

View File

@ -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;