From 51224d618ff0a8f90b80222355aaa1cf079e7907 Mon Sep 17 00:00:00 2001 From: Jozufozu Date: Fri, 21 Jun 2024 15:26:48 -0700 Subject: [PATCH] Indirectly lit - "Functional" arena based lighting for indirect - Strip out most of the reference counting stuffs for embeddings - Naively re-buffer all tracked light sections every frame --- .../flywheel/backend/Samplers.java | 1 - .../backend/compile/ContextShader.java | 2 +- .../component/SsboInstanceComponent.java | 4 +-- .../backend/engine/AbstractInstancer.java | 6 +---- .../flywheel/backend/engine/DrawManager.java | 3 ++- .../flywheel/backend/engine/EngineImpl.java | 10 +++---- .../backend/engine/EnvironmentStorage.java | 9 +++++-- .../embed/AbstractEmbeddedEnvironment.java | 22 ++++++++------- .../flywheel/backend/engine/embed/Arena.java | 4 +++ .../backend/engine/embed/Environment.java | 4 --- .../engine/embed/GlobalEnvironment.java | 10 ------- .../backend/engine/embed/LightStorage.java | 26 +++++++++++++++--- .../embed/NestedEmbeddedEnvironment.java | 6 ----- .../embed/TopLevelEmbeddedEnvironment.java | 17 ++++-------- .../engine/indirect/BufferBindings.java | 14 ++++++++++ .../engine/indirect/IndirectBuffers.java | 11 ++------ .../engine/indirect/IndirectDrawManager.java | 13 ++++++--- .../engine/indirect/IndirectInstancer.java | 2 -- .../backend/engine/indirect/LightBuffers.java | 19 ++++++++++++- .../instancing/InstancedDrawManager.java | 5 ++-- .../engine/instancing/InstancedInstancer.java | 2 -- .../flywheel/flywheel/internal/common.frag | 19 ------------- .../flywheel/flywheel/internal/common.vert | 4 +-- .../internal/indirect/buffer_bindings.glsl | 2 ++ .../flywheel/internal/indirect/main.vert | 27 ++++++++++++++----- .../flywheel/internal/instancing/main.vert | 2 +- 26 files changed, 134 insertions(+), 110 deletions(-) create mode 100644 common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/BufferBindings.java diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/Samplers.java b/common/src/backend/java/dev/engine_room/flywheel/backend/Samplers.java index d8d2975dc..cbdde0166 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/Samplers.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/Samplers.java @@ -8,5 +8,4 @@ public class Samplers { public static final GlTextureUnit LIGHT = GlTextureUnit.T2; public static final GlTextureUnit CRUMBLING = GlTextureUnit.T3; public static final GlTextureUnit INSTANCE_BUFFER = GlTextureUnit.T4; - public static final GlTextureUnit EMBEDDED_LIGHT = GlTextureUnit.T5; } diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/compile/ContextShader.java b/common/src/backend/java/dev/engine_room/flywheel/backend/compile/ContextShader.java index bcc7832e5..6d3fede7a 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/compile/ContextShader.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/compile/ContextShader.java @@ -13,7 +13,7 @@ public enum ContextShader { DEFAULT(null, $ -> { }), CRUMBLING("_FLW_CRUMBLING", program -> program.setSamplerBinding("_flw_crumblingTex", Samplers.CRUMBLING)), - EMBEDDED("_FLW_EMBEDDED", program -> program.setSamplerBinding("_flw_lightVolume", Samplers.EMBEDDED_LIGHT)); + EMBEDDED("_FLW_EMBEDDED", $ -> {}); @Nullable private final String define; diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/compile/component/SsboInstanceComponent.java b/common/src/backend/java/dev/engine_room/flywheel/backend/compile/component/SsboInstanceComponent.java index 756ab202f..92fb61099 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/compile/component/SsboInstanceComponent.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/compile/component/SsboInstanceComponent.java @@ -5,7 +5,7 @@ import java.util.ArrayList; import dev.engine_room.flywheel.api.Flywheel; import dev.engine_room.flywheel.api.instance.InstanceType; import dev.engine_room.flywheel.api.layout.Layout; -import dev.engine_room.flywheel.backend.engine.indirect.IndirectBuffers; +import dev.engine_room.flywheel.backend.engine.indirect.BufferBindings; import dev.engine_room.flywheel.backend.glsl.generate.FnSignature; import dev.engine_room.flywheel.backend.glsl.generate.GlslBlock; import dev.engine_room.flywheel.backend.glsl.generate.GlslBuilder; @@ -43,7 +43,7 @@ public class SsboInstanceComponent extends InstanceAssemblerComponent { fnBody.ret(GlslExpr.call(STRUCT_NAME, unpackArgs)); - builder._addRaw("layout(std430, binding = " + IndirectBuffers.INSTANCE_INDEX + ") restrict readonly buffer InstanceBuffer {\n" + builder._addRaw("layout(std430, binding = " + BufferBindings.INSTANCE_BUFFER_BINDING + ") restrict readonly buffer InstanceBuffer {\n" + " uint _flw_instances[];\n" + "};"); builder.blankLine(); diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/AbstractInstancer.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/AbstractInstancer.java index 56fbfcf9d..6cbadf9c9 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/AbstractInstancer.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/AbstractInstancer.java @@ -25,8 +25,6 @@ public abstract class AbstractInstancer implements Instancer protected AbstractInstancer(InstanceType type, Environment environment) { this.type = type; this.environment = environment; - - environment.acquire(); } @Override @@ -177,9 +175,7 @@ public abstract class AbstractInstancer implements Instancer deleted.clear(); } - public void delete() { - environment.release(); - } + public abstract void delete(); @Override public String toString() { diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/DrawManager.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/DrawManager.java index 014d2ccdf..8f8def6e0 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/DrawManager.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/DrawManager.java @@ -16,6 +16,7 @@ import dev.engine_room.flywheel.api.instance.Instancer; import dev.engine_room.flywheel.api.model.Model; import dev.engine_room.flywheel.backend.FlwBackend; import dev.engine_room.flywheel.backend.engine.embed.Environment; +import dev.engine_room.flywheel.backend.engine.embed.LightStorage; import dev.engine_room.flywheel.lib.util.Pair; import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; @@ -45,7 +46,7 @@ public abstract class DrawManager> { initializationQueue.clear(); } - public void flush() { + public void flush(LightStorage lightStorage) { // Thread safety: flush is called from the render thread after all visual updates have been made, // so there are no:tm: threads we could be racing with. for (var instancer : initializationQueue) { diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/EngineImpl.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/EngineImpl.java index 87349d721..4b17aa5c8 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/EngineImpl.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/EngineImpl.java @@ -31,7 +31,7 @@ import net.minecraft.world.phys.Vec3; public class EngineImpl implements Engine { private final int sqrMaxOriginDistance; private final DrawManager> drawManager; - private final EnvironmentStorage environmentStorage = new EnvironmentStorage(); + private final EnvironmentStorage environmentStorage; private final LightStorage lightStorage; private final Flag flushFlag = new NamedFlag("flushed"); @@ -40,12 +40,13 @@ public class EngineImpl implements Engine { public EngineImpl(LevelAccessor level, DrawManager> drawManager, int maxOriginDistance) { this.drawManager = drawManager; sqrMaxOriginDistance = maxOriginDistance * maxOriginDistance; - lightStorage = new LightStorage(level); + environmentStorage = new EnvironmentStorage(); + lightStorage = new LightStorage(level, environmentStorage); } @Override public Plan createFramePlan() { - return SyncedPlan.of(this::flush); + return lightStorage.createFramePlan().then(SyncedPlan.of(this::flush)); } @Override @@ -96,7 +97,6 @@ public class EngineImpl implements Engine { @Override public void delete() { drawManager.delete(); - environmentStorage.delete(); lightStorage.delete(); } @@ -107,8 +107,8 @@ public class EngineImpl implements Engine { private void flush(RenderContext ctx) { try (var state = GlStateTracker.getRestoreState()) { Uniforms.update(ctx); - drawManager.flush(); environmentStorage.flush(); + drawManager.flush(lightStorage); } flushFlag.raise(); diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/EnvironmentStorage.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/EnvironmentStorage.java index 5a260eb04..66e3a9dd5 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/EnvironmentStorage.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/EnvironmentStorage.java @@ -1,6 +1,8 @@ package dev.engine_room.flywheel.backend.engine; import dev.engine_room.flywheel.backend.engine.embed.AbstractEmbeddedEnvironment; +import it.unimi.dsi.fastutil.longs.LongOpenHashSet; +import it.unimi.dsi.fastutil.longs.LongSet; import it.unimi.dsi.fastutil.objects.ReferenceLinkedOpenHashSet; import it.unimi.dsi.fastutil.objects.ReferenceSet; import it.unimi.dsi.fastutil.objects.ReferenceSets; @@ -13,10 +15,13 @@ public class EnvironmentStorage { } public void flush() { + environments.removeIf(AbstractEmbeddedEnvironment::isDeleted); environments.forEach(AbstractEmbeddedEnvironment::flush); } - public void delete() { - environments.clear(); + public LongSet allLightSections() { + var out = new LongOpenHashSet(); + environments.forEach(e -> e.addLightSections(out)); + return out; } } diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/AbstractEmbeddedEnvironment.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/AbstractEmbeddedEnvironment.java index f2a7912be..5d6c573d1 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/AbstractEmbeddedEnvironment.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/AbstractEmbeddedEnvironment.java @@ -15,10 +15,10 @@ import dev.engine_room.flywheel.api.visualization.VisualEmbedding; import dev.engine_room.flywheel.backend.compile.ContextShader; import dev.engine_room.flywheel.backend.engine.EngineImpl; import dev.engine_room.flywheel.backend.gl.shader.GlProgram; -import dev.engine_room.flywheel.backend.util.AtomicReferenceCounted; +import it.unimi.dsi.fastutil.longs.LongSet; import net.minecraft.core.Vec3i; -public abstract class AbstractEmbeddedEnvironment extends AtomicReferenceCounted implements Environment, VisualEmbedding { +public abstract class AbstractEmbeddedEnvironment implements Environment, VisualEmbedding { protected final Matrix4f pose = new Matrix4f(); protected final Matrix3f normal = new Matrix3f(); private final Matrix4f poseComposed = new Matrix4f(); @@ -27,6 +27,8 @@ public abstract class AbstractEmbeddedEnvironment extends AtomicReferenceCounted protected final EngineImpl engine; private final RenderStage renderStage; + private boolean deleted = false; + public AbstractEmbeddedEnvironment(EngineImpl engine, RenderStage renderStage) { this.engine = engine; this.renderStage = renderStage; @@ -38,9 +40,6 @@ public abstract class AbstractEmbeddedEnvironment extends AtomicReferenceCounted return engine.instancer(AbstractEmbeddedEnvironment.this, type, model, renderStage); } }; - - // Acquire the reference owned by the visual that created this. - acquire(); } @Override @@ -94,15 +93,20 @@ public abstract class AbstractEmbeddedEnvironment extends AtomicReferenceCounted return out; } + public boolean isDeleted() { + return deleted; + } + + public void addLightSections(LongSet out) { + + } + /** * Called by visuals */ @Override public void delete() { - // Release the reference owned by the visual that created this. - // Note that visuals don't explicitly call acquire, instead the - // storage acquired a reference when this was constructed. - release(); + deleted = true; } public abstract void setupLight(GlProgram program); diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/Arena.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/Arena.java index 31dbc77cd..a43d6cbe5 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/Arena.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/Arena.java @@ -47,4 +47,8 @@ public class Arena { public void delete() { memoryBlock.free(); } + + public int capacity() { + return top; + } } diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/Environment.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/Environment.java index 91da73062..626f103e5 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/Environment.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/Environment.java @@ -9,8 +9,4 @@ public interface Environment { void setupDraw(GlProgram drawProgram); void setupCull(GlProgram cullProgram); - - void acquire(); - - void release(); } diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/GlobalEnvironment.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/GlobalEnvironment.java index b4c852280..c6e50acbd 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/GlobalEnvironment.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/GlobalEnvironment.java @@ -23,14 +23,4 @@ public class GlobalEnvironment implements Environment { public void setupCull(GlProgram cullProgram) { cullProgram.setBool(EmbeddingUniforms.USE_MODEL_MATRIX, false); } - - @Override - public void acquire() { - - } - - @Override - public void release() { - - } } diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/LightStorage.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/LightStorage.java index c1edb2fcf..242c595f3 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/LightStorage.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/LightStorage.java @@ -4,7 +4,11 @@ import java.util.BitSet; import org.lwjgl.system.MemoryUtil; +import dev.engine_room.flywheel.api.event.RenderContext; +import dev.engine_room.flywheel.api.task.Plan; +import dev.engine_room.flywheel.backend.engine.EnvironmentStorage; import dev.engine_room.flywheel.backend.engine.indirect.StagingBuffer; +import dev.engine_room.flywheel.lib.task.SimplePlan; import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.longs.Long2IntMap; import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; @@ -29,11 +33,12 @@ import net.minecraft.world.level.LightLayer; *

Thus, each section occupies 5832 bytes. */ public class LightStorage { - private final long SECTION_SIZE_BYTES = 9 * 9 * 9 * 8; - private final int DEFAULT_ARENA_CAPACITY_SECTIONS = 64; - private final int INVALID_SECTION = -1; + public static final long SECTION_SIZE_BYTES = 9 * 9 * 9 * 8; + private static final int DEFAULT_ARENA_CAPACITY_SECTIONS = 64; + private static final int INVALID_SECTION = -1; private final LevelAccessor level; + private final EnvironmentStorage environmentStorage; private final Arena arena; private final Long2IntMap section2ArenaIndex = new Long2IntOpenHashMap(); @@ -44,12 +49,24 @@ public class LightStorage { private final BitSet changed = new BitSet(); private boolean newSections = false; - public LightStorage(LevelAccessor level) { + public LightStorage(LevelAccessor level, EnvironmentStorage environmentStorage) { this.level = level; + this.environmentStorage = environmentStorage; arena = new Arena(SECTION_SIZE_BYTES, DEFAULT_ARENA_CAPACITY_SECTIONS); } + public Plan createFramePlan() { + return SimplePlan.of(() -> { + var longs = environmentStorage.allLightSections(); + longs.forEach(this::addSection); + }); + } + + public int capacity() { + return arena.capacity(); + } + public void addSection(long section) { var lightEngine = level.getLightEngine(); @@ -187,6 +204,7 @@ public class LightStorage { for (int i = changed.nextSetBit(0); i >= 0; i = changed.nextSetBit(i + 1)) { staging.enqueueCopy(arena.indexToPointer(i), SECTION_SIZE_BYTES, dstVbo, i * SECTION_SIZE_BYTES); } + changed.clear(); } public IntArrayList createLut() { diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/NestedEmbeddedEnvironment.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/NestedEmbeddedEnvironment.java index 82afd22fa..e2b727476 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/NestedEmbeddedEnvironment.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/NestedEmbeddedEnvironment.java @@ -14,7 +14,6 @@ public class NestedEmbeddedEnvironment extends AbstractEmbeddedEnvironment { public NestedEmbeddedEnvironment(AbstractEmbeddedEnvironment parent, EngineImpl engine, RenderStage renderStage) { super(engine, renderStage); this.parent = parent; - parent.acquire(); } @Override @@ -33,9 +32,4 @@ public class NestedEmbeddedEnvironment extends AbstractEmbeddedEnvironment { pose.mul(this.pose); normal.mul(this.normal); } - - @Override - public void _delete() { - parent.release(); - } } diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/TopLevelEmbeddedEnvironment.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/TopLevelEmbeddedEnvironment.java index 926d246b9..a79ce7ae8 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/TopLevelEmbeddedEnvironment.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/TopLevelEmbeddedEnvironment.java @@ -16,19 +16,17 @@ public class TopLevelEmbeddedEnvironment extends AbstractEmbeddedEnvironment { super(engine, renderStage); } - @Override - public void flush() { - super.flush(); - - lightSections.forEach(engine.lightStorage()::addSection); - } - @Override public void lightChunks(LongSet chunks) { lightSections.clear(); lightSections.addAll(chunks); } + @Override + public void addLightSections(LongSet out) { + out.addAll(lightSections); + } + @Override public void setupLight(GlProgram program) { program.setBool(EmbeddingUniforms.USE_LIGHT_VOLUME, !lightSections.isEmpty()); @@ -39,9 +37,4 @@ public class TopLevelEmbeddedEnvironment extends AbstractEmbeddedEnvironment { pose.set(this.pose); normal.set(this.normal); } - - @Override - protected void _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 new file mode 100644 index 000000000..eba0afbfd --- /dev/null +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/BufferBindings.java @@ -0,0 +1,14 @@ +package dev.engine_room.flywheel.backend.engine.indirect; + +public class BufferBindings { + public static final int INSTANCE_BUFFER_BINDING = 0; + public static final int TARGET_BUFFER_BINDING = 1; + public static final int MODEL_INDEX_BUFFER_BINDING = 2; + public static final int MODEL_BUFFER_BINDING = 3; + public static final int DRAW_BUFFER_BINDING = 4; + public static final int EMBEDDING_LUT_BINDING = 5; + public static final int EMBEDDING_LIGHT_BINDING = 6; + + private BufferBindings() { + } +} 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 fff5d9ea1..68034d16a 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 @@ -22,13 +22,6 @@ public class IndirectBuffers { public static final long DRAW_COMMAND_STRIDE = 40; public static final long DRAW_COMMAND_OFFSET = 0; - public static final int INSTANCE_INDEX = 0; - public static final int TARGET_INDEX = 1; - public static final int MODEL_INDEX_INDEX = 2; - public static final int MODEL_INDEX = 3; - public static final int DRAW_INDEX = 4; - - // Offsets to the 3 segments private static final long HANDLE_OFFSET = 0; private static final long OFFSET_OFFSET = BUFFER_COUNT * INT_SIZE; @@ -117,7 +110,7 @@ public class IndirectBuffers { private void multiBind() { final long ptr = multiBindBlock.ptr(); - nglBindBuffersRange(GL_SHADER_STORAGE_BUFFER, 0, IndirectBuffers.BUFFER_COUNT, ptr, ptr + OFFSET_OFFSET, ptr + SIZE_OFFSET); + nglBindBuffersRange(GL_SHADER_STORAGE_BUFFER, BufferBindings.INSTANCE_BUFFER_BINDING, IndirectBuffers.BUFFER_COUNT, ptr, ptr + OFFSET_OFFSET, ptr + SIZE_OFFSET); } /** @@ -125,7 +118,7 @@ public class IndirectBuffers { */ public void bindForCrumbling() { final long ptr = multiBindBlock.ptr(); - nglBindBuffersRange(GL_SHADER_STORAGE_BUFFER, 0, 4, ptr, ptr + OFFSET_OFFSET, ptr + SIZE_OFFSET); + nglBindBuffersRange(GL_SHADER_STORAGE_BUFFER, BufferBindings.INSTANCE_BUFFER_BINDING, 4, ptr, ptr + OFFSET_OFFSET, ptr + SIZE_OFFSET); } public void delete() { 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 8da0093f9..acc555013 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 @@ -23,6 +23,7 @@ import dev.engine_room.flywheel.backend.engine.InstancerKey; import dev.engine_room.flywheel.backend.engine.MaterialRenderState; import dev.engine_room.flywheel.backend.engine.MeshPool; import dev.engine_room.flywheel.backend.engine.TextureBinder; +import dev.engine_room.flywheel.backend.engine.embed.LightStorage; import dev.engine_room.flywheel.backend.engine.uniform.Uniforms; import dev.engine_room.flywheel.backend.gl.GlStateTracker; import dev.engine_room.flywheel.backend.gl.array.GlVertexArray; @@ -40,6 +41,8 @@ public class IndirectDrawManager extends DrawManager> { private final Map, IndirectCullingGroup> cullingGroups = new HashMap<>(); private final GlBuffer crumblingDrawBuffer = new GlBuffer(); + private final LightBuffers lightBuffers; + public IndirectDrawManager(IndirectPrograms programs) { this.programs = programs; programs.acquire(); @@ -50,6 +53,7 @@ public class IndirectDrawManager extends DrawManager> { vertexArray = GlVertexArray.create(); meshPool.bind(vertexArray); + lightBuffers = new LightBuffers(); } @Override @@ -83,6 +87,7 @@ public class IndirectDrawManager extends DrawManager> { TextureBinder.bindLightAndOverlay(); vertexArray.bindForDraw(); + lightBuffers.bind(); Uniforms.bindAll(); for (var group : cullingGroups.values()) { @@ -95,8 +100,8 @@ public class IndirectDrawManager extends DrawManager> { } @Override - public void flush() { - super.flush(); + public void flush(LightStorage lightStorage) { + super.flush(lightStorage); for (var group : cullingGroups.values()) { group.flushInstancers(); @@ -108,6 +113,8 @@ public class IndirectDrawManager extends DrawManager> { stagingBuffer.reclaim(); + lightBuffers.flush(stagingBuffer, lightStorage); + for (var group : cullingGroups.values()) { group.upload(stagingBuffer); } @@ -159,7 +166,7 @@ public class IndirectDrawManager extends DrawManager> { var block = MemoryBlock.malloc(IndirectBuffers.DRAW_COMMAND_STRIDE); GlBufferType.DRAW_INDIRECT_BUFFER.bind(crumblingDrawBuffer.handle()); - glBindBufferRange(GL_SHADER_STORAGE_BUFFER, IndirectBuffers.DRAW_INDEX, crumblingDrawBuffer.handle(), 0, IndirectBuffers.DRAW_COMMAND_STRIDE); + glBindBufferRange(GL_SHADER_STORAGE_BUFFER, BufferBindings.DRAW_BUFFER_BINDING, crumblingDrawBuffer.handle(), 0, IndirectBuffers.DRAW_COMMAND_STRIDE); for (var groupEntry : byType.entrySet()) { var byProgress = groupEntry.getValue(); 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 38099c85d..b0ac9bc98 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 @@ -125,8 +125,6 @@ public class IndirectInstancer extends AbstractInstancer @Override public void delete() { - super.delete(); - for (IndirectDraw draw : draws()) { draw.delete(); } diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/LightBuffers.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/LightBuffers.java index 9a0a37a57..76e3d200c 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/LightBuffers.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/LightBuffers.java @@ -1,17 +1,25 @@ package dev.engine_room.flywheel.backend.engine.indirect; +import org.lwjgl.opengl.GL46; import org.lwjgl.system.MemoryUtil; import dev.engine_room.flywheel.backend.engine.embed.LightStorage; public class LightBuffers { - private final ResizableStorageBuffer lightArena = new ResizableStorageBuffer(); + private final ResizableStorageArray lightArena = new ResizableStorageArray(LightStorage.SECTION_SIZE_BYTES); private final ResizableStorageArray lut = new ResizableStorageArray(4); public LightBuffers() { } public void flush(StagingBuffer staging, LightStorage light) { + var capacity = light.capacity(); + + if (capacity == 0) { + return; + } + + lightArena.ensureCapacity(capacity); light.uploadChangedSections(staging, lightArena.handle()); if (light.hasNewSections()) { @@ -26,4 +34,13 @@ public class LightBuffers { }); } } + + public void bind() { + if (lightArena.capacity() == 0) { + return; + } + + GL46.glBindBufferRange(GL46.GL_SHADER_STORAGE_BUFFER, BufferBindings.EMBEDDING_LUT_BINDING, lut.handle(), 0, lut.byteCapacity()); + GL46.glBindBufferRange(GL46.GL_SHADER_STORAGE_BUFFER, BufferBindings.EMBEDDING_LIGHT_BINDING, lightArena.handle(), 0, lightArena.byteCapacity()); + } } diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/instancing/InstancedDrawManager.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/instancing/InstancedDrawManager.java index b532823ab..bba7a716a 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/instancing/InstancedDrawManager.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/instancing/InstancedDrawManager.java @@ -22,6 +22,7 @@ import dev.engine_room.flywheel.backend.engine.MaterialEncoder; import dev.engine_room.flywheel.backend.engine.MaterialRenderState; import dev.engine_room.flywheel.backend.engine.MeshPool; import dev.engine_room.flywheel.backend.engine.TextureBinder; +import dev.engine_room.flywheel.backend.engine.embed.LightStorage; import dev.engine_room.flywheel.backend.engine.uniform.Uniforms; import dev.engine_room.flywheel.backend.gl.GlStateTracker; import dev.engine_room.flywheel.backend.gl.TextureBuffer; @@ -55,8 +56,8 @@ public class InstancedDrawManager extends DrawManager> { } @Override - public void flush() { - super.flush(); + public void flush(LightStorage lightStorage) { + super.flush(lightStorage); var instancers = this.instancers.values(); instancers.removeIf(instancer -> { diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/instancing/InstancedInstancer.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/instancing/InstancedInstancer.java index 9ca3d5cc8..a5dff27d9 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/instancing/InstancedInstancer.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/instancing/InstancedInstancer.java @@ -116,8 +116,6 @@ public class InstancedInstancer extends AbstractInstancer } public void delete() { - super.delete(); - if (vbo == null) { return; } diff --git a/common/src/backend/resources/assets/flywheel/flywheel/internal/common.frag b/common/src/backend/resources/assets/flywheel/flywheel/internal/common.frag index f73846dea..23df5b7e9 100644 --- a/common/src/backend/resources/assets/flywheel/flywheel/internal/common.frag +++ b/common/src/backend/resources/assets/flywheel/flywheel/internal/common.frag @@ -13,14 +13,6 @@ uniform sampler2D _flw_crumblingTex; in vec2 _flw_crumblingTexCoord; #endif -#ifdef _FLW_EMBEDDED -uniform sampler3D _flw_lightVolume; - -uniform bool _flw_useLightVolume; - -in vec3 _flw_lightVolumeCoord; -#endif - flat in uint _flw_instanceID; out vec4 _flw_outputColor; @@ -43,12 +35,6 @@ void _flw_main() { flw_fragOverlay = flw_vertexOverlay; flw_fragLight = flw_vertexLight; - #ifdef _FLW_EMBEDDED - if (_flw_useLightVolume) { - flw_fragLight = max(flw_fragLight, texture(_flw_lightVolume, _flw_lightVolumeCoord).rg); - } - #endif - flw_materialFragment(); #ifdef _FLW_CRUMBLING @@ -98,11 +84,6 @@ void _flw_main() { case 6u: color = vec4(vec3(diffuseFactor), 1.); break; - #ifdef _FLW_EMBEDDED - case 7u: - color = vec4(_flw_lightVolumeCoord, 1.); - break; - #endif } _flw_outputColor = flw_fogFilter(color); diff --git a/common/src/backend/resources/assets/flywheel/flywheel/internal/common.vert b/common/src/backend/resources/assets/flywheel/flywheel/internal/common.vert index fae9fd91c..e65cacd7b 100644 --- a/common/src/backend/resources/assets/flywheel/flywheel/internal/common.vert +++ b/common/src/backend/resources/assets/flywheel/flywheel/internal/common.vert @@ -70,7 +70,7 @@ vec2 getCrumblingTexCoord() { uniform mat4 _flw_modelMatrix; uniform mat3 _flw_normalMatrix; -bool _flw_embeddedLight(vec3 worldPos, vec3 normal, out vec2 lightCoord); +bool _flw_embeddedLight(vec3 worldPos, out vec2 lightCoord); #endif flat out uint _flw_instanceID; @@ -89,7 +89,7 @@ void _flw_main(in FlwInstance instance, in uint stableInstanceID) { flw_vertexNormal = _flw_normalMatrix * flw_vertexNormal; vec2 embeddedLight; - if (_flw_embeddedLight(flw_vertexPos, flw_vertexNormal, embeddedLight)) { + if (_flw_embeddedLight(flw_vertexPos.xyz, embeddedLight)) { flw_vertexLight = max(flw_vertexLight, embeddedLight); } #endif 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 4aa9edc56..439c78057 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 @@ -3,3 +3,5 @@ #define _FLW_MODEL_INDEX_BUFFER_BINDING 2 #define _FLW_MODEL_BUFFER_BINDING 3 #define _FLW_DRAW_BUFFER_BINDING 4 +#define _FLW_EMBEDDING_LUT_BINDING 5 +#define _FLW_EMBEDDING_LIGHT_BINDING 6 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 de5493d3c..c9dba65ce 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 @@ -13,24 +13,33 @@ layout(std430, binding = _FLW_DRAW_BUFFER_BINDING) restrict readonly buffer Draw #ifdef _FLW_EMBEDDED -layout(std430, binding = 8) restrict readonly buffer EmbeddingLut { +layout(std430, binding = _FLW_EMBEDDING_LUT_BINDING) restrict readonly buffer EmbeddingLut { uint _flw_embeddingLut[]; }; const uint _FLW_LIGHT_SECTION_SIZE_BYTES = 18 * 18 * 18; const uint _FLW_LIGHT_SECTION_SIZE_INTS = _FLW_LIGHT_SECTION_SIZE_BYTES / 4; -layout(std430, binding = 9) restrict readonly buffer LightSections { +layout(std430, binding = _FLW_EMBEDDING_LIGHT_BINDING) restrict readonly buffer LightSections { uint _flw_lightSections[]; }; +/// Find the index for the next step in the LUT. +/// @param base The base index in the LUT, should point to the start of a coordinate span. +/// @param coord The coordinate to look for. +/// @param next Output. The index of the next step in the LUT. +/// @return true if the coordinate is not in the span. bool _flw_nextLut(uint base, int coord, out uint next) { + // The base coordinate. int start = int(_flw_embeddingLut[base]); + // The width of the coordinate span. uint size = _flw_embeddingLut[base + 1]; + // Index of the coordinate in the span. int i = coord - start; if (i < 0 || i >= size) { + // We missed. return true; } @@ -52,25 +61,29 @@ bool _flw_chunkCoordToSectionIndex(ivec3 sectionPos, out uint index) { return _flw_nextLut(z, sectionPos.z, index); } -vec2 _flw_lightAt(uint sectionOffset, ivec3 blockInSectionPos) { +vec2 _flw_lightAt(uint sectionOffset, uvec3 blockInSectionPos) { uint byteOffset = blockInSectionPos.x + blockInSectionPos.z * 18u + blockInSectionPos.y * 18u * 18u; uint uintOffset = byteOffset >> 2u; uint bitOffset = (byteOffset & 3u) << 3; - uint packed = _flw_lightSections[sectionOffset + uintOffset]; - uint block = (packed >> bitOffset) & 0xFu; - uint sky = (packed >> (bitOffset + 4u)) & 0xFu; + uint raw = _flw_lightSections[sectionOffset + uintOffset]; + uint block = (raw >> bitOffset) & 0xFu; + uint sky = (raw >> (bitOffset + 4u)) & 0xFu; return vec2(block, sky); } -bool _flw_embeddedLight(vec3 worldPos, vec3 normal, out vec2 lightCoord) { +bool _flw_embeddedLight(vec3 worldPos, out vec2 lightCoord) { + ivec3 blockPos = ivec3(floor(worldPos)); + ivec3 sectionPos = blockPos >> 4; uvec3 blockInSectionPos = (blockPos & 0xF) + 1; uint lightSectionIndex; if (_flw_chunkCoordToSectionIndex(sectionPos, lightSectionIndex)) { + // TODO: useful debug mode for this. + // flw_vertexOverlay = ivec2(0, 3); return false; } diff --git a/common/src/backend/resources/assets/flywheel/flywheel/internal/instancing/main.vert b/common/src/backend/resources/assets/flywheel/flywheel/internal/instancing/main.vert index ad3e9f9e3..16d52eb58 100644 --- a/common/src/backend/resources/assets/flywheel/flywheel/internal/instancing/main.vert +++ b/common/src/backend/resources/assets/flywheel/flywheel/internal/instancing/main.vert @@ -5,7 +5,7 @@ uniform uvec4 _flw_packedMaterial; uniform int _flw_baseInstance = 0; #ifdef _FLW_EMBEDDED -bool _flw_embeddedLight(vec3 worldPos, vec3 normal, out vec2 lightCoord) { +bool _flw_embeddedLight(vec3 worldPos, out vec2 lightCoord) { return true; } #endif