Even more pain, but gpu side should fully work ™️
This commit is contained in:
@@ -75,7 +75,9 @@ public class RenderService<T extends AbstractSectionRenderer<J, ?>, J extends Vi
|
||||
Arrays.stream(world.getMapper().getBiomeEntries()).forEach(this.modelService::addBiome);
|
||||
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;
|
||||
for (int x = -H_WIDTH; x <= H_WIDTH; x++) {
|
||||
for (int y = -1; y <= 0; y++) {
|
||||
@@ -83,7 +85,7 @@ public class RenderService<T extends AbstractSectionRenderer<J, ?>, J extends Vi
|
||||
this.nodeManager.insertTopLevelNode(WorldEngine.getWorldSectionId(4, x, y, z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
public void setup(Camera camera) {
|
||||
@@ -117,6 +119,9 @@ public class RenderService<T extends AbstractSectionRenderer<J, ?>, 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();
|
||||
}
|
||||
}
|
||||
UploadStream.INSTANCE.tick();
|
||||
|
||||
|
||||
@@ -3,9 +3,11 @@ package me.cortex.voxy.client.core.rendering.hierachical2;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
||||
import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap;
|
||||
import me.cortex.voxy.client.core.gl.GlBuffer;
|
||||
import me.cortex.voxy.client.core.rendering.building.BuiltSection;
|
||||
import me.cortex.voxy.client.core.rendering.building.SectionUpdateRouter;
|
||||
import me.cortex.voxy.client.core.rendering.section.AbstractSectionGeometryManager;
|
||||
import me.cortex.voxy.client.core.rendering.util.UploadStream;
|
||||
import me.cortex.voxy.client.core.util.ExpandingObjectAllocationList;
|
||||
import me.cortex.voxy.common.Logger;
|
||||
import me.cortex.voxy.common.world.WorldEngine;
|
||||
@@ -102,7 +104,7 @@ public class HierarchicalNodeManager {
|
||||
|
||||
int id = this.nodeData.allocate();
|
||||
this.nodeData.setNodePosition(id, position);
|
||||
this.activeSectionMap.put(position, id|ID_TYPE_LEAF);//ID_TYPE_TOP
|
||||
this.activeSectionMap.put(position, id|ID_TYPE_LEAF); this.nodeData.setNodeType(id, ID_TYPE_LEAF); //ID_TYPE_TOP
|
||||
this.updateRouter.watch(position, WorldEngine.UPDATE_FLAGS);
|
||||
}
|
||||
|
||||
@@ -182,7 +184,8 @@ public class HierarchicalNodeManager {
|
||||
|
||||
//2 branches, either its a leaf node -> emit a leaf request
|
||||
// or the nodes geometry must be empty (i.e. culled from the graph/tree) so add to tracker and watch
|
||||
if (this.nodeData.isLeafNode(node)) {
|
||||
int type = this.nodeData.getNodeType(node);
|
||||
if (type == ID_TYPE_LEAF) {
|
||||
this.makeLeafRequest(node, this.nodeData.getNodeChildExistence(node));
|
||||
} else {
|
||||
//Verify that the node section is not in the section store. if it is then it is a state desynchonization
|
||||
@@ -190,6 +193,8 @@ public class HierarchicalNodeManager {
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: FIXME: so there is a fundamental issue with this, if the gpu requests from cpu before childExistance is set
|
||||
// then everything explodes cause it wont get notified or updated
|
||||
private void makeLeafRequest(int node, byte childExistence) {
|
||||
long pos = this.nodeData.nodePosition(node);
|
||||
|
||||
@@ -205,6 +210,7 @@ public class HierarchicalNodeManager {
|
||||
}
|
||||
long childPos = makeChildPos(pos, i);
|
||||
request.addChildRequirement(i);
|
||||
|
||||
//Insert all the children into the tracking map with the node id
|
||||
if (this.activeSectionMap.put(childPos, requestId|ID_TYPE_REQUEST) != NO_NODE) {
|
||||
throw new IllegalStateException("Leaf request creation failed to insert child into map as a mapping already existed for the node!");
|
||||
@@ -297,7 +303,7 @@ public class HierarchicalNodeManager {
|
||||
if ((toAdd & (i << 1)) == 0) continue;
|
||||
request.addChildRequirement(i);
|
||||
long cpos = makeChildPos(position, i);
|
||||
int prev = this.activeSectionMap.put(cpos, ID_TYPE_REQUEST|reqId);
|
||||
int prev = this.activeSectionMap.put(cpos, reqId|ID_TYPE_REQUEST);
|
||||
if (prev!=-1) {
|
||||
throw new IllegalStateException("Child is already mapped to a node id " + WorldEngine.pprintPos(cpos) + " " + reqId + " " + prev);
|
||||
}
|
||||
@@ -386,9 +392,17 @@ public class HierarchicalNodeManager {
|
||||
|
||||
//Process NodeChildRequest results
|
||||
private void consumeFinishedNodeChildRequest(int nodeId, NodeChildRequest request) {
|
||||
//TODO:!!! NOTE: DONT
|
||||
|
||||
int children = this.nodeData.getChildPtr(nodeId);
|
||||
if (children != NO_NODE) {
|
||||
//There are children already part of this node, so need to reallocate all the children
|
||||
//There are children already part of this node, so need to reallocate all the children which is _really_ bad as it can cause so many desyncs
|
||||
// between gpu and cpu its not even funny
|
||||
|
||||
//TODO: what will need to be done is a fence be created, and to not release the ids until the gpu is done with them??
|
||||
// that _might :tm:_ help with preventing desyncs???
|
||||
// the issue is like a request right, sends id to cpu, that id might have changed and everything then proceeds to explode
|
||||
|
||||
int count = Integer.bitCount(Byte.toUnsignedInt(this.nodeData.getNodeChildExistence(nodeId)));
|
||||
|
||||
} else {
|
||||
@@ -396,6 +410,22 @@ public class HierarchicalNodeManager {
|
||||
}
|
||||
}
|
||||
|
||||
//============================================================================================
|
||||
|
||||
public boolean writeChanges(GlBuffer nodeBuffer) {
|
||||
//TODO: use like compute based copy system or something
|
||||
// since microcopies are bad
|
||||
if (this.nodeUpdates.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
for (int i : this.nodeUpdates) {
|
||||
this.nodeData.writeNode(UploadStream.INSTANCE.upload(nodeBuffer, i*16L, 16L), i);
|
||||
}
|
||||
this.nodeUpdates.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================================================================================
|
||||
|
||||
private static int getChildIdx(long pos) {
|
||||
|
||||
@@ -244,6 +244,10 @@ public class HierarchicalOcclusionTraverser {
|
||||
}
|
||||
}
|
||||
|
||||
public GlBuffer getNodeBuffer() {
|
||||
return this.nodeBuffer;
|
||||
}
|
||||
|
||||
public void free() {
|
||||
this.traversal.free();
|
||||
this.requestBuffer.free();
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
package me.cortex.voxy.client.core.rendering.hierachical2;
|
||||
|
||||
import me.cortex.voxy.common.util.HierarchicalBitSet;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
public final class NodeStore {
|
||||
public static final int EMPTY_GEOMETRY_ID = -1;
|
||||
public static final int NODE_ID_MSK = ((1<<24)-1);
|
||||
public static final int REQUEST_ID_MSK = ((1<<16)-1);
|
||||
public static final int GEOMETRY_ID_MSK = (1<<24)-1;
|
||||
public static final int MAX_GEOMETRY_ID = GEOMETRY_ID_MSK-1;
|
||||
public static final int MAX_GEOMETRY_ID = GEOMETRY_ID_MSK-2;
|
||||
public static final int ABSENT_GEOMETRY_ID = GEOMETRY_ID_MSK-1;//Value for if want to clear geometry and make gpu request it if its needed
|
||||
private static final int SENTINEL_EMPTY_GEOMETRY_ID = GEOMETRY_ID_MSK;
|
||||
private static final int SENTINEL_NULL_NODE_ID = NODE_ID_MSK -1;
|
||||
private static final int SENTINEL_REQUEST_ID = REQUEST_ID_MSK -1;
|
||||
@@ -167,8 +169,17 @@ public final class NodeStore {
|
||||
return ((this.localNodeData[id2idx(nodeId)+1]>>63)&1)!=0;
|
||||
}
|
||||
|
||||
public boolean isLeafNode(int nodeId) {
|
||||
return ((this.localNodeData[id2idx(nodeId)+1]>>62)&1)!=0;
|
||||
public int getNodeType(int nodeId) {
|
||||
return (int)((this.localNodeData[id2idx(nodeId)+1]>>61)&3)<<30;
|
||||
}
|
||||
|
||||
public void setNodeType(int nodeId, int type) {
|
||||
type >>>= 30;
|
||||
int idx = id2idx(nodeId)+1;
|
||||
long data = this.localNodeData[idx];
|
||||
data &= ~(3L<<61);
|
||||
data |= ((long)type)<<61;
|
||||
this.localNodeData[idx] = data;
|
||||
}
|
||||
|
||||
public byte getNodeChildExistence(int nodeId) {
|
||||
@@ -184,9 +195,48 @@ public final class NodeStore {
|
||||
this.localNodeData[idx] = data;
|
||||
}
|
||||
|
||||
public int getChildPtrCount(int nodeId) {
|
||||
long data = this.localNodeData[id2idx(nodeId)+1];
|
||||
return (int) ((data>>56)&0x7);
|
||||
}
|
||||
|
||||
public void setChildPtrCount(int nodeId, int count) {
|
||||
if (count <= 0 || count>8) throw new IllegalArgumentException("Count: " + count);
|
||||
int idx = id2idx(nodeId)+1;
|
||||
long data = this.localNodeData[idx];
|
||||
data &= ~(7L<<56);
|
||||
data |= ((long) (count - 1)) <<56;
|
||||
this.localNodeData[idx] = data;
|
||||
}
|
||||
|
||||
//Writes out a nodes data to the ptr in the compacted/reduced format
|
||||
public void writeNode(long ptr, int nodeId) {
|
||||
long pos = this.nodePosition(nodeId);
|
||||
MemoryUtil.memPutInt(ptr, (int) (pos>>32)); ptr += 4;
|
||||
MemoryUtil.memPutInt(ptr, (int) pos); ptr += 4;
|
||||
|
||||
int z = 0;
|
||||
int w = 0;
|
||||
|
||||
short flags = 0;
|
||||
flags |= (short) (this.getChildPtrCount(nodeId)<<2);
|
||||
|
||||
{
|
||||
int geometry = this.getNodeGeometry(nodeId);
|
||||
if (geometry == -1) {
|
||||
z |= 0xFFFFFF-1;//This is a special case, which basically says to the renderer that the geometry is empty (not that it doesnt exist)
|
||||
} else {
|
||||
z |= geometry&0xFFFFFF;//TODO: check and ensure bounds
|
||||
}
|
||||
}
|
||||
|
||||
w |= this.getChildPtr(nodeId)&0xFFFFFF;//TODO: check and ensure bounds
|
||||
|
||||
z |= (flags&0xFF)<<24;
|
||||
w |= ((flags>>8)&0xFF)<<24;
|
||||
|
||||
MemoryUtil.memPutInt(ptr, z); ptr += 4;
|
||||
MemoryUtil.memPutInt(ptr, w); ptr += 4;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -70,6 +70,7 @@ void setupScreenspace(in UnpackedNode node) {
|
||||
|
||||
//Checks if the node is implicitly culled (outside frustum)
|
||||
bool outsideFrustum() {
|
||||
//printf("Cull point (%f %f %f)x(%f %f %f)", maxBB.x, maxBB.y, maxBB.z, minBB.x, minBB.y, minBB.z);
|
||||
return any(lessThanEqual(maxBB, vec3(-1f, -1f, 0f))) || any(lessThanEqual(vec3(1f, 1f, 1f), minBB));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user