auto-format

This commit is contained in:
James Seibel
2021-09-30 19:24:30 -05:00
parent c13abc3b7d
commit b1995445e2
@@ -18,19 +18,21 @@
package com.seibel.lod.builders.bufferBuilding;
import java.nio.ByteBuffer;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.locks.ReentrantLock;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.seibel.lod.util.*;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL15C;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.seibel.lod.builders.bufferBuilding.lodTemplates.Box;
import com.seibel.lod.config.LodConfig;
import com.seibel.lod.objects.LodDimension;
@@ -41,6 +43,12 @@ import com.seibel.lod.proxy.ClientProxy;
import com.seibel.lod.proxy.GlProxy;
import com.seibel.lod.proxy.GlProxy.GlProxyContext;
import com.seibel.lod.render.LodRenderer;
import com.seibel.lod.util.DataPointUtil;
import com.seibel.lod.util.DetailDistanceUtil;
import com.seibel.lod.util.LevelPosUtil;
import com.seibel.lod.util.LodThreadFactory;
import com.seibel.lod.util.LodUtil;
import com.seibel.lod.util.ThreadMapUtil;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.vertex.VertexBuffer;
@@ -64,87 +72,87 @@ public class LodBufferBuilder
* This holds the threads used to generate buffers.
*/
public static ExecutorService bufferBuilderThreads = Executors.newFixedThreadPool(LodConfig.CLIENT.threading.numberOfBufferBuilderThreads.get(), new ThreadFactoryBuilder().setNameFormat("Buffer-Builder-%d").build());
/**
* This boolean matrix indicate the buffer builder in that position has to be regenerated
*/
public volatile boolean[][] regenPos;
/**
* This boolean indicate that all buffer need to be regenerated
*/
public volatile boolean fullRegeneration = false;
/**
* max capacity of buffers
*/
//public volatile int BUFFER_MAX_CAPACITY = 1 << (26);
public volatile int BUFFER_MAX_CAPACITY = (int) (64 * Math.pow(10, 6));
/**
* buffer builder for the vertex
*/
public volatile int[][] bufferSize;
/**
* buffer builder for the vertex
*/
public volatile BufferBuilder[][][] buildableBuffers;
/**
* Used when building new VBOs
*/
public volatile VertexBuffer[][][] buildableVbos;
/**
* VBOs that are sent over to the LodNodeRenderer
*/
public volatile VertexBuffer[][][] drawableVbos;
/**
* if this is true the LOD buffers are currently being
* regenerated.
*/
public boolean generatingBuffers = false;
/**
* if this is true new LOD buffers have been generated
* and are waiting to be swapped with the drawable buffers
*/
private boolean switchVbos = false;
/**
* Size of the buffer builders in bytes last time we created them
*/
public int previousBufferSize = 0;
/**
* Width of the dimension in regions last time we created the buffers
*/
public int previousRegionWidth = 0;
/**
* this is used to prevent multiple threads creating, destroying, or using the buffers at the same time
*/
private ReentrantLock bufferLock = new ReentrantLock();
private volatile Box[][] boxCache;
private volatile PosToRenderContainer[][] setsToRender;
private volatile RegionPos center;
/**
* This is the ChunkPos the player was at the last time the buffers were built.
* IE the center of the buffers last time they were built
*/
private volatile ChunkPos drawableCenterChunkPos = new ChunkPos(0, 0);
private volatile ChunkPos buildableCenterChunkPos = new ChunkPos(0, 0);
public LodBufferBuilder()
{
}
/**
* Create a thread to asynchronously generate LOD buffers
* centered around the given camera X and Z.
@@ -155,60 +163,60 @@ public class LodBufferBuilder
* swapped with the drawable buffers in the LodRenderer to be drawn.
*/
public void generateLodBuffersAsync(LodRenderer renderer, LodDimension lodDim,
BlockPos playerBlockPos, boolean fullRegen)
BlockPos playerBlockPos, boolean fullRegen)
{
// only allow one generation process to happen at a time
if (generatingBuffers)
return;
if (buildableBuffers == null)
// setupBuffers hasn't been called yet
return;
generatingBuffers = true;
// round the player's block position down to the nearest chunk BlockPos
ChunkPos playerChunkPos = new ChunkPos(playerBlockPos);
BlockPos playerBlockPosRounded = playerChunkPos.getWorldPosition();
Thread thread = new Thread(() ->
{
bufferLock.lock();
try
{
long startTime = System.currentTimeMillis();
ArrayList<Callable<Boolean>> nodeToRenderThreads = new ArrayList<>(lodDim.getWidth() * lodDim.getWidth());
startBuffers(fullRegen, lodDim);
RegionPos playerRegionPos = new RegionPos(playerChunkPos);
if (center == null)
center = playerRegionPos;
if (setsToRender == null)
setsToRender = new PosToRenderContainer[lodDim.getWidth()][lodDim.getWidth()];
if (setsToRender.length != lodDim.getWidth())
setsToRender = new PosToRenderContainer[lodDim.getWidth()][lodDim.getWidth()];
if (boxCache == null)
boxCache = new Box[lodDim.getWidth()][lodDim.getWidth()];
if (boxCache.length != lodDim.getWidth())
boxCache = new Box[lodDim.getWidth()][lodDim.getWidth()];
// this will be the center of the VBOs once they have been built
buildableCenterChunkPos = playerChunkPos;
//================================//
// create the nodeToRenderThreads //
//================================//
for (int xRegion = 0; xRegion < lodDim.getWidth(); xRegion++)
{
for (int zRegion = 0; zRegion < lodDim.getWidth(); zRegion++)
@@ -218,25 +226,25 @@ public class LodBufferBuilder
RegionPos regionPos = new RegionPos(
xRegion + lodDim.getCenterRegionPosX() - Math.floorDiv(lodDim.getWidth(), 2),
zRegion + lodDim.getCenterRegionPosZ() - Math.floorDiv(lodDim.getWidth(), 2));
// local position in the vbo and bufferBuilder arrays
BufferBuilder[] currentBuffers = buildableBuffers[xRegion][zRegion];
LodRegion region = lodDim.getRegion(regionPos.x, regionPos.z);
if (region == null)
continue;
// make sure the buffers weren't
// changed while we were running this method
if (currentBuffers == null || !currentBuffers[0].building())
return;
byte minDetail = region.getMinDetailLevel();
final int xR = xRegion;
final int zR = zRegion;
//we create the Callable to use for the buffer builder creation
Callable<Boolean> dataToRenderThread = () ->
{
@@ -251,55 +259,55 @@ public class LodBufferBuilder
int bufferIndex;
Box box = ThreadMapUtil.getBox();
boolean[] adjShadeDisabled = ThreadMapUtil.getAdjShadeDisabledArray();
// determine how many LODs we can stack vertically
int maxVerticalData = DetailDistanceUtil.getMaxVerticalData((byte) 0);
//we get or create the map that will contain the adj data
Map<Direction, long[]> adjData = ThreadMapUtil.getAdjDataArray(maxVerticalData);
//previous setToRender cache
if (setsToRender[xR][zR] == null)
setsToRender[xR][zR] = new PosToRenderContainer(minDetail, regionPos.x, regionPos.z);
PosToRenderContainer posToRender = setsToRender[xR][zR];
posToRender.clear(minDetail, regionPos.x, regionPos.z);
lodDim.getDataToRender(
posToRender,
regionPos,
playerBlockPosRounded.getX(),
playerBlockPosRounded.getZ());
// keep a local version so we don't have to worry about indexOutOfBounds Exceptions
// if it changes in the LodRenderer while we are working here
boolean[][] vanillaRenderedChunks = renderer.vanillaRenderedChunks;
short gameChunkRenderDistance = (short) (vanillaRenderedChunks.length / 2 - 1);
boolean smallRenderDistance = gameChunkRenderDistance <= 4;
for (int index = 0; index < posToRender.getNumberOfPos(); index++)
{
bufferIndex = Math.floorMod(index, currentBuffers.length);
detailLevel = posToRender.getNthDetailLevel(index);
posX = posToRender.getNthPosX(index);
posZ = posToRender.getNthPosZ(index);
// skip any chunks that Minecraft is going to render
chunkXdist = LevelPosUtil.getChunkPos(detailLevel, posX) - playerChunkPos.x;
chunkZdist = LevelPosUtil.getChunkPos(detailLevel, posZ) - playerChunkPos.z;
boolean isItBorderPos = LodUtil.isBorderChunk(vanillaRenderedChunks, chunkXdist + gameChunkRenderDistance + 1, chunkZdist + gameChunkRenderDistance + 1);
if (gameChunkRenderDistance >= Math.abs(chunkXdist)
&& gameChunkRenderDistance >= Math.abs(chunkZdist)
&& detailLevel <= LodUtil.CHUNK_DETAIL_LEVEL
&& vanillaRenderedChunks[chunkXdist + gameChunkRenderDistance + 1][chunkZdist + gameChunkRenderDistance + 1]
&& (!isItBorderPos || smallRenderDistance))
&& gameChunkRenderDistance >= Math.abs(chunkZdist)
&& detailLevel <= LodUtil.CHUNK_DETAIL_LEVEL
&& vanillaRenderedChunks[chunkXdist + gameChunkRenderDistance + 1][chunkZdist + gameChunkRenderDistance + 1]
&& (!isItBorderPos || smallRenderDistance))
{
continue;
}
@@ -312,54 +320,55 @@ public class LodBufferBuilder
chunkXdist = LevelPosUtil.getChunkPos(detailLevel, xAdj) - playerChunkPos.x;
chunkZdist = LevelPosUtil.getChunkPos(detailLevel, zAdj) - playerChunkPos.z;
if (posToRender.contains(detailLevel, xAdj, zAdj)
&& (gameChunkRenderDistance < Math.abs(chunkXdist)
|| gameChunkRenderDistance < Math.abs(chunkZdist)
|| !(vanillaRenderedChunks[chunkXdist + gameChunkRenderDistance + 1][chunkZdist + gameChunkRenderDistance + 1]
&& (!LodUtil.isBorderChunk(vanillaRenderedChunks, chunkXdist + gameChunkRenderDistance + 1, chunkZdist + gameChunkRenderDistance + 1) || smallRenderDistance))))
&& (gameChunkRenderDistance < Math.abs(chunkXdist)
|| gameChunkRenderDistance < Math.abs(chunkZdist)
|| !(vanillaRenderedChunks[chunkXdist + gameChunkRenderDistance + 1][chunkZdist + gameChunkRenderDistance + 1]
&& (!LodUtil.isBorderChunk(vanillaRenderedChunks, chunkXdist + gameChunkRenderDistance + 1, chunkZdist + gameChunkRenderDistance + 1) || smallRenderDistance))))
{
for (int verticalIndex = 0; verticalIndex < lodDim.getMaxVerticalData(detailLevel, xAdj, zAdj); verticalIndex++)
{
long data = lodDim.getData(detailLevel, xAdj, zAdj, verticalIndex);
adjData.get(direction)[verticalIndex] = data;
}
} else
}
else
{
if (gameChunkRenderDistance >= Math.abs(chunkXdist)
&& gameChunkRenderDistance >= Math.abs(chunkZdist)
&& (!LodUtil.isBorderChunk(vanillaRenderedChunks, chunkXdist + gameChunkRenderDistance + 1, chunkZdist + gameChunkRenderDistance + 1) || smallRenderDistance)
&& vanillaRenderedChunks[chunkXdist + gameChunkRenderDistance + 1][chunkZdist + gameChunkRenderDistance + 1]
&& !DataPointUtil.isVoid(lodDim.getSingleData(detailLevel, xAdj, zAdj)))
&& gameChunkRenderDistance >= Math.abs(chunkZdist)
&& (!LodUtil.isBorderChunk(vanillaRenderedChunks, chunkXdist + gameChunkRenderDistance + 1, chunkZdist + gameChunkRenderDistance + 1) || smallRenderDistance)
&& vanillaRenderedChunks[chunkXdist + gameChunkRenderDistance + 1][chunkZdist + gameChunkRenderDistance + 1]
&& !DataPointUtil.isVoid(lodDim.getSingleData(detailLevel, xAdj, zAdj)))
adjShadeDisabled[Box.DIRECTION_INDEX.get(direction)] = true;
adjData.get(direction)[0] = DataPointUtil.EMPTY_DATA;
}
}
long data;
for (int verticalIndex = 0; verticalIndex < lodDim.getMaxVerticalData(detailLevel, posX, posZ); verticalIndex++)
{
data = lodDim.getData(detailLevel, posX, posZ, verticalIndex);
if (DataPointUtil.isVoid(data) || !DataPointUtil.doesItExist(data))
break;
LodConfig.CLIENT.graphics.lodTemplate.get().template.addLodToBuffer(currentBuffers[bufferIndex], playerBlockPosRounded, data, adjData,
detailLevel, posX, posZ, box, renderer.previousDebugMode, renderer.lightMap, adjShadeDisabled);
}
} // for pos to in list to render
// the thread executed successfully
// the thread executed successfully
return true;
};
nodeToRenderThreads.add(dataToRenderThread);
}
} // region z
} // region z
long executeStart = System.currentTimeMillis();
// wait for all threads to finish
List<Future<Boolean>> futuresBuffer = bufferBuilderThreads.invokeAll(nodeToRenderThreads);
@@ -374,47 +383,49 @@ public class LodBufferBuilder
}
}
long executeEnd = System.currentTimeMillis();
long endTime = System.currentTimeMillis();
@SuppressWarnings("unused")
long buildTime = endTime - startTime;
@SuppressWarnings("unused")
long executeTime = executeEnd - executeStart;
// ClientProxy.LOGGER.info("Thread Build time: " + buildTime + " ms" + '\n' +
// "thread execute time: " + executeTime + " ms");
// mark that the buildable buffers as ready to swap
switchVbos = true;
} catch (Exception e)
}
catch (Exception e)
{
ClientProxy.LOGGER.warn("\"LodNodeBufferBuilder.generateLodBuffersAsync\" ran into trouble: ");
e.printStackTrace();
} finally
}
finally
{
// regardless of if we successfully created the buffers
// we are done generating.
generatingBuffers = false;
// clean up any potentially open resources
if (buildableBuffers != null)
closeBuffers(fullRegen, lodDim);
// upload the new buffers
uploadBuffers(fullRegen, lodDim);
bufferLock.unlock();
}
});
mainGenThread.execute(thread);
}
//===============================//
// BufferBuilder related methods //
//===============================//
/**
* Called from the LodRenderer to create the
* BufferBuilders. <br><br>
@@ -427,14 +438,14 @@ public class LodBufferBuilder
int numbRegionsWide = lodDimension.getWidth();
long memoryRequired;
int numberOfBuffers;
previousRegionWidth = numbRegionsWide;
bufferSize = new int[numbRegionsWide][numbRegionsWide];
buildableBuffers = new BufferBuilder[numbRegionsWide][numbRegionsWide][];
buildableVbos = new VertexBuffer[numbRegionsWide][numbRegionsWide][];
drawableVbos = new VertexBuffer[numbRegionsWide][numbRegionsWide][];
for (int x = 0; x < numbRegionsWide; x++)
{
for (int z = 0; z < numbRegionsWide; z++)
@@ -447,7 +458,8 @@ public class LodBufferBuilder
buildableBuffers[x][z] = new BufferBuilder[1];
buildableVbos[x][z] = new VertexBuffer[1];
drawableVbos[x][z] = new VertexBuffer[1];
} else
}
else
{
numberOfBuffers = (int) Math.ceil(memoryRequired / BUFFER_MAX_CAPACITY) + 1;
System.out.println(numberOfBuffers);
@@ -457,7 +469,7 @@ public class LodBufferBuilder
buildableVbos[x][z] = new VertexBuffer[numberOfBuffers];
drawableVbos[x][z] = new VertexBuffer[numberOfBuffers];
}
for (int i = 0; i < bufferSize[x][z]; i++)
{
buildableBuffers[x][z][i] = new BufferBuilder((int) memoryRequired);
@@ -466,10 +478,10 @@ public class LodBufferBuilder
}
}
}
bufferLock.unlock();
}
/**
* sets the buffers and Vbos to null, forcing them to be recreated. <br><br>
* <p>
@@ -478,14 +490,14 @@ public class LodBufferBuilder
public void destroyBuffers()
{
bufferLock.lock();
buildableBuffers = null;
buildableVbos = null;
drawableVbos = null;
bufferLock.unlock();
}
/**
* Calls begin on each of the buildable BufferBuilders.
*/
@@ -500,18 +512,18 @@ public class LodBufferBuilder
// for some reason BufferBuilder.vertexCounts
// isn't reset unless this is called, which can cause
// a false indexOutOfBoundsException
for (int i = 0; i < buildableBuffers[x][z].length; i++)
{
buildableBuffers[x][z][i].discard();
buildableBuffers[x][z][i].begin(GL11.GL_QUADS, LodRenderer.LOD_VERTEX_FORMAT);
}
}
}
}
}
/**
* Calls end on each of the buildable BufferBuilders.
*/
@@ -527,20 +539,20 @@ public class LodBufferBuilder
}
}
}
/**
* Upload all buildableBuffers to the GPU.
*/
private void uploadBuffers(boolean fullRegen, LodDimension lodDim)
{
GlProxy glProxy = GlProxy.getInstance();
try
{
// make sure we are uploading to a different OpenGL context,
// to prevent interference (IE stuttering) with the Minecraft context.
glProxy.setGlContext(GlProxyContext.LOD_BUILDER);
for (int x = 0; x < buildableVbos.length; x++)
{
for (int z = 0; z < buildableVbos.length; z++)
@@ -556,17 +568,19 @@ public class LodBufferBuilder
}
}
}
} catch (IllegalStateException e)
}
catch (IllegalStateException e)
{
ClientProxy.LOGGER.error(LodBufferBuilder.class.getSimpleName() + " - UploadBuffers failed: " + e.getMessage());
e.printStackTrace();
} finally
}
finally
{
// make sure the context is disabled
glProxy.setGlContext(GlProxyContext.NONE);
}
}
/**
* Uploads the uploadBuffer into the VBO in GPU memory.
*/
@@ -577,22 +591,22 @@ public class LodBufferBuilder
{
// this is how many points will be rendered
vbo.vertexCount = (uploadBuffer.remaining() / vbo.format.getVertexSize());
GL15C.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo.id);
// subData only works if the memory is allocated beforehand.
GL15C.glBufferData(GL15.GL_ARRAY_BUFFER, uploadBuffer.remaining(), GL15C.GL_DYNAMIC_DRAW);
// interestingly bufferSubData renders faster than glMapBuffer
// even though OpenGLInsights-AsynchronousBufferTransfers says glMapBuffer
// is faster for transferring data. They must put the data in different memory
// or something.
GL15C.glBufferSubData(GL15.GL_ARRAY_BUFFER, 0, uploadBuffer);
GL15C.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
}
}
/**
* Get the newly created VBOs
*/
@@ -605,17 +619,17 @@ public class LodBufferBuilder
VertexBuffer[][][] tmpVbo = drawableVbos;
drawableVbos = buildableVbos;
buildableVbos = tmpVbo;
drawableCenterChunkPos = buildableCenterChunkPos;
// the vbos have been swapped
switchVbos = false;
bufferLock.unlock();
}
return new VertexBuffersAndOffset(drawableVbos, drawableCenterChunkPos);
}
/**
* A simple container to pass multiple objects back in the getVertexBuffers method.
*/
@@ -623,14 +637,14 @@ public class LodBufferBuilder
{
public VertexBuffer[][][] vbos;
public ChunkPos drawableCenterChunkPos;
public VertexBuffersAndOffset(VertexBuffer[][][] newVbos, ChunkPos newDrawableCenterChunkPos)
{
vbos = newVbos;
drawableCenterChunkPos = newDrawableCenterChunkPos;
}
}
/**
* If this is true the buildable near and far
* buffers have been generated and are ready to be
@@ -640,15 +654,15 @@ public class LodBufferBuilder
{
return switchVbos;
}
/**
*
*/
public void setPartialRegen()
{
}
/**
*
*/