Fix critical mem leak in BlockDetail + Add spaced out worldGenThread + make worldGenUpdate update once per 10 ticks + Semi-impl proper EarthCurveRatio limits + make worldGenThreads terminate faster + impl temp bypass to stop deadlocks on BufferFactory destroy() + fix chat logging messages with Throwable twice
This commit is contained in:
@@ -292,7 +292,7 @@ public class Config
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _earthCurveRatio = IAdvancedGraphics.EARTH_CURVE_RATIO_DESC;
|
||||
@ConfigAnnotations.Entry(minValue = 0, maxValue = 10000)
|
||||
@ConfigAnnotations.Entry(minValue = 0, maxValue = 5000)
|
||||
public static int earthCurveRatio = IAdvancedGraphics.EARTH_CURVE_RATIO_MIN_DEFAULT_MAX.defaultValue;
|
||||
|
||||
/*
|
||||
@@ -378,8 +378,8 @@ public class Config
|
||||
{
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _numberOfWorldGenerationThreads = IThreading.NUMBER_OF_WORLD_GENERATION_THREADS_DESC;
|
||||
@ConfigAnnotations.Entry(minValue = 1, maxValue = 50)
|
||||
public static int numberOfWorldGenerationThreads = IThreading.NUMBER_OF_WORLD_GENERATION_THREADS_DEFAULT.defaultValue;
|
||||
@ConfigAnnotations.Entry(minValue = 0.1, maxValue = 50.0)
|
||||
public static double numberOfWorldGenerationThreads = IThreading.NUMBER_OF_WORLD_GENERATION_THREADS_DEFAULT.defaultValue;
|
||||
|
||||
@ConfigAnnotations.FileComment
|
||||
public static String _numberOfBufferBuilderThreads = IThreading.NUMBER_OF_BUFFER_BUILDER_THREADS_DESC;
|
||||
|
||||
@@ -69,6 +69,8 @@ import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/*-- WARN: This class should NEVER hold reference to anything large,
|
||||
as this is never dealloc until the end of runtime!! --*/
|
||||
public class BlockDetailWrapper extends IBlockDetailWrapper
|
||||
{
|
||||
private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
|
||||
@@ -158,10 +160,6 @@ public class BlockDetailWrapper extends IBlockDetailWrapper
|
||||
return tempColor;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private static final Block[] BLOCK_TO_AVOID = {Blocks.AIR, Blocks.CAVE_AIR, Blocks.BARRIER};
|
||||
|
||||
private static final Direction[] DIRECTION_ORDER = {Direction.UP, Direction.NORTH, Direction.EAST, Direction.WEST, Direction.SOUTH, Direction.DOWN};
|
||||
@@ -173,10 +171,11 @@ public class BlockDetailWrapper extends IBlockDetailWrapper
|
||||
}
|
||||
|
||||
final BlockState state;
|
||||
final BlockPos samplePos;
|
||||
final LevelReader sampleGetter;
|
||||
|
||||
boolean isShapeResolved = false;
|
||||
//boolean isShapeResolved = false;
|
||||
//^ Shapes no longer lazy resolved due to memory leaks from needing
|
||||
// to keep a reference to the block getter
|
||||
|
||||
boolean[] dontOccludeFaces = null;
|
||||
boolean noCollision = false;
|
||||
boolean noFullFace = false;
|
||||
@@ -191,15 +190,12 @@ public class BlockDetailWrapper extends IBlockDetailWrapper
|
||||
|
||||
public BlockDetailWrapper(BlockState state, BlockPos pos, LevelReader getter) {
|
||||
this.state = state;
|
||||
this.samplePos = pos;
|
||||
this.sampleGetter = getter;
|
||||
resolveShapes(getter, pos);
|
||||
//ApiShared.LOGGER.info("Created BlockDetailWrapper for blockstate {} at {}", state, pos);
|
||||
}
|
||||
|
||||
private BlockDetailWrapper() {
|
||||
this.state = null;
|
||||
this.samplePos = null;
|
||||
this.sampleGetter = null;
|
||||
}
|
||||
|
||||
static BlockDetailWrapper make(BlockState bs, BlockPos pos, LevelReader getter) {
|
||||
@@ -214,8 +210,8 @@ public class BlockDetailWrapper extends IBlockDetailWrapper
|
||||
}
|
||||
}
|
||||
|
||||
private void resolveShapes() {
|
||||
if (isShapeResolved) return;
|
||||
private void resolveShapes(LevelReader sampleGetter, BlockPos samplePos) {
|
||||
//if (isShapeResolved) return;
|
||||
if (state.getFluidState().isEmpty()) {
|
||||
noCollision = state.getCollisionShape(sampleGetter, samplePos).isEmpty();
|
||||
dontOccludeFaces = new boolean[6];
|
||||
@@ -242,7 +238,6 @@ public class BlockDetailWrapper extends IBlockDetailWrapper
|
||||
} else { // Liquid Block
|
||||
dontOccludeFaces = new boolean[6];
|
||||
}
|
||||
isShapeResolved = true;
|
||||
}
|
||||
|
||||
private void resolveColors() {
|
||||
@@ -261,7 +256,6 @@ public class BlockDetailWrapper extends IBlockDetailWrapper
|
||||
quads = Minecraft.getInstance().getModelManager().getBlockModelShaper().
|
||||
getBlockModel(state).getQuads(state, null, random);
|
||||
}
|
||||
|
||||
if (quads != null && !quads.isEmpty()) {
|
||||
needPostTinting = quads.get(0).isTinted();
|
||||
needShade = quads.get(0).isShade();
|
||||
@@ -278,13 +272,11 @@ public class BlockDetailWrapper extends IBlockDetailWrapper
|
||||
ColorMode.getColorMode(state.getBlock()));
|
||||
}
|
||||
} else { // Liquid Block
|
||||
|
||||
needPostTinting = true;
|
||||
needShade = false;
|
||||
tintIndex = 0;
|
||||
baseColor = calculateColorFromTexture(Minecraft.getInstance().getModelManager().getBlockModelShaper().getParticleIcon(state),
|
||||
ColorMode.getColorMode(state.getBlock()));
|
||||
|
||||
}
|
||||
isColorResolved = true;
|
||||
}
|
||||
@@ -314,21 +306,21 @@ public class BlockDetailWrapper extends IBlockDetailWrapper
|
||||
@Override
|
||||
public boolean hasFaceCullingFor(LodDirection dir)
|
||||
{
|
||||
resolveShapes();
|
||||
//resolveShapes();
|
||||
return !dontOccludeFaces[dir.ordinal()];
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNoCollision()
|
||||
{
|
||||
resolveShapes();
|
||||
//resolveShapes();
|
||||
return noCollision;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean noFaceIsFullFace()
|
||||
{
|
||||
resolveShapes();
|
||||
//resolveShapes();
|
||||
return noFullFace;
|
||||
}
|
||||
|
||||
|
||||
+4
-3
@@ -546,11 +546,12 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
|
||||
@Override
|
||||
public int getEarthCurveRatio()
|
||||
{
|
||||
return Config.Client.Graphics.AdvancedGraphics.earthCurveRatio;
|
||||
return (int) ConfigGui.editSingleOption.getEntry("client.graphics.advancedGraphics.earthCurveRatio").value;
|
||||
}
|
||||
@Override
|
||||
public void setEarthCurveRatio(int newEarthCurveRatio)
|
||||
{
|
||||
if (newEarthCurveRatio < 50) newEarthCurveRatio = 0;
|
||||
ConfigGui.editSingleOption.getEntry("client.graphics.advancedGraphics.earthCurveRatio").value = newEarthCurveRatio;
|
||||
ConfigGui.editSingleOption.saveOption("client.graphics.advancedGraphics.earthCurveRatio");
|
||||
}
|
||||
@@ -715,12 +716,12 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
|
||||
public static class Threading implements IThreading
|
||||
{
|
||||
@Override
|
||||
public int getNumberOfWorldGenerationThreads()
|
||||
public double getNumberOfWorldGenerationThreads()
|
||||
{
|
||||
return Config.Client.Advanced.Threading.numberOfWorldGenerationThreads;
|
||||
}
|
||||
@Override
|
||||
public void setNumberOfWorldGenerationThreads(int newNumberOfWorldGenerationThreads)
|
||||
public void setNumberOfWorldGenerationThreads(double newNumberOfWorldGenerationThreads)
|
||||
{
|
||||
ConfigGui.editSingleOption.getEntry("client.advanced.threading.numberOfWorldGenerationThreads").value = newNumberOfWorldGenerationThreads;
|
||||
ConfigGui.editSingleOption.saveOption("client.advanced.threading.numberOfWorldGenerationThreads");
|
||||
|
||||
+3
-3
@@ -256,7 +256,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
}
|
||||
|
||||
public ExecutorService executors = Executors.newFixedThreadPool(
|
||||
CONFIG.client().advanced().threading().getNumberOfWorldGenerationThreads(), threadFactory);
|
||||
CONFIG.client().advanced().threading()._getWorldGenerationThreadPoolSize(), threadFactory);
|
||||
|
||||
public <T> T joinSync(CompletableFuture<T> f) {
|
||||
if (!unsafeThreadingRecorded && !f.isDone()) {
|
||||
@@ -273,7 +273,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
new LodThreadFactory("Gen-Worker-Thread", Thread.MIN_PRIORITY));
|
||||
}
|
||||
|
||||
public boolean tryAddPoint(int px, int pz, int range, Steps target, boolean genAllDetails)
|
||||
public boolean tryAddPoint(int px, int pz, int range, Steps target, boolean genAllDetails, double runTimeRatio)
|
||||
{
|
||||
int boxSize = range * 2 + 1;
|
||||
int x = Math.floorDiv(px, boxSize) * boxSize + range;
|
||||
@@ -285,7 +285,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
|
||||
return false;
|
||||
}
|
||||
// System.out.println(x + ", "+z);
|
||||
events.add(new GenerationEvent(new ChunkPos(x, z), range, this, target, genAllDetails));
|
||||
events.add(new GenerationEvent(new ChunkPos(x, z), range, this, target, genAllDetails, runTimeRatio));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+18
-5
@@ -43,16 +43,19 @@ public final class GenerationEvent
|
||||
final ChunkPos pos;
|
||||
final int range;
|
||||
final Future<?> future;
|
||||
long nanotime;
|
||||
long creationNanotime;
|
||||
final int id;
|
||||
final Steps target;
|
||||
final LightGenerationMode lightMode;
|
||||
final PrefEvent pEvent = new PrefEvent();
|
||||
final boolean genAllDetails;
|
||||
|
||||
final double runTimeRatio;
|
||||
|
||||
public GenerationEvent(ChunkPos pos, int range, BatchGenerationEnvironment generationGroup, Steps target, boolean genAllDetails)
|
||||
public GenerationEvent(ChunkPos pos, int range, BatchGenerationEnvironment generationGroup,
|
||||
Steps target, boolean genAllDetails, double runTimeRatio)
|
||||
{
|
||||
nanotime = System.nanoTime();
|
||||
creationNanotime = System.nanoTime();
|
||||
this.pos = pos;
|
||||
this.range = range;
|
||||
id = generationFutureDebugIDs++;
|
||||
@@ -62,14 +65,24 @@ public final class GenerationEvent
|
||||
|
||||
this.lightMode = mode;
|
||||
this.genAllDetails = genAllDetails;
|
||||
this.runTimeRatio = runTimeRatio;
|
||||
|
||||
future = generationGroup.executors.submit(() ->
|
||||
{
|
||||
long startTime = System.nanoTime();
|
||||
BatchGenerationEnvironment.isDistantGeneratorThread.set(true);
|
||||
try {
|
||||
generationGroup.generateLodFromList(this);
|
||||
} finally {
|
||||
BatchGenerationEnvironment.isDistantGeneratorThread.remove();
|
||||
if (!Thread.interrupted() && runTimeRatio < 1.0) {
|
||||
long endTime = System.nanoTime();
|
||||
try {
|
||||
long deltaMs = TimeUnit.NANOSECONDS.toMillis(endTime - startTime);
|
||||
Thread.sleep((long) (deltaMs/runTimeRatio - deltaMs));
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -82,7 +95,7 @@ public final class GenerationEvent
|
||||
public boolean hasTimeout(int duration, TimeUnit unit)
|
||||
{
|
||||
long currentTime = System.nanoTime();
|
||||
long delta = currentTime - nanotime;
|
||||
long delta = currentTime - creationNanotime;
|
||||
return (delta > TimeUnit.NANOSECONDS.convert(duration, unit));
|
||||
}
|
||||
|
||||
@@ -117,7 +130,7 @@ public final class GenerationEvent
|
||||
|
||||
public void refreshTimeout()
|
||||
{
|
||||
nanotime = System.nanoTime();
|
||||
creationNanotime = System.nanoTime();
|
||||
LodUtil.checkInterruptsUnchecked();
|
||||
}
|
||||
|
||||
|
||||
+2
@@ -28,6 +28,7 @@ import com.google.common.collect.Sets;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||
import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
|
||||
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
import net.minecraft.server.level.WorldGenRegion;
|
||||
import net.minecraft.util.Mth;
|
||||
#if POST_MC_1_17_1
|
||||
@@ -82,6 +83,7 @@ public final class StepNoise {
|
||||
chunk = environment.joinSync(environment.params.generator.fillFromNoise(Runnable::run, Blender.of(worldGenRegion),
|
||||
tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk));
|
||||
#endif
|
||||
LodUtil.checkInterruptsUnchecked(); // Speed up termination responsiveness
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
Submodule core updated: d2fef22719...a3022d2c64
Reference in New Issue
Block a user