diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/compile/IndirectPrograms.java b/common/src/backend/java/dev/engine_room/flywheel/backend/compile/IndirectPrograms.java index bb140cf56..47e381eff 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/compile/IndirectPrograms.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/compile/IndirectPrograms.java @@ -33,7 +33,8 @@ public class IndirectPrograms extends AtomicReferenceCounted { private static final ResourceLocation SCATTER_SHADER_MAIN = Flywheel.rl("internal/indirect/scatter.glsl"); private static final ResourceLocation DEPTH_REDUCE_SHADER_MAIN = Flywheel.rl("internal/indirect/depth_reduce.glsl"); private static final ResourceLocation READ_VISIBILITY_SHADER_MAIN = Flywheel.rl("internal/indirect/read_visibility.glsl"); - public static final List UTIL_SHADERS = List.of(APPLY_SHADER_MAIN, SCATTER_SHADER_MAIN, DEPTH_REDUCE_SHADER_MAIN, READ_VISIBILITY_SHADER_MAIN); + private static final ResourceLocation ZERO_MODELS_SHADER_MAIN = Flywheel.rl("internal/indirect/zero_models.glsl"); + public static final List UTIL_SHADERS = List.of(APPLY_SHADER_MAIN, SCATTER_SHADER_MAIN, DEPTH_REDUCE_SHADER_MAIN, READ_VISIBILITY_SHADER_MAIN, ZERO_MODELS_SHADER_MAIN); private static final Compile> CULL = new Compile<>(); private static final Compile UTIL = new Compile<>(); @@ -47,19 +48,13 @@ public class IndirectPrograms extends AtomicReferenceCounted { private final Map pipeline; private final Map, GlProgram> culling; private final Map, GlProgram> cullPassTwo; - private final GlProgram apply; - private final GlProgram scatter; - private final GlProgram depthReduce; - private final GlProgram readVisibility; + private final Map utils; - private IndirectPrograms(Map pipeline, Map, GlProgram> culling, Map, GlProgram> cullPassTwo, GlProgram apply, GlProgram scatter, GlProgram depthReduce, GlProgram readVisibility) { + private IndirectPrograms(Map pipeline, Map, GlProgram> culling, Map, GlProgram> cullPassTwo, Map utils) { this.pipeline = pipeline; this.culling = culling; this.cullPassTwo = cullPassTwo; - this.apply = apply; - this.scatter = scatter; - this.depthReduce = depthReduce; - this.readVisibility = readVisibility; + this.utils = utils; } private static List getExtensions(GlslVersion glslVersion) { @@ -110,7 +105,7 @@ public class IndirectPrograms extends AtomicReferenceCounted { var utils = utilCompiler.compileAndReportErrors(UTIL_SHADERS); if (pipelineResult != null && pass1Result != null && pass2Result != null && utils != null) { - newInstance = new IndirectPrograms(pipelineResult, pass1Result, pass2Result, utils.get(APPLY_SHADER_MAIN), utils.get(SCATTER_SHADER_MAIN), utils.get(DEPTH_REDUCE_SHADER_MAIN), utils.get(READ_VISIBILITY_SHADER_MAIN)); + newInstance = new IndirectPrograms(pipelineResult, pass1Result, pass2Result, utils); } } catch (Throwable t) { FlwPrograms.LOGGER.error("Failed to compile indirect programs", t); @@ -195,19 +190,23 @@ public class IndirectPrograms extends AtomicReferenceCounted { } public GlProgram getApplyProgram() { - return apply; + return utils.get(APPLY_SHADER_MAIN); + } + + public GlProgram getZeroModelProgram() { + return utils.get(ZERO_MODELS_SHADER_MAIN); } public GlProgram getScatterProgram() { - return scatter; + return utils.get(SCATTER_SHADER_MAIN); } public GlProgram getDepthReduceProgram() { - return depthReduce; + return utils.get(DEPTH_REDUCE_SHADER_MAIN); } public GlProgram getReadVisibilityProgram() { - return readVisibility; + return utils.get(READ_VISIBILITY_SHADER_MAIN); } @Override @@ -216,6 +215,7 @@ public class IndirectPrograms extends AtomicReferenceCounted { .forEach(GlProgram::delete); culling.values() .forEach(GlProgram::delete); - apply.delete(); + utils.values() + .forEach(GlProgram::delete); } } diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/MaterialRenderState.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/MaterialRenderState.java index 0ddf8e1e7..d4fd52a41 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/MaterialRenderState.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/MaterialRenderState.java @@ -35,6 +35,7 @@ public final class MaterialRenderState { setupBackfaceCulling(material.backfaceCulling()); setupPolygonOffset(material.polygonOffset()); setupDepthTest(material.depthTest()); +// setupDepthTest(DepthTest.OFF); setupTransparency(material.transparency()); setupWriteMask(material.writeMask()); } diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/IndirectBuffers.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/IndirectBuffers.java index 82be8783a..2b0631525 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/IndirectBuffers.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/IndirectBuffers.java @@ -126,6 +126,10 @@ public class IndirectBuffers { multiBind(5, 2); } + public void bindForModelReset() { + multiBind(5, 1); + } + public void bindForDraw() { multiBind(3, 4); GlBufferType.DRAW_INDIRECT_BUFFER.bind(draw.handle()); 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 0290f41cf..278d95b6c 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 @@ -165,6 +165,15 @@ public class IndirectCullingGroup { glDispatchCompute(GlCompat.getComputeGroupCount(indirectDraws.size()), 1, 1); } + public void dispatchModelReset() { + if (nothingToDo()) { + return; + } + + buffers.bindForModelReset(); + glDispatchCompute(GlCompat.getComputeGroupCount(instancers.size()), 1, 1); + } + private boolean nothingToDo() { return indirectDraws.isEmpty() || instanceCountThisFrame == 0; } 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 b0083f241..799495a09 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 @@ -93,7 +93,8 @@ public class IndirectDrawManager extends DrawManager> { } public void render(VisualType visualType) { - if (!hasVisualType(visualType)) { + // FIXME: Two pass occlusion prefers to render everything at once + if (visualType != VisualType.BLOCK_ENTITY) { return; } @@ -105,17 +106,50 @@ public class IndirectDrawManager extends DrawManager> { matrixBuffer.bind(); Uniforms.bindAll(); + glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); + + visibilityBuffer.bind(); + + for (var group1 : cullingGroups.values()) { + group1.dispatchCull(); + } + + glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); + + dispatchApply(); + + glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); + visibilityBuffer.attach(); - if (needsBarrier) { - glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); - needsBarrier = false; - } + submitDraws(); + + depthPyramid.generate(); + + programs.getZeroModelProgram() + .bind(); for (var group : cullingGroups.values()) { - group.submit(visualType); + group.dispatchModelReset(); } + glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); + + GlTextureUnit.T0.makeActive(); + GlStateManager._bindTexture(depthPyramid.pyramidTextureId); + + for (var group1 : cullingGroups.values()) { + group1.dispatchCullPassTwo(); + } + + glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); + + dispatchApply(); + + glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); + + submitDraws(); + MaterialRenderState.reset(); TextureBinder.resetLightAndOverlay(); @@ -123,6 +157,23 @@ public class IndirectDrawManager extends DrawManager> { } } + private void dispatchApply() { + programs.getApplyProgram() + .bind(); + + for (var group1 : cullingGroups.values()) { + group1.dispatchApply(); + } + } + + private void submitDraws() { + for (var group : cullingGroups.values()) { + group.submit(VisualType.BLOCK_ENTITY); + group.submit(VisualType.ENTITY); + group.submit(VisualType.EFFECT); + } + } + @Override public void flush(LightStorage lightStorage, EnvironmentStorage environmentStorage) { super.flush(lightStorage, environmentStorage); @@ -159,31 +210,9 @@ public class IndirectDrawManager extends DrawManager> { stagingBuffer.flush(); - depthPyramid.generate(); - // 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(); - - GlTextureUnit.T0.makeActive(); - GlStateManager._bindTexture(depthPyramid.pyramidTextureId); - - 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; totalPagesLastFrame = totalPagesThisFrame; diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/VisibilityBuffer.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/VisibilityBuffer.java index 85a26e816..34ef71499 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/VisibilityBuffer.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/VisibilityBuffer.java @@ -54,7 +54,7 @@ public class VisibilityBuffer { } readVisibilityProgram.bind(); - GL46.glBindBufferBase(GL46.GL_SHADER_STORAGE_BUFFER, BufferBindings.LAST_FRAME_VISIBILITY, lastFrameVisibility.handle()); + bind(); GlTextureUnit.T0.makeActive(); GlStateManager._bindTexture(textureId); @@ -62,6 +62,10 @@ public class VisibilityBuffer { GL46.glDispatchCompute(MoreMath.ceilingDiv(lastWidth, READ_GROUP_SIZE), MoreMath.ceilingDiv(lastHeight, READ_GROUP_SIZE), 1); } + public void bind() { + GL46.glBindBufferBase(GL46.GL_SHADER_STORAGE_BUFFER, BufferBindings.LAST_FRAME_VISIBILITY, lastFrameVisibility.handle()); + } + public void attach() { var mainRenderTarget = Minecraft.getInstance() .getMainRenderTarget(); diff --git a/common/src/backend/resources/assets/flywheel/flywheel/internal/indirect/zero_models.glsl b/common/src/backend/resources/assets/flywheel/flywheel/internal/indirect/zero_models.glsl new file mode 100644 index 000000000..c8f7a0b9c --- /dev/null +++ b/common/src/backend/resources/assets/flywheel/flywheel/internal/indirect/zero_models.glsl @@ -0,0 +1,18 @@ +#include "flywheel:internal/indirect/buffer_bindings.glsl" +#include "flywheel:internal/indirect/model_descriptor.glsl" + +layout(local_size_x = _FLW_SUBGROUP_SIZE) in; + +layout(std430, binding = _FLW_MODEL_BUFFER_BINDING) restrict writeonly buffer ModelBuffer { + ModelDescriptor models[]; +}; + +void main() { + uint modelIndex = gl_GlobalInvocationID.x; + + if (modelIndex >= models.length()) { + return; + } + + models[modelIndex].instanceCount = 0; +}