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