From 688cb3f89a4bd4bc5a477370377b37fc309cb27b Mon Sep 17 00:00:00 2001 From: Leonardo Date: Mon, 20 Sep 2021 18:58:02 +0200 Subject: [PATCH] New memory getter system --- .../seibel/lod/builders/LodBufferBuilder.java | 43 +++- .../lodTemplates/AbstractLodTemplate.java | 2 +- .../lodTemplates/CubicLodTemplate.java | 4 +- .../lodTemplates/DynamicLodTemplate.java | 2 +- .../lodTemplates/TriangularLodTemplate.java | 2 +- .../java/com/seibel/lod/config/LodConfig.java | 9 - .../com/seibel/lod/enums/LodTemplate.java | 4 +- .../seibel/lod/mixin/MixinWorldRenderer.java | 3 +- .../seibel/lod/objects/LevelContainer.java | 13 + .../com/seibel/lod/objects/LodDimension.java | 223 ++++++++++-------- .../com/seibel/lod/objects/LodRegion.java | 13 +- .../lod/objects/SingleLevelContainer.java | 9 + .../lod/objects/VerticalLevelContainer.java | 8 + .../com/seibel/lod/proxy/ClientProxy.java | 7 +- .../com/seibel/lod/render/LodRenderer.java | 10 +- .../com/seibel/lod/render/RenderUtil.java | 11 +- 16 files changed, 228 insertions(+), 135 deletions(-) diff --git a/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java b/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java index 2526f2a11..fe3e03d81 100644 --- a/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java +++ b/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java @@ -28,6 +28,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.locks.ReentrantLock; +import com.seibel.lod.render.RenderUtil; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL15; import org.lwjgl.opengl.GL15C; @@ -402,12 +403,12 @@ public class LodBufferBuilder *

