From 87238bdb45e0fd43618a5e5636832b776c1c4b82 Mon Sep 17 00:00:00 2001 From: mcrcortex <18544518+MCRcortex@users.noreply.github.com> Date: Mon, 23 Sep 2024 01:10:43 +1000 Subject: [PATCH] It works EVEN BETTER --- .../client/core/rendering/RenderService.java | 19 +++++---- .../HierarchicalOcclusionTraverser.java | 6 +-- .../rendering/hierachical2/NodeManager2.java | 39 +++++++++++++++++++ .../rendering/hierachical2/NodeStore.java | 1 + .../AbstractSectionGeometryManager.java | 2 +- .../section/BasicSectionGeometryManager.java | 2 +- .../section/MDICSectionRenderer.java | 8 +--- .../util/ExpandingObjectAllocationList.java | 4 ++ .../lod/hierarchical/traversal_dev.comp | 4 +- 9 files changed, 65 insertions(+), 20 deletions(-) diff --git a/src/main/java/me/cortex/voxy/client/core/rendering/RenderService.java b/src/main/java/me/cortex/voxy/client/core/rendering/RenderService.java index 9143d653..602ea780 100644 --- a/src/main/java/me/cortex/voxy/client/core/rendering/RenderService.java +++ b/src/main/java/me/cortex/voxy/client/core/rendering/RenderService.java @@ -77,16 +77,16 @@ public class RenderService, J extends Vi world.getMapper().setBiomeCallback(this.modelService::addBiome); //this.nodeManager.insertTopLevelNode(WorldEngine.getWorldSectionId(0, 0,0,0)); - this.nodeManager.insertTopLevelNode(WorldEngine.getWorldSectionId(4, 0,0,0)); - /* - final int H_WIDTH = 1; + //this.nodeManager.insertTopLevelNode(WorldEngine.getWorldSectionId(4, 0,0,0)); + + final int H_WIDTH = 10; for (int x = -H_WIDTH; x <= H_WIDTH; x++) { - for (int y = -1; y <= 0; y++) { + for (int y = 0; y <= 0; y++) { for (int z = -H_WIDTH; z <= H_WIDTH; z++) { this.nodeManager.insertTopLevelNode(WorldEngine.getWorldSectionId(4, x, y, z)); } } - }*/ + } } public void setup(Camera camera) { @@ -120,9 +120,11 @@ public class RenderService, J extends Vi this.sectionUpdateQueue.consume(); this.geometryUpdateQueue.consume(); - if (this.nodeManager.writeChanges(this.traversal.getNodeBuffer())) {//TODO: maybe move the node buffer out of the traversal class - UploadStream.INSTANCE.commit(); - } + if (this.nodeManager.writeChanges(this.traversal.getNodeBuffer())) {//TODO: maybe move the node buffer out of the traversal class + UploadStream.INSTANCE.commit(); + } + //this needs to go after, due to geometry updates committed by the nodeManager + this.sectionRenderer.getGeometryManager().tick(); } UploadStream.INSTANCE.tick(); @@ -142,6 +144,7 @@ public class RenderService, J extends Vi this.modelService.addDebugData(debug); this.renderGen.addDebugData(debug); this.sectionRenderer.addDebug(debug); + this.nodeManager.addDebug(debug); } public void shutdown() { diff --git a/src/main/java/me/cortex/voxy/client/core/rendering/hierachical2/HierarchicalOcclusionTraverser.java b/src/main/java/me/cortex/voxy/client/core/rendering/hierachical2/HierarchicalOcclusionTraverser.java index fecbe5ca..339b6471 100644 --- a/src/main/java/me/cortex/voxy/client/core/rendering/hierachical2/HierarchicalOcclusionTraverser.java +++ b/src/main/java/me/cortex/voxy/client/core/rendering/hierachical2/HierarchicalOcclusionTraverser.java @@ -115,7 +115,7 @@ public class HierarchicalOcclusionTraverser { MemoryUtil.memPutInt(ptr, (int) (this.renderList.size()/4-1)); ptr += 4;//TODO maybe move this to a #define //Screen space size for descending - MemoryUtil.memPutFloat(ptr, 64*64); ptr += 4; + MemoryUtil.memPutFloat(ptr, 128*128); ptr += 4; } private void bindings() { @@ -143,7 +143,7 @@ public class HierarchicalOcclusionTraverser { PrintfDebugUtil.bind(); - this.traverseInternal(1); + this.traverseInternal(this.nodeManager.getTopLevelNodeIds().size()); this.downloadResetRequestQueue(); @@ -192,7 +192,7 @@ public class HierarchicalOcclusionTraverser { ptr = UploadStream.INSTANCE.upload(this.scratchQueueA, 0, 4L*initialQueueSize); for (int i = 0; i < initialQueueSize; i++) { - MemoryUtil.memPutInt(ptr + 4L*i, 0); + MemoryUtil.memPutInt(ptr + 4L*i, this.nodeManager.getTopLevelNodeIds().getInt(i)); } UploadStream.INSTANCE.commit(); diff --git a/src/main/java/me/cortex/voxy/client/core/rendering/hierachical2/NodeManager2.java b/src/main/java/me/cortex/voxy/client/core/rendering/hierachical2/NodeManager2.java index a3bbba34..a4bd29dd 100644 --- a/src/main/java/me/cortex/voxy/client/core/rendering/hierachical2/NodeManager2.java +++ b/src/main/java/me/cortex/voxy/client/core/rendering/hierachical2/NodeManager2.java @@ -1,5 +1,6 @@ package me.cortex.voxy.client.core.rendering.hierachical2; +import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; import me.cortex.voxy.client.core.gl.GlBuffer; @@ -12,6 +13,10 @@ import me.cortex.voxy.common.Logger; import me.cortex.voxy.common.world.WorldEngine; import me.jellysquid.mods.sodium.client.util.MathUtil; +import java.util.List; + + + public class NodeManager2 { //Assumptions: // all nodes have children (i.e. all nodes have at least one child existence bit set at all times) @@ -22,6 +27,18 @@ public class NodeManager2 { // For the queue processing, will need a redirect node-value type // since for inner node child resize gpu could take N frames to update + + + //There is a very funny issue that has kinda, just resolved itself accidentally, + // however i wonder if i want a better solution for. + //That issue is, top level nodes that have no children + // the accidental solution, is that when the node is marked, it generates + // the child request, + // however, since there are no children in it, it sticks around, since there isnt anything to update it and invoke + // the finishRequest on it + // if the top level node ends up being updated with a child update, it should automatically solve itself + // as the new children are added to the already inprogress request!!!! + public static final int NULL_GEOMETRY_ID = -1; public static final int EMPTY_GEOMETRY_ID = -2; @@ -44,6 +61,7 @@ public class NodeManager2 { private final Long2IntOpenHashMap activeSectionMap = new Long2IntOpenHashMap(); private final NodeStore nodeData; public final int maxNodeCount; + private final IntArrayList topLevelNodeIds = new IntArrayList(); public NodeManager2(int maxNodeCount, AbstractSectionGeometryManager geometryManager, SectionUpdateRouter updateRouter) { if (!MathUtil.isPowerOfTwo(maxNodeCount)) { throw new IllegalArgumentException("Max node count must be a power of 2"); @@ -68,6 +86,8 @@ public class NodeManager2 { int id = this.singleRequests.put(request); this.updateRouter.watch(pos, WorldEngine.UPDATE_FLAGS); this.activeSectionMap.put(pos, id|NODE_TYPE_REQUEST|REQUEST_TYPE_SINGLE); + + } public void removeTopLevelNode(long pos) { @@ -77,6 +97,16 @@ public class NodeManager2 { return; } //TODO: assert is top level node + + //TODO:FIXME augment topLevelNodeIds with a hashmap from node id to array index + // OR!! just ensure the list is always ordered?? maybe? idk i think hashmap is best + // since the array list might get shuffled as nodes are removed + // since need to move the entry at the end of the array to fill a hole made + } + + + IntArrayList getTopLevelNodeIds() { + return this.topLevelNodeIds; } //================================================================================================================== @@ -217,6 +247,11 @@ public class NodeManager2 { //this.nodeData.setNodeType(); this.activeSectionMap.put(request.getPosition(), id|NODE_TYPE_LEAF);//Assume that the result of any single request type is a leaf node this.nodeUpdates.add(id); + + + //Assume that this is always a top node + // FIXME: DONT DO THIS + this.topLevelNodeIds.add(id); } private void finishRequest(int requestId, NodeChildRequest request) { @@ -367,4 +402,8 @@ public class NodeManager2 { (WorldEngine.getY(basePos)<<1)|((addin>>2)&1), (WorldEngine.getZ(basePos)<<1)|((addin>>1)&1)); } + + public void addDebug(List debug) { + debug.add("NC/IF: " + this.activeSectionMap.size() + "/" + (this.singleRequests.count() + this.childRequests.count())); + } } diff --git a/src/main/java/me/cortex/voxy/client/core/rendering/hierachical2/NodeStore.java b/src/main/java/me/cortex/voxy/client/core/rendering/hierachical2/NodeStore.java index 5e5f9d54..65a326c5 100644 --- a/src/main/java/me/cortex/voxy/client/core/rendering/hierachical2/NodeStore.java +++ b/src/main/java/me/cortex/voxy/client/core/rendering/hierachical2/NodeStore.java @@ -235,6 +235,7 @@ public final class NodeStore { int w = 0; short flags = 0; + flags |= (short) (this.isNodeRequestInFlight(nodeId)?1:0); flags |= (short) (this.getChildPtrCount(nodeId)<<2); { diff --git a/src/main/java/me/cortex/voxy/client/core/rendering/section/AbstractSectionGeometryManager.java b/src/main/java/me/cortex/voxy/client/core/rendering/section/AbstractSectionGeometryManager.java index f8e95648..83896ec4 100644 --- a/src/main/java/me/cortex/voxy/client/core/rendering/section/AbstractSectionGeometryManager.java +++ b/src/main/java/me/cortex/voxy/client/core/rendering/section/AbstractSectionGeometryManager.java @@ -21,7 +21,7 @@ public abstract class AbstractSectionGeometryManager { public int uploadSection(BuiltSection section) {return this.uploadReplaceSection(-1, section);} public abstract int uploadReplaceSection(int oldId, BuiltSection section); public abstract void removeSection(int id); - void tick() {} + public void tick() {} public void free() {} } diff --git a/src/main/java/me/cortex/voxy/client/core/rendering/section/BasicSectionGeometryManager.java b/src/main/java/me/cortex/voxy/client/core/rendering/section/BasicSectionGeometryManager.java index 28ba5903..9b0cfa45 100644 --- a/src/main/java/me/cortex/voxy/client/core/rendering/section/BasicSectionGeometryManager.java +++ b/src/main/java/me/cortex/voxy/client/core/rendering/section/BasicSectionGeometryManager.java @@ -105,7 +105,7 @@ public class BasicSectionGeometryManager extends AbstractSectionGeometryManager } @Override - void tick() { + public void tick() { //Upload all invalidated bits if (!this.invalidatedSectionIds.isEmpty()) { for (int id : this.invalidatedSectionIds) { diff --git a/src/main/java/me/cortex/voxy/client/core/rendering/section/MDICSectionRenderer.java b/src/main/java/me/cortex/voxy/client/core/rendering/section/MDICSectionRenderer.java index 6bbfc15c..3a8bb3e8 100644 --- a/src/main/java/me/cortex/voxy/client/core/rendering/section/MDICSectionRenderer.java +++ b/src/main/java/me/cortex/voxy/client/core/rendering/section/MDICSectionRenderer.java @@ -34,6 +34,7 @@ import static org.lwjgl.opengl.GL45.glCopyNamedBufferSubData; //Uses MDIC to render the sections public class MDICSectionRenderer extends AbstractSectionRenderer { private final Shader terrainShader = Shader.make() + .defineIf("DEBUG_RENDER", false) .add(ShaderType.VERTEX, "voxy:lod/gl46/quads2.vert") .add(ShaderType.FRAGMENT, "voxy:lod/gl46/quads.frag") .compile(); @@ -119,11 +120,6 @@ public class MDICSectionRenderer extends AbstractSectionRenderer lines) { super.addDebug(lines); - lines.add("NC/GS: " + this.geometryManager.getSectionCount() + "/" + (this.geometryManager.getGeometryUsed()/(1024*1024)));//Node count/geometry size (MB) + lines.add("SC/GS: " + this.geometryManager.getSectionCount() + "/" + (this.geometryManager.getGeometryUsed()/(1024*1024)));//section count/geometry size (MB) } @Override diff --git a/src/main/java/me/cortex/voxy/client/core/util/ExpandingObjectAllocationList.java b/src/main/java/me/cortex/voxy/client/core/util/ExpandingObjectAllocationList.java index f36a77ce..200516ee 100644 --- a/src/main/java/me/cortex/voxy/client/core/util/ExpandingObjectAllocationList.java +++ b/src/main/java/me/cortex/voxy/client/core/util/ExpandingObjectAllocationList.java @@ -42,4 +42,8 @@ public class ExpandingObjectAllocationList { } return this.objects[index]; } + + public int count() { + return this.bitSet.getCount(); + } } diff --git a/src/main/resources/assets/voxy/shaders/lod/hierarchical/traversal_dev.comp b/src/main/resources/assets/voxy/shaders/lod/hierarchical/traversal_dev.comp index 4a26eab4..63a1e37d 100644 --- a/src/main/resources/assets/voxy/shaders/lod/hierarchical/traversal_dev.comp +++ b/src/main/resources/assets/voxy/shaders/lod/hierarchical/traversal_dev.comp @@ -88,7 +88,9 @@ void traverse(in UnpackedNode node) { addRequest(node); //TODO: Decend into children? maybe add a bitflag saying is bad if the immediate children dont have meshes - enqueueChildren(node); + if (node.lodLevel != 0) { + enqueueChildren(node); + } } } }