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 de65679b..998b111d 100644 --- a/src/main/java/me/cortex/voxy/client/core/VoxelCore.java +++ b/src/main/java/me/cortex/voxy/client/core/VoxelCore.java @@ -239,17 +239,20 @@ public class VoxelCore { this.importerBossBarUUID = MathHelper.randomUuid(); var bossBar = new ClientBossBar(this.importerBossBarUUID, Text.of("Voxy world importer"), 0.0f, BossBar.Color.GREEN, BossBar.Style.PROGRESS, false, false, false); MinecraftClient.getInstance().inGameHud.getBossBarHud().bossBars.put(bossBar.getUuid(), bossBar); + long start = System.currentTimeMillis(); this.importer.importWorldAsyncStart(worldPath, (a,b)-> MinecraftClient.getInstance().executeSync(()-> { Taskbar.INSTANCE.setProgress(a, b); bossBar.setPercent(((float) a)/((float) b)); bossBar.setName(Text.of("Voxy import: "+ a+"/"+b + " chunks")); }), - ()-> { + chunkCount -> { MinecraftClient.getInstance().executeSync(()-> { MinecraftClient.getInstance().inGameHud.getBossBarHud().bossBars.remove(this.importerBossBarUUID); this.importerBossBarUUID = null; - String msg = "Voxy world import finished"; + long delta = System.currentTimeMillis() - start; + + String msg = "Voxy world import finished in " + (delta/1000) + " seconds, averaging " + (chunkCount/(delta/1000)) + " chunks per second"; MinecraftClient.getInstance().inGameHud.getChatHud().addMessage(Text.literal(msg)); Logger.info(msg); Taskbar.INSTANCE.setIsNone(); diff --git a/src/main/java/me/cortex/voxy/client/core/rendering/RenderService.java b/src/main/java/me/cortex/voxy/client/core/rendering/RenderService.java index 027656b5..944d7ee6 100644 --- a/src/main/java/me/cortex/voxy/client/core/rendering/RenderService.java +++ b/src/main/java/me/cortex/voxy/client/core/rendering/RenderService.java @@ -92,12 +92,13 @@ public class RenderService, J extends Vi } } }*/ + if (true) { if (true) { if (true) { return; } - final int H_WIDTH = 50; + final int H_WIDTH = 10;//50; for (int x = -H_WIDTH; x <= H_WIDTH; x++) { for (int z = -H_WIDTH; z <= H_WIDTH; z++) { for (int y = -1; y <= 0; y++) { @@ -142,12 +143,15 @@ public class RenderService, J extends Vi //this.nodeManager.insertTopLevelNode(WorldEngine.getWorldSectionId(4, 0,0,0)); + } - private int q = -128; + private int q = -60; public void setup(Camera camera) { - for (int i = 0; i<32 && q<(151*151*2)&&q++>=0;i++) { - this.nodeManager.insertTopLevelNode(WorldEngine.getWorldSectionId(4, (q%151)-75, ((q/151)/151)-1, ((q/151)%151)-75)); + final int W = 80; + final int H = 2; + for (int i = 0; i<32 && q<((W*2+1)*(W*2+1)*H)&&q++>=0;i++) { + this.nodeManager.insertTopLevelNode(WorldEngine.getWorldSectionId(4, (q%(W*2+1))-W, ((q/(W*2+1))/(W*2+1))-1, ((q/(W*2+1))%(W*2+1)))-W); } this.modelService.tick(); } diff --git a/src/main/java/me/cortex/voxy/client/core/rendering/hierachical/HierarchicalOcclusionTraverser.java b/src/main/java/me/cortex/voxy/client/core/rendering/hierachical/HierarchicalOcclusionTraverser.java index 0038e64e..b398d0fc 100644 --- a/src/main/java/me/cortex/voxy/client/core/rendering/hierachical/HierarchicalOcclusionTraverser.java +++ b/src/main/java/me/cortex/voxy/client/core/rendering/hierachical/HierarchicalOcclusionTraverser.java @@ -39,6 +39,11 @@ public class HierarchicalOcclusionTraverser { private final GlBuffer uniformBuffer = new GlBuffer(1024).zero(); private final GlBuffer renderList = new GlBuffer(100_000 * 4 + 4).zero();//100k sections max to render, TODO: Maybe move to render service or somewhere else + + + private final GlBuffer renderTrackingBuffer; + + private final GlBuffer queueMetaBuffer = new GlBuffer(4*4*5).zero(); private final GlBuffer scratchQueueA = new GlBuffer(100_000*4).zero(); private final GlBuffer scratchQueueB = new GlBuffer(100_000*4).zero(); @@ -55,6 +60,7 @@ public class HierarchicalOcclusionTraverser { 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 static final int RENDER_TRACKER_BINDING = BINDING_COUNTER++; private final HiZBuffer hiZBuffer = new HiZBuffer(); private final int hizSampler = glGenSamplers(); @@ -77,6 +83,8 @@ public class HierarchicalOcclusionTraverser { .define("NODE_QUEUE_SOURCE_BINDING", NODE_QUEUE_SOURCE_BINDING) .define("NODE_QUEUE_SINK_BINDING", NODE_QUEUE_SINK_BINDING) + .define("RENDER_TRACKER_BINDING", RENDER_TRACKER_BINDING) + .add(ShaderType.COMPUTE, "voxy:lod/hierarchical/traversal_dev.comp") .compile(); @@ -87,6 +95,8 @@ public class HierarchicalOcclusionTraverser { this.requestBuffer = new GlBuffer(REQUEST_QUEUE_SIZE*8L+8).zero(); this.nodeBuffer = new GlBuffer(nodeManager.maxNodeCount*16L).zero(); + this.renderTrackingBuffer = new GlBuffer(nodeManager.maxNodeCount*4L).zero(); + glSamplerParameteri(this.hizSampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); glSamplerParameteri(this.hizSampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -118,6 +128,14 @@ public class HierarchicalOcclusionTraverser { MemoryUtil.memPutInt(ptr, (int) (this.renderList.size()/4-1)); ptr += 4; + final float screenspaceAreaDecreasingSize = VoxyConfig.CONFIG.subDivisionSize*VoxyConfig.CONFIG.subDivisionSize; + //Screen space size for descending + MemoryUtil.memPutFloat(ptr, (float) (screenspaceAreaDecreasingSize) /(viewport.width*viewport.height)); ptr += 4; + + + //FrameId for timing info + MemoryUtil.memPutInt(ptr, viewport.frameId); ptr += 4; + /* //Very funny and cool thing that is possible if (MinecraftClient.getInstance().getCurrentFps() < 30) { @@ -127,10 +145,6 @@ public class HierarchicalOcclusionTraverser { if (60 < MinecraftClient.getInstance().getCurrentFps()) { VoxyConfig.CONFIG.subDivisionSize = Math.max(VoxyConfig.CONFIG.subDivisionSize - 1, 32); }*/ - - final float screenspaceAreaDecreasingSize = VoxyConfig.CONFIG.subDivisionSize*VoxyConfig.CONFIG.subDivisionSize; - //Screen space size for descending - MemoryUtil.memPutFloat(ptr, (float) (screenspaceAreaDecreasingSize) /(viewport.width*viewport.height)); ptr += 4; } private void bindings() { @@ -139,6 +153,7 @@ public class HierarchicalOcclusionTraverser { 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); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, RENDER_TRACKER_BINDING, this.renderTrackingBuffer.id); glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, this.queueMetaBuffer.id); //Bind the hiz buffer @@ -292,6 +307,7 @@ public class HierarchicalOcclusionTraverser { this.queueMetaBuffer.free(); this.scratchQueueA.free(); this.scratchQueueB.free(); + this.renderTrackingBuffer.free(); glDeleteSamplers(this.hizSampler); } } diff --git a/src/main/java/me/cortex/voxy/client/core/rendering/hierachical/NodeManager.java b/src/main/java/me/cortex/voxy/client/core/rendering/hierachical/NodeManager.java index dcd66f33..774ba24c 100644 --- a/src/main/java/me/cortex/voxy/client/core/rendering/hierachical/NodeManager.java +++ b/src/main/java/me/cortex/voxy/client/core/rendering/hierachical/NodeManager.java @@ -398,6 +398,7 @@ public class NodeManager { if (rem != 0) { //There are child node entries that need removing Logger.error("UNFINISHED OPERATION TODO: FIXME"); + //TODO:FIXME:FINISH:CRITICAL } } } diff --git a/src/main/java/me/cortex/voxy/commonImpl/importers/WorldImporter.java b/src/main/java/me/cortex/voxy/commonImpl/importers/WorldImporter.java index aa76ce6f..1e9d583d 100644 --- a/src/main/java/me/cortex/voxy/commonImpl/importers/WorldImporter.java +++ b/src/main/java/me/cortex/voxy/commonImpl/importers/WorldImporter.java @@ -127,7 +127,7 @@ public class WorldImporter { private volatile Thread worker; private UpdateCallback updateCallback; - public void importWorldAsyncStart(File directory, UpdateCallback updateCallback, Runnable onCompletion) { + public void importWorldAsyncStart(File directory, UpdateCallback updateCallback, Consumer onCompletion) { this.totalChunks.set(0); this.estimatedTotalChunks.set(0); this.chunksProcessed.set(0); @@ -166,7 +166,7 @@ public class WorldImporter { while (this.chunksProcessed.get() != this.totalChunks.get() && this.isRunning) { Thread.onSpinWait(); } - onCompletion.run(); + onCompletion.accept(this.totalChunks.get()); this.worker = null; }); this.worker.setName("World importer"); diff --git a/src/main/resources/assets/voxy/shaders/lod/hierarchical/traversal_dev.comp b/src/main/resources/assets/voxy/shaders/lod/hierarchical/traversal_dev.comp index ebcfe17d..c8420a74 100644 --- a/src/main/resources/assets/voxy/shaders/lod/hierarchical/traversal_dev.comp +++ b/src/main/resources/assets/voxy/shaders/lod/hierarchical/traversal_dev.comp @@ -13,6 +13,7 @@ layout(binding = SCENE_UNIFORM_BINDING, std140) uniform SceneUniform { float screenH; uint renderQueueMaxSize; float minSSS; + uint frameId; }; #import @@ -31,6 +32,10 @@ layout(binding = RENDER_QUEUE_BINDING, std430) restrict buffer renderQueueStruct uint[] renderQueue; }; +layout(binding = RENDER_TRACKER_BINDING, std430) restrict writeonly buffer renderTrackerArray { + uint[] lastRenderFrame; +}; + void addRequest(inout UnpackedNode node) { //printf("Put node decend request"); if (!hasRequested(node)) { @@ -61,6 +66,10 @@ void enqueueSelfForRender(in UnpackedNode 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 + lastRenderFrame[getId(node)] = frameId; } }