diff --git a/src/chunk.zig b/src/chunk.zig index 503bb860..dc3b4a85 100644 --- a/src/chunk.zig +++ b/src/chunk.zig @@ -602,8 +602,7 @@ pub const ServerChunk = struct { // MARK: ServerChunk for(0..2) |dy| { const mapX = mapStartX +% main.server.terrain.SurfaceMap.MapFragment.mapSize*@as(i32, @intCast(dx)); const mapY = mapStartY +% main.server.terrain.SurfaceMap.MapFragment.mapSize*@as(i32, @intCast(dy)); - const map = main.server.terrain.SurfaceMap.getOrGenerateFragmentAndIncreaseRefCount(mapX, mapY, self.super.pos.voxelSize); - defer map.decreaseRefCount(); + const map = main.server.terrain.SurfaceMap.getOrGenerateFragment(mapX, mapY, self.super.pos.voxelSize); if(!map.wasStored.swap(true, .monotonic)) { map.save(null, .{}); } diff --git a/src/renderer/chunk_meshing.zig b/src/renderer/chunk_meshing.zig index c2bfdfd3..e166f3fd 100644 --- a/src/renderer/chunk_meshing.zig +++ b/src/renderer/chunk_meshing.zig @@ -711,7 +711,7 @@ pub const ChunkMesh = struct { // MARK: ChunkMesh return self; } - pub fn deinit(self: *ChunkMesh, _: usize) void { + fn privateDeinit(self: *ChunkMesh, _: usize) void { chunkBuffer.free(self.chunkAllocation); self.opaqueMesh.deinit(); self.transparentMesh.deinit(); @@ -729,6 +729,10 @@ pub const ChunkMesh = struct { // MARK: ChunkMesh mesh_storage.meshMemoryPool.destroy(self); } + pub fn deferredDeinit(self: *ChunkMesh) void { + main.heap.GarbageCollection.deferredFree(.{.ptr = self, .freeFunction = main.utils.castFunctionSelfToAnyopaque(privateDeinit)}); + } + pub fn scheduleLightRefresh(pos: chunk.ChunkPosition) void { LightRefreshTask.schedule(pos); } diff --git a/src/renderer/mesh_storage.zig b/src/renderer/mesh_storage.zig index 6dafd9d8..c3c4dc78 100644 --- a/src/renderer/mesh_storage.zig +++ b/src/renderer/mesh_storage.zig @@ -371,10 +371,7 @@ fn freeOldMeshes(olderPx: i32, olderPy: i32, olderPz: i32, olderRD: u16) void { if(oldMesh) |mesh| { node.finishedMeshing = false; updateHigherLodNodeFinishedMeshing(mesh.pos, false); - main.heap.GarbageCollection.deferredFree(.{ - .ptr = mesh, - .freeFunction = main.utils.castFunctionSelfToAnyopaque(ChunkMesh.deinit), - }); + mesh.deferredDeinit(); } node.isNeighborLod = @splat(false); } @@ -897,7 +894,7 @@ pub const MeshGenerationTask = struct { // MARK: MeshGenerationTask defer main.globalAllocator.destroy(self); const pos = self.mesh.pos; const mesh = ChunkMesh.init(pos, self.mesh); - mesh.generateLightingData() catch mesh.deinit(undefined); + mesh.generateLightingData() catch mesh.deferredDeinit(); } pub fn clean(self: *MeshGenerationTask) void { diff --git a/src/server/command/tp.zig b/src/server/command/tp.zig index 0dce4963..7979cd95 100644 --- a/src/server/command/tp.zig +++ b/src/server/command/tp.zig @@ -27,8 +27,7 @@ pub fn execute(args: []const u8, source: *User) void { var dir: main.chunk.Neighbor = .dirNegX; var stepsRemaining: usize = 1; for(0..spiralLen) |_| { - const map = main.server.terrain.ClimateMap.getOrGenerateFragmentAndIncreaseRefCount(wx, wy); - defer map.decreaseRefCount(); + const map = main.server.terrain.ClimateMap.getOrGenerateFragment(wx, wy); for(0..map.map.len) |_| { const x = main.random.nextIntBounded(u31, &main.seed, map.map.len); const y = main.random.nextIntBounded(u31, &main.seed, map.map.len); diff --git a/src/server/terrain/CaveBiomeMap.zig b/src/server/terrain/CaveBiomeMap.zig index 733c6cf1..f32781d7 100644 --- a/src/server/terrain/CaveBiomeMap.zig +++ b/src/server/terrain/CaveBiomeMap.zig @@ -39,12 +39,12 @@ pub const CaveBiomeMapFragment = struct { // MARK: caveBiomeMapFragment }; } - fn deinit(self: *CaveBiomeMapFragment, _: usize) void { + fn privateDeinit(self: *CaveBiomeMapFragment, _: usize) void { memoryPool.destroy(self); } pub fn deferredDeinit(self: *CaveBiomeMapFragment) void { - main.heap.GarbageCollection.deferredFree(.{.ptr = self, .freeFunction = main.utils.castFunctionSelfToAnyopaque(CaveBiomeMapFragment.deinit)}); + main.heap.GarbageCollection.deferredFree(.{.ptr = self, .freeFunction = main.utils.castFunctionSelfToAnyopaque(privateDeinit)}); } const rotationMatrixShift = 30; @@ -154,10 +154,10 @@ pub const InterpolatableCaveBiomeMapView = struct { // MARK: InterpolatableCaveB var result = InterpolatableCaveBiomeMapView{ .fragments = Array3D(*CaveBiomeMapFragment).init(allocator, caveBiomeFragmentWidth, caveBiomeFragmentWidth, caveBiomeFragmentWidth), .surfaceFragments = [_]*MapFragment{ - SurfaceMap.getOrGenerateFragmentAndIncreaseRefCount(center[0] -% SurfaceMap.MapFragment.mapSize/2*pos.voxelSize, center[1] -% SurfaceMap.MapFragment.mapSize/2*pos.voxelSize, pos.voxelSize), - SurfaceMap.getOrGenerateFragmentAndIncreaseRefCount(center[0] -% SurfaceMap.MapFragment.mapSize/2*pos.voxelSize, center[1] +% SurfaceMap.MapFragment.mapSize/2*pos.voxelSize, pos.voxelSize), - SurfaceMap.getOrGenerateFragmentAndIncreaseRefCount(center[0] +% SurfaceMap.MapFragment.mapSize/2*pos.voxelSize, center[1] -% SurfaceMap.MapFragment.mapSize/2*pos.voxelSize, pos.voxelSize), - SurfaceMap.getOrGenerateFragmentAndIncreaseRefCount(center[0] +% SurfaceMap.MapFragment.mapSize/2*pos.voxelSize, center[1] +% SurfaceMap.MapFragment.mapSize/2*pos.voxelSize, pos.voxelSize), + SurfaceMap.getOrGenerateFragment(center[0] -% SurfaceMap.MapFragment.mapSize/2*pos.voxelSize, center[1] -% SurfaceMap.MapFragment.mapSize/2*pos.voxelSize, pos.voxelSize), + SurfaceMap.getOrGenerateFragment(center[0] -% SurfaceMap.MapFragment.mapSize/2*pos.voxelSize, center[1] +% SurfaceMap.MapFragment.mapSize/2*pos.voxelSize, pos.voxelSize), + SurfaceMap.getOrGenerateFragment(center[0] +% SurfaceMap.MapFragment.mapSize/2*pos.voxelSize, center[1] -% SurfaceMap.MapFragment.mapSize/2*pos.voxelSize, pos.voxelSize), + SurfaceMap.getOrGenerateFragment(center[0] +% SurfaceMap.MapFragment.mapSize/2*pos.voxelSize, center[1] +% SurfaceMap.MapFragment.mapSize/2*pos.voxelSize, pos.voxelSize), }, .pos = pos, .width = width, @@ -182,9 +182,6 @@ pub const InterpolatableCaveBiomeMapView = struct { // MARK: InterpolatableCaveB pub fn deinit(self: InterpolatableCaveBiomeMapView) void { self.fragments.deinit(self.allocator); - for(self.surfaceFragments) |mapFragment| { - mapFragment.decreaseRefCount(); - } } fn rotate231(in: Vec3i) Vec3i { diff --git a/src/server/terrain/CaveMap.zig b/src/server/terrain/CaveMap.zig index 24c86f8d..b9b2a652 100644 --- a/src/server/terrain/CaveMap.zig +++ b/src/server/terrain/CaveMap.zig @@ -21,7 +21,6 @@ pub const CaveMapFragment = struct { // MARK: CaveMapFragment data: [width*width]u64 = undefined, pos: ChunkPosition, voxelShift: u5, - refCount: Atomic(u16) = .init(0), pub fn init(self: *CaveMapFragment, wx: i32, wy: i32, wz: i32, voxelSize: u31) void { self.* = .{ @@ -36,6 +35,14 @@ pub const CaveMapFragment = struct { // MARK: CaveMapFragment @memset(&self.data, std.math.maxInt(u64)); } + fn privateDeinit(self: *CaveMapFragment, _: usize) void { + memoryPool.destroy(self); + } + + pub fn deferredDeinit(self: *CaveMapFragment) void { + main.heap.GarbageCollection.deferredFree(.{.ptr = self, .freeFunction = main.utils.castFunctionSelfToAnyopaque(privateDeinit)}); + } + fn getIndex(x: i32, y: i32) usize { std.debug.assert(x >= 0 and x < width and y >= 0 and y < width); // Coordinates out of range. return @intCast(x*width + y); @@ -50,19 +57,6 @@ pub const CaveMapFragment = struct { // MARK: CaveMapFragment return maskLower | maskUpper; } - pub fn increaseRefCount(self: *CaveMapFragment) void { - const prevVal = self.refCount.fetchAdd(1, .monotonic); - std.debug.assert(prevVal != 0); - } - - pub fn decreaseRefCount(self: *CaveMapFragment) void { - const prevVal = self.refCount.fetchSub(1, .monotonic); - std.debug.assert(prevVal != 0); - if(prevVal == 1) { - memoryPool.destroy(self); - } - } - pub fn addRange(self: *CaveMapFragment, _relX: i32, _relY: i32, _start: i32, _end: i32) void { const relX = _relX >> self.voxelShift; const relY = _relY >> self.voxelShift; @@ -132,30 +126,24 @@ pub const CaveMapView = struct { // MARK: CaveMapView reference: *ServerChunk, fragments: [8]*CaveMapFragment, - pub fn init(chunk: *ServerChunk) CaveMapView { + pub fn findMapsAround(chunk: *ServerChunk) CaveMapView { const pos = chunk.super.pos; const width = chunk.super.width; return CaveMapView{ .reference = chunk, .fragments = [_]*CaveMapFragment{ - getOrGenerateFragmentAndIncreaseRefCount(pos.wx -% width, pos.wy -% width, pos.wz -% width, pos.voxelSize), - getOrGenerateFragmentAndIncreaseRefCount(pos.wx -% width, pos.wy -% width, pos.wz +% width, pos.voxelSize), - getOrGenerateFragmentAndIncreaseRefCount(pos.wx -% width, pos.wy +% width, pos.wz -% width, pos.voxelSize), - getOrGenerateFragmentAndIncreaseRefCount(pos.wx -% width, pos.wy +% width, pos.wz +% width, pos.voxelSize), - getOrGenerateFragmentAndIncreaseRefCount(pos.wx +% width, pos.wy -% width, pos.wz -% width, pos.voxelSize), - getOrGenerateFragmentAndIncreaseRefCount(pos.wx +% width, pos.wy -% width, pos.wz +% width, pos.voxelSize), - getOrGenerateFragmentAndIncreaseRefCount(pos.wx +% width, pos.wy +% width, pos.wz -% width, pos.voxelSize), - getOrGenerateFragmentAndIncreaseRefCount(pos.wx +% width, pos.wy +% width, pos.wz +% width, pos.voxelSize), + getOrGenerateFragment(pos.wx -% width, pos.wy -% width, pos.wz -% width, pos.voxelSize), + getOrGenerateFragment(pos.wx -% width, pos.wy -% width, pos.wz +% width, pos.voxelSize), + getOrGenerateFragment(pos.wx -% width, pos.wy +% width, pos.wz -% width, pos.voxelSize), + getOrGenerateFragment(pos.wx -% width, pos.wy +% width, pos.wz +% width, pos.voxelSize), + getOrGenerateFragment(pos.wx +% width, pos.wy -% width, pos.wz -% width, pos.voxelSize), + getOrGenerateFragment(pos.wx +% width, pos.wy -% width, pos.wz +% width, pos.voxelSize), + getOrGenerateFragment(pos.wx +% width, pos.wy +% width, pos.wz -% width, pos.voxelSize), + getOrGenerateFragment(pos.wx +% width, pos.wy +% width, pos.wz +% width, pos.voxelSize), }, }; } - pub fn deinit(self: CaveMapView) void { - for(self.fragments) |mapFragment| { - mapFragment.decreaseRefCount(); - } - } - pub fn isSolid(self: CaveMapView, relX: i32, relY: i32, relZ: i32) bool { const wx = relX +% self.reference.super.pos.wx; const wy = relY +% self.reference.super.pos.wy; @@ -289,7 +277,7 @@ pub const CaveMapView = struct { // MARK: CaveMapView const cacheSize = 1 << 11; // Must be a power of 2! const cacheMask = cacheSize - 1; const associativity = 8; // 512 MiB Cache size -var cache: Cache(CaveMapFragment, cacheSize, associativity, CaveMapFragment.decreaseRefCount) = .{}; +var cache: Cache(CaveMapFragment, cacheSize, associativity, CaveMapFragment.deferredDeinit) = .{}; var profile: TerrainGenerationProfile = undefined; var memoryPool: main.heap.MemoryPool(CaveMapFragment) = undefined; @@ -300,7 +288,6 @@ fn cacheInit(pos: ChunkPosition) *CaveMapFragment { for(profile.caveGenerators) |generator| { generator.generate(mapFragment, profile.seed ^ generator.generatorSeed); } - _ = @atomicRmw(u16, &mapFragment.refCount.raw, .Add, 1, .monotonic); return mapFragment; } @@ -325,13 +312,13 @@ pub fn deinit() void { cache.clear(); } -fn getOrGenerateFragmentAndIncreaseRefCount(wx: i32, wy: i32, wz: i32, voxelSize: u31) *CaveMapFragment { +fn getOrGenerateFragment(wx: i32, wy: i32, wz: i32, voxelSize: u31) *CaveMapFragment { const compare = ChunkPosition{ .wx = wx & ~@as(i32, CaveMapFragment.widthMask*voxelSize | voxelSize - 1), .wy = wy & ~@as(i32, CaveMapFragment.widthMask*voxelSize | voxelSize - 1), .wz = wz & ~@as(i32, CaveMapFragment.heightMask*voxelSize | voxelSize - 1), .voxelSize = voxelSize, }; - const result = cache.findOrCreate(compare, cacheInit, CaveMapFragment.increaseRefCount); + const result = cache.findOrCreate(compare, cacheInit, null); return result; } diff --git a/src/server/terrain/ClimateMap.zig b/src/server/terrain/ClimateMap.zig index 6b9bcf86..2ee9441f 100644 --- a/src/server/terrain/ClimateMap.zig +++ b/src/server/terrain/ClimateMap.zig @@ -48,30 +48,23 @@ pub const ClimateMapFragment = struct { pos: ClimateMapFragmentPosition, map: [mapEntrysSize][mapEntrysSize]BiomeSample = undefined, - refCount: Atomic(u16) = .init(0), - pub fn init(self: *ClimateMapFragment, wx: i32, wy: i32) void { self.* = .{ .pos = .{.wx = wx, .wy = wy}, }; } + fn privateDeinit(self: *ClimateMapFragment, _: usize) void { + memoryPool.destroy(self); + } + + pub fn deferredDeinit(self: *ClimateMapFragment) void { + main.heap.GarbageCollection.deferredFree(.{.ptr = self, .freeFunction = main.utils.castFunctionSelfToAnyopaque(privateDeinit)}); + } + pub fn hashCode(wx: i32, wy: i32) u32 { return @bitCast((wx >> mapShift)*%33 + (wy >> mapShift)); } - - pub fn increaseRefCount(self: *ClimateMapFragment) void { - const prevVal = self.refCount.fetchAdd(1, .monotonic); - std.debug.assert(prevVal != 0); - } - - pub fn decreaseRefCount(self: *ClimateMapFragment) void { - const prevVal = self.refCount.fetchSub(1, .monotonic); - std.debug.assert(prevVal != 0); - if(prevVal == 1) { - memoryPool.destroy(self); - } - } }; /// Generates the climate(aka Biome) map, which is a rough representation of the world. @@ -102,7 +95,7 @@ pub const ClimateMapGenerator = struct { const cacheSize = 1 << 5; // Must be a power of 2! const cacheMask = cacheSize - 1; const associativity = 8; // ~400 MiB -var cache: Cache(ClimateMapFragment, cacheSize, associativity, ClimateMapFragment.decreaseRefCount) = .{}; +var cache: Cache(ClimateMapFragment, cacheSize, associativity, ClimateMapFragment.deferredDeinit) = .{}; var profile: TerrainGenerationProfile = undefined; var memoryPool: main.heap.MemoryPool(ClimateMapFragment) = undefined; @@ -124,7 +117,6 @@ fn cacheInit(pos: ClimateMapFragmentPosition) *ClimateMapFragment { const mapFragment = memoryPool.create(); mapFragment.init(pos.wx, pos.wy); profile.climateGenerator.generateMapFragment(mapFragment, profile.seed); - _ = @atomicRmw(u16, &mapFragment.refCount.raw, .Add, 1, .monotonic); return mapFragment; } @@ -136,9 +128,9 @@ pub fn deinit() void { cache.clear(); } -pub fn getOrGenerateFragmentAndIncreaseRefCount(wx: i32, wy: i32) *ClimateMapFragment { +pub fn getOrGenerateFragment(wx: i32, wy: i32) *ClimateMapFragment { const compare = ClimateMapFragmentPosition{.wx = wx, .wy = wy}; - const result = cache.findOrCreate(compare, cacheInit, ClimateMapFragment.increaseRefCount); + const result = cache.findOrCreate(compare, cacheInit, null); return result; } @@ -152,8 +144,7 @@ pub fn getBiomeMap(allocator: NeverFailingAllocator, wx: i32, wy: i32, width: u3 while(wxEnd -% x >= 0) : (x +%= ClimateMapFragment.mapSize) { var y = wzStart; while(wzEnd -% y >= 0) : (y +%= ClimateMapFragment.mapSize) { - const mapPiece = getOrGenerateFragmentAndIncreaseRefCount(x, y); - defer mapPiece.decreaseRefCount(); + const mapPiece = getOrGenerateFragment(x, y); // Offset of the indices in the result map: const xOffset = (x -% wx) >> MapFragment.biomeShift; const yOffset = (y -% wy) >> MapFragment.biomeShift; diff --git a/src/server/terrain/LightMap.zig b/src/server/terrain/LightMap.zig index a0e57546..4a9fe9f2 100644 --- a/src/server/terrain/LightMap.zig +++ b/src/server/terrain/LightMap.zig @@ -26,12 +26,12 @@ pub const LightMapFragment = struct { }; } - fn deinit(self: *const LightMapFragment, _: usize) void { + fn privateDeinit(self: *const LightMapFragment, _: usize) void { main.globalAllocator.destroy(self); } pub fn deferredDeinit(self: *LightMapFragment) void { - main.heap.GarbageCollection.deferredFree(.{.ptr = self, .freeFunction = main.utils.castFunctionSelfToAnyopaque(LightMapFragment.deinit)}); + main.heap.GarbageCollection.deferredFree(.{.ptr = self, .freeFunction = main.utils.castFunctionSelfToAnyopaque(privateDeinit)}); } pub fn getHeight(self: *LightMapFragment, wx: i32, wy: i32) i32 { @@ -49,8 +49,7 @@ var cache: Cache(LightMapFragment, cacheSize, associativity, LightMapFragment.de fn cacheInit(pos: MapFragmentPosition) *LightMapFragment { const mapFragment = main.globalAllocator.create(LightMapFragment); mapFragment.init(pos.wx, pos.wy, pos.voxelSize); - const surfaceMap = terrain.SurfaceMap.getOrGenerateFragmentAndIncreaseRefCount(pos.wx, pos.wy, pos.voxelSize); - defer surfaceMap.decreaseRefCount(); + const surfaceMap = terrain.SurfaceMap.getOrGenerateFragment(pos.wx, pos.wy, pos.voxelSize); comptime std.debug.assert(LightMapFragment.mapSize == terrain.SurfaceMap.MapFragment.mapSize); for(0..LightMapFragment.mapSize) |x| { for(0..LightMapFragment.mapSize) |y| { diff --git a/src/server/terrain/StructureMap.zig b/src/server/terrain/StructureMap.zig index e26a139b..94034ac0 100644 --- a/src/server/terrain/StructureMap.zig +++ b/src/server/terrain/StructureMap.zig @@ -40,7 +40,6 @@ pub const StructureMapFragment = struct { pos: ChunkPosition, voxelShift: u5, - refCount: Atomic(u16) = .init(0), arena: main.heap.NeverFailingArenaAllocator, allocator: main.heap.NeverFailingAllocator, @@ -68,11 +67,15 @@ pub const StructureMapFragment = struct { @memset(self.tempData.lists, .{}); } - pub fn deinit(self: *StructureMapFragment) void { + fn privateDeinit(self: *StructureMapFragment, _: usize) void { self.arena.deinit(); memoryPool.destroy(self); } + pub fn deferredDeinit(self: *StructureMapFragment) void { + main.heap.GarbageCollection.deferredFree(.{.ptr = self, .freeFunction = main.utils.castFunctionSelfToAnyopaque(privateDeinit)}); + } + fn finishGeneration(self: *StructureMapFragment) void { for(0..self.data.len) |i| { std.sort.insertion(Structure, self.tempData.lists[i].items, {}, Structure.lessThan); @@ -93,19 +96,6 @@ pub const StructureMapFragment = struct { return @intCast(((x >> main.chunk.chunkShift + self.voxelShift)*chunkedSize + (y >> main.chunk.chunkShift + self.voxelShift))*chunkedSize + (z >> main.chunk.chunkShift + self.voxelShift)); } - pub fn increaseRefCount(self: *StructureMapFragment) void { - const prevVal = self.refCount.fetchAdd(1, .monotonic); - std.debug.assert(prevVal != 0); - } - - pub fn decreaseRefCount(self: *StructureMapFragment) void { - const prevVal = self.refCount.fetchSub(1, .monotonic); - std.debug.assert(prevVal != 0); - if(prevVal == 1) { - self.deinit(); - } - } - pub fn generateStructuresInChunk(self: *const StructureMapFragment, chunk: *ServerChunk, caveMap: terrain.CaveMap.CaveMapView, biomeMap: terrain.CaveBiomeMap.CaveBiomeMapView) void { const index = self.getIndex(chunk.super.pos.wx - self.pos.wx, chunk.super.pos.wy - self.pos.wy, chunk.super.pos.wz - self.pos.wz); for(self.data[index]) |structure| { @@ -175,7 +165,7 @@ pub const StructureMapGenerator = struct { const cacheSize = 1 << 10; // Must be a power of 2! const cacheMask = cacheSize - 1; const associativity = 8; -var cache: Cache(StructureMapFragment, cacheSize, associativity, StructureMapFragment.decreaseRefCount) = .{}; +var cache: Cache(StructureMapFragment, cacheSize, associativity, StructureMapFragment.deferredDeinit) = .{}; var profile: TerrainGenerationProfile = undefined; var memoryPool: main.heap.MemoryPool(StructureMapFragment) = undefined; @@ -187,7 +177,6 @@ fn cacheInit(pos: ChunkPosition) *StructureMapFragment { generator.generate(mapFragment, profile.seed ^ generator.generatorSeed); } mapFragment.finishGeneration(); - _ = @atomicRmw(u16, &mapFragment.refCount.raw, .Add, 1, .monotonic); return mapFragment; } @@ -212,13 +201,13 @@ pub fn deinit() void { cache.clear(); } -pub fn getOrGenerateFragmentAndIncreaseRefCount(wx: i32, wy: i32, wz: i32, voxelSize: u31) *StructureMapFragment { +pub fn getOrGenerateFragment(wx: i32, wy: i32, wz: i32, voxelSize: u31) *StructureMapFragment { const compare = ChunkPosition{ .wx = wx & ~@as(i32, StructureMapFragment.sizeMask*voxelSize | voxelSize - 1), .wy = wy & ~@as(i32, StructureMapFragment.sizeMask*voxelSize | voxelSize - 1), .wz = wz & ~@as(i32, StructureMapFragment.sizeMask*voxelSize | voxelSize - 1), .voxelSize = voxelSize, }; - const result = cache.findOrCreate(compare, cacheInit, StructureMapFragment.increaseRefCount); + const result = cache.findOrCreate(compare, cacheInit, null); return result; } diff --git a/src/server/terrain/SurfaceMap.zig b/src/server/terrain/SurfaceMap.zig index f7480c5b..ae78e4e3 100644 --- a/src/server/terrain/SurfaceMap.zig +++ b/src/server/terrain/SurfaceMap.zig @@ -74,25 +74,18 @@ pub const MapFragment = struct { // MARK: MapFragment wasStored: Atomic(bool) = .init(false), - refCount: Atomic(u16) = .init(0), - pub fn init(self: *MapFragment, wx: i32, wy: i32, voxelSize: u31) void { self.* = .{ .pos = MapFragmentPosition.init(wx, wy, voxelSize), }; } - pub fn increaseRefCount(self: *MapFragment) void { - const prevVal = self.refCount.fetchAdd(1, .monotonic); - std.debug.assert(prevVal != 0); + fn privateDeinit(self: *MapFragment, _: usize) void { + memoryPool.destroy(self); } - pub fn decreaseRefCount(self: *MapFragment) void { - const prevVal = self.refCount.fetchSub(1, .monotonic); - std.debug.assert(prevVal != 0); - if(prevVal == 1) { - memoryPool.destroy(self); - } + pub fn deferredDeinit(self: *MapFragment) void { + main.heap.GarbageCollection.deferredFree(.{.ptr = self, .freeFunction = main.utils.castFunctionSelfToAnyopaque(privateDeinit)}); } pub fn getBiome(self: *MapFragment, wx: i32, wy: i32) *const Biome { @@ -254,7 +247,7 @@ pub const MapGenerator = struct { const cacheSize = 1 << 6; // Must be a power of 2! const cacheMask = cacheSize - 1; const associativity = 8; // ~400MiB MiB Cache size -var cache: Cache(MapFragment, cacheSize, associativity, MapFragment.decreaseRefCount) = .{}; +var cache: Cache(MapFragment, cacheSize, associativity, MapFragment.deferredDeinit) = .{}; var profile: TerrainGenerationProfile = undefined; var memoryPool: main.heap.MemoryPool(MapFragment) = undefined; @@ -278,7 +271,6 @@ fn cacheInit(pos: MapFragmentPosition) *MapFragment { _ = mapFragment.load(main.server.world.?.biomePalette, null) catch { profile.mapFragmentGenerator.generateMapFragment(mapFragment, profile.seed); }; - _ = @atomicRmw(u16, &mapFragment.refCount.raw, .Add, 1, .monotonic); return mapFragment; } @@ -577,7 +569,6 @@ pub fn regenerateLOD(worldName: []const u8) !void { // MARK: regenerateLOD() mapFragment.save(&originalHeightMap, neighborInfo); // Store the interpolated map // Generate LODs var cur = mapFragment; - defer if(cur.pos.voxelSize != 1) cur.decreaseRefCount(); while(cur.pos.voxelSizeShift < main.settings.highestSupportedLod) { var nextPos = cur.pos; nextPos.voxelSize *= 2; @@ -585,7 +576,7 @@ pub fn regenerateLOD(worldName: []const u8) !void { // MARK: regenerateLOD() const nextMask = ~@as(i32, nextPos.voxelSize*MapFragment.mapSize - 1); nextPos.wx &= nextMask; nextPos.wy &= nextMask; - const next = getOrGenerateFragmentAndIncreaseRefCount(nextPos.wx, nextPos.wy, nextPos.voxelSize); + const next = getOrGenerateFragment(nextPos.wx, nextPos.wy, nextPos.voxelSize); const offSetX: usize = @intCast((cur.pos.wx -% nextPos.wx) >> nextPos.voxelSizeShift); const offSetY: usize = @intCast((cur.pos.wy -% nextPos.wy) >> nextPos.voxelSizeShift); for(0..MapFragment.mapSize/2) |x| { @@ -627,7 +618,6 @@ pub fn regenerateLOD(worldName: []const u8) !void { // MARK: regenerateLOD() } next.save(null, .{}); next.wasStored.store(true, .monotonic); - if(cur.pos.voxelSize != 1) cur.decreaseRefCount(); cur = next; } } @@ -643,12 +633,12 @@ pub fn deinit() void { } /// Call deinit on the result. -pub fn getOrGenerateFragmentAndIncreaseRefCount(wx: i32, wy: i32, voxelSize: u31) *MapFragment { +pub fn getOrGenerateFragment(wx: i32, wy: i32, voxelSize: u31) *MapFragment { const compare = MapFragmentPosition.init( wx & ~@as(i32, MapFragment.mapMask*voxelSize | voxelSize - 1), wy & ~@as(i32, MapFragment.mapMask*voxelSize | voxelSize - 1), voxelSize, ); - const result = cache.findOrCreate(compare, cacheInit, MapFragment.increaseRefCount); + const result = cache.findOrCreate(compare, cacheInit, null); return result; } diff --git a/src/server/terrain/chunkgen/StructureGenerator.zig b/src/server/terrain/chunkgen/StructureGenerator.zig index 5956dcfc..a66273be 100644 --- a/src/server/terrain/chunkgen/StructureGenerator.zig +++ b/src/server/terrain/chunkgen/StructureGenerator.zig @@ -26,7 +26,6 @@ pub fn init(parameters: ZonElement) void { pub fn deinit() void {} pub fn generate(_: u64, chunk: *main.chunk.ServerChunk, caveMap: CaveMap.CaveMapView, biomeMap: CaveBiomeMap.CaveBiomeMapView) void { - const structureMap = terrain.StructureMap.getOrGenerateFragmentAndIncreaseRefCount(chunk.super.pos.wx, chunk.super.pos.wy, chunk.super.pos.wz, chunk.super.pos.voxelSize); - defer structureMap.decreaseRefCount(); + const structureMap = terrain.StructureMap.getOrGenerateFragment(chunk.super.pos.wx, chunk.super.pos.wy, chunk.super.pos.wz, chunk.super.pos.voxelSize); structureMap.generateStructuresInChunk(chunk, caveMap, biomeMap); } diff --git a/src/server/world.zig b/src/server/world.zig index 029a1f34..5878e0fc 100644 --- a/src/server/world.zig +++ b/src/server/world.zig @@ -321,8 +321,7 @@ const ChunkManager = struct { // MARK: ChunkManager return ch; } ch.generated = true; - const caveMap = terrain.CaveMap.CaveMapView.init(ch); - defer caveMap.deinit(); + const caveMap = terrain.CaveMap.CaveMapView.findMapsAround(ch); const biomeMap = terrain.CaveBiomeMap.CaveBiomeMapView.init(main.stackAllocator, ch.super.pos, ch.super.width, 32); defer biomeMap.deinit(); for(server.world.?.chunkManager.terrainGenerationProfile.generators) |generator| { @@ -721,8 +720,7 @@ pub const ServerWorld = struct { // MARK: ServerWorld for(0..2) |dy| { const mapX = mapStartX +% main.server.terrain.SurfaceMap.MapFragment.mapSize*@as(i32, @intCast(dx)); const mapY = mapStartY +% main.server.terrain.SurfaceMap.MapFragment.mapSize*@as(i32, @intCast(dy)); - const map = main.server.terrain.SurfaceMap.getOrGenerateFragmentAndIncreaseRefCount(mapX, mapY, ch.super.pos.voxelSize); - defer map.decreaseRefCount(); + const map = main.server.terrain.SurfaceMap.getOrGenerateFragment(mapX, mapY, ch.super.pos.voxelSize); if(!map.wasStored.swap(true, .monotonic)) { map.save(null, .{}); } @@ -855,8 +853,7 @@ pub const ServerWorld = struct { // MARK: ServerWorld var dir: main.chunk.Neighbor = .dirNegX; var stepsRemaining: usize = 1; for(0..spiralLen) |_| { - const map = main.server.terrain.ClimateMap.getOrGenerateFragmentAndIncreaseRefCount(wx, wy); - defer map.decreaseRefCount(); + const map = main.server.terrain.ClimateMap.getOrGenerateFragment(wx, wy); for(0..map.map.len) |_| { const x = main.random.nextIntBounded(u31, &main.seed, map.map.len); const y = main.random.nextIntBounded(u31, &main.seed, map.map.len); @@ -895,8 +892,7 @@ pub const ServerWorld = struct { // MARK: ServerWorld } std.log.err("Found no valid spawn location", .{}); } - const map = terrain.SurfaceMap.getOrGenerateFragmentAndIncreaseRefCount(self.spawn[0], self.spawn[1], 1); - defer map.decreaseRefCount(); + const map = terrain.SurfaceMap.getOrGenerateFragment(self.spawn[0], self.spawn[1], 1); self.spawn[2] = map.getHeight(self.spawn[0], self.spawn[1]) + 1; } const newBiomeCheckSum: i64 = @bitCast(terrain.biomes.getBiomeCheckSum(self.seed)); @@ -1038,8 +1034,7 @@ pub const ServerWorld = struct { // MARK: ServerWorld } fn isValidSpawnLocation(_: *ServerWorld, wx: i32, wy: i32) bool { - const map = terrain.SurfaceMap.getOrGenerateFragmentAndIncreaseRefCount(wx, wy, 1); - defer map.decreaseRefCount(); + const map = terrain.SurfaceMap.getOrGenerateFragment(wx, wy, 1); return map.getBiome(wx, wy).isValidPlayerSpawn; }