mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-08-03 03:06:55 -04:00
Remove reference counting in terrain generation data structures.
more progress towards #1413
This commit is contained in:
parent
949900f518
commit
77fb637fe3
@ -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, .{});
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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| {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user