Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 91f9ef3f4b | |||
| d52a3abb14 | |||
| 16370b0b6e | |||
| bfa60b48cf | |||
| 50518bfe21 | |||
| 80e4467829 | |||
| 396315bd05 | |||
| 7a0fec2c2f | |||
| 4afaaa7b12 | |||
| b057041467 | |||
| 33e6ce6376 | |||
| 118ef39c30 | |||
| 1013e1c824 | |||
| b0e924c7fe | |||
| 1777acd1d4 | |||
| 8276a862f8 | |||
| 4329acf91d | |||
| 72f83b40f7 | |||
| a33eb30a53 | |||
| d3e96f50a8 | |||
| 3aefeb98b4 | |||
| 3553ff8e60 | |||
| 945a2c0c5a | |||
| 8c7974e216 | |||
| 37756cd759 | |||
| c60cc4f013 | |||
| 87cce2e33c | |||
| 40ada9c186 | |||
| 55fb458266 | |||
| 79d2466fa2 | |||
| d750e489df | |||
| a206e49b2b | |||
| e5536de44f |
@@ -25,6 +25,8 @@ hs_err_pid*
|
|||||||
Merged/
|
Merged/
|
||||||
# Folder created by the buildAll scripts
|
# Folder created by the buildAll scripts
|
||||||
buildAllJars/
|
buildAllJars/
|
||||||
|
_buildAllJars/
|
||||||
|
_buildWorkers/
|
||||||
|
|
||||||
relocate_natives/.venv/
|
relocate_natives/.venv/
|
||||||
relocate_natives/__pycache__/
|
relocate_natives/__pycache__/
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
@echo off & setlocal enabledelayedexpansion
|
||||||
|
|
||||||
|
|
||||||
|
echo ==================== Getting versions to build... ====================
|
||||||
|
mkdir _buildAllJars 2>nul
|
||||||
|
del _buildAllJars\* /Q 2>nul
|
||||||
|
|
||||||
|
set "ROOT=%~dp0"
|
||||||
|
set "WORK_DIR=%ROOT%_buildWorkers"
|
||||||
|
mkdir "%WORK_DIR%" 2>nul
|
||||||
|
|
||||||
|
|
||||||
|
REM get the number of versions to compile
|
||||||
|
set count=0
|
||||||
|
for %%f in (versionProperties\*) do set /a count+=1
|
||||||
|
echo ==================== Found %count% versions to build in parallel ====================
|
||||||
|
|
||||||
|
REM Launch a parallel job for each version
|
||||||
|
for %%f in (%ROOT%versionProperties\*) do (
|
||||||
|
set version=%%~nf
|
||||||
|
|
||||||
|
echo starting [!version!]...
|
||||||
|
start "Build !version!" cmd /c ""%ROOT%build_worker.bat" "!version!" "%ROOT%" "%WORK_DIR%" ""..\..\_buildAllJars"""
|
||||||
|
|
||||||
|
REM Minor timeout between launches so we can stop the build early if we only want
|
||||||
|
REM to test part of the script and to reduce startup load
|
||||||
|
timeout /t 3 /nobreak
|
||||||
|
|
||||||
|
REM 2>nul to supress a harmless warning that the for loop
|
||||||
|
REM "cannot find the drive specified"
|
||||||
|
) 2>nul
|
||||||
|
|
||||||
|
|
||||||
|
echo ==================== All builds started... Completed Jars will be in _buildAllJars ====================
|
||||||
|
endlocal
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
@echo off & setlocal enabledelayedexpansion
|
||||||
|
|
||||||
|
set "VERSION=%~1"
|
||||||
|
set "ROOT=%~2"
|
||||||
|
set "WORK_DIR=%~3"
|
||||||
|
set "WORKER=%WORK_DIR%\%VERSION%"
|
||||||
|
set "JAR_OUTPUT_DIR=%~4"
|
||||||
|
|
||||||
|
REM remove the ending "\" from the root folder, otherwise the final quote
|
||||||
|
REM in the robocopy command will be escaped and it won't run
|
||||||
|
if "%ROOT:~-1%"=="\" set "ROOT=%ROOT:~0,-1%"
|
||||||
|
set "WORKER=%~3\%~1"
|
||||||
|
|
||||||
|
set "BUILT_JAR_DIR=%WORKER%\build\forgix"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
echo ==================== [%VERSION%] Copying workspace ====================
|
||||||
|
mkdir "%WORKER%"
|
||||||
|
robocopy "%ROOT%" "%WORKER%" /E /XD "%WORKER%" "_buildWorkers" "buildAllJars" ".gradle" "build" ".git" ".idea" ".gitlab" "run" "testScripts" /NFL /NDL
|
||||||
|
|
||||||
|
echo ==================== [%VERSION%] Cleaning ====================
|
||||||
|
cd /d "%WORKER%"
|
||||||
|
call .\gradlew.bat clean
|
||||||
|
REM optional arg that can be added if we want to log the result to a file
|
||||||
|
REM >"%WORK_DIR%\build_%VERSION%.log" 2>&1
|
||||||
|
|
||||||
|
echo ==================== [%VERSION%] Assembling ====================
|
||||||
|
call .\gradlew.bat assemble -PmcVer="%VERSION%"
|
||||||
|
REM optional arg that can be added if we want to log the result to a file
|
||||||
|
REM >>"%WORK_DIR%\build_%VERSION%.log" 2>&1
|
||||||
|
|
||||||
|
echo ==================== [%VERSION%] Exporting ====================
|
||||||
|
mkdir "%JAR_OUTPUT_DIR%"
|
||||||
|
robocopy "%BUILT_JAR_DIR%" "%JAR_OUTPUT_DIR%" /NFL /NDL
|
||||||
|
|
||||||
|
echo ==================== [%VERSION%] Done ====================
|
||||||
|
endlocal
|
||||||
|
|
||||||
|
REM can be uncommented for debugging
|
||||||
|
REM pause
|
||||||
@@ -8,8 +8,8 @@ import com.seibel.distanthorizons.common.commands.CommandInitializer;
|
|||||||
import com.seibel.distanthorizons.common.wrappers.DependencySetup;
|
import com.seibel.distanthorizons.common.wrappers.DependencySetup;
|
||||||
import com.seibel.distanthorizons.common.wrappers.gui.DhDebugScreenEntry;
|
import com.seibel.distanthorizons.common.wrappers.gui.DhDebugScreenEntry;
|
||||||
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftServerWrapper;
|
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftServerWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.Initializer;
|
||||||
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
||||||
import com.seibel.distanthorizons.core.api.internal.SharedApi;
|
|
||||||
import com.seibel.distanthorizons.core.config.Config;
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
import com.seibel.distanthorizons.core.config.ConfigHandler;
|
import com.seibel.distanthorizons.core.config.ConfigHandler;
|
||||||
import com.seibel.distanthorizons.core.config.eventHandlers.presets.ThreadPresetConfigEventHandler;
|
import com.seibel.distanthorizons.core.config.eventHandlers.presets.ThreadPresetConfigEventHandler;
|
||||||
@@ -95,7 +95,8 @@ public abstract class AbstractModInitializer
|
|||||||
|
|
||||||
// Client uses config for auto-updater, so it's initialized here instead of post-init stage
|
// Client uses config for auto-updater, so it's initialized here instead of post-init stage
|
||||||
this.initConfig();
|
this.initConfig();
|
||||||
logModIncompatibilityWarnings(); // needs to be called after config loading
|
logIncompatibilityWarnings(); // needs to be called after config loading
|
||||||
|
Initializer.postConfigInit();
|
||||||
|
|
||||||
LOGGER.info(ModInfo.READABLE_NAME + " client Initialized.");
|
LOGGER.info(ModInfo.READABLE_NAME + " client Initialized.");
|
||||||
|
|
||||||
@@ -137,6 +138,7 @@ public abstract class AbstractModInitializer
|
|||||||
MinecraftServerWrapper.INSTANCE.dedicatedServer = (DedicatedServer)server;
|
MinecraftServerWrapper.INSTANCE.dedicatedServer = (DedicatedServer)server;
|
||||||
|
|
||||||
this.initConfig();
|
this.initConfig();
|
||||||
|
Initializer.postConfigInit();
|
||||||
this.postInit();
|
this.postInit();
|
||||||
this.postServerInit();
|
this.postServerInit();
|
||||||
this.commandInitializer.onServerReady();
|
this.commandInitializer.onServerReady();
|
||||||
@@ -159,7 +161,7 @@ public abstract class AbstractModInitializer
|
|||||||
private void startup()
|
private void startup()
|
||||||
{
|
{
|
||||||
DependencySetup.createSharedBindings();
|
DependencySetup.createSharedBindings();
|
||||||
SharedApi.init();
|
Initializer.preConfigInit();
|
||||||
this.createInitialSharedBindings();
|
this.createInitialSharedBindings();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,9 +263,9 @@ public abstract class AbstractModInitializer
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
//==================================//
|
//======================//
|
||||||
// mod partial compatibility checks //
|
// compatibility checks //
|
||||||
//==================================//
|
//======================//
|
||||||
//region
|
//region
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -272,7 +274,7 @@ public abstract class AbstractModInitializer
|
|||||||
* This method will log (and display to chat if enabled)
|
* This method will log (and display to chat if enabled)
|
||||||
* these warnings and potential fixes.
|
* these warnings and potential fixes.
|
||||||
*/
|
*/
|
||||||
private static void logModIncompatibilityWarnings()
|
private static void logIncompatibilityWarnings()
|
||||||
{
|
{
|
||||||
boolean showChatWarnings = Config.Common.Logging.Warning.showModCompatibilityWarningsOnStartup.get();
|
boolean showChatWarnings = Config.Common.Logging.Warning.showModCompatibilityWarningsOnStartup.get();
|
||||||
IModChecker modChecker = SingletonInjector.INSTANCE.get(IModChecker.class);
|
IModChecker modChecker = SingletonInjector.INSTANCE.get(IModChecker.class);
|
||||||
|
|||||||
+21
-21
@@ -299,27 +299,27 @@ public class BlazeDebugWireframeRenderer extends AbstractDebugWireframeRenderer
|
|||||||
|
|
||||||
// render //
|
// render //
|
||||||
|
|
||||||
//try (RenderPass renderPass = commandEncoder.createRenderPass(
|
try (RenderPass renderPass = commandEncoder.createRenderPass(
|
||||||
// this::getRenderPassName,
|
this::getRenderPassName,
|
||||||
// BlazeDhMetaRenderer.INSTANCE.dhColorTextureWrapper.textureView,
|
BlazeDhMetaRenderer.INSTANCE.dhColorTextureWrapper.textureView,
|
||||||
// /*optionalClearColorAsInt*/ OptionalInt.empty(),
|
/*optionalClearColorAsInt*/ OptionalInt.empty(),
|
||||||
// BlazeDhMetaRenderer.INSTANCE.dhDepthTextureWrapper.textureView,
|
BlazeDhMetaRenderer.INSTANCE.dhDepthTextureWrapper.textureView,
|
||||||
// /*optionalDepthValueAsDouble*/ OptionalDouble.empty()))
|
/*optionalDepthValueAsDouble*/ OptionalDouble.empty()))
|
||||||
//{
|
{
|
||||||
// // Bind instance data //
|
// Bind instance data //
|
||||||
// renderPass.setUniform("uniformBlock", this.uniformBuffer);
|
renderPass.setUniform("uniformBlock", this.uniformBuffer);
|
||||||
//
|
|
||||||
// renderPass.setPipeline(this.pipeline);
|
renderPass.setPipeline(this.pipeline);
|
||||||
// renderPass.setIndexBuffer(this.boxIndexBuffer, VertexFormat.IndexType.INT);
|
renderPass.setIndexBuffer(this.boxIndexBuffer, VertexFormat.IndexType.INT);
|
||||||
//
|
|
||||||
// renderPass.setVertexBuffer(0, this.boxVertexBuffer);
|
renderPass.setVertexBuffer(0, this.boxVertexBuffer);
|
||||||
//
|
|
||||||
// renderPass.drawIndexed(
|
renderPass.drawIndexed(
|
||||||
// /*indexStart*/ 0,
|
/*indexStart*/ 0,
|
||||||
// /*firstIndex*/0,
|
/*firstIndex*/0,
|
||||||
// /*indexCount*/BOX_OUTLINE_INDICES.length,
|
/*indexCount*/BOX_OUTLINE_INDICES.length,
|
||||||
// /*instanceCount*/1);
|
/*instanceCount*/1);
|
||||||
//}
|
}
|
||||||
}
|
}
|
||||||
private String getRenderPassName() { return "distantHorizons:McDebugRenderer"; }
|
private String getRenderPassName() { return "distantHorizons:McDebugRenderer"; }
|
||||||
|
|
||||||
|
|||||||
+3
@@ -19,6 +19,7 @@ import com.mojang.blaze3d.systems.RenderPass;
|
|||||||
import com.mojang.blaze3d.systems.RenderSystem;
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||||
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeBufferRenderEvent;
|
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeBufferRenderEvent;
|
||||||
|
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeRenderPassEvent;
|
||||||
import com.seibel.distanthorizons.common.render.blaze.util.BlazeDhVertexFormatUtil;
|
import com.seibel.distanthorizons.common.render.blaze.util.BlazeDhVertexFormatUtil;
|
||||||
import com.seibel.distanthorizons.common.render.blaze.util.BlazeUniformUtil;
|
import com.seibel.distanthorizons.common.render.blaze.util.BlazeUniformUtil;
|
||||||
import com.seibel.distanthorizons.common.render.blaze.wrappers.RenderPipelineBuilderWrapper;
|
import com.seibel.distanthorizons.common.render.blaze.wrappers.RenderPipelineBuilderWrapper;
|
||||||
@@ -267,6 +268,8 @@ public class BlazeDhTerrainRenderer implements IDhTerrainRenderer
|
|||||||
{
|
{
|
||||||
profiler.popPush("rendering");
|
profiler.popPush("rendering");
|
||||||
|
|
||||||
|
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeRenderPassEvent.class, renderEventParam);
|
||||||
|
|
||||||
// create a render pass
|
// create a render pass
|
||||||
try (RenderPass renderPass = COMMAND_ENCODER.createRenderPass(
|
try (RenderPass renderPass = COMMAND_ENCODER.createRenderPass(
|
||||||
this::getRenderPassName,
|
this::getRenderPassName,
|
||||||
|
|||||||
-2
@@ -10,7 +10,6 @@ import com.seibel.distanthorizons.common.render.openGl.glObject.GLProxy;
|
|||||||
import com.seibel.distanthorizons.common.render.openGl.glObject.GlDhFramebuffer;
|
import com.seibel.distanthorizons.common.render.openGl.glObject.GlDhFramebuffer;
|
||||||
import com.seibel.distanthorizons.common.render.openGl.glObject.texture.*;
|
import com.seibel.distanthorizons.common.render.openGl.glObject.texture.*;
|
||||||
import com.seibel.distanthorizons.common.render.openGl.postProcessing.apply.GlDhApplyShader;
|
import com.seibel.distanthorizons.common.render.openGl.postProcessing.apply.GlDhApplyShader;
|
||||||
import com.seibel.distanthorizons.common.render.openGl.terrain.GlDhTerrainShaderProgram;
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftGLWrapper;
|
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftGLWrapper;
|
||||||
import com.seibel.distanthorizons.common.wrappers.misc.LightMapWrapper;
|
import com.seibel.distanthorizons.common.wrappers.misc.LightMapWrapper;
|
||||||
import com.seibel.distanthorizons.core.config.Config;
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
@@ -22,7 +21,6 @@ import com.seibel.distanthorizons.core.render.DhApiRenderProxy;
|
|||||||
import com.seibel.distanthorizons.core.render.RenderParams;
|
import com.seibel.distanthorizons.core.render.RenderParams;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.ILightMapWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.ILightMapWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.AbstractOptifineAccessor;
|
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IOptifineAccessor;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IOptifineAccessor;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhMetaRenderer;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhMetaRenderer;
|
||||||
import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector;
|
import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector;
|
||||||
|
|||||||
+97
-39
@@ -21,7 +21,6 @@ package com.seibel.distanthorizons.common.render.openGl.glObject.buffer;
|
|||||||
|
|
||||||
import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod;
|
import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod;
|
||||||
import com.seibel.distanthorizons.common.render.openGl.glObject.GLProxy;
|
import com.seibel.distanthorizons.common.render.openGl.glObject.GLProxy;
|
||||||
import com.seibel.distanthorizons.common.render.openGl.glObject.GLState;
|
|
||||||
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftGLWrapper;
|
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftGLWrapper;
|
||||||
import com.seibel.distanthorizons.core.config.Config;
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
@@ -39,6 +38,7 @@ import java.nio.ByteBuffer;
|
|||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.concurrent.locks.StampedLock;
|
||||||
|
|
||||||
public class GLBuffer implements AutoCloseable
|
public class GLBuffer implements AutoCloseable
|
||||||
{
|
{
|
||||||
@@ -62,14 +62,24 @@ public class GLBuffer implements AutoCloseable
|
|||||||
private static final ThreadPoolExecutor CLEANUP_THREAD = ThreadUtil.makeSingleDaemonThreadPool("GLBuffer Cleanup");
|
private static final ThreadPoolExecutor CLEANUP_THREAD = ThreadUtil.makeSingleDaemonThreadPool("GLBuffer Cleanup");
|
||||||
|
|
||||||
|
|
||||||
protected int id;
|
protected volatile int id = 0;
|
||||||
public final int getId() { return this.id; }
|
public final int getId() { return this.id; }
|
||||||
protected int size = 0;
|
protected int size = 0;
|
||||||
public int getSize() { return this.size; }
|
public int getSize() { return this.size; }
|
||||||
protected boolean bufferStorage;
|
protected boolean bufferStorage;
|
||||||
public final boolean isBufferStorage() { return this.bufferStorage; }
|
|
||||||
protected boolean isMapped = false;
|
protected boolean isMapped = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Locking on the render thread isn't great, but is needed due to an inconsistent
|
||||||
|
* race condition where VBOs can be marked as deleted outside the render thread. <br><br>
|
||||||
|
*
|
||||||
|
* But, due to being a read-write lock the chance of freezing
|
||||||
|
* the render thread is very low
|
||||||
|
* and since this is a stamped lock, the optimistic read time is basically zero.
|
||||||
|
* (The optimistic lock time doesn't even appear in the profiler).
|
||||||
|
*/
|
||||||
|
public final StampedLock renderStampLock = new StampedLock();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//==============//
|
//==============//
|
||||||
@@ -112,36 +122,73 @@ public class GLBuffer implements AutoCloseable
|
|||||||
LodUtil.assertNotReach("Thread ["+Thread.currentThread()+"] tried to create a GLBuffer outside the MC render thread.");
|
LodUtil.assertNotReach("Thread ["+Thread.currentThread()+"] tried to create a GLBuffer outside the MC render thread.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// destroy the old buffer if one is present
|
|
||||||
if (this.id != 0)
|
// lock to prevent the render thread from accessing the buffer's ID
|
||||||
|
// while we are removing it
|
||||||
|
long writeStamp = renderStampLock.writeLock();
|
||||||
|
try
|
||||||
{
|
{
|
||||||
destroyBufferIdNow(this.id);
|
int oldId = this.id;
|
||||||
|
this.id = GLMC.glGenBuffers();
|
||||||
|
|
||||||
|
// destroy the old buffer
|
||||||
|
// after the new one has been created
|
||||||
|
// to hopefully prevent a rare race conditions where the old ID
|
||||||
|
// is still used somewhere
|
||||||
|
if (oldId != 0)
|
||||||
|
{
|
||||||
|
// this ID doesn't need to be tracked anymore
|
||||||
|
tryRemoveBufferIdFromPhantom(oldId);
|
||||||
|
destroyBufferIdNow(oldId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
this.bufferStorage = asBufferStorage;
|
||||||
|
bufferCount.getAndIncrement();
|
||||||
|
|
||||||
|
PhantomReference<GLBuffer> phantom = new PhantomReference<>(this, PHANTOM_REFERENCE_QUEUE);
|
||||||
|
PHANTOM_TO_BUFFER_ID.put(phantom, this.id);
|
||||||
|
BUFFER_ID_TO_PHANTOM.put(this.id, phantom);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
renderStampLock.unlock(writeStamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.id = GLMC.glGenBuffers();
|
|
||||||
this.bufferStorage = asBufferStorage;
|
|
||||||
bufferCount.getAndIncrement();
|
|
||||||
|
|
||||||
PhantomReference<GLBuffer> phantom = new PhantomReference<>(this, PHANTOM_REFERENCE_QUEUE);
|
|
||||||
PHANTOM_TO_BUFFER_ID.put(phantom, this.id);
|
|
||||||
BUFFER_ID_TO_PHANTOM.put(this.id, phantom);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void destroyAsync()
|
protected void destroyAsync()
|
||||||
{
|
{
|
||||||
if (this.id == 0)
|
// lock to prevent the render thread from accessing the buffer's ID
|
||||||
|
// while we are removing it
|
||||||
|
long writeStamp = renderStampLock.writeLock();
|
||||||
|
try
|
||||||
{
|
{
|
||||||
// the buffer has already been closed
|
if (this.id == 0)
|
||||||
return;
|
{
|
||||||
|
// the buffer has already been closed
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int idToDelete = this.id; // saving the ID to a separate variable is necessary so it can be captured by the lambda
|
||||||
|
|
||||||
|
// remove the phantom tracking now so the phantom doesn't have the chance to
|
||||||
|
// get garbage collected before the render thread task runs
|
||||||
|
// (this can happen if MC is running at extremely low framerates like 1 fps via mods)
|
||||||
|
tryRemoveBufferIdFromPhantom(idToDelete);
|
||||||
|
|
||||||
|
// mark the old data is invalid before deleting to prevent a rare race condition
|
||||||
|
// where the queued on render thread task runs before the ID is cleared
|
||||||
|
this.id = 0;
|
||||||
|
this.size = 0;
|
||||||
|
|
||||||
|
RenderThreadTaskHandler.INSTANCE.queueRunningOnRenderThread("GLBuffer destroyAsync", () -> { destroyBufferIdNow(idToDelete); });
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
renderStampLock.unlock(writeStamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
final int idToDelete = this.id; // saving the ID to a separate variable is necessary so it can be captured by the lambda
|
|
||||||
RenderThreadTaskHandler.INSTANCE.queueRunningOnRenderThread("GLBuffer destroyAsync", () -> { destroyBufferIdNow(idToDelete); });
|
|
||||||
|
|
||||||
this.id = 0;
|
|
||||||
this.size = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void destroyBufferIdNow(int id)
|
private static void destroyBufferIdNow(int id)
|
||||||
{
|
{
|
||||||
// only delete valid buffers
|
// only delete valid buffers
|
||||||
@@ -151,20 +198,6 @@ public class GLBuffer implements AutoCloseable
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove and clear the phantom reference if present
|
|
||||||
if (BUFFER_ID_TO_PHANTOM.containsKey(id))
|
|
||||||
{
|
|
||||||
Reference<? extends GLBuffer> phantom = BUFFER_ID_TO_PHANTOM.get(id);
|
|
||||||
|
|
||||||
// if we are manually closing this buffer, we don't want the phantom reference to accidentally close it again
|
|
||||||
// this can cause a race condition were we accidentally delete an in-use buffer and cause NVIDIA
|
|
||||||
// to throw an EXCEPTION_ACCESS_VIOLATION when we attempt to render it
|
|
||||||
phantom.clear();
|
|
||||||
|
|
||||||
PHANTOM_TO_BUFFER_ID.remove(phantom);
|
|
||||||
BUFFER_ID_TO_PHANTOM.remove(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
bufferCount.decrementAndGet();
|
bufferCount.decrementAndGet();
|
||||||
|
|
||||||
// destroy the buffer if it exists,
|
// destroy the buffer if it exists,
|
||||||
@@ -178,6 +211,32 @@ public class GLBuffer implements AutoCloseable
|
|||||||
LOGGER.info("destroyed buffer [" + id + "], remaining: [" + BUFFER_ID_TO_PHANTOM.size() + "]");
|
LOGGER.info("destroyed buffer [" + id + "], remaining: [" + BUFFER_ID_TO_PHANTOM.size() + "]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// shouldn't happen, but just in case
|
||||||
|
LOGGER.warn("Attempted to destroy a non buffer object with ID ["+id+"].");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** should be called before {@link GLBuffer#destroyBufferIdNow} */
|
||||||
|
private static void tryRemoveBufferIdFromPhantom(int id)
|
||||||
|
{
|
||||||
|
if (BUFFER_ID_TO_PHANTOM.containsKey(id))
|
||||||
|
{
|
||||||
|
Reference<? extends GLBuffer> phantom = BUFFER_ID_TO_PHANTOM.get(id);
|
||||||
|
|
||||||
|
// if we are manually closing this buffer, we don't want the phantom reference to accidentally close it again
|
||||||
|
// this can cause a race condition were we accidentally delete an in-use buffer and cause NVIDIA
|
||||||
|
// to throw an EXCEPTION_ACCESS_VIOLATION when we attempt to render it
|
||||||
|
phantom.clear();
|
||||||
|
|
||||||
|
PHANTOM_TO_BUFFER_ID.remove(phantom);
|
||||||
|
BUFFER_ID_TO_PHANTOM.remove(id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOGGER.warn("Unable to remove phantom GLBuffer with ID ["+id+"], buffer may have already been deleted.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
@@ -321,7 +380,6 @@ public class GLBuffer implements AutoCloseable
|
|||||||
{
|
{
|
||||||
// recreate if the buffer storage type changed
|
// recreate if the buffer storage type changed
|
||||||
this.bind();
|
this.bind();
|
||||||
destroyBufferIdNow(this.id);
|
|
||||||
this.destroyOldAndCreate(uploadMethod.useBufferStorage);
|
this.destroyOldAndCreate(uploadMethod.useBufferStorage);
|
||||||
this.bind();
|
this.bind();
|
||||||
}
|
}
|
||||||
|
|||||||
+46
-17
@@ -289,6 +289,9 @@ public class GlDhTerrainShaderProgram extends GlShaderProgram implements IDhApiS
|
|||||||
GLMC.disableBlend();
|
GLMC.disableBlend();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// needs to be triggered after DH attempts to set the GL state so that Iris
|
||||||
|
// can override it as needed
|
||||||
|
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeRenderPassEvent.class, renderEventParam);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -311,6 +314,12 @@ public class GlDhTerrainShaderProgram extends GlShaderProgram implements IDhApiS
|
|||||||
for (int lodIndex = 0; lodIndex < bufferContainers.size(); lodIndex++)
|
for (int lodIndex = 0; lodIndex < bufferContainers.size(); lodIndex++)
|
||||||
{
|
{
|
||||||
LodBufferContainer bufferContainer = bufferContainers.get(lodIndex);
|
LodBufferContainer bufferContainer = bufferContainers.get(lodIndex);
|
||||||
|
if (!bufferContainer.buffersUploaded)
|
||||||
|
{
|
||||||
|
// make sure we don't accidentally try
|
||||||
|
// rendering a buffer that is (or is going to be) freed
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// set uniforms and fire events
|
// set uniforms and fire events
|
||||||
{
|
{
|
||||||
@@ -335,25 +344,45 @@ public class GlDhTerrainShaderProgram extends GlShaderProgram implements IDhApiS
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vbo.getVertexCount() == 0)
|
|
||||||
|
// for lock information please view the lock's javadocs
|
||||||
|
long vboReadStamp = vbo.renderStampLock.readLock();
|
||||||
|
long iboReadStamp = vbo.getQuadIBO().renderStampLock.readLock();
|
||||||
|
try
|
||||||
{
|
{
|
||||||
continue;
|
// don't render empty sections
|
||||||
|
if (vbo.getVertexCount() == 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't render deleted VBOs (this will crash the driver/game)
|
||||||
|
if (vbo.getId() == 0
|
||||||
|
|| vbo.getQuadIBO().getId() == 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4 vertices per face, but 6 indices (IE 2 triangles) per face, aka need to multiply by 1.5
|
||||||
|
int indexCount = (int) (vbo.getVertexCount() * 1.5);
|
||||||
|
|
||||||
|
vbo.bind();
|
||||||
|
vbo.getQuadIBO().bind();
|
||||||
|
|
||||||
|
GlDhMetaRenderer.INSTANCE.shaderProgramForThisFrame.bindVertexBuffer(vbo.getId());
|
||||||
|
GL32.glDrawElements(
|
||||||
|
GL32.GL_TRIANGLES,
|
||||||
|
indexCount,
|
||||||
|
vbo.getQuadIBO().getGlType(), 0);
|
||||||
|
|
||||||
|
vbo.unbind();
|
||||||
|
vbo.getQuadIBO().unbind();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
vbo.renderStampLock.unlock(vboReadStamp);
|
||||||
|
vbo.getQuadIBO().renderStampLock.unlock(iboReadStamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4 vertices per face, but 6 indices (IE 2 triangles) per face, aka need to multiply by 1.5
|
|
||||||
int indexCount = (int)(vbo.getVertexCount() * 1.5);
|
|
||||||
|
|
||||||
vbo.bind();
|
|
||||||
vbo.getQuadIBO().bind();
|
|
||||||
|
|
||||||
GlDhMetaRenderer.INSTANCE.shaderProgramForThisFrame.bindVertexBuffer(vbo.getId());
|
|
||||||
GL32.glDrawElements(
|
|
||||||
GL32.GL_TRIANGLES,
|
|
||||||
indexCount,
|
|
||||||
vbo.getQuadIBO().getGlType(), 0);
|
|
||||||
|
|
||||||
vbo.unbind();
|
|
||||||
vbo.getQuadIBO().unbind();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-1
@@ -80,9 +80,20 @@ public class DependencySetup
|
|||||||
SingletonInjector.INSTANCE.bind(IConfigGui.class, ClassicConfigGUI.CONFIG_CORE_INTERFACE);
|
SingletonInjector.INSTANCE.bind(IConfigGui.class, ClassicConfigGUI.CONFIG_CORE_INTERFACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean renderingApiBindingsSet = false;
|
||||||
/** will be called from a DH thread, not the render thread */
|
/** will be called from a DH thread, not the render thread */
|
||||||
public static void setRenderingApiBindings()
|
public synchronized static void setRenderingApiBindings()
|
||||||
{
|
{
|
||||||
|
// shouldn't happen, but there was a single report that this method was triggered twice
|
||||||
|
if (renderingApiBindingsSet)
|
||||||
|
{
|
||||||
|
LOGGER.warn("Rendering bindings already set, skipping. How did this happen?");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
renderingApiBindingsSet = true;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
EDhApiRenderApi renderingApiEnum = Config.Client.Advanced.Graphics.Experimental.renderingApi.get();
|
EDhApiRenderApi renderingApiEnum = Config.Client.Advanced.Graphics.Experimental.renderingApi.get();
|
||||||
if (renderingApiEnum == EDhApiRenderApi.AUTO)
|
if (renderingApiEnum == EDhApiRenderApi.AUTO)
|
||||||
{
|
{
|
||||||
|
|||||||
+2
-17
@@ -154,22 +154,12 @@ public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironm
|
|||||||
|
|
||||||
static
|
static
|
||||||
{
|
{
|
||||||
boolean isTerraFirmaCraftPresent = false;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Class.forName("net.dries007.tfc.world.TFCChunkGenerator");
|
|
||||||
isTerraFirmaCraftPresent = true;
|
|
||||||
LOGGER.info("TerraFirmaCraft detected.");
|
|
||||||
}
|
|
||||||
catch (ClassNotFoundException ignore) { }
|
|
||||||
|
|
||||||
|
|
||||||
ImmutableMap.Builder<EDhApiWorldGenerationStep, Integer> builder = ImmutableMap.builder();
|
ImmutableMap.Builder<EDhApiWorldGenerationStep, Integer> builder = ImmutableMap.builder();
|
||||||
builder.put(EDhApiWorldGenerationStep.EMPTY, 1);
|
builder.put(EDhApiWorldGenerationStep.EMPTY, 1);
|
||||||
builder.put(EDhApiWorldGenerationStep.STRUCTURE_START, 0);
|
builder.put(EDhApiWorldGenerationStep.STRUCTURE_START, 0);
|
||||||
builder.put(EDhApiWorldGenerationStep.STRUCTURE_REFERENCE, 0);
|
builder.put(EDhApiWorldGenerationStep.STRUCTURE_REFERENCE, 0);
|
||||||
builder.put(EDhApiWorldGenerationStep.BIOMES, isTerraFirmaCraftPresent ? 1 : 0);
|
builder.put(EDhApiWorldGenerationStep.BIOMES, 0);
|
||||||
builder.put(EDhApiWorldGenerationStep.NOISE, isTerraFirmaCraftPresent ? 1 : 0);
|
builder.put(EDhApiWorldGenerationStep.NOISE, 0);
|
||||||
builder.put(EDhApiWorldGenerationStep.SURFACE, 0);
|
builder.put(EDhApiWorldGenerationStep.SURFACE, 0);
|
||||||
builder.put(EDhApiWorldGenerationStep.CARVERS, 0);
|
builder.put(EDhApiWorldGenerationStep.CARVERS, 0);
|
||||||
builder.put(EDhApiWorldGenerationStep.LIQUID_CARVERS, 0);
|
builder.put(EDhApiWorldGenerationStep.LIQUID_CARVERS, 0);
|
||||||
@@ -205,11 +195,6 @@ public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironm
|
|||||||
LOGGER.info("TerraForge Chunk Generator detected: [" + generator.getClass() + "], Distant Generation will try its best to support it.");
|
LOGGER.info("TerraForge Chunk Generator detected: [" + generator.getClass() + "], Distant Generation will try its best to support it.");
|
||||||
LOGGER.info("If it does crash, turn Distant Generation off or set it to to [" + EDhApiDistantGeneratorMode.PRE_EXISTING_ONLY + "].");
|
LOGGER.info("If it does crash, turn Distant Generation off or set it to to [" + EDhApiDistantGeneratorMode.PRE_EXISTING_ONLY + "].");
|
||||||
}
|
}
|
||||||
else if (generator.getClass().toString().equals("class net.dries007.tfc.world.TFCChunkGenerator"))
|
|
||||||
{
|
|
||||||
LOGGER.info("TerraFirmaCraft Chunk Generator detected: [" + generator.getClass() + "], Distant Generation will try its best to support it.");
|
|
||||||
LOGGER.info("If it does crash, turn Distant Generation off or set it to to [" + EDhApiDistantGeneratorMode.PRE_EXISTING_ONLY + "].");
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOGGER.warn("Unknown Chunk Generator detected: [" + generator.getClass() + "], Distant Generation May Fail!");
|
LOGGER.warn("Unknown Chunk Generator detected: [" + generator.getClass() + "], Distant Generation May Fail!");
|
||||||
|
|||||||
+21
-5
@@ -12,11 +12,9 @@ import com.seibel.distanthorizons.core.config.Config;
|
|||||||
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
|
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
|
||||||
import com.seibel.distanthorizons.core.enums.MinecraftTextFormat;
|
import com.seibel.distanthorizons.core.enums.MinecraftTextFormat;
|
||||||
import com.seibel.distanthorizons.core.generation.DhLightingEngine;
|
import com.seibel.distanthorizons.core.generation.DhLightingEngine;
|
||||||
import com.seibel.distanthorizons.core.level.DhServerLevel;
|
|
||||||
import com.seibel.distanthorizons.core.level.IDhServerLevel;
|
import com.seibel.distanthorizons.core.level.IDhServerLevel;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
|
||||||
import com.seibel.distanthorizons.core.util.ExceptionUtil;
|
import com.seibel.distanthorizons.core.util.ExceptionUtil;
|
||||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||||
import com.seibel.distanthorizons.core.util.TimerUtil;
|
import com.seibel.distanthorizons.core.util.TimerUtil;
|
||||||
@@ -195,12 +193,22 @@ public class InternalServerGenerator
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
ArrayList<CompletableFuture<Void>> releaseFutures = new ArrayList<>();
|
||||||
|
|
||||||
// release all chunks from the server to prevent out of memory issues
|
// release all chunks from the server to prevent out of memory issues
|
||||||
Iterator<ChunkPos> chunkPosIterator = ChunkPosGenStream.getIterator(genEvent.minPos.getX(), genEvent.minPos.getZ(), genEvent.widthInChunks, 0);
|
Iterator<ChunkPos> chunkPosIterator = ChunkPosGenStream.getIterator(genEvent.minPos.getX(), genEvent.minPos.getZ(), genEvent.widthInChunks, 0);
|
||||||
while (chunkPosIterator.hasNext())
|
while (chunkPosIterator.hasNext())
|
||||||
{
|
{
|
||||||
ChunkPos chunkPos = chunkPosIterator.next();
|
ChunkPos chunkPos = chunkPosIterator.next();
|
||||||
this.releaseChunkFromServer(this.params.mcServerLevel, this.params.dhServerLevel, chunkPos);
|
releaseFutures.add(this.releaseChunkFromServerAsync(this.params.mcServerLevel, chunkPos));
|
||||||
|
}
|
||||||
|
|
||||||
|
// wait for all release futures to finish to prevent an issue where DH queues
|
||||||
|
// tickets faster than MC can clear them out
|
||||||
|
for (int i = 0; i < releaseFutures.size(); i++)
|
||||||
|
{
|
||||||
|
CompletableFuture<Void> releaseFuture = releaseFutures.get(i);
|
||||||
|
releaseFuture.join();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -286,8 +294,10 @@ public class InternalServerGenerator
|
|||||||
* mitigates out of memory issues in the vanilla chunk system. <br>
|
* mitigates out of memory issues in the vanilla chunk system. <br>
|
||||||
* See: https://github.com/pop4959/Chunky/pull/383
|
* See: https://github.com/pop4959/Chunky/pull/383
|
||||||
*/
|
*/
|
||||||
private void releaseChunkFromServer(ServerLevel level, IDhServerLevel dhLevel, ChunkPos chunkPos)
|
private CompletableFuture<Void> releaseChunkFromServerAsync(ServerLevel level, ChunkPos chunkPos)
|
||||||
{
|
{
|
||||||
|
CompletableFuture<Void> removeTicketFuture = new CompletableFuture<>();
|
||||||
|
|
||||||
level.getChunkSource().chunkMap.mainThreadExecutor.execute(() ->
|
level.getChunkSource().chunkMap.mainThreadExecutor.execute(() ->
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -323,9 +333,15 @@ public class InternalServerGenerator
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
LOGGER.warn("Failed to release chunk back to internal server. Error: ["+e.getMessage()+"]", e);
|
LOGGER.warn("Failed to release chunk ["+chunkPos+"] back to internal server. Error: ["+e.getMessage()+"]", e);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
removeTicketFuture.complete(null);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return removeTicketFuture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
-3
@@ -40,8 +40,6 @@ public final class ThreadWorldGenParams
|
|||||||
public StructureCheck structCheck;
|
public StructureCheck structCheck;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
boolean isValid = true;
|
|
||||||
|
|
||||||
// used for some older MC versions
|
// used for some older MC versions
|
||||||
private static GlobalWorldGenParams previousGlobalWorldGenParams = null;
|
private static GlobalWorldGenParams previousGlobalWorldGenParams = null;
|
||||||
|
|
||||||
@@ -55,7 +53,6 @@ public final class ThreadWorldGenParams
|
|||||||
{
|
{
|
||||||
ThreadWorldGenParams threadParam = LOCAL_PARAM_REF.get();
|
ThreadWorldGenParams threadParam = LOCAL_PARAM_REF.get();
|
||||||
if (threadParam != null
|
if (threadParam != null
|
||||||
&& threadParam.isValid
|
|
||||||
&& threadParam.level == globalParams.mcServerLevel)
|
&& threadParam.level == globalParams.mcServerLevel)
|
||||||
{
|
{
|
||||||
return threadParam;
|
return threadParam;
|
||||||
|
|||||||
+1
-1
Submodule coreSubProjects updated: 22efbb211a...1b066327a8
+2
-2
@@ -6,8 +6,8 @@ org.gradle.caching=true
|
|||||||
# Mod Info
|
# Mod Info
|
||||||
mod_name=DistantHorizons
|
mod_name=DistantHorizons
|
||||||
api_name=DistantHorizonsApi
|
api_name=DistantHorizonsApi
|
||||||
mod_version=3.0.1-b
|
mod_version=3.0.2-b
|
||||||
api_version=6.0.0
|
api_version=6.1.0
|
||||||
maven_group=com.seibel.distanthorizons
|
maven_group=com.seibel.distanthorizons
|
||||||
mod_readable_name=Distant Horizons
|
mod_readable_name=Distant Horizons
|
||||||
mod_description=This mod generates and renders simplified terrain beyond the normal view distance at a low performance cost. Allowing you to see much farther without turning your game into a slideshow.
|
mod_description=This mod generates and renders simplified terrain beyond the normal view distance at a low performance cost. Allowing you to see much farther without turning your game into a slideshow.
|
||||||
|
|||||||
Reference in New Issue
Block a user