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)

This commit is contained in:
mcrcortex
2025-10-31 20:02:38 +10:00
parent 86882d5ac9
commit 5baf4ce2db
10 changed files with 70 additions and 37 deletions

View File

@@ -70,6 +70,7 @@ public class VoxyCommands {
}
VoxyCommon.shutdownInstance();
System.gc();
VoxyCommon.createInstance();
if (wr!=null) {
((IGetVoxyRenderSystem)wr).createRenderer();

View File

@@ -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];

View File

@@ -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);
}

View File

@@ -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() {

View File

@@ -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<BuiltSection> consumer) {
@@ -354,14 +354,12 @@ public class RenderGenerationService {
}
private long lastChangedTime = 0;
private int failedCounter = 0;
public void addDebugData(List<String> 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
}

View File

@@ -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();
}

View File

@@ -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);
}
}
}
}
}

View File

@@ -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<<i;
continue;
}
long jc = service.numJobs();
if (sc&&jc!=0&&selectedService==null) selectedService=service;
totalWeight += jc * service.weight;
}
if (totalWeight == 0) return false;
if (totalWeight == 0) return skipMsk!=0?3:2;
long sample = ctx.rand(totalWeight);//Random number
for (int i = 0; i < services.length; i++) {
var service = services[(i+shiftFactor)%services.length];
if (service.limiter!=null && !service.limiter.getAsBoolean()) continue;
if (service.limiter!=null && (((skipMsk&(1L<<i))!=0)|| !service.limiter.getAsBoolean())) {
skipMsk |= 1L<<i;
continue;
}
sample -= service.numJobs() * service.weight;
if (sample<=0) {
selectedService = service;
@@ -108,7 +109,7 @@ public class ServiceManager {
}
if (selectedService == null) {
return false;
return skipMsk!=0?3:2;
}
if (!selectedService.isLive()) {
@@ -124,7 +125,7 @@ public class ServiceManager {
}
break;
}
return true;
return 0;
}
public void shutdown() {

View File

@@ -18,7 +18,7 @@ public class UnifiedServiceThreadPool {
public UnifiedServiceThreadPool() {
this.dedicatedPool = new ThreadGroup("Voxy Dedicated Service");
this.serviceManager = new ServiceManager(this::release);
this.groupSemaphore = new MultiThreadPrioritySemaphore(this.serviceManager::runAJob);
this.groupSemaphore = new MultiThreadPrioritySemaphore(this.serviceManager::tryRunAJob);
this.selfBlock = this.groupSemaphore.createBlock();
}

View File

@@ -54,7 +54,7 @@ uint getFace() {
#ifdef PATCHED_SHADER
vec2 getLightmap() {
//return clamp(vec2(interData.y&0xFu, (interData.y>>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
}