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:
James Seibel
2021-10-10 14:01:13 -05:00
parent 6018449cbe
commit 9d1a9eb9f3
10 changed files with 46 additions and 191 deletions
@@ -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);
}
}
@@ -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);
}
@@ -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);
}
}
@@ -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;
}
}
@@ -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.
+6 -74
View File
@@ -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.