Use MemoryPool for chunk and lighting data.

Temporarily fixes #263
This commit is contained in:
IntegratedQuantum 2024-02-05 21:33:56 +01:00
parent 1cca3a5769
commit 781ca89aff
7 changed files with 79 additions and 33 deletions

View File

@ -98,6 +98,17 @@ fn extractZFromIndex(index: usize) i32 {
return @intCast(index & chunkMask);
}
var memoryPool: std.heap.MemoryPoolAligned(Chunk, @alignOf(Chunk)) = undefined;
var memoryPoolMutex: std.Thread.Mutex = .{};
pub fn init() void {
memoryPool = std.heap.MemoryPoolAligned(Chunk, @alignOf(Chunk)).init(main.globalAllocator.allocator);
}
pub fn deinit() void {
memoryPool.deinit();
}
pub const ChunkPosition = struct {
wx: i32,
wy: i32,
@ -170,7 +181,10 @@ pub const Chunk = struct {
widthShift: u5,
mutex: std.Thread.Mutex,
pub fn init(self: *Chunk, pos: ChunkPosition) void {
pub fn init(pos: ChunkPosition) *Chunk {
memoryPoolMutex.lock();
const self = memoryPool.create() catch unreachable;
memoryPoolMutex.unlock();
std.debug.assert((pos.voxelSize - 1 & pos.voxelSize) == 0);
std.debug.assert(@mod(pos.wx, pos.voxelSize) == 0 and @mod(pos.wy, pos.voxelSize) == 0 and @mod(pos.wz, pos.voxelSize) == 0);
const voxelSizeShift: u5 = @intCast(std.math.log2_int(u31, pos.voxelSize));
@ -182,6 +196,13 @@ pub const Chunk = struct {
.widthShift = voxelSizeShift + chunkShift,
.mutex = std.Thread.Mutex{},
};
return self;
}
pub fn deinit(self: *Chunk) void {
memoryPoolMutex.lock();
memoryPool.destroy(@alignCast(self));
memoryPoolMutex.unlock();
}
pub fn setChanged(self: *Chunk) void {

View File

@ -707,6 +707,9 @@ pub fn main() void {
gui.init();
defer gui.deinit();
chunk.init();
defer chunk.deinit();
rotation.init();
defer rotation.deinit();

View File

@ -743,8 +743,7 @@ pub const Protocols = struct {
std.log.err("Transmission of chunk has invalid size: {}. Input data: {any}, After inflate: {any}", .{_inflatedLen, data, _inflatedData[0.._inflatedLen]});
}
data = _inflatedData;
const ch = main.globalAllocator.create(chunk.Chunk);
ch.init(pos);
const ch = chunk.Chunk.init(pos);
for(&ch.blocks) |*block| {
block.* = Block.fromInt(std.mem.readInt(u32, data[0..4], .big));
data = data[4..];
@ -768,8 +767,7 @@ pub const Protocols = struct {
conn.sendImportant(id, data);
}
fn sendChunkLocally(ch: *chunk.Chunk) void {
const chunkCopy = main.globalAllocator.create(chunk.Chunk);
chunkCopy.init(ch.pos);
const chunkCopy = chunk.Chunk.init(ch.pos);
@memcpy(&chunkCopy.blocks, &ch.blocks);
renderer.mesh_storage.updateChunkMesh(chunkCopy);
}

View File

@ -52,6 +52,7 @@ pub var quadsDrawn: usize = 0;
pub var transparentQuadsDrawn: usize = 0;
pub fn init() void {
lighting.init();
shader = Shader.initAndGetUniforms("assets/cubyz/shaders/chunks/chunk_vertex.vs", "assets/cubyz/shaders/chunks/chunk_fragment.fs", &uniforms);
transparentShader = Shader.initAndGetUniforms("assets/cubyz/shaders/chunks/chunk_vertex.vs", "assets/cubyz/shaders/chunks/transparent_fragment.fs", &transparentUniforms);
@ -73,6 +74,7 @@ pub fn init() void {
}
pub fn deinit() void {
lighting.deinit();
shader.deinit();
transparentShader.deinit();
c.glDeleteVertexArrays(1, &vao);
@ -240,12 +242,12 @@ const PrimitiveMesh = struct {
const z = (wz >> mesh.chunk.voxelSizeShift) & chunk.chunkMask;
const index = chunk.getIndex(x, y, z);
return .{
mesh.lightingData.*[0].data[index].load(.Unordered),
mesh.lightingData.*[1].data[index].load(.Unordered),
mesh.lightingData.*[2].data[index].load(.Unordered),
mesh.lightingData.*[3].data[index].load(.Unordered),
mesh.lightingData.*[4].data[index].load(.Unordered),
mesh.lightingData.*[5].data[index].load(.Unordered),
mesh.lightingData[0].data[index].load(.Unordered),
mesh.lightingData[1].data[index].load(.Unordered),
mesh.lightingData[2].data[index].load(.Unordered),
mesh.lightingData[3].data[index].load(.Unordered),
mesh.lightingData[4].data[index].load(.Unordered),
mesh.lightingData[5].data[index].load(.Unordered),
};
}
@ -422,7 +424,7 @@ pub const ChunkMesh = struct {
pos: chunk.ChunkPosition,
size: i32,
chunk: *chunk.Chunk,
lightingData: *[6]lighting.ChannelChunk,
lightingData: [6]*lighting.ChannelChunk,
opaqueMesh: PrimitiveMesh,
transparentMesh: PrimitiveMesh,
lastNeighborsSameLod: [6]?*const ChunkMesh = [_]?*const ChunkMesh{null} ** 6,
@ -444,20 +446,20 @@ pub const ChunkMesh = struct {
chunkBorders: [6]BoundingRectToNeighborChunk = [1]BoundingRectToNeighborChunk{.{}} ** 6,
pub fn init(self: *ChunkMesh, pos: chunk.ChunkPosition, ch: *chunk.Chunk) void {
const lightingData = main.globalAllocator.create([6]lighting.ChannelChunk);
lightingData[0].init(ch, .sun_red);
lightingData[1].init(ch, .sun_green);
lightingData[2].init(ch, .sun_blue);
lightingData[3].init(ch, .red);
lightingData[4].init(ch, .green);
lightingData[5].init(ch, .blue);
self.* = ChunkMesh{
.pos = pos,
.size = chunk.chunkSize*pos.voxelSize,
.opaqueMesh = .{},
.transparentMesh = .{},
.chunk = ch,
.lightingData = lightingData,
.lightingData = .{
lighting.ChannelChunk.init(ch, .sun_red),
lighting.ChannelChunk.init(ch, .sun_green),
lighting.ChannelChunk.init(ch, .sun_blue),
lighting.ChannelChunk.init(ch, .red),
lighting.ChannelChunk.init(ch, .green),
lighting.ChannelChunk.init(ch, .blue),
},
};
}
@ -465,10 +467,12 @@ pub const ChunkMesh = struct {
std.debug.assert(self.refCount.load(.Monotonic) == 0);
self.opaqueMesh.deinit();
self.transparentMesh.deinit();
self.chunk.deinit();
main.globalAllocator.free(self.currentSorting);
main.globalAllocator.free(self.sortingOutputBuffer);
main.globalAllocator.destroy(self.chunk);
main.globalAllocator.destroy(self.lightingData);
for(self.lightingData) |lightingChunk| {
lightingChunk.deinit();
}
}
pub fn increaseRefCount(self: *ChunkMesh) void {
@ -584,7 +588,7 @@ pub const ChunkMesh = struct {
}
}
self.mutex.unlock();
for(self.lightingData[3..]) |*lightingData| {
for(self.lightingData[3..]) |lightingData| {
lightingData.propagateLights(lightEmittingBlocks.items, true);
}
sunLight: {
@ -604,7 +608,7 @@ pub const ChunkMesh = struct {
}
}
}
for(self.lightingData[0..3]) |*lightingData| {
for(self.lightingData[0..3]) |lightingData| {
lightingData.propagateLights(sunStarters[0..index], true);
}
}
@ -728,11 +732,11 @@ pub const ChunkMesh = struct {
const oldBlock = self.chunk.blocks[chunk.getIndex(x, y, z)];
self.chunk.blocks[chunk.getIndex(x, y, z)] = newBlock;
self.mutex.unlock();
for(self.lightingData[0..]) |*lightingData| {
for(self.lightingData[0..]) |lightingData| {
lightingData.propagateLightsDestructive(&.{.{@intCast(x), @intCast(y), @intCast(z)}});
}
if(newBlock.light() != 0) {
for(self.lightingData[3..]) |*lightingData| {
for(self.lightingData[3..]) |lightingData| {
lightingData.propagateLights(&.{.{@intCast(x), @intCast(y), @intCast(z)}}, false);
}
}

View File

@ -31,17 +31,38 @@ const Channel = enum(u8) {
}
};
var memoryPool: std.heap.MemoryPool(ChannelChunk) = undefined;
var memoryPoolMutex: std.Thread.Mutex = .{};
pub fn init() void {
memoryPool = std.heap.MemoryPool(ChannelChunk).init(main.globalAllocator.allocator);
}
pub fn deinit() void {
memoryPool.deinit();
}
pub const ChannelChunk = struct {
data: [chunk.chunkVolume]Atomic(u8),
mutex: std.Thread.Mutex,
ch: *chunk.Chunk,
channel: Channel,
pub fn init(self: *ChannelChunk, ch: *chunk.Chunk, channel: Channel) void {
pub fn init(ch: *chunk.Chunk, channel: Channel) *ChannelChunk {
memoryPoolMutex.lock();
const self = memoryPool.create() catch unreachable;
memoryPoolMutex.unlock();
self.mutex = .{};
self.ch = ch;
self.channel = channel;
@memset(&self.data, Atomic(u8).init(0));
return self;
}
pub fn deinit(self: *ChannelChunk) void {
memoryPoolMutex.lock();
memoryPool.destroy(self);
memoryPoolMutex.unlock();
}
const Entry = struct {
@ -235,7 +256,7 @@ pub const ChannelChunk = struct {
const otherZ = z+%chunk.Neighbors.relZ[neighbor] & chunk.chunkMask;
const neighborMesh = mesh_storage.getNeighborAndIncreaseRefCount(self.ch.pos, self.ch.pos.voxelSize, @intCast(neighbor)) orelse continue;
defer neighborMesh.decreaseRefCount();
const neighborLightChunk = &neighborMesh.lightingData[@intFromEnum(self.channel)];
const neighborLightChunk = neighborMesh.lightingData[@intFromEnum(self.channel)];
const index = chunk.getIndex(x, y, z);
const neighborIndex = chunk.getIndex(otherX, otherY, otherZ);
var value: u8 = neighborLightChunk.data[neighborIndex].load(.Unordered);
@ -272,7 +293,7 @@ pub const ChannelChunk = struct {
defer if(mesh) |_mesh| _mesh.decreaseRefCount();
var entryList = entries.entries;
defer entryList.deinit(main.globalAllocator);
const channelChunk = if(mesh) |_mesh| &_mesh.lightingData[@intFromEnum(self.channel)] else self;
const channelChunk = if(mesh) |_mesh| _mesh.lightingData[@intFromEnum(self.channel)] else self;
for(entryList.items) |entry| {
const index = chunk.getIndex(entry.x, entry.y, entry.z);
const value = channelChunk.data[index].load(.Unordered);

View File

@ -1022,7 +1022,7 @@ pub const MeshGenerationTask = struct {
}
pub fn clean(self: *MeshGenerationTask) void {
main.globalAllocator.destroy(self.mesh);
self.mesh.deinit();
main.globalAllocator.destroy(self);
}
};

View File

@ -213,8 +213,7 @@ const ChunkManager = struct {
}
fn chunkInitFunctionForCache(pos: ChunkPosition) *Chunk {
const ch = main.globalAllocator.create(Chunk);
ch.init(pos);
const ch = Chunk.init(pos);
ch.generated = true;
// TODO: if(!ChunkIO.loadChunkFromFile(world, this)) {
const caveMap = terrain.CaveMap.CaveMapView.init(ch);
@ -228,7 +227,7 @@ const ChunkManager = struct {
}
fn chunkDeinitFunctionForCache(ch: *Chunk) void {
main.globalAllocator.destroy(ch);
ch.deinit();
// TODO: Store chunk.
}
/// Generates a normal chunk at a given location, or if possible gets it from the cache.