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:
@@ -70,6 +70,7 @@ public class VoxyCommands {
|
|||||||
}
|
}
|
||||||
|
|
||||||
VoxyCommon.shutdownInstance();
|
VoxyCommon.shutdownInstance();
|
||||||
|
System.gc();
|
||||||
VoxyCommon.createInstance();
|
VoxyCommon.createInstance();
|
||||||
if (wr!=null) {
|
if (wr!=null) {
|
||||||
((IGetVoxyRenderSystem)wr).createRenderer();
|
((IGetVoxyRenderSystem)wr).createRenderer();
|
||||||
|
|||||||
@@ -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
|
//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
|
// than timeout, we keep the world acquired
|
||||||
world.acquireRef();
|
world.acquireRef();
|
||||||
|
System.gc();
|
||||||
|
|
||||||
//Fking HATE EVERYTHING AAAAAAAAAAAAAAAA
|
//Fking HATE EVERYTHING AAAAAAAAAAAAAAAA
|
||||||
int[] oldBufferBindings = new int[10];
|
int[] oldBufferBindings = new int[10];
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ public class ModelBakerySubsystem {
|
|||||||
while (this.isRunning) {
|
while (this.isRunning) {
|
||||||
this.factory.processAllThings();
|
this.factory.processAllThings();
|
||||||
try {
|
try {
|
||||||
Thread.sleep(50);
|
Thread.sleep(10);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -913,14 +913,14 @@ public class ModelFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void free() {
|
public void free() {
|
||||||
|
this.bakery.free();
|
||||||
|
this.downstream.free();
|
||||||
while (!this.rawBakeResults.isEmpty()) {
|
while (!this.rawBakeResults.isEmpty()) {
|
||||||
this.rawBakeResults.poll().rawData.free();
|
this.rawBakeResults.poll().rawData.free();
|
||||||
}
|
}
|
||||||
while (!this.uploadResults.isEmpty()) {
|
while (!this.uploadResults.isEmpty()) {
|
||||||
this.uploadResults.poll().free();
|
this.uploadResults.poll().free();
|
||||||
}
|
}
|
||||||
this.downstream.free();
|
|
||||||
this.bakery.free();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getBakedCount() {
|
public int getBakedCount() {
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ public class RenderGenerationService {
|
|||||||
return new Pair<>(() -> {
|
return new Pair<>(() -> {
|
||||||
this.processJob(factory, seenMissed);
|
this.processJob(factory, seenMissed);
|
||||||
}, factory::free);
|
}, 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) {
|
public void setResultConsumer(Consumer<BuiltSection> consumer) {
|
||||||
@@ -354,14 +354,12 @@ public class RenderGenerationService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private long lastChangedTime = 0;
|
private long lastChangedTime = 0;
|
||||||
private int failedCounter = 0;
|
|
||||||
public void addDebugData(List<String> debug) {
|
public void addDebugData(List<String> debug) {
|
||||||
if (System.currentTimeMillis()-this.lastChangedTime > 1000) {
|
if (System.currentTimeMillis()-this.lastChangedTime > 100) {
|
||||||
this.failedCounter = 0;
|
MESH_FAILED_COUNTER.set(0);
|
||||||
this.lastChangedTime = System.currentTimeMillis();
|
this.lastChangedTime = System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
this.failedCounter += MESH_FAILED_COUNTER.getAndSet(0);
|
debug.add("RSSQ/TFC: " + this.taskQueueCount.get() + "/" + MESH_FAILED_COUNTER.get());//render section service queue, Task Fail Counter
|
||||||
debug.add("RSSQ/TFC: " + this.taskQueueCount.get() + "/" + this.failedCounter);//render section service queue, Task Fail Counter
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -80,6 +80,17 @@ public class RawDownloadStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void free() {
|
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.frames.forEach(a->a.fence.free());
|
||||||
this.downloadBuffer.free();
|
this.downloadBuffer.free();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import me.cortex.voxy.common.util.TrackedObject;
|
|||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.Semaphore;
|
import java.util.concurrent.Semaphore;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.function.IntSupplier;
|
||||||
|
|
||||||
//Basiclly acts as a priority based mutlti semaphore
|
//Basiclly acts as a priority based mutlti semaphore
|
||||||
// allows the pooling of multiple threadpools together while prioritizing the work the original was ment for
|
// 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
|
if (this.localSemaphore.tryAcquire()) {//We prioritize locals first
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.man.tryRun(this);
|
if (this.man.tryRun(this)) {//Returns true if it captured a local job
|
||||||
|
break;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.localSemaphore.acquireUninterruptibly();
|
this.localSemaphore.acquireUninterruptibly();
|
||||||
if (!this.blockSemaphore.tryAcquire()) {
|
if (!this.blockSemaphore.tryAcquire()) {
|
||||||
@@ -87,11 +91,11 @@ public class MultiThreadPrioritySemaphore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private final Semaphore pooledSemaphore = new Semaphore(0);
|
private final Semaphore pooledSemaphore = new Semaphore(0);
|
||||||
private final Runnable executor;
|
private final IntSupplier executor;
|
||||||
|
|
||||||
private volatile Block[] blocks = new Block[0];
|
private volatile Block[] blocks = new Block[0];
|
||||||
|
|
||||||
public MultiThreadPrioritySemaphore(Runnable executor) {
|
public MultiThreadPrioritySemaphore(IntSupplier executor) {
|
||||||
this.executor = executor;
|
this.executor = executor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,7 +140,22 @@ public class MultiThreadPrioritySemaphore {
|
|||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
//Run the pooled job
|
//Run the pooled job
|
||||||
this.executor.run();
|
while (true) {
|
||||||
return 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,48 +58,49 @@ public class ServiceManager {
|
|||||||
return newService;
|
return newService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean runAJob() {//Executes a single job on the current thread
|
public int tryRunAJob() {//Executes a single job on the current thread
|
||||||
while (true) {
|
if (this.services.length == 0 || this.totalJobs.get() == 0) return 1;
|
||||||
if (this.services.length == 0 || this.totalJobs.get() == 0) return false;
|
return this.runAJob0();
|
||||||
if (this.runAJob0()) return true;
|
|
||||||
try {
|
|
||||||
Thread.sleep(10);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean runAJob0() {//Executes a single job on the current thread
|
private int runAJob0() {//Executes a single job on the current thread
|
||||||
if (this.services.length == 0) return false;
|
if (this.services.length == 0) return 1;
|
||||||
var ctx = this.accelerationContext.get();
|
var ctx = this.accelerationContext.get();
|
||||||
outer:
|
outer:
|
||||||
while (true) {
|
while (true) {
|
||||||
|
long skipMsk = 0;
|
||||||
var services = this.services;//Capture the current services array
|
var services = this.services;//Capture the current services array
|
||||||
if (services.length == 0) return false;
|
if (services.length == 0) return 1;
|
||||||
if (this.totalJobs.get()==0) return false;
|
if (this.totalJobs.get()==0) return 1;
|
||||||
long totalWeight = 0;
|
long totalWeight = 0;
|
||||||
int shiftFactor = (ctx.shiftFactor++)&Integer.MAX_VALUE;//We cycle and shift the starting service when choosing to prevent bias
|
int shiftFactor = (ctx.shiftFactor++)&Integer.MAX_VALUE;//We cycle and shift the starting service when choosing to prevent bias
|
||||||
int c = shiftFactor;
|
int c = shiftFactor;
|
||||||
Service selectedService = null;
|
Service selectedService = null;
|
||||||
for (var service:services) {
|
for (int i = 0; i < services.length; i++) {
|
||||||
|
var service = services[i];
|
||||||
if (!service.isLive()) {
|
if (!service.isLive()) {
|
||||||
Thread.yield();
|
Thread.yield();
|
||||||
continue outer;//We need to refetch the array and start over
|
continue outer;//We need to refetch the array and start over
|
||||||
}
|
}
|
||||||
boolean sc = c--<=0;
|
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();
|
long jc = service.numJobs();
|
||||||
if (sc&&jc!=0&&selectedService==null) selectedService=service;
|
if (sc&&jc!=0&&selectedService==null) selectedService=service;
|
||||||
totalWeight += jc * service.weight;
|
totalWeight += jc * service.weight;
|
||||||
}
|
}
|
||||||
if (totalWeight == 0) return false;
|
if (totalWeight == 0) return skipMsk!=0?3:2;
|
||||||
|
|
||||||
long sample = ctx.rand(totalWeight);//Random number
|
long sample = ctx.rand(totalWeight);//Random number
|
||||||
|
|
||||||
for (int i = 0; i < services.length; i++) {
|
for (int i = 0; i < services.length; i++) {
|
||||||
var service = services[(i+shiftFactor)%services.length];
|
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;
|
sample -= service.numJobs() * service.weight;
|
||||||
if (sample<=0) {
|
if (sample<=0) {
|
||||||
selectedService = service;
|
selectedService = service;
|
||||||
@@ -108,7 +109,7 @@ public class ServiceManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (selectedService == null) {
|
if (selectedService == null) {
|
||||||
return false;
|
return skipMsk!=0?3:2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!selectedService.isLive()) {
|
if (!selectedService.isLive()) {
|
||||||
@@ -124,7 +125,7 @@ public class ServiceManager {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return true;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ public class UnifiedServiceThreadPool {
|
|||||||
public UnifiedServiceThreadPool() {
|
public UnifiedServiceThreadPool() {
|
||||||
this.dedicatedPool = new ThreadGroup("Voxy Dedicated Service");
|
this.dedicatedPool = new ThreadGroup("Voxy Dedicated Service");
|
||||||
this.serviceManager = new ServiceManager(this::release);
|
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();
|
this.selfBlock = this.groupSemaphore.createBlock();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ uint getFace() {
|
|||||||
#ifdef PATCHED_SHADER
|
#ifdef PATCHED_SHADER
|
||||||
vec2 getLightmap() {
|
vec2 getLightmap() {
|
||||||
//return clamp(vec2(interData.y&0xFu, (interData.y>>4)&0xFu)/16, vec2(4.0f/255), vec2(252.0f/255));
|
//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
|
#endif
|
||||||
|
|
||||||
@@ -190,7 +190,9 @@ void main() {
|
|||||||
tint = uint2vec4RGBA(interData.z).yzwx;
|
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
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user