improved lru cache and improved world import speed slightly
This commit is contained in:
@@ -138,7 +138,9 @@ public class RenderGenerationService {
|
||||
//If we did put it in the queue, dont release the section
|
||||
shouldFreeSection = false;
|
||||
} else {
|
||||
Logger.warn("Funkyness happened and multiple tasks for same section where in queue");
|
||||
//This should no longer be a worry with LRU section cache
|
||||
//Logger.info("Funkyness happened and multiple tasks for same section where in queue");
|
||||
|
||||
//Things went bad, set section to null and ensure section is freed
|
||||
task.section = null;
|
||||
shouldFreeSection = true;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package me.cortex.voxy.common.thread;
|
||||
|
||||
import me.cortex.voxy.common.Logger;
|
||||
import me.cortex.voxy.common.util.Pair;
|
||||
import me.cortex.voxy.common.util.TrackedObject;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
@@ -76,8 +77,7 @@ public class ServiceSlice extends TrackedObject {
|
||||
try {
|
||||
ctx.run();
|
||||
} catch (Exception e) {
|
||||
System.err.println("Unexpected error occurred while executing a service job, expect things to break badly");
|
||||
e.printStackTrace();
|
||||
Logger.error("Unexpected error occurred while executing a service job, expect things to break badly", e);
|
||||
MinecraftClient.getInstance().execute(()->MinecraftClient.getInstance().player.sendMessage(Text.literal("A voxy service had an exception while executing please check logs and report error"), true));
|
||||
} finally {
|
||||
if (this.activeCount.decrementAndGet() < 0) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package me.cortex.voxy.common.voxelization;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap;
|
||||
import me.cortex.voxy.common.util.Pair;
|
||||
import me.cortex.voxy.common.world.other.Mipper;
|
||||
import me.cortex.voxy.common.world.other.Mapper;
|
||||
import net.minecraft.block.BlockState;
|
||||
@@ -11,30 +12,34 @@ import net.minecraft.world.chunk.ReadableContainer;
|
||||
|
||||
public class WorldConversionFactory {
|
||||
//TODO: create a mapping for world/mapper -> local mapping
|
||||
private static final ThreadLocal<Reference2IntOpenHashMap<BlockState>> BLOCK_CACHE = ThreadLocal.withInitial(Reference2IntOpenHashMap::new);
|
||||
private static final ThreadLocal<Pair<int[],Reference2IntOpenHashMap<BlockState>>> THREAD_LOCAL = ThreadLocal.withInitial(()->new Pair<>(new int[4*4*4], new Reference2IntOpenHashMap<>()));
|
||||
|
||||
public static VoxelizedSection convert(VoxelizedSection section,
|
||||
Mapper stateMapper,
|
||||
PalettedContainer<BlockState> blockContainer,
|
||||
ReadableContainer<RegistryEntry<Biome>> biomeContainer,
|
||||
ILightingSupplier lightSupplier) {
|
||||
var blockCache = BLOCK_CACHE.get();
|
||||
var threadLocal = THREAD_LOCAL.get();
|
||||
var blockCache = threadLocal.right();
|
||||
var biomes = threadLocal.left();
|
||||
var data = section.section;
|
||||
|
||||
int blockId = -1;
|
||||
BlockState block = null;
|
||||
{
|
||||
int i = 0;
|
||||
for (int y = 0; y < 4; y++) {
|
||||
for (int z = 0; z < 4; z++) {
|
||||
for (int x = 0; x < 4; x++) {
|
||||
biomes[i++] = stateMapper.getIdForBiome(biomeContainer.get(x, y, z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int oy = 0; oy < 4; oy++) {
|
||||
for (int oz = 0; oz < 4; oz++) {
|
||||
for (int ox = 0; ox < 4; ox++) {
|
||||
int biomeId = stateMapper.getIdForBiome(biomeContainer.get(ox, oy, oz));
|
||||
|
||||
for (int iy = 0; iy < 4; iy++) {
|
||||
for (int iz = 0; iz < 4; iz++) {
|
||||
for (int ix = 0; ix < 4; ix++) {
|
||||
int x = (ox<<2)|ix;
|
||||
int y = (oy<<2)|iy;
|
||||
int z = (oz<<2)|iz;
|
||||
for (int y = 0; y < 16; y++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
var state = blockContainer.get(x, y, z);
|
||||
byte light = lightSupplier.supply(x,y,z,state);
|
||||
if (!(state.isAir() && (light==0))) {
|
||||
@@ -51,16 +56,13 @@ public class WorldConversionFactory {
|
||||
block = state;
|
||||
}
|
||||
}
|
||||
data[G(x, y, z)] = Mapper.composeMappingId(light, blockId, biomeId);
|
||||
data[G(x, y, z)] = Mapper.composeMappingId(light, blockId, biomes[((y&0b1100)<<2)|(z&0b1100)|(x>>2)]);
|
||||
} else {
|
||||
data[G(x, y, z)] = Mapper.AIR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return section;
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ public class ActiveSectionTracker {
|
||||
var cache = this.loadedSectionCache[index];
|
||||
VolatileHolder<WorldSection> holder = null;
|
||||
boolean isLoader = false;
|
||||
WorldSection cachedSection = null;
|
||||
WorldSection section;
|
||||
synchronized (cache) {
|
||||
holder = cache.get(key);
|
||||
if (holder == null) {
|
||||
@@ -49,23 +49,19 @@ public class ActiveSectionTracker {
|
||||
cache.put(key, holder);
|
||||
isLoader = true;
|
||||
}
|
||||
var section = holder.obj;
|
||||
section = holder.obj;
|
||||
if (section != null) {
|
||||
section.acquire();
|
||||
return section;
|
||||
}
|
||||
if (isLoader) {
|
||||
cachedSection = this.lruSecondaryCache[index].remove(key);
|
||||
if (cachedSection != null) {
|
||||
cachedSection.primeForReuse();
|
||||
}
|
||||
section = this.lruSecondaryCache[index].remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
//If this thread was the one to create the reference then its the thread to load the section
|
||||
if (isLoader) {
|
||||
int status = 0;
|
||||
var section = cachedSection;
|
||||
if (section == null) {//Secondary cache miss
|
||||
section = new WorldSection(WorldEngine.getLevel(key),
|
||||
WorldEngine.getX(key),
|
||||
@@ -87,7 +83,10 @@ public class ActiveSectionTracker {
|
||||
//We need to set the data to air as it is undefined state
|
||||
Arrays.fill(section.data, 0);
|
||||
}
|
||||
} else {
|
||||
section.primeForReuse();
|
||||
}
|
||||
|
||||
section.acquire();
|
||||
holder.obj = section;
|
||||
if (nullOnEmpty && status == 1) {//If its air return null as stated, release the section aswell
|
||||
@@ -96,7 +95,6 @@ public class ActiveSectionTracker {
|
||||
}
|
||||
return section;
|
||||
} else {
|
||||
WorldSection section = null;
|
||||
while ((section = holder.obj) == null)
|
||||
Thread.onSpinWait();
|
||||
|
||||
@@ -117,6 +115,7 @@ public class ActiveSectionTracker {
|
||||
if (cache.remove(section.key).obj != section) {
|
||||
throw new IllegalStateException("Removed section not the same as the referenced section in the cache");
|
||||
}
|
||||
|
||||
//Add section to secondary cache while primary is locked
|
||||
var lruCache = this.lruSecondaryCache[index];
|
||||
var prev = lruCache.put(section.key, section);
|
||||
|
||||
Reference in New Issue
Block a user