mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-09-08 03:29:48 -04:00
Use a RwLock for the lighting data to allow meshing to lock it in a wider scope.
Fixes #319
This commit is contained in:
parent
86e08b9f8a
commit
413372a321
@ -233,9 +233,15 @@ const PrimitiveMesh = struct {
|
|||||||
@memcpy(completeList[i..][0..neighborFaces.items.len], neighborFaces.items);
|
@memcpy(completeList[i..][0..neighborFaces.items.len], neighborFaces.items);
|
||||||
i += neighborFaces.items.len;
|
i += neighborFaces.items.len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parent.lightingData[0].lock.lockShared();
|
||||||
|
parent.lightingData[1].lock.lockShared();
|
||||||
for(completeList) |*face| {
|
for(completeList) |*face| {
|
||||||
face.light = getLight(parent, .{face.position.x, face.position.y, face.position.z}, face.blockAndQuad.quadIndex);
|
face.light = getLight(parent, .{face.position.x, face.position.y, face.position.z}, face.blockAndQuad.quadIndex);
|
||||||
}
|
}
|
||||||
|
parent.lightingData[1].lock.unlockShared();
|
||||||
|
parent.lightingData[0].lock.unlockShared();
|
||||||
|
|
||||||
self.mutex.lock();
|
self.mutex.lock();
|
||||||
const oldList = self.completeList;
|
const oldList = self.completeList;
|
||||||
self.completeList = completeList;
|
self.completeList = completeList;
|
||||||
@ -254,7 +260,7 @@ const PrimitiveMesh = struct {
|
|||||||
const x = (wx >> mesh.chunk.voxelSizeShift) & chunk.chunkMask;
|
const x = (wx >> mesh.chunk.voxelSizeShift) & chunk.chunkMask;
|
||||||
const y = (wy >> mesh.chunk.voxelSizeShift) & chunk.chunkMask;
|
const y = (wy >> mesh.chunk.voxelSizeShift) & chunk.chunkMask;
|
||||||
const z = (wz >> mesh.chunk.voxelSizeShift) & chunk.chunkMask;
|
const z = (wz >> mesh.chunk.voxelSizeShift) & chunk.chunkMask;
|
||||||
return mesh.lightingData[1].getValue(x, y, z) ++ mesh.lightingData[0].getValue(x, y, z);
|
return mesh.lightingData[1].getValueHoldingTheLock(x, y, z) ++ mesh.lightingData[0].getValueHoldingTheLock(x, y, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getLightAt(parent: *ChunkMesh, x: i32, y: i32, z: i32) [6]u8 {
|
fn getLightAt(parent: *ChunkMesh, x: i32, y: i32, z: i32) [6]u8 {
|
||||||
@ -266,6 +272,10 @@ const PrimitiveMesh = struct {
|
|||||||
}
|
}
|
||||||
const neighborMesh = mesh_storage.getMeshAndIncreaseRefCount(.{.wx = wx, .wy = wy, .wz = wz, .voxelSize = parent.pos.voxelSize}) orelse return .{0, 0, 0, 0, 0, 0};
|
const neighborMesh = mesh_storage.getMeshAndIncreaseRefCount(.{.wx = wx, .wy = wy, .wz = wz, .voxelSize = parent.pos.voxelSize}) orelse return .{0, 0, 0, 0, 0, 0};
|
||||||
defer neighborMesh.decreaseRefCount();
|
defer neighborMesh.decreaseRefCount();
|
||||||
|
neighborMesh.lightingData[0].lock.lockShared();
|
||||||
|
defer neighborMesh.lightingData[0].lock.unlockShared();
|
||||||
|
neighborMesh.lightingData[1].lock.lockShared();
|
||||||
|
defer neighborMesh.lightingData[1].lock.unlockShared();
|
||||||
return getValues(neighborMesh, wx, wy, wz);
|
return getValues(neighborMesh, wx, wy, wz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ pub const ChannelChunk = struct {
|
|||||||
paletteOccupancy: []u32,
|
paletteOccupancy: []u32,
|
||||||
paletteLength: u32,
|
paletteLength: u32,
|
||||||
activePaletteEntries: u32,
|
activePaletteEntries: u32,
|
||||||
mutex: std.Thread.Mutex,
|
lock: std.Thread.RwLock,
|
||||||
ch: *chunk.Chunk,
|
ch: *chunk.Chunk,
|
||||||
isSun: bool,
|
isSun: bool,
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ pub const ChannelChunk = struct {
|
|||||||
memoryPoolMutex.lock();
|
memoryPoolMutex.lock();
|
||||||
const self = memoryPool.create() catch unreachable;
|
const self = memoryPool.create() catch unreachable;
|
||||||
memoryPoolMutex.unlock();
|
memoryPoolMutex.unlock();
|
||||||
self.mutex = .{};
|
self.lock = .{};
|
||||||
self.ch = ch;
|
self.ch = ch;
|
||||||
self.isSun = isSun;
|
self.isSun = isSun;
|
||||||
self.data = .{};
|
self.data = .{};
|
||||||
@ -83,20 +83,17 @@ pub const ChannelChunk = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
fn getValueInternal(self: *ChannelChunk, i: usize) [3]u8 {
|
fn getValueInternal(self: *ChannelChunk, i: usize) [3]u8 {
|
||||||
std.debug.assert(!self.mutex.tryLock());
|
|
||||||
return self.palette[self.data.getValue(i)];
|
return self.palette[self.data.getValue(i)];
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getValue(self: *ChannelChunk, x: i32, y: i32, z: i32) [3]u8 {
|
pub fn getValueHoldingTheLock(self: *ChannelChunk, x: i32, y: i32, z: i32) [3]u8 {
|
||||||
const index = chunk.getIndex(x, y, z);
|
const index = chunk.getIndex(x, y, z);
|
||||||
self.mutex.lock(); // TODO: Locking a mutex this often can be quite slow.
|
|
||||||
defer self.mutex.unlock();
|
|
||||||
return self.getValueInternal(index);
|
return self.getValueInternal(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setValueInternal(self: *ChannelChunk, i: usize, val: [3]u8) void {
|
fn setValueInternal(self: *ChannelChunk, i: usize, val: [3]u8) void {
|
||||||
std.debug.assert(self.paletteLength <= self.palette.len);
|
std.debug.assert(self.paletteLength <= self.palette.len);
|
||||||
std.debug.assert(!self.mutex.tryLock());
|
std.debug.assert(!self.lock.tryLock());
|
||||||
var paletteIndex: u32 = 0;
|
var paletteIndex: u32 = 0;
|
||||||
while(paletteIndex < self.paletteLength) : (paletteIndex += 1) { // TODO: There got to be a faster way to do this. Either using SIMD or using a cache or hashmap.
|
while(paletteIndex < self.paletteLength) : (paletteIndex += 1) { // TODO: There got to be a faster way to do this. Either using SIMD or using a cache or hashmap.
|
||||||
if(std.meta.eql(self.palette[paletteIndex], val)) {
|
if(std.meta.eql(self.palette[paletteIndex], val)) {
|
||||||
@ -128,7 +125,7 @@ pub const ChannelChunk = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn optimizeLayout(self: *ChannelChunk) void {
|
fn optimizeLayout(self: *ChannelChunk) void {
|
||||||
std.debug.assert(!self.mutex.tryLock());
|
std.debug.assert(!self.lock.tryLock());
|
||||||
if(std.math.log2_int_ceil(usize, self.palette.len) == std.math.log2_int_ceil(usize, self.activePaletteEntries)) return;
|
if(std.math.log2_int_ceil(usize, self.palette.len) == std.math.log2_int_ceil(usize, self.activePaletteEntries)) return;
|
||||||
|
|
||||||
var newData = main.utils.DynamicPackedIntArray(chunk.chunkVolume).initCapacity(main.globalAllocator, @intCast(std.math.log2_int_ceil(u32, self.activePaletteEntries)));
|
var newData = main.utils.DynamicPackedIntArray(chunk.chunkVolume).initCapacity(main.globalAllocator, @intCast(std.math.log2_int_ceil(u32, self.activePaletteEntries)));
|
||||||
@ -197,7 +194,7 @@ pub const ChannelChunk = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.mutex.lock();
|
self.lock.lock();
|
||||||
while(lightQueue.dequeue()) |entry| {
|
while(lightQueue.dequeue()) |entry| {
|
||||||
const index = chunk.getIndex(entry.x, entry.y, entry.z);
|
const index = chunk.getIndex(entry.x, entry.y, entry.z);
|
||||||
const oldValue: [3]u8 = self.getValueInternal(index);
|
const oldValue: [3]u8 = self.getValueInternal(index);
|
||||||
@ -231,7 +228,7 @@ pub const ChannelChunk = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.optimizeLayout();
|
self.optimizeLayout();
|
||||||
self.mutex.unlock();
|
self.lock.unlock();
|
||||||
if(mesh_storage.getMeshAndIncreaseRefCount(self.ch.pos)) |mesh| {
|
if(mesh_storage.getMeshAndIncreaseRefCount(self.ch.pos)) |mesh| {
|
||||||
mesh.scheduleLightRefreshAndDecreaseRefCount();
|
mesh.scheduleLightRefreshAndDecreaseRefCount();
|
||||||
}
|
}
|
||||||
@ -254,7 +251,7 @@ pub const ChannelChunk = struct {
|
|||||||
}
|
}
|
||||||
var isFirstIteration: bool = isFirstBlock;
|
var isFirstIteration: bool = isFirstBlock;
|
||||||
|
|
||||||
self.mutex.lock();
|
self.lock.lock();
|
||||||
while(lightQueue.dequeue()) |entry| {
|
while(lightQueue.dequeue()) |entry| {
|
||||||
const index = chunk.getIndex(entry.x, entry.y, entry.z);
|
const index = chunk.getIndex(entry.x, entry.y, entry.z);
|
||||||
const oldValue: [3]u8 = self.getValueInternal(index);
|
const oldValue: [3]u8 = self.getValueInternal(index);
|
||||||
@ -309,7 +306,7 @@ pub const ChannelChunk = struct {
|
|||||||
lightQueue.enqueue(result);
|
lightQueue.enqueue(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.mutex.unlock();
|
self.lock.unlock();
|
||||||
if(mesh_storage.getMeshAndIncreaseRefCount(self.ch.pos)) |mesh| {
|
if(mesh_storage.getMeshAndIncreaseRefCount(self.ch.pos)) |mesh| {
|
||||||
mesh.scheduleLightRefreshAndDecreaseRefCount();
|
mesh.scheduleLightRefreshAndDecreaseRefCount();
|
||||||
}
|
}
|
||||||
@ -388,8 +385,8 @@ pub const ChannelChunk = struct {
|
|||||||
const neighborMesh = mesh_storage.getNeighborAndIncreaseRefCount(self.ch.pos, self.ch.pos.voxelSize, @intCast(neighbor)) orelse continue;
|
const neighborMesh = mesh_storage.getNeighborAndIncreaseRefCount(self.ch.pos, self.ch.pos.voxelSize, @intCast(neighbor)) orelse continue;
|
||||||
defer neighborMesh.decreaseRefCount();
|
defer neighborMesh.decreaseRefCount();
|
||||||
const neighborLightChunk = neighborMesh.lightingData[@intFromBool(self.isSun)];
|
const neighborLightChunk = neighborMesh.lightingData[@intFromBool(self.isSun)];
|
||||||
neighborLightChunk.mutex.lock();
|
neighborLightChunk.lock.lockShared();
|
||||||
defer neighborLightChunk.mutex.unlock();
|
defer neighborLightChunk.lock.unlockShared();
|
||||||
const index = chunk.getIndex(x, y, z);
|
const index = chunk.getIndex(x, y, z);
|
||||||
const neighborIndex = chunk.getIndex(otherX, otherY, otherZ);
|
const neighborIndex = chunk.getIndex(otherX, otherY, otherZ);
|
||||||
var value: [3]u8 = neighborLightChunk.getValueInternal(neighborIndex);
|
var value: [3]u8 = neighborLightChunk.getValueInternal(neighborIndex);
|
||||||
@ -412,12 +409,12 @@ pub const ChannelChunk = struct {
|
|||||||
pub fn propagateLightsDestructive(self: *ChannelChunk, lights: []const [3]u8) void {
|
pub fn propagateLightsDestructive(self: *ChannelChunk, lights: []const [3]u8) void {
|
||||||
var lightQueue = main.utils.CircularBufferQueue(Entry).init(main.stackAllocator, 1 << 12);
|
var lightQueue = main.utils.CircularBufferQueue(Entry).init(main.stackAllocator, 1 << 12);
|
||||||
defer lightQueue.deinit();
|
defer lightQueue.deinit();
|
||||||
self.mutex.lock();
|
self.lock.lockShared();
|
||||||
for(lights) |pos| {
|
for(lights) |pos| {
|
||||||
const index = chunk.getIndex(pos[0], pos[1], pos[2]);
|
const index = chunk.getIndex(pos[0], pos[1], pos[2]);
|
||||||
lightQueue.enqueue(.{.x = @intCast(pos[0]), .y = @intCast(pos[1]), .z = @intCast(pos[2]), .value = self.getValueInternal(index), .sourceDir = 6, .activeValue = 0b111});
|
lightQueue.enqueue(.{.x = @intCast(pos[0]), .y = @intCast(pos[1]), .z = @intCast(pos[2]), .value = self.getValueInternal(index), .sourceDir = 6, .activeValue = 0b111});
|
||||||
}
|
}
|
||||||
self.mutex.unlock();
|
self.lock.unlockShared();
|
||||||
var constructiveEntries: main.ListUnmanaged(ChunkEntries) = .{};
|
var constructiveEntries: main.ListUnmanaged(ChunkEntries) = .{};
|
||||||
defer constructiveEntries.deinit(main.stackAllocator);
|
defer constructiveEntries.deinit(main.stackAllocator);
|
||||||
constructiveEntries.append(main.stackAllocator, .{
|
constructiveEntries.append(main.stackAllocator, .{
|
||||||
@ -430,7 +427,7 @@ pub const ChannelChunk = struct {
|
|||||||
var entryList = entries.entries;
|
var entryList = entries.entries;
|
||||||
defer entryList.deinit(main.stackAllocator);
|
defer entryList.deinit(main.stackAllocator);
|
||||||
const channelChunk = if(mesh) |_mesh| _mesh.lightingData[@intFromBool(self.isSun)] else self;
|
const channelChunk = if(mesh) |_mesh| _mesh.lightingData[@intFromBool(self.isSun)] else self;
|
||||||
channelChunk.mutex.lock();
|
channelChunk.lock.lockShared();
|
||||||
for(entryList.items) |entry| {
|
for(entryList.items) |entry| {
|
||||||
const index = chunk.getIndex(entry.x, entry.y, entry.z);
|
const index = chunk.getIndex(entry.x, entry.y, entry.z);
|
||||||
const value = channelChunk.getValueInternal(index);
|
const value = channelChunk.getValueInternal(index);
|
||||||
@ -438,7 +435,7 @@ pub const ChannelChunk = struct {
|
|||||||
channelChunk.setValueInternal(index, .{0, 0, 0});
|
channelChunk.setValueInternal(index, .{0, 0, 0});
|
||||||
lightQueue.enqueue(.{.x = entry.x, .y = entry.y, .z = entry.z, .value = value, .sourceDir = 6, .activeValue = 0b111});
|
lightQueue.enqueue(.{.x = entry.x, .y = entry.y, .z = entry.z, .value = value, .sourceDir = 6, .activeValue = 0b111});
|
||||||
}
|
}
|
||||||
channelChunk.mutex.unlock();
|
channelChunk.lock.unlockShared();
|
||||||
channelChunk.propagateDirect(&lightQueue);
|
channelChunk.propagateDirect(&lightQueue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user