Restructure and optimize the debug wireframe renderer

This commit is contained in:
James Seibel
2023-09-21 19:19:38 -05:00
parent 9a82b718a5
commit 74cac0c263
6 changed files with 216 additions and 186 deletions
@@ -45,7 +45,7 @@ import java.util.concurrent.*;
*
* @see ColumnRenderBufferBuilder
*/
public class ColumnRenderBuffer extends AbstractRenderBuffer implements IDebugRenderable
public class ColumnRenderBuffer extends AbstractRenderBuffer
{
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
@@ -71,21 +71,8 @@ public class ColumnRenderBuffer extends AbstractRenderBuffer implements IDebugRe
{
this.pos = pos;
this.debugPos = debugPos;
vbos = new GLVertexBuffer[0];
vbosTransparent = new GLVertexBuffer[0];
DebugRenderer.register(this);
}
@Override
public void debugRender(DebugRenderer renderer)
{
if (this.closed || this.vbos == null)
{
return;
}
Color c = Color.green;
//renderer.renderBox(debugPos, 128, 128, 0.05f, c);
this.vbos = new GLVertexBuffer[0];
this.vbosTransparent = new GLVertexBuffer[0];
}
@@ -114,7 +114,7 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile implements I
this.level = level;
LodUtil.assertTrue(this.baseMetaData == null);
this.doesFileExist = false;
DebugRenderer.register(this);
DebugRenderer.register(this, Config.Client.Advanced.Debugging.DebugWireframe.showFullDataFileStatus);
}
@@ -142,7 +142,7 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile implements I
}
this.fullDataSourceClass = this.fullDataSourceLoader.fullDataSourceClass;
DebugRenderer.register(this);
DebugRenderer.register(this, Config.Client.Advanced.Debugging.DebugWireframe.showFullDataFileStatus);
}
@@ -467,12 +467,7 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile implements I
@Override
public void debugRender(DebugRenderer debugRenderer)
{
boolean showFullDataFileStatus = Config.Client.Advanced.Debugging.DebugWireframe.showFullDataFileStatus.get();
if (!showFullDataFileStatus)
{
return;
}
else if (this.pos.getDetailLevel() > DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL)
if (this.pos.getDetailLevel() > DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL)
{
return;
}
@@ -108,7 +108,7 @@ public class RenderDataMetaFile extends AbstractMetaDataContainerFile implements
this.clientLevel = clientLevel;
LodUtil.assertTrue(this.baseMetaData == null);
this.doesFileExist = this.file.exists();
DebugRenderer.register(this);
DebugRenderer.register(this, Config.Client.Advanced.Debugging.DebugWireframe.showRenderDataFileStatus);
}
@@ -124,7 +124,7 @@ public class RenderDataMetaFile extends AbstractMetaDataContainerFile implements
this.clientLevel = clientLevel;
LodUtil.assertTrue(this.baseMetaData != null);
this.doesFileExist = this.file.exists();
DebugRenderer.register(this);
DebugRenderer.register(this, Config.Client.Advanced.Debugging.DebugWireframe.showRenderDataFileStatus);
}
@@ -151,7 +151,7 @@ public class RenderDataMetaFile extends AbstractMetaDataContainerFile implements
boolean dataUpdated = renderSource.updateWithChunkData(chunkDataView, this.clientLevel);
// add a debug renderer
// add a debug particle
boolean showRenderDataFileStatus = Config.Client.Advanced.Debugging.DebugWireframe.showRenderDataFileStatus.get();
if (showRenderDataFileStatus)
{
@@ -453,14 +453,6 @@ public class RenderDataMetaFile extends AbstractMetaDataContainerFile implements
@Override
public void debugRender(DebugRenderer debugRenderer)
{
boolean showRenderDataFileStatus = Config.Client.Advanced.Debugging.DebugWireframe.showRenderDataFileStatus.get();
if (!showRenderDataFileStatus)
{
return;
}
if (this.cachedRenderDataSourceRef.get() != null)
{
return;
@@ -125,7 +125,7 @@ public class WorldGenerationQueue implements IWorldGenerationQueue, IDebugRender
{
throw new IllegalArgumentException(IDhApiWorldGenerator.class.getSimpleName() + ": max granularity smaller than min granularity!");
}
DebugRenderer.register(this);
DebugRenderer.register(this, Config.Client.Advanced.Debugging.DebugWireframe.showWorldGenQueue);
LOGGER.info("Created world gen queue");
}
@@ -673,7 +673,7 @@ public class WorldGenerationQueue implements IWorldGenerationQueue, IDebugRender
LOGGER.warn("Failed to close generation queue: ", e);
}
LOGGER.info("Finished closing " + WorldGenerationQueue.class.getSimpleName());
DebugRenderer.unregister(this);
DebugRenderer.unregister(this, Config.Client.Advanced.Debugging.DebugWireframe.showWorldGenQueue);
}
@@ -722,13 +722,6 @@ public class WorldGenerationQueue implements IWorldGenerationQueue, IDebugRender
@Override
public void debugRender(DebugRenderer renderer)
{
boolean showWorldGenQueue = Config.Client.Advanced.Debugging.DebugWireframe.showWorldGenQueue.get();
if (!showWorldGenQueue)
{
return;
}
this.waitingTasks.keySet().forEach((pos) -> { renderer.renderBox(new DebugRenderer.Box(pos, -32f, 64f, 0.05f, Color.blue)); });
this.inProgressGenTasksByLodPos.forEach((pos, t) -> { renderer.renderBox(new DebugRenderer.Box(pos, -32f, 64f, 0.05f, Color.red)); });
}
@@ -95,46 +95,7 @@ public class LodRenderSection implements IDebugRenderable
this.pos = pos;
this.parentQuadTree = parentQuadTree;
DebugRenderer.register(this);
}
@Override
public void debugRender(DebugRenderer debugRenderer)
{
boolean showRenderSectionStatus = Config.Client.Advanced.Debugging.DebugWireframe.showRenderSectionStatus.get();
if (!showRenderSectionStatus)
{
return;
}
Color color = Color.red;
if (this.renderSourceProvider == null)
{
color = Color.black;
}
else if (this.renderSourceLoadFuture != null)
{
color = Color.yellow;
}
else if (this.renderSource != null)
{
color = Color.blue;
if (this.buildRenderBufferFuture != null)
{
color = Color.magenta;
}
else if (this.canRenderNow())
{
color = Color.cyan;
}
else if (this.canRenderNow() && this.isRenderingEnabled)
{
color = Color.green;
}
}
debugRenderer.renderBox(new DebugRenderer.Box(this.pos, 400, 8f, Objects.hashCode(this), 0.1f, color));
DebugRenderer.register(this, Config.Client.Advanced.Debugging.DebugWireframe.showRenderSectionStatus);
}
@@ -269,18 +230,13 @@ public class LodRenderSection implements IDebugRenderable
);
}
//================//
// Render Methods //
//================//
private void cancelBuildBuffer()
{
if (this.buildRenderBufferFuture != null)
{
//LOGGER.info("Cancelling build of render buffer for {}", sectionPos);
this.buildRenderBufferFuture.cancel(true);
this.buildRenderBufferFuture = null;
}
}
public void markBufferDirty() { this.lastSwapLocalVersion = -1; }
//=================//
// buffer building //
//=================//
private LodRenderSection[] getNeighbors()
{
@@ -323,6 +279,34 @@ public class LodRenderSection implements IDebugRenderable
public boolean canSwapBuffer() { return this.buildRenderBufferFuture != null && this.buildRenderBufferFuture.isDone(); }
private void cancelBuildBuffer()
{
if (this.buildRenderBufferFuture != null)
{
//LOGGER.info("Cancelling build of render buffer for {}", sectionPos);
this.buildRenderBufferFuture.cancel(true);
this.buildRenderBufferFuture = null;
}
}
public synchronized void disposeRenderData() // synchronized is a band-aid solution to prevent a rare bug where the future isn't canceled in the right order
{
this.disposeRenderBuffer();
this.renderSource = null;
if (this.renderSourceLoadFuture != null)
{
this.renderSourceLoadFuture.cancel(true);
this.renderSourceLoadFuture = null;
}
}
public void disposeRenderBuffer()
{
this.cancelBuildBuffer();
this.disposeActiveBuffer = true;
}
/**
* Try and swap in new render buffer for this section. Note that before this call, there should be no other
@@ -446,30 +430,43 @@ public class LodRenderSection implements IDebugRenderable
public void dispose()
{
this.disposeRenderData();
DebugRenderer.unregister(this);
DebugRenderer.unregister(this, Config.Client.Advanced.Debugging.DebugWireframe.showRenderSectionStatus);
if (this.disposeActiveBuffer && this.activeRenderBufferRef.get() != null)
{
this.activeRenderBufferRef.get().close();
}
}
public synchronized void disposeRenderData() // synchronized is a band-aid solution to prevent a rare bug where the future isn't canceled in the right order
@Override
public void debugRender(DebugRenderer debugRenderer)
{
this.disposeRenderBuffer();
this.renderSource = null;
if (this.renderSourceLoadFuture != null)
Color color = Color.red;
if (this.renderSourceProvider == null)
{
this.renderSourceLoadFuture.cancel(true);
this.renderSourceLoadFuture = null;
color = Color.black;
}
else if (this.renderSourceLoadFuture != null)
{
color = Color.yellow;
}
else if (this.renderSource != null)
{
color = Color.blue;
if (this.buildRenderBufferFuture != null)
{
color = Color.magenta;
}
else if (this.canRenderNow())
{
color = Color.cyan;
}
else if (this.canRenderNow() && this.isRenderingEnabled)
{
color = Color.green;
}
}
debugRenderer.renderBox(new DebugRenderer.Box(this.pos, 400, 8f, Objects.hashCode(this), 0.1f, color));
}
public void disposeRenderBuffer()
{
this.cancelBuildBuffer();
this.disposeActiveBuffer = true;
}
public void markBufferDirty() { this.lastSwapLocalVersion = -1; }
}
@@ -22,6 +22,7 @@ package com.seibel.distanthorizons.core.render.renderer;
import com.seibel.distanthorizons.api.enums.config.EGpuUploadMethod;
import com.seibel.distanthorizons.api.enums.config.ELoggerMode;
import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.config.types.ConfigEntry;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.logging.ConfigBasedLogger;
import com.seibel.distanthorizons.core.logging.ConfigBasedSpamLogger;
@@ -39,6 +40,7 @@ import com.seibel.distanthorizons.coreapi.util.math.Vec3d;
import com.seibel.distanthorizons.coreapi.util.math.Vec3f;
import org.apache.logging.log4j.LogManager;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.lwjgl.opengl.GL32;
import java.awt.*;
@@ -72,9 +74,7 @@ public class DebugRenderer
private Vec3f camPosFloatThisFrame;
// render lists
private final LinkedList<WeakReference<IDebugRenderable>> renderers = new LinkedList<>();
private final RendererLists rendererLists = new RendererLists();
private final PriorityBlockingQueue<BoxParticle> particles = new PriorityBlockingQueue<>();
@@ -123,45 +123,29 @@ public class DebugRenderer
// registration //
//==============//
public static void unregister(IDebugRenderable renderable)
{
if (INSTANCE != null)
{
INSTANCE.removeRenderer(renderable);
}
}
public static void makeParticle(BoxParticle particle)
{
if (INSTANCE != null && !Config.Client.Advanced.Debugging.DebugWireframe.enableRendering.get())
if (INSTANCE != null && Config.Client.Advanced.Debugging.DebugWireframe.enableRendering.get())
{
INSTANCE.particles.add(particle);
}
}
private void removeRenderer(IDebugRenderable renderable)
{
synchronized (this.renderers)
{
Iterator<WeakReference<IDebugRenderable>> iterator = this.renderers.iterator();
while (iterator.hasNext())
{
WeakReference<IDebugRenderable> renderableRef = iterator.next();
if (renderableRef.get() == null)
{
iterator.remove();
continue;
}
if (renderableRef.get() == renderable)
{
iterator.remove();
return;
}
}
}
}
public static void register(IDebugRenderable renderable, ConfigEntry<Boolean> config) { if (INSTANCE != null) { INSTANCE.addRenderer(renderable, config); } }
public void addRenderer(IDebugRenderable renderable, ConfigEntry<Boolean> config) { this.rendererLists.addRenderable(renderable, config); }
public static void clearRenderables() { INSTANCE.renderers.clear(); }
public static void unregister(IDebugRenderable renderable, ConfigEntry<Boolean> config) { if (INSTANCE != null) { INSTANCE.removeRenderer(renderable, config); } }
private void removeRenderer(IDebugRenderable renderable, ConfigEntry<Boolean> config) { this.rendererLists.removeRenderable(renderable, config); }
public static void clearRenderables() { INSTANCE.rendererLists.clearRenderables(); }
//===========//
// rendering //
//===========//
public void init()
{
@@ -202,29 +186,6 @@ public class DebugRenderer
this.boxOutlineBuffer.uploadBuffer(buffer, EGpuUploadMethod.DATA, box_outline_indices.length * Integer.BYTES, GL32.GL_STATIC_DRAW);
}
public void addRenderer(IDebugRenderable r)
{
if (!Config.Client.Advanced.Debugging.DebugWireframe.enableRendering.get()) return;
synchronized (this.renderers)
{
this.renderers.add(new WeakReference<>(r));
}
}
public static void register(IDebugRenderable r)
{
if (INSTANCE != null)
{
INSTANCE.addRenderer(r);
}
}
//===========//
// rendering //
//===========//
public void render(Mat4f transform)
{
this.transformThiFrame = transform;
@@ -249,22 +210,7 @@ public class DebugRenderer
this.boxOutlineBuffer.bind();
synchronized (this.renderers)
{
Iterator<WeakReference<IDebugRenderable>> it = this.renderers.iterator();
while (it.hasNext())
{
// TODO split this up to improve frame times when only some items are needed
WeakReference<IDebugRenderable> ref = it.next();
IDebugRenderable r = ref.get();
if (r == null)
{
it.remove();
continue;
}
r.debugRender(this);
}
}
this.rendererLists.render(this);
BoxParticle head = null;
@@ -410,7 +356,7 @@ public class DebugRenderer
{
this.box = box;
this.particaleOnClose = new BoxParticle(new Box(box.a, box.b, deathColor), -1, ns, yChange);
register(this);
register(this, null);
}
@@ -431,10 +377,130 @@ public class DebugRenderer
public void close()
{
makeParticle(new BoxParticle(this.particaleOnClose.getBox(), System.nanoTime(), this.particaleOnClose.duration, this.particaleOnClose.yChange));
unregister(this);
unregister(this, null);
}
}
private static class RendererLists
{
public final LinkedList<WeakReference<IDebugRenderable>> generalRenderableList = new LinkedList<>();
private final HashMap<ConfigEntry<Boolean>, LinkedList<WeakReference<IDebugRenderable>>> renderableListByConfig = new HashMap<>();
// registration //
public void addRenderable(IDebugRenderable renderable, @Nullable ConfigEntry<Boolean> config)
{
synchronized (this)
{
if (config != null)
{
if (!this.renderableListByConfig.containsKey(config))
{
this.renderableListByConfig.put(config, new LinkedList<>());
}
LinkedList<WeakReference<IDebugRenderable>> renderableList = this.renderableListByConfig.get(config);
renderableList.add(new WeakReference<>(renderable));
}
else
{
this.generalRenderableList.add(new WeakReference<>(renderable));
}
}
}
public void removeRenderable(IDebugRenderable renderable, @Nullable ConfigEntry<Boolean> config)
{
synchronized (this)
{
if (config != null)
{
if (this.renderableListByConfig.containsKey(config))
{
LinkedList<WeakReference<IDebugRenderable>> renderableList = this.renderableListByConfig.get(config);
this.removeRenderableFromInternalList(renderableList, renderable);
}
}
else
{
this.removeRenderableFromInternalList(this.generalRenderableList, renderable);
}
}
}
private void removeRenderableFromInternalList(LinkedList<WeakReference<IDebugRenderable>> rendererList, IDebugRenderable renderable)
{
Iterator<WeakReference<IDebugRenderable>> iterator = rendererList.iterator();
while (iterator.hasNext())
{
WeakReference<IDebugRenderable> renderableRef = iterator.next();
if (renderableRef.get() == null)
{
iterator.remove();
continue;
}
if (renderableRef.get() == renderable)
{
iterator.remove();
return;
}
}
}
public void clearRenderables()
{
for (ConfigEntry<Boolean> config : this.renderableListByConfig.keySet())
{
LinkedList<WeakReference<IDebugRenderable>> renderableList = this.renderableListByConfig.get(config);
if (config.get() && renderableList != null)
{
renderableList.clear();
}
}
}
// rendering //
public void render(DebugRenderer debugRenderer)
{
this.renderList(debugRenderer, this.generalRenderableList);
for (ConfigEntry<Boolean> config : this.renderableListByConfig.keySet())
{
LinkedList<WeakReference<IDebugRenderable>> renderableList = this.renderableListByConfig.get(config);
if (config.get() && renderableList != null && renderableList.size() != 0)
{
this.renderList(debugRenderer, renderableList);
}
}
}
private void renderList(DebugRenderer debugRenderer, LinkedList<WeakReference<IDebugRenderable>> rendererList)
{
synchronized (this)
{
Iterator<WeakReference<IDebugRenderable>> iterator = rendererList.iterator();
while (iterator.hasNext())
{
WeakReference<IDebugRenderable> ref = iterator.next();
IDebugRenderable renderable = ref.get();
if (renderable == null)
{
iterator.remove();
continue;
}
renderable.debugRender(debugRenderer);
}
}
}
}
}