From 4b04d747bd6e1c380b8a3f2f64c021131ff93235 Mon Sep 17 00:00:00 2001 From: Jozufozu Date: Sat, 6 Jul 2024 22:19:47 -0700 Subject: [PATCH] SmoothLit joins the battle - Not attached to the name - Add SmoothLitVisual opt in interface, allowing any visuals to contribute light sections to the arena - Remove lightChunks from VisualEmbedding, it has been usurped - Pass total collected light sections from BEs, Es, and effects to the engine interface. It seemed the most proper way to hand off information from the impl to the backend - Add SmoothLitVisualStorage to maintain the set of collected sections, though at the moment it is very naive and simply unions everything upon request, which is also naively done every frame --- .../flywheel/api/backend/Engine.java | 8 ++++ .../flywheel/api/visual/LitVisual.java | 3 ++ .../flywheel/api/visual/SmoothLitVisual.java | 24 ++++++++++ .../api/visualization/VisualEmbedding.java | 3 -- .../flywheel/backend/engine/EngineImpl.java | 8 +++- .../backend/engine/EnvironmentStorage.java | 8 ---- .../embed/AbstractEmbeddedEnvironment.java | 5 --- .../backend/engine/embed/LightStorage.java | 25 +++++++---- .../embed/NestedEmbeddedEnvironment.java | 6 --- .../embed/TopLevelEmbeddedEnvironment.java | 15 ------- .../VisualizationManagerImpl.java | 9 ++++ .../manager/VisualManagerImpl.java | 5 +++ .../storage/SmoothLitVisualStorage.java | 45 +++++++++++++++++++ .../impl/visualization/storage/Storage.java | 15 +++++++ 14 files changed, 132 insertions(+), 47 deletions(-) create mode 100644 common/src/api/java/dev/engine_room/flywheel/api/visual/SmoothLitVisual.java create mode 100644 common/src/main/java/dev/engine_room/flywheel/impl/visualization/storage/SmoothLitVisualStorage.java diff --git a/common/src/api/java/dev/engine_room/flywheel/api/backend/Engine.java b/common/src/api/java/dev/engine_room/flywheel/api/backend/Engine.java index ab7d41ee9..64e960240 100644 --- a/common/src/api/java/dev/engine_room/flywheel/api/backend/Engine.java +++ b/common/src/api/java/dev/engine_room/flywheel/api/backend/Engine.java @@ -9,6 +9,7 @@ import dev.engine_room.flywheel.api.task.Plan; import dev.engine_room.flywheel.api.task.TaskExecutor; import dev.engine_room.flywheel.api.visualization.VisualizationContext; +import it.unimi.dsi.fastutil.longs.LongSet; import net.minecraft.client.Camera; import net.minecraft.core.BlockPos; import net.minecraft.core.Vec3i; @@ -68,6 +69,13 @@ public interface Engine { */ void delete(); + /** + * Assign the set of sections that visuals have requested GPU light for. + * + * @param sections The set of sections. + */ + void lightSections(LongSet sections); + /** * A block to be rendered as a crumbling overlay. * @param progress The progress of the crumbling animation in the range [0, 10). diff --git a/common/src/api/java/dev/engine_room/flywheel/api/visual/LitVisual.java b/common/src/api/java/dev/engine_room/flywheel/api/visual/LitVisual.java index 4f05e7687..9891962ea 100644 --- a/common/src/api/java/dev/engine_room/flywheel/api/visual/LitVisual.java +++ b/common/src/api/java/dev/engine_room/flywheel/api/visual/LitVisual.java @@ -2,6 +2,8 @@ import java.util.function.LongConsumer; +import org.jetbrains.annotations.ApiStatus; + import net.minecraft.core.SectionPos; /** @@ -51,6 +53,7 @@ public interface LitVisual extends Visual { * A notifier object that can be used to indicate to the impl * that the sections a visual is contained in have changed. */ + @ApiStatus.NonExtendable interface Notifier { /** * Invoke this to indicate to the impl that your visual has moved to a different set of sections. diff --git a/common/src/api/java/dev/engine_room/flywheel/api/visual/SmoothLitVisual.java b/common/src/api/java/dev/engine_room/flywheel/api/visual/SmoothLitVisual.java new file mode 100644 index 000000000..43daf3757 --- /dev/null +++ b/common/src/api/java/dev/engine_room/flywheel/api/visual/SmoothLitVisual.java @@ -0,0 +1,24 @@ +package dev.engine_room.flywheel.api.visual; + +import org.jetbrains.annotations.ApiStatus; + +import it.unimi.dsi.fastutil.longs.LongSet; + +public interface SmoothLitVisual extends Visual { + /** + * Set the section property object. + * + *

This method is only called once, upon visual creation, + * + * @param property The property. + */ + void setSectionProperty(SectionProperty property); + + @ApiStatus.NonExtendable + interface SectionProperty { + /** + * Invoke this to indicate to the impl that your visual has moved to a different set of sections. + */ + void lightSections(LongSet sections); + } +} diff --git a/common/src/api/java/dev/engine_room/flywheel/api/visualization/VisualEmbedding.java b/common/src/api/java/dev/engine_room/flywheel/api/visualization/VisualEmbedding.java index e0b6d4f81..baf35844c 100644 --- a/common/src/api/java/dev/engine_room/flywheel/api/visualization/VisualEmbedding.java +++ b/common/src/api/java/dev/engine_room/flywheel/api/visualization/VisualEmbedding.java @@ -4,7 +4,6 @@ import org.joml.Matrix4fc; import dev.engine_room.flywheel.api.BackendImplemented; -import it.unimi.dsi.fastutil.longs.LongSet; @BackendImplemented public interface VisualEmbedding extends VisualizationContext { @@ -16,8 +15,6 @@ public interface VisualEmbedding extends VisualizationContext { */ void transforms(Matrix4fc pose, Matrix3fc normal); - void lightChunks(LongSet chunks); - /** * Delete this embedding. * 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 1912bbf23..fa36cd21f 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 @@ -22,6 +22,7 @@ import dev.engine_room.flywheel.lib.task.Flag; import dev.engine_room.flywheel.lib.task.NamedFlag; import dev.engine_room.flywheel.lib.task.SyncedPlan; +import it.unimi.dsi.fastutil.longs.LongSet; import net.minecraft.client.Camera; import net.minecraft.core.BlockPos; import net.minecraft.core.Vec3i; @@ -41,7 +42,7 @@ public EngineImpl(LevelAccessor level, DrawManager Instancer instancer(Environment environment, InstanceType type, Model model, RenderStage stage) { return drawManager.getInstancer(environment, type, model, stage); } 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 66e3a9dd5..e68ea5250 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,8 +1,6 @@ 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; @@ -18,10 +16,4 @@ public void flush() { environments.removeIf(AbstractEmbeddedEnvironment::isDeleted); environments.forEach(AbstractEmbeddedEnvironment::flush); } - - 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 2861dee83..6bf89450c 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,7 +15,6 @@ 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 it.unimi.dsi.fastutil.longs.LongSet; import net.minecraft.core.Vec3i; public abstract class AbstractEmbeddedEnvironment implements Environment, VisualEmbedding { @@ -95,10 +94,6 @@ public boolean isDeleted() { return deleted; } - public void addLightSections(LongSet out) { - - } - /** * Called by visuals */ 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 02cd179e8..c9dd9b179 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 @@ -2,11 +2,11 @@ import java.util.BitSet; +import org.jetbrains.annotations.Nullable; 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.backend.gl.buffer.GlBuffer; import dev.engine_room.flywheel.lib.task.SimplePlan; @@ -40,7 +40,6 @@ public class LightStorage { 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(); @@ -51,18 +50,26 @@ public class LightStorage { private final BitSet changed = new BitSet(); private boolean needsLutRebuild = false; - public LightStorage(LevelAccessor level, EnvironmentStorage environmentStorage) { + @Nullable + private LongSet requestedSections; + + public LightStorage(LevelAccessor level) { this.level = level; - this.environmentStorage = environmentStorage; arena = new Arena(SECTION_SIZE_BYTES, DEFAULT_ARENA_CAPACITY_SECTIONS); } + public void sections(LongSet sections) { + requestedSections = sections; + } + public Plan createFramePlan() { return SimplePlan.of(() -> { - var allLightSections = environmentStorage.allLightSections(); + if (requestedSections == null) { + return; + } - removeUnusedSections(allLightSections); + removeUnusedSections(requestedSections); var knownSections = section2ArenaIndex.keySet(); @@ -70,7 +77,7 @@ public Plan createFramePlan() { .getUpdatedSections(); // Only add the new sections. - allLightSections.removeAll(knownSections); + requestedSections.removeAll(knownSections); for (long updatedSection : updatedSections) { for (int x = -1; x <= 1; x++) { @@ -78,14 +85,14 @@ public Plan createFramePlan() { for (int z = -1; z <= 1; z++) { long section = SectionPos.offset(updatedSection, x, y, z); if (knownSections.contains(section)) { - allLightSections.add(section); + requestedSections.add(section); } } } } } - for (long section : allLightSections) { + for (long section : requestedSections) { addSection(section); } }); 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 516d1f358..fb4bfbb49 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 @@ -5,7 +5,6 @@ import dev.engine_room.flywheel.api.event.RenderStage; import dev.engine_room.flywheel.backend.engine.EngineImpl; -import it.unimi.dsi.fastutil.longs.LongSet; public class NestedEmbeddedEnvironment extends AbstractEmbeddedEnvironment { private final AbstractEmbeddedEnvironment parent; @@ -15,11 +14,6 @@ public NestedEmbeddedEnvironment(AbstractEmbeddedEnvironment parent, EngineImpl this.parent = parent; } - @Override - public void lightChunks(LongSet chunks) { - // noop - } - @Override public void composeMatrices(Matrix4f pose, Matrix3f normal) { parent.composeMatrices(pose, normal); 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 4c58a8660..297c3dd6b 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 @@ -5,27 +5,12 @@ import dev.engine_room.flywheel.api.event.RenderStage; import dev.engine_room.flywheel.backend.engine.EngineImpl; -import it.unimi.dsi.fastutil.longs.LongArraySet; -import it.unimi.dsi.fastutil.longs.LongSet; public class TopLevelEmbeddedEnvironment extends AbstractEmbeddedEnvironment { - private final LongSet lightSections = new LongArraySet(); - public TopLevelEmbeddedEnvironment(EngineImpl engine, RenderStage renderStage) { super(engine, renderStage); } - @Override - public void lightChunks(LongSet chunks) { - lightSections.clear(); - lightSections.addAll(chunks); - } - - @Override - public void addLightSections(LongSet out) { - out.addAll(lightSections); - } - @Override public void composeMatrices(Matrix4f pose, Matrix3f normal) { pose.set(this.pose); diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/visualization/VisualizationManagerImpl.java b/common/src/main/java/dev/engine_room/flywheel/impl/visualization/VisualizationManagerImpl.java index e0accaf2d..7b2f9920e 100644 --- a/common/src/main/java/dev/engine_room/flywheel/impl/visualization/VisualizationManagerImpl.java +++ b/common/src/main/java/dev/engine_room/flywheel/impl/visualization/VisualizationManagerImpl.java @@ -45,6 +45,7 @@ import dev.engine_room.flywheel.lib.task.SimplePlan; import dev.engine_room.flywheel.lib.util.LevelAttached; import it.unimi.dsi.fastutil.longs.Long2ObjectMap; +import it.unimi.dsi.fastutil.longs.LongOpenHashSet; import net.minecraft.client.Minecraft; import net.minecraft.core.Vec3i; import net.minecraft.server.level.BlockDestructionProgress; @@ -104,6 +105,14 @@ private VisualizationManagerImpl(LevelAccessor level) { .ifTrue(recreate) .ifFalse(update) .plan() + .then(SimplePlan.of(() -> { + // TODO: Lazily re-evaluate the union'd set + var out = new LongOpenHashSet(); + out.addAll(blockEntities.lightSections()); + out.addAll(entities.lightSections()); + out.addAll(effects.lightSections()); + engine.lightSections(out); + })) .then(RaisePlan.raise(frameVisualsFlag)) .then(engine.createFramePlan()) .then(RaisePlan.raise(frameFlag)); diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/visualization/manager/VisualManagerImpl.java b/common/src/main/java/dev/engine_room/flywheel/impl/visualization/manager/VisualManagerImpl.java index 3abc3c7ac..213b9b436 100644 --- a/common/src/main/java/dev/engine_room/flywheel/impl/visualization/manager/VisualManagerImpl.java +++ b/common/src/main/java/dev/engine_room/flywheel/impl/visualization/manager/VisualManagerImpl.java @@ -10,6 +10,7 @@ import dev.engine_room.flywheel.impl.visualization.storage.Storage; import dev.engine_room.flywheel.impl.visualization.storage.Transaction; import dev.engine_room.flywheel.lib.task.SimplePlan; +import it.unimi.dsi.fastutil.longs.LongSet; public class VisualManagerImpl> implements VisualManager { private final Queue> queue = new ConcurrentLinkedQueue<>(); @@ -74,4 +75,8 @@ public Plan tickPlan() { return SimplePlan.of(context -> processQueue(1)) .then(storage.tickPlan()); } + + public LongSet lightSections() { + return getStorage().lightSections(); + } } diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/visualization/storage/SmoothLitVisualStorage.java b/common/src/main/java/dev/engine_room/flywheel/impl/visualization/storage/SmoothLitVisualStorage.java new file mode 100644 index 000000000..2dbe51d3b --- /dev/null +++ b/common/src/main/java/dev/engine_room/flywheel/impl/visualization/storage/SmoothLitVisualStorage.java @@ -0,0 +1,45 @@ +package dev.engine_room.flywheel.impl.visualization.storage; + +import java.util.Map; + +import dev.engine_room.flywheel.api.visual.SmoothLitVisual; +import it.unimi.dsi.fastutil.longs.LongArraySet; +import it.unimi.dsi.fastutil.longs.LongOpenHashSet; +import it.unimi.dsi.fastutil.longs.LongSet; +import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap; + +public class SmoothLitVisualStorage { + private final Map visuals = new Reference2ObjectOpenHashMap<>(); + + public LongSet sections() { + var out = new LongOpenHashSet(); + for (SectionProperty value : visuals.values()) { + out.addAll(value.sections); + } + return out; + } + + public void remove(SmoothLitVisual smoothLit) { + visuals.remove(smoothLit); + } + + public void add(SmoothLitVisual smoothLit) { + var sections = new SectionProperty(); + visuals.put(smoothLit, sections); + smoothLit.setSectionProperty(sections); + } + + public void clear() { + visuals.clear(); + } + + private static final class SectionProperty implements SmoothLitVisual.SectionProperty { + private final LongSet sections = new LongArraySet(); + + @Override + public void lightSections(LongSet sections) { + this.sections.clear(); + this.sections.addAll(sections); + } + } +} diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/visualization/storage/Storage.java b/common/src/main/java/dev/engine_room/flywheel/impl/visualization/storage/Storage.java index b599dc26e..e2445ddd9 100644 --- a/common/src/main/java/dev/engine_room/flywheel/impl/visualization/storage/Storage.java +++ b/common/src/main/java/dev/engine_room/flywheel/impl/visualization/storage/Storage.java @@ -11,6 +11,7 @@ import dev.engine_room.flywheel.api.task.Plan; import dev.engine_room.flywheel.api.visual.DynamicVisual; import dev.engine_room.flywheel.api.visual.LitVisual; +import dev.engine_room.flywheel.api.visual.SmoothLitVisual; import dev.engine_room.flywheel.api.visual.TickableVisual; import dev.engine_room.flywheel.api.visual.Visual; import dev.engine_room.flywheel.api.visualization.VisualizationContext; @@ -19,6 +20,7 @@ import dev.engine_room.flywheel.lib.task.PlanMap; import dev.engine_room.flywheel.lib.visual.SimpleDynamicVisual; import dev.engine_room.flywheel.lib.visual.SimpleTickableVisual; +import it.unimi.dsi.fastutil.longs.LongSet; import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap; public abstract class Storage { @@ -28,6 +30,7 @@ public abstract class Storage { protected final List simpleDynamicVisuals = new ArrayList<>(); protected final List simpleTickableVisuals = new ArrayList<>(); protected final LitVisualStorage litVisuals = new LitVisualStorage(); + protected final SmoothLitVisualStorage smoothLitVisuals = new SmoothLitVisualStorage(); private final Map visuals = new Reference2ObjectOpenHashMap<>(); @@ -71,6 +74,9 @@ public void remove(T obj) { if (visual instanceof LitVisual lit) { litVisuals.remove(lit); } + if (visual instanceof SmoothLitVisual smoothLit) { + smoothLitVisuals.remove(smoothLit); + } visual.delete(); } @@ -90,6 +96,7 @@ public void recreateAll(float partialTick) { simpleTickableVisuals.clear(); simpleDynamicVisuals.clear(); litVisuals.clear(); + smoothLitVisuals.clear(); visuals.replaceAll((obj, visual) -> { visual.delete(); @@ -156,6 +163,10 @@ private void setup(Visual visual) { if (visual instanceof LitVisual lit) { litVisuals.setNotifierAndAdd(lit); } + + if (visual instanceof SmoothLitVisual smoothLit) { + smoothLitVisuals.add(smoothLit); + } } /** @@ -164,4 +175,8 @@ private void setup(Visual visual) { * @return true if the object is currently capable of being visualized. */ public abstract boolean willAccept(T obj); + + public LongSet lightSections() { + return smoothLitVisuals.sections(); + } }