mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2024-11-14 14:33:57 +01:00
Lessen updates today!
- LightLut now does incremental updates java-side - Still requires a full upload when changed, though it does not take up much space - ShaderLightVisualStorage now actually triggers removal of light section from the lut
This commit is contained in:
parent
5b97a56c8c
commit
bedb92c73c
@ -3,17 +3,16 @@ package dev.engine_room.flywheel.backend.engine;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
import it.unimi.dsi.fastutil.longs.Long2IntMap;
|
||||
import net.minecraft.core.SectionPos;
|
||||
|
||||
// Massive kudos to RogueLogix for figuring out this LUT scheme.
|
||||
public final class LightLut {
|
||||
private final Layer<Layer<IntLayer>> indices = new Layer<>();
|
||||
|
||||
private LightLut() {
|
||||
}
|
||||
|
||||
private void add(long position, int index) {
|
||||
public void add(long position, int index) {
|
||||
final var x = SectionPos.x(position);
|
||||
final var y = SectionPos.y(position);
|
||||
final var z = SectionPos.z(position);
|
||||
@ -23,31 +22,32 @@ public final class LightLut {
|
||||
.set(z, index + 1);
|
||||
}
|
||||
|
||||
private IntArrayList toLut() {
|
||||
public void remove(long section) {
|
||||
final var x = SectionPos.x(section);
|
||||
final var y = SectionPos.y(section);
|
||||
final var z = SectionPos.z(section);
|
||||
|
||||
var first = indices.get(x);
|
||||
|
||||
if (first == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var second = first.get(y);
|
||||
|
||||
if (second == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
second.clear(z);
|
||||
}
|
||||
|
||||
public IntArrayList flatten() {
|
||||
final var out = new IntArrayList();
|
||||
indices.fillLut(out, (yIndices, lut) -> yIndices.fillLut(lut, IntLayer::fillLut));
|
||||
return out;
|
||||
}
|
||||
|
||||
// Massive kudos to RogueLogix for figuring out this LUT scheme.
|
||||
// TODO: switch to y x z or x z y ordering
|
||||
// DATA LAYOUT
|
||||
// [0] : base chunk X, X index count, followed by linear indices of y blocks
|
||||
// [yBlockIndex] : baseChunk Y, Y index count, followed by linear indices of z blocks for this x
|
||||
// [zBlockIndex] : baseChunk Z, Z index count, followed by linear indices of lighting chunks
|
||||
// this data layout allows a single buffer to represent the lighting volume, without requiring the entire 3d lookup volume to be allocated
|
||||
public static IntArrayList buildLut(Long2IntMap sectionIndicesMaps) {
|
||||
if (sectionIndicesMaps.isEmpty()) {
|
||||
return new IntArrayList();
|
||||
}
|
||||
|
||||
var out = new LightLut();
|
||||
|
||||
sectionIndicesMaps.forEach(out::add);
|
||||
|
||||
return out.toLut();
|
||||
}
|
||||
|
||||
private static final class Layer<T> {
|
||||
private boolean hasBase = false;
|
||||
private int base = 0;
|
||||
@ -78,6 +78,25 @@ public final class LightLut {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public T get(int i) {
|
||||
if (!hasBase) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (i < base) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final var offset = i - base;
|
||||
|
||||
if (offset >= nextLayer.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (T) nextLayer[offset];
|
||||
}
|
||||
|
||||
public T computeIfAbsent(int i, Supplier<T> ifAbsent) {
|
||||
if (!hasBase) {
|
||||
// We don't want to default to base 0, so we'll use the first value we get.
|
||||
@ -155,6 +174,24 @@ public final class LightLut {
|
||||
indices[offset] = index;
|
||||
}
|
||||
|
||||
public void clear(int i) {
|
||||
if (!hasBase) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (i < base) {
|
||||
return;
|
||||
}
|
||||
|
||||
final var offset = i - base;
|
||||
|
||||
if (offset >= indices.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
indices[offset] = 0;
|
||||
}
|
||||
|
||||
private void resize(int length) {
|
||||
final var newIndices = new int[length];
|
||||
System.arraycopy(indices, 0, newIndices, 0, indices.length);
|
||||
|
@ -44,12 +44,9 @@ public class LightStorage {
|
||||
private static final int INVALID_SECTION = -1;
|
||||
|
||||
private final LevelAccessor level;
|
||||
|
||||
private final LightLut lut;
|
||||
private final CpuArena arena;
|
||||
private final Long2IntMap section2ArenaIndex = new Long2IntOpenHashMap();
|
||||
{
|
||||
section2ArenaIndex.defaultReturnValue(INVALID_SECTION);
|
||||
}
|
||||
private final Long2IntMap section2ArenaIndex;
|
||||
|
||||
private final BitSet changed = new BitSet();
|
||||
private boolean needsLutRebuild = false;
|
||||
@ -60,8 +57,10 @@ public class LightStorage {
|
||||
|
||||
public LightStorage(LevelAccessor level) {
|
||||
this.level = level;
|
||||
|
||||
lut = new LightLut();
|
||||
arena = new CpuArena(SECTION_SIZE_BYTES, DEFAULT_ARENA_CAPACITY_SECTIONS);
|
||||
section2ArenaIndex = new Long2IntOpenHashMap();
|
||||
section2ArenaIndex.defaultReturnValue(INVALID_SECTION);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -135,12 +134,22 @@ public class LightStorage {
|
||||
|
||||
if (!requestedSections.contains(section)) {
|
||||
arena.free(entry.getIntValue());
|
||||
needsLutRebuild = true;
|
||||
endTrackingSection(section);
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void beginTrackingSection(long section, int index) {
|
||||
lut.add(section, index);
|
||||
needsLutRebuild = true;
|
||||
}
|
||||
|
||||
private void endTrackingSection(long section) {
|
||||
lut.remove(section);
|
||||
needsLutRebuild = true;
|
||||
}
|
||||
|
||||
public int capacity() {
|
||||
return arena.capacity();
|
||||
}
|
||||
@ -374,7 +383,7 @@ public class LightStorage {
|
||||
if (out == INVALID_SECTION) {
|
||||
out = arena.alloc();
|
||||
section2ArenaIndex.put(section, out);
|
||||
needsLutRebuild = true;
|
||||
beginTrackingSection(section, out);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
@ -406,8 +415,7 @@ public class LightStorage {
|
||||
}
|
||||
|
||||
public IntArrayList createLut() {
|
||||
// TODO: incremental lut updates
|
||||
return LightLut.buildLut(section2ArenaIndex);
|
||||
return lut.flatten();
|
||||
}
|
||||
|
||||
private enum SectionEdge {
|
||||
|
@ -43,7 +43,11 @@ public class ShaderLightVisualStorage {
|
||||
}
|
||||
|
||||
public void remove(ShaderLightVisual visual) {
|
||||
trackers.remove(visual);
|
||||
var tracker = trackers.remove(visual);
|
||||
|
||||
if (tracker != null) {
|
||||
markDirty();
|
||||
}
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
|
Loading…
Reference in New Issue
Block a user