From 76f28e648cf31c1b1cc16b23cd91b3ff7ac8bbdd Mon Sep 17 00:00:00 2001 From: James Seibel Date: Thu, 30 May 2024 20:13:55 -0500 Subject: [PATCH 1/6] Up the version number 2.0.4-a-dev -> 2.1.0-a --- .../main/java/com/seibel/distanthorizons/coreapi/ModInfo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/com/seibel/distanthorizons/coreapi/ModInfo.java b/api/src/main/java/com/seibel/distanthorizons/coreapi/ModInfo.java index 75fb9c8a5..5d5649470 100644 --- a/api/src/main/java/com/seibel/distanthorizons/coreapi/ModInfo.java +++ b/api/src/main/java/com/seibel/distanthorizons/coreapi/ModInfo.java @@ -34,7 +34,7 @@ public final class ModInfo public static final String NAME = "DistantHorizons"; /** Human-readable version of NAME */ public static final String READABLE_NAME = "Distant Horizons"; - public static final String VERSION = "2.0.4-a-dev"; + public static final String VERSION = "2.1.0-a"; /** Returns true if the current build is an unstable developer build, false otherwise. */ public static boolean IS_DEV_BUILD = VERSION.toLowerCase().contains("dev"); From c3abfb123db2ad57afc266559b5e3546bedac833 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Fri, 7 Jun 2024 17:42:36 -0500 Subject: [PATCH 2/6] Up the version number 2.1.0-a -> 2.1.1-a-dev --- .../main/java/com/seibel/distanthorizons/coreapi/ModInfo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/com/seibel/distanthorizons/coreapi/ModInfo.java b/api/src/main/java/com/seibel/distanthorizons/coreapi/ModInfo.java index 5d5649470..efff0ef0f 100644 --- a/api/src/main/java/com/seibel/distanthorizons/coreapi/ModInfo.java +++ b/api/src/main/java/com/seibel/distanthorizons/coreapi/ModInfo.java @@ -34,7 +34,7 @@ public final class ModInfo public static final String NAME = "DistantHorizons"; /** Human-readable version of NAME */ public static final String READABLE_NAME = "Distant Horizons"; - public static final String VERSION = "2.1.0-a"; + public static final String VERSION = "2.1.1-a-dev"; /** Returns true if the current build is an unstable developer build, false otherwise. */ public static boolean IS_DEV_BUILD = VERSION.toLowerCase().contains("dev"); From b7a5bfd274724195ddc32ca9746c5b38b9fa629a Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sat, 8 Jun 2024 08:11:09 -0500 Subject: [PATCH 3/6] Add update branch config "auto" --- .../api/enums/config/EDhApiUpdateBranch.java | 33 +++++++++++++++++-- .../distanthorizons/core/config/Config.java | 9 ++--- .../core/jar/updater/SelfUpdater.java | 12 ++----- .../assets/distanthorizons/lang/en_us.json | 2 ++ 4 files changed, 40 insertions(+), 16 deletions(-) diff --git a/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EDhApiUpdateBranch.java b/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EDhApiUpdateBranch.java index dc94d28f7..6b149a666 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EDhApiUpdateBranch.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EDhApiUpdateBranch.java @@ -1,14 +1,41 @@ package com.seibel.distanthorizons.api.enums.config; +import com.seibel.distanthorizons.coreapi.ModInfo; + /** + * AUTO,
* STABLE,
* NIGHTLY,

* - * @since API 2.0.0 - * @version 2024-4-6 + * @since API 2.1.0 + * @version 2024-6-8 */ public enum EDhApiUpdateBranch { + AUTO, STABLE, - NIGHTLY + NIGHTLY; + + + + /** + * If the updateBranch value is {@link EDhApiUpdateBranch#AUTO} + * this method will convert it either to {@link EDhApiUpdateBranch#STABLE} or {@link EDhApiUpdateBranch#NIGHTLY} + * based on this jar's state.

+ * + * If updateBranch is {@link EDhApiUpdateBranch#STABLE} or {@link EDhApiUpdateBranch#NIGHTLY} + * it just returns. + */ + public static EDhApiUpdateBranch convertAutoToStableOrNightly(EDhApiUpdateBranch updateBranch) + { + if (updateBranch != EDhApiUpdateBranch.AUTO) + { + return updateBranch; + } + else + { + return ModInfo.IS_DEV_BUILD ? EDhApiUpdateBranch.NIGHTLY : EDhApiUpdateBranch.STABLE; + } + } + } 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 827177ed6..2ccfd9824 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 @@ -1054,11 +1054,12 @@ public class Config .build(); public static ConfigEntry updateBranch = new ConfigEntry.Builder() - .set( - ModInfo.IS_DEV_BUILD? EDhApiUpdateBranch.NIGHTLY: EDhApiUpdateBranch.STABLE // If it's already a nightly build, then download the nightly build ofc - ) + .set(EDhApiUpdateBranch.AUTO) .comment("" - + " If DH should use the nightly (provided by Gitlab), or stable (provided by Modrinth) build") + + "If DH should use the nightly (provided by Gitlab), or stable (provided by Modrinth) build. \n" + + "If ["+EDhApiUpdateBranch.AUTO+"] is selected DH will update to new stable releases if the current jar is a stable jar \n" + + "and will update to new nightly builds if the current jar is a nightly jar (IE the version number ends in '-dev')." + + "") .build(); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/jar/updater/SelfUpdater.java b/core/src/main/java/com/seibel/distanthorizons/core/jar/updater/SelfUpdater.java index 16df88e2b..92a6940de 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/jar/updater/SelfUpdater.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/jar/updater/SelfUpdater.java @@ -19,6 +19,7 @@ package com.seibel.distanthorizons.core.jar.updater; +import com.seibel.distanthorizons.api.enums.config.EDhApiUpdateBranch; import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.jar.JarUtils; @@ -83,15 +84,8 @@ public class SelfUpdater boolean returnValue = false; try { - switch (Config.Client.Advanced.AutoUpdater.updateBranch.get()) - { - case STABLE: - returnValue = onStableStart(); - break; - case NIGHTLY: - returnValue = onNightlyStart(); - break; - }; + EDhApiUpdateBranch updateBranch = EDhApiUpdateBranch.convertAutoToStableOrNightly(Config.Client.Advanced.AutoUpdater.updateBranch.get()); + returnValue = (updateBranch == EDhApiUpdateBranch.STABLE) ? onStableStart() : onNightlyStart(); } catch (Exception e) // Shouldn't be needed, but just in case { diff --git a/core/src/main/resources/assets/distanthorizons/lang/en_us.json b/core/src/main/resources/assets/distanthorizons/lang/en_us.json index d1ee62c9d..771e660dd 100644 --- a/core/src/main/resources/assets/distanthorizons/lang/en_us.json +++ b/core/src/main/resources/assets/distanthorizons/lang/en_us.json @@ -920,6 +920,8 @@ "Stable", "distanthorizons.config.enum.EDhApiUpdateBranch.NIGHTLY": "Nightly", + "distanthorizons.config.enum.EDhApiUpdateBranch.AUTO": + "Auto", "distanthorizons.config.enum.EDhApiGrassSideRendering.AS_GRASS": "As Grass", From e41abdd17649681367871ddf674f03c3cb2bba18 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sat, 8 Jun 2024 08:33:32 -0500 Subject: [PATCH 4/6] Improve config comment spacing --- .../core/config/file/ConfigFileHandling.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/file/ConfigFileHandling.java b/core/src/main/java/com/seibel/distanthorizons/core/config/file/ConfigFileHandling.java index 0bd02668f..966bc8310 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/file/ConfigFileHandling.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/file/ConfigFileHandling.java @@ -265,7 +265,11 @@ public class ConfigFileHandling ) return; - nightConfig.setComment(entry.getNameWCategory(), " " + entry.getComment().replaceAll("\n", "\n ") + "\n "); + String comment = entry.getComment().replaceAll("\n", "\n ").trim(); + // the new line makes it easier to read and separate configs + // the space makes sure the first word of a comment isn't directly in line with the "#" + comment = "\n " + comment; + nightConfig.setComment(entry.getNameWCategory(), comment); } From 1dd6359c89adfcc2010a18f6cb5f7567811a7001 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sat, 8 Jun 2024 11:06:26 -0500 Subject: [PATCH 5/6] Try changing LZMA preset from 4 -> 3 (faster, less compressed) --- .../core/util/objects/dataStreams/DhDataOutputStream.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/dataStreams/DhDataOutputStream.java b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/dataStreams/DhDataOutputStream.java index 5fff65581..6797af8d2 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/objects/dataStreams/DhDataOutputStream.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/objects/dataStreams/DhDataOutputStream.java @@ -68,8 +68,8 @@ public class DhDataOutputStream extends DataOutputStream ResettableArrayCache arrayCache = LZMA_RESETTABLE_ARRAY_CACHE_GETTER.get(); arrayCache.reset(); // Note: if the LZMA2Options are changed the array cache may need to be re-tested. - // the array cache was specifically tested and tuned for LZMA preset 4 - return new XZOutputStream(stream, new LZMA2Options(4), + // the array cache was specifically tested and tuned for LZMA preset 3/4 + return new XZOutputStream(stream, new LZMA2Options(3), XZ.CHECK_CRC64, arrayCache); default: From e011ce3ee065fa195a694495ec54d5f446520879 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sat, 8 Jun 2024 12:49:08 -0500 Subject: [PATCH 6/6] Remove OpenGL multithreading --- .../distanthorizons/core/config/Config.java | 10 - .../core/config/gui/OpenGLConfigScreen.java | 3 +- .../bufferBuilding/ColumnRenderBuffer.java | 71 ++-- .../core/enums/EGLProxyContext.java | 44 --- .../core/render/glObject/GLProxy.java | 361 ++---------------- .../core/render/glObject/buffer/GLBuffer.java | 62 ++- .../glObject/buffer/GLElementBuffer.java | 8 +- .../glObject/buffer/GLVertexBuffer.java | 6 +- .../core/render/renderer/LodRenderer.java | 2 +- .../core/render/renderer/TestRenderer.java | 3 +- 10 files changed, 92 insertions(+), 478 deletions(-) delete mode 100644 core/src/main/java/com/seibel/distanthorizons/core/enums/EGLProxyContext.java 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 2ccfd9824..36eec9d3c 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 @@ -1025,16 +1025,6 @@ public class Config + "") .build(); - public static ConfigEntry gpuUploadAsync = new ConfigEntry.Builder() - .set(true) - .comment("" - + "If true geometry data will be uploaded on a DH controlled thread, reducing FPS stuttering. \n" - + "If false uploading will be done on Minecraft's main rendering thread. \n" - + "\n" - + "Setting this to false may reduce crashes or corrupted geometry on systems with an AMD GPU when Sodium is installed.\n" - + "") - .build(); - } public static class AutoUpdater diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/gui/OpenGLConfigScreen.java b/core/src/main/java/com/seibel/distanthorizons/core/config/gui/OpenGLConfigScreen.java index 35a6cf353..c39897a5c 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/gui/OpenGLConfigScreen.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/gui/OpenGLConfigScreen.java @@ -82,8 +82,7 @@ public class OpenGLConfigScreen extends AbstractScreen private void createBuffer() { - GLProxy.getInstance().recordOpenGlCall(() -> sharedContextBuffer = createTextingBuffer()); - GLProxy.ensureAllGLJobCompleted(); + sharedContextBuffer = createTextingBuffer(); sameContextBuffer = createTextingBuffer(); } 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 755b6b91c..8762bec32 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 @@ -22,7 +22,6 @@ package com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding; import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; -import com.seibel.distanthorizons.core.enums.EGLProxyContext; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.pos.DhBlockPos; import com.seibel.distanthorizons.core.render.glObject.GLProxy; @@ -92,58 +91,36 @@ public class ColumnRenderBuffer implements AutoCloseable LodUtil.assertTrue(Thread.currentThread().getName().startsWith(ThreadUtil.THREAD_NAME_PREFIX), "Buffer uploading needs to be done on a DH thread to prevent locking up any MC threads."); - // the async is relative to MC's render thread - boolean uploadAsync = Config.Client.Advanced.GpuBuffers.gpuUploadAsync.get(); - if (uploadAsync) + // upload on MC's render thread + CompletableFuture uploadFuture = new CompletableFuture<>(); + minecraftClient.executeOnRenderThread(() -> { - // upload here on a DH thread - GLProxy glProxy = GLProxy.getInstance(); - EGLProxyContext oldContext = glProxy.getGlContext(); - glProxy.setGlContext(EGLProxyContext.LOD_BUILDER); try { this.uploadBuffersUsingUploadMethod(builder, gpuUploadMethod); + uploadFuture.complete(null); } - finally + catch (InterruptedException e) { - glProxy.setGlContext(oldContext); + throw new CompletionException(e); } - } - else + }); + + + try { - // upload on MC's render thread - CompletableFuture uploadFuture = new CompletableFuture<>(); - minecraftClient.executeOnRenderThread(() -> - { - try - { - this.uploadBuffersUsingUploadMethod(builder, gpuUploadMethod); - uploadFuture.complete(null); - } - catch (InterruptedException e) - { - throw new CompletionException(e); - } - }); - - - try - { - // wait for the upload to finish - uploadFuture.get(1000, TimeUnit.MILLISECONDS); - } - catch (ExecutionException e) - { - LOGGER.warn("Error uploading builder ["+builder+"] synchronously. Error: "+e.getMessage(), e); - } - catch (TimeoutException e) - { - // timeouts can be ignored because it generally means the - // MC Render thread executor was closed - //LOGGER.warn("Error uploading builder ["+builder+"] synchronously. Error: "+e.getMessage(), e); - } - - + // wait for the upload to finish + uploadFuture.get(5_000, TimeUnit.MILLISECONDS); + } + catch (ExecutionException e) + { + LOGGER.warn("Error uploading builder ["+builder+"] synchronously. Error: "+e.getMessage(), e); + } + catch (TimeoutException e) + { + // timeouts can be ignored because it generally means the + // MC Render thread executor was closed + //LOGGER.warn("Error uploading builder ["+builder+"] synchronously. Error: "+e.getMessage(), e); } } private void uploadBuffersUsingUploadMethod(LodQuadBuilder builder, EDhApiGpuUploadMethod gpuUploadMethod) throws InterruptedException @@ -403,7 +380,7 @@ public class ColumnRenderBuffer implements AutoCloseable { if (buffer != null) { - buffer.destroy(false); + buffer.destroyAsync(); } } @@ -411,7 +388,7 @@ public class ColumnRenderBuffer implements AutoCloseable { if (buffer != null) { - buffer.destroy(false); + buffer.destroyAsync(); } } }); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/enums/EGLProxyContext.java b/core/src/main/java/com/seibel/distanthorizons/core/enums/EGLProxyContext.java deleted file mode 100644 index f069507a1..000000000 --- a/core/src/main/java/com/seibel/distanthorizons/core/enums/EGLProxyContext.java +++ /dev/null @@ -1,44 +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.enums; - -/** - * Minecraft,
- * Lod_Builder,
- * Proxy_Worker,
- * None
- * - * @author James Seibel - * @version 10-1-2021 - */ -public enum EGLProxyContext -{ - /** Minecraft's render thread */ - MINECRAFT, - - /** The context we send buffers to the GPU on */ - LOD_BUILDER, - - /** A context that can be used for miscellaneous tasks, owned by the GLProxy */ - PROXY_WORKER, - - /** used to un-bind threads */ - NONE, -} \ No newline at end of file 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 c49f74ce9..ffe831b00 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 @@ -19,22 +19,17 @@ package com.seibel.distanthorizons.core.render.glObject; -import com.google.common.util.concurrent.ThreadFactoryBuilder; import com.seibel.distanthorizons.api.enums.config.EDhApiGLErrorHandlingMode; -import com.seibel.distanthorizons.api.enums.config.EDhApiGlProfileMode; import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod; import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; -import com.seibel.distanthorizons.core.enums.EGLProxyContext; import com.seibel.distanthorizons.core.logging.ConfigBasedLogger; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; -import com.seibel.distanthorizons.core.util.ReflectionUtil; import com.seibel.distanthorizons.core.util.objects.GLMessage; import com.seibel.distanthorizons.core.util.objects.GLMessageOutputStream; import com.seibel.distanthorizons.core.util.objects.Pair; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; import com.seibel.distanthorizons.coreapi.ModInfo; -import com.seibel.distanthorizons.coreapi.util.StringUtil; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.lwjgl.glfw.GLFW; @@ -48,9 +43,6 @@ import java.lang.invoke.MethodHandles; import java.util.ArrayList; import java.util.Arrays; import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; /** * A singleton that holds references to different openGL contexts @@ -74,34 +66,13 @@ public class GLProxy public static final ConfigBasedLogger GL_LOGGER = new ConfigBasedLogger(LogManager.getLogger(GLProxy.class), () -> Config.Client.Advanced.Logging.logRendererGLEvent.get()); - /** newest version first */ - private static final ArrayList> SUPPORTED_GL_VERSIONS = new ArrayList<>( - Arrays.asList( - new Pair<>(4,6), new Pair<>(4,5), new Pair<>(4,4), new Pair<>(4,3), new Pair<>(4,2), new Pair<>(4,1), new Pair<>(4,0), - new Pair<>(3,3), new Pair<>(3,2) - )); - private static GLProxy instance = null; - private ExecutorService workerThread = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat(GLProxy.class.getSimpleName() + "-Worker-Thread").build()); + private final ConcurrentLinkedQueue renderThreadRunnableQueue = new ConcurrentLinkedQueue<>(); - private ConcurrentLinkedQueue renderThreadRunnableQueue = new ConcurrentLinkedQueue<>(); - - /** Minecraft's GLFW window */ - public final long minecraftGlContext; /** Minecraft's GL capabilities */ - public final GLCapabilities minecraftGlCapabilities; - - /** the LodBuilder's GLFW window */ - public final long lodBuilderGlContext; - /** the LodBuilder's GL capabilities */ - public final GLCapabilities lodBuilderGlCapabilities; - - /** the proxyWorker's GLFW window */ - public final long proxyWorkerGlContext; - /** the proxyWorker's GL capabilities */ - public final GLCapabilities proxyWorkerGlCapabilities; + public final GLCapabilities glCapabilities; public boolean namedObjectSupported = false; // ~OpenGL 4.5 (UNUSED CURRENTLY) public boolean bufferStorageSupported = false; // ~OpenGL 4.4 @@ -110,8 +81,6 @@ public class GLProxy private final EDhApiGpuUploadMethod preferredUploadMethod; public final GLMessage.Builder vanillaDebugMessageBuilder = GLMessage.Builder.DEFAULT_MESSAGE_BUILDER; - public final GLMessage.Builder lodBuilderDebugMessageBuilder = GLMessage.Builder.DEFAULT_MESSAGE_BUILDER; - public final GLMessage.Builder proxyWorkerDebugMessageBuilder = GLMessage.Builder.DEFAULT_MESSAGE_BUILDER; @@ -139,14 +108,13 @@ public class GLProxy // get Minecraft's GL context // //============================// - // get Minecraft's context - this.minecraftGlContext = GLFW.glfwGetCurrentContext(); - this.minecraftGlCapabilities = GL.getCapabilities(); + // get Minecraft's capabilities + this.glCapabilities = GL.getCapabilities(); // crash the game if the GPU doesn't support OpenGL 3.2 - if (!this.minecraftGlCapabilities.OpenGL32) + if (!this.glCapabilities.OpenGL32) { - String supportedVersionInfo = this.getFailedVersionInfo(this.minecraftGlCapabilities); + String supportedVersionInfo = this.getFailedVersionInfo(this.glCapabilities); // See full requirement at above. String errorMessage = ModInfo.READABLE_NAME + " was initializing " + GLProxy.class.getSimpleName() @@ -154,7 +122,7 @@ public class GLProxy "Additional info:\n" + supportedVersionInfo; MC.crashMinecraft(errorMessage, new UnsupportedOperationException("Distant Horizon OpenGL requirements not met")); } - GL_LOGGER.info("minecraftGlCapabilities:\n" + this.versionInfoToString(this.minecraftGlCapabilities)); + GL_LOGGER.info("minecraftGlCapabilities:\n" + this.versionInfoToString(this.glCapabilities)); if (Config.Client.Advanced.Debugging.OpenGl.overrideVanillaGLLogger.get()) { @@ -163,155 +131,20 @@ public class GLProxy - //================================// - // create the lod builder context // - //================================// - - String contextCreateErrorMessage = ""; - long potentialLodBuilderGlContext = 0; - GLCapabilities potentialLodBuilderGlCapabilities = null; - - int majorGlVersion = Config.Client.Advanced.Debugging.OpenGl.glContextMajorVersion.get(); - int minorGlVersion = Config.Client.Advanced.Debugging.OpenGl.glContextMinorVersion.get(); - - ArrayList> glVersions = new ArrayList<>(); - if (majorGlVersion != 0) - { - glVersions.add(new Pair<>(majorGlVersion, minorGlVersion)); - } - else - { - glVersions.addAll(SUPPORTED_GL_VERSIONS); - } - - for (Pair supportedGlVersion : glVersions) - { - int glMajorVersion = supportedGlVersion.first; - int glMinorVersion = supportedGlVersion.second; - - GL_LOGGER.info("Attempting to create a context with GL version: ["+glMajorVersion+"."+glMinorVersion+"]"); - - - - GLFW.glfwMakeContextCurrent(0L); - - // context creation setup - GLFW.glfwDefaultWindowHints(); - // make the context window invisible - GLFW.glfwWindowHint(GLFW.GLFW_VISIBLE, GLFW.GLFW_FALSE); - - boolean debugContextEnabled = Config.Client.Advanced.Debugging.OpenGl.enableGlDebugContext.get(); - boolean forwardCompatEnabled = Config.Client.Advanced.Debugging.OpenGl.enableGlForwardCompatibilityMode.get(); - - GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MAJOR, glMajorVersion); - GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, glMinorVersion); - GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_DEBUG_CONTEXT, debugContextEnabled ? GLFW.GLFW_TRUE : GLFW.GLFW_FALSE); - - GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_FORWARD_COMPAT, forwardCompatEnabled ? GLFW.GLFW_TRUE : GLFW.GLFW_FALSE); - int profileModeInt; - EDhApiGlProfileMode profileModeEnum = Config.Client.Advanced.Debugging.OpenGl.glProfileMode.get(); - switch (profileModeEnum) - { - case CORE: - profileModeInt = GLFW.GLFW_OPENGL_CORE_PROFILE; - break; - case COMPAT: - profileModeInt = GLFW.GLFW_OPENGL_COMPAT_PROFILE; - break; - default: - case ANY: - profileModeInt = GLFW.GLFW_OPENGL_ANY_PROFILE; - break; - } - GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_PROFILE, profileModeInt); - - contextCreateErrorMessage = - "Failed to create OpenGL GLFW context for OpenGL Version: [" + glMajorVersion + "." + glMinorVersion + "] \n" + - "with Debugging: [" + (debugContextEnabled ? "Enabled" : "Disabled") + "], \n" + - "Forward Compatibility: [" + (true ? "Enabled" : "Disabled") + "], \n" + - "and Profile: [" + profileModeEnum.name() + "]. "; - - - // try creating the Lod Builder context - potentialLodBuilderGlContext = GLFW.glfwCreateWindow(64, 64, "LOD Builder Window", 0L, this.minecraftGlContext); - if (potentialLodBuilderGlContext == 0) - { - GL_LOGGER.info(contextCreateErrorMessage); - GL_LOGGER.debug("Minecraft GL Capabilities:\n [\n" + ReflectionUtil.getAllFieldValuesAsString(this.minecraftGlCapabilities) + "\n]\n"); - - continue; - } - - // create the window - GLFW.glfwMakeContextCurrent(potentialLodBuilderGlContext); - GL_LOGGER.info("Successfully created a context with GL version: ["+glMajorVersion+"."+glMinorVersion+"]"); - - // set and log the capabilities - potentialLodBuilderGlCapabilities = GL.createCapabilities(); - GL_LOGGER.info("lodBuilderGlCapabilities:\n" + this.versionInfoToString(potentialLodBuilderGlCapabilities)); - // override the GL logger - GLUtil.setupDebugMessageCallback(new PrintStream(new GLMessageOutputStream(GLProxy::logMessage, this.lodBuilderDebugMessageBuilder), true)); - // clear the context for the next stage - GLFW.glfwMakeContextCurrent(0L); - - break; - } - - if (potentialLodBuilderGlContext == 0) - { - // no context was created - throw new UnsupportedOperationException("ERROR: Unable to create a GL Context using any of the supported GL versions: ["+ StringUtil.join(",", SUPPORTED_GL_VERSIONS) +"]"); - } - - this.lodBuilderGlContext = potentialLodBuilderGlContext; - this.lodBuilderGlCapabilities = potentialLodBuilderGlCapabilities; - - - - - //=================================// - // create the proxy worker context // - //=================================// - - // create the proxyWorker's context - this.proxyWorkerGlContext = GLFW.glfwCreateWindow(64, 48, "LOD proxy worker Window", 0L, this.minecraftGlContext); - if (this.proxyWorkerGlContext == 0) - { - GL_LOGGER.error(contextCreateErrorMessage + - "\n Your OS and GPU Driver may have not support this combination."); - GL_LOGGER.error("Minecraft GL Capabilities:\n [\n"+ReflectionUtil.getAllFieldValuesAsString(this.minecraftGlCapabilities)+"\n]\n"); - - throw new UnsupportedOperationException("Forward Compat Core Profile 3.2 creation failure"); - } - // create the window - GLFW.glfwMakeContextCurrent(this.proxyWorkerGlContext); - // set and log the capabilities - this.proxyWorkerGlCapabilities = GL.createCapabilities(); - GL_LOGGER.info("proxyWorkerGlCapabilities:\n" + this.versionInfoToString(this.lodBuilderGlCapabilities)); - // override the GL logger - GLUtil.setupDebugMessageCallback(new PrintStream(new GLMessageOutputStream(GLProxy::logMessage, this.proxyWorkerDebugMessageBuilder), true)); - // clear the context for the next stage - GLFW.glfwMakeContextCurrent(0L); - - - //======================// // get GPU capabilities // //======================// - // get capabilities from a context we use - this.setGlContext(EGLProxyContext.LOD_BUILDER); - // Check if we can use the make-over version of Vertex Attribute, which is available in GL4.3 or after - this.VertexAttributeBufferBindingSupported = this.minecraftGlCapabilities.glBindVertexBuffer != 0L; // Nullptr + this.VertexAttributeBufferBindingSupported = this.glCapabilities.glBindVertexBuffer != 0L; // Nullptr // UNUSED currently // Check if we can use the named version of all calls, which is available in GL4.5 or after - this.namedObjectSupported = this.minecraftGlCapabilities.glNamedBufferData != 0L; //Nullptr + this.namedObjectSupported = this.glCapabilities.glNamedBufferData != 0L; //Nullptr // get specific capabilities // Check if we can use the Buffer Storage, which is available in GL4.4 or after - this.bufferStorageSupported = this.minecraftGlCapabilities.glBufferStorage != 0L && this.lodBuilderGlCapabilities.glBufferStorage != 0L; // Nullptr + this.bufferStorageSupported = this.glCapabilities.glBufferStorage != 0L; // Nullptr if (!this.bufferStorageSupported) { GL_LOGGER.warn("This GPU doesn't support Buffer Storage (OpenGL 4.4), falling back to using other methods."); @@ -337,99 +170,12 @@ public class GLProxy // clean up // //==========// - // Since this is created on the render thread, make sure the Minecraft context is used in the end - this.setGlContext(EGLProxyContext.MINECRAFT); - // GLProxy creation success GL_LOGGER.info(GLProxy.class.getSimpleName() + " creation successful. OpenGL smiles upon you this day."); } - //==================// - // context handling // - //==================// - - /** - * A wrapper function to make switching contexts easier.
- * Does nothing if the calling thread is already using newContext. - */ - public void setGlContext(EGLProxyContext newContext) - { - EGLProxyContext currentContext = this.getGlContext(); - - // we don't have to change the context, we are already there. - if (currentContext == newContext) - return; - - long contextPointer; - GLCapabilities newGlCapabilities = null; - - // get the pointer(s) for this context - switch (newContext) - { - case LOD_BUILDER: - contextPointer = this.lodBuilderGlContext; - newGlCapabilities = this.lodBuilderGlCapabilities; - break; - - case MINECRAFT: - contextPointer = this.minecraftGlContext; - newGlCapabilities = this.minecraftGlCapabilities; - break; - - case PROXY_WORKER: - contextPointer = this.proxyWorkerGlContext; - newGlCapabilities = this.proxyWorkerGlCapabilities; - break; - - default: // default should never happen, it is just here to make the compiler happy - case NONE: - // 0L is equivalent to null - contextPointer = 0L; - break; - } - - GLFW.glfwMakeContextCurrent(contextPointer); - GL.setCapabilities(newGlCapabilities); - } - - /** Returns this thread's OpenGL context. */ - public EGLProxyContext getGlContext() - { - long currentContext = GLFW.glfwGetCurrentContext(); - - - if (currentContext == this.lodBuilderGlContext) - { - return EGLProxyContext.LOD_BUILDER; - } - else if (currentContext == this.minecraftGlContext) - { - return EGLProxyContext.MINECRAFT; - } - else if (currentContext == this.proxyWorkerGlContext) - { - return EGLProxyContext.PROXY_WORKER; - } - else if (currentContext == 0L) - { - return EGLProxyContext.NONE; - } - else - { - // hopefully this shouldn't happen - throw new IllegalStateException(Thread.currentThread().getName() + - " has a unknown OpenGl context: [" + currentContext + "]. " - + "Minecraft context [" + this.minecraftGlContext + "], " - + "LodBuilder context [" + this.lodBuilderGlContext + "], " - + "ProxyWorker context [" + this.proxyWorkerGlContext + "], " - + "no context [0]."); - } - } - - - //=========// // getters // //=========// @@ -457,33 +203,27 @@ public class GLProxy return method == EDhApiGpuUploadMethod.AUTO ? this.preferredUploadMethod : method; } + public boolean runningOnRenderThread() + { + long currentContext = GLFW.glfwGetCurrentContext(); + return currentContext != 0L; // if the context isn't null, it's the MC context + } + //=========================// // Worker Thread Runnables // //=========================// - /** - * Asynchronously calls the given runnable on proxy's OpenGL context. - * Useful for creating/destroying OpenGL objects in a thread - * that doesn't normally have access to a OpenGL context.
- * No rendering can be done through this method. - */ - public void recordOpenGlCall(Runnable renderCall) + public void queueRunningOnRenderThread(Runnable renderCall) { StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); - this.workerThread.execute(() -> this.runOpenGlCall(renderCall, stackTrace, true)); + this.renderThreadRunnableQueue.add(() -> this.runOpenGlCall(renderCall, stackTrace)); } - private void runOpenGlCall(Runnable renderCall, StackTraceElement[] stackTrace, boolean useProxyWorkerContext) + private void runOpenGlCall(Runnable renderCall, StackTraceElement[] stackTrace) { try { - // set up the context if requested... - if (useProxyWorkerContext) - { - this.setGlContext(EGLProxyContext.PROXY_WORKER); - } - // ...run the actual code... renderCall.run(); } @@ -493,67 +233,28 @@ public class GLProxy error.setStackTrace(stackTrace); GL_LOGGER.error(Thread.currentThread().getName() + " ran into a issue: ", error); } - finally - { - // ...and make sure the context is released when the thread finishes - if (useProxyWorkerContext) - { - this.setGlContext(EGLProxyContext.NONE); - } - } } - public static void ensureAllGLJobCompleted() - { - if (!hasInstance()) - { - return; - } - - - LOGGER.info("Blocking until GL jobs finished..."); - try - { - instance.workerThread.shutdown(); - boolean worked = instance.workerThread.awaitTermination(30, TimeUnit.SECONDS); - if (!worked) - { - LOGGER.error("GLWorkerThread shutdown timed out! Game may crash on exit due to cleanup failure!"); - } - } - catch (InterruptedException e) - { - LOGGER.error("GLWorkerThread shutdown is interrupted! Game may crash on exit due to cleanup failure!"); - e.printStackTrace(); - } - finally - { - instance.workerThread = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat(GLProxy.class.getSimpleName() + "-Worker-Thread").build()); - } - LOGGER.info("All GL jobs finished!"); - } - - - - //=========================// - // Render Thread Runnables // - //=========================// - - public void queueRunningOnRenderThread(Runnable renderCall) - { - StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); - this.renderThreadRunnableQueue.add(() -> this.runOpenGlCall(renderCall, stackTrace, false)); - } - - /** + /** * Doesn't do any thread/GL Context validation. * Running this outside of the render thread may cause crashes or other issues. */ public void runRenderThreadTasks() { + long startTime = System.nanoTime(); + Runnable runnable = this.renderThreadRunnableQueue.poll(); while(runnable != null) { + long currentTime = System.nanoTime(); + long runDuration = currentTime - startTime; + // only try running for 4ms at a time to (hopefully) prevent random lag spikes + if (runDuration > 4_000_000) + { + break; + } + + runnable.run(); runnable = this.renderThreadRunnableQueue.poll(); } 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 112a13cd0..7d8608a83 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 @@ -20,7 +20,6 @@ package com.seibel.distanthorizons.core.render.glObject.buffer; import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod; -import com.seibel.distanthorizons.core.enums.EGLProxyContext; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.render.glObject.GLProxy; import com.seibel.distanthorizons.core.util.LodUtil; @@ -94,9 +93,9 @@ public class GLBuffer implements AutoCloseable protected void create(boolean asBufferStorage) { - if (GLProxy.getInstance().getGlContext() == EGLProxyContext.NONE) + if (!GLProxy.getInstance().runningOnRenderThread()) { - LodUtil.assertNotReach("Thread ["+Thread.currentThread()+"] tried to create a GLBuffer outside a OpenGL context."); + LodUtil.assertNotReach("Thread ["+Thread.currentThread()+"] tried to create a GLBuffer outside the MC render thread."); } this.id = GL32.glGenBuffers(); @@ -109,7 +108,7 @@ public class GLBuffer implements AutoCloseable } - protected void destroy(boolean async) + protected void destroyAsync() { if (this.id == 0) { @@ -117,40 +116,33 @@ public class GLBuffer implements AutoCloseable return; } - destroyBufferId(async, this.id); + destroyBufferIdAsync(this.id); this.id = 0; this.size = 0; } - private static void destroyBufferId(boolean async, int id) + private static void destroyBufferIdAsync(int id) { - EGLProxyContext glContext = GLProxy.getInstance().getGlContext(); - if (async - && glContext != EGLProxyContext.PROXY_WORKER - && glContext != EGLProxyContext.MINECRAFT) - { - GLProxy.getInstance().queueRunningOnRenderThread(() -> destroyBufferId(false, id)); - } - else - { - // remove the phantom references - if (BUFFER_ID_TO_PHANTOM.containsKey(id)) + GLProxy.getInstance().queueRunningOnRenderThread(() -> { - Reference phantom = BUFFER_ID_TO_PHANTOM.get(id); - PHANTOM_TO_BUFFER_ID.remove(phantom); - BUFFER_ID_TO_PHANTOM.remove(id); - } - - // destroy the buffer if it exists, - // the buffer may not exist if the destroy method is called twice - if (GL32.glIsBuffer(id)) - { - GL32.glDeleteBuffers(id); - bufferCount.decrementAndGet(); + // remove the phantom references + if (BUFFER_ID_TO_PHANTOM.containsKey(id)) + { + Reference phantom = BUFFER_ID_TO_PHANTOM.get(id); + PHANTOM_TO_BUFFER_ID.remove(phantom); + BUFFER_ID_TO_PHANTOM.remove(id); + } - //LOGGER.info("destroyed buffer ["+id+"], remaining: ["+BUFFER_ID_TO_PHANTOM.size()+"]"); - } - } + // destroy the buffer if it exists, + // the buffer may not exist if the destroy method is called twice + if (GL32.glIsBuffer(id)) + { + GL32.glDeleteBuffers(id); + bufferCount.decrementAndGet(); + + //LOGGER.info("destroyed buffer ["+id+"], remaining: ["+BUFFER_ID_TO_PHANTOM.size()+"]"); + } + }); } @@ -205,7 +197,7 @@ public class GLBuffer implements AutoCloseable LodUtil.assertTrue(this.bufferStorage, "Buffer is not bufferStorage but its trying to use bufferStorage upload method!"); int bbSize = bb.limit() - bb.position(); - this.destroy(true); + this.destroyAsync(); this.create(true); this.bind(); GL44.glBufferStorage(this.getBufferBindingTarget(), bb, bufferStorageHint); @@ -293,7 +285,7 @@ public class GLBuffer implements AutoCloseable //===========// @Override - public void close() { this.destroy(true); } + public void close() { this.destroyAsync(); } @Override public String toString() @@ -319,7 +311,7 @@ public class GLBuffer implements AutoCloseable { // recreate if the buffer storage type changed this.bind(); - this.destroy(true); + this.destroyAsync(); this.create(uploadMethod.useBufferStorage); this.bind(); } @@ -362,7 +354,7 @@ public class GLBuffer implements AutoCloseable if (PHANTOM_TO_BUFFER_ID.containsKey(phantomRef)) { int id = PHANTOM_TO_BUFFER_ID.get(phantomRef); - destroyBufferId(true, id); + destroyBufferIdAsync(id); } phantomRef = PHANTOM_REFERENCE_QUEUE.poll(); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/buffer/GLElementBuffer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/buffer/GLElementBuffer.java index 1dd5289ab..3d394075c 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/buffer/GLElementBuffer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/buffer/GLElementBuffer.java @@ -35,7 +35,7 @@ public class GLElementBuffer extends GLBuffer * bigger than the upload payload */ protected int indicesCount = 0; - public int getIndicesCount() { return indicesCount; } + public int getIndicesCount() { return this.indicesCount; } protected int type = GL32.GL_UNSIGNED_INT; public int getType() { return type; } @@ -45,10 +45,10 @@ public class GLElementBuffer extends GLBuffer } @Override - public void destroy(boolean async) + public void destroyAsync() { - super.destroy(async); - indicesCount = 0; + super.destroyAsync(); + this.indicesCount = 0; } @Override 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 05fbe1287..f3957ef56 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 @@ -39,7 +39,7 @@ public class GLVertexBuffer extends GLBuffer * bigger than the upload payload */ protected int vertexCount = 0; - public int getVertexCount() { return vertexCount; } + public int getVertexCount() { return this.vertexCount; } // FIXME: This setter is needed for premapping buffer to manually set the vertexCount. Fix this. public void setVertexCount(int vertexCount) { this.vertexCount = vertexCount; } @@ -52,9 +52,9 @@ public class GLVertexBuffer extends GLBuffer @Override - public void destroy(boolean async) + public void destroyAsync() { - super.destroy(async); + super.destroyAsync(); this.vertexCount = 0; } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java index b8ec6d63f..6ea356fd8 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java @@ -849,7 +849,7 @@ public class LodRenderer } if (this.quadIBO != null) - this.quadIBO.destroy(false); + this.quadIBO.destroyAsync(); // Delete framebuffer, color texture, and depth texture if (this.framebuffer != null && !this.usingMcFrameBuffer) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/TestRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/TestRenderer.java index 5d13b95d5..9050f3083 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/TestRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/TestRenderer.java @@ -97,8 +97,7 @@ public class TestRenderer private void createBuffer() { - GLProxy.getInstance().recordOpenGlCall(() -> sharedContextBuffer = createTextingBuffer()); - GLProxy.ensureAllGLJobCompleted(); + sharedContextBuffer = createTextingBuffer(); sameContextBuffer = createTextingBuffer(); }