Prepare
This commit is contained in:
@@ -73,7 +73,6 @@ public class RenderService<T extends AbstractSectionRenderer<J, ?>, J extends Vi
|
||||
world.getMapper().setBiomeCallback(this.modelService::addBiome);
|
||||
|
||||
|
||||
/*
|
||||
final int H_WIDTH = 1;
|
||||
for (int x = -H_WIDTH; x <= H_WIDTH; x++) {
|
||||
for (int y = -1; y <= 0; y++) {
|
||||
@@ -81,8 +80,7 @@ public class RenderService<T extends AbstractSectionRenderer<J, ?>, J extends Vi
|
||||
this.nodeManager.insertTopLevelNode(WorldEngine.getWorldSectionId(4, x, y, z));
|
||||
}
|
||||
}
|
||||
}*/
|
||||
router.watch(WorldEngine.getWorldSectionId(4, 0,0,0), 3);
|
||||
}
|
||||
}
|
||||
|
||||
public void setup(Camera camera) {
|
||||
|
||||
@@ -65,9 +65,9 @@ public class HierarchicalNodeManager {
|
||||
|
||||
private static final int ID_TYPE_MSK = (3<<30);
|
||||
private static final int ID_TYPE_LEAF = (3<<30);
|
||||
private static final int ID_TYPE_NONE = 0;
|
||||
private static final int ID_TYPE_INNER = 0;
|
||||
private static final int ID_TYPE_REQUEST = (2<<30);
|
||||
private static final int ID_TYPE_TOP = (1<<30);
|
||||
//private static final int ID_TYPE_TOP = (1<<30);
|
||||
|
||||
public final int maxNodeCount;
|
||||
private final IntOpenHashSet nodeUpdates = new IntOpenHashSet();
|
||||
@@ -102,7 +102,7 @@ public class HierarchicalNodeManager {
|
||||
|
||||
int id = this.nodeData.allocate();
|
||||
this.nodeData.setNodePosition(id, position);
|
||||
this.activeSectionMap.put(position, id|ID_TYPE_TOP);
|
||||
this.activeSectionMap.put(position, id|ID_TYPE_LEAF);//ID_TYPE_TOP
|
||||
this.updateRouter.watch(position, WorldEngine.UPDATE_FLAGS);
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@ public class HierarchicalNodeManager {
|
||||
if (type == ID_TYPE_REQUEST) {
|
||||
//TODO: THIS
|
||||
|
||||
} else if (type == ID_TYPE_NONE || type == ID_TYPE_TOP) {
|
||||
} else if (type == ID_TYPE_INNER) {// || type == ID_TYPE_TOP
|
||||
if (!this.nodeData.nodeExists(node)) {
|
||||
throw new IllegalStateException("Section in active map but not in node data");
|
||||
}
|
||||
@@ -235,14 +235,24 @@ public class HierarchicalNodeManager {
|
||||
if (type == ID_TYPE_REQUEST) {
|
||||
//Doesnt result in an invalidation as we must wait for geometry to create a child
|
||||
this.requests.get(nodeId).putChildResult(getChildIdx(position), childExistence);
|
||||
} else if (type == ID_TYPE_LEAF || type == ID_TYPE_NONE || type == ID_TYPE_TOP) {
|
||||
} else if (type == ID_TYPE_LEAF || type == ID_TYPE_INNER) {// || type == ID_TYPE_TOP
|
||||
if (this.nodeData.getNodeChildExistence(nodeId) == childExistence) {
|
||||
//Dont need to update the internal state since it is the same
|
||||
return;
|
||||
}
|
||||
|
||||
//ALSO: TODO: HERE: if a child is removed, need to remove it and all children accociated
|
||||
|
||||
//If its an inner node and doesnt have an inflight request, create an empty request, this will get autofilled by the following part
|
||||
if (type == ID_TYPE_NONE) {
|
||||
if (type == ID_TYPE_INNER) {
|
||||
|
||||
}
|
||||
//If its a top level node, it needs a request? aswell
|
||||
//If its a top level node, it needs a request? aswell, no no it doesnt :tm: what could do tho, is if it has a request in progress, update it (already handled)
|
||||
// _or_ if the top level node has a child ptr then also handle it??
|
||||
// the issue is that top nodes probably need an extra state like "shouldMakeChildren" or something
|
||||
// cause if a top level node, that has no children, requests a decent from the gpu
|
||||
// but there are no children so no decent is made, if a child update is added to that section,
|
||||
// the update will be ignored since the cpu doesnt know the gpu still wants it
|
||||
|
||||
//If its a leaf node, its fine, dont need to create a request, only need to update the node msk
|
||||
|
||||
@@ -336,7 +346,7 @@ public class HierarchicalNodeManager {
|
||||
if (request.isSatisfied()) {
|
||||
this.consumeFinishedNodeChildRequest(nodeId, request);
|
||||
}
|
||||
} else if (type == ID_TYPE_NONE || type == ID_TYPE_TOP || type == ID_TYPE_LEAF) {
|
||||
} else if (type == ID_TYPE_INNER || type == ID_TYPE_LEAF) {//type == ID_TYPE_TOP ||
|
||||
//Update the node geometry, and enqueue if it changed
|
||||
if (this.updateNodeGeometry(nodeId, section) != 0) {//TODO: might need to mark the node as empty geometry or something
|
||||
this.nodeUpdates.add(nodeId);
|
||||
|
||||
@@ -5,10 +5,14 @@ import me.cortex.voxy.client.core.gl.GlBuffer;
|
||||
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.hierarchical.NodeManager;
|
||||
import me.cortex.voxy.client.core.rendering.util.HiZBuffer;
|
||||
import me.cortex.voxy.client.core.rendering.Viewport;
|
||||
import me.cortex.voxy.client.core.rendering.util.DownloadStream;
|
||||
import me.cortex.voxy.client.core.rendering.util.UploadStream;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Vector3f;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import static me.cortex.voxy.client.core.rendering.PrintfDebugUtil.PRINTF_object;
|
||||
@@ -39,18 +43,31 @@ public class HierarchicalOcclusionTraverser {
|
||||
private static final int LOCAL_WORK_SIZE_BITS = 5;
|
||||
private static final int MAX_ITERATIONS = 5;
|
||||
|
||||
private static final int NODE_QUEUE_INDEX_BINDING = 1;
|
||||
private static final int NODE_QUEUE_META_BINDING = 2;
|
||||
private static final int NODE_QUEUE_SOURCE_BINDING = 3;
|
||||
private static final int NODE_QUEUE_SINK_BINDING = 4;
|
||||
private static int BINDING_COUNTER = 1;
|
||||
private static final int SCENE_UNIFORM_BINDING = BINDING_COUNTER++;
|
||||
private static final int REQUEST_QUEUE_BINDING = BINDING_COUNTER++;
|
||||
private static final int RENDER_QUEUE_BINDING = BINDING_COUNTER++;
|
||||
private static final int NODE_DATA_BINDING = BINDING_COUNTER++;
|
||||
private static final int NODE_QUEUE_INDEX_BINDING = BINDING_COUNTER++;
|
||||
private static final int NODE_QUEUE_META_BINDING = BINDING_COUNTER++;
|
||||
private static final int NODE_QUEUE_SOURCE_BINDING = BINDING_COUNTER++;
|
||||
private static final int NODE_QUEUE_SINK_BINDING = BINDING_COUNTER++;
|
||||
|
||||
private final HiZBuffer hiZBuffer = new HiZBuffer();
|
||||
private final int hizSampler = glGenSamplers();
|
||||
|
||||
private final Shader traversal = Shader.make(PRINTF_object)
|
||||
.defineIf("DEBUG", Voxy.SHADER_DEBUG)
|
||||
.define("MAX_ITERATIONS", MAX_ITERATIONS)
|
||||
.define("LOCAL_SIZE_BITS", LOCAL_WORK_SIZE_BITS)
|
||||
|
||||
.define("HIZ_BINDING", 0)
|
||||
|
||||
.define("SCENE_UNIFORM_BINDING", SCENE_UNIFORM_BINDING)
|
||||
.define("REQUEST_QUEUE_BINDING", REQUEST_QUEUE_BINDING)
|
||||
.define("RENDER_QUEUE_BINDING", RENDER_QUEUE_BINDING)
|
||||
.define("NODE_DATA_BINDING", NODE_DATA_BINDING)
|
||||
|
||||
.define("NODE_QUEUE_INDEX_BINDING", NODE_QUEUE_INDEX_BINDING)
|
||||
.define("NODE_QUEUE_META_BINDING", NODE_QUEUE_META_BINDING)
|
||||
.define("NODE_QUEUE_SOURCE_BINDING", NODE_QUEUE_SOURCE_BINDING)
|
||||
@@ -65,15 +82,52 @@ public class HierarchicalOcclusionTraverser {
|
||||
this.requestBuffer = new GlBuffer(requestBufferCount*4L+1024).zero();//The 1024 is to assist with race condition issues
|
||||
this.nodeBuffer = new GlBuffer(nodeManager.maxNodeCount*16L).zero();
|
||||
this.maxRequestCount = requestBufferCount;
|
||||
|
||||
|
||||
glSamplerParameteri(this.hizSampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
||||
glSamplerParameteri(this.hizSampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glSamplerParameteri(this.hizSampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glSamplerParameteri(this.hizSampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glSamplerParameteri(this.hizSampler, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
|
||||
glSamplerParameteri(this.hizSampler, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
|
||||
}
|
||||
|
||||
private void uploadUniform(Viewport<?> viewport) {
|
||||
long ptr = UploadStream.INSTANCE.upload(this.uniformBuffer, 0, 1024);
|
||||
int sx = MathHelper.floor(viewport.cameraX)>>5;
|
||||
int sy = MathHelper.floor(viewport.cameraY)>>5;
|
||||
int sz = MathHelper.floor(viewport.cameraZ)>>5;
|
||||
|
||||
new Matrix4f(viewport.projection).mul(viewport.modelView).getToAddress(ptr); ptr += 4*4*4;
|
||||
|
||||
MemoryUtil.memPutInt(ptr, sx); ptr += 4;
|
||||
MemoryUtil.memPutInt(ptr, sy); ptr += 4;
|
||||
MemoryUtil.memPutInt(ptr, sz); ptr += 4;
|
||||
MemoryUtil.memPutInt(ptr, viewport.width); ptr += 4;
|
||||
|
||||
var innerTranslation = new Vector3f((float) (viewport.cameraX-(sx<<5)), (float) (viewport.cameraY-(sy<<5)), (float) (viewport.cameraZ-(sz<<5)));
|
||||
innerTranslation.getToAddress(ptr); ptr += 4*3;
|
||||
|
||||
MemoryUtil.memPutInt(ptr, viewport.height); ptr += 4;
|
||||
|
||||
MemoryUtil.memPutInt(ptr, NodeManager.REQUEST_QUEUE_SIZE); ptr += 4;
|
||||
MemoryUtil.memPutInt(ptr, 1000000); ptr += 4;
|
||||
|
||||
//Screen space size for descending
|
||||
MemoryUtil.memPutFloat(ptr, 64*64); ptr += 4;
|
||||
}
|
||||
|
||||
private void bindings() {
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, SCENE_UNIFORM_BINDING, this.uniformBuffer.id);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, REQUEST_QUEUE_BINDING, this.requestBuffer.id);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, RENDER_QUEUE_BINDING, this.renderList.id);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, NODE_DATA_BINDING, this.nodeBuffer.id);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, NODE_QUEUE_META_BINDING, this.queueMetaBuffer.id);
|
||||
glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, this.queueMetaBuffer.id);
|
||||
|
||||
//Bind the hiz buffer
|
||||
glBindSampler(0, this.hizSampler);
|
||||
glBindTextureUnit(0, this.hiZBuffer.getHizTextureId());
|
||||
}
|
||||
|
||||
public void doTraversal(Viewport<?> viewport, int depthBuffer) {
|
||||
@@ -190,5 +244,6 @@ public class HierarchicalOcclusionTraverser {
|
||||
this.queueMetaBuffer.free();
|
||||
this.scratchQueueA.free();
|
||||
this.scratchQueueB.free();
|
||||
glDeleteSamplers(this.hizSampler);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ public final class NodeStore {
|
||||
private void clear(int nodeId) {
|
||||
int idx = id2idx(nodeId);
|
||||
this.localNodeData[idx] = -1;//Position
|
||||
this.localNodeData[idx+1] = 0;
|
||||
this.localNodeData[idx+1] = GEOMETRY_ID_MSK|(((long)NODE_ID_MSK)<<24);
|
||||
this.localNodeData[idx+2] = 0;
|
||||
this.localNodeData[idx+3] = 0;
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ public class BasicSectionGeometryManager extends AbstractSectionGeometryManager
|
||||
@Override
|
||||
public void removeSection(int id) {
|
||||
if (!this.allocationSet.free(id)) {
|
||||
throw new IllegalStateException("Id was not already allocated");
|
||||
throw new IllegalStateException("Id was not already allocated. id: " + id);
|
||||
}
|
||||
var oldMetadata = this.sectionMetadata.set(id, null);
|
||||
this.geometry.free(oldMetadata.geometryPtr);
|
||||
|
||||
@@ -43,4 +43,8 @@ public class MemoryBuffer extends TrackedObject {
|
||||
|
||||
return new MemoryBuffer(this.address, size);
|
||||
}
|
||||
|
||||
|
||||
//TODO: create like Long(offset) -> value at offset
|
||||
// methods for get and set, that way can have a single unifed system to ensure memory access bounds
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
layout(binding = NODE_DATA_INDEX, std430) restrict buffer NodeData {
|
||||
layout(binding = NODE_DATA_BINDING, std430) restrict buffer NodeData {
|
||||
//Needs to be read and writeable for marking data,
|
||||
//(could do an evil violation, make this readonly, then have a writeonly varient, which means that writing might not be visible but will show up by the next frame)
|
||||
//Nodes are 16 bytes big (or 32 cant decide, 16 might _just_ be enough)
|
||||
@@ -84,9 +84,10 @@ uint getChildPtr(in UnpackedNode node) {
|
||||
return node.childPtr;
|
||||
}
|
||||
|
||||
/*
|
||||
uint getTransformIndex(in UnpackedNode node) {
|
||||
return (node.flags >> 5)&31u;
|
||||
}
|
||||
}*/
|
||||
|
||||
//-----------------------------------
|
||||
|
||||
|
||||
@@ -48,3 +48,10 @@ void pushNode(uint nodeId) {
|
||||
#endif
|
||||
nodeQueueSink[nodePushIndex++] = nodeId;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define SIMPLE_QUEUE(name, binding) layout(binding = binding, std430) restrict buffer name##Struct { \
|
||||
uint name##Index; \
|
||||
uint[] name; \
|
||||
};
|
||||
@@ -12,7 +12,7 @@
|
||||
// substantually for performance (for both persistent threads and incremental)
|
||||
|
||||
|
||||
layout(binding = HIZ_BINDING_INDEX) uniform sampler2DShadow hizDepthSampler;
|
||||
layout(binding = HIZ_BINDING) uniform sampler2DShadow hizDepthSampler;
|
||||
|
||||
//TODO: maybe do spher bounds aswell? cause they have different accuracies but are both over estimates (liberals (non conservative xD))
|
||||
// so can do &&
|
||||
@@ -27,9 +27,10 @@ vec2 size;
|
||||
void setupScreenspace(in UnpackedNode node) {
|
||||
//TODO: Need to do aabb size for the nodes, it must be an overesimate of all the children
|
||||
|
||||
Transform transform = transforms[getTransformIndex(node)];
|
||||
|
||||
/*
|
||||
Transform transform = transforms[getTransformIndex(node)];
|
||||
|
||||
vec3 point = VP*(((transform.transform*vec4((node.pos<<node.lodLevel) - transform.originPos.xyz, 1))
|
||||
+ (transform.worldPos.xyz-camChunkPos))-camSubChunk);
|
||||
*/
|
||||
|
||||
@@ -4,11 +4,29 @@
|
||||
#define LOCAL_SIZE_MSK ((1<<LOCAL_SIZE_BITS)-1)
|
||||
#define LOCAL_SIZE (1<<LOCAL_SIZE_BITS)
|
||||
layout(local_size_x=LOCAL_SIZE) in;//, local_size_y=1
|
||||
|
||||
#import <voxy:lod/hierarchical/queue.glsl>
|
||||
#import <voxy:lod/hierarchical/node.glsl>
|
||||
#import <voxy:lod/hierarchical/screenspace.glsl>
|
||||
|
||||
SIMPLE_QUEUE(requestQueue, REQUEST_QUEUE_BINDING);
|
||||
SIMPLE_QUEUE(renderQueue, RENDER_QUEUE_BINDING);
|
||||
|
||||
/*
|
||||
layout(binding = REQUEST_QUEUE_INDEX, std430) restrict buffer RequestQueue {
|
||||
uint requestQueueIndex;
|
||||
uint[] requestQueue;
|
||||
};
|
||||
|
||||
layout(binding = RENDER_QUEUE_INDEX, std430) restrict buffer RenderQueue {
|
||||
uint renderQueueIndex;
|
||||
uint[] renderQueue;
|
||||
};*/
|
||||
|
||||
|
||||
void main() {
|
||||
uint node = getCurrentNode();
|
||||
if (node != SENTINAL_OUT_OF_BOUNDS && queueIdx != 4) {
|
||||
if (node != SENTINAL_OUT_OF_BOUNDS) {
|
||||
printf("GID:%d, NODE %d, %d, AA, %d, %d, %d, %d", gl_GlobalInvocationID.x, node, queueIdx, nodeQueueMetadata[queueIdx].x, nodeQueueMetadata[queueIdx].y, nodeQueueMetadata[queueIdx].z, nodeQueueMetadata[queueIdx].w);
|
||||
pushNodesInit(1);
|
||||
pushNode(node);
|
||||
|
||||
Reference in New Issue
Block a user