From 9b7d3c083fbfe0a8bafe8690f5b8fb963188d71c Mon Sep 17 00:00:00 2001 From: James Seibel Date: Mon, 29 Nov 2021 21:23:45 -0600 Subject: [PATCH] Add buffer timeout and improve the uploading logic slightly --- .../java/com/seibel/lod/core/ModInfo.java | 4 +-- .../com/seibel/lod/core/api/ClientApi.java | 2 +- .../LodBufferBuilderFactory.java | 33 +++++++++++++++---- .../config/ILodConfigWrapperSingleton.java | 24 ++++++++++++-- 4 files changed, 51 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/seibel/lod/core/ModInfo.java b/src/main/java/com/seibel/lod/core/ModInfo.java index c0deeb9d2..5a7e25f8b 100644 --- a/src/main/java/com/seibel/lod/core/ModInfo.java +++ b/src/main/java/com/seibel/lod/core/ModInfo.java @@ -28,7 +28,7 @@ package com.seibel.lod.core; * Pretty much all of the mod stems from there. * * @author James Seibel - * @version 11-13-2021 + * @version 11-29-2021 */ public final class ModInfo { @@ -38,5 +38,5 @@ public final class ModInfo /** Human readable version of NAME */ public static final String READABLE_NAME = "Distant Horizons"; public static final String API = "LodAPI"; - public static final String VERSION = "a1.5.3"; + public static final String VERSION = "a1.5.4"; } \ No newline at end of file diff --git a/src/main/java/com/seibel/lod/core/api/ClientApi.java b/src/main/java/com/seibel/lod/core/api/ClientApi.java index c66458fcc..3989434f4 100644 --- a/src/main/java/com/seibel/lod/core/api/ClientApi.java +++ b/src/main/java/com/seibel/lod/core/api/ClientApi.java @@ -161,7 +161,7 @@ public class ClientApi // CONFIG.client().advanced().buffers().setRebuildTimes(BufferRebuildTimes.FREQUENT); - CONFIG.client().advanced().debugging().setDebugKeybindingsEnabled(true); +// CONFIG.client().advanced().debugging().setDebugKeybindingsEnabled(true); } diff --git a/src/main/java/com/seibel/lod/core/builders/bufferBuilding/LodBufferBuilderFactory.java b/src/main/java/com/seibel/lod/core/builders/bufferBuilding/LodBufferBuilderFactory.java index 7e8106744..d93445364 100644 --- a/src/main/java/com/seibel/lod/core/builders/bufferBuilding/LodBufferBuilderFactory.java +++ b/src/main/java/com/seibel/lod/core/builders/bufferBuilding/LodBufferBuilderFactory.java @@ -68,7 +68,7 @@ import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftWrapper; * rendered by the LodRenderer. * * @author James Seibel - * @version 11-21-2021 + * @version 11-29-2021 */ public class LodBufferBuilderFactory { @@ -757,6 +757,7 @@ public class LodBufferBuilderFactory private void uploadBuffers(boolean fullRegen, LodDimension lodDim) { GLProxy glProxy = GLProxy.getInstance(); + long fence = 0; try { @@ -774,6 +775,17 @@ public class LodBufferBuilderFactory uploadMethod = GpuUploadMethod.SUB_DATA; } + // determine the upload timeout + int uploadTimeoutInMS = CONFIG.client().graphics().advancedGraphics().getGpuUploadTimeoutInMilliseconds(); + + // James has no idea if this does anything helpful, + // but in theory it should prevent OpenGL from drawing and + // writing to a buffer at the same time. + GL45.glMemoryBarrier(GL45.GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT); + fence = GL45.glFenceSync(GL45.GL_SYNC_GPU_COMMANDS_COMPLETE, 0); + + + // actually upload the buffers for (int x = 0; x < buildableVbos.length; x++) { @@ -786,16 +798,20 @@ public class LodBufferBuilderFactory ByteBuffer uploadBuffer = buildableBuffers[x][z][i].getCleanedByteBuffer(); vboUpload(x,z,i, uploadBuffer, true, uploadMethod); lodDim.setRegenRegionBufferByArrayIndex(x, z, false); + + + // upload buffers over a extended period of time + // to hopefully prevent stuttering. + if (uploadTimeoutInMS != 0) + Thread.sleep(uploadTimeoutInMS); + GL15.glFinish(); } } } } // make sure all of the uploads finish before continuing - GL45.glMemoryBarrier(GL45.GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT); - long fence = GL45.glFenceSync(GL45.GL_SYNC_GPU_COMMANDS_COMPLETE, 0); - GL45.glClientWaitSync(fence, GL45.GL_SYNC_FLUSH_COMMANDS_BIT, 5 * 1000000000); // 5 seconds - GL45.glDeleteSync(fence); + GL45.glClientWaitSync(fence, GL45.GL_SYNC_FLUSH_COMMANDS_BIT, 5 * 1000000000); // wait up to 5 seconds } catch (Exception e) { @@ -806,7 +822,9 @@ public class LodBufferBuilderFactory finally { GL15.glFinish(); - + if (fence != 0) + GL45.glDeleteSync(fence); + // close the context so it can be re-used later. // I'm guessing we can't just leave it because the executor service // does something that invalidates the OpenGL context. @@ -899,7 +917,7 @@ public class LodBufferBuilderFactory // map buffer range is better since it can be explicitly unsynchronized if (GLProxy.getInstance().mapBufferRangeSupported) - vboBuffer = GL30.glMapBufferRange(GL30.GL_ARRAY_BUFFER, 0, uploadBuffer.capacity(), GL30.GL_MAP_WRITE_BIT | GL30.GL_MAP_UNSYNCHRONIZED_BIT); + vboBuffer = GL30.glMapBufferRange(GL30.GL_ARRAY_BUFFER, 0, uploadBuffer.capacity(), GL30.GL_MAP_WRITE_BIT | GL30.GL_MAP_UNSYNCHRONIZED_BIT | GL30.GL_MAP_INVALIDATE_BUFFER_BIT); else vboBuffer = GL15.glMapBuffer(GL30.GL_ARRAY_BUFFER, uploadBuffer.capacity()); @@ -920,6 +938,7 @@ public class LodBufferBuilderFactory // high stutter, low GPU usage // But simplest/most compatible + GL15.glBufferData(GL15.GL_ARRAY_BUFFER, uploadBuffer.capacity(), GL15.GL_STATIC_DRAW); GL15.glBufferData(GL15.GL_ARRAY_BUFFER, uploadBuffer, GL15.GL_STATIC_DRAW); } else diff --git a/src/main/java/com/seibel/lod/core/wrapperInterfaces/config/ILodConfigWrapperSingleton.java b/src/main/java/com/seibel/lod/core/wrapperInterfaces/config/ILodConfigWrapperSingleton.java index 37daef20c..92a9e6f7f 100644 --- a/src/main/java/com/seibel/lod/core/wrapperInterfaces/config/ILodConfigWrapperSingleton.java +++ b/src/main/java/com/seibel/lod/core/wrapperInterfaces/config/ILodConfigWrapperSingleton.java @@ -43,7 +43,7 @@ import com.seibel.lod.core.util.LodUtil; * the options that should be implemented in a configWrapperSingleton. * * @author James Seibel - * @version 11-27-2021 + * @version 11-29-2021 */ public interface ILodConfigWrapperSingleton { @@ -252,10 +252,30 @@ public interface ILodConfigWrapperSingleton + " " + GpuUploadMethod.BUFFER_STORAGE + ": Default if OpenGL 4.5 is supported. Fast rendering, no stuttering. \n" + " " + GpuUploadMethod.SUB_DATA + ": Default if OpenGL 4.5 is NOT supported. Fast rendering but will probably stutter when uploading. \n" + " " + GpuUploadMethod.DATA + ": Fast rendering but will stutter when uploading. \n" - + " " + GpuUploadMethod.BUFFER_MAPPING + ": Slow rendering but won't stutter when uploading. Possibly better than " + GpuUploadMethod.SUB_DATA + " if using an integrated GPU. \n"; + + " " + GpuUploadMethod.BUFFER_MAPPING + ": Slow rendering but won't stutter when uploading. Possibly better than " + GpuUploadMethod.SUB_DATA + " if using an integrated GPU. \n" + + "\n" + + " If you don't see any difference when changing these settings\n" + + " a restart may be necessary to clear the old buffers. \n"; public GpuUploadMethod getGpuUploadMethod(); public void setGpuUploadMethod(GpuUploadMethod newDisableVanillaFog); + MinDefaultMax GPU_UPLOAD_TIMEOUT_IN_MILLISECONDS_DEFAULT = new MinDefaultMax(0, 0, 5000); + String GPU_UPLOAD_TIMEOUT_IN_MILLISECONDS_DESC = "" + + " EXPERIMENTAL \n" + + "\n" + + " How long should we wait before uploading a buffer to the GPU? \n" + + " Helpful resource for frame times: https://fpstoms.com \n" + + "\n" + + " Longer times may reduce stuttering but will make fake chunks \n" + + " transition and load slower. \n" + + "\n" + + " NOTE:\n" + + " This should be a last resort option." + + " Only change this from [0], after you have tried all of the \n" + + " GPU Upload methods and determined none of them work with your hardware."; + public int getGpuUploadTimeoutInMilliseconds(); + public void setGpuUploadTimeoutInMilliseconds(int newTimeoutInMilliseconds); + boolean USE_EXTENDED_NEAR_CLIP_PLANE_DEFAULT = false; String USE_EXTENDED_NEAR_CLIP_PLANE_DESC = "" + " Will prevent some overdraw issues, but may cause nearby fake chunks to render incorrectly \n"