Convert ingest to be per section

This commit is contained in:
mcrcortex
2025-03-03 10:44:45 +10:00
parent a6ed760304
commit ce5f792500

View File

@@ -1,6 +1,7 @@
package me.cortex.voxy.common.world.service; package me.cortex.voxy.common.world.service;
import it.unimi.dsi.fastutil.Pair; import it.unimi.dsi.fastutil.Pair;
import me.cortex.voxy.common.voxelization.ILightingSupplier;
import me.cortex.voxy.common.voxelization.VoxelizedSection; import me.cortex.voxy.common.voxelization.VoxelizedSection;
import me.cortex.voxy.common.voxelization.WorldConversionFactory; import me.cortex.voxy.common.voxelization.WorldConversionFactory;
import me.cortex.voxy.common.world.WorldEngine; import me.cortex.voxy.common.world.WorldEngine;
@@ -9,6 +10,7 @@ import me.cortex.voxy.common.thread.ServiceThreadPool;
import net.minecraft.util.math.ChunkSectionPos; import net.minecraft.util.math.ChunkSectionPos;
import net.minecraft.world.LightType; import net.minecraft.world.LightType;
import net.minecraft.world.chunk.ChunkNibbleArray; import net.minecraft.world.chunk.ChunkNibbleArray;
import net.minecraft.world.chunk.ChunkSection;
import net.minecraft.world.chunk.WorldChunk; import net.minecraft.world.chunk.WorldChunk;
import java.util.Map; import java.util.Map;
@@ -18,8 +20,8 @@ import java.util.concurrent.ConcurrentLinkedDeque;
public class VoxelIngestService { public class VoxelIngestService {
private static final ThreadLocal<VoxelizedSection> SECTION_CACHE = ThreadLocal.withInitial(VoxelizedSection::createEmpty); private static final ThreadLocal<VoxelizedSection> SECTION_CACHE = ThreadLocal.withInitial(VoxelizedSection::createEmpty);
private final ServiceSlice threads; private final ServiceSlice threads;
private final ConcurrentLinkedDeque<WorldChunk> ingestQueue = new ConcurrentLinkedDeque<>(); private record IngestSection(int cx, int cy, int cz, ChunkSection section, ChunkNibbleArray blockLight, ChunkNibbleArray skyLight){}
private final ConcurrentHashMap<Long, Pair<ChunkNibbleArray, ChunkNibbleArray>> captureLightMap = new ConcurrentHashMap<>(1000,0.75f, 7); private final ConcurrentLinkedDeque<IngestSection> ingestQueue = new ConcurrentLinkedDeque<>();
private final WorldEngine world; private final WorldEngine world;
public VoxelIngestService(WorldEngine world, ServiceThreadPool pool) { public VoxelIngestService(WorldEngine world, ServiceThreadPool pool) {
@@ -28,40 +30,56 @@ public class VoxelIngestService {
} }
private void processJob() { private void processJob() {
var chunk = this.ingestQueue.pop(); var task = this.ingestQueue.pop();
int i = chunk.getBottomSectionCoord() - 1; var section = task.section;
for (var section : chunk.getSectionArray()) { var vs = SECTION_CACHE.get().setPosition(task.cx, task.cy, task.cz);
i++;
var lighting = this.captureLightMap.remove(ChunkSectionPos.from(chunk.getPos(), i).asLong()); if (section.isEmpty() && task.blockLight==null && task.skyLight==null) {//If the chunk section has lighting data, propagate it
if (section.isEmpty() && lighting==null) {//If the chunk section has lighting data, propagate it this.world.insertUpdate(vs.zero());
this.world.insertUpdate(SECTION_CACHE.get().zero().setPosition(chunk.getPos().x, i, chunk.getPos().z)); } else {
} else { ILightingSupplier supplier = (x,y,z) -> (byte) 0;
VoxelizedSection csec = WorldConversionFactory.convert( var sla = task.skyLight;
SECTION_CACHE.get().setPosition(chunk.getPos().x, i, chunk.getPos().z), var bla = task.blockLight;
this.world.getMapper(), boolean sl = sla != null && !sla.isUninitialized();
section.getBlockStateContainer(), boolean bl = bla != null && !bla.isUninitialized();
section.getBiomeContainer(), if (sl || bl) {
(x, y, z) -> { if (sl && bl) {
if (lighting == null || ((lighting.first() != null && lighting.first().isUninitialized())&&(lighting.second()!=null&&lighting.second().isUninitialized()))) { supplier = (x,y,z)-> {
return (byte) 0; int block = Math.min(15,bla.get(x, y, z));
} else { int sky = Math.min(15,sla.get(x, y, z));
//Lighting is hell return (byte) (sky|(block<<4));
int block = lighting.first()!=null?Math.min(15,lighting.first().get(x, y, z)):0; };
int sky = lighting.second()!=null?Math.min(15,lighting.second().get(x, y, z)):0; } else if (bl) {
//if (block<state.getLuminance()) { supplier = (x,y,z)-> {
// block = state.getLuminance(); int block = Math.min(15,bla.get(x, y, z));
//} int sky = 0;
return (byte) (sky|(block<<4)); return (byte) (sky|(block<<4));
} };
} } else {
); supplier = (x,y,z)-> {
WorldConversionFactory.mipSection(csec, this.world.getMapper()); int block = 0;
this.world.insertUpdate(csec); int sky = Math.min(15,sla.get(x, y, z));
return (byte) (sky|(block<<4));
};
}
} }
VoxelizedSection csec = WorldConversionFactory.convert(
SECTION_CACHE.get(),
this.world.getMapper(),
section.getBlockStateContainer(),
section.getBiomeContainer(),
supplier
);
WorldConversionFactory.mipSection(csec, this.world.getMapper());
this.world.insertUpdate(csec);
} }
} }
private static void fetchLightingData(Map<Long, Pair<ChunkNibbleArray, ChunkNibbleArray>> out, WorldChunk chunk) { private static boolean shouldIngestSection(ChunkSection section, int cx, int cy, int cz) {
return true;
}
public void enqueueIngest(WorldChunk chunk) {
var lightingProvider = chunk.getWorld().getLightingProvider(); var lightingProvider = chunk.getWorld().getLightingProvider();
var blp = lightingProvider.get(LightType.BLOCK); var blp = lightingProvider.get(LightType.BLOCK);
var slp = lightingProvider.get(LightType.SKY); var slp = lightingProvider.get(LightType.SKY);
@@ -69,7 +87,7 @@ public class VoxelIngestService {
int i = chunk.getBottomSectionCoord() - 1; int i = chunk.getBottomSectionCoord() - 1;
for (var section : chunk.getSectionArray()) { for (var section : chunk.getSectionArray()) {
i++; i++;
if (section == null) continue; if (section == null || !shouldIngestSection(section, chunk.getPos().x, i, chunk.getPos().z)) continue;
//if (section.isEmpty()) continue; //if (section.isEmpty()) continue;
var pos = ChunkSectionPos.from(chunk.getPos(), i); var pos = ChunkSectionPos.from(chunk.getPos(), i);
var bl = blp.getLightSection(pos); var bl = blp.getLightSection(pos);
@@ -84,17 +102,14 @@ public class VoxelIngestService {
} else { } else {
sl = null; sl = null;
} }
if (bl == null && sl == null) {
if ((bl == null && sl == null) && section.isEmpty()) {
continue; continue;
} }
out.put(pos.asLong(), Pair.of(bl, sl));
}
}
public void enqueueIngest(WorldChunk chunk) { this.ingestQueue.add(new IngestSection(chunk.getPos().x, i, chunk.getPos().z, section, bl, sl));
fetchLightingData(this.captureLightMap, chunk); this.threads.execute();
this.ingestQueue.add(chunk); }
this.threads.execute();
} }
public int getTaskCount() { public int getTaskCount() {