diff --git a/src/main/java/me/cortex/voxy/client/core/VoxelCore.java b/src/main/java/me/cortex/voxy/client/core/VoxelCore.java index b3460ad5..9084370c 100644 --- a/src/main/java/me/cortex/voxy/client/core/VoxelCore.java +++ b/src/main/java/me/cortex/voxy/client/core/VoxelCore.java @@ -183,7 +183,7 @@ public class VoxelCore { this.renderer.renderFarAwayOpaque(viewport); //Compute the SSAO of the rendered terrain - this.postProcessing.computeSSAO(projection, matrices); + //this.postProcessing.computeSSAO(projection, matrices); //We can render the translucent directly after as it is the furthest translucent objects this.renderer.renderFarAwayTranslucent(viewport); diff --git a/src/main/java/me/cortex/voxy/client/core/gl/shader/PrintfInjector.java b/src/main/java/me/cortex/voxy/client/core/gl/shader/PrintfInjector.java index 8217841b..ece46b3b 100644 --- a/src/main/java/me/cortex/voxy/client/core/gl/shader/PrintfInjector.java +++ b/src/main/java/me/cortex/voxy/client/core/gl/shader/PrintfInjector.java @@ -23,11 +23,17 @@ public class PrintfInjector implements IShaderProcessor { private final HashMap idToPrintfStringMap = new HashMap<>(); private final int bindingIndex; private final Consumer callback; + private final Runnable preRun; public PrintfInjector(int bufferSize, int bufferBindingIndex, Consumer callback) { + this(bufferSize, bufferBindingIndex, callback, null); + } + + public PrintfInjector(int bufferSize, int bufferBindingIndex, Consumer callback, Runnable pre) { this.textBuffer = new GlBuffer(bufferSize*4L+4); nglClearNamedBufferData(this.textBuffer.id, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT, 0); this.bindingIndex = bufferBindingIndex; this.callback = callback; + this.preRun = pre; } private static int findNextCall(String src, int after) { @@ -183,6 +189,13 @@ public class PrintfInjector implements IShaderProcessor { private void processResult(long ptr, long size) { int total = MemoryUtil.memGetInt(ptr); ptr += 4; + if (total == 0) { + return; + } + if (this.preRun != null) { + this.preRun.run(); + } + int cnt = 0; List types = new ArrayList<>(); while (cnt < total) { diff --git a/src/main/java/me/cortex/voxy/client/core/rendering/Gl46HierarchicalRenderer.java b/src/main/java/me/cortex/voxy/client/core/rendering/Gl46HierarchicalRenderer.java index 79c9d31a..661e77e7 100644 --- a/src/main/java/me/cortex/voxy/client/core/rendering/Gl46HierarchicalRenderer.java +++ b/src/main/java/me/cortex/voxy/client/core/rendering/Gl46HierarchicalRenderer.java @@ -9,6 +9,7 @@ import me.cortex.voxy.client.core.model.ModelManager; import me.cortex.voxy.client.core.rendering.building.BuiltSection; import me.cortex.voxy.client.core.rendering.building.RenderDataFactory; import me.cortex.voxy.client.core.rendering.building.RenderGenerationService; +import me.cortex.voxy.client.core.rendering.hierarchical.DebugRenderer; import me.cortex.voxy.client.core.rendering.hierarchical.HierarchicalOcclusionRenderer; import me.cortex.voxy.client.core.rendering.hierarchical.INodeInteractor; import me.cortex.voxy.client.core.rendering.hierarchical.MeshManager; @@ -56,11 +57,17 @@ public class Gl46HierarchicalRenderer implements IRenderInterface printfQueue = new ArrayList<>(); - private final PrintfInjector printf = new PrintfInjector(100000, 10, this.printfQueue::add); + private final PrintfInjector printf = new PrintfInjector(100000, 10, line->{ + if (line.startsWith("LOG")) { + System.err.println(line); + } + this.printfQueue.add(line); + }, this.printfQueue::clear); private final GlBuffer renderSections = new GlBuffer(100_000 * 4 + 4).zero(); + private final DebugRenderer debugRenderer = new DebugRenderer(); private final ConcurrentLinkedDeque blockStateUpdates = new ConcurrentLinkedDeque<>(); private final ConcurrentLinkedDeque biomeUpdates = new ConcurrentLinkedDeque<>(); @@ -150,6 +157,8 @@ public class Gl46HierarchicalRenderer implements IRenderInterface debug) { debug.add("Printf Queue: "); debug.addAll(this.printfQueue); - for (String a : this.printfQueue) { - if (a.startsWith("LOG")) { - System.err.println(a); - } - } - this.printfQueue.clear(); } @@ -244,5 +247,6 @@ public class Gl46HierarchicalRenderer implements IRenderInterface>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; + } + + public void render(Gl46HierarchicalViewport viewport, GlBuffer nodeData, GlBuffer nodeList) { + this.uploadUniform(viewport); + UploadStream.INSTANCE.commit(); + + this.setupShader.bind(); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, this.drawBuffer.id); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, nodeList.id); + glDispatchCompute(1,1,1); + glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT|GL_COMMAND_BARRIER_BIT); + + glEnable(GL_DEPTH_TEST); + this.debugShader.bind(); + glBindVertexArray(AbstractFarWorldRenderer.STATIC_VAO); + glBindBuffer(GL_DRAW_INDIRECT_BUFFER, this.drawBuffer.id); + GL15.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, SharedIndexBuffer.INSTANCE_BYTE.id()); + glBindBufferBase(GL_UNIFORM_BUFFER, 0, this.uniformBuffer.id); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, nodeData.id); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, nodeList.id); + glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_BYTE, 0); + } + + public void free() { + this.drawBuffer.free(); + this.uniformBuffer.free(); + this.debugShader.free(); + this.setupShader.free(); + } +} diff --git a/src/main/java/me/cortex/voxy/client/core/rendering/hierarchical/HierarchicalOcclusionRenderer.java b/src/main/java/me/cortex/voxy/client/core/rendering/hierarchical/HierarchicalOcclusionRenderer.java index 9fc93fa5..6e4376eb 100644 --- a/src/main/java/me/cortex/voxy/client/core/rendering/hierarchical/HierarchicalOcclusionRenderer.java +++ b/src/main/java/me/cortex/voxy/client/core/rendering/hierarchical/HierarchicalOcclusionRenderer.java @@ -89,6 +89,9 @@ public class HierarchicalOcclusionRenderer { glMemoryBarrier(GL_PIXEL_BUFFER_BARRIER_BIT); this.hierarchicalTraversal.bind(); + //Clear the render counter + nglClearNamedBufferSubData(renderSelectionResult.id, GL_R32UI, 0, 4, GL_RED_INTEGER, GL_UNSIGNED_INT, 0); + { glBindBufferBase(GL_UNIFORM_BUFFER, 0, this.uniformBuffer.id); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, this.nodeManager.nodeBuffer.id); @@ -119,19 +122,19 @@ public class HierarchicalOcclusionRenderer { nglClearNamedBufferSubData(this.nodeQueueB.id, GL_R32UI, 0, 4, GL_RED_INTEGER, GL_UNSIGNED_INT, 0); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, this.nodeQueueA.id); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, this.nodeQueueB.id); - glDispatchCompute(16,1,1); + glDispatchCompute(8*8,1,1); glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); nglClearNamedBufferSubData(this.nodeQueueA.id, GL_R32UI, 0, 4, GL_RED_INTEGER, GL_UNSIGNED_INT, 0); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, this.nodeQueueB.id); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, this.nodeQueueA.id); - glDispatchCompute(32,1,1); + glDispatchCompute(8*8*8,1,1); glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); nglClearNamedBufferSubData(this.nodeQueueB.id, GL_R32UI, 0, 4, GL_RED_INTEGER, GL_UNSIGNED_INT, 0); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, this.nodeQueueA.id); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, this.nodeQueueB.id); - glDispatchCompute(64,1,1); + glDispatchCompute(8*8*8*8,1,1); glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); } @@ -147,4 +150,8 @@ public class HierarchicalOcclusionRenderer { this.nodeManager.free(); glDeleteSamplers(this.hizSampler); } + + public GlBuffer getNodeDataBuffer() { + return this.nodeManager.nodeBuffer; + } } diff --git a/src/main/java/me/cortex/voxy/client/core/rendering/hierarchical/NodeManager.java b/src/main/java/me/cortex/voxy/client/core/rendering/hierarchical/NodeManager.java index 84b063c4..d32b615c 100644 --- a/src/main/java/me/cortex/voxy/client/core/rendering/hierarchical/NodeManager.java +++ b/src/main/java/me/cortex/voxy/client/core/rendering/hierarchical/NodeManager.java @@ -221,6 +221,12 @@ public class NodeManager { // the request queue only needs to supply the node id, since if its an inner node, it must be requesting for a mesh, while if its a leaf node, it must be requesting for children private void processRequestQueue(long ptr, long size) { int count = MemoryUtil.memGetInt(ptr); ptr += 4; + if (count > REQUEST_QUEUE_SIZE*1.5) { + System.err.println("CORRUPTED PROCESS REQUEST, IGNORING (had count of: "+count+")"); + return; + } + + for (int i = 0; i < count; i++) { int requestOp = MemoryUtil.memGetInt(ptr + i*4L); int node = requestOp&NODE_MSK; @@ -414,7 +420,8 @@ public class NodeManager { this.pushNode(id);//request it to be uploaded } else { - //The section was empty, so just remove/skip it + //The section was empty, so just remove/skip it, but remove it from the map + this.pos2meshId.remove(request.childPositions[i]); } } if (cnt == 0) { @@ -443,7 +450,9 @@ public class NodeManager { flags |= this.isEmptyNode(id)?2:0; flags |= Math.max(0, this.getNodeChildCnt(id)-1)<<2; - int a = this.getNodeMesh(id)|((flags&0xFF)<<24); + //TODO: PUT BACK PUT BACK PUT BACK PUT BACK PUT BACK PUT BACK PUT BACK PUT BACK PUT BACK PUT BACK PUT BACK PUT BACK PUT BACK PUT BACK PUT BACK PUT BACK PUT BACK PUT BACK PUT BACK PUT BACK PUT BACK PUT BACK PUT BACK PUT BACK PUT BACK PUT BACK PUT BACK PUT BACK + //int a = this.getNodeMesh(id)|((flags&0xFF)<<24); + int a = id|((flags&0xFF)<<24); int b = this.getNodeChildPtr(id)|(((flags>>8)&0xFF)<<24); System.out.println("Setting mesh " + this.getNodeMesh(id) + " for node " + id); MemoryUtil.memPutInt(dst, a); dst += 4; @@ -468,7 +477,6 @@ public class NodeManager { DownloadStream.INSTANCE.download(this.requestQueue, this::processRequestQueue); DownloadStream.INSTANCE.commit(); nglClearNamedBufferSubData(this.requestQueue.id, GL_R32UI, 0, 4, GL_RED_INTEGER, GL_UNSIGNED_INT, 0); - } diff --git a/src/main/resources/assets/voxy/shaders/lod/hierarchical/debug/frag.frag b/src/main/resources/assets/voxy/shaders/lod/hierarchical/debug/frag.frag new file mode 100644 index 00000000..71846303 --- /dev/null +++ b/src/main/resources/assets/voxy/shaders/lod/hierarchical/debug/frag.frag @@ -0,0 +1,7 @@ +#version 450 + +layout(location = 1) in flat vec4 colour; +layout(location = 0) out vec4 outColour; +void main() { + outColour = colour; +} \ No newline at end of file diff --git a/src/main/resources/assets/voxy/shaders/lod/hierarchical/debug/node_outline.vert b/src/main/resources/assets/voxy/shaders/lod/hierarchical/debug/node_outline.vert new file mode 100644 index 00000000..bd27fb72 --- /dev/null +++ b/src/main/resources/assets/voxy/shaders/lod/hierarchical/debug/node_outline.vert @@ -0,0 +1,38 @@ +#version 450 +#extension GL_ARB_shader_draw_parameters : require + +layout(binding = 0, std140) uniform SceneUniform { + mat4 VP; + ivec3 camSecPos; + uint screenW; + vec3 camSubSecPos; + uint screenH; +}; + +#define NODE_DATA_INDEX 1 +#import + +layout(binding = 2, std430) restrict buffer NodeList { + uint count; + uint nodeQueue[]; +}; + +layout(location = 1) out flat vec4 colour; + +void main() { + UnpackedNode node; + unpackNode(node, nodeQueue[gl_InstanceID]); + + vec4 base = VP*vec4(vec3(((node.pos<>2)&1, (gl_VertexID>>1)&1)<<(5+node.lodLevel), 1)); + + gl_Position = pos; + + uint hash = node.nodeId*1231421+123141; + hash ^= hash>>16; + hash = hash*1231421+123141; + hash ^= hash>>16; + hash = hash * 1827364925 + 123325621; + colour = vec4(float(hash&15u)/15, float((hash>>4)&15u)/15, float((hash>>8)&15u)/15, 1); +} \ No newline at end of file diff --git a/src/main/resources/assets/voxy/shaders/lod/hierarchical/debug/setup.comp b/src/main/resources/assets/voxy/shaders/lod/hierarchical/debug/setup.comp new file mode 100644 index 00000000..7bbeff8b --- /dev/null +++ b/src/main/resources/assets/voxy/shaders/lod/hierarchical/debug/setup.comp @@ -0,0 +1,24 @@ +#version 460 core +layout(local_size_x=1, local_size_y=1) in; + + +layout(binding = 0, std430) restrict buffer DrawCmd { + uint count; + uint instanceCount; + uint firstIndex; + int baseVertex; + uint baseInstance; +}; + +layout(binding = 1, std430) restrict buffer NodeList { + uint nodeCount; + uint nodes[]; +}; + +void main() { + count = 6 * 2 * 3; + instanceCount = nodeCount; + firstIndex = (1<<8)*6; + baseVertex = 0; + baseInstance = 0; +} \ No newline at end of file diff --git a/src/main/resources/assets/voxy/shaders/lod/hierarchical/node.glsl b/src/main/resources/assets/voxy/shaders/lod/hierarchical/node.glsl index e4eb2647..4eab6acb 100644 --- a/src/main/resources/assets/voxy/shaders/lod/hierarchical/node.glsl +++ b/src/main/resources/assets/voxy/shaders/lod/hierarchical/node.glsl @@ -92,5 +92,5 @@ void markRequested(inout UnpackedNode node) { } void debugDumpNode(in UnpackedNode node) { - printf("Node %d, %d@[%d,%d,%d], flags: %d, mesh: %d, ChildPtr: %d", node.nodeId, node.lodLevel, node.pos.x, node.pos.y, node.pos.z, node.flags, node.meshPtr, node.childPtr); + //printf("Node %d, %d@[%d,%d,%d], flags: %d, mesh: %d, ChildPtr: %d", node.nodeId, node.lodLevel, node.pos.x, node.pos.y, node.pos.z, node.flags, node.meshPtr, node.childPtr); } \ No newline at end of file