Remove the memory estimation code.
Buffers will now be purposely created smaller than expected and then expanded to fit the need.
This commit is contained in:
@@ -62,7 +62,7 @@ import net.minecraft.util.math.ChunkPos;
|
||||
* This object is used to create NearFarBuffer objects.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 10-9-2021
|
||||
* @version 10-10-2021
|
||||
*/
|
||||
public class LodBufferBuilder
|
||||
{
|
||||
@@ -77,6 +77,13 @@ public class LodBufferBuilder
|
||||
*/
|
||||
public static final double BUFFER_EXPANSION_MULTIPLIER = 1.5;
|
||||
|
||||
/**
|
||||
* When buffers are first created they are allocated to this size (in Bytes).
|
||||
* This size will be too small, more than likely. The buffers will be expanded
|
||||
* when need be to fit the larger sizes.
|
||||
*/
|
||||
public static final int DEFAULT_MEMORY_ALLOCATION = 1024;
|
||||
|
||||
|
||||
/** This boolean matrix indicate the buffer builder in that position has to be regenerated */
|
||||
public volatile boolean[][] regenPos;
|
||||
@@ -464,7 +471,7 @@ public class LodBufferBuilder
|
||||
{
|
||||
for (int z = 0; z < numbRegionsWide; z++)
|
||||
{
|
||||
regionMemoryRequired = LodUtil.calculateMaximumRegionGpuMemoryUse(x, z, LodConfig.CLIENT.graphics.lodTemplate.get());
|
||||
regionMemoryRequired = DEFAULT_MEMORY_ALLOCATION;
|
||||
|
||||
// if the memory required is greater than the max buffer
|
||||
// capacity, divide the memory across multiple buffers
|
||||
@@ -507,6 +514,7 @@ public class LodBufferBuilder
|
||||
buildableVbos[x][z][i] = new VertexBuffer(LodUtil.LOD_VERTEX_FORMAT);
|
||||
drawableVbos[x][z][i] = new VertexBuffer(LodUtil.LOD_VERTEX_FORMAT);
|
||||
|
||||
|
||||
// create the initial mapped buffers (system memory)
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, buildableVbos[x][z][i].id);
|
||||
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, regionMemoryRequired, GL45.GL_DYNAMIC_DRAW);
|
||||
@@ -517,9 +525,7 @@ public class LodBufferBuilder
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
|
||||
|
||||
|
||||
// create the buffer storage (GPU memory)
|
||||
|
||||
buildableStorageBufferIds[x][z][i] = GL45.glGenBuffers();
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, buildableStorageBufferIds[x][z][i]);
|
||||
GL45.glBufferStorage(GL15.GL_ARRAY_BUFFER, regionMemoryRequired, 0); // the 0 flag means to create the storage in the GPU's memory
|
||||
@@ -680,8 +686,8 @@ public class LodBufferBuilder
|
||||
{
|
||||
for (int i = 0; i < buildableBuffers[x][z].length; i++)
|
||||
{
|
||||
ByteBuffer builderBuffer = buildableBuffers[x][z][i].popNextBuffer().getSecond();
|
||||
vboUpload(buildableVbos[x][z][i], buildableStorageBufferIds[x][z][i], builderBuffer, x,z,i, true);
|
||||
ByteBuffer uploadBuffer = buildableBuffers[x][z][i].popNextBuffer().getSecond();
|
||||
vboUpload(buildableVbos[x][z][i], buildableStorageBufferIds[x][z][i], uploadBuffer, x,z,i, true);
|
||||
lodDim.setRegenRegionBufferByArrayIndex(x, z, false);
|
||||
}
|
||||
}
|
||||
|
||||
+6
-14
@@ -18,34 +18,31 @@
|
||||
|
||||
package com.seibel.lod.builders.bufferBuilding.lodTemplates;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.seibel.lod.enums.DebugMode;
|
||||
import com.seibel.lod.util.ColorUtil;
|
||||
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.texture.NativeImage;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This is the abstract class used to create different
|
||||
* BufferBuilders.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 8-8-2021
|
||||
* @version 10-10-2021
|
||||
*/
|
||||
public abstract class AbstractLodTemplate
|
||||
{
|
||||
|
||||
/**
|
||||
* Uploads the given LOD to the buffer.
|
||||
*/
|
||||
/** Uploads the given LOD to the buffer. */
|
||||
public abstract void addLodToBuffer(BufferBuilder buffer, BlockPos bufferCenterBlockPos, long data, Map<Direction, long[]> adjData,
|
||||
byte detailLevel, int posX, int posZ, Box box, DebugMode debugging, NativeImage lightMap, boolean[] adjShadeDisabled);
|
||||
|
||||
/**
|
||||
* add the given position and color to the buffer
|
||||
*/
|
||||
/** add the given position and color to the buffer */
|
||||
protected void addPosAndColor(BufferBuilder buffer,
|
||||
double x, double y, double z,
|
||||
int color)
|
||||
@@ -54,9 +51,4 @@ public abstract class AbstractLodTemplate
|
||||
buffer.vertex(x, y, z).color(ColorUtil.getRed(color), ColorUtil.getGreen(color), ColorUtil.getBlue(color), 255).endVertex();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns in bytes how much buffer memory is required
|
||||
* for one LOD object
|
||||
*/
|
||||
public abstract int getBufferMemoryForSingleNode(int maxVerticalData);
|
||||
}
|
||||
|
||||
+1
-8
@@ -33,7 +33,7 @@ import net.minecraft.util.math.BlockPos;
|
||||
* Builds LODs as rectangular prisms.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 9-25-2021
|
||||
* @version 10-10-2021
|
||||
*/
|
||||
public class CubicLodTemplate extends AbstractLodTemplate
|
||||
{
|
||||
@@ -127,11 +127,4 @@ public class CubicLodTemplate extends AbstractLodTemplate
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBufferMemoryForSingleNode(int maxVerticalData)
|
||||
{
|
||||
// TODO, what do these magic numbers mean
|
||||
return 2 * 4 * (3 + 4) + 4 * 4 * Math.max((maxVerticalData + 1) / 2, 1) * (3 + 4);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-7
@@ -18,15 +18,16 @@
|
||||
|
||||
package com.seibel.lod.builders.bufferBuilding.lodTemplates;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.seibel.lod.enums.DebugMode;
|
||||
import com.seibel.lod.proxy.ClientProxy;
|
||||
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.texture.NativeImage;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* TODO DynamicLodTemplate
|
||||
* Chunks smoothly transition between
|
||||
@@ -45,9 +46,4 @@ public class DynamicLodTemplate extends AbstractLodTemplate
|
||||
ClientProxy.LOGGER.error(DynamicLodTemplate.class.getSimpleName() + " is not implemented!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBufferMemoryForSingleNode(int maxVerticalData)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
+3
-7
@@ -18,15 +18,16 @@
|
||||
|
||||
package com.seibel.lod.builders.bufferBuilding.lodTemplates;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.seibel.lod.enums.DebugMode;
|
||||
import com.seibel.lod.proxy.ClientProxy;
|
||||
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.texture.NativeImage;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* TODO #21 TriangularLodTemplate
|
||||
* Builds each LOD chunk as a singular rectangular prism.
|
||||
@@ -43,9 +44,4 @@ public class TriangularLodTemplate extends AbstractLodTemplate
|
||||
ClientProxy.LOGGER.error(DynamicLodTemplate.class.getSimpleName() + " is not implemented!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBufferMemoryForSingleNode(int maxVerticalData)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ import com.seibel.lod.builders.bufferBuilding.lodTemplates.TriangularLodTemplate
|
||||
* Cubic, Triangular, Dynamic
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 8-4-2021
|
||||
* @version 10-10-2021
|
||||
*/
|
||||
public enum LodTemplate
|
||||
{
|
||||
@@ -51,9 +51,4 @@ public enum LodTemplate
|
||||
template = newTemplate;
|
||||
}
|
||||
|
||||
|
||||
public int getBufferMemoryForSingleLod(int maxVerticalData)
|
||||
{
|
||||
return template.getBufferMemoryForSingleNode(maxVerticalData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,23 +18,28 @@
|
||||
|
||||
package com.seibel.lod.objects;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import com.seibel.lod.config.LodConfig;
|
||||
import com.seibel.lod.enums.DistanceGenerationMode;
|
||||
import com.seibel.lod.enums.GenerationPriority;
|
||||
import com.seibel.lod.enums.VerticalQuality;
|
||||
import com.seibel.lod.handlers.LodDimensionFileHandler;
|
||||
import com.seibel.lod.util.*;
|
||||
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.wrappers.MinecraftWrapper;
|
||||
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.world.DimensionType;
|
||||
import net.minecraft.world.server.ServerChunkProvider;
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
|
||||
/**
|
||||
* This object holds all loaded LOD regions
|
||||
@@ -46,7 +51,7 @@ import java.util.concurrent.Executors;
|
||||
*
|
||||
* @author Leonardo Amato
|
||||
* @author James Seibel
|
||||
* @version 9-27-2021
|
||||
* @version 10-10-2021
|
||||
*/
|
||||
public class LodDimension
|
||||
{
|
||||
@@ -238,27 +243,6 @@ public class LodDimension
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* return the minimum needed memory in bytes
|
||||
*/
|
||||
public int getMinMemoryNeeded()
|
||||
{
|
||||
int count = 0;
|
||||
LodRegion region;
|
||||
|
||||
for (LodRegion[] lodRegions : regions)
|
||||
{
|
||||
for (int z = 0; z < regions.length; z++)
|
||||
{
|
||||
region = lodRegions[z];
|
||||
if (region != null)
|
||||
count += region.getMinMemoryNeeded(LodConfig.CLIENT.graphics.lodTemplate.get());
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the region at the given LevelPos
|
||||
* <br>
|
||||
|
||||
@@ -3,7 +3,6 @@ package com.seibel.lod.objects;
|
||||
|
||||
import com.seibel.lod.config.LodConfig;
|
||||
import com.seibel.lod.enums.DistanceGenerationMode;
|
||||
import com.seibel.lod.enums.LodTemplate;
|
||||
import com.seibel.lod.enums.VerticalQuality;
|
||||
import com.seibel.lod.util.DataPointUtil;
|
||||
import com.seibel.lod.util.DetailDistanceUtil;
|
||||
@@ -19,7 +18,7 @@ import com.seibel.lod.util.LodUtil;
|
||||
* unless stated otherwise. <br>
|
||||
*
|
||||
* @author Leonardo Amato
|
||||
* @version 9-27-2021
|
||||
* @version 10-10-2021
|
||||
*/
|
||||
public class LodRegion
|
||||
{
|
||||
@@ -517,20 +516,6 @@ public class LodRegion
|
||||
return new RegionPos(regionPosX, regionPosZ);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the minimum memory needed in bytes
|
||||
*/
|
||||
public int getMinMemoryNeeded(LodTemplate template)
|
||||
{
|
||||
int memory = 0;
|
||||
for (byte detailLevelIndex = LodUtil.REGION_DETAIL_LEVEL; detailLevelIndex > minDetailLevel; detailLevelIndex--)
|
||||
{
|
||||
// TODO why are we multiplying the dataContainer's memory by the template's memory?
|
||||
memory += dataContainer[detailLevelIndex].getMaxMemoryUse() * template.getBufferMemoryForSingleLod(dataContainer[detailLevelIndex].getMaxVerticalData());
|
||||
}
|
||||
return memory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns how many LODs are in this region
|
||||
*/
|
||||
|
||||
@@ -18,8 +18,6 @@
|
||||
|
||||
package com.seibel.lod.render;
|
||||
|
||||
import com.seibel.lod.config.LodConfig;
|
||||
import com.seibel.lod.objects.LodRegion;
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
import com.seibel.lod.wrappers.MinecraftWrapper;
|
||||
|
||||
@@ -32,7 +30,7 @@ import net.minecraft.util.math.vector.Vector3d;
|
||||
* to be used in the rendering process.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 8-21-2021
|
||||
* @version 10-10-2021
|
||||
*/
|
||||
public class RenderUtil
|
||||
{
|
||||
@@ -82,28 +80,6 @@ public class RenderUtil
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get how much buffer memory would be required for the given radius multiplier
|
||||
*/
|
||||
public static int getBufferMemoryForRegion(LodRegion region)
|
||||
{
|
||||
// calculate the max amount of buffer memory needed (in bytes)
|
||||
return region.getMinMemoryNeeded(LodConfig.CLIENT.graphics.lodTemplate.get());
|
||||
}
|
||||
|
||||
///**
|
||||
// * Returns the maxViewDistanceMultiplier for the given LodTemplate
|
||||
// * at the given LodDetail level.
|
||||
// */
|
||||
/*public static int getMaxRadiusMultiplierWithAvailableMemory(LodTemplate lodTemplate, int detailLevel)
|
||||
{
|
||||
int maxNumberOfLods = LodRenderer.MAX_ALLOCATABLE_DIRECT_MEMORY / lodTemplate.getBufferMemoryForSingleLod();
|
||||
int numbLodsWide = (int) Math.sqrt(maxNumberOfLods);
|
||||
|
||||
return numbLodsWide / (2 * mc.getRenderDistance());
|
||||
}*/
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if one of the region's 4 corners is in front
|
||||
* of the camera.
|
||||
|
||||
@@ -18,11 +18,15 @@
|
||||
|
||||
package com.seibel.lod.util;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.io.File;
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.seibel.lod.builders.bufferBuilding.lodTemplates.Box;
|
||||
import com.seibel.lod.enums.LodTemplate;
|
||||
import com.seibel.lod.objects.LodDimension;
|
||||
import com.seibel.lod.objects.RegionPos;
|
||||
import com.seibel.lod.wrappers.MinecraftWrapper;
|
||||
|
||||
import net.minecraft.client.multiplayer.ServerData;
|
||||
import net.minecraft.client.renderer.WorldRenderer;
|
||||
import net.minecraft.client.renderer.chunk.ChunkRenderDispatcher.CompiledChunk;
|
||||
@@ -40,15 +44,11 @@ import net.minecraft.world.gen.Heightmap;
|
||||
import net.minecraft.world.server.ServerChunkProvider;
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.util.HashSet;
|
||||
|
||||
/**
|
||||
* This class holds methods and constants that may be used in multiple places.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 10-7-2021
|
||||
* @version 10-10-2021
|
||||
*/
|
||||
public class LodUtil
|
||||
{
|
||||
@@ -350,74 +350,6 @@ public class LodUtil
|
||||
return Math.min(max, Math.max(value, min));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the GPU memory needed if all LODs in
|
||||
* the given region are rendered.
|
||||
*
|
||||
* @param regionPosX x region position to check
|
||||
* @param regionPosZ z region position to check
|
||||
* @return number of lods in the region
|
||||
*/
|
||||
public static long calculateMaximumRegionGpuMemoryUse(int regionPosX, int regionPosZ, LodTemplate template)
|
||||
{
|
||||
int xRegionSign = (int) Math.signum(regionPosX);
|
||||
int zRegionSign = (int) Math.signum(regionPosZ);
|
||||
|
||||
// we first find the center of the circle which is one of the following X position in the center region
|
||||
/*
|
||||
X - X - X
|
||||
| |
|
||||
X X X
|
||||
| |
|
||||
X - X - X
|
||||
*/
|
||||
int circleCenterX = 256 + 256 * xRegionSign;
|
||||
int circleCenterZ = 256 + 256 * zRegionSign;
|
||||
|
||||
|
||||
int innerRadius;
|
||||
int outerRadius;
|
||||
int size;
|
||||
int count;
|
||||
int minDistance;
|
||||
int maxDistance;
|
||||
long memoryUse = 0;
|
||||
for (byte detailLevel = BLOCK_DETAIL_LEVEL; detailLevel <= REGION_DETAIL_LEVEL; detailLevel++)
|
||||
{
|
||||
// Find the inner and outer detail of this area
|
||||
innerRadius = DetailDistanceUtil.getDrawDistanceFromDetail(detailLevel);
|
||||
outerRadius = DetailDistanceUtil.getDrawDistanceFromDetail(detailLevel + 1);
|
||||
|
||||
// skip this region if it does not intersect the two circles.
|
||||
minDistance = LevelPosUtil.minDistance(REGION_DETAIL_LEVEL, regionPosX, regionPosZ, circleCenterX, circleCenterZ);
|
||||
maxDistance = LevelPosUtil.maxDistance(REGION_DETAIL_LEVEL, regionPosX, regionPosZ, circleCenterX, circleCenterZ);
|
||||
if (innerRadius > maxDistance || minDistance > outerRadius)
|
||||
continue;
|
||||
|
||||
// count every position in the region that falls between the two circles
|
||||
size = 1 << (REGION_DETAIL_LEVEL - detailLevel);
|
||||
count = 0;
|
||||
for (int x = 0; x < size; x++)
|
||||
{
|
||||
for (int z = 0; z < size; z++)
|
||||
{
|
||||
minDistance = LevelPosUtil.minDistance(detailLevel, x, z, circleCenterX, circleCenterZ, regionPosX, regionPosZ);
|
||||
if (innerRadius < minDistance && minDistance < outerRadius)
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
// we multiply the data with the max vertical data of this detail level
|
||||
int maxVerticalData = DetailDistanceUtil.getMaxVerticalData(detailLevel);
|
||||
|
||||
count *= maxVerticalData;
|
||||
memoryUse += (long) template.getBufferMemoryForSingleLod(maxVerticalData) * count;
|
||||
}
|
||||
|
||||
return memoryUse;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a HashSet of all ChunkPos within the normal render distance
|
||||
* that should not be rendered.
|
||||
|
||||
Reference in New Issue
Block a user