node clean something, its still broken mode

This commit is contained in:
mcrcortex
2025-01-28 06:03:06 +10:00
parent aac3db90d3
commit 4d6859db43
7 changed files with 54 additions and 26 deletions

View File

@@ -49,7 +49,7 @@ public class RenderService<T extends AbstractSectionRenderer<J, ?>, J extends Vi
//Max sections: ~500k
//Max geometry: 1 gb
this.sectionRenderer = (T) createSectionRenderer(this.modelService.getStore(),1<<20, (1L<<30)-1024);
this.sectionRenderer = (T) createSectionRenderer(this.modelService.getStore(),1<<20, (1L<<32)-1024);
//Do something incredibly hacky, we dont need to keep the reference to this around, so just connect and discard
var router = new SectionUpdateRouter();

View File

@@ -3,8 +3,10 @@ package me.cortex.voxy.client.core.rendering.hierachical;
import it.unimi.dsi.fastutil.ints.IntArrayFIFOQueue;
import me.cortex.voxy.client.core.gl.GlBuffer;
import me.cortex.voxy.client.core.gl.shader.AutoBindingShader;
import me.cortex.voxy.client.core.gl.shader.PrintfInjector;
import me.cortex.voxy.client.core.gl.shader.Shader;
import me.cortex.voxy.client.core.gl.shader.ShaderType;
import me.cortex.voxy.client.core.rendering.PrintfDebugUtil;
import me.cortex.voxy.client.core.rendering.util.DownloadStream;
import me.cortex.voxy.client.core.rendering.util.UploadStream;
import me.cortex.voxy.common.world.WorldEngine;
@@ -30,10 +32,11 @@ public class NodeCleaner {
private static final int BATCH_SET_SIZE = 2048;
private final AutoBindingShader sorter = Shader.makeAuto()
private final AutoBindingShader sorter = Shader.makeAuto(PrintfDebugUtil.PRINTF_processor)
.define("OUTPUT_SIZE", OUTPUT_COUNT)
.define("VISIBILITY_BUFFER_BINDING", 1)
.define("OUTPUT_BUFFER_BINDING", 2)
.define("NODE_DATA_BINDING", 3)
.add(ShaderType.COMPUTE, "voxy:lod/hierarchical/cleaner/sort_visibility.comp")
.compile();
@@ -75,6 +78,8 @@ public class NodeCleaner {
this.sorter
.ssbo("VISIBILITY_BUFFER_BINDING", this.visibilityBuffer)
.ssbo("OUTPUT_BUFFER_BINDING", this.outputBuffer);
this.nodeManager.setClearIdCallback(this::clearId);
}
public void clearId(int id) {
@@ -90,6 +95,8 @@ public class NodeCleaner {
this.outputBuffer.fill(this.nodeManager.maxNodeCount-2);//TODO: maybe dont set to zero??
this.sorter.bind();
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, nodeDataBuffer.id);
//TODO: choose whether this is in nodeSpace or section/geometryId space
//this.nodeManager.getCurrentMaxNodeId()
glDispatchCompute((200_000+127)/128, 1, 1);
@@ -105,16 +112,12 @@ public class NodeCleaner {
glDispatchCompute(1,1,1);
DownloadStream.INSTANCE.download(this.outputBuffer, 4*OUTPUT_COUNT, 8*OUTPUT_COUNT, this::onDownload);
this.visibilityBuffer.fill(-1);
}
}
private boolean shouldCleanGeometry() {
// if there is less than 200mb of space, clean
return this.nodeManager.getGeometryManager().getRemainingCapacity() < 200_000_000L;
return this.nodeManager.getGeometryManager().getRemainingCapacity() < 500_000_000L;
}
private void onDownload(long ptr, long size) {
@@ -122,6 +125,10 @@ public class NodeCleaner {
for (int i = 0; i < 64; i++) {
long pos = Integer.toUnsignedLong(MemoryUtil.memGetInt(ptr + 8 * i))<<32;
pos |= Integer.toUnsignedLong(MemoryUtil.memGetInt(ptr + 8 * i + 4));
if (pos == 0) {
//TODO: investigate how or what this happens
continue;
}
this.nodeManager.removeNodeGeometry(pos);
//b.append(", ").append(WorldEngine.pprintPos(pos));//.append(((int)((pos>>32)&0xFFFFFFFFL)));//
}
@@ -139,7 +146,8 @@ public class NodeCleaner {
MemoryUtil.memPutInt(ptr + cnt * 4, this.idsToClear.dequeueInt());
}
UploadStream.INSTANCE.commit();
glUniform1i(0, cnt);
glUniform1ui(0, cnt);
glUniform1ui(1, this.visibilityId);
glDispatchCompute((cnt+127)/128, 1, 1);
}
}

View File

@@ -73,6 +73,11 @@ public class NodeManager {
private final IntArrayList topLevelNodeIds = new IntArrayList();
private int activeNodeRequestCount;
public interface ClearIdCallback {void clearId(int id);}
private ClearIdCallback clearIdCallback;
public void setClearIdCallback(ClearIdCallback callback) {this.clearIdCallback = callback;}
private void clearId(int id) { if (this.clearIdCallback != null) this.clearIdCallback.clearId(id); }
public NodeManager(int maxNodeCount, AbstractSectionGeometryManager geometryManager, SectionUpdateRouter updateRouter) {
if (!MathUtil.isPowerOfTwo(maxNodeCount)) {
throw new IllegalArgumentException("Max node count must be a power of 2");
@@ -222,7 +227,6 @@ public class NodeManager {
}
//==================================================================================================================
//TODO: cleanup this code shitshow and extract common operations to reduce code duplication
public void processChildChange(long pos, byte childExistence) {
int nodeId = this.activeSectionMap.get(pos);
if (nodeId == -1) {
@@ -460,13 +464,13 @@ public class NodeManager {
Logger.error("UNFINISHED OPERATION TODO: FIXME2");
//Free geometry and related memory for this node
this.nodeData.free(nodeId);
this.clearId(nodeId);
//Unwatch geometry
if (!this.updateRouter.unwatch(pos, WorldEngine.UPDATE_FLAGS)) {
throw new IllegalStateException("Pos was not being watched");
}
} else {
Logger.error("UNFINISHED OPERATION TODO: FIXME3");
@@ -522,6 +526,8 @@ public class NodeManager {
this.nodeData.setNodeGeometry(childNodeId, request.getChildMesh(childIdx));
//Mark for update
this.invalidateNode(childNodeId);
this.clearId(childNodeId);//Clear the id
//Put in map
int pid = this.activeSectionMap.put(childPos, childNodeId|NODE_TYPE_LEAF);
if ((pid&NODE_TYPE_MSK) != NODE_TYPE_REQUEST) {
@@ -780,6 +786,9 @@ public class NodeManager {
return;
}
//Reset/clear the id
this.clearId(nodeId);
if (nodeType == NODE_TYPE_LEAF) {
//If it is a leaf node, check that the parent has geometry, if it doesnt, request geometry for that parent
// if it DOES tho, remove all the children and make the parent a leaf node
@@ -791,7 +800,10 @@ public class NodeManager {
if (WorldEngine.getLevel(pos) == MAX_LOD_LAYERS-1) {
//Cannot remove top level nodes
Logger.info("Tried cleaning top level node " + WorldEngine.pprintPos(pos));
//Logger.info("Tried cleaning top level node " + WorldEngine.pprintPos(pos));
this.removeGeometryInternal(pos, nodeId);
return;
}
@@ -804,15 +816,19 @@ public class NodeManager {
if (this.nodeData.getNodeGeometry(pId) == NULL_GEOMETRY_ID) {
//If the parent has null geometry we must first fill it before we can remove it
//Logger.error("TODO: THIS");
Logger.error("TODO: THIS");
} else {
//Else make the parent node a leaf node and remove all the children
//Logger.error("TODO: THIS 2");
Logger.error("TODO: THIS 2");
}
//this.removeGeometryInternal(pos, nodeId);
return;
}
this.removeGeometryInternal(pos, nodeId);
}
private void removeGeometryInternal(long pos, int nodeId) {
int geometryId = this.nodeData.getNodeGeometry(nodeId);
if (geometryId != NULL_GEOMETRY_ID && geometryId != EMPTY_GEOMETRY_ID) {
//Unwatch geometry updates
@@ -826,7 +842,6 @@ public class NodeManager {
//this.cleaner
}
this.invalidateNode(nodeId);
}
//==================================================================================================================

View File

@@ -66,7 +66,7 @@ public final class NodeStore {
}
}
private void free(int nodeId) {
public void free(int nodeId) {
this.free(nodeId, 1);
}

View File

@@ -11,11 +11,11 @@ layout(binding = LIST_BUFFER_BINDING, std430) restrict readonly buffer SetListBu
};
layout(location=0) uniform uint count;
#define SET_TO uint(-1)
layout(location=1) uniform uint setTo;
void main() {
uint id = gl_GlobalInvocationID.x;
if (count <= id) {
return;
}
visiblity[ids[id]] = SET_TO;
visiblity[ids[id]] = setTo;
}

View File

@@ -7,6 +7,7 @@
layout(local_size_x=128, local_size_y=1) in;
//256 workgroup
#import <voxy:lod/hierarchical/node.glsl>
layout(binding = VISIBILITY_BUFFER_BINDING, std430) restrict readonly buffer VisibilityDataBuffer {
uint[] visiblity;
@@ -54,5 +55,10 @@ void main() {
if (visiblity[minVisIds[OUTPUT_SIZE-1]] <= vis) {
return;
}
UnpackedNode node;
unpackNode(node, gl_GlobalInvocationID.x);
if (isEmptyMesh(node) || !hasMesh(node)) {
return;
}
bubbleSort(0, gl_GlobalInvocationID.x, vis);
}

View File

@@ -61,15 +61,14 @@ void enqueueChildren(in UnpackedNode node) {
void enqueueSelfForRender(in UnpackedNode node) {
//printf("render %d@[%d,%d,%d]", node.lodLevel, node.pos.x, node.pos.y, node.pos.z);
if ((!isEmptyMesh(node)) && renderQueueIndex < renderQueueMaxSize) {
renderQueue[atomicAdd(renderQueueIndex, 1)] = getMesh(node);
#ifdef IS_DEBUG
debugRenderNodeQueue[atomicAdd(debugRenderNodeQueueIndex, 1)] = node.nodeId;
#endif
//TODO: decide if it should be this node id, or the mesh id
// for now do node id... think
if (renderQueueIndex < renderQueueMaxSize) {
lastRenderFrame[getId(node)] = frameId;
if (!isEmptyMesh(node)) {
renderQueue[atomicAdd(renderQueueIndex, 1)] = getMesh(node);
#ifdef IS_DEBUG
debugRenderNodeQueue[atomicAdd(debugRenderNodeQueueIndex, 1)] = node.nodeId;
#endif
}
}
}