From 5baf4ce2dbfd6bd33cbc0eda69be990b62ff1643 Mon Sep 17 00:00:00 2001 From: mcrcortex <18544518+MCRcortex@users.noreply.github.com> Date: Fri, 31 Oct 2025 20:02:38 +1000 Subject: [PATCH] Shader lighting, fixes for loosing tasks in MultiThreadPrioritySemaphore, limit render generation rebuilds based on model queue and failure rate, fix native memory leak in ModelFactory (related to raw download stream) --- .../me/cortex/voxy/client/VoxyCommands.java | 1 + .../voxy/client/core/VoxyRenderSystem.java | 1 + .../core/model/ModelBakerySubsystem.java | 2 +- .../voxy/client/core/model/ModelFactory.java | 4 +- .../building/RenderGenerationService.java | 10 ++--- .../rendering/util/RawDownloadStream.java | 11 +++++ .../thread/MultiThreadPrioritySemaphore.java | 29 ++++++++++--- .../voxy/common/thread/ServiceManager.java | 41 ++++++++++--------- .../thread/UnifiedServiceThreadPool.java | 2 +- .../assets/voxy/shaders/lod/gl46/quads.frag | 6 ++- 10 files changed, 70 insertions(+), 37 deletions(-) diff --git a/src/main/java/me/cortex/voxy/client/VoxyCommands.java b/src/main/java/me/cortex/voxy/client/VoxyCommands.java index 4bf4cd01..b9062e79 100644 --- a/src/main/java/me/cortex/voxy/client/VoxyCommands.java +++ b/src/main/java/me/cortex/voxy/client/VoxyCommands.java @@ -70,6 +70,7 @@ public class VoxyCommands { } VoxyCommon.shutdownInstance(); + System.gc(); VoxyCommon.createInstance(); if (wr!=null) { ((IGetVoxyRenderSystem)wr).createRenderer(); diff --git a/src/main/java/me/cortex/voxy/client/core/VoxyRenderSystem.java b/src/main/java/me/cortex/voxy/client/core/VoxyRenderSystem.java index f31bc2cf..e6370617 100644 --- a/src/main/java/me/cortex/voxy/client/core/VoxyRenderSystem.java +++ b/src/main/java/me/cortex/voxy/client/core/VoxyRenderSystem.java @@ -77,6 +77,7 @@ public class VoxyRenderSystem { //Keep the world loaded, NOTE: this is done FIRST, to keep and ensure that even if the rest of loading takes more // than timeout, we keep the world acquired world.acquireRef(); + System.gc(); //Fking HATE EVERYTHING AAAAAAAAAAAAAAAA int[] oldBufferBindings = new int[10]; diff --git a/src/main/java/me/cortex/voxy/client/core/model/ModelBakerySubsystem.java b/src/main/java/me/cortex/voxy/client/core/model/ModelBakerySubsystem.java index d904ac58..e923d1fa 100644 --- a/src/main/java/me/cortex/voxy/client/core/model/ModelBakerySubsystem.java +++ b/src/main/java/me/cortex/voxy/client/core/model/ModelBakerySubsystem.java @@ -33,7 +33,7 @@ public class ModelBakerySubsystem { while (this.isRunning) { this.factory.processAllThings(); try { - Thread.sleep(50); + Thread.sleep(10); } catch (InterruptedException e) { throw new RuntimeException(e); } diff --git a/src/main/java/me/cortex/voxy/client/core/model/ModelFactory.java b/src/main/java/me/cortex/voxy/client/core/model/ModelFactory.java index b96bb65d..ac6d194d 100644 --- a/src/main/java/me/cortex/voxy/client/core/model/ModelFactory.java +++ b/src/main/java/me/cortex/voxy/client/core/model/ModelFactory.java @@ -913,14 +913,14 @@ public class ModelFactory { } public void free() { + this.bakery.free(); + this.downstream.free(); while (!this.rawBakeResults.isEmpty()) { this.rawBakeResults.poll().rawData.free(); } while (!this.uploadResults.isEmpty()) { this.uploadResults.poll().free(); } - this.downstream.free(); - this.bakery.free(); } public int getBakedCount() { diff --git a/src/main/java/me/cortex/voxy/client/core/rendering/building/RenderGenerationService.java b/src/main/java/me/cortex/voxy/client/core/rendering/building/RenderGenerationService.java index 09441df3..01407b8b 100644 --- a/src/main/java/me/cortex/voxy/client/core/rendering/building/RenderGenerationService.java +++ b/src/main/java/me/cortex/voxy/client/core/rendering/building/RenderGenerationService.java @@ -79,7 +79,7 @@ public class RenderGenerationService { return new Pair<>(() -> { this.processJob(factory, seenMissed); }, factory::free); - }, 10, "Section mesh generation service"); + }, 10, "Section mesh generation service", ()->modelBakery.getProcessingCount()<400||RenderGenerationService.MESH_FAILED_COUNTER.get()<500); } public void setResultConsumer(Consumer consumer) { @@ -354,14 +354,12 @@ public class RenderGenerationService { } private long lastChangedTime = 0; - private int failedCounter = 0; public void addDebugData(List debug) { - if (System.currentTimeMillis()-this.lastChangedTime > 1000) { - this.failedCounter = 0; + if (System.currentTimeMillis()-this.lastChangedTime > 100) { + MESH_FAILED_COUNTER.set(0); this.lastChangedTime = System.currentTimeMillis(); } - this.failedCounter += MESH_FAILED_COUNTER.getAndSet(0); - debug.add("RSSQ/TFC: " + this.taskQueueCount.get() + "/" + this.failedCounter);//render section service queue, Task Fail Counter + debug.add("RSSQ/TFC: " + this.taskQueueCount.get() + "/" + MESH_FAILED_COUNTER.get());//render section service queue, Task Fail Counter } diff --git a/src/main/java/me/cortex/voxy/client/core/rendering/util/RawDownloadStream.java b/src/main/java/me/cortex/voxy/client/core/rendering/util/RawDownloadStream.java index 62699ea7..d3ebb198 100644 --- a/src/main/java/me/cortex/voxy/client/core/rendering/util/RawDownloadStream.java +++ b/src/main/java/me/cortex/voxy/client/core/rendering/util/RawDownloadStream.java @@ -80,6 +80,17 @@ public class RawDownloadStream { } public void free() { + glFinish(); + this.tick(); + GlFence fence = new GlFence(); + while (!fence.signaled()) { + glFinish(); + } + fence.free(); + this.tick(); + if (this.frames.size() != 0) { + throw new IllegalStateException(); + } this.frames.forEach(a->a.fence.free()); this.downloadBuffer.free(); } diff --git a/src/main/java/me/cortex/voxy/common/thread/MultiThreadPrioritySemaphore.java b/src/main/java/me/cortex/voxy/common/thread/MultiThreadPrioritySemaphore.java index a4719609..c9198cc9 100644 --- a/src/main/java/me/cortex/voxy/common/thread/MultiThreadPrioritySemaphore.java +++ b/src/main/java/me/cortex/voxy/common/thread/MultiThreadPrioritySemaphore.java @@ -4,6 +4,8 @@ import me.cortex.voxy.common.util.TrackedObject; import java.util.*; import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; +import java.util.function.IntSupplier; //Basiclly acts as a priority based mutlti semaphore // allows the pooling of multiple threadpools together while prioritizing the work the original was ment for @@ -51,7 +53,9 @@ public class MultiThreadPrioritySemaphore { if (this.localSemaphore.tryAcquire()) {//We prioritize locals first return; } - this.man.tryRun(this); + if (this.man.tryRun(this)) {//Returns true if it captured a local job + break; + } } else { this.localSemaphore.acquireUninterruptibly(); if (!this.blockSemaphore.tryAcquire()) { @@ -87,11 +91,11 @@ public class MultiThreadPrioritySemaphore { } private final Semaphore pooledSemaphore = new Semaphore(0); - private final Runnable executor; + private final IntSupplier executor; private volatile Block[] blocks = new Block[0]; - public MultiThreadPrioritySemaphore(Runnable executor) { + public MultiThreadPrioritySemaphore(IntSupplier executor) { this.executor = executor; } @@ -136,7 +140,22 @@ public class MultiThreadPrioritySemaphore { } }*/ //Run the pooled job - this.executor.run(); - return true; + while (true) { + int status = this.executor.getAsInt(); + if (status == 0) return false;//We finished pure and true + if (status == 1) return false;// we didnt run a job because there either wasnt any or no services exist + if (2 <= status) {//2 and 3 mean failed to find a service that can currently run, but should try again after a delay + try { + if (block.localSemaphore.tryAcquire(10, TimeUnit.MILLISECONDS)) {//Await 10 millis for a local job to come in + //We do this confusing thing + block.blockSemaphore.tryAcquire();//Try acquire the block that we just got + this.pooledRelease(1);//We need to release back into the pool + return true; + } + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + } } } diff --git a/src/main/java/me/cortex/voxy/common/thread/ServiceManager.java b/src/main/java/me/cortex/voxy/common/thread/ServiceManager.java index 43424661..454d8c70 100644 --- a/src/main/java/me/cortex/voxy/common/thread/ServiceManager.java +++ b/src/main/java/me/cortex/voxy/common/thread/ServiceManager.java @@ -58,48 +58,49 @@ public class ServiceManager { return newService; } - public boolean runAJob() {//Executes a single job on the current thread - while (true) { - if (this.services.length == 0 || this.totalJobs.get() == 0) return false; - if (this.runAJob0()) return true; - try { - Thread.sleep(10); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - } + public int tryRunAJob() {//Executes a single job on the current thread + if (this.services.length == 0 || this.totalJobs.get() == 0) return 1; + return this.runAJob0(); } - private boolean runAJob0() {//Executes a single job on the current thread - if (this.services.length == 0) return false; + private int runAJob0() {//Executes a single job on the current thread + if (this.services.length == 0) return 1; var ctx = this.accelerationContext.get(); outer: while (true) { + long skipMsk = 0; var services = this.services;//Capture the current services array - if (services.length == 0) return false; - if (this.totalJobs.get()==0) return false; + if (services.length == 0) return 1; + if (this.totalJobs.get()==0) return 1; long totalWeight = 0; int shiftFactor = (ctx.shiftFactor++)&Integer.MAX_VALUE;//We cycle and shift the starting service when choosing to prevent bias int c = shiftFactor; Service selectedService = null; - for (var service:services) { + for (int i = 0; i < services.length; i++) { + var service = services[i]; if (!service.isLive()) { Thread.yield(); continue outer;//We need to refetch the array and start over } boolean sc = c--<=0; - if (service.limiter!=null && !service.limiter.getAsBoolean()) continue; + if (service.limiter!=null && !service.limiter.getAsBoolean()) { + skipMsk |= 1L<>4)&0xFu)/16, vec2(4.0f/255), vec2(252.0f/255)); - return vec2(interData.y&0xFu, (interData.y>>4)&0xFu)/15; + return clamp((vec2((interData.y>>4)&0xFu, interData.y&0xFu))/16, vec2(8.0f/256), vec2(248.0f/256)); } #endif @@ -190,7 +190,9 @@ void main() { tint = uint2vec4RGBA(interData.z).yzwx; } - voxy_emitFragment(VoxyFragmentParameters(colour, tile, texPos, getFace(), modelId, getLightmap().yx, tint, model.customId)); + uint face = getFace(); + face ^= uint((face&1u)!=uint(gl_FrontFacing!=((face>>1)!=0u))); + voxy_emitFragment(VoxyFragmentParameters(colour, tile, texPos, face, modelId, getLightmap(), tint, model.customId)); #endif }