Merge branch 'master' into toadstool-mushroom-caves

This commit is contained in:
codemob-dev 2025-07-25 16:10:29 -04:00
commit d572521204
5 changed files with 26 additions and 50 deletions

View File

@ -1215,7 +1215,6 @@ pub const Protocols = struct {
var ligthMapReader = utils.BinaryReader.init(_inflatedData);
const map = main.globalAllocator.create(main.server.terrain.LightMap.LightMapFragment);
map.init(pos.wx, pos.wy, pos.voxelSize);
_ = map.refCount.fetchAdd(1, .monotonic);
for(&map.startHeight) |*val| {
val.* = try ligthMapReader.readInt(i16);
}

View File

@ -807,8 +807,7 @@ pub const ChunkMesh = struct { // MARK: ChunkMesh
var allSun: bool = self.chunk.data.paletteLength == 1 and self.chunk.data.palette[0].typ == 0;
var sunStarters: [chunk.chunkSize*chunk.chunkSize][3]u8 = undefined;
var index: usize = 0;
const lightStartMap = mesh_storage.getLightMapPieceAndIncreaseRefCount(self.pos.wx, self.pos.wy, self.pos.voxelSize) orelse break :sunLight;
defer lightStartMap.decreaseRefCount();
const lightStartMap = mesh_storage.getLightMapPiece(self.pos.wx, self.pos.wy, self.pos.voxelSize) orelse break :sunLight;
x = 0;
while(x < chunk.chunkSize) : (x += 1) {
var y: u8 = 0;

View File

@ -33,7 +33,7 @@ const ChunkMeshNode = struct {
const storageSize = 64;
const storageMask = storageSize - 1;
var storageLists: [settings.highestSupportedLod + 1]*[storageSize*storageSize*storageSize]ChunkMeshNode = undefined;
var mapStorageLists: [settings.highestSupportedLod + 1]*[storageSize*storageSize]?*LightMap.LightMapFragment = undefined;
var mapStorageLists: [settings.highestSupportedLod + 1]*[storageSize*storageSize]Atomic(?*LightMap.LightMapFragment) = undefined;
var meshList = main.List(*chunk_meshing.ChunkMesh).init(main.globalAllocator);
var priorityMeshUpdateList: main.utils.ConcurrentQueue(chunk.ChunkPosition) = undefined;
pub var updatableList = main.List(chunk.ChunkPosition).init(main.globalAllocator);
@ -85,8 +85,8 @@ pub fn init() void { // MARK: init()
}
}
for(&mapStorageLists) |*mapStorageList| {
mapStorageList.* = main.globalAllocator.create([storageSize*storageSize]?*LightMap.LightMapFragment);
@memset(mapStorageList.*, null);
mapStorageList.* = main.globalAllocator.create([storageSize*storageSize]Atomic(?*LightMap.LightMapFragment));
@memset(mapStorageList.*, .init(null));
}
priorityMeshUpdateList = .init(main.globalAllocator, 16);
mapUpdatableList = .init(main.globalAllocator, 16);
@ -102,7 +102,6 @@ pub fn deinit() void {
lastPz = 0;
lastRD = 0;
freeOldMeshes(olderPx, olderPy, olderPz, olderRD);
main.heap.GarbageCollection.waitForFreeCompletion();
for(storageLists) |storageList| {
main.globalAllocator.destroy(storageList);
}
@ -112,7 +111,7 @@ pub fn deinit() void {
updatableList.clearAndFree();
while(mapUpdatableList.dequeue()) |map| {
map.decreaseRefCount();
map.deferredDeinit();
}
mapUpdatableList.deinit();
priorityMeshUpdateList.deinit();
@ -121,6 +120,7 @@ pub fn deinit() void {
}
blockUpdateList.deinit();
meshList.clearAndFree();
main.heap.GarbageCollection.waitForFreeCompletion();
meshMemoryPool.deinit();
}
@ -159,7 +159,7 @@ fn updateHigherLodNodeFinishedMeshing(pos_: chunk.ChunkPosition, finishedMeshing
}
}
fn getMapPiecePointer(x: i32, y: i32, voxelSize: u31) *?*LightMap.LightMapFragment {
fn getMapPiecePointer(x: i32, y: i32, voxelSize: u31) *Atomic(?*LightMap.LightMapFragment) {
const lod = std.math.log2_int(u31, voxelSize);
var xIndex = x >> lod + LightMap.LightMapFragment.mapShift;
var yIndex = y >> lod + LightMap.LightMapFragment.mapShift;
@ -169,14 +169,8 @@ fn getMapPiecePointer(x: i32, y: i32, voxelSize: u31) *?*LightMap.LightMapFragme
return &(&mapStorageLists)[lod][@intCast(index)];
}
pub fn getLightMapPieceAndIncreaseRefCount(x: i32, y: i32, voxelSize: u31) ?*LightMap.LightMapFragment {
mutex.lock();
defer mutex.unlock();
const result: *LightMap.LightMapFragment = getMapPiecePointer(x, y, voxelSize).* orelse {
return null;
};
result.increaseRefCount();
return result;
pub fn getLightMapPiece(x: i32, y: i32, voxelSize: u31) ?*LightMap.LightMapFragment {
return getMapPiecePointer(x, y, voxelSize).load(.acquire);
}
pub fn getBlockFromRenderThread(x: i32, y: i32, z: i32) ?blocks.Block {
@ -437,13 +431,9 @@ fn freeOldMeshes(olderPx: i32, olderPy: i32, olderPz: i32, olderRD: u16) void {
const yIndex = @divExact(y, size) & storageMask;
const index = xIndex*storageSize + yIndex;
const mapPointer = &mapStorageLists[_lod][@intCast(index)];
mutex.lock();
const oldMap = mapPointer.*;
mapPointer.* = null;
mutex.unlock();
const oldMap = mapStorageLists[_lod][@intCast(index)].swap(null, .monotonic);
if(oldMap) |map| {
map.decreaseRefCount();
map.deferredDeinit();
}
}
}
@ -576,14 +566,12 @@ fn createNewMeshes(olderPx: i32, olderPy: i32, olderPz: i32, olderRD: u16, meshR
const index = xIndex*storageSize + yIndex;
const pos = LightMap.MapFragmentPosition{.wx = x, .wy = y, .voxelSize = @as(u31, 1) << lod, .voxelSizeShift = lod};
const node = &mapStorageLists[_lod][@intCast(index)];
mutex.lock();
if(node.*) |map| {
std.debug.assert(std.meta.eql(pos, map.pos));
const map = mapStorageLists[_lod][@intCast(index)].load(.unordered);
if(map) |_map| {
std.debug.assert(std.meta.eql(pos, _map.pos));
} else {
mapRequests.append(pos);
}
mutex.unlock();
}
}
}
@ -770,13 +758,12 @@ pub fn updateMeshes(targetTime: i64) void { // MARK: updateMeshes()=
}
while(mapUpdatableList.dequeue()) |map| {
if(!isMapInRenderDistance(map.pos)) {
map.decreaseRefCount();
map.deferredDeinit();
} else {
const mapPointer = getMapPiecePointer(map.pos.wx, map.pos.wy, map.pos.voxelSize);
if(mapPointer.*) |old| {
old.decreaseRefCount();
const mapPointer = getMapPiecePointer(map.pos.wx, map.pos.wy, map.pos.voxelSize).swap(map, .release);
if(mapPointer) |old| {
old.deferredDeinit();
}
mapPointer.* = map;
}
}
while(updatableList.items.len != 0) {

View File

@ -20,25 +20,18 @@ pub const LightMapFragment = struct {
startHeight: [mapSize*mapSize]i16 = undefined,
pos: MapFragmentPosition,
refCount: Atomic(u16) = .init(0),
pub fn init(self: *LightMapFragment, wx: i32, wy: i32, voxelSize: u31) void {
self.* = .{
.pos = MapFragmentPosition.init(wx, wy, voxelSize),
};
}
pub fn increaseRefCount(self: *LightMapFragment) void {
const prevVal = self.refCount.fetchAdd(1, .monotonic);
std.debug.assert(prevVal != 0);
fn deinit(self: *const LightMapFragment, _: usize) void {
main.globalAllocator.destroy(self);
}
pub fn decreaseRefCount(self: *LightMapFragment) void {
const prevVal = self.refCount.fetchSub(1, .monotonic);
std.debug.assert(prevVal != 0);
if(prevVal == 1) {
main.globalAllocator.destroy(self);
}
pub fn deferredDeinit(self: *LightMapFragment) void {
main.heap.GarbageCollection.deferredFree(.{.ptr = self, .freeFunction = main.utils.castFunctionSelfToAnyopaque(LightMapFragment.deinit)});
}
pub fn getHeight(self: *LightMapFragment, wx: i32, wy: i32) i32 {
@ -51,7 +44,7 @@ pub const LightMapFragment = struct {
const cacheSize = 1 << 6; // Must be a power of 2!
const cacheMask = cacheSize - 1;
const associativity = 8; // 64MiB MiB Cache size
var cache: Cache(LightMapFragment, cacheSize, associativity, LightMapFragment.decreaseRefCount) = .{};
var cache: Cache(LightMapFragment, cacheSize, associativity, LightMapFragment.deferredDeinit) = .{};
fn cacheInit(pos: MapFragmentPosition) *LightMapFragment {
const mapFragment = main.globalAllocator.create(LightMapFragment);
@ -65,7 +58,6 @@ fn cacheInit(pos: MapFragmentPosition) *LightMapFragment {
mapFragment.startHeight[x << LightMapFragment.mapShift | y] = @max(0, baseHeight +| 16); // Simple heuristic. TODO: Update this value once chunks get generated in the region.
}
}
_ = @atomicRmw(u16, &mapFragment.refCount.raw, .Add, 1, .monotonic);
return mapFragment;
}
@ -73,12 +65,12 @@ pub fn deinit() void {
cache.clear();
}
pub fn getOrGenerateFragmentAndIncreaseRefCount(wx: i32, wy: i32, voxelSize: u31) *LightMapFragment {
pub fn getOrGenerateFragment(wx: i32, wy: i32, voxelSize: u31) *LightMapFragment {
const compare = MapFragmentPosition.init(
wx & ~@as(i32, LightMapFragment.mapMask*voxelSize | voxelSize - 1),
wy & ~@as(i32, LightMapFragment.mapMask*voxelSize | voxelSize - 1),
voxelSize,
);
const result = cache.findOrCreate(compare, cacheInit, LightMapFragment.increaseRefCount);
const result = cache.findOrCreate(compare, cacheInit, null);
return result;
}

View File

@ -226,8 +226,7 @@ const ChunkManager = struct { // MARK: ChunkManager
pub fn run(self: *LightMapLoadTask) void {
defer self.clean();
const map = terrain.LightMap.getOrGenerateFragmentAndIncreaseRefCount(self.pos.wx, self.pos.wy, self.pos.voxelSize);
defer map.decreaseRefCount();
const map = terrain.LightMap.getOrGenerateFragment(self.pos.wx, self.pos.wy, self.pos.voxelSize);
if(self.source) |source| {
if(source.connected.load(.unordered)) main.network.Protocols.lightMapTransmission.sendLightMap(source.conn, map);
} else {