* May have to wait for the bufferLock to open. */ - public void setupBuffers(int numbRegionsWide, int bufferMaxCapacity) + public void setupBuffers(int numbRegionsWide, LodDimension lodDimension) { bufferLock.lock(); previousRegionWidth = numbRegionsWide; - previousBufferSize = bufferMaxCapacity; + int bufferMaxCapacity; buildableBuffers = new BufferBuilder[numbRegionsWide][numbRegionsWide]; @@ -418,6 +419,7 @@ public class LodBufferBuilder { for (int z = 0; z < numbRegionsWide; z++) { + bufferMaxCapacity = lodDimension.getMemoryRequired(x,z); buildableBuffers[x][z] = new BufferBuilder(bufferMaxCapacity); buildableVbos[x][z] = new VertexBuffer(LodRenderer.LOD_VERTEX_FORMAT); @@ -542,6 +544,43 @@ public class LodBufferBuilder GL15C.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0); } + /* + // this shouldn't happen, but just to be safe + if (vbo.id != -1) + { + vbo.vertexCount = uploadBuffer.remaining() / vbo.format.getVertexSize(); + + + GL15C.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo.id); + + + // make sure enough space is allocated to fit the builderBuffer + GL15C.glBufferData(GL15.GL_ARRAY_BUFFER, uploadBuffer.capacity(), GL15C.GL_DYNAMIC_DRAW); + // try to get a pointer to the VBO's byteBuffer in GPU memory + ByteBuffer vboBuffer = GL15C.glMapBuffer(GL15.GL_ARRAY_BUFFER, GL15.GL_WRITE_ONLY); + + // upload the builderBuffer to the GPU + if (vboBuffer != null) + { + // This is the best way to upload lots of data, since writes directly to GPU + // memory, and doesn't pause OpenGL. + vboBuffer.put(uploadBuffer); + } + else + { + // Sometimes the vboBuffer is null (I think it may be due to buffer sizes + // changing or a setup process that didn't complete), so in that case + // we have to use this method which is slower and pauses OpenGL, + // but always succeeds. + GL15C.glBufferData(GL15.GL_ARRAY_BUFFER, uploadBuffer, GL15C.GL_DYNAMIC_DRAW); + + } + + + GL15C.glUnmapBuffer(GL15.GL_ARRAY_BUFFER); + GL15C.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0); + }*/ + } /** diff --git a/src/main/java/com/seibel/lod/builders/lodTemplates/AbstractLodTemplate.java b/src/main/java/com/seibel/lod/builders/lodTemplates/AbstractLodTemplate.java index f40c79d5f..2cd2c4e2b 100644 --- a/src/main/java/com/seibel/lod/builders/lodTemplates/AbstractLodTemplate.java +++ b/src/main/java/com/seibel/lod/builders/lodTemplates/AbstractLodTemplate.java @@ -56,5 +56,5 @@ public abstract class AbstractLodTemplate * Returns in bytes how much buffer memory is required * for one LOD object */ - public abstract int getBufferMemoryForSingleNode(); + public abstract int getBufferMemoryForSingleNode(int maxVerticalData); } diff --git a/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java b/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java index 61bb68e80..4f7dadbd4 100644 --- a/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java +++ b/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java @@ -126,10 +126,10 @@ public class CubicLodTemplate extends AbstractLodTemplate } @Override - public int getBufferMemoryForSingleNode() + public int getBufferMemoryForSingleNode(int maxVerticalData) { // (sidesOnACube * pointsInASquare * (positionPoints + colorPoints))) - return (6 * 4 * (3 + 4)); + return (2 * 4 * (3 + 4)) + (4 * 4 * (maxVerticalData + 1) * (3 + 4)); } } diff --git a/src/main/java/com/seibel/lod/builders/lodTemplates/DynamicLodTemplate.java b/src/main/java/com/seibel/lod/builders/lodTemplates/DynamicLodTemplate.java index d53fb9f6c..47d1384af 100644 --- a/src/main/java/com/seibel/lod/builders/lodTemplates/DynamicLodTemplate.java +++ b/src/main/java/com/seibel/lod/builders/lodTemplates/DynamicLodTemplate.java @@ -46,7 +46,7 @@ public class DynamicLodTemplate extends AbstractLodTemplate } @Override - public int getBufferMemoryForSingleNode() + public int getBufferMemoryForSingleNode(int maxVerticalData) { return 0; } diff --git a/src/main/java/com/seibel/lod/builders/lodTemplates/TriangularLodTemplate.java b/src/main/java/com/seibel/lod/builders/lodTemplates/TriangularLodTemplate.java index 9bfd8c920..d16c76f1d 100644 --- a/src/main/java/com/seibel/lod/builders/lodTemplates/TriangularLodTemplate.java +++ b/src/main/java/com/seibel/lod/builders/lodTemplates/TriangularLodTemplate.java @@ -44,7 +44,7 @@ public class TriangularLodTemplate extends AbstractLodTemplate } @Override - public int getBufferMemoryForSingleNode() + public int getBufferMemoryForSingleNode(int maxVerticalData) { return 0; } diff --git a/src/main/java/com/seibel/lod/config/LodConfig.java b/src/main/java/com/seibel/lod/config/LodConfig.java index e825ea3ac..55512c7ea 100644 --- a/src/main/java/com/seibel/lod/config/LodConfig.java +++ b/src/main/java/com/seibel/lod/config/LodConfig.java @@ -71,8 +71,6 @@ public class LodConfig public static class Graphics { - public ForgeConfigSpec.BooleanValue drawLODs; - public ForgeConfigSpec.EnumValue fogDistance; public ForgeConfigSpec.EnumValue fogDrawOverride; @@ -93,13 +91,6 @@ public class LodConfig { builder.comment("These settings control how the LODs look.").push(this.getClass().getSimpleName()); - drawLODs = builder - .comment("\n\n" - + " If false LODs will not be drawn, \n" - + " however they will still be generated \n" - + " and saved to file for later use. \n") - .define("drawLODs", true); - fogDistance = builder .comment("\n\n" + " At what distance should Fog be drawn on the LODs? \n" diff --git a/src/main/java/com/seibel/lod/enums/LodTemplate.java b/src/main/java/com/seibel/lod/enums/LodTemplate.java index ee4a1b56e..4815563fa 100644 --- a/src/main/java/com/seibel/lod/enums/LodTemplate.java +++ b/src/main/java/com/seibel/lod/enums/LodTemplate.java @@ -54,8 +54,8 @@ public enum LodTemplate } - public int getBufferMemoryForSingleLod() + public int getBufferMemoryForSingleLod(int maxVerticalData) { - return template.getBufferMemoryForSingleNode(); + return template.getBufferMemoryForSingleNode(maxVerticalData); } } diff --git a/src/main/java/com/seibel/lod/mixin/MixinWorldRenderer.java b/src/main/java/com/seibel/lod/mixin/MixinWorldRenderer.java index a804962e3..d03879a88 100644 --- a/src/main/java/com/seibel/lod/mixin/MixinWorldRenderer.java +++ b/src/main/java/com/seibel/lod/mixin/MixinWorldRenderer.java @@ -17,6 +17,7 @@ */ package com.seibel.lod.mixin; +import com.seibel.lod.proxy.ClientProxy; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -57,7 +58,7 @@ public class MixinWorldRenderer { // only render if LODs are enabled and // only render before solid blocks - if (LodConfig.CLIENT.graphics.drawLODs.get() && renderType.equals(RenderType.solid())) + if (ClientProxy.drawLods && renderType.equals(RenderType.solid())) LodMain.client_proxy.renderLods(matrixStackIn, previousPartialTicks); } } diff --git a/src/main/java/com/seibel/lod/objects/LevelContainer.java b/src/main/java/com/seibel/lod/objects/LevelContainer.java index a60bef3d2..b019d34e8 100644 --- a/src/main/java/com/seibel/lod/objects/LevelContainer.java +++ b/src/main/java/com/seibel/lod/objects/LevelContainer.java @@ -76,4 +76,17 @@ public interface LevelContainer * @return data as a String */ public byte[] toDataString(); + + + /** + * This will give the data to save in the file + * @return data as a String + */ + public int getMaxNumberOfLods(); + + /** + * This will give the data to save in the file + * @return data as a String + */ + public int getMaxMemoryUse(); } diff --git a/src/main/java/com/seibel/lod/objects/LodDimension.java b/src/main/java/com/seibel/lod/objects/LodDimension.java index 272ffca2d..39a6b1afe 100644 --- a/src/main/java/com/seibel/lod/objects/LodDimension.java +++ b/src/main/java/com/seibel/lod/objects/LodDimension.java @@ -49,9 +49,9 @@ import net.minecraft.world.server.ServerWorld; */ public class LodDimension { - + public final DimensionType dimension; - + /** * measured in regions */ @@ -60,28 +60,34 @@ public class LodDimension * measured in regions */ private volatile int halfWidth; - + // these three variables are private to force use of the getWidth() method // which is a safer way to get the width then directly asking the arrays - /** stores all the regions in this dimension */ - private volatile LodRegion[][] regions; - /** stores if the region at the given x and z index needs to be saved to disk */ + /** + * stores all the regions in this dimension + */ + public volatile LodRegion[][] regions; + /** + * stores if the region at the given x and z index needs to be saved to disk + */ private volatile boolean[][] isRegionDirty; - /** stores if the region at the given x and z index needs to be regenerated */ + /** + * stores if the region at the given x and z index needs to be regenerated + */ private volatile boolean[][] regionNeedsRegen; - + /** * if true that means there are regions in this dimension * that need to have their buffers rebuilt. */ public volatile boolean regenDimension = false; - + private volatile RegionPos center; private volatile ChunkPos lastGenChunk; private volatile ChunkPos lastCutChunk; private LodDimensionFileHandler fileHandler; private ExecutorService cutAndGenThreads = Executors.newSingleThreadExecutor(new LodThreadFactory(this.getClass().getSimpleName() + " - cutAndGen")); - + /** * Creates the dimension centered at (0,0) * @@ -99,14 +105,14 @@ public class LodDimension { try { - + File saveDir; if (mc.hasSingleplayerServer()) { // local world - + ServerWorld serverWorld = LodUtil.getServerWorldFromDimension(newDimension); - + // provider needs a separate variable to prevent // the compiler from complaining ServerChunkProvider provider = serverWorld.getChunkSource(); @@ -114,11 +120,11 @@ public class LodDimension } else { // connected to server - + saveDir = new File(mc.getGameDirectory().getCanonicalFile().getPath() + - File.separatorChar + "lod server data" + File.separatorChar + mc.getCurrentDimensionId()); + File.separatorChar + "lod server data" + File.separatorChar + mc.getCurrentDimensionId()); } - + fileHandler = new LodDimensionFileHandler(saveDir, this); } catch (IOException e) { @@ -126,23 +132,23 @@ public class LodDimension // we won't be able to read or write any files } } - - + + regions = new LodRegion[width][width]; isRegionDirty = new boolean[width][width]; regionNeedsRegen = new boolean[width][width]; - + //treeGenerator((int) mc.player.getX(),(int) mc.player.getZ()); - + // populate isRegionDirty for (int i = 0; i < width; i++) for (int j = 0; j < width; j++) isRegionDirty[i][j] = false; - + center = new RegionPos(0, 0); } - - + + /** * Move the center of this LodDimension and move all owned * regions over by the given x and z offset.

@@ -153,7 +159,7 @@ public class LodDimension { int xOffset = regionOffset.x; int zOffset = regionOffset.z; - + // if the x or z offset is equal to or greater than // the total size, just delete the current data // and update the centerX and/or centerZ @@ -166,15 +172,15 @@ public class LodDimension regions[x][z] = null; } } - + // update the new center center.x += xOffset; center.z += zOffset; - + return; } - - + + // X if (xOffset > 0) { @@ -205,8 +211,8 @@ public class LodDimension } } } - - + + // Z if (zOffset > 0) { @@ -235,14 +241,14 @@ public class LodDimension } } } - - + + // update the new center center.x += xOffset; center.z += zOffset; } - - + + /** * return needed memory in bytes */ @@ -250,7 +256,7 @@ public class LodDimension { int count = 0; LodRegion region; - + for (int x = 0; x < regions.length; x++) { for (int z = 0; z < regions.length; z++) @@ -258,14 +264,14 @@ public class LodDimension region = regions[x][z]; if (region != null) { - count += region.getMinMemoryNeeded(); + count += region.getMinMemoryNeeded(LodConfig.CLIENT.graphics.lodTemplate.get()); } } } return count; } - - + + /** * Gets the region at the given X and Z *
@@ -278,19 +284,19 @@ public class LodDimension int zRegion = LevelPosUtil.getRegion(detailLevel, posZ); int xIndex = (xRegion - center.x) + halfWidth; int zIndex = (zRegion - center.z) + halfWidth; - + if (!regionIsInRange(xRegion, zRegion)) return null; - //throw new ArrayIndexOutOfBoundsException("Region for level pos " + LevelPosUtil.toString(detailLevel, posX, posZ) + " out of range"); + //throw new ArrayIndexOutOfBoundsException("Region for level pos " + LevelPosUtil.toString(detailLevel, posX, posZ) + " out of range"); else if (regions[xIndex][zIndex] == null) return null; - //throw new InvalidParameterException("Region for level pos " + LevelPosUtil.toString(detailLevel, posX, posZ) + " not currently initialized"); + //throw new InvalidParameterException("Region for level pos " + LevelPosUtil.toString(detailLevel, posX, posZ) + " not currently initialized"); else if (regions[xIndex][zIndex].getMinDetailLevel() > detailLevel) return null; //throw new InvalidParameterException("Region for level pos " + LevelPosUtil.toString(detailLevel, posX, posZ) + " currently only reach level " + regions[xIndex][zIndex].getMinDetailLevel()); return regions[xIndex][zIndex]; } - + /** * Gets the region at the given X and Z *
@@ -301,22 +307,24 @@ public class LodDimension { int xIndex = (regionPosX - center.x) + halfWidth; int zIndex = (regionPosZ - center.z) + halfWidth; - + if (!regionIsInRange(regionPosX, regionPosZ)) return null; - //throw new ArrayIndexOutOfBoundsException("Region " + regionPosX + " " + regionPosZ + " out of range"); + //throw new ArrayIndexOutOfBoundsException("Region " + regionPosX + " " + regionPosZ + " out of range"); else if (regions[xIndex][zIndex] == null) return null; //throw new InvalidParameterException("Region " + regionPosX + " " + regionPosZ + " not currently initialized"); return regions[xIndex][zIndex]; } - - /** Useful when needing to iterate over every region. */ + + /** + * Useful when needing to iterate over every region. + */ public LodRegion getRegionByArrayIndex(int xIndex, int zIndex) { return regions[xIndex][zIndex]; } - + /** * Overwrite the LodRegion at the location of newRegion with newRegion. * @@ -326,15 +334,15 @@ public class LodDimension { int xIndex = (newRegion.regionPosX - center.x) + halfWidth; int zIndex = (newRegion.regionPosZ - center.z) + halfWidth; - + if (!regionIsInRange(newRegion.regionPosX, newRegion.regionPosZ)) // out of range throw new ArrayIndexOutOfBoundsException("Region " + newRegion.regionPosX + ", " + newRegion.regionPosZ + " out of range"); - + regions[xIndex][zIndex] = newRegion; } - - + + /** * */ @@ -353,7 +361,7 @@ public class LodDimension int minDistance; byte detail; byte levelToCut; - + for (int x = 0; x < regions.length; x++) { for (int z = 0; z < regions.length; z++) @@ -373,15 +381,15 @@ public class LodDimension regions[x][z].cutTree(levelToCut); } } - + }// region z }// region z - + }); cutAndGenThreads.execute(thread); } } - + /** * */ @@ -390,7 +398,7 @@ public class LodDimension DistanceGenerationMode generationMode = LodConfig.CLIENT.worldGenerator.distanceGenerationMode.get(); ChunkPos newPlayerChunk = new ChunkPos(LevelPosUtil.getChunkPos((byte) 0, playerPosX), LevelPosUtil.getChunkPos((byte) 0, playerPosZ)); VerticalQuality verticalQuality = LodConfig.CLIENT.worldGenerator.lodQualityMode.get(); - + if (lastGenChunk == null) lastGenChunk = new ChunkPos(newPlayerChunk.x + 1, newPlayerChunk.z - 1); if (newPlayerChunk.x != lastGenChunk.x || newPlayerChunk.z != lastGenChunk.z) @@ -413,17 +421,17 @@ public class LodDimension final RegionPos regionPos = new RegionPos(regionX, regionZ); region = regions[x][z]; //We require that the region we are checking is loaded with at least this level - + minDistance = LevelPosUtil.minDistance(LodUtil.REGION_DETAIL_LEVEL, regionX, regionZ, playerPosX, playerPosZ); detail = DetailDistanceUtil.getTreeGenDetailFromDistance(minDistance); levelToGen = DetailDistanceUtil.getLodGenDetail(detail).detailLevel; if (region == null || region.getGenerationMode() != generationMode) { //First case, region has to be initialized - + //We check if there is a file at the target level regions[x][z] = getRegionFromFile(regionPos, levelToGen, generationMode, verticalQuality); - + //if there is no file we initialize the region if (regions[x][z] == null) { @@ -431,7 +439,7 @@ public class LodDimension } regionNeedsRegen[x][z] = true; regenDimension = true; - + } else if (region.getMinDetailLevel() > levelToGen) { //Second case, region has been initialized but at a higher level @@ -481,8 +489,8 @@ public class LodDimension } return nodeAdded; } - - + + /** * Add the given LOD to this dimension at the coordinate * stored in the LOD. If an LOD already exists at the given @@ -490,11 +498,11 @@ public class LodDimension */ public Boolean addSingleData(byte detailLevel, int posX, int posZ, long dataPoint, boolean dontSave, boolean serverQuality) { - + // don't continue if the region can't be saved int regionPosX = LevelPosUtil.getRegion(detailLevel, posX); int regionPosZ = LevelPosUtil.getRegion(detailLevel, posZ); - + LodRegion region = getRegion(regionPosX, regionPosZ); if (region == null) return false; @@ -519,14 +527,14 @@ public class LodDimension } return nodeAdded; } - + public void setToRegen(int xRegion, int zRegion) { int xIndex = (xRegion - center.x) + halfWidth; int zIndex = (zRegion - center.z) + halfWidth; regionNeedsRegen[xIndex][zIndex] = true; } - + /** * method to get all the quadtree level that have to be generated based on the position of the player * @@ -548,12 +556,12 @@ public class LodDimension region = getRegion(xIndex, zIndex); if (region != null) region.getDataToGenerate(posToGenerate, playerPosX, playerPosZ); - + } } return posToGenerate; } - + /** * method to get all the nodes that have to be rendered based on the position of the player * @@ -592,14 +600,14 @@ public class LodDimension { if (detailLevel > LodUtil.REGION_DETAIL_LEVEL) throw new IllegalArgumentException("getLodFromCoordinates given a level of \"" + detailLevel + "\" when \"" + LodUtil.REGION_DETAIL_LEVEL + "\" is the max."); - + LodRegion region = getRegion(detailLevel, posX, posZ); - + if (region == null) { return DataPointUtil.EMPTY_DATA; } - + return region.getData(detailLevel, posX, posZ, verticalIndex); } @@ -615,14 +623,14 @@ public class LodDimension { if (detailLevel > LodUtil.REGION_DETAIL_LEVEL) throw new IllegalArgumentException("getLodFromCoordinates given a level of \"" + detailLevel + "\" when \"" + LodUtil.REGION_DETAIL_LEVEL + "\" is the max."); - + LodRegion region = getRegion(detailLevel, posX, posZ); - + if (region == null) { return DataPointUtil.EMPTY_DATA; } - + return region.getSingleData(detailLevel, posX, posZ); } @@ -640,17 +648,17 @@ public class LodDimension region.clear(detailLevel, posX, posZ); } - + public boolean getRegenByArrayIndex(int xIndex, int zIndex) { return regionNeedsRegen[xIndex][zIndex]; } - + public void setRegenByArrayIndex(int xIndex, int zIndex, boolean newRegen) { regionNeedsRegen[xIndex][zIndex] = newRegen; } - + /** * Get the data point at the given X and Z coordinates * in this dimension. @@ -662,32 +670,32 @@ public class LodDimension { if (detailLevel > LodUtil.REGION_DETAIL_LEVEL) throw new IllegalArgumentException("getLodFromCoordinates given a level of \"" + detailLevel + "\" when \"" + LodUtil.REGION_DETAIL_LEVEL + "\" is the max."); - + LodRegion region = getRegion(detailLevel, posX, posZ); - - + + if (region == null) { return; } region.updateArea(detailLevel, posX, posZ); } - + /** * return true if and only if the node at that position exist */ public boolean doesDataExist(byte detailLevel, int posX, int posZ) { LodRegion region = getRegion(detailLevel, posX, posZ); - + if (region == null) { return false; } - + return region.doesDataExist(detailLevel, posX, posZ); } - + /** * Get the region at the given X and Z coordinates from the * RegionFileHandler. @@ -699,7 +707,7 @@ public class LodDimension else return null; } - + /** * Save all dirty regions in this LodDimension to file. */ @@ -707,8 +715,8 @@ public class LodDimension { fileHandler.saveDirtyRegionsToFileAsync(); } - - + + /** * Returns whether the region at the given X and Z coordinates * is within the loaded range. @@ -717,22 +725,24 @@ public class LodDimension { int xIndex = (regionX - center.x) + halfWidth; int zIndex = (regionZ - center.z) + halfWidth; - + return xIndex >= 0 && xIndex < width && zIndex >= 0 && zIndex < width; } - - + + public int getCenterX() { return center.x; } - + public int getCenterZ() { return center.z; } - - /** returns the width of the dimension in regions */ + + /** + * returns the width of the dimension in regions + */ public int getWidth() { if (regions != null) @@ -746,29 +756,29 @@ public class LodDimension return width; } } - - + + public void setRegionWidth(int newWidth) { width = newWidth; halfWidth = Math.floorDiv(width, 2); - + regions = new LodRegion[width][width]; isRegionDirty = new boolean[width][width]; regionNeedsRegen = new boolean[width][width]; - + // populate isRegionDirty for (int i = 0; i < width; i++) for (int j = 0; j < width; j++) isRegionDirty[i][j] = false; } - - + + @Override public String toString() { LodRegion region; - + StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("Dimension : \n"); for (int x = 0; x < regions.length; x++) @@ -780,7 +790,7 @@ public class LodDimension { stringBuilder.append("n"); stringBuilder.append("\t"); - + } else { stringBuilder.append(region.getMinDetailLevel()); @@ -792,4 +802,15 @@ public class LodDimension return stringBuilder.toString(); } + public int getMemoryRequired(int x, int z) + { + int minDistance = LevelPosUtil.minDistance(LodUtil.REGION_DETAIL_LEVEL, x, z, halfWidth, halfWidth); + int detail = DetailDistanceUtil.getGenerationDetailFromDistance(minDistance); + int levelToGen = DetailDistanceUtil.getLodGenDetail(detail).detailLevel; + int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - levelToGen); + int maxVerticalData = DetailDistanceUtil.getMaxVerticalData(levelToGen); + int numberOfLods = size * size * maxVerticalData; + int memoryUse = numberOfLods * LodConfig.CLIENT.graphics.lodTemplate.get().getBufferMemoryForSingleLod(maxVerticalData); + return memoryUse; + } } diff --git a/src/main/java/com/seibel/lod/objects/LodRegion.java b/src/main/java/com/seibel/lod/objects/LodRegion.java index f1d3855e7..c722e402f 100644 --- a/src/main/java/com/seibel/lod/objects/LodRegion.java +++ b/src/main/java/com/seibel/lod/objects/LodRegion.java @@ -2,6 +2,7 @@ package com.seibel.lod.objects; import com.seibel.lod.enums.DistanceGenerationMode; +import com.seibel.lod.enums.LodTemplate; import com.seibel.lod.enums.VerticalQuality; import com.seibel.lod.proxy.ClientProxy; import com.seibel.lod.util.DataPointUtil; @@ -466,8 +467,9 @@ public class LodRegion /** * return needed memory in byte + * @param template */ - public int getMinMemoryNeeded() + public int getMinMemoryNeeded(LodTemplate template) { int count = 0; for (byte tempLod = LodUtil.REGION_DETAIL_LEVEL; tempLod > minDetailLevel; tempLod--) @@ -475,7 +477,7 @@ public class LodRegion //i'm doing a upper limit of the minimum //Color should be just 3 byte but i'm gonna calculate as 12 byte //Height and depth should be just 4 byte but i'm gonna calculate as 8 byte - count += Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - tempLod) * (8 + 3 + 2 + 2 + 1); + count += dataContainer[tempLod].getMaxMemoryUse() * template.getBufferMemoryForSingleLod(dataContainer[tempLod].getMaxVerticalData()); //count += Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - tempLod) * (24 + 8 + 8 + 8 + 8); } return count; @@ -486,4 +488,11 @@ public class LodRegion { return getLevel(LodUtil.REGION_DETAIL_LEVEL).toString(); } + + public int getNumberOfLods(){ + int count = 0; + for(LevelContainer container : dataContainer) + count += container.getMaxNumberOfLods(); + return count; + } } diff --git a/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java b/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java index c631b2515..e07700bc7 100644 --- a/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java +++ b/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java @@ -166,4 +166,13 @@ public class SingleLevelContainer implements LevelContainer stringBuilder.append(detailLevel); return stringBuilder.toString(); } + + + public int getMaxNumberOfLods(){ + return size*size*getMaxVerticalData(); + } + + public int getMaxMemoryUse(){ + return getMaxNumberOfLods() * 2; //2 byte + } } diff --git a/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java b/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java index edd759d3c..0b9b54982 100644 --- a/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java +++ b/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java @@ -205,4 +205,12 @@ public class VerticalLevelContainer implements LevelContainer */ return " "; } + + public int getMaxNumberOfLods(){ + return size*size*getMaxVerticalData(); + } + + public int getMaxMemoryUse(){ + return getMaxNumberOfLods() * 2; //2 byte + } } diff --git a/src/main/java/com/seibel/lod/proxy/ClientProxy.java b/src/main/java/com/seibel/lod/proxy/ClientProxy.java index 54427f245..fb43e4b5e 100644 --- a/src/main/java/com/seibel/lod/proxy/ClientProxy.java +++ b/src/main/java/com/seibel/lod/proxy/ClientProxy.java @@ -58,6 +58,7 @@ public class ClientProxy public static final Logger LOGGER = LogManager.getLogger("LOD"); private boolean firstTimeSetupComplete = false; + public static boolean drawLods = true; private static LodWorld lodWorld = new LodWorld(); private static LodBuilder lodBuilder = new LodBuilder(); @@ -144,7 +145,7 @@ public class ClientProxy profiler.pop(); // get out of "terrain" profiler.push("LOD"); - if(LodConfig.CLIENT.graphics.drawLODs.get()) + if(drawLods) { renderer.drawLODs(lodDim, mcMatrixStack, partialTicks, mc.getProfiler()); } @@ -297,7 +298,7 @@ public class ClientProxy if(LodConfig.CLIENT.debugging.enableDebugKeybinding.get() && event.getKey() == GLFW.GLFW_KEY_F6 && event.getAction() == GLFW.GLFW_PRESS) { - LodConfig.CLIENT.graphics.drawLODs.set(!LodConfig.CLIENT.graphics.drawLODs.get()); + drawLods = !drawLods; } } @@ -340,7 +341,7 @@ public class ClientProxy // update the dimensions to fit the new width lodWorld.resizeDimensionRegionWidth(newWidth); lodBuilder.defaultDimensionWidthInRegions = newWidth; - renderer.setupBuffers(newWidth); + renderer.setupBuffers(newWidth, lodWorld.getLodDimension(mc.getClientWorld().dimensionType())); recalculateWidths = false; //LOGGER.info("new dimension width in regions: " + newWidth + "\t potential: " + newWidth ); diff --git a/src/main/java/com/seibel/lod/render/LodRenderer.java b/src/main/java/com/seibel/lod/render/LodRenderer.java index 20ae3c16b..d4bd5bb5e 100644 --- a/src/main/java/com/seibel/lod/render/LodRenderer.java +++ b/src/main/java/com/seibel/lod/render/LodRenderer.java @@ -589,21 +589,21 @@ public class LodRenderer /** * Create all buffers that will be used. */ - public void setupBuffers(int numbRegionsWide) + public void setupBuffers(int numbRegionsWide, LodDimension lodDim) { // calculate the max amount of memory needed (in bytes) - int bufferMemory = RenderUtil.getBufferMemoryForRegion(); + /*int bufferMemory = RenderUtil.getBufferMemoryForRegion(lodDim);*/ // if the required memory is greater than the // MAX_ALOCATEABLE_DIRECT_MEMORY lower the lodChunkRadiusMultiplier // to fit. - if (bufferMemory > MAX_ALOCATEABLE_DIRECT_MEMORY) + /*if (bufferMemory > MAX_ALOCATEABLE_DIRECT_MEMORY) { ClientProxy.LOGGER.warn("setupBuffers tried to allocate too much memory for the BufferBuilders." + " It tried to allocate \"" + bufferMemory + "\" bytes, when \"" + MAX_ALOCATEABLE_DIRECT_MEMORY + "\" is the max."); - } + }*/ - lodBufferBuilder.setupBuffers(numbRegionsWide, bufferMemory); + lodBufferBuilder.setupBuffers(numbRegionsWide, lodDim); } diff --git a/src/main/java/com/seibel/lod/render/RenderUtil.java b/src/main/java/com/seibel/lod/render/RenderUtil.java index 2c474d519..182770ff4 100644 --- a/src/main/java/com/seibel/lod/render/RenderUtil.java +++ b/src/main/java/com/seibel/lod/render/RenderUtil.java @@ -19,6 +19,8 @@ package com.seibel.lod.render; import com.seibel.lod.config.LodConfig; import com.seibel.lod.enums.LodTemplate; +import com.seibel.lod.objects.LodRegion; +import com.seibel.lod.util.DetailDistanceUtil; import com.seibel.lod.util.LodUtil; import com.seibel.lod.wrappers.MinecraftWrapper; @@ -89,24 +91,23 @@ public class RenderUtil * it is possible (albeit unlikely) to have a buffer indexOutOfBounds exception * which is caused by the buffer not being big enough. */ - public static int getBufferMemoryForRegion() + public static int getBufferMemoryForRegion(LodRegion region) { // calculate the max amount of buffer memory needed (in bytes) - return LodUtil.REGION_WIDTH_IN_CHUNKS * LodUtil.REGION_WIDTH_IN_CHUNKS * 6 * // TODO this really needs to be more accurate - LodConfig.CLIENT.graphics.lodTemplate.get().getBufferMemoryForSingleLod() * LodUtil.MAX_VERTICAL_DATA; + return region.getMinMemoryNeeded(LodConfig.CLIENT.graphics.lodTemplate.get()); } /** * Returns the maxViewDistanceMultiplier for the given LodTemplate * at the given LodDetail level. */ - public static int getMaxRadiusMultiplierWithAvaliableMemory(LodTemplate lodTemplate, int detailLevel) + /*public static int getMaxRadiusMultiplierWithAvaliableMemory(LodTemplate lodTemplate, int detailLevel) { int maxNumberOfLods = LodRenderer.MAX_ALOCATEABLE_DIRECT_MEMORY / lodTemplate.getBufferMemoryForSingleLod(); int numbLodsWide = (int) Math.sqrt(maxNumberOfLods); return numbLodsWide / (2 * mc.getRenderDistance()); - } + }*/ /**