Merge branch 'main' of https://gitlab.com/jeseibel/distant-horizons-core into refactor/remove-tcp-connection
This commit is contained in:
+30
-3
@@ -1,14 +1,41 @@
|
||||
package com.seibel.distanthorizons.api.enums.config;
|
||||
|
||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||
|
||||
/**
|
||||
* AUTO, <br>
|
||||
* STABLE, <br>
|
||||
* NIGHTLY, <br><br>
|
||||
*
|
||||
* @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. <Br><br>
|
||||
*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -42,7 +42,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.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");
|
||||
|
||||
|
||||
@@ -1118,16 +1118,6 @@ public class Config
|
||||
+ "")
|
||||
.build();
|
||||
|
||||
public static ConfigEntry<Boolean> gpuUploadAsync = new ConfigEntry.Builder<Boolean>()
|
||||
.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
|
||||
@@ -1147,11 +1137,12 @@ public class Config
|
||||
.build();
|
||||
|
||||
public static ConfigEntry<EDhApiUpdateBranch> updateBranch = new ConfigEntry.Builder<EDhApiUpdateBranch>()
|
||||
.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();
|
||||
}
|
||||
|
||||
|
||||
+6
-2
@@ -271,7 +271,11 @@ public class ConfigFileHandling
|
||||
if (SingletonInjector.INSTANCE.get(IMinecraftSharedWrapper.class).isDedicatedServer() && entry.getServersideShortName() == null)
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -393,4 +397,4 @@ public class ConfigFileHandling
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
+1
-2
@@ -82,8 +82,7 @@ public class OpenGLConfigScreen extends AbstractScreen
|
||||
|
||||
private void createBuffer()
|
||||
{
|
||||
GLProxy.getInstance().recordOpenGlCall(() -> sharedContextBuffer = createTextingBuffer());
|
||||
GLProxy.ensureAllGLJobCompleted();
|
||||
sharedContextBuffer = createTextingBuffer();
|
||||
sameContextBuffer = createTextingBuffer();
|
||||
}
|
||||
|
||||
|
||||
+24
-47
@@ -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<Void> 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<Void> 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();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.distanthorizons.core.enums;
|
||||
|
||||
/**
|
||||
* Minecraft, <br>
|
||||
* Lod_Builder, <br>
|
||||
* Proxy_Worker, <br>
|
||||
* None <br>
|
||||
*
|
||||
* @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,
|
||||
}
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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<Pair<Integer, Integer>> 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<Runnable> renderThreadRunnableQueue = new ConcurrentLinkedQueue<>();
|
||||
|
||||
private ConcurrentLinkedQueue<Runnable> 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<Pair<Integer, Integer>> glVersions = new ArrayList<>();
|
||||
if (majorGlVersion != 0)
|
||||
{
|
||||
glVersions.add(new Pair<>(majorGlVersion, minorGlVersion));
|
||||
}
|
||||
else
|
||||
{
|
||||
glVersions.addAll(SUPPORTED_GL_VERSIONS);
|
||||
}
|
||||
|
||||
for (Pair<Integer, Integer> 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. <br>
|
||||
* 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. <br>
|
||||
* 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();
|
||||
}
|
||||
|
||||
+27
-35
@@ -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<? extends GLBuffer> 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<? extends GLBuffer> 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();
|
||||
|
||||
+4
-4
@@ -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
|
||||
|
||||
+3
-3
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
+1
-2
@@ -97,8 +97,7 @@ public class TestRenderer
|
||||
|
||||
private void createBuffer()
|
||||
{
|
||||
GLProxy.getInstance().recordOpenGlCall(() -> sharedContextBuffer = createTextingBuffer());
|
||||
GLProxy.ensureAllGLJobCompleted();
|
||||
sharedContextBuffer = createTextingBuffer();
|
||||
sameContextBuffer = createTextingBuffer();
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -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:
|
||||
|
||||
@@ -941,6 +941,8 @@
|
||||
"Stable",
|
||||
"distanthorizons.config.enum.EDhApiUpdateBranch.NIGHTLY":
|
||||
"Nightly",
|
||||
"distanthorizons.config.enum.EDhApiUpdateBranch.AUTO":
|
||||
"Auto",
|
||||
|
||||
"distanthorizons.config.enum.EDhApiGrassSideRendering.AS_GRASS":
|
||||
"As Grass",
|
||||
|
||||
Reference in New Issue
Block a user