This commit is contained in:
mcrcortex
2024-11-28 17:36:53 +10:00
parent fac00a81d3
commit 53672d3ace
8 changed files with 70 additions and 32 deletions

View File

@@ -8,6 +8,7 @@ import me.cortex.voxy.client.core.rendering.post.PostProcessing;
import me.cortex.voxy.client.core.rendering.util.DownloadStream;
import me.cortex.voxy.client.core.util.IrisUtil;
import me.cortex.voxy.client.saver.ContextSelectionSystem;
import me.cortex.voxy.common.Logger;
import me.cortex.voxy.common.world.WorldEngine;
import me.cortex.voxy.client.importers.WorldImporter;
import me.cortex.voxy.common.thread.ServiceThreadPool;
@@ -64,17 +65,17 @@ public class VoxelCore {
this.serviceThreadPool = new ServiceThreadPool(VoxyConfig.CONFIG.serviceThreads);
this.world = worldSelection.createEngine(this.serviceThreadPool);
System.out.println("Initializing voxy core");
Logger.info("Initializing voxy core");
//Trigger the shared index buffer loading
SharedIndexBuffer.INSTANCE.id();
Capabilities.init();//Ensure clinit is called
this.renderer = new RenderService(this.world, this.serviceThreadPool);
System.out.println("Using " + this.renderer.getClass().getSimpleName());
Logger.info("Using " + this.renderer.getClass().getSimpleName());
this.postProcessing = new PostProcessing();
System.out.println("Voxy core initialized");
Logger.info("Voxy core initialized");
//this.verifyTopNodeChildren(0,0,0);
}
@@ -174,7 +175,7 @@ public class VoxelCore {
// since they are AABBS crossing the normal is impossible without one of the axis being equal
public void shutdown() {
System.out.println("Flushing download stream");
Logger.info("Flushing download stream");
DownloadStream.INSTANCE.flushWaitClear();
//if (Thread.currentThread() != this.shutdownThread) {
@@ -183,18 +184,18 @@ public class VoxelCore {
//this.world.getMapper().forceResaveStates();
if (this.importer != null) {
System.out.println("Shutting down importer");
try {this.importer.shutdown();this.importer = null;} catch (Exception e) {e.printStackTrace();}
Logger.info("Shutting down importer");
try {this.importer.shutdown();this.importer = null;} catch (Exception e) {Logger.error("Error shutting down importer", e);}
}
System.out.println("Shutting down rendering");
try {this.renderer.shutdown();} catch (Exception e) {e.printStackTrace();}
System.out.println("Shutting down post processor");
if (this.postProcessing!=null){try {this.postProcessing.shutdown();} catch (Exception e) {e.printStackTrace();}}
System.out.println("Shutting down world engine");
try {this.world.shutdown();} catch (Exception e) {e.printStackTrace();}
System.out.println("Shutting down service thread pool");
Logger.info("Shutting down rendering");
try {this.renderer.shutdown();} catch (Exception e) {Logger.error("Error shutting down renderer", e);}
Logger.info("Shutting down post processor");
if (this.postProcessing!=null){try {this.postProcessing.shutdown();} catch (Exception e) {Logger.error("Error shutting down post processor", e);}}
Logger.info("Shutting down world engine");
try {this.world.shutdown();} catch (Exception e) {Logger.error("Error shutting down world engine", e);}
Logger.info("Shutting down service thread pool");
this.serviceThreadPool.shutdown();
System.out.println("Voxel core shut down");
Logger.info("Voxel core shut down");
}
public boolean createWorldImporter(World mcWorld, File worldPath) {
@@ -235,7 +236,7 @@ public class VoxelCore {
if (lvl == 0) {
var own = this.world.acquire(lvl, x, y, z);
if ((own.getNonEmptyChildren() != 0) ^ (own.getNonEmptyBlockCount() != 0)) {
System.err.println("Lvl 0 node not marked correctly " + WorldEngine.pprintPos(own.key));
Logger.error("Lvl 0 node not marked correctly " + WorldEngine.pprintPos(own.key));
}
own.release();
} else {
@@ -247,7 +248,7 @@ public class VoxelCore {
}
var own = this.world.acquire(lvl, x, y, z);
if (own.getNonEmptyChildren() != msk) {
System.err.println("Section empty child mask not correct " + WorldEngine.pprintPos(own.key) + " got: " + String.format("%8s", Integer.toBinaryString(Byte.toUnsignedInt(own.getNonEmptyChildren()))).replace(' ', '0') + " expected: " + String.format("%8s", Integer.toBinaryString(Byte.toUnsignedInt(msk))).replace(' ', '0'));
Logger.error("Section empty child mask not correct " + WorldEngine.pprintPos(own.key) + " got: " + String.format("%8s", Integer.toBinaryString(Byte.toUnsignedInt(own.getNonEmptyChildren()))).replace(' ', '0') + " expected: " + String.format("%8s", Integer.toBinaryString(Byte.toUnsignedInt(msk))).replace(' ', '0'));
}
own.release();
}

View File

@@ -38,7 +38,7 @@ public class ModelBakerySubsystem {
public void tick() {
//There should be a method to access the frame time IIRC, if the user framecap is unlimited lock it to like 60 fps for computation
int BUDGET = 20;//TODO: make this computed based on the remaining free time in a frame (and like div by 2 to reduce overhead) (with a min of 1)
int BUDGET = 10;//TODO: make this computed based on the remaining free time in a frame (and like div by 2 to reduce overhead) (with a min of 1)
for (int i = 0; i < BUDGET && !this.blockIdQueue.isEmpty(); i++) {
int blockId = -1;

View File

@@ -47,7 +47,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<<19, (1L<<31)-1024);
this.sectionRenderer = (T) createSectionRenderer(this.modelService.getStore(),1<<19, (1L<<30)-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

@@ -28,7 +28,7 @@ import static org.lwjgl.opengl.GL45.*;
// TODO: swap to persistent gpu threads instead of dispatching MAX_ITERATIONS of compute layers
public class HierarchicalOcclusionTraverser {
public static final int REQUEST_QUEUE_SIZE = 256;
public static final int REQUEST_QUEUE_SIZE = 50;
private final NodeManager2 nodeManager;
@@ -242,12 +242,16 @@ public class HierarchicalOcclusionTraverser {
throw new IllegalStateException("Count unexpected extreme value: " + count);
}
if (count > (this.requestBuffer.size()>>3)-1) {
Logger.warn("Count over max buffer size, clamping, got count: " + count);
//This should not break the synchonization between gpu and cpu as in the traversal shader is
// `if (atomRes < REQUEST_QUEUE_SIZE) {` which forcefully clamps to the request size
//Logger.warn("Count over max buffer size, clamping, got count: " + count + ".");
count = (int) ((this.requestBuffer.size()>>3)-1);
}
if (count > REQUEST_QUEUE_SIZE) {
System.err.println("Count larger than 'maxRequestCount', overflow captured. Overflowed by " + (count-REQUEST_QUEUE_SIZE));
}
//if (count > REQUEST_QUEUE_SIZE) {
// Logger.warn("Count larger than 'maxRequestCount', overflow captured. Overflowed by " + (count-REQUEST_QUEUE_SIZE));
//}
if (count != 0) {
//this.nodeManager.processRequestQueue(count, ptr + 8);

View File

@@ -17,6 +17,12 @@ import java.util.List;
//TODO FIXME: CIRTICAL ISSUE: if a node is a top level section and is empty, when a child is tried to be made it explodes
// since all the children are empty
// To properly fix this, the top level nodes should only exist if there are non empty children
// (issues related to this fix, lod updates from 0 children state to something children state, aswell as other way round)
public class NodeManager2 {
//Assumptions:
// all nodes have children (i.e. all nodes have at least one child existence bit set at all times)
@@ -62,6 +68,8 @@ public class NodeManager2 {
private final NodeStore nodeData;
public final int maxNodeCount;
private final IntArrayList topLevelNodeIds = new IntArrayList();
private int activeNodeRequestCount;
public NodeManager2(int maxNodeCount, AbstractSectionGeometryManager geometryManager, SectionUpdateRouter updateRouter) {
if (!MathUtil.isPowerOfTwo(maxNodeCount)) {
throw new IllegalArgumentException("Max node count must be a power of 2");
@@ -86,8 +94,6 @@ 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) {
@@ -154,7 +160,7 @@ public class NodeManager2 {
} else if ((nodeId&NODE_TYPE_MSK)==NODE_TYPE_INNER || (nodeId&NODE_TYPE_MSK)==NODE_TYPE_LEAF) {
// Just doing a geometry update
if (this.updateNodeGeometry(nodeId&NODE_ID_MSK, sectionResult) != 0) {
this.nodeUpdates.add(nodeId&NODE_ID_MSK);
this.invalidateNode(nodeId&NODE_ID_MSK);
}
}
}
@@ -246,7 +252,7 @@ public class NodeManager2 {
//TODO: this (or remove)
//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);
this.invalidateNode(id);
//Assume that this is always a top node
@@ -277,7 +283,7 @@ public class NodeManager2 {
this.nodeData.setNodeChildExistence(childNodeId, request.getChildChildExistence(childIdx));
this.nodeData.setNodeGeometry(childNodeId, request.getChildMesh(childIdx));
//Mark for update
this.nodeUpdates.add(childNodeId);
this.invalidateNode(childNodeId);
//Put in map
int pid = this.activeSectionMap.put(childPos, childNodeId|NODE_TYPE_LEAF);
if ((pid&NODE_TYPE_MSK) != NODE_TYPE_REQUEST) {
@@ -290,8 +296,9 @@ public class NodeManager2 {
this.nodeData.setChildPtr(parentNodeId, base);
this.nodeData.setChildPtrCount(parentNodeId, offset+1);
this.nodeData.setNodeRequest(parentNodeId, 0);//TODO: create a better null request
this.activeNodeRequestCount--;
this.nodeData.unmarkRequestInFlight(parentNodeId);
this.nodeUpdates.add(parentNodeId);
this.invalidateNode(parentNodeId);
} else if ((parentNodeId&NODE_TYPE_MSK)==NODE_TYPE_INNER) {
System.err.println("TODO: FIXME FINISH: finishRequest NODE_TYPE_INNER");
} else {
@@ -319,8 +326,17 @@ public class NodeManager2 {
Logger.warn("Tried processing a node that already has a request in flight: " + nodeId + " pos: " + WorldEngine.pprintPos(pos) + " ignoring");
return;
}
this.nodeData.markRequestInFlight(nodeId);
//TODO: ADJUST AND FIX THIS TO MAKE IT REMOVE THE LAST THING IN QUEUE OR SOMETHING
//if (this.activeNodeRequestCount > 100 && WorldEngine.getLevel(pos) < 2) {
//Logger.info("Many active requests, declining request at " + WorldEngine.pprintPos(pos));
// this.invalidateNode(nodeId);
// return;
//}
this.nodeData.markRequestInFlight(nodeId);
if (nodeType == NODE_TYPE_LEAF) {
//The hard one of processRequest, spin up a new request for the node
this.makeLeafChildRequest(nodeId);
@@ -355,6 +371,7 @@ public class NodeManager2 {
//Insert all the children into the tracking map with the node id
int pid = this.activeSectionMap.put(childPos, requestId|NODE_TYPE_REQUEST|REQUEST_TYPE_CHILD);
if (pid != -1) {
throw new IllegalStateException("Leaf request creation failed to insert child into map as a mapping already existed for the node! pos: " + WorldEngine.pprintPos(childPos) + " id: " + pid);
}
@@ -366,6 +383,7 @@ public class NodeManager2 {
}
this.nodeData.setNodeRequest(nodeId, requestId);
this.activeNodeRequestCount++;
}
//==================================================================================================================
@@ -393,7 +411,9 @@ public class NodeManager2 {
return true;
}
private void invalidateNode(int nodeId) {
this.nodeUpdates.add(nodeId);
}
//==================================================================================================================
private static int getChildIdx(long pos) {

View File

@@ -33,6 +33,7 @@ public class ExpandingObjectAllocationList<T> {
if (!this.bitSet.free(id)) {
throw new IllegalArgumentException("Index " + id + " was already released");
}
this.objects[id] = null;
}
public T get(int index) {

View File

@@ -29,4 +29,15 @@ public class Logger {
var stackEntry = new Throwable().getStackTrace()[1];
LOGGER.warn("["+stackEntry.getClassName()+"]: "+ Stream.of(args).map(Object::toString).collect(Collectors.joining(" ")), throwable);
}
public static void info(Object... args) {
Throwable throwable = null;
for (var i : args) {
if (i instanceof Throwable) {
throwable = (Throwable) i;
}
}
var stackEntry = new Throwable().getStackTrace()[1];
LOGGER.info("["+stackEntry.getClassName()+"]: "+ Stream.of(args).map(Object::toString).collect(Collectors.joining(" ")), throwable);
}
}

View File

@@ -1,6 +1,7 @@
package me.cortex.voxy.common.storage.lmdb;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import me.cortex.voxy.common.Logger;
import me.cortex.voxy.common.storage.StorageBackend;
import me.cortex.voxy.common.storage.config.ConfigBuildCtx;
import me.cortex.voxy.common.storage.config.StorageConfig;
@@ -40,7 +41,7 @@ public class LMDBStorageBackend extends StorageBackend {
private void growEnv() {
long size = this.dbi.getMapSize() + GROW_SIZE;
System.out.println("Growing DBI env size to: " + size + " bytes");
Logger.info("Growing DBI env size to: " + size + " bytes");
this.dbi.setMapSize(size);
}