Cheaper block writes and palette lookups

- ColumnExtentListeningHunk reports writes through a primitive listener instead of boxing ListeningHunk
- Palette layer generators memoized per seed slot instead of one shared recent entry
This commit is contained in:
Brian Neumann-Fopiano
2026-09-28 13:41:08 -04:00
parent f4a06efa21
commit 2ac9609407
2 changed files with 41 additions and 8 deletions
@@ -47,6 +47,7 @@ import lombok.Setter;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicReferenceArray;
@Snippet("biome-palette") @Snippet("biome-palette")
@Accessors(chain = true) @Accessors(chain = true)
@@ -64,7 +65,8 @@ public class IrisBiomePaletteLayer {
new LazyBoundedCache<>(LAYER_GENERATOR_CACHE_SIZE); new LazyBoundedCache<>(LAYER_GENERATOR_CACHE_SIZE);
@Getter(AccessLevel.NONE) @Getter(AccessLevel.NONE)
@Setter(AccessLevel.NONE) @Setter(AccessLevel.NONE)
private final transient AtomicReference<CachedLayerGenerator> recentLayerGenerator = new AtomicReference<>(); private final transient AtomicReferenceArray<CachedLayerGenerator> recentLayerGenerators =
new AtomicReferenceArray<>(LAYER_GENERATOR_CACHE_SIZE);
@Getter(AccessLevel.NONE) @Getter(AccessLevel.NONE)
@Setter(AccessLevel.NONE) @Setter(AccessLevel.NONE)
private final transient LazyBoundedCache<LayerGeneratorKey, CNG> heightGenerators = private final transient LazyBoundedCache<LayerGeneratorKey, CNG> heightGenerators =
@@ -145,7 +147,8 @@ public class IrisBiomePaletteLayer {
public CNG getLayerGenerator(RNG parent, int signature, IrisData data) { public CNG getLayerGenerator(RNG parent, int signature, IrisData data) {
Engine engine = data == null ? null : data.getEngine(); Engine engine = data == null ? null : data.getEngine();
long generatorSeed = parent.getSeed() + signature + minHeight + maxHeight + getBlockData(data).size(); long generatorSeed = parent.getSeed() + signature + minHeight + maxHeight + getBlockData(data).size();
CachedLayerGenerator recent = recentLayerGenerator.get(); int slot = (int) generatorSeed & (LAYER_GENERATOR_CACHE_SIZE - 1);
CachedLayerGenerator recent = recentLayerGenerators.getAcquire(slot);
if (recent != null && recent.key.matches(data, engine, generatorSeed)) { if (recent != null && recent.key.matches(data, engine, generatorSeed)) {
return recent.generator; return recent.generator;
} }
@@ -154,7 +157,7 @@ public class IrisBiomePaletteLayer {
CNG generator = layerGenerators.computeIfAbsent(key, CNG generator = layerGenerators.computeIfAbsent(key,
ignored -> style.create(new RNG(generatorSeed), data, engine)); ignored -> style.create(new RNG(generatorSeed), data, engine));
if (generator != null) { if (generator != null) {
recentLayerGenerator.set(new CachedLayerGenerator(key, generator)); recentLayerGenerators.setRelease(slot, new CachedLayerGenerator(key, generator));
} }
return generator; return generator;
} }
@@ -18,20 +18,50 @@
package art.arcane.iris.generation.chunk; package art.arcane.iris.generation.chunk;
import art.arcane.volmlib.util.function.Consumer4;
import art.arcane.volmlib.util.hunk.Hunk; import art.arcane.volmlib.util.hunk.Hunk;
import art.arcane.volmlib.util.hunk.view.ListeningHunk;
public final class ColumnExtentListeningHunk<T> extends ListeningHunk<T> implements ColumnExtent { public final class ColumnExtentListeningHunk<T> implements Hunk<T>, ColumnExtent {
private final Hunk<T> source; private final Hunk<T> source;
private final Listener<T> listener;
public ColumnExtentListeningHunk(Hunk<T> source, Consumer4<Integer, Integer, Integer, T> listener) { public ColumnExtentListeningHunk(Hunk<T> source, Listener<T> listener) {
super(source, listener);
this.source = source; this.source = source;
this.listener = listener;
}
@Override
public void setRaw(int x, int y, int z, T t) {
listener.onWrite(x, y, z, t);
source.setRaw(x, y, z, t);
}
@Override
public T getRaw(int x, int y, int z) {
return source.getRaw(x, y, z);
}
@Override
public int getWidth() {
return source.getWidth();
}
@Override
public int getHeight() {
return source.getHeight();
}
@Override
public int getDepth() {
return source.getDepth();
} }
@Override @Override
public int highestStoredY(int x, int z) { public int highestStoredY(int x, int z) {
return ColumnExtent.highestStoredY(source, x, z); return ColumnExtent.highestStoredY(source, x, z);
} }
@FunctionalInterface
public interface Listener<T> {
void onWrite(int x, int y, int z, T value);
}
} }