Optimize world generation and add a config to set the number of generation threads
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package com.seibel.lod.builders;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
@@ -48,15 +49,20 @@ public class LodBufferBuilder
|
||||
* and are waiting to be swapped with the drawable buffers*/
|
||||
private volatile boolean switchBuffers = false;
|
||||
|
||||
/** If this is greater than 0 no new chunk generation requests will be made
|
||||
* this is to prevent chunks from being generated for a long time in an area
|
||||
/** This keeps track of how many chunk generation requests are on going.
|
||||
* This is to prevent chunks from being generated for a long time in an area
|
||||
* the player is no longer in. */
|
||||
public volatile int numberOfChunksWaitingToGenerate = 0;
|
||||
public volatile AtomicInteger numberOfChunksWaitingToGenerate = new AtomicInteger(0);
|
||||
|
||||
|
||||
|
||||
/** how many chunks to generate outside of the player's
|
||||
* view distance at one time. (or more specifically how
|
||||
* many requests to make at one time) */
|
||||
public int maxChunkGenRequests = Runtime.getRuntime().availableProcessors();
|
||||
* many requests to make at one time).
|
||||
* I multiply by 8 to make sure there is always a buffer of chunk requests,
|
||||
* to make sure the CPU is always busy and we can generate LODs as quickly as
|
||||
* possible. */
|
||||
public int maxChunkGenRequests = LodConfig.CLIENT.numberOfWorldGenerationThreads.get() * 8;
|
||||
|
||||
|
||||
public LodBufferBuilder(LodChunkBuilder newLodBuilder)
|
||||
@@ -95,8 +101,6 @@ public class LodBufferBuilder
|
||||
previousDimension = lodDim;
|
||||
}
|
||||
|
||||
|
||||
|
||||
generatingBuffers = true;
|
||||
|
||||
|
||||
@@ -111,7 +115,7 @@ public class LodBufferBuilder
|
||||
int startZ = (-LodChunk.WIDTH * (numbChunksWide / 2)) + playerZChunkOffset;
|
||||
|
||||
|
||||
Thread t = new Thread(()->
|
||||
Thread thread = new Thread(()->
|
||||
{
|
||||
// index of the chunk currently being added to the
|
||||
// generation list
|
||||
@@ -129,6 +133,8 @@ public class LodBufferBuilder
|
||||
buildableNearBuffer.begin(GL11.GL_QUADS, LodRenderer.LOD_VERTEX_FORMAT);
|
||||
buildableFarBuffer.begin(GL11.GL_QUADS, LodRenderer.LOD_VERTEX_FORMAT);
|
||||
|
||||
|
||||
|
||||
// x axis
|
||||
for (int i = 0; i < numbChunksWide; i++)
|
||||
{
|
||||
@@ -158,7 +164,7 @@ public class LodBufferBuilder
|
||||
{
|
||||
// generate a new chunk if no chunk currently exists
|
||||
// and we aren't waiting on any other chunks to generate
|
||||
if (lod == null && numberOfChunksWaitingToGenerate < maxChunkGenRequests)
|
||||
if (lod == null && numberOfChunksWaitingToGenerate.get() < maxChunkGenRequests)
|
||||
{
|
||||
ChunkPos pos = new ChunkPos(chunkX, chunkZ);
|
||||
|
||||
@@ -171,7 +177,41 @@ public class LodBufferBuilder
|
||||
// this chunk is closer, clear any previous
|
||||
// positions and update the new minimum distance
|
||||
minChunkDist = newDistance;
|
||||
chunksToGenReserve = chunksToGen;
|
||||
|
||||
|
||||
// move all the old chunks into the reserve
|
||||
ChunkPos[] newReserve = new ChunkPos[maxChunkGenRequests];
|
||||
int oldToGenIndex = 0;
|
||||
int oldReserveIndex = 0;
|
||||
for(int tmpIndex = 0; tmpIndex < newReserve.length; tmpIndex++)
|
||||
{
|
||||
// we don't check if the boundaries are good since
|
||||
// the tmp array will always be the same length
|
||||
// as chunksToGen and chunksToGenReserve
|
||||
|
||||
if (chunksToGen[oldToGenIndex] != null)
|
||||
{
|
||||
// add all the closest chunks...
|
||||
newReserve[tmpIndex] = chunksToGen[oldToGenIndex];
|
||||
oldToGenIndex++;
|
||||
}
|
||||
else if (chunksToGenReserve[oldReserveIndex] != null)
|
||||
{
|
||||
// ...then add all the previous reserve chunks
|
||||
// (which are farther away)
|
||||
newReserve[tmpIndex] = chunksToGenReserve[oldToGenIndex];
|
||||
oldReserveIndex++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// we have moved all the items from
|
||||
// the old chunksToGen and reserve
|
||||
break;
|
||||
}
|
||||
}
|
||||
chunksToGenReserve = newReserve;
|
||||
|
||||
|
||||
|
||||
chunkGenIndex = 0;
|
||||
chunksToGen = new ChunkPos[maxChunkGenRequests];
|
||||
@@ -231,7 +271,10 @@ public class LodBufferBuilder
|
||||
if(chunkPos == null)
|
||||
break;
|
||||
|
||||
numberOfChunksWaitingToGenerate++;
|
||||
// make sure we don't generate this chunk again
|
||||
lodDim.addLod(new LodChunk(chunkPos));
|
||||
|
||||
numberOfChunksWaitingToGenerate.addAndGet(1);
|
||||
|
||||
LodChunkGenWorker genWorker = new LodChunkGenWorker(chunkPos, renderer, lodChunkBuilder, this, lodDim, serverWorld, biomeContainer);
|
||||
WorldWorkerManager.addWorker(genWorker);
|
||||
@@ -247,7 +290,7 @@ public class LodBufferBuilder
|
||||
switchBuffers = true;
|
||||
});
|
||||
|
||||
genThread.execute(t);
|
||||
genThread.execute(thread);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ import net.minecraftforge.common.WorldWorkerManager.IWorker;
|
||||
*/
|
||||
public class LodChunkGenWorker implements IWorker
|
||||
{
|
||||
public static final ExecutorService genThreads = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
|
||||
public static final ExecutorService genThreads = Executors.newFixedThreadPool(LodConfig.CLIENT.numberOfWorldGenerationThreads.get());
|
||||
|
||||
private boolean threadStarted = false;
|
||||
private LodChunkGenThread thread;
|
||||
@@ -87,7 +87,7 @@ public class LodChunkGenWorker implements IWorker
|
||||
{
|
||||
if (!threadStarted)
|
||||
{
|
||||
thread.lodBufferBuilder.numberOfChunksWaitingToGenerate--;
|
||||
thread.lodBufferBuilder.numberOfChunksWaitingToGenerate.addAndGet(-1);
|
||||
|
||||
if (LodConfig.CLIENT.distanceGenerationMode.get() == DistanceGenerationMode.SERVER)
|
||||
{
|
||||
|
||||
@@ -46,10 +46,14 @@ public class LodConfig
|
||||
|
||||
public ForgeConfigSpec.BooleanValue allowUnstableFeatureGeneration;
|
||||
|
||||
public ForgeConfigSpec.IntValue numberOfWorldGenerationThreads;
|
||||
|
||||
/** this is multiplied by the default view distance
|
||||
* to determine how far out to generate/render LODs */
|
||||
public ForgeConfigSpec.IntValue lodChunkRadiusMultiplier;
|
||||
|
||||
|
||||
|
||||
Client(ForgeConfigSpec.Builder builder)
|
||||
{
|
||||
builder.comment(ModInfo.MODNAME + " configuration settings").push("client");
|
||||
@@ -176,6 +180,18 @@ public class LodConfig
|
||||
+ " https://gitlab.com/jeseibel/minecraft-lod-mod/-/issues/35 \n")
|
||||
.define("allowUnstableFeatureGeneration", false);
|
||||
|
||||
numberOfWorldGenerationThreads = builder
|
||||
.comment("\n\n"
|
||||
+ " This is how many threads are used when generating terrain. \n"
|
||||
+ " If you experience stuttering when generating terrain, decrease \n"
|
||||
+ " this number. If you want to increase LOD generation speed, \n"
|
||||
+ " increase the number. \n"
|
||||
+ " The max is the number of processors on your CPU. \n"
|
||||
+ "\n"
|
||||
+ " Requires a restart to take effect. \n"
|
||||
)
|
||||
.defineInRange("numberOfWorldGenerationThreads", Runtime.getRuntime().availableProcessors(), 1, Runtime.getRuntime().availableProcessors());
|
||||
|
||||
|
||||
builder.pop();
|
||||
}
|
||||
|
||||
@@ -93,15 +93,18 @@ public class ClientProxy
|
||||
}
|
||||
|
||||
|
||||
// TODO for testing
|
||||
// for testing
|
||||
// LodConfig.CLIENT.debugMode.set(false);
|
||||
|
||||
// LodConfig.CLIENT.lodDetail.set(LodDetail.DOUBLE);
|
||||
// LodConfig.CLIENT.lodColorStyle.set(LodColorStyle.INDIVIDUAL_SIDES);
|
||||
// LodConfig.CLIENT.lodChunkRadiusMultiplier.set(12);
|
||||
// LodConfig.CLIENT.distanceGenerationMode.set(DistanceGenerationMode.FEATURES);
|
||||
// LodConfig.CLIENT.fogDistance.set(FogDistance.FAR);
|
||||
// LodConfig.CLIENT.fogDrawOverride.set(FogDrawOverride.ALWAYS_DRAW_FOG_FANCY);
|
||||
|
||||
// LodConfig.CLIENT.distanceGenerationMode.set(DistanceGenerationMode.FEATURES);
|
||||
// LodConfig.CLIENT.allowUnstableFeatureGeneration.set(false);
|
||||
|
||||
|
||||
// Note to self:
|
||||
// if "unspecified" shows up in the pie chart, it is
|
||||
// possibly because the amount of time between sections
|
||||
@@ -147,7 +150,7 @@ public class ClientProxy
|
||||
|
||||
if(mc.getConnection().getLevel() == null)
|
||||
{
|
||||
lodBufferBuilder.numberOfChunksWaitingToGenerate = 0;
|
||||
lodBufferBuilder.numberOfChunksWaitingToGenerate.set(0);
|
||||
// the player has disconnected from a server
|
||||
lodWorld.deselectWorld();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user