Fix #4 (Prevent excessive render distances from causing out of memory errors)
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
package com.seibel.lod.builders.lodTemplates;
|
||||
|
||||
import com.seibel.lod.enums.LodDetail;
|
||||
import com.seibel.lod.objects.LodChunk;
|
||||
import com.seibel.lod.objects.LodDimension;
|
||||
|
||||
@@ -10,7 +11,7 @@ import net.minecraft.client.renderer.BufferBuilder;
|
||||
* BufferBuilders.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 06-12-2021
|
||||
* @version 06-16-2021
|
||||
*/
|
||||
public abstract class AbstractLodTemplate
|
||||
{
|
||||
@@ -27,7 +28,9 @@ public abstract class AbstractLodTemplate
|
||||
buffer.pos(x, y, z).color(red, green, blue, alpha).endVertex();
|
||||
}
|
||||
|
||||
|
||||
/** Returns in bytes how much buffer memory is required
|
||||
* for one LOD object */
|
||||
public abstract int getBufferMemoryForSingleLod(LodDetail detail);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ import net.minecraft.util.math.AxisAlignedBB;
|
||||
* Builds LODs as rectangular prisms.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 06-13-2021
|
||||
* @version 06-16-2021
|
||||
*/
|
||||
public class CubicLodTemplate extends AbstractLodTemplate
|
||||
{
|
||||
@@ -159,6 +159,14 @@ public class CubicLodTemplate extends AbstractLodTemplate
|
||||
addPosAndColor(buffer, bb.maxX, bb.minY, bb.maxZ, c[ColorDirection.EAST.value].getRed(), c[ColorDirection.EAST.value].getGreen(), c[ColorDirection.EAST.value].getBlue(), c[ColorDirection.EAST.value].getAlpha());
|
||||
addPosAndColor(buffer, bb.maxX, bb.minY, bb.minZ, c[ColorDirection.EAST.value].getRed(), c[ColorDirection.EAST.value].getGreen(), c[ColorDirection.EAST.value].getBlue(), c[ColorDirection.EAST.value].getAlpha());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getBufferMemoryForSingleLod(LodDetail detail)
|
||||
{
|
||||
// (sidesOnACube * pointsInASquare * (positionPoints + colorPoints))) * howManyPointsPerLodChunk
|
||||
return (6 * 4 * (3 + 4)) * detail.lengthCount * detail.lengthCount;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.seibel.lod.builders.lodTemplates;
|
||||
|
||||
import com.seibel.lod.enums.LodDetail;
|
||||
import com.seibel.lod.objects.LodChunk;
|
||||
import com.seibel.lod.objects.LodDimension;
|
||||
|
||||
@@ -12,7 +13,7 @@ import net.minecraft.client.renderer.BufferBuilder;
|
||||
* is at a significantly different height.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 05-07-2021
|
||||
* @version 06-16-2021
|
||||
*/
|
||||
public class DynamicLodTemplate extends AbstractLodTemplate
|
||||
{
|
||||
@@ -24,4 +25,10 @@ public class DynamicLodTemplate extends AbstractLodTemplate
|
||||
{
|
||||
System.err.println("DynamicLodTemplate not implemented!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBufferMemoryForSingleLod(LodDetail detail) {
|
||||
// TODO Auto-generated method stub
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.seibel.lod.builders.lodTemplates;
|
||||
|
||||
import com.seibel.lod.enums.LodDetail;
|
||||
import com.seibel.lod.objects.LodChunk;
|
||||
import com.seibel.lod.objects.LodDimension;
|
||||
|
||||
@@ -10,7 +11,7 @@ import net.minecraft.client.renderer.BufferBuilder;
|
||||
* Builds each LOD chunk as a singular rectangular prism.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 05-07-2021
|
||||
* @version 06-16-2021
|
||||
*/
|
||||
public class TriangularLodTemplate extends AbstractLodTemplate
|
||||
{
|
||||
@@ -22,4 +23,10 @@ public class TriangularLodTemplate extends AbstractLodTemplate
|
||||
{
|
||||
System.err.println("DynamicLodTemplate not implemented!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBufferMemoryForSingleLod(LodDetail detail) {
|
||||
// TODO Auto-generated method stub
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import com.seibel.lod.builders.lodTemplates.TriangularLodTemplate;
|
||||
* Cubic, Triangular, Dynamic
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 05-07-2021
|
||||
* @version 06-16-2021
|
||||
*/
|
||||
public enum LodTemplate
|
||||
{
|
||||
@@ -35,4 +35,10 @@ public enum LodTemplate
|
||||
{
|
||||
template = newTemplate;
|
||||
}
|
||||
|
||||
|
||||
public int getBufferMemoryForSingleLod(LodDetail detail)
|
||||
{
|
||||
return template.getBufferMemoryForSingleLod(detail);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,11 +13,14 @@ import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.seibel.lod.builders.LodBufferBuilder;
|
||||
import com.seibel.lod.enums.FogDistance;
|
||||
import com.seibel.lod.enums.FogQuality;
|
||||
import com.seibel.lod.enums.LodDetail;
|
||||
import com.seibel.lod.enums.LodTemplate;
|
||||
import com.seibel.lod.handlers.ReflectionHandler;
|
||||
import com.seibel.lod.objects.LodChunk;
|
||||
import com.seibel.lod.objects.LodDimension;
|
||||
import com.seibel.lod.objects.NearFarBuffer;
|
||||
import com.seibel.lod.objects.NearFarFogSetting;
|
||||
import com.seibel.lod.proxy.ClientProxy;
|
||||
import com.seibel.lod.util.LodConfig;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
@@ -45,14 +48,28 @@ import net.minecraft.util.math.vector.Vector3f;
|
||||
* This is where LODs are draw to the world.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 05-08-2021
|
||||
* @version 06-17-2021
|
||||
*/
|
||||
public class LodRender
|
||||
{
|
||||
/** this is the light used when rendering the LODs,
|
||||
* it should be something different than what is used by Minecraft */
|
||||
private static final int LOD_GL_LIGHT_NUMBER = GL11.GL_LIGHT2;
|
||||
|
||||
|
||||
/**
|
||||
* 64 MB by default is the maximum amount of memory that
|
||||
* can be directly allocated. <br><br>
|
||||
*
|
||||
* I know there are commands to change that amount
|
||||
* (specifically "-XX:MaxDirectMemorySize"), but
|
||||
* I have no idea how to access that amount. <br>
|
||||
* So I guess this will be the hard limit for now. <br><br>
|
||||
*
|
||||
* https://stackoverflow.com/questions/50499238/bytebuffer-allocatedirect-and-xmx
|
||||
*/
|
||||
public static final int MAX_ALOCATEABLE_DIRECT_MEMORY = 64 * 1024 * 1024;
|
||||
|
||||
|
||||
/** If true the LODs colors will be replaced with
|
||||
* a checkerboard, this can be used for debugging. */
|
||||
public boolean debugging = false;
|
||||
@@ -114,7 +131,6 @@ public class LodRender
|
||||
* @param newDimension The dimension to draw, if null doesn't replace the current dimension.
|
||||
* @param partialTicks how far into the current tick this method was called.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public void drawLODs(LodDimension lodDim, float partialTicks, IProfiler newProfiler)
|
||||
{
|
||||
if (lodDim == null)
|
||||
@@ -493,7 +509,6 @@ public class LodRender
|
||||
/**
|
||||
* setup the lighting to be used for the LODs
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private void setupLighting(LodDimension lodDimension, float partialTicks)
|
||||
{
|
||||
float sunBrightness = lodDimension.dimension.hasSkyLight() ? mc.world.getSunBrightness(partialTicks) : 0.2f;
|
||||
@@ -510,28 +525,63 @@ public class LodRender
|
||||
RenderSystem.enableLighting();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create all buffers that will be used.
|
||||
*/
|
||||
private void setupBuffers(int numbChunksWide)
|
||||
{
|
||||
// calculate the max amount of storage needed (in bytes)
|
||||
int bufferMaxCapacity = (numbChunksWide * numbChunksWide * (6 * 4 * (3 + 4)));
|
||||
// (numbChunksWide * numbChunksWide *
|
||||
// (sidesOnACube * pointsInASquare * (positionPoints + colorPoints)))
|
||||
// calculate the max amount of memory needed (in bytes)
|
||||
int bufferMemory = getBufferMemoryForRadiusMultiplier(LodConfig.CLIENT.lodChunkRadiusMultiplier.get());
|
||||
|
||||
// TODO complain or do something when memory is too low
|
||||
// currently the VM will just crash and complain there is no more memory
|
||||
// issue #4
|
||||
drawableNearBuffer = new BufferBuilder(bufferMaxCapacity);
|
||||
drawableFarBuffer = new BufferBuilder(bufferMaxCapacity);
|
||||
// if the required memory is greater than the
|
||||
// MAX_ALOCATEABLE_DIRECT_MEMORY lower the lodChunkRadiusMultiplier
|
||||
// to fit.
|
||||
if (bufferMemory > MAX_ALOCATEABLE_DIRECT_MEMORY)
|
||||
{
|
||||
int maxRadiusMultiplier = getMaxRadiusMultiplierWithAvaliableMemory(LodConfig.CLIENT.lodTemplate.get(), LodConfig.CLIENT.lodDetail.get());
|
||||
|
||||
ClientProxy.LOGGER.warn("The lodChunkRadiusMultiplier was set too high "
|
||||
+ "and had to be lowered to fit memory constraints "
|
||||
+ "from " + LodConfig.CLIENT.lodChunkRadiusMultiplier.get() + " "
|
||||
+ "to " + maxRadiusMultiplier);
|
||||
|
||||
LodConfig.CLIENT.lodChunkRadiusMultiplier.set(
|
||||
maxRadiusMultiplier);
|
||||
|
||||
bufferMemory = getBufferMemoryForRadiusMultiplier(maxRadiusMultiplier);
|
||||
}
|
||||
|
||||
lodBufferBuilder.setupBuffers(bufferMaxCapacity);
|
||||
drawableNearBuffer = new BufferBuilder(bufferMemory);
|
||||
drawableFarBuffer = new BufferBuilder(bufferMemory);
|
||||
|
||||
lodBufferBuilder.setupBuffers(bufferMemory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get how much buffer memory would be required for the given radius multiplier
|
||||
*/
|
||||
public int getBufferMemoryForRadiusMultiplier(int radiusMultiplier)
|
||||
{
|
||||
int numbChunksWide = mc.gameSettings.renderDistanceChunks *
|
||||
radiusMultiplier * 2;
|
||||
|
||||
// calculate the max amount of buffer memory needed (in bytes)
|
||||
return numbChunksWide * numbChunksWide *
|
||||
LodConfig.CLIENT.lodTemplate.get().
|
||||
getBufferMemoryForSingleLod(LodConfig.CLIENT.lodDetail.get());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the maxViewDistanceMultiplier for the given LodTemplate
|
||||
* at the given LodDetail level.
|
||||
*/
|
||||
public int getMaxRadiusMultiplierWithAvaliableMemory(LodTemplate lodTemplate, LodDetail lodDetail)
|
||||
{
|
||||
int maxNumberOfLods = MAX_ALOCATEABLE_DIRECT_MEMORY / lodTemplate.getBufferMemoryForSingleLod(lodDetail);
|
||||
int numbLodsWide = (int) Math.sqrt(maxNumberOfLods);
|
||||
|
||||
return numbLodsWide / (2 * mc.gameSettings.renderDistanceChunks);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import net.minecraftforge.fml.config.ModConfig;
|
||||
/**
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 6-13-2021
|
||||
* @version 6-17-2021
|
||||
*/
|
||||
@Mod.EventBusSubscriber
|
||||
public class LodConfig
|
||||
@@ -89,8 +89,8 @@ public class LodConfig
|
||||
+ " This is multiplied by the default view distance \n"
|
||||
+ " to determine how far out to generate/render LODs. \n"
|
||||
+ " A value of 2 means that there is 1 render distance worth \n"
|
||||
+ " of LODs in each cardinal direction.")
|
||||
.defineInRange("lodChunkRadiusMultiplier", 6, 2, 1023);
|
||||
+ " of LODs in each cardinal direction. ")
|
||||
.defineInRange("lodChunkRadiusMultiplier", 6, 2, 32);
|
||||
|
||||
builder.pop();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user