Simplify the multi-context uploading, improve stability, and refactor
This commit is contained in:
@@ -82,9 +82,6 @@ public class LodBufferBuilder
|
||||
*/
|
||||
public volatile VertexBuffer[][] drawableVbos;
|
||||
|
||||
public GlProxyContext buildingContext = GlProxyContext.ALPHA;
|
||||
public GlProxyContext renderContext = GlProxyContext.BETA;
|
||||
|
||||
/**
|
||||
* if this is true the LOD buffers are currently being
|
||||
* regenerated.
|
||||
@@ -459,8 +456,11 @@ public class LodBufferBuilder
|
||||
*/
|
||||
private void uploadBuffers(boolean fullRegen, LodDimension lodDim)
|
||||
{
|
||||
GlProxy.getInstance().setGlContext(buildingContext);
|
||||
// used to prevent debug printing multiple times per upload cycle
|
||||
GlProxy glProxy = GlProxy.getInstance();
|
||||
// make sure we are uploading to a different OpenGL context,
|
||||
// to prevent interference (IE stuttering) with the Minecraft context.
|
||||
glProxy.setGlContext(GlProxyContext.LOD_BUILDER);
|
||||
// only print console debugging for vboUpload once per upload cycle
|
||||
boolean bufferMapFail = false;
|
||||
|
||||
|
||||
@@ -481,7 +481,7 @@ public class LodBufferBuilder
|
||||
// make sure all the buffers have been uploaded.
|
||||
// this probably is necessary, but it makes me feel good :)
|
||||
GL11.glFlush();
|
||||
GlProxy.getInstance().setGlContext(GlProxyContext.NONE);
|
||||
glProxy.setGlContext(GlProxyContext.NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -520,7 +520,7 @@ public class LodBufferBuilder
|
||||
|
||||
// only print to console once per upload cycle
|
||||
if (!bufferMapFail)
|
||||
ClientProxy.LOGGER.debug("LOD buffer upload glMapBuffer failed, using slower glBufferData.");
|
||||
ClientProxy.LOGGER.debug("LOD buffer upload: glMapBuffer failed, used slower glBufferData.");
|
||||
bufferMapFail = true;
|
||||
}
|
||||
|
||||
@@ -547,10 +547,6 @@ public class LodBufferBuilder
|
||||
drawableVbos = buildableVbos;
|
||||
buildableVbos = tmpVbo;
|
||||
|
||||
GlProxyContext tmpContext = renderContext;
|
||||
renderContext = buildingContext;
|
||||
buildingContext = tmpContext;
|
||||
|
||||
drawableCenterChunkPos = buildableCenterChunkPos;
|
||||
|
||||
// the vbos have been swapped
|
||||
@@ -558,7 +554,7 @@ public class LodBufferBuilder
|
||||
bufferLock.unlock();
|
||||
}
|
||||
|
||||
return new VertexBuffersAndOffset(drawableVbos, drawableCenterChunkPos, renderContext);
|
||||
return new VertexBuffersAndOffset(drawableVbos, drawableCenterChunkPos);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -568,13 +564,11 @@ public class LodBufferBuilder
|
||||
{
|
||||
public VertexBuffer[][] vbos;
|
||||
public ChunkPos drawableCenterChunkPos;
|
||||
public GlProxyContext drawingContext;
|
||||
|
||||
public VertexBuffersAndOffset(VertexBuffer[][] newVbos, ChunkPos newDrawableCenterChunkPos, GlProxyContext newDrawingContext)
|
||||
public VertexBuffersAndOffset(VertexBuffer[][] newVbos, ChunkPos newDrawableCenterChunkPos)
|
||||
{
|
||||
vbos = newVbos;
|
||||
drawableCenterChunkPos = newDrawableCenterChunkPos;
|
||||
drawingContext = newDrawingContext;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,6 @@ import com.seibel.lod.builders.worldGeneration.LodNodeGenWorker;
|
||||
import com.seibel.lod.builders.worldGeneration.LodWorldGenerator;
|
||||
import com.seibel.lod.config.LodConfig;
|
||||
import com.seibel.lod.enums.DistanceGenerationMode;
|
||||
import com.seibel.lod.enums.LodDetail;
|
||||
import com.seibel.lod.objects.LodDimension;
|
||||
import com.seibel.lod.objects.LodWorld;
|
||||
import com.seibel.lod.objects.RegionPos;
|
||||
@@ -47,15 +46,17 @@ import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
|
||||
/**
|
||||
* This handles all events sent to the client,
|
||||
* and is the starting point for most of this program.
|
||||
* and is the starting point for most of the mod.
|
||||
*
|
||||
* @author James_Seibel
|
||||
* @version 8-24-2021
|
||||
* @version 9-14-2021
|
||||
*/
|
||||
public class ClientProxy
|
||||
{
|
||||
public static final Logger LOGGER = LogManager.getLogger("LOD");
|
||||
|
||||
private boolean firstTimeSetupComplete = false;
|
||||
|
||||
private static LodWorld lodWorld = new LodWorld();
|
||||
private static LodBuilder lodBuilder = new LodBuilder();
|
||||
private static LodBufferBuilder lodBufferBuilder = new LodBufferBuilder();
|
||||
@@ -64,7 +65,7 @@ public class ClientProxy
|
||||
|
||||
private boolean configOverrideReminderPrinted = false;
|
||||
|
||||
MinecraftWrapper mc = MinecraftWrapper.INSTANCE;
|
||||
private MinecraftWrapper mc = MinecraftWrapper.INSTANCE;
|
||||
|
||||
|
||||
/**
|
||||
@@ -99,7 +100,13 @@ public class ClientProxy
|
||||
*/
|
||||
public void renderLods(float partialTicks)
|
||||
{
|
||||
GlProxy.getInstance();
|
||||
// only run the first time setup once
|
||||
if (firstTimeSetupComplete)
|
||||
{
|
||||
firstFrameSetup();
|
||||
}
|
||||
|
||||
|
||||
|
||||
DetailDistanceUtil.updateSettings();
|
||||
if (mc == null || mc.getPlayer() == null || !lodWorld.getIsWorldLoaded())
|
||||
@@ -113,8 +120,6 @@ public class ClientProxy
|
||||
|
||||
|
||||
playerMoveEvent(lodDim);
|
||||
//System.out.println("memory needed " + lodDim.getMinMemoryNeeded() + " byte");
|
||||
//System.out.println(lodDim);
|
||||
|
||||
lodDim.treeCutter((int) mc.getPlayer().getX(), (int) mc.getPlayer().getZ());
|
||||
lodDim.treeGenerator((int) mc.getPlayer().getX(), (int) mc.getPlayer().getZ());
|
||||
@@ -135,7 +140,7 @@ public class ClientProxy
|
||||
renderer.drawLODs(lodDim, partialTicks, mc.getProfiler());
|
||||
|
||||
profiler.pop(); // end LOD
|
||||
profiler.push("terrain"); // restart "terrain"
|
||||
profiler.push("terrain"); // go back into "terrain"
|
||||
|
||||
|
||||
// these can't be set until after the buffers are built (in renderer.drawLODs)
|
||||
@@ -157,8 +162,8 @@ public class ClientProxy
|
||||
//LodConfig.CLIENT.drawLODs.set(true);
|
||||
//LodConfig.CLIENT.debugMode.set(true);
|
||||
|
||||
LodConfig.CLIENT.graphics.maxDrawDetail.set(LodDetail.FULL);
|
||||
LodConfig.CLIENT.worldGenerator.maxGenerationDetail.set(LodDetail.FULL);
|
||||
// LodConfig.CLIENT.graphics.maxDrawDetail.set(LodDetail.FULL);
|
||||
// LodConfig.CLIENT.worldGenerator.maxGenerationDetail.set(LodDetail.FULL);
|
||||
|
||||
// LodConfig.CLIENT.graphics.fogDistance.set(FogDistance.FAR);
|
||||
// LodConfig.CLIENT.graphics.fogDrawOverride.set(FogDrawOverride.ALWAYS_DRAW_FOG_FANCY);
|
||||
@@ -167,14 +172,14 @@ public class ClientProxy
|
||||
// LodConfig.CLIENT.graphics.saturationMultiplier.set(1.0);
|
||||
|
||||
// LodConfig.CLIENT.worldGenerator.distanceGenerationMode.set(DistanceGenerationMode.SURFACE);
|
||||
LodConfig.CLIENT.graphics.lodChunkRenderDistance.set(256);
|
||||
// LodConfig.CLIENT.graphics.lodChunkRenderDistance.set(64);
|
||||
// LodConfig.CLIENT.worldGenerator.lodDistanceCalculatorType.set(DistanceCalculatorType.LINEAR);
|
||||
LodConfig.CLIENT.graphics.lodQuality.set(3);
|
||||
// LodConfig.CLIENT.graphics.lodQuality.set(2);
|
||||
// LodConfig.CLIENT.worldGenerator.allowUnstableFeatureGeneration.set(false);
|
||||
|
||||
LodConfig.CLIENT.buffers.bufferRebuildPlayerMoveTimeout.set(2000); // 2000
|
||||
LodConfig.CLIENT.buffers.bufferRebuildChunkChangeTimeout.set(1000); // 1000
|
||||
LodConfig.CLIENT.buffers.bufferRebuildLodChangeTimeout.set(5000); // 5000
|
||||
// LodConfig.CLIENT.buffers.bufferRebuildPlayerMoveTimeout.set(2000); // 2000
|
||||
// LodConfig.CLIENT.buffers.bufferRebuildChunkChangeTimeout.set(1000); // 1000
|
||||
// LodConfig.CLIENT.buffers.bufferRebuildLodChangeTimeout.set(5000); // 5000
|
||||
|
||||
LodConfig.CLIENT.debugging.enableDebugKeybinding.set(true);
|
||||
}
|
||||
@@ -267,10 +272,9 @@ public class ClientProxy
|
||||
}
|
||||
|
||||
|
||||
|
||||
//==================//
|
||||
// frame LOD events //
|
||||
//==================//
|
||||
//============//
|
||||
// LOD events //
|
||||
//============//
|
||||
|
||||
/**
|
||||
* Re-centers the given LodDimension if it needs to be.
|
||||
@@ -315,6 +319,20 @@ public class ClientProxy
|
||||
DetailDistanceUtil.updateSettings();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This event is called once during the first frame Minecraft renders in the world.
|
||||
*/
|
||||
public void firstFrameSetup()
|
||||
{
|
||||
// make sure the GlProxy is created before the LodBufferBuilder
|
||||
GlProxy.getInstance();
|
||||
|
||||
|
||||
|
||||
firstTimeSetupComplete = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
|
||||
@@ -7,7 +7,8 @@ import org.lwjgl.opengl.WGL;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
|
||||
/**
|
||||
* A singleton that holds references to different openGL contexts.
|
||||
* A singleton that holds references to different openGL contexts
|
||||
* and GPU capabilities.
|
||||
*
|
||||
* <p>
|
||||
* Helpful OpenGL resources: <br><br>
|
||||
@@ -31,8 +32,13 @@ public class GlProxy
|
||||
|
||||
public long lodBuilderGlContext;
|
||||
public GLCapabilities lodBuilderGlCapabilities;
|
||||
public long lodRenderGlContext;
|
||||
public GLCapabilities lodRenderGlCapabilities;
|
||||
|
||||
/**
|
||||
* Does this computer's GPU support fancy fog?
|
||||
*/
|
||||
public final boolean fancyFogAvailable;
|
||||
|
||||
|
||||
|
||||
private GlProxy()
|
||||
{
|
||||
@@ -42,6 +48,12 @@ public class GlProxy
|
||||
throw new IllegalStateException(GlProxy.class.getSimpleName() + " was created outside the render thread!");
|
||||
|
||||
|
||||
|
||||
|
||||
//============================//
|
||||
// create the builder context //
|
||||
//============================//
|
||||
|
||||
minecraftGlContext = WGL.wglGetCurrentContext();
|
||||
minecraftGlCapabilities = GL.getCapabilities();
|
||||
deviceContext = WGL.wglGetCurrentDC();
|
||||
@@ -50,22 +62,28 @@ public class GlProxy
|
||||
if (!WGL.wglShareLists(minecraftGlContext, lodBuilderGlContext))
|
||||
throw new IllegalStateException("Unable to share lists between Minecraft and builder contexts.");
|
||||
if (!WGL.wglMakeCurrent(deviceContext, lodBuilderGlContext))
|
||||
throw new IllegalStateException("Unable to change OpenGL contexts! tried to change to [" + GlProxyContext.ALPHA.toString() + "] from [" + GlProxyContext.MINECRAFT.toString() + "]");
|
||||
throw new IllegalStateException("Unable to change OpenGL contexts! tried to change to [" + GlProxyContext.LOD_BUILDER.toString() + "] from [" + GlProxyContext.MINECRAFT.toString() + "]");
|
||||
lodBuilderGlCapabilities = GL.createCapabilities();
|
||||
WGL.wglMakeCurrent(deviceContext, 0L);
|
||||
|
||||
|
||||
|
||||
lodRenderGlContext = WGL.wglCreateContext(deviceContext);
|
||||
if (!WGL.wglShareLists(minecraftGlContext, lodRenderGlContext))
|
||||
throw new IllegalStateException("Unable to share lists between builder and render contexts.");
|
||||
if (!WGL.wglMakeCurrent(deviceContext, lodRenderGlContext))
|
||||
throw new IllegalStateException("Unable to change OpenGL contexts! tried to change to [" + GlProxyContext.ALPHA.toString() + "] from [" + GlProxyContext.BETA.toString() + "]");
|
||||
lodRenderGlCapabilities = GL.createCapabilities();
|
||||
|
||||
|
||||
// Since this is called on the render thread, make sure the Minecraft context is used in the end
|
||||
WGL.wglMakeCurrent(deviceContext, minecraftGlContext);
|
||||
|
||||
|
||||
|
||||
|
||||
//==================================//
|
||||
// get any GPU related capabilities //
|
||||
//==================================//
|
||||
|
||||
// see if this GPU can run fancy fog
|
||||
fancyFogAvailable = GL.getCapabilities().GL_NV_fog_distance;
|
||||
|
||||
if (!fancyFogAvailable)
|
||||
{
|
||||
ClientProxy.LOGGER.info("This GPU does not support GL_NV_fog_distance. This means that the fancy fog option will not be available.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -80,14 +98,10 @@ public class GlProxy
|
||||
GLCapabilities newGlCapabilities = null;
|
||||
switch(context)
|
||||
{
|
||||
case ALPHA:
|
||||
case LOD_BUILDER:
|
||||
contextPointer = lodBuilderGlContext;
|
||||
newGlCapabilities = lodBuilderGlCapabilities;
|
||||
break;
|
||||
case BETA:
|
||||
contextPointer = lodRenderGlContext;
|
||||
newGlCapabilities = lodRenderGlCapabilities;
|
||||
break;
|
||||
case MINECRAFT:
|
||||
contextPointer = minecraftGlContext;
|
||||
newGlCapabilities = minecraftGlCapabilities;
|
||||
@@ -111,11 +125,7 @@ public class GlProxy
|
||||
long currentContext = WGL.wglGetCurrentContext();
|
||||
if(currentContext == lodBuilderGlContext)
|
||||
{
|
||||
return GlProxyContext.ALPHA;
|
||||
}
|
||||
else if(currentContext == lodRenderGlContext)
|
||||
{
|
||||
return GlProxyContext.BETA;
|
||||
return GlProxyContext.LOD_BUILDER;
|
||||
}
|
||||
else if(currentContext == minecraftGlContext)
|
||||
{
|
||||
@@ -130,8 +140,7 @@ public class GlProxy
|
||||
public enum GlProxyContext
|
||||
{
|
||||
MINECRAFT,
|
||||
ALPHA,
|
||||
BETA,
|
||||
LOD_BUILDER,
|
||||
|
||||
/** used to un-bind threads */
|
||||
NONE,
|
||||
|
||||
@@ -23,7 +23,6 @@ import java.nio.FloatBuffer;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.lwjgl.opengl.GL;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.opengl.GL15C;
|
||||
@@ -95,13 +94,7 @@ public class LodRenderer
|
||||
* https://stackoverflow.com/questions/50499238/bytebuffer-allocatedirect-and-xmx
|
||||
*/
|
||||
public static final int MAX_ALOCATEABLE_DIRECT_MEMORY = 64 * 1024 * 1024;
|
||||
|
||||
/**
|
||||
* Does this computer's GPU support fancy fog?
|
||||
*/
|
||||
private static Boolean fancyFogAvailable = null;
|
||||
private static GlProxy glProxy;
|
||||
|
||||
|
||||
/**
|
||||
* If true the LODs colors will be replaced with
|
||||
* a checkerboard, this can be used for debugging.
|
||||
@@ -189,25 +182,8 @@ public class LodRenderer
|
||||
|
||||
profiler = newProfiler;
|
||||
profiler.push("LOD setup");
|
||||
|
||||
|
||||
// only check the GPU capability's once
|
||||
if (fancyFogAvailable == null)
|
||||
{
|
||||
//TODO add this to the GlProxy
|
||||
// see if this GPU can run fancy fog
|
||||
fancyFogAvailable = GL.getCapabilities().GL_NV_fog_distance;
|
||||
|
||||
if (!fancyFogAvailable)
|
||||
{
|
||||
ClientProxy.LOGGER.info("This GPU does not support GL_NV_fog_distance. This means that fancy fog options will not be available.");
|
||||
}
|
||||
|
||||
// create the GlProxy TODO this should probably be done somewhere else
|
||||
glProxy = GlProxy.getInstance();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// TODO move the buffer regeneration logic into its own class (probably called in the client proxy instead)
|
||||
// starting here...
|
||||
determineIfLodsShouldRegenerate(lodDim);
|
||||
@@ -243,11 +219,6 @@ public class LodRenderer
|
||||
swapBuffers();
|
||||
}
|
||||
|
||||
if (renderContext == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//===========================//
|
||||
@@ -738,7 +709,7 @@ public class LodRenderer
|
||||
|
||||
|
||||
// only use fancy fog if the user's GPU can deliver
|
||||
if (!fancyFogAvailable && quality == FogQuality.FANCY)
|
||||
if (!GlProxy.getInstance().fancyFogAvailable && quality == FogQuality.FANCY)
|
||||
{
|
||||
quality = FogQuality.FAST;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user