mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-10-27 14:30:14 +00:00
Trim generation hot path allocations
- Replace the six per-voxel IrisPosition probes in MantleWriter neighborhood hollowing with an origin-relative primitive key set - Look mask membership up through the same primitive key set instead of allocating an IrisPosition per candidate voxel - Give the squared-distance helper a fixed arity so ballooning no longer depends on escape analysis to drop its varargs array - Resolve each Matter slice once per write instead of paying a hasSlice probe and a getSlice lookup for the same class - Read the river water surface through the primitive stream accessor instead of boxing a Double per column - Add nullable primary surface layer accessors so the terrain actuator stops building two Optionals per column - Add MantleWriterNeighborhoodTest, MantleWriterNeighborhoodBenchmarkTest and HydrologyColumnSampleAccessorTest
This commit is contained in:
1 parent
1be563bd28
commit
79af11c435
6 files changed
+580
-63
No files matched your search
@@ -22,6 +22,7 @@ import art.arcane.iris.engine.framework.Engine;
|
||||
import art.arcane.iris.engine.framework.EngineAssignedActuator;
|
||||
import art.arcane.iris.core.loader.IrisData;
|
||||
import art.arcane.iris.engine.IrisComplex;
|
||||
import art.arcane.iris.util.project.stream.ProceduralStream;
|
||||
import art.arcane.iris.engine.UpperDimensionContext;
|
||||
import art.arcane.iris.engine.hydrology.HydrologyColumnLayer;
|
||||
import art.arcane.iris.engine.hydrology.HydrologyColumnSample;
|
||||
@@ -84,6 +85,7 @@ public class IrisTerrainNormalActuator extends EngineAssignedActuator<PlatformBl
|
||||
IrisDimension dimension = getDimension();
|
||||
IrisData data = getData();
|
||||
IrisComplex complex = getComplex();
|
||||
ProceduralStream<Double> riverWaterSurfaceStream = complex.getRiverWaterSurfaceStream();
|
||||
RNG localRng = rng;
|
||||
boolean bedrockEnabled = dimension.isBedrock();
|
||||
boolean hideOres = dimension.isHideOresForHiddenOre();
|
||||
@@ -117,7 +119,7 @@ public class IrisTerrainNormalActuator extends EngineAssignedActuator<PlatformBl
|
||||
int he = Math.min(chunkHeight, context.getRoundedHeight(xf, zf));
|
||||
int surfaceFluidHeight = Math.min(
|
||||
chunkHeight,
|
||||
(int) Math.round(complex.getRiverWaterSurfaceStream().get(realX, realZ))
|
||||
(int) Math.round(riverWaterSurfaceStream.getDouble(realX, realZ))
|
||||
);
|
||||
int hf = Math.max(surfaceFluidHeight, he);
|
||||
if (hf < 0) {
|
||||
@@ -128,10 +130,10 @@ public class IrisTerrainNormalActuator extends EngineAssignedActuator<PlatformBl
|
||||
HydrologyColumnSample hydrology = complex.sampleHydrologyColumn(realX, realZ);
|
||||
HydrologyColumnLayer hydrologyFluid = hydrology == null
|
||||
? null
|
||||
: hydrology.primarySurfaceFluidLayer().orElse(null);
|
||||
: hydrology.primarySurfaceFluidLayerOrNull();
|
||||
HydrologyColumnLayer hydrologyTerrain = hydrology == null
|
||||
? null
|
||||
: hydrology.primarySurfaceLayer().orElse(null);
|
||||
: hydrology.primarySurfaceLayerOrNull();
|
||||
int cut = exposeCutStrata
|
||||
&& hydrologyTerrain != null
|
||||
&& hydrologyTerrain.terrainOwned()
|
||||
|
||||
@@ -92,10 +92,18 @@ public record HydrologyColumnSample(
|
||||
}
|
||||
|
||||
public Optional<HydrologyColumnLayer> primarySurfaceLayer() {
|
||||
return selectSurfaceLayer(false);
|
||||
return Optional.ofNullable(selectSurfaceLayer(false));
|
||||
}
|
||||
|
||||
public Optional<HydrologyColumnLayer> primarySurfaceFluidLayer() {
|
||||
return Optional.ofNullable(selectSurfaceLayer(true));
|
||||
}
|
||||
|
||||
public HydrologyColumnLayer primarySurfaceLayerOrNull() {
|
||||
return selectSurfaceLayer(false);
|
||||
}
|
||||
|
||||
public HydrologyColumnLayer primarySurfaceFluidLayerOrNull() {
|
||||
return selectSurfaceLayer(true);
|
||||
}
|
||||
|
||||
@@ -120,11 +128,10 @@ public record HydrologyColumnSample(
|
||||
}
|
||||
|
||||
public int terrainHeight() {
|
||||
Optional<HydrologyColumnLayer> layer = primarySurfaceLayer();
|
||||
if (layer.isEmpty()) {
|
||||
HydrologyColumnLayer primary = selectSurfaceLayer(false);
|
||||
if (primary == null) {
|
||||
return naturalHeight;
|
||||
}
|
||||
HydrologyColumnLayer primary = layer.get();
|
||||
if (primary.channel()) {
|
||||
return primary.bedY();
|
||||
}
|
||||
@@ -147,7 +154,7 @@ public record HydrologyColumnSample(
|
||||
return new HydrologyRenderSample(x, z, features);
|
||||
}
|
||||
|
||||
private Optional<HydrologyColumnLayer> selectSurfaceLayer(boolean fluidOnly) {
|
||||
private HydrologyColumnLayer selectSurfaceLayer(boolean fluidOnly) {
|
||||
HydrologyColumnLayer selected = null;
|
||||
for (HydrologyColumnLayer layer : layers) {
|
||||
if (layer.oceanApron() || !layer.feature().type().isSurface()) {
|
||||
@@ -164,7 +171,7 @@ public record HydrologyColumnSample(
|
||||
selected = layer;
|
||||
}
|
||||
}
|
||||
return Optional.ofNullable(selected);
|
||||
return selected;
|
||||
}
|
||||
|
||||
private static int surfaceRolePriority(HydrologyColumnLayer layer) {
|
||||
|
||||
@@ -23,6 +23,7 @@ import art.arcane.iris.spi.IrisLogging;
|
||||
import art.arcane.iris.util.project.matter.TileWrapper;
|
||||
import art.arcane.iris.util.project.matter.PreObjectMatterCell;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
|
||||
import art.arcane.iris.core.IrisSettings;
|
||||
import art.arcane.iris.core.link.Identifier;
|
||||
import art.arcane.iris.core.tools.WorldMaintenance;
|
||||
@@ -175,7 +176,7 @@ public class MantleWriter implements ObjectPassPlacer, AutoCloseable {
|
||||
}
|
||||
}
|
||||
|
||||
private static Set<IrisPosition> getBallooned(Set<IrisPosition> vset, double radius) {
|
||||
static Set<IrisPosition> getBallooned(Set<IrisPosition> vset, double radius) {
|
||||
Set<IrisPosition> returnset = new HashSet<>();
|
||||
int ceilrad = (int) Math.ceil(radius);
|
||||
double r2 = Math.pow(radius, 2);
|
||||
@@ -198,30 +199,83 @@ public class MantleWriter implements ObjectPassPlacer, AutoCloseable {
|
||||
return returnset;
|
||||
}
|
||||
|
||||
private static Set<IrisPosition> getHollowed(Set<IrisPosition> vset) {
|
||||
static Set<IrisPosition> getHollowed(Set<IrisPosition> vset) {
|
||||
PositionLookup lookup = PositionLookup.of(vset);
|
||||
Set<IrisPosition> returnset = new KSet<>();
|
||||
for (IrisPosition v : vset) {
|
||||
double x = v.getX();
|
||||
double y = v.getY();
|
||||
double z = v.getZ();
|
||||
if (!(vset.contains(new IrisPosition(x + 1, y, z))
|
||||
&& vset.contains(new IrisPosition(x - 1, y, z))
|
||||
&& vset.contains(new IrisPosition(x, y + 1, z))
|
||||
&& vset.contains(new IrisPosition(x, y - 1, z))
|
||||
&& vset.contains(new IrisPosition(x, y, z + 1))
|
||||
&& vset.contains(new IrisPosition(x, y, z - 1)))) {
|
||||
int x = v.getX();
|
||||
int y = v.getY();
|
||||
int z = v.getZ();
|
||||
if (!(lookup.contains(x + 1, y, z)
|
||||
&& lookup.contains(x - 1, y, z)
|
||||
&& lookup.contains(x, y + 1, z)
|
||||
&& lookup.contains(x, y - 1, z)
|
||||
&& lookup.contains(x, y, z + 1)
|
||||
&& lookup.contains(x, y, z - 1))) {
|
||||
returnset.add(v);
|
||||
}
|
||||
}
|
||||
return returnset;
|
||||
}
|
||||
|
||||
private static double hypot(double... pars) {
|
||||
double sum = 0;
|
||||
for (double d : pars) {
|
||||
sum += Math.pow(d, 2);
|
||||
private static double hypot(double x, double y, double z) {
|
||||
return Math.pow(x, 2) + Math.pow(y, 2) + Math.pow(z, 2);
|
||||
}
|
||||
|
||||
record PositionLookup(LongOpenHashSet keys, Set<IrisPosition> positions, int originX, int originY, int originZ) {
|
||||
private static final int AXIS_BITS = 21;
|
||||
private static final long AXIS_LIMIT = 1L << AXIS_BITS;
|
||||
|
||||
static PositionLookup of(Set<IrisPosition> positions) {
|
||||
if (positions.isEmpty()) {
|
||||
return new PositionLookup(new LongOpenHashSet(), positions, 0, 0, 0);
|
||||
}
|
||||
|
||||
int minX = Integer.MAX_VALUE;
|
||||
int minY = Integer.MAX_VALUE;
|
||||
int minZ = Integer.MAX_VALUE;
|
||||
int maxX = Integer.MIN_VALUE;
|
||||
int maxY = Integer.MIN_VALUE;
|
||||
int maxZ = Integer.MIN_VALUE;
|
||||
for (IrisPosition position : positions) {
|
||||
minX = Math.min(minX, position.getX());
|
||||
minY = Math.min(minY, position.getY());
|
||||
minZ = Math.min(minZ, position.getZ());
|
||||
maxX = Math.max(maxX, position.getX());
|
||||
maxY = Math.max(maxY, position.getY());
|
||||
maxZ = Math.max(maxZ, position.getZ());
|
||||
}
|
||||
|
||||
if ((long) maxX - minX >= AXIS_LIMIT - 2L
|
||||
|| (long) maxY - minY >= AXIS_LIMIT - 2L
|
||||
|| (long) maxZ - minZ >= AXIS_LIMIT - 2L) {
|
||||
return new PositionLookup(null, positions, 0, 0, 0);
|
||||
}
|
||||
|
||||
LongOpenHashSet keys = new LongOpenHashSet(positions.size());
|
||||
for (IrisPosition position : positions) {
|
||||
keys.add(key(position.getX() - minX, position.getY() - minY, position.getZ() - minZ));
|
||||
}
|
||||
return new PositionLookup(keys, positions, minX, minY, minZ);
|
||||
}
|
||||
|
||||
boolean contains(int x, int y, int z) {
|
||||
if (keys == null) {
|
||||
return positions.contains(new IrisPosition(x, y, z));
|
||||
}
|
||||
|
||||
long dx = (long) x - originX;
|
||||
long dy = (long) y - originY;
|
||||
long dz = (long) z - originZ;
|
||||
if ((dx | dy | dz) < 0L || dx >= AXIS_LIMIT || dy >= AXIS_LIMIT || dz >= AXIS_LIMIT) {
|
||||
return false;
|
||||
}
|
||||
return keys.contains(key(dx, dy, dz));
|
||||
}
|
||||
|
||||
private static long key(long x, long y, long z) {
|
||||
return (x << (AXIS_BITS * 2)) | (y << AXIS_BITS) | z;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
private static double lengthSq(double x, double y, double z) {
|
||||
@@ -294,9 +348,7 @@ public class MantleWriter implements ObjectPassPlacer, AutoCloseable {
|
||||
if (hasProtectedHydrology(matter, x, y, z)) {
|
||||
return false;
|
||||
}
|
||||
MatterSlice<MatterCavern> cavernSlice = matter.hasSlice(MatterCavern.class)
|
||||
? matter.getSlice(MatterCavern.class)
|
||||
: null;
|
||||
MatterSlice<MatterCavern> cavernSlice = matter.getSlice(MatterCavern.class);
|
||||
MatterCavern existing = cavernSlice == null
|
||||
? null
|
||||
: cavernSlice.get(x & 15, y & 15, z & 15);
|
||||
@@ -328,15 +380,13 @@ public class MantleWriter implements ObjectPassPlacer, AutoCloseable {
|
||||
if (hasProtectedHydrology(matter, x, y, z)) {
|
||||
return false;
|
||||
}
|
||||
if (matter.hasSlice(PlatformBlockState.class)) {
|
||||
MatterSlice<PlatformBlockState> blockSlice = matter.getSlice(PlatformBlockState.class);
|
||||
if (blockSlice != null) {
|
||||
capturePreObjectOriginal(matter, x, y, z, PlatformBlockState.class);
|
||||
matter.<PlatformBlockState>getSlice(PlatformBlockState.class)
|
||||
.set(x & 15, y & 15, z & 15, null);
|
||||
blockSlice.set(x & 15, y & 15, z & 15, null);
|
||||
}
|
||||
clearDeferredPlacement(matter, x, y, z);
|
||||
MatterSlice<MatterCavern> cavernSlice = matter.hasSlice(MatterCavern.class)
|
||||
? matter.getSlice(MatterCavern.class)
|
||||
: null;
|
||||
MatterSlice<MatterCavern> cavernSlice = matter.getSlice(MatterCavern.class);
|
||||
if (cavernSlice != null && cavernSlice.get(x & 15, y & 15, z & 15) != null) {
|
||||
return false;
|
||||
}
|
||||
@@ -363,10 +413,10 @@ public class MantleWriter implements ObjectPassPlacer, AutoCloseable {
|
||||
if (hasProtectedHydrology(matter, x, y, z)) {
|
||||
return;
|
||||
}
|
||||
if (matter.hasSlice(PlatformBlockState.class)) {
|
||||
MatterSlice<PlatformBlockState> blockSlice = matter.getSlice(PlatformBlockState.class);
|
||||
if (blockSlice != null) {
|
||||
capturePreObjectOriginal(matter, x, y, z, PlatformBlockState.class);
|
||||
matter.<PlatformBlockState>getSlice(PlatformBlockState.class)
|
||||
.set(x & 15, y & 15, z & 15, null);
|
||||
blockSlice.set(x & 15, y & 15, z & 15, null);
|
||||
}
|
||||
clearDeferredPlacement(matter, x, y, z);
|
||||
capturePreObjectOriginal(matter, x, y, z, MatterCavern.class);
|
||||
@@ -394,10 +444,10 @@ public class MantleWriter implements ObjectPassPlacer, AutoCloseable {
|
||||
if (hasProtectedHydrology(matter, x, y, z)) {
|
||||
return;
|
||||
}
|
||||
if (matter.hasSlice(PlatformBlockState.class)) {
|
||||
MatterSlice<PlatformBlockState> blockSlice = matter.getSlice(PlatformBlockState.class);
|
||||
if (blockSlice != null) {
|
||||
capturePreObjectOriginal(matter, x, y, z, PlatformBlockState.class);
|
||||
matter.<PlatformBlockState>getSlice(PlatformBlockState.class)
|
||||
.set(x & 15, y & 15, z & 15, null);
|
||||
blockSlice.set(x & 15, y & 15, z & 15, null);
|
||||
}
|
||||
clearDeferredPlacement(matter, x, y, z);
|
||||
}
|
||||
@@ -651,17 +701,18 @@ public class MantleWriter implements ObjectPassPlacer, AutoCloseable {
|
||||
}
|
||||
|
||||
private static boolean hasProtectedHydrology(Matter matter, int x, int y, int z) {
|
||||
if (!matter.hasSlice(HydrologyCaveCell.class)) {
|
||||
MatterSlice<HydrologyCaveCell> slice = matter.getSlice(HydrologyCaveCell.class);
|
||||
if (slice == null) {
|
||||
return false;
|
||||
}
|
||||
HydrologyCaveCell hydrology = matter.<HydrologyCaveCell>getSlice(HydrologyCaveCell.class)
|
||||
.get(x & 15, y & 15, z & 15);
|
||||
HydrologyCaveCell hydrology = slice.get(x & 15, y & 15, z & 15);
|
||||
return hydrology != null && hydrology.protectsPlacement();
|
||||
}
|
||||
|
||||
private static void clearDeferredPlacement(Matter matter, int x, int y, int z) {
|
||||
if (matter.hasSlice(Identifier.class)) {
|
||||
matter.<Identifier>getSlice(Identifier.class).set(x & 15, y & 15, z & 15, null);
|
||||
MatterSlice<Identifier> slice = matter.getSlice(Identifier.class);
|
||||
if (slice != null) {
|
||||
slice.set(x & 15, y & 15, z & 15, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -728,11 +779,11 @@ public class MantleWriter implements ObjectPassPlacer, AutoCloseable {
|
||||
}
|
||||
|
||||
private static PreObjectMatterCell preObjectCell(Matter matter, int x, int y, int z) {
|
||||
if (matter == null || !matter.hasSlice(PreObjectMatterCell.class)) {
|
||||
if (matter == null) {
|
||||
return null;
|
||||
}
|
||||
return matter.<PreObjectMatterCell>getSlice(PreObjectMatterCell.class)
|
||||
.get(x & 15, y & 15, z & 15);
|
||||
MatterSlice<PreObjectMatterCell> slice = matter.getSlice(PreObjectMatterCell.class);
|
||||
return slice == null ? null : slice.get(x & 15, y & 15, z & 15);
|
||||
}
|
||||
|
||||
private static <T> T prerequisiteValue(Matter matter, int x, int y, int z, Class<T> type) {
|
||||
@@ -740,17 +791,13 @@ public class MantleWriter implements ObjectPassPlacer, AutoCloseable {
|
||||
if (cell != null && cell.captures(type)) {
|
||||
return cell.original(type);
|
||||
}
|
||||
if (!matter.hasSlice(type)) {
|
||||
return null;
|
||||
}
|
||||
return matter.<T>getSlice(type).get(x & 15, y & 15, z & 15);
|
||||
MatterSlice<T> slice = matter.getSlice(type);
|
||||
return slice == null ? null : slice.get(x & 15, y & 15, z & 15);
|
||||
}
|
||||
|
||||
private static Object rawValue(Matter matter, int x, int y, int z, Class<?> type) {
|
||||
if (!matter.hasSlice(type)) {
|
||||
return null;
|
||||
}
|
||||
return matter.getSlice(type).get(x, y, z);
|
||||
MatterSlice<?> slice = matter.getSlice(type);
|
||||
return slice == null ? null : slice.get(x, y, z);
|
||||
}
|
||||
|
||||
private boolean allowsWrite(int blockX, int blockZ) {
|
||||
@@ -762,10 +809,10 @@ public class MantleWriter implements ObjectPassPlacer, AutoCloseable {
|
||||
private static void restoreRaw(Matter matter, int x, int y, int z, Class<?> type, Object value) {
|
||||
MatterSlice<Object> slice;
|
||||
if (value == null) {
|
||||
if (!matter.hasSlice(type)) {
|
||||
slice = (MatterSlice<Object>) matter.getSlice(type);
|
||||
if (slice == null) {
|
||||
return;
|
||||
}
|
||||
slice = (MatterSlice<Object>) matter.getSlice(type);
|
||||
} else {
|
||||
slice = (MatterSlice<Object>) matter.slice(type);
|
||||
}
|
||||
@@ -951,9 +998,7 @@ public class MantleWriter implements ObjectPassPlacer, AutoCloseable {
|
||||
continue;
|
||||
}
|
||||
|
||||
MatterSlice<MatterCavern> cavernSlice = matter.hasSlice(MatterCavern.class)
|
||||
? matter.getSlice(MatterCavern.class)
|
||||
: null;
|
||||
MatterSlice<MatterCavern> cavernSlice = matter.getSlice(MatterCavern.class);
|
||||
MatterSlice<HydrologyCaveCell> hydrologySlice = matter.hasSlice(HydrologyCaveCell.class)
|
||||
? matter.getSlice(HydrologyCaveCell.class)
|
||||
: null;
|
||||
@@ -1277,10 +1322,11 @@ public class MantleWriter implements ObjectPassPlacer, AutoCloseable {
|
||||
setConsumer(vset, data);
|
||||
}
|
||||
|
||||
private static Set<IrisPosition> getMasked(Set<IrisPosition> vectors, Set<IrisPosition> masks, double radius) {
|
||||
static Set<IrisPosition> getMasked(Set<IrisPosition> vectors, Set<IrisPosition> masks, double radius) {
|
||||
Set<IrisPosition> vset = new KSet<>();
|
||||
int ceil = (int) Math.ceil(radius);
|
||||
double r2 = Math.pow(radius, 2);
|
||||
PositionLookup maskLookup = PositionLookup.of(masks);
|
||||
|
||||
for (IrisPosition v : vectors) {
|
||||
int tipX = v.getX();
|
||||
@@ -1290,7 +1336,7 @@ public class MantleWriter implements ObjectPassPlacer, AutoCloseable {
|
||||
for (int x = -ceil; x <= ceil; x++) {
|
||||
for (int y = -ceil; y <= ceil; y++) {
|
||||
for (int z = -ceil; z <= ceil; z++) {
|
||||
if (hypot(x, y, z) > r2 || !masks.contains(new IrisPosition(x, y, z)))
|
||||
if (hypot(x, y, z) > r2 || !maskLookup.contains(x, y, z))
|
||||
continue;
|
||||
vset.add(new IrisPosition(tipX + x, tipY + y, tipZ + z));
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user