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 df1696657..cc43568da 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 @@ -31,6 +31,7 @@ public class IndirectPrograms extends AtomicReferenceCounted { private static final ResourceLocation APPLY_SHADER_MAIN = Flywheel.rl("internal/indirect/apply.glsl"); 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"); + public static final List UTIL_SHADERS = List.of(APPLY_SHADER_MAIN, SCATTER_SHADER_MAIN, DEPTH_REDUCE_SHADER_MAIN); private static final Compile> CULL = new Compile<>(); private static final Compile UTIL = new Compile<>(); @@ -43,16 +44,12 @@ public class IndirectPrograms extends AtomicReferenceCounted { private final Map pipeline; private final Map, GlProgram> culling; - private final GlProgram apply; - private final GlProgram scatter; - private final GlProgram depthReduce; + private final Map utils; - private IndirectPrograms(Map pipeline, Map, GlProgram> culling, GlProgram apply, GlProgram scatter, GlProgram depthReduce) { + private IndirectPrograms(Map pipeline, Map, GlProgram> culling, Map utils) { this.pipeline = pipeline; this.culling = culling; - this.apply = apply; - this.scatter = scatter; - this.depthReduce = depthReduce; + this.utils = utils; } private static List getExtensions(GlslVersion glslVersion) { @@ -97,10 +94,10 @@ static void reload(ShaderSources sources, ImmutableList pipe try { var pipelineResult = pipelineCompiler.compileAndReportErrors(pipelineKeys); var cullingResult = cullingCompiler.compileAndReportErrors(createCullingKeys()); - var utils = utilCompiler.compileAndReportErrors(List.of(APPLY_SHADER_MAIN, SCATTER_SHADER_MAIN, DEPTH_REDUCE_SHADER_MAIN)); + var utils = utilCompiler.compileAndReportErrors(UTIL_SHADERS); if (pipelineResult != null && cullingResult != null && utils != null) { - newInstance = new IndirectPrograms(pipelineResult, cullingResult, utils.get(APPLY_SHADER_MAIN), utils.get(SCATTER_SHADER_MAIN), utils.get(DEPTH_REDUCE_SHADER_MAIN)); + newInstance = new IndirectPrograms(pipelineResult, cullingResult, utils); } } catch (Throwable t) { FlwPrograms.LOGGER.error("Failed to compile indirect programs", t); @@ -180,23 +177,23 @@ public GlProgram getCullingProgram(InstanceType instanceType) { } public GlProgram getApplyProgram() { - return apply; + return utils.get(APPLY_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); } - @Override protected void _delete() { pipeline.values() .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/indirect/BufferBindings.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/BufferBindings.java index 658096695..0b9eea6fd 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/BufferBindings.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/BufferBindings.java @@ -1,11 +1,12 @@ package dev.engine_room.flywheel.backend.engine.indirect; public final class BufferBindings { - public static final int INSTANCE = 0; - public static final int TARGET = 1; - public static final int PAGE_FRAME_DESCRIPTOR = 2; + public static final int PAGE_FRAME_DESCRIPTOR = 0; + public static final int INSTANCE = 1; + public static final int DRAW_INSTANCE_INDEX = 2; public static final int MODEL = 3; public static final int DRAW = 4; + public static final int LIGHT_LUT = 5; public static final int LIGHT_SECTION = 6; public static final int MATRICES = 7; diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/DepthPyramid.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/DepthPyramid.java index cb17f5276..1ba12b86f 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/DepthPyramid.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/DepthPyramid.java @@ -5,6 +5,7 @@ import com.mojang.blaze3d.platform.GlStateManager; +import dev.engine_room.flywheel.backend.gl.GlTextureUnit; import dev.engine_room.flywheel.backend.gl.shader.GlProgram; import dev.engine_room.flywheel.lib.math.MoreMath; import net.minecraft.client.Minecraft; @@ -12,23 +13,13 @@ public class DepthPyramid { private final GlProgram depthReduceProgram; - public final int pyramidTextureId; + public int pyramidTextureId = -1; private int lastWidth = -1; private int lastHeight = -1; public DepthPyramid(GlProgram depthReduceProgram) { this.depthReduceProgram = depthReduceProgram; - - pyramidTextureId = GL32.glGenTextures(); - - GlStateManager._bindTexture(pyramidTextureId); - GlStateManager._texParameter(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MIN_FILTER, GL32.GL_NEAREST); - GlStateManager._texParameter(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MAG_FILTER, GL32.GL_NEAREST); - GlStateManager._texParameter(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_COMPARE_MODE, GL32.GL_NONE); - GlStateManager._texParameter(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_WRAP_S, GL32.GL_CLAMP_TO_EDGE); - GlStateManager._texParameter(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_WRAP_T, GL32.GL_CLAMP_TO_EDGE); - } public void generate() { @@ -44,11 +35,9 @@ public void generate() { int depthBufferId = mainRenderTarget.getDepthTextureId(); - GlStateManager._bindTexture(depthBufferId); - GL46.glMemoryBarrier(GL46.GL_FRAMEBUFFER_BARRIER_BIT); - GL46.glActiveTexture(GL32.GL_TEXTURE1); + GlTextureUnit.T1.makeActive(); depthReduceProgram.bind(); @@ -57,7 +46,7 @@ public void generate() { int mipHeight = mipSize(height, i); int srcTexture = (i == 0) ? depthBufferId : pyramidTextureId; - GL46.glBindTexture(GL32.GL_TEXTURE_2D, srcTexture); + GlStateManager._bindTexture(srcTexture); GL46.glBindImageTexture(0, pyramidTextureId, i, false, 0, GL32.GL_WRITE_ONLY, GL32.GL_R32F); @@ -71,7 +60,10 @@ public void generate() { } public void delete() { - GL32.glDeleteTextures(pyramidTextureId); + if (pyramidTextureId != -1) { + GL32.glDeleteTextures(pyramidTextureId); + pyramidTextureId = -1; + } } private void createPyramidMips(int mipLevels, int width, int height) { @@ -82,14 +74,16 @@ private void createPyramidMips(int mipLevels, int width, int height) { lastWidth = width; lastHeight = height; - GL32.glBindTexture(GL32.GL_TEXTURE_2D, pyramidTextureId); + delete(); - for (int i = 0; i < mipLevels; i++) { - int mipWidth = mipSize(width, i); - int mipHeight = mipSize(height, i); + pyramidTextureId = GL46.glCreateTextures(GL46.GL_TEXTURE_2D); + GL46.glTextureStorage2D(pyramidTextureId, mipLevels, GL32.GL_R32F, width, height); - GL32.glTexImage2D(GL32.GL_TEXTURE_2D, i, GL32.GL_R32F, mipWidth, mipHeight, 0, GL32.GL_RED, GL32.GL_FLOAT, 0); - } + GL46.glTextureParameteri(pyramidTextureId, GL32.GL_TEXTURE_MIN_FILTER, GL32.GL_NEAREST); + GL46.glTextureParameteri(pyramidTextureId, GL32.GL_TEXTURE_MAG_FILTER, GL32.GL_NEAREST); + GL46.glTextureParameteri(pyramidTextureId, GL32.GL_TEXTURE_COMPARE_MODE, GL32.GL_NONE); + GL46.glTextureParameteri(pyramidTextureId, GL32.GL_TEXTURE_WRAP_S, GL32.GL_CLAMP_TO_EDGE); + GL46.glTextureParameteri(pyramidTextureId, GL32.GL_TEXTURE_WRAP_T, GL32.GL_CLAMP_TO_EDGE); } public static int mipSize(int mip0Size, int level) { 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 498030fe7..f8597184b 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 @@ -30,18 +30,19 @@ public class IndirectBuffers { private static final long BUFFERS_SIZE_BYTES = SIZE_OFFSET + BUFFER_COUNT * PTR_SIZE; // Offsets to the vbos - private static final long INSTANCE_HANDLE_OFFSET = HANDLE_OFFSET; - private static final long TARGET_HANDLE_OFFSET = INT_SIZE; - private static final long PAGE_FRAME_DESCRIPTOR_HANDLE_OFFSET = INT_SIZE * 2; - private static final long MODEL_HANDLE_OFFSET = INT_SIZE * 3; - private static final long DRAW_HANDLE_OFFSET = INT_SIZE * 4; + private static final long PAGE_FRAME_DESCRIPTOR_HANDLE_OFFSET = HANDLE_OFFSET + BufferBindings.PAGE_FRAME_DESCRIPTOR * INT_SIZE; + private static final long INSTANCE_HANDLE_OFFSET = HANDLE_OFFSET + BufferBindings.INSTANCE * INT_SIZE; + private static final long DRAW_INSTANCE_INDEX_HANDLE_OFFSET = HANDLE_OFFSET + BufferBindings.DRAW_INSTANCE_INDEX * INT_SIZE; + private static final long MODEL_HANDLE_OFFSET = HANDLE_OFFSET + BufferBindings.MODEL * INT_SIZE; + private static final long DRAW_HANDLE_OFFSET = HANDLE_OFFSET + BufferBindings.DRAW * INT_SIZE; // Offsets to the sizes - private static final long INSTANCE_SIZE_OFFSET = SIZE_OFFSET; - private static final long TARGET_SIZE_OFFSET = SIZE_OFFSET + PTR_SIZE; - private static final long PAGE_FRAME_DESCRIPTOR_SIZE_OFFSET = SIZE_OFFSET + PTR_SIZE * 2; - private static final long MODEL_SIZE_OFFSET = SIZE_OFFSET + PTR_SIZE * 3; - private static final long DRAW_SIZE_OFFSET = SIZE_OFFSET + PTR_SIZE * 4; + private static final long PAGE_FRAME_DESCRIPTOR_SIZE_OFFSET = SIZE_OFFSET + BufferBindings.PAGE_FRAME_DESCRIPTOR * PTR_SIZE; + private static final long INSTANCE_SIZE_OFFSET = SIZE_OFFSET + BufferBindings.INSTANCE * PTR_SIZE; + private static final long DRAW_INSTANCE_INDEX_SIZE_OFFSET = SIZE_OFFSET + BufferBindings.DRAW_INSTANCE_INDEX * PTR_SIZE; + private static final long MODEL_SIZE_OFFSET = SIZE_OFFSET + BufferBindings.MODEL * PTR_SIZE; + private static final long DRAW_SIZE_OFFSET = SIZE_OFFSET + BufferBindings.DRAW * PTR_SIZE; + private static final float INSTANCE_GROWTH_FACTOR = 1.25f; private static final float MODEL_GROWTH_FACTOR = 2f; @@ -60,69 +61,71 @@ public class IndirectBuffers { * one for the instance buffer, target buffer, model index buffer, model buffer, and draw buffer. */ private final MemoryBlock multiBindBlock; - private final long instanceStride; public final ObjectStorage objectStorage; - public final ResizableStorageArray target; + public final ResizableStorageArray drawInstanceIndex; public final ResizableStorageArray model; public final ResizableStorageArray draw; IndirectBuffers(long instanceStride) { - this.instanceStride = instanceStride; this.multiBindBlock = MemoryBlock.calloc(BUFFERS_SIZE_BYTES, 1); objectStorage = new ObjectStorage(instanceStride); - target = new ResizableStorageArray(INT_SIZE, INSTANCE_GROWTH_FACTOR); + drawInstanceIndex = new ResizableStorageArray(INT_SIZE, INSTANCE_GROWTH_FACTOR); model = new ResizableStorageArray(MODEL_STRIDE, MODEL_GROWTH_FACTOR); draw = new ResizableStorageArray(DRAW_COMMAND_STRIDE, DRAW_GROWTH_FACTOR); } void updateCounts(int instanceCount, int modelCount, int drawCount) { - target.ensureCapacity(instanceCount); + drawInstanceIndex.ensureCapacity(instanceCount); model.ensureCapacity(modelCount); draw.ensureCapacity(drawCount); final long ptr = multiBindBlock.ptr(); - MemoryUtil.memPutInt(ptr + INSTANCE_HANDLE_OFFSET, objectStorage.objectBuffer.handle()); - MemoryUtil.memPutInt(ptr + TARGET_HANDLE_OFFSET, target.handle()); + MemoryUtil.memPutInt(ptr + PAGE_FRAME_DESCRIPTOR_HANDLE_OFFSET, objectStorage.frameDescriptorBuffer.handle()); + MemoryUtil.memPutInt(ptr + INSTANCE_HANDLE_OFFSET, objectStorage.objectBuffer.handle()); + MemoryUtil.memPutInt(ptr + DRAW_INSTANCE_INDEX_HANDLE_OFFSET, drawInstanceIndex.handle()); MemoryUtil.memPutInt(ptr + MODEL_HANDLE_OFFSET, model.handle()); MemoryUtil.memPutInt(ptr + DRAW_HANDLE_OFFSET, draw.handle()); - MemoryUtil.memPutAddress(ptr + INSTANCE_SIZE_OFFSET, objectStorage.objectBuffer.capacity()); - MemoryUtil.memPutAddress(ptr + TARGET_SIZE_OFFSET, INT_SIZE * instanceCount); MemoryUtil.memPutAddress(ptr + PAGE_FRAME_DESCRIPTOR_SIZE_OFFSET, objectStorage.frameDescriptorBuffer.capacity()); + MemoryUtil.memPutAddress(ptr + INSTANCE_SIZE_OFFSET, objectStorage.objectBuffer.capacity()); + MemoryUtil.memPutAddress(ptr + DRAW_INSTANCE_INDEX_SIZE_OFFSET, INT_SIZE * instanceCount); MemoryUtil.memPutAddress(ptr + MODEL_SIZE_OFFSET, MODEL_STRIDE * modelCount); MemoryUtil.memPutAddress(ptr + DRAW_SIZE_OFFSET, DRAW_COMMAND_STRIDE * drawCount); } - public void bindForCompute() { - multiBind(); + public void bindForCull() { + multiBind(0, 4); } - public void bindForDraw() { - multiBind(); - GlBufferType.DRAW_INDIRECT_BUFFER.bind(draw.handle()); + public void bindForApply() { + multiBind(3, 2); } - private void multiBind() { - final long ptr = multiBindBlock.ptr(); - nglBindBuffersRange(GL_SHADER_STORAGE_BUFFER, BufferBindings.INSTANCE, IndirectBuffers.BUFFER_COUNT, ptr, ptr + OFFSET_OFFSET, ptr + SIZE_OFFSET); + public void bindForDraw() { + multiBind(1, 4); + GlBufferType.DRAW_INDIRECT_BUFFER.bind(draw.handle()); } /** * Bind all buffers except the draw command buffer. */ public void bindForCrumbling() { + multiBind(3, 3); + } + + private void multiBind(int base, int count) { final long ptr = multiBindBlock.ptr(); - nglBindBuffersRange(GL_SHADER_STORAGE_BUFFER, BufferBindings.INSTANCE, 4, ptr, ptr + OFFSET_OFFSET, ptr + SIZE_OFFSET); + nglBindBuffersRange(GL_SHADER_STORAGE_BUFFER, base, count, ptr + base * INT_SIZE, ptr + OFFSET_OFFSET + base * PTR_SIZE, ptr + SIZE_OFFSET + base * PTR_SIZE); } public void delete() { multiBindBlock.free(); objectStorage.delete(); - target.delete(); + drawInstanceIndex.delete(); model.delete(); draw.delete(); } 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 961d5b2ce..c12277860 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 @@ -118,7 +118,7 @@ public void dispatchCull() { Uniforms.bindAll(); cullProgram.bind(); - buffers.bindForCompute(); + buffers.bindForCull(); glDispatchCompute(buffers.objectStorage.capacity(), 1, 1); } @@ -127,7 +127,7 @@ public void dispatchApply() { return; } - buffers.bindForCompute(); + buffers.bindForApply(); glDispatchCompute(GlCompat.getComputeGroupCount(indirectDraws.size()), 1, 1); } diff --git a/common/src/backend/resources/assets/flywheel/flywheel/internal/indirect/buffer_bindings.glsl b/common/src/backend/resources/assets/flywheel/flywheel/internal/indirect/buffer_bindings.glsl index 449836630..256bd68eb 100644 --- a/common/src/backend/resources/assets/flywheel/flywheel/internal/indirect/buffer_bindings.glsl +++ b/common/src/backend/resources/assets/flywheel/flywheel/internal/indirect/buffer_bindings.glsl @@ -1,8 +1,12 @@ -#define _FLW_INSTANCE_BUFFER_BINDING 0 -#define _FLW_TARGET_BUFFER_BINDING 1 -#define _FLW_PAGE_FRAME_DESCRIPTOR_BUFFER_BINDING 2 -#define _FLW_MODEL_BUFFER_BINDING 3 -#define _FLW_DRAW_BUFFER_BINDING 4 +// Per culling group +#define _FLW_PAGE_FRAME_DESCRIPTOR_BUFFER_BINDING 0// cull +#define _FLW_INSTANCE_BUFFER_BINDING 1// cull, draw +#define _FLW_DRAW_INSTANCE_INDEX_BUFFER_BINDING 2// cull, draw +#define _FLW_MODEL_BUFFER_BINDING 3// cull, apply +#define _FLW_DRAW_BUFFER_BINDING 4// apply, draw + +// Global to the engine #define _FLW_LIGHT_LUT_BUFFER_BINDING 5 #define _FLW_LIGHT_SECTIONS_BUFFER_BINDING 6 + #define _FLW_MATRIX_BUFFER_BINDING 7 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 c1ab067bd..38724599f 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 @@ -6,7 +6,7 @@ layout(local_size_x = 32) in; -layout(std430, binding = _FLW_TARGET_BUFFER_BINDING) restrict writeonly buffer TargetBuffer { +layout(std430, binding = _FLW_DRAW_INSTANCE_INDEX_BUFFER_BINDING) restrict writeonly buffer TargetBuffer { uint _flw_instanceIndices[]; }; diff --git a/common/src/backend/resources/assets/flywheel/flywheel/internal/indirect/main.vert b/common/src/backend/resources/assets/flywheel/flywheel/internal/indirect/main.vert index e53dff313..d94725fcb 100644 --- a/common/src/backend/resources/assets/flywheel/flywheel/internal/indirect/main.vert +++ b/common/src/backend/resources/assets/flywheel/flywheel/internal/indirect/main.vert @@ -5,7 +5,7 @@ #include "flywheel:internal/indirect/light.glsl" #include "flywheel:internal/indirect/matrices.glsl" -layout(std430, binding = _FLW_TARGET_BUFFER_BINDING) restrict readonly buffer TargetBuffer { +layout(std430, binding = _FLW_DRAW_INSTANCE_INDEX_BUFFER_BINDING) restrict readonly buffer TargetBuffer { uint _flw_instanceIndices[]; };