diff --git a/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EDhApiGpuUploadMethod.java b/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EDhApiGpuUploadMethod.java
index df4c4a767..8b6b737f8 100644
--- a/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EDhApiGpuUploadMethod.java
+++ b/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EDhApiGpuUploadMethod.java
@@ -23,13 +23,12 @@ package com.seibel.distanthorizons.api.enums.config;
* AUTO,
* BUFFER_STORAGE,
* SUB_DATA,
- * BUFFER_MAPPING,
* DATA
*
* @author Leetom
* @author James Seibel
* @version 2024-4-6
- * @since API 2.0.0
+ * @since API 3.0.0
*/
public enum EDhApiGpuUploadMethod
{
@@ -49,7 +48,10 @@ public enum EDhApiGpuUploadMethod
* May end up storing buffers in System memory.
* Fast rending if in GPU memory, slow if in system memory,
* but won't stutter when uploading.
+ *
+ * @deprecated not currently supported
*/
+ @Deprecated
BUFFER_MAPPING(true, false),
/** Fast rendering but may stutter when uploading. */
diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/IDhApiConfig.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/IDhApiConfig.java
index a0f81b499..fd7a5b8b4 100644
--- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/IDhApiConfig.java
+++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/IDhApiConfig.java
@@ -36,7 +36,6 @@ public interface IDhApiConfig
IDhApiWorldGenerationConfig worldGenerator();
IDhApiMultiplayerConfig multiplayer();
IDhApiMultiThreadingConfig multiThreading();
- IDhApiGpuBuffersConfig gpuBuffers();
// note: DON'T add the Auto Updater to this API. We only want the user's to have the ability to control when things are downloaded to their machines.
//IDhApiLoggingConfig logging(); // TODO implement
IDhApiDebuggingConfig debugging();
diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/client/IDhApiGpuBuffersConfig.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/client/IDhApiGpuBuffersConfig.java
deleted file mode 100644
index 4b0433f7a..000000000
--- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/client/IDhApiGpuBuffersConfig.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * This file is part of the Distant Horizons mod
- * licensed under the GNU LGPL v3 License.
- *
- * Copyright (C) 2020-2023 James Seibel
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, version 3.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.seibel.distanthorizons.api.interfaces.config.client;
-
-import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod;
-import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigGroup;
-import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigValue;
-
-/**
- * Distant Horizons' OpenGL buffer configuration.
- *
- * @author James Seibel
- * @version 2023-6-14
- * @since API 1.0.0
- */
-public interface IDhApiGpuBuffersConfig extends IDhApiConfigGroup
-{
-
- /** Defines how geometry data is uploaded to the GPU. */
- IDhApiConfigValue gpuUploadMethod();
-
- /**
- * Defines how long we should wait after uploading one
- * Megabyte of geometry data to the GPU before uploading
- * the next Megabyte of data.
- * This can be set to a non-zero number to reduce stuttering caused by
- * uploading buffers to the GPU.
- */
- IDhApiConfigValue gpuUploadPerMegabyteInMilliseconds();
-
-}
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/DhApiConfig.java b/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/DhApiConfig.java
index 5197f7b46..1abbf6d32 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/DhApiConfig.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/DhApiConfig.java
@@ -42,8 +42,6 @@ public class DhApiConfig implements IDhApiConfig
@Override
public IDhApiMultiThreadingConfig multiThreading() { return DhApiMultiThreadingConfig.INSTANCE; }
@Override
- public IDhApiGpuBuffersConfig gpuBuffers() { return DhApiGpuBuffersConfig.INSTANCE; }
- @Override
public IDhApiDebuggingConfig debugging() { return DhApiDebuggingConfig.INSTANCE; }
}
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/client/DhApiGpuBuffersConfig.java b/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/client/DhApiGpuBuffersConfig.java
deleted file mode 100644
index 22f4852b0..000000000
--- a/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/client/DhApiGpuBuffersConfig.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * This file is part of the Distant Horizons mod
- * licensed under the GNU LGPL v3 License.
- *
- * Copyright (C) 2020-2023 James Seibel
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, version 3.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.seibel.distanthorizons.core.api.external.methods.config.client;
-
-import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigValue;
-import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiGpuBuffersConfig;
-import com.seibel.distanthorizons.api.objects.config.DhApiConfigValue;
-import com.seibel.distanthorizons.core.config.Config;
-import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod;
-
-public class DhApiGpuBuffersConfig implements IDhApiGpuBuffersConfig
-{
- public static DhApiGpuBuffersConfig INSTANCE = new DhApiGpuBuffersConfig();
-
- private DhApiGpuBuffersConfig() { }
-
-
-
- public IDhApiConfigValue gpuUploadMethod()
- { return new DhApiConfigValue<>(Config.Client.Advanced.GpuBuffers.gpuUploadMethod); }
-
- public IDhApiConfigValue gpuUploadPerMegabyteInMilliseconds()
- { return new DhApiConfigValue<>(Config.Client.Advanced.GpuBuffers.gpuUploadPerMegabyteInMilliseconds); }
-
-}
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java
index b6c2448dd..463ebcbea 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java
@@ -125,7 +125,6 @@ public class Config
public static ConfigCategory multiplayer = new ConfigCategory.Builder().set(Multiplayer.class).build();
public static ConfigCategory lodBuilding = new ConfigCategory.Builder().set(LodBuilding.class).build();
public static ConfigCategory multiThreading = new ConfigCategory.Builder().set(MultiThreading.class).build();
- public static ConfigCategory buffers = new ConfigCategory.Builder().set(GpuBuffers.class).build();
public static ConfigCategory autoUpdater = new ConfigCategory.Builder().set(AutoUpdater.class).build();
public static ConfigCategory logging = new ConfigCategory.Builder().set(Logging.class).build();
@@ -1072,53 +1071,6 @@ public class Config
}
- public static class GpuBuffers
- {
- public static ConfigEntry gpuUploadMethod = new ConfigEntry.Builder()
- .set(EDhApiGpuUploadMethod.AUTO)
- .comment(""
- + "What method should be used to upload geometry to the GPU? \n"
- + "\n"
- + EDhApiGpuUploadMethod.AUTO + ": Picks the best option based on the GPU you have. \n"
- + "\n"
- + EDhApiGpuUploadMethod.BUFFER_STORAGE + ": Default if OpenGL 4.5 is supported. \n"
- + " Fast rendering, no stuttering. \n"
- + "\n"
- + EDhApiGpuUploadMethod.SUB_DATA + ": Backup option for NVIDIA. \n"
- + " Fast rendering but may stutter when uploading. \n"
- + "\n"
- + EDhApiGpuUploadMethod.BUFFER_MAPPING + ": Slow rendering but won't stutter when uploading. \n"
- + " Generally the best option for integrated GPUs. \n"
- + " Default option for AMD/Intel if OpenGL 4.5 isn't supported. \n"
- + " May end up storing buffers in System memory. \n"
- + " Fast rendering if in GPU memory, slow if in system memory, \n"
- + " but won't stutter when uploading. \n"
- + "\n"
- + EDhApiGpuUploadMethod.DATA + ": Fast rendering but will stutter when uploading. \n"
- + " Backup option for AMD/Intel. \n"
- + " Fast rendering but may stutter when uploading. \n"
- + "\n"
- + "If you don't see any difference when changing these settings, \n"
- + "or the world looks corrupted: restart your game."
- + "")
- .build();
-
- public static ConfigEntry gpuUploadPerMegabyteInMilliseconds = new ConfigEntry.Builder()
- .setMinDefaultMax(0, 0, 50)
- .comment(""
- + "How long should a buffer wait per Megabyte of data uploaded? \n"
- + "Helpful resource for frame times: https://fpstoms.com \n"
- + "\n"
- + "Longer times may reduce stuttering but will make LODs \n"
- + "transition and load slower. Change this to [0] for no timeout. \n"
- + "\n"
- + "NOTE:\n"
- + "Before changing this config, try changing the \"GPU Upload method\" first. \n"
- + "")
- .build();
-
- }
-
public static class AutoUpdater
{
public static ConfigEntry enableAutoUpdater = new ConfigEntry.Builder()
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBuffer.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBuffer.java
index 6b6807787..833e0cf8b 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBuffer.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBuffer.java
@@ -36,7 +36,7 @@ import org.apache.logging.log4j.Logger;
import org.lwjgl.system.MemoryUtil;
import java.nio.ByteBuffer;
-import java.util.Iterator;
+import java.util.ArrayList;
import java.util.concurrent.*;
/**
@@ -101,7 +101,7 @@ public class ColumnRenderBuffer implements AutoCloseable
{
try
{
- this.uploadBuffersUsingUploadMethod(builder, gpuUploadMethod);
+ this.uploadBuffers(builder, gpuUploadMethod);
uploadFuture.complete(null);
}
catch (InterruptedException e)
@@ -127,72 +127,46 @@ public class ColumnRenderBuffer implements AutoCloseable
//LOGGER.warn("Error uploading builder ["+builder+"] synchronously. Error: "+e.getMessage(), e);
}
}
- private void uploadBuffersUsingUploadMethod(LodQuadBuilder builder, EDhApiGpuUploadMethod gpuUploadMethod) throws InterruptedException
+ private void uploadBuffers(LodQuadBuilder builder, EDhApiGpuUploadMethod method) throws InterruptedException
{
- if (gpuUploadMethod.useEarlyMapping)
- {
- this.uploadBuffersMapped(builder, gpuUploadMethod);
- }
- else
- {
- this.uploadBuffersDirect(builder, gpuUploadMethod);
- }
+ // uploading mapped buffers used to be done here,
+ // however due to a memory leak and complication with the previous code,
+ // now we only allow direct uploading.
+ // (There's also insufficient data to state whether mapped buffers are necessary
+ // for DH to upload without stuttering the main thread)
+
+ this.vbos = makeAndUploadBuffers(builder, method, this.vbos, builder.makeOpaqueVertexBuffers());
+ this.vbosTransparent = makeAndUploadBuffers(builder, method, this.vbosTransparent, builder.makeTransparentVertexBuffers());
this.buffersUploaded = true;
}
-
-
-
- private void uploadBuffersMapped(LodQuadBuilder builder, EDhApiGpuUploadMethod method)
+ /** This resizes and returns the vbo array if necessary based on the amount of data needed for this area. */
+ private static GLVertexBuffer[] makeAndUploadBuffers(LodQuadBuilder builder, EDhApiGpuUploadMethod method, GLVertexBuffer[] vbos, ArrayList buffers) throws InterruptedException
{
- // opaque vbos //
-
- this.vbos = resizeBuffer(this.vbos, builder.getCurrentNeededOpaqueVertexBufferCount());
- for (int i = 0; i < this.vbos.length; i++)
+ try
{
- if (this.vbos[i] == null)
+ vbos = resizeBuffer(vbos, buffers.size());
+ uploadBuffersDirect(vbos, buffers, method);
+ }
+ finally
+ {
+ // all the buffers must be manually freed to prevent memory leaks
+ if (buffers != null)
{
- this.vbos[i] = new GLVertexBuffer(method.useBufferStorage);
+ for (ByteBuffer buffer : buffers)
+ {
+ MemoryUtil.memFree(buffer);
+ }
}
}
- LodQuadBuilder.BufferFiller func = builder.makeOpaqueBufferFiller(method);
- for (GLVertexBuffer vbo : this.vbos)
- {
- func.fill(vbo);
- }
-
- // transparent vbos //
-
- this.vbosTransparent = resizeBuffer(this.vbosTransparent, builder.getCurrentNeededTransparentVertexBufferCount());
- for (int i = 0; i < this.vbosTransparent.length; i++)
- {
- if (this.vbosTransparent[i] == null)
- {
- this.vbosTransparent[i] = new GLVertexBuffer(method.useBufferStorage);
- }
- }
- LodQuadBuilder.BufferFiller transparentFillerFunc = builder.makeTransparentBufferFiller(method);
- for (GLVertexBuffer vbo : this.vbosTransparent)
- {
- transparentFillerFunc.fill(vbo);
- }
+ // return the array in case it was resized
+ return vbos;
}
-
- private void uploadBuffersDirect(LodQuadBuilder builder, EDhApiGpuUploadMethod method) throws InterruptedException
+ private static void uploadBuffersDirect(GLVertexBuffer[] vbos, ArrayList byteBuffers, EDhApiGpuUploadMethod method) throws InterruptedException
{
- this.vbos = resizeBuffer(this.vbos, builder.getCurrentNeededOpaqueVertexBufferCount());
- uploadBuffersDirect(this.vbos, builder.makeOpaqueVertexBuffers(), method);
-
- this.vbosTransparent = resizeBuffer(this.vbosTransparent, builder.getCurrentNeededTransparentVertexBufferCount());
- uploadBuffersDirect(this.vbosTransparent, builder.makeTransparentVertexBuffers(), method);
- }
- private static void uploadBuffersDirect(GLVertexBuffer[] vbos, Iterator iter, EDhApiGpuUploadMethod method) throws InterruptedException
- {
- long remainingMS = 0;
- long MBPerMS = Config.Client.Advanced.GpuBuffers.gpuUploadPerMegabyteInMilliseconds.get();
int vboIndex = 0;
- while (iter.hasNext())
+ for (int i = 0; i < byteBuffers.size(); i++)
{
if (vboIndex >= vbos.length)
{
@@ -208,41 +182,19 @@ public class ColumnRenderBuffer implements AutoCloseable
GLVertexBuffer vbo = vbos[vboIndex];
- ByteBuffer bb = iter.next();
- int size = bb.limit() - bb.position();
+ ByteBuffer buffer = byteBuffers.get(i);
+ int size = buffer.limit() - buffer.position();
try
{
vbo.bind();
- vbo.uploadBuffer(bb, size / LodUtil.LOD_VERTEX_FORMAT.getByteSize(), method, FULL_SIZED_BUFFER);
+ vbo.uploadBuffer(buffer, size / LodUtil.LOD_VERTEX_FORMAT.getByteSize(), method, FULL_SIZED_BUFFER);
}
catch (Exception e)
{
vbos[vboIndex] = null;
vbo.close();
LOGGER.error("Failed to upload buffer: ", e);
- }
- finally
- {
- MemoryUtil.memFree(bb);
- }
-
-
- if (MBPerMS > 0)
- {
- // upload buffers over an extended period of time
- // to hopefully prevent stuttering.
- remainingMS += size * MBPerMS;
- if (remainingMS >= TimeUnit.NANOSECONDS.convert(1000 / 60, TimeUnit.MILLISECONDS))
- {
- if (remainingMS > MAX_BUFFER_UPLOAD_TIMEOUT_NANOSECONDS)
- {
- remainingMS = MAX_BUFFER_UPLOAD_TIMEOUT_NANOSECONDS;
- }
-
- Thread.sleep(remainingMS / 1000000, (int) (remainingMS % 1000000));
- remainingMS = 0;
- }
}
vboIndex++;
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/LodQuadBuilder.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/LodQuadBuilder.java
index 12e2daf01..89cbcfec3 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/LodQuadBuilder.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/LodQuadBuilder.java
@@ -206,10 +206,124 @@ public class LodQuadBuilder
+ //=================//
+ // data finalizing //
+ //=================//
+
+ /** runs any final data cleanup, merging, etc. */
+ public void finalizeData() { this.mergeQuads(); }
+
+ /** Uses Greedy meshing to merge this builder's Quads. */
+ public void mergeQuads()
+ {
+ long mergeCount = 0; // can be used for debugging
+ long preQuadsCount = this.getCurrentOpaqueQuadsCount() + this.getCurrentTransparentQuadsCount();
+ if (preQuadsCount <= 1)
+ {
+ return;
+ }
+
+ for (int directionIndex = 0; directionIndex < 6; directionIndex++)
+ {
+ mergeCount += mergeQuadsInternal(this.opaqueQuads, directionIndex, BufferMergeDirectionEnum.EastWest);
+ if (this.doTransparency)
+ {
+ mergeCount += mergeQuadsInternal(this.transparentQuads, directionIndex, BufferMergeDirectionEnum.EastWest);
+ }
+
+
+ // only run the second merge if the face is the top or bottom
+ if (directionIndex == EDhDirection.UP.ordinal() || directionIndex == EDhDirection.DOWN.ordinal())
+ {
+ mergeCount += mergeQuadsInternal(this.opaqueQuads, directionIndex, BufferMergeDirectionEnum.NorthSouthOrUpDown);
+ if (this.doTransparency)
+ {
+ mergeCount += mergeQuadsInternal(this.transparentQuads, directionIndex, BufferMergeDirectionEnum.NorthSouthOrUpDown);
+ }
+ }
+ }
+
+ //long postQuadsCount = this.getCurrentOpaqueQuadsCount() + this.getCurrentTransparentQuadsCount();
+ //LOGGER.trace("Merged "+mergeCount+"/"+preQuadsCount+"("+(mergeCount / (double) preQuadsCount)+") quads");
+ }
+
+ /** Merges all of this builder's quads for the given directionIndex (up, down, left, etc.) in the given direction */
+ private static long mergeQuadsInternal(ArrayList[] list, int directionIndex, BufferMergeDirectionEnum mergeDirection)
+ {
+ if (list[directionIndex].size() <= 1)
+ return 0;
+
+ list[directionIndex].sort((objOne, objTwo) -> objOne.compare(objTwo, mergeDirection));
+
+ long mergeCount = 0;
+ ListIterator iter = list[directionIndex].listIterator();
+ BufferQuad currentQuad = iter.next();
+ while (iter.hasNext())
+ {
+ BufferQuad nextQuad = iter.next();
+
+ if (currentQuad.tryMerge(nextQuad, mergeDirection))
+ {
+ // merge successful, attempt to merge the next quad
+ mergeCount++;
+ iter.set(null);
+ }
+ else
+ {
+ // merge fail, move on to the next quad
+ currentQuad = nextQuad;
+ }
+ }
+ list[directionIndex].removeIf(Objects::isNull);
+ return mergeCount;
+ }
+
+
+
//==============//
- // add vertices //
+ // buffer setup //
//==============//
+ public ArrayList makeOpaqueVertexBuffers() { return this.makeVertexBuffers(this.opaqueQuads); }
+ public ArrayList makeTransparentVertexBuffers() { return this.makeVertexBuffers(this.transparentQuads); }
+ private ArrayList makeVertexBuffers(ArrayList[] quadList)
+ {
+ ArrayList byteBufferList = new ArrayList<>(3);
+
+ ByteBuffer buffer = null;
+ for (int directionIndex = 0; directionIndex < 6; directionIndex++)
+ {
+ // ignore empty directions
+ if (quadList[directionIndex].isEmpty())
+ {
+ continue;
+ }
+
+ // put all the quads in this direction into the buffer
+ for (int quadIndex = 0; quadIndex < quadList[directionIndex].size(); quadIndex++)
+ {
+ // if this is the first iteration or the buffer is full,
+ // create a new buffer
+ if (buffer == null || !buffer.hasRemaining())
+ {
+ buffer = MemoryUtil.memAlloc(ColumnRenderBuffer.FULL_SIZED_BUFFER);
+ byteBufferList.add(buffer);
+ }
+
+ this.putQuad(buffer, quadList[directionIndex].get(quadIndex));
+ }
+ }
+
+ // rewind all the buffers so they can be read from
+ for (int i = 0; i < byteBufferList.size(); i++)
+ {
+ buffer = byteBufferList.get(i);
+ buffer.limit(buffer.position());
+ buffer.rewind();
+ }
+
+ return byteBufferList;
+ }
private void putQuad(ByteBuffer bb, BufferQuad quad)
{
int[][] quadBase = DIRECTION_VERTEX_IBO_QUAD[quad.direction.ordinal()];
@@ -267,10 +381,10 @@ public class LodQuadBuilder
if (quad.direction.getAxis().isHorizontal() || quad.direction == EDhDirection.DOWN)
{
if (this.grassSideRenderingMode == EDhApiGrassSideRendering.AS_DIRT
- // if we want the color to fade, only apply the dirt color to the bottom vertices
- || (this.grassSideRenderingMode == EDhApiGrassSideRendering.FADE_TO_DIRT && quadBase[i][1] == 0)
- // always render the bottom as dirt
- || quad.direction == EDhDirection.DOWN)
+ // if we want the color to fade, only apply the dirt color to the bottom vertices
+ || (this.grassSideRenderingMode == EDhApiGrassSideRendering.FADE_TO_DIRT && quadBase[i][1] == 0)
+ // always render the bottom as dirt
+ || quad.direction == EDhDirection.DOWN)
{
// for horizontal and bottom faces of grass blocks, use the dirt color to
// prevent green cliff walls
@@ -278,7 +392,7 @@ public class LodQuadBuilder
color = ColorUtil.applyShade(color, MC.getShade(quad.direction));
}
}
- }
+ }
}
}
@@ -292,7 +406,6 @@ public class LodQuadBuilder
mx, my, mz);
}
}
-
private void putVertex(ByteBuffer bb, short x, short y, short z, int color, byte normalIndex, byte irisBlockMaterialId, byte skylight, byte blocklight, int mx, int my, int mz)
{
skylight %= 16;
@@ -333,387 +446,6 @@ public class LodQuadBuilder
- //=================//
- // data finalizing //
- //=================//
-
- /** runs any final data cleanup, merging, etc. */
- public void finalizeData() { this.mergeQuads(); }
-
- /** Uses Greedy meshing to merge this builder's Quads. */
- public void mergeQuads()
- {
- long mergeCount = 0;
- long preQuadsCount = this.getCurrentOpaqueQuadsCount() + this.getCurrentTransparentQuadsCount();
- if (preQuadsCount <= 1)
- {
- return;
- }
-
- for (int directionIndex = 0; directionIndex < 6; directionIndex++)
- {
- mergeCount += mergeQuadsInternal(this.opaqueQuads, directionIndex, BufferMergeDirectionEnum.EastWest);
- if (this.doTransparency)
- {
- mergeCount += mergeQuadsInternal(this.transparentQuads, directionIndex, BufferMergeDirectionEnum.EastWest);
- }
-
-
- // only run the second merge if the face is the top or bottom
- if (directionIndex == EDhDirection.UP.ordinal() || directionIndex == EDhDirection.DOWN.ordinal())
- {
- mergeCount += mergeQuadsInternal(this.opaqueQuads, directionIndex, BufferMergeDirectionEnum.NorthSouthOrUpDown);
- if (this.doTransparency)
- {
- mergeCount += mergeQuadsInternal(this.transparentQuads, directionIndex, BufferMergeDirectionEnum.NorthSouthOrUpDown);
- }
- }
- }
-
- long postQuadsCount = this.getCurrentOpaqueQuadsCount() + this.getCurrentTransparentQuadsCount();
- LOGGER.debug("Merged "+mergeCount+"/"+preQuadsCount+"("+(mergeCount / (double) preQuadsCount)+") quads");
- }
-
- /** Merges all of this builder's quads for the given directionIndex (up, down, left, etc.) in the given direction */
- private static long mergeQuadsInternal(ArrayList[] list, int directionIndex, BufferMergeDirectionEnum mergeDirection)
- {
- if (list[directionIndex].size() <= 1)
- return 0;
-
- list[directionIndex].sort((objOne, objTwo) -> objOne.compare(objTwo, mergeDirection));
-
- long mergeCount = 0;
- ListIterator iter = list[directionIndex].listIterator();
- BufferQuad currentQuad = iter.next();
- while (iter.hasNext())
- {
- BufferQuad nextQuad = iter.next();
-
- if (currentQuad.tryMerge(nextQuad, mergeDirection))
- {
- // merge successful, attempt to merge the next quad
- mergeCount++;
- iter.set(null);
- }
- else
- {
- // merge fail, move on to the next quad
- currentQuad = nextQuad;
- }
- }
- list[directionIndex].removeIf(Objects::isNull);
- return mergeCount;
- }
-
-
-
- //==============//
- // buffer setup //
- //==============//
-
- public Iterator makeOpaqueVertexBuffers()
- {
- return new Iterator()
- {
- final ByteBuffer bb = MemoryUtil.memAlloc(ColumnRenderBuffer.FULL_SIZED_BUFFER);
- int dir = this.skipEmpty(0);
- int quad = 0;
-
- private int skipEmpty(int d)
- {
- while (d < 6 && opaqueQuads[d].isEmpty())
- {
- d++;
- }
- return d;
- }
-
- @Override
- public boolean hasNext()
- {
- return dir < 6;
- }
-
- @Override
- public ByteBuffer next()
- {
- if (dir >= 6)
- {
- return null;
- }
- bb.clear();
- bb.limit(ColumnRenderBuffer.FULL_SIZED_BUFFER);
- while (bb.hasRemaining() && dir < 6)
- {
- writeData();
- }
- bb.limit(bb.position());
- bb.rewind();
- return bb;
- }
-
- private void writeData()
- {
- int i = quad;
- for (; i < opaqueQuads[dir].size(); i++)
- {
- if (!bb.hasRemaining())
- {
- break;
- }
- putQuad(bb, opaqueQuads[dir].get(i));
- }
-
- if (i >= opaqueQuads[dir].size())
- {
- quad = 0;
- dir++;
- dir = skipEmpty(dir);
- }
- else
- {
- quad = i;
- }
- }
- };
- }
-
- public Iterator makeTransparentVertexBuffers()
- {
- return new Iterator()
- {
- final ByteBuffer bb = MemoryUtil.memAlloc(ColumnRenderBuffer.FULL_SIZED_BUFFER);
- int directionIndex = this.skipEmptyDirectionIndices(0);
- int quad = 0;
-
- private int skipEmptyDirectionIndices(int directionIndex)
- {
- while (directionIndex < 6 &&
- (LodQuadBuilder.this.transparentQuads[directionIndex] == null
- || LodQuadBuilder.this.transparentQuads[directionIndex].isEmpty()))
- {
- directionIndex++;
- }
-
- return directionIndex;
- }
-
- @Override
- public boolean hasNext() { return this.directionIndex < 6; }
-
- @Override
- public ByteBuffer next()
- {
- if (this.directionIndex >= 6)
- {
- return null;
- }
-
- this.bb.clear();
- this.bb.limit(ColumnRenderBuffer.FULL_SIZED_BUFFER);
- while (this.bb.hasRemaining() && this.directionIndex < 6)
- {
- this.writeData();
- }
- this.bb.limit(this.bb.position());
- this.bb.rewind();
- return this.bb;
- }
-
- private void writeData()
- {
- int i = this.quad;
- for (; i < LodQuadBuilder.this.transparentQuads[this.directionIndex].size(); i++)
- {
- if (!this.bb.hasRemaining())
- {
- break;
- }
- putQuad(this.bb, LodQuadBuilder.this.transparentQuads[this.directionIndex].get(i));
- }
-
- if (i >= LodQuadBuilder.this.transparentQuads[this.directionIndex].size())
- {
- this.quad = 0;
- this.directionIndex++;
- this.directionIndex = this.skipEmptyDirectionIndices(this.directionIndex);
- }
- else
- {
- this.quad = i;
- }
- }
- };
- }
- public interface BufferFiller
- {
- /** If true: more data needs to be filled */
- boolean fill(GLVertexBuffer vbo);
-
- }
-
- public BufferFiller makeOpaqueBufferFiller(EDhApiGpuUploadMethod method)
- {
- return new BufferFiller()
- {
- int dir = 0;
- int quad = 0;
-
- public boolean fill(GLVertexBuffer vbo)
- {
- if (dir >= 6)
- {
- vbo.setVertexCount(0);
- return false;
- }
-
- int numOfQuads = _countRemainingQuads();
- if (numOfQuads > ColumnRenderBuffer.MAX_QUADS_PER_BUFFER)
- numOfQuads = ColumnRenderBuffer.MAX_QUADS_PER_BUFFER;
- if (numOfQuads == 0)
- {
- vbo.setVertexCount(0);
- return false;
- }
- ByteBuffer bb = vbo.mapBuffer(numOfQuads * ColumnRenderBuffer.QUADS_BYTE_SIZE, method,
- ColumnRenderBuffer.FULL_SIZED_BUFFER);
- if (bb == null)
- throw new NullPointerException("mapBuffer returned null");
- bb.clear();
- bb.limit(numOfQuads * ColumnRenderBuffer.QUADS_BYTE_SIZE);
- while (bb.hasRemaining() && dir < 6)
- {
- writeData(bb);
- }
- bb.rewind();
- vbo.unmapBuffer();
- vbo.setVertexCount(numOfQuads * 4);
- return dir < 6;
- }
-
- private int _countRemainingQuads()
- {
- int a = opaqueQuads[dir].size() - quad;
- for (int i = dir + 1; i < opaqueQuads.length; i++)
- {
- a += opaqueQuads[i].size();
- }
- return a;
- }
-
- private void writeData(ByteBuffer bb)
- {
- int startQ = quad;
-
- int i = startQ;
- for (i = startQ; i < opaqueQuads[dir].size(); i++)
- {
- if (!bb.hasRemaining())
- {
- break;
- }
- putQuad(bb, opaqueQuads[dir].get(i));
- }
-
- if (i >= opaqueQuads[dir].size())
- {
- quad = 0;
- dir++;
- while (dir < 6 && opaqueQuads[dir].isEmpty())
- {
- dir++;
- }
- }
- else
- {
- quad = i;
- }
- }
- };
- }
-
- public BufferFiller makeTransparentBufferFiller(EDhApiGpuUploadMethod method)
- {
- return new BufferFiller()
- {
- int dir = 0;
- int quad = 0;
-
- public boolean fill(GLVertexBuffer vbo)
- {
- if (dir >= 6)
- {
- vbo.setVertexCount(0);
- return false;
- }
-
- int numOfQuads = _countRemainingQuads();
- if (numOfQuads > ColumnRenderBuffer.MAX_QUADS_PER_BUFFER)
- numOfQuads = ColumnRenderBuffer.MAX_QUADS_PER_BUFFER;
- if (numOfQuads == 0)
- {
- vbo.setVertexCount(0);
- return false;
- }
- ByteBuffer bb = vbo.mapBuffer(numOfQuads * ColumnRenderBuffer.QUADS_BYTE_SIZE, method,
- ColumnRenderBuffer.FULL_SIZED_BUFFER);
- if (bb == null)
- throw new NullPointerException("mapBuffer returned null");
- bb.clear();
- bb.limit(numOfQuads * ColumnRenderBuffer.QUADS_BYTE_SIZE);
- while (bb.hasRemaining() && dir < 6)
- {
- writeData(bb);
- }
- bb.rewind();
- vbo.unmapBuffer();
- vbo.setVertexCount(numOfQuads * 4);
- return dir < 6;
- }
-
- private int _countRemainingQuads()
- {
- int a = transparentQuads[dir].size() - quad;
- for (int i = dir + 1; i < transparentQuads.length; i++)
- {
- a += transparentQuads[i].size();
- }
- return a;
- }
-
- private void writeData(ByteBuffer bb)
- {
- int startQ = quad;
-
- int i = startQ;
- for (i = startQ; i < transparentQuads[dir].size(); i++)
- {
- if (!bb.hasRemaining())
- {
- break;
- }
- putQuad(bb, transparentQuads[dir].get(i));
- }
-
- if (i >= transparentQuads[dir].size())
- {
- quad = 0;
- dir++;
- while (dir < 6 && transparentQuads[dir].isEmpty())
- {
- dir++;
- }
- }
- else
- {
- quad = i;
- }
- }
- };
- }
-
-
-
//=========//
// getters //
//=========//
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/GLProxy.java b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/GLProxy.java
index 4bbfbd6e8..c5556bd9d 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/GLProxy.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/GLProxy.java
@@ -193,17 +193,7 @@ public class GLProxy
return instance;
}
- public EDhApiGpuUploadMethod getGpuUploadMethod()
- {
- EDhApiGpuUploadMethod method = Config.Client.Advanced.GpuBuffers.gpuUploadMethod.get();
- if (!this.bufferStorageSupported && method == EDhApiGpuUploadMethod.BUFFER_STORAGE)
- {
- // if buffer storage isn't supported
- // default to DATA since that is the most compatible
- method = EDhApiGpuUploadMethod.DATA;
- }
- return method == EDhApiGpuUploadMethod.AUTO ? this.preferredUploadMethod : method;
- }
+ public EDhApiGpuUploadMethod getGpuUploadMethod() { return this.preferredUploadMethod; }
public boolean runningOnRenderThread()
{
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/buffer/GLBuffer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/buffer/GLBuffer.java
index bdfee1f4b..c90ebc1c0 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/buffer/GLBuffer.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/buffer/GLBuffer.java
@@ -238,7 +238,7 @@ public class GLBuffer implements AutoCloseable
// buffer mapping //
//================//
- public ByteBuffer mapBuffer(int targetSize, EDhApiGpuUploadMethod uploadMethod, int maxExpensionSize, int bufferHint, int mapFlags)
+ public ByteBuffer mapBuffer(int targetSize, EDhApiGpuUploadMethod uploadMethod, int maxExpansionSize, int bufferHint, int mapFlags)
{
LodUtil.assertTrue(targetSize != 0, "MapBuffer targetSize is 0");
LodUtil.assertTrue(uploadMethod.useEarlyMapping, "Upload method must be one that use early mappings in order to call mapBuffer");
@@ -252,7 +252,7 @@ public class GLBuffer implements AutoCloseable
if (this.size < targetSize || this.size > targetSize * BUFFER_SHRINK_TRIGGER)
{
int newSize = (int) (targetSize * BUFFER_EXPANSION_MULTIPLIER);
- if (newSize > maxExpensionSize) newSize = maxExpensionSize;
+ if (newSize > maxExpansionSize) newSize = maxExpansionSize;
this.size = newSize;
if (this.bufferStorage)
{
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/buffer/GLVertexBuffer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/buffer/GLVertexBuffer.java
index f3957ef56..5c5586e61 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/buffer/GLVertexBuffer.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/buffer/GLVertexBuffer.java
@@ -77,9 +77,9 @@ public class GLVertexBuffer extends GLBuffer
this.vertexCount = vertCount;
}
- public ByteBuffer mapBuffer(int targetSize, EDhApiGpuUploadMethod uploadMethod, int maxExpensionSize)
+ public ByteBuffer mapBuffer(int targetSize, EDhApiGpuUploadMethod uploadMethod, int maxExpansionSize)
{
- return super.mapBuffer(targetSize, uploadMethod, maxExpensionSize,
+ return super.mapBuffer(targetSize, uploadMethod, maxExpansionSize,
uploadMethod.useBufferStorage ? GL32.GL_MAP_WRITE_BIT :
uploadMethod.useEarlyMapping ? GL32.GL_DYNAMIC_DRAW : GL32.GL_STATIC_DRAW,
GL32.GL_MAP_WRITE_BIT | GL32.GL_MAP_UNSYNCHRONIZED_BIT | GL32.GL_MAP_INVALIDATE_BUFFER_BIT);