mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-08-03 03:06:55 -04:00
Atomicize the palette
This commit is contained in:
parent
714b0a91d7
commit
a85a3ec2d2
@ -351,7 +351,7 @@ pub const BlockEntityTypes = struct {
|
||||
}
|
||||
data.valuePtr.* = .{
|
||||
.blockPos = pos,
|
||||
.block = chunk.data.getValue(chunk.getLocalBlockIndex(pos)),
|
||||
.block = chunk.data.getValueFromOwnerThread(chunk.getLocalBlockIndex(pos)),
|
||||
.renderedTexture = null,
|
||||
.text = main.globalAllocator.dupe(u8, event.createOrUpdate.remaining),
|
||||
};
|
||||
@ -405,7 +405,7 @@ pub const BlockEntityTypes = struct {
|
||||
mesh.mutex.lock();
|
||||
defer mesh.mutex.unlock();
|
||||
const index = mesh.chunk.getLocalBlockIndex(pos);
|
||||
const block = mesh.chunk.data.getValue(index);
|
||||
const block = mesh.chunk.data.getValueFromOwnerThread(index);
|
||||
const blockEntity = block.blockEntity() orelse return;
|
||||
if(!std.mem.eql(u8, blockEntity.id, id)) return;
|
||||
|
||||
@ -418,7 +418,7 @@ pub const BlockEntityTypes = struct {
|
||||
}
|
||||
data.valuePtr.* = .{
|
||||
.blockPos = pos,
|
||||
.block = mesh.chunk.data.getValue(mesh.chunk.getLocalBlockIndex(pos)),
|
||||
.block = mesh.chunk.data.getValueFromOwnerThread(mesh.chunk.getLocalBlockIndex(pos)),
|
||||
.renderedTexture = null,
|
||||
.text = main.globalAllocator.dupe(u8, newText),
|
||||
};
|
||||
|
@ -296,7 +296,7 @@ pub const Chunk = struct { // MARK: Chunk
|
||||
while(iterator.next()) |elem| {
|
||||
const index = elem.key_ptr.*;
|
||||
const entityDataIndex = elem.value_ptr.*;
|
||||
const block = self.data.getValue(index);
|
||||
const block = self.data.getValueFromOwnerThread(index);
|
||||
const blockEntity = block.blockEntity() orelse unreachable;
|
||||
switch(side) {
|
||||
.client => {
|
||||
@ -327,7 +327,7 @@ pub const Chunk = struct { // MARK: Chunk
|
||||
const y = _y >> self.voxelSizeShift;
|
||||
const z = _z >> self.voxelSizeShift;
|
||||
const index = getIndex(x, y, z);
|
||||
return self.data.getValue(index);
|
||||
return self.data.getValueFromOwnerThread(index);
|
||||
}
|
||||
|
||||
/// Checks if the given relative coordinates lie within the bounds of this chunk.
|
||||
@ -437,7 +437,7 @@ pub const ServerChunk = struct { // MARK: ServerChunk
|
||||
const y = _y >> self.super.voxelSizeShift;
|
||||
const z = _z >> self.super.voxelSizeShift;
|
||||
const index = getIndex(x, y, z);
|
||||
return self.super.data.getValue(index);
|
||||
return self.super.data.getValueFromOwnerThread(index);
|
||||
}
|
||||
|
||||
/// Updates a block if it is inside this chunk.
|
||||
@ -487,7 +487,7 @@ pub const ServerChunk = struct { // MARK: ServerChunk
|
||||
const y = _y >> self.super.voxelSizeShift;
|
||||
const z = _z >> self.super.voxelSizeShift;
|
||||
const index = getIndex(x, y, z);
|
||||
const oldBlock = self.super.data.getValue(index);
|
||||
const oldBlock = self.super.data.getValueFromOwnerThread(index);
|
||||
if(oldBlock.typ == 0 or oldBlock.degradable()) {
|
||||
self.super.data.setValue(index, newBlock);
|
||||
}
|
||||
@ -544,7 +544,7 @@ pub const ServerChunk = struct { // MARK: ServerChunk
|
||||
while(dz <= 1) : (dz += 1) {
|
||||
const index = getIndex(x*2 + dx, y*2 + dy, z*2 + dz);
|
||||
const i = dx*4 + dz*2 + dy;
|
||||
octantBlocks[i] = other.super.data.getValue(index);
|
||||
octantBlocks[i] = other.super.data.getValueFromOwnerThread(index);
|
||||
octantBlocks[i].typ = octantBlocks[i].lodReplacement();
|
||||
if(octantBlocks[i].typ == 0) {
|
||||
neighborCount[i] = 0;
|
||||
@ -558,7 +558,7 @@ pub const ServerChunk = struct { // MARK: ServerChunk
|
||||
const nz = z*2 + dz + n.relZ();
|
||||
if((nx & chunkMask) == nx and (ny & chunkMask) == ny and (nz & chunkMask) == nz) { // If it's inside the chunk.
|
||||
const neighborIndex = getIndex(nx, ny, nz);
|
||||
if(other.super.data.getValue(neighborIndex).transparent()) {
|
||||
if(other.super.data.getValueFromOwnerThread(neighborIndex).transparent()) {
|
||||
count += 5;
|
||||
}
|
||||
} else {
|
||||
|
@ -1312,7 +1312,7 @@ pub const Protocols = struct {
|
||||
mesh.mutex.lock();
|
||||
defer mesh.mutex.unlock();
|
||||
const index = mesh.chunk.getLocalBlockIndex(pos);
|
||||
const block = mesh.chunk.data.getValue(index);
|
||||
const block = mesh.chunk.data.getValueFromOwnerThread(index);
|
||||
const blockEntity = block.blockEntity() orelse return;
|
||||
|
||||
var writer = utils.BinaryWriter.init(main.stackAllocator);
|
||||
|
@ -799,7 +799,7 @@ pub const ChunkMesh = struct { // MARK: ChunkMesh
|
||||
while(y < chunk.chunkSize) : (y += 1) {
|
||||
var z: u8 = 0;
|
||||
while(z < chunk.chunkSize) : (z += 1) {
|
||||
const block = self.chunk.data.getValue(chunk.getIndex(x, y, z));
|
||||
const block = self.chunk.data.getValueFromOwnerThread(chunk.getIndex(x, y, z));
|
||||
if(block.light() != 0) lightEmittingBlocks.append(.{x, y, z});
|
||||
}
|
||||
}
|
||||
@ -807,7 +807,7 @@ pub const ChunkMesh = struct { // MARK: ChunkMesh
|
||||
self.mutex.unlock();
|
||||
self.lightingData[0].propagateLights(lightEmittingBlocks.items, true, lightRefreshList);
|
||||
sunLight: {
|
||||
var allSun: bool = self.chunk.data.paletteLength == 1 and self.chunk.data.palette[0].typ == 0;
|
||||
var allSun: bool = self.chunk.data.paletteLength == 1 and self.chunk.data.palette.raw.toSlice()[0].raw.typ == 0;
|
||||
var sunStarters: [chunk.chunkSize*chunk.chunkSize][3]u8 = undefined;
|
||||
var index: usize = 0;
|
||||
const lightStartMap = mesh_storage.getLightMapPiece(self.pos.wx, self.pos.wy, self.pos.voxelSize) orelse break :sunLight;
|
||||
@ -918,7 +918,7 @@ pub const ChunkMesh = struct { // MARK: ChunkMesh
|
||||
var paletteCache = main.stackAllocator.alloc(OcclusionInfo, self.chunk.data.paletteLength);
|
||||
defer main.stackAllocator.free(paletteCache);
|
||||
for(0..self.chunk.data.paletteLength) |i| {
|
||||
const block = self.chunk.data.palette[i];
|
||||
const block = self.chunk.data.palette.raw.toSlice()[i].raw;
|
||||
const model = blocks.meshes.model(block).model();
|
||||
var result: OcclusionInfo = .{};
|
||||
if(model.noNeighborsOccluded or block.viewThrough()) {
|
||||
@ -1002,7 +1002,7 @@ pub const ChunkMesh = struct { // MARK: ChunkMesh
|
||||
hasFaces[x][y] |= setBit;
|
||||
}
|
||||
if(occlusionInfo.hasInternalQuads) {
|
||||
const block = self.chunk.data.palette[paletteId];
|
||||
const block = self.chunk.data.palette.raw.toSlice()[paletteId].raw;
|
||||
if(block.transparent()) {
|
||||
appendInternalQuads(block, x, y, z, false, &transparentCore, main.stackAllocator);
|
||||
} else {
|
||||
@ -1022,10 +1022,10 @@ pub const ChunkMesh = struct { // MARK: ChunkMesh
|
||||
const z = @ctz(bitMask);
|
||||
const setBit = @as(u32, 1) << @intCast(z);
|
||||
bitMask &= ~setBit;
|
||||
var block = self.chunk.data.getValue(chunk.getIndex(@intCast(x), @intCast(y), z));
|
||||
var block = self.chunk.data.getValueFromOwnerThread(chunk.getIndex(@intCast(x), @intCast(y), z));
|
||||
if(depthFilteredViewThroughMask[x][y] & setBit != 0) block.typ = block.opaqueVariant();
|
||||
if(block.viewThrough() and !block.alwaysViewThrough()) { // Needs to check the neighbor block
|
||||
const neighborBlock = self.chunk.data.getValue(chunk.getIndex(@intCast(x - 1), @intCast(y), z));
|
||||
const neighborBlock = self.chunk.data.getValueFromOwnerThread(chunk.getIndex(@intCast(x - 1), @intCast(y), z));
|
||||
if(block == neighborBlock) continue;
|
||||
}
|
||||
if(block.transparent()) {
|
||||
@ -1049,10 +1049,10 @@ pub const ChunkMesh = struct { // MARK: ChunkMesh
|
||||
const z = @ctz(bitMask);
|
||||
const setBit = @as(u32, 1) << @intCast(z);
|
||||
bitMask &= ~setBit;
|
||||
var block = self.chunk.data.getValue(chunk.getIndex(@intCast(x), @intCast(y), z));
|
||||
var block = self.chunk.data.getValueFromOwnerThread(chunk.getIndex(@intCast(x), @intCast(y), z));
|
||||
if(depthFilteredViewThroughMask[x][y] & setBit != 0) block.typ = block.opaqueVariant();
|
||||
if(block.viewThrough() and !block.alwaysViewThrough()) { // Needs to check the neighbor block
|
||||
const neighborBlock = self.chunk.data.getValue(chunk.getIndex(@intCast(x + 1), @intCast(y), z));
|
||||
const neighborBlock = self.chunk.data.getValueFromOwnerThread(chunk.getIndex(@intCast(x + 1), @intCast(y), z));
|
||||
if(block == neighborBlock) continue;
|
||||
}
|
||||
if(block.transparent()) {
|
||||
@ -1076,10 +1076,10 @@ pub const ChunkMesh = struct { // MARK: ChunkMesh
|
||||
const z = @ctz(bitMask);
|
||||
const setBit = @as(u32, 1) << @intCast(z);
|
||||
bitMask &= ~setBit;
|
||||
var block = self.chunk.data.getValue(chunk.getIndex(@intCast(x), @intCast(y), z));
|
||||
var block = self.chunk.data.getValueFromOwnerThread(chunk.getIndex(@intCast(x), @intCast(y), z));
|
||||
if(depthFilteredViewThroughMask[x][y] & setBit != 0) block.typ = block.opaqueVariant();
|
||||
if(block.viewThrough() and !block.alwaysViewThrough()) { // Needs to check the neighbor block
|
||||
const neighborBlock = self.chunk.data.getValue(chunk.getIndex(@intCast(x), @intCast(y - 1), z));
|
||||
const neighborBlock = self.chunk.data.getValueFromOwnerThread(chunk.getIndex(@intCast(x), @intCast(y - 1), z));
|
||||
if(block == neighborBlock) continue;
|
||||
}
|
||||
if(block.transparent()) {
|
||||
@ -1103,10 +1103,10 @@ pub const ChunkMesh = struct { // MARK: ChunkMesh
|
||||
const z = @ctz(bitMask);
|
||||
const setBit = @as(u32, 1) << @intCast(z);
|
||||
bitMask &= ~setBit;
|
||||
var block = self.chunk.data.getValue(chunk.getIndex(@intCast(x), @intCast(y), z));
|
||||
var block = self.chunk.data.getValueFromOwnerThread(chunk.getIndex(@intCast(x), @intCast(y), z));
|
||||
if(depthFilteredViewThroughMask[x][y] & setBit != 0) block.typ = block.opaqueVariant();
|
||||
if(block.viewThrough() and !block.alwaysViewThrough()) { // Needs to check the neighbor block
|
||||
const neighborBlock = self.chunk.data.getValue(chunk.getIndex(@intCast(x), @intCast(y + 1), z));
|
||||
const neighborBlock = self.chunk.data.getValueFromOwnerThread(chunk.getIndex(@intCast(x), @intCast(y + 1), z));
|
||||
if(block == neighborBlock) continue;
|
||||
}
|
||||
if(block.transparent()) {
|
||||
@ -1130,10 +1130,10 @@ pub const ChunkMesh = struct { // MARK: ChunkMesh
|
||||
const z = @ctz(bitMask);
|
||||
const setBit = @as(u32, 1) << @intCast(z);
|
||||
bitMask &= ~setBit;
|
||||
var block = self.chunk.data.getValue(chunk.getIndex(@intCast(x), @intCast(y), z));
|
||||
var block = self.chunk.data.getValueFromOwnerThread(chunk.getIndex(@intCast(x), @intCast(y), z));
|
||||
if(depthFilteredViewThroughMask[x][y] & setBit != 0) block.typ = block.opaqueVariant();
|
||||
if(block.viewThrough() and !block.alwaysViewThrough()) { // Needs to check the neighbor block
|
||||
const neighborBlock = self.chunk.data.getValue(chunk.getIndex(@intCast(x), @intCast(y), z - 1));
|
||||
const neighborBlock = self.chunk.data.getValueFromOwnerThread(chunk.getIndex(@intCast(x), @intCast(y), z - 1));
|
||||
if(block == neighborBlock) continue;
|
||||
}
|
||||
if(block.transparent()) {
|
||||
@ -1157,10 +1157,10 @@ pub const ChunkMesh = struct { // MARK: ChunkMesh
|
||||
const z = @ctz(bitMask);
|
||||
const setBit = @as(u32, 1) << @intCast(z);
|
||||
bitMask &= ~setBit;
|
||||
var block = self.chunk.data.getValue(chunk.getIndex(@intCast(x), @intCast(y), z));
|
||||
var block = self.chunk.data.getValueFromOwnerThread(chunk.getIndex(@intCast(x), @intCast(y), z));
|
||||
if(depthFilteredViewThroughMask[x][y] & setBit != 0) block.typ = block.opaqueVariant();
|
||||
if(block.viewThrough() and !block.alwaysViewThrough()) { // Needs to check the neighbor block
|
||||
const neighborBlock = self.chunk.data.getValue(chunk.getIndex(@intCast(x), @intCast(y), z + 1));
|
||||
const neighborBlock = self.chunk.data.getValueFromOwnerThread(chunk.getIndex(@intCast(x), @intCast(y), z + 1));
|
||||
if(block == neighborBlock) continue;
|
||||
}
|
||||
if(block.transparent()) {
|
||||
@ -1202,7 +1202,7 @@ pub const ChunkMesh = struct { // MARK: ChunkMesh
|
||||
const z: u5 = @intCast(_z & chunk.chunkMask);
|
||||
var newBlock = _newBlock;
|
||||
self.mutex.lock();
|
||||
const oldBlock = self.chunk.data.getValue(chunk.getIndex(x, y, z));
|
||||
const oldBlock = self.chunk.data.getValueFromOwnerThread(chunk.getIndex(x, y, z));
|
||||
|
||||
if(oldBlock == newBlock) {
|
||||
if(newBlock.blockEntity()) |blockEntity| {
|
||||
@ -1240,7 +1240,7 @@ pub const ChunkMesh = struct { // MARK: ChunkMesh
|
||||
const index = chunk.getIndex(nnx, nny, nnz);
|
||||
|
||||
neighborChunkMesh.mutex.lock();
|
||||
var neighborBlock = neighborChunkMesh.chunk.data.getValue(index);
|
||||
var neighborBlock = neighborChunkMesh.chunk.data.getValueFromOwnerThread(index);
|
||||
|
||||
if(neighborBlock.mode().dependsOnNeighbors and neighborBlock.mode().updateData(&neighborBlock, neighbor.reverse(), newBlock)) {
|
||||
neighborChunkMesh.chunk.data.setValue(index, neighborBlock);
|
||||
@ -1254,7 +1254,7 @@ pub const ChunkMesh = struct { // MARK: ChunkMesh
|
||||
} else {
|
||||
const index = chunk.getIndex(nx, ny, nz);
|
||||
self.mutex.lock();
|
||||
var neighborBlock = self.chunk.data.getValue(index);
|
||||
var neighborBlock = self.chunk.data.getValueFromOwnerThread(index);
|
||||
if(neighborBlock.mode().dependsOnNeighbors and neighborBlock.mode().updateData(&neighborBlock, neighbor.reverse(), newBlock)) {
|
||||
self.chunk.data.setValue(index, neighborBlock);
|
||||
self.updateBlockLight(@intCast(nx), @intCast(ny), @intCast(nz), neighborBlock, lightRefreshList);
|
||||
@ -1409,9 +1409,9 @@ pub const ChunkMesh = struct { // MARK: ChunkMesh
|
||||
const otherX = x +% neighbor.relX() & chunk.chunkMask;
|
||||
const otherY = y +% neighbor.relY() & chunk.chunkMask;
|
||||
const otherZ = z +% neighbor.relZ() & chunk.chunkMask;
|
||||
var block = self.chunk.data.getValue(chunk.getIndex(x, y, z));
|
||||
var block = self.chunk.data.getValueFromOwnerThread(chunk.getIndex(x, y, z));
|
||||
if(settings.leavesQuality == 0) block.typ = block.opaqueVariant();
|
||||
var otherBlock = neighborMesh.chunk.data.getValue(chunk.getIndex(otherX, otherY, otherZ));
|
||||
var otherBlock = neighborMesh.chunk.data.getValueFromOwnerThread(chunk.getIndex(otherX, otherY, otherZ));
|
||||
if(settings.leavesQuality == 0) otherBlock.typ = otherBlock.opaqueVariant();
|
||||
if(canBeSeenThroughOtherBlock(block, otherBlock, neighbor)) {
|
||||
if(block.transparent()) {
|
||||
@ -1501,9 +1501,9 @@ pub const ChunkMesh = struct { // MARK: ChunkMesh
|
||||
const otherX = (x +% neighbor.relX() +% offsetX >> 1) & chunk.chunkMask;
|
||||
const otherY = (y +% neighbor.relY() +% offsetY >> 1) & chunk.chunkMask;
|
||||
const otherZ = (z +% neighbor.relZ() +% offsetZ >> 1) & chunk.chunkMask;
|
||||
var block = self.chunk.data.getValue(chunk.getIndex(x, y, z));
|
||||
var block = self.chunk.data.getValueFromOwnerThread(chunk.getIndex(x, y, z));
|
||||
if(settings.leavesQuality == 0) block.typ = block.opaqueVariant();
|
||||
var otherBlock = neighborMesh.chunk.data.getValue(chunk.getIndex(otherX, otherY, otherZ));
|
||||
var otherBlock = neighborMesh.chunk.data.getValueFromOwnerThread(chunk.getIndex(otherX, otherY, otherZ));
|
||||
if(settings.leavesQuality == 0) otherBlock.typ = otherBlock.opaqueVariant();
|
||||
if(canBeSeenThroughOtherBlock(otherBlock, block, neighbor.reverse())) {
|
||||
if(otherBlock.transparent()) {
|
||||
|
@ -17,6 +17,21 @@ pub fn deinit() void {
|
||||
memoryPool.deinit();
|
||||
}
|
||||
|
||||
const LightValue = packed struct(u32) {
|
||||
r: u8,
|
||||
g: u8,
|
||||
b: u8,
|
||||
pad: u8 = undefined,
|
||||
|
||||
fn fromArray(arr: [3]u8) LightValue {
|
||||
return .{.r = arr[0], .g = arr[1], .b = arr[2]};
|
||||
}
|
||||
|
||||
fn toArray(self: LightValue) [3]u8 {
|
||||
return .{self.r, self.g, self.b};
|
||||
}
|
||||
};
|
||||
|
||||
fn extractColor(in: u32) [3]u8 {
|
||||
return .{
|
||||
@truncate(in >> 16),
|
||||
@ -26,7 +41,7 @@ fn extractColor(in: u32) [3]u8 {
|
||||
}
|
||||
|
||||
pub const ChannelChunk = struct {
|
||||
data: main.utils.PaletteCompressedRegion([3]u8, chunk.chunkVolume),
|
||||
data: main.utils.PaletteCompressedRegion(LightValue, chunk.chunkVolume),
|
||||
lock: main.utils.ReadWriteLock,
|
||||
ch: *chunk.Chunk,
|
||||
isSun: bool,
|
||||
@ -66,9 +81,8 @@ pub const ChannelChunk = struct {
|
||||
};
|
||||
|
||||
pub fn getValue(self: *ChannelChunk, x: i32, y: i32, z: i32) [3]u8 {
|
||||
self.lock.assertLockedRead();
|
||||
const index = chunk.getIndex(x, y, z);
|
||||
return self.data.getValue(index);
|
||||
return self.data.getValueUnordered(index).toArray();
|
||||
}
|
||||
|
||||
fn calculateIncomingOcclusion(result: *[3]u8, block: blocks.Block, voxelSize: u31, neighbor: chunk.Neighbor) void {
|
||||
@ -109,14 +123,14 @@ pub const ChannelChunk = struct {
|
||||
self.lock.lockWrite();
|
||||
while(lightQueue.popFront()) |entry| {
|
||||
const index = chunk.getIndex(entry.x, entry.y, entry.z);
|
||||
const oldValue: [3]u8 = self.data.getValue(index);
|
||||
const oldValue: [3]u8 = self.data.getValueFromOwnerThread(index).toArray();
|
||||
const newValue: [3]u8 = .{
|
||||
@max(entry.value[0], oldValue[0]),
|
||||
@max(entry.value[1], oldValue[1]),
|
||||
@max(entry.value[2], oldValue[2]),
|
||||
};
|
||||
if(newValue[0] == oldValue[0] and newValue[1] == oldValue[1] and newValue[2] == oldValue[2]) continue;
|
||||
self.data.setValue(index, newValue);
|
||||
self.data.setValue(index, .fromArray(newValue));
|
||||
for(chunk.Neighbor.iterable) |neighbor| {
|
||||
if(neighbor.toInt() == entry.sourceDir) continue;
|
||||
const nx = entry.x + neighbor.relX();
|
||||
@ -128,14 +142,14 @@ pub const ChannelChunk = struct {
|
||||
result.value[1] -|= 8*|@as(u8, @intCast(self.ch.pos.voxelSize));
|
||||
result.value[2] -|= 8*|@as(u8, @intCast(self.ch.pos.voxelSize));
|
||||
}
|
||||
calculateOutgoingOcclusion(&result.value, self.ch.data.getValue(index), self.ch.pos.voxelSize, neighbor);
|
||||
calculateOutgoingOcclusion(&result.value, self.ch.data.getValueFromOwnerThread(index), self.ch.pos.voxelSize, neighbor);
|
||||
if(result.value[0] == 0 and result.value[1] == 0 and result.value[2] == 0) continue;
|
||||
if(nx < 0 or nx >= chunk.chunkSize or ny < 0 or ny >= chunk.chunkSize or nz < 0 or nz >= chunk.chunkSize) {
|
||||
neighborLists[neighbor.toInt()].append(main.stackAllocator, result);
|
||||
continue;
|
||||
}
|
||||
const neighborIndex = chunk.getIndex(nx, ny, nz);
|
||||
calculateIncomingOcclusion(&result.value, self.ch.data.getValue(neighborIndex), self.ch.pos.voxelSize, neighbor.reverse());
|
||||
calculateIncomingOcclusion(&result.value, self.ch.data.getValueFromOwnerThread(neighborIndex), self.ch.pos.voxelSize, neighbor.reverse());
|
||||
if(result.value[0] != 0 or result.value[1] != 0 or result.value[2] != 0) lightQueue.pushBack(result);
|
||||
}
|
||||
}
|
||||
@ -175,7 +189,7 @@ pub const ChannelChunk = struct {
|
||||
self.lock.lockWrite();
|
||||
while(lightQueue.popFront()) |entry| {
|
||||
const index = chunk.getIndex(entry.x, entry.y, entry.z);
|
||||
const oldValue: [3]u8 = self.data.getValue(index);
|
||||
const oldValue: [3]u8 = self.data.getValueFromOwnerThread(index).toArray();
|
||||
var activeValue: @Vector(3, bool) = @bitCast(entry.activeValue);
|
||||
var append: bool = false;
|
||||
if(activeValue[0] and entry.value[0] != oldValue[0]) {
|
||||
@ -209,7 +223,7 @@ pub const ChannelChunk = struct {
|
||||
if(activeValue[0]) insertValue[0] = 0;
|
||||
if(activeValue[1]) insertValue[1] = 0;
|
||||
if(activeValue[2]) insertValue[2] = 0;
|
||||
self.data.setValue(index, insertValue);
|
||||
self.data.setValue(index, .fromArray(insertValue));
|
||||
for(chunk.Neighbor.iterable) |neighbor| {
|
||||
if(neighbor.toInt() == entry.sourceDir) continue;
|
||||
const nx = entry.x + neighbor.relX();
|
||||
@ -221,13 +235,13 @@ pub const ChannelChunk = struct {
|
||||
result.value[1] -|= 8*|@as(u8, @intCast(self.ch.pos.voxelSize));
|
||||
result.value[2] -|= 8*|@as(u8, @intCast(self.ch.pos.voxelSize));
|
||||
}
|
||||
calculateOutgoingOcclusion(&result.value, self.ch.data.getValue(index), self.ch.pos.voxelSize, neighbor);
|
||||
calculateOutgoingOcclusion(&result.value, self.ch.data.getValueFromOwnerThread(index), self.ch.pos.voxelSize, neighbor);
|
||||
if(nx < 0 or nx >= chunk.chunkSize or ny < 0 or ny >= chunk.chunkSize or nz < 0 or nz >= chunk.chunkSize) {
|
||||
neighborLists[neighbor.toInt()].append(main.stackAllocator, result);
|
||||
continue;
|
||||
}
|
||||
const neighborIndex = chunk.getIndex(nx, ny, nz);
|
||||
calculateIncomingOcclusion(&result.value, self.ch.data.getValue(neighborIndex), self.ch.pos.voxelSize, neighbor.reverse());
|
||||
calculateIncomingOcclusion(&result.value, self.ch.data.getValueFromOwnerThread(neighborIndex), self.ch.pos.voxelSize, neighbor.reverse());
|
||||
lightQueue.pushBack(result);
|
||||
}
|
||||
}
|
||||
@ -251,7 +265,7 @@ pub const ChannelChunk = struct {
|
||||
for(lights) |entry| {
|
||||
const index = chunk.getIndex(entry.x, entry.y, entry.z);
|
||||
var result = entry;
|
||||
calculateIncomingOcclusion(&result.value, self.ch.data.getValue(index), self.ch.pos.voxelSize, @enumFromInt(entry.sourceDir));
|
||||
calculateIncomingOcclusion(&result.value, self.ch.data.getValueFromOwnerThread(index), self.ch.pos.voxelSize, @enumFromInt(entry.sourceDir));
|
||||
if(result.value[0] != 0 or result.value[1] != 0 or result.value[2] != 0) lightQueue.pushBack(result);
|
||||
}
|
||||
self.propagateDirect(lightQueue, lightRefreshList);
|
||||
@ -262,7 +276,7 @@ pub const ChannelChunk = struct {
|
||||
for(lights) |entry| {
|
||||
const index = chunk.getIndex(entry.x, entry.y, entry.z);
|
||||
var result = entry;
|
||||
calculateIncomingOcclusion(&result.value, self.ch.data.getValue(index), self.ch.pos.voxelSize, @enumFromInt(entry.sourceDir));
|
||||
calculateIncomingOcclusion(&result.value, self.ch.data.getValueFromOwnerThread(index), self.ch.pos.voxelSize, @enumFromInt(entry.sourceDir));
|
||||
lightQueue.pushBack(result);
|
||||
}
|
||||
return self.propagateDestructive(lightQueue, constructiveEntries, false, lightRefreshList);
|
||||
@ -276,7 +290,7 @@ pub const ChannelChunk = struct {
|
||||
if(self.isSun) {
|
||||
lightQueue.pushBack(.{.x = @intCast(pos[0]), .y = @intCast(pos[1]), .z = @intCast(pos[2]), .value = .{255, 255, 255}, .sourceDir = 6, .activeValue = 0b111});
|
||||
} else {
|
||||
lightQueue.pushBack(.{.x = @intCast(pos[0]), .y = @intCast(pos[1]), .z = @intCast(pos[2]), .value = extractColor(self.ch.data.getValue(index).light()), .sourceDir = 6, .activeValue = 0b111});
|
||||
lightQueue.pushBack(.{.x = @intCast(pos[0]), .y = @intCast(pos[1]), .z = @intCast(pos[2]), .value = extractColor(self.ch.data.getValueFromOwnerThread(index).light()), .sourceDir = 6, .activeValue = 0b111});
|
||||
}
|
||||
}
|
||||
if(checkNeighbors) {
|
||||
@ -311,15 +325,15 @@ pub const ChannelChunk = struct {
|
||||
defer neighborLightChunk.lock.unlockRead();
|
||||
const index = chunk.getIndex(x, y, z);
|
||||
const neighborIndex = chunk.getIndex(otherX, otherY, otherZ);
|
||||
var value: [3]u8 = neighborLightChunk.data.getValue(neighborIndex);
|
||||
var value: [3]u8 = neighborLightChunk.data.getValueFromOwnerThread(neighborIndex).toArray();
|
||||
if(!self.isSun or neighbor != .dirUp or value[0] != 255 or value[1] != 255 or value[2] != 255) {
|
||||
value[0] -|= 8*|@as(u8, @intCast(self.ch.pos.voxelSize));
|
||||
value[1] -|= 8*|@as(u8, @intCast(self.ch.pos.voxelSize));
|
||||
value[2] -|= 8*|@as(u8, @intCast(self.ch.pos.voxelSize));
|
||||
}
|
||||
calculateOutgoingOcclusion(&value, self.ch.data.getValue(neighborIndex), self.ch.pos.voxelSize, neighbor);
|
||||
calculateOutgoingOcclusion(&value, self.ch.data.getValueFromOwnerThread(neighborIndex), self.ch.pos.voxelSize, neighbor);
|
||||
if(value[0] == 0 and value[1] == 0 and value[2] == 0) continue;
|
||||
calculateIncomingOcclusion(&value, self.ch.data.getValue(index), self.ch.pos.voxelSize, neighbor.reverse());
|
||||
calculateIncomingOcclusion(&value, self.ch.data.getValueFromOwnerThread(index), self.ch.pos.voxelSize, neighbor.reverse());
|
||||
if(value[0] != 0 or value[1] != 0 or value[2] != 0) lightQueue.pushBack(.{.x = @intCast(x), .y = @intCast(y), .z = @intCast(z), .value = value, .sourceDir = neighbor.toInt(), .activeValue = 0b111});
|
||||
}
|
||||
}
|
||||
@ -335,7 +349,7 @@ pub const ChannelChunk = struct {
|
||||
self.data.deinit();
|
||||
self.data.init();
|
||||
}
|
||||
self.data.palette[0] = .{255, 255, 255};
|
||||
self.data.palette.raw.toSlice()[0].store(.fromArray(@splat(255)), .unordered);
|
||||
self.lock.unlockWrite();
|
||||
const val = 255 -| 8*|@as(u8, @intCast(self.ch.pos.voxelSize));
|
||||
var lightQueue = main.utils.CircularBufferQueue(Entry).init(main.stackAllocator, 1 << 12);
|
||||
@ -381,7 +395,7 @@ pub const ChannelChunk = struct {
|
||||
self.lock.lockRead();
|
||||
for(lights) |pos| {
|
||||
const index = chunk.getIndex(pos[0], pos[1], pos[2]);
|
||||
lightQueue.pushBack(.{.x = @intCast(pos[0]), .y = @intCast(pos[1]), .z = @intCast(pos[2]), .value = self.data.getValue(index), .sourceDir = 6, .activeValue = 0b111});
|
||||
lightQueue.pushBack(.{.x = @intCast(pos[0]), .y = @intCast(pos[1]), .z = @intCast(pos[2]), .value = self.data.getValueFromOwnerThread(index).toArray(), .sourceDir = 6, .activeValue = 0b111});
|
||||
}
|
||||
self.lock.unlockRead();
|
||||
var constructiveEntries: main.ListUnmanaged(ChunkEntries) = .{};
|
||||
@ -398,15 +412,15 @@ pub const ChannelChunk = struct {
|
||||
channelChunk.lock.lockWrite();
|
||||
for(entryList.items) |entry| {
|
||||
const index = chunk.getIndex(entry.x, entry.y, entry.z);
|
||||
var value = channelChunk.data.getValue(index);
|
||||
const light = if(self.isSun) .{0, 0, 0} else extractColor(channelChunk.ch.data.getValue(index).light());
|
||||
var value = channelChunk.data.getValueFromOwnerThread(index).toArray();
|
||||
const light = if(self.isSun) .{0, 0, 0} else extractColor(channelChunk.ch.data.getValueFromOwnerThread(index).light());
|
||||
value = .{
|
||||
@max(value[0], light[0]),
|
||||
@max(value[1], light[1]),
|
||||
@max(value[2], light[2]),
|
||||
};
|
||||
if(value[0] == 0 and value[1] == 0 and value[2] == 0) continue;
|
||||
channelChunk.data.setValue(index, .{0, 0, 0});
|
||||
channelChunk.data.setValue(index, .fromArray(.{0, 0, 0}));
|
||||
lightQueue.pushBack(.{.x = entry.x, .y = entry.y, .z = entry.z, .value = value, .sourceDir = 6, .activeValue = 0b111});
|
||||
}
|
||||
channelChunk.lock.unlockWrite();
|
||||
|
@ -284,7 +284,7 @@ pub const ChunkCompression = struct { // MARK: ChunkCompression
|
||||
fn compressBlockData(ch: *chunk.Chunk, allowLossy: bool, writer: *BinaryWriter) void {
|
||||
if(ch.data.paletteLength == 1) {
|
||||
writer.writeEnum(ChunkCompressionAlgo, .uniform);
|
||||
writer.writeInt(u32, ch.data.palette[0].toInt());
|
||||
writer.writeInt(u32, ch.data.getValueFromOwnerThread(0).toInt());
|
||||
return;
|
||||
}
|
||||
if(ch.data.paletteLength < 256) {
|
||||
@ -293,7 +293,7 @@ pub const ChunkCompression = struct { // MARK: ChunkCompression
|
||||
for(0..chunk.chunkVolume) |i| {
|
||||
uncompressedData[i] = @intCast(ch.data.data.getValue(i));
|
||||
if(allowLossy) {
|
||||
const block = ch.data.palette[uncompressedData[i]];
|
||||
const block = ch.data.palette.raw.toSlice()[uncompressedData[i]].raw;
|
||||
const model = main.blocks.meshes.model(block).model();
|
||||
const occluder = model.allNeighborsOccluded and !block.viewThrough();
|
||||
if(occluder) {
|
||||
@ -326,7 +326,7 @@ pub const ChunkCompression = struct { // MARK: ChunkCompression
|
||||
writer.writeInt(u8, @intCast(ch.data.paletteLength));
|
||||
|
||||
for(0..ch.data.paletteLength) |i| {
|
||||
writer.writeInt(u32, ch.data.palette[i].toInt());
|
||||
writer.writeInt(u32, ch.data.palette.raw.toSlice()[i].raw.toInt());
|
||||
}
|
||||
writer.writeVarInt(usize, compressedData.len);
|
||||
writer.writeSlice(compressedData);
|
||||
@ -336,7 +336,7 @@ pub const ChunkCompression = struct { // MARK: ChunkCompression
|
||||
defer uncompressedWriter.deinit();
|
||||
|
||||
for(0..chunk.chunkVolume) |i| {
|
||||
uncompressedWriter.writeInt(u32, ch.data.getValue(i).toInt());
|
||||
uncompressedWriter.writeInt(u32, ch.data.getValueFromOwnerThread(i).toInt());
|
||||
}
|
||||
const compressedData = main.utils.Compression.deflate(main.stackAllocator, uncompressedWriter.data.items, .default);
|
||||
defer main.stackAllocator.free(compressedData);
|
||||
@ -375,7 +375,7 @@ pub const ChunkCompression = struct { // MARK: ChunkCompression
|
||||
ch.data.initCapacity(paletteLength);
|
||||
|
||||
for(0..paletteLength) |i| {
|
||||
ch.data.palette[i] = main.blocks.Block.fromInt(try reader.readInt(u32));
|
||||
ch.data.palette.raw.toSlice()[i] = .init(main.blocks.Block.fromInt(try reader.readInt(u32)));
|
||||
}
|
||||
|
||||
const decompressedData = main.stackAllocator.alloc(u8, chunk.chunkVolume);
|
||||
@ -392,7 +392,7 @@ pub const ChunkCompression = struct { // MARK: ChunkCompression
|
||||
}
|
||||
},
|
||||
.uniform => {
|
||||
ch.data.palette[0] = main.blocks.Block.fromInt(try reader.readInt(u32));
|
||||
ch.data.palette.raw.toSlice()[0] = .init(main.blocks.Block.fromInt(try reader.readInt(u32)));
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -409,7 +409,7 @@ pub const ChunkCompression = struct { // MARK: ChunkCompression
|
||||
while(iterator.next()) |entry| {
|
||||
const index = entry.key_ptr.*;
|
||||
const blockEntityIndex = entry.value_ptr.*;
|
||||
const block = ch.data.getValue(index);
|
||||
const block = ch.data.getValueFromOwnerThread(index);
|
||||
const blockEntity = block.blockEntity() orelse continue;
|
||||
|
||||
var tempWriter = BinaryWriter.init(main.stackAllocator);
|
||||
@ -441,7 +441,7 @@ pub const ChunkCompression = struct { // MARK: ChunkCompression
|
||||
const dataLength = try reader.readVarInt(usize);
|
||||
|
||||
const blockEntityData = try reader.readSlice(dataLength);
|
||||
const block = ch.data.getValue(index);
|
||||
const block = ch.data.getValueFromOwnerThread(index);
|
||||
const blockEntity = block.blockEntity() orelse {
|
||||
std.log.err("Could not load BlockEntity at position {} for block {s}: Block has no block entity", .{pos, block.id()});
|
||||
continue;
|
||||
|
@ -47,13 +47,13 @@ pub fn generate(worldSeed: u64, chunk: *main.chunk.ServerChunk, caveMap: CaveMap
|
||||
if(minHeight > chunk.super.pos.wz +| chunk.super.width) {
|
||||
chunk.super.data.deinit();
|
||||
chunk.super.data.init();
|
||||
chunk.super.data.palette[0] = stone;
|
||||
chunk.super.data.palette.raw.toSlice()[0] = .init(stone);
|
||||
return;
|
||||
}
|
||||
if(maxHeight < chunk.super.pos.wz) {
|
||||
chunk.super.data.deinit();
|
||||
chunk.super.data.init();
|
||||
chunk.super.data.palette[0] = air;
|
||||
chunk.super.data.palette.raw.toSlice()[0] = .init(air);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -328,8 +328,8 @@ const ChunkManager = struct { // MARK: ChunkManager
|
||||
generator.generate(server.world.?.seed ^ generator.generatorSeed, ch, caveMap, biomeMap);
|
||||
}
|
||||
if(pos.voxelSize != 1) { // Generate LOD replacements
|
||||
for(ch.super.data.palette[0..ch.super.data.paletteLength]) |*block| {
|
||||
block.typ = block.lodReplacement();
|
||||
for(ch.super.data.palette.raw.toSlice()[0..ch.super.data.paletteLength]) |*block| {
|
||||
block.store(.{.typ = block.raw.lodReplacement(), .data = block.raw.data}, .unordered);
|
||||
}
|
||||
}
|
||||
return ch;
|
||||
|
@ -1027,7 +1027,7 @@ pub fn DynamicPackedIntArray(size: comptime_int) type { // MARK: DynamicPackedIn
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Self) void {
|
||||
main.heap.GarbageCollection.deferredFreeSlice(dynamicIntArrayAllocator.allocator(), Atomic(u32), self.content.swap(@bitCast(@as(u64, 0)), .monotonic).toSlice());
|
||||
main.heap.GarbageCollection.deferredFreeSlice(dynamicIntArrayAllocator.allocator(), self.content.swap(@bitCast(@as(u64, 0)), .monotonic).toSlice());
|
||||
}
|
||||
|
||||
inline fn bitInterleave(bits: comptime_int, source: u32) u32 {
|
||||
@ -1060,7 +1060,7 @@ pub fn DynamicPackedIntArray(size: comptime_int) type { // MARK: DynamicPackedIn
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
main.heap.GarbageCollection.deferredFreeSlice(dynamicIntArrayAllocator.allocator(), Atomic(u32), oldContent.toSlice());
|
||||
main.heap.GarbageCollection.deferredFreeSlice(dynamicIntArrayAllocator.allocator(), oldContent.toSlice());
|
||||
self.content.store(newContent, .release);
|
||||
}
|
||||
|
||||
@ -1110,7 +1110,7 @@ pub fn DynamicPackedIntArray(size: comptime_int) type { // MARK: DynamicPackedIn
|
||||
pub fn PaletteCompressedRegion(T: type, size: comptime_int) type { // MARK: PaletteCompressedRegion
|
||||
return struct {
|
||||
data: DynamicPackedIntArray(size) = .{},
|
||||
palette: []T,
|
||||
palette: Atomic(PowerOfTwoSlice(Atomic(T))),
|
||||
paletteOccupancy: []u32,
|
||||
paletteLength: u32,
|
||||
activePaletteEntries: u32,
|
||||
@ -1119,12 +1119,12 @@ pub fn PaletteCompressedRegion(T: type, size: comptime_int) type { // MARK: Pale
|
||||
|
||||
pub fn init(self: *Self) void {
|
||||
self.* = .{
|
||||
.palette = main.globalAllocator.alloc(T, 1),
|
||||
.palette = .init(.fromSlice(main.globalAllocator.alignedAlloc(Atomic(T), .@"64", 1))),
|
||||
.paletteOccupancy = main.globalAllocator.alloc(u32, 1),
|
||||
.paletteLength = 1,
|
||||
.activePaletteEntries = 1,
|
||||
};
|
||||
self.palette[0] = std.mem.zeroes(T);
|
||||
self.palette.raw.toSlice()[0] = .init(std.mem.zeroes(T));
|
||||
self.paletteOccupancy[0] = size;
|
||||
}
|
||||
|
||||
@ -1134,18 +1134,18 @@ pub fn PaletteCompressedRegion(T: type, size: comptime_int) type { // MARK: Pale
|
||||
const bufferLength = @as(u32, 1) << bitSize;
|
||||
self.* = .{
|
||||
.data = DynamicPackedIntArray(size).initCapacity(bitSize),
|
||||
.palette = main.globalAllocator.alloc(T, bufferLength),
|
||||
.palette = .init(.fromSlice(main.globalAllocator.alignedAlloc(Atomic(T), .@"64", bufferLength))),
|
||||
.paletteOccupancy = main.globalAllocator.alloc(u32, bufferLength),
|
||||
.paletteLength = paletteLength,
|
||||
.activePaletteEntries = 1,
|
||||
};
|
||||
self.palette[0] = std.mem.zeroes(T);
|
||||
self.palette.raw.toSlice()[0] = .init(std.mem.zeroes(T));
|
||||
self.paletteOccupancy[0] = size;
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Self) void {
|
||||
self.data.deinit();
|
||||
main.globalAllocator.free(self.palette);
|
||||
main.heap.GarbageCollection.deferredFreeSlice(main.globalAllocator, self.palette.raw.toSlice());
|
||||
main.globalAllocator.free(self.paletteOccupancy);
|
||||
}
|
||||
|
||||
@ -1156,29 +1156,40 @@ pub fn PaletteCompressedRegion(T: type, size: comptime_int) type { // MARK: Pale
|
||||
return @as(u5, 1) << logLog;
|
||||
}
|
||||
|
||||
pub fn getValue(self: *const Self, i: usize) T {
|
||||
return self.palette[self.data.getValue(i)];
|
||||
/// Uses the Java memory model to get a value.
|
||||
/// In case of congestion a random value may get returned.
|
||||
pub fn getValueUnordered(self: *const Self, i: usize) T {
|
||||
const paletteIndex = self.data.getValue(i);
|
||||
const palette = self.palette.load(.unordered).toSlice();
|
||||
if(paletteIndex >= palette.len) return undefined;
|
||||
return palette[paletteIndex].load(.unordered);
|
||||
}
|
||||
|
||||
pub fn getValueFromOwnerThread(self: *const Self, i: usize) T {
|
||||
return self.palette.raw.toSlice()[self.data.getValue(i)].raw;
|
||||
}
|
||||
|
||||
fn getOrInsertPaletteIndex(noalias self: *Self, val: T) u32 {
|
||||
std.debug.assert(self.paletteLength <= self.palette.len);
|
||||
std.debug.assert(self.paletteLength <= self.palette.raw.toSlice().len);
|
||||
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.
|
||||
if(std.meta.eql(self.palette[paletteIndex], val)) {
|
||||
if(std.meta.eql(self.palette.raw.toSlice()[paletteIndex].raw, val)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(paletteIndex == self.paletteLength) {
|
||||
if(self.paletteLength == self.palette.len) {
|
||||
if(self.paletteLength == self.palette.raw.toSlice().len) {
|
||||
self.data.resizeOnce();
|
||||
self.palette = main.globalAllocator.realloc(self.palette, @as(usize, 1) << self.data.bitSizeUnsafe());
|
||||
const newPalette = main.globalAllocator.alignedAlloc(Atomic(T), .@"64", @as(usize, 1) << self.data.bitSizeUnsafe());
|
||||
@memcpy(newPalette[0..self.palette.raw.toSlice().len], self.palette.raw.toSlice());
|
||||
main.heap.GarbageCollection.deferredFreeSlice(main.globalAllocator, self.palette.swap(.fromSlice(newPalette), .monotonic).toSlice());
|
||||
const oldLen = self.paletteOccupancy.len;
|
||||
self.paletteOccupancy = main.globalAllocator.realloc(self.paletteOccupancy, @as(usize, 1) << self.data.bitSizeUnsafe());
|
||||
@memset(self.paletteOccupancy[oldLen..], 0);
|
||||
}
|
||||
self.palette[paletteIndex] = val;
|
||||
self.palette.raw.toSlice()[paletteIndex].store(val, .unordered);
|
||||
self.paletteLength += 1;
|
||||
std.debug.assert(self.paletteLength <= self.palette.len);
|
||||
std.debug.assert(self.paletteLength <= self.palette.raw.toSlice().len);
|
||||
}
|
||||
return paletteIndex;
|
||||
}
|
||||
@ -1247,7 +1258,7 @@ pub fn PaletteCompressedRegion(T: type, size: comptime_int) type { // MARK: Pale
|
||||
if(len == i) break :outer;
|
||||
}
|
||||
paletteMap[len] = i;
|
||||
self.palette[i] = self.palette[len];
|
||||
self.palette.raw.toSlice()[i].store(self.palette.raw.toSlice()[len].raw, .unordered);
|
||||
self.paletteOccupancy[i] = self.paletteOccupancy[len];
|
||||
self.paletteOccupancy[len] = 0;
|
||||
}
|
||||
@ -1259,7 +1270,9 @@ pub fn PaletteCompressedRegion(T: type, size: comptime_int) type { // MARK: Pale
|
||||
newData.content.raw = self.data.content.swap(newData.content.raw, .release);
|
||||
newData.deinit();
|
||||
self.paletteLength = self.activePaletteEntries;
|
||||
self.palette = main.globalAllocator.realloc(self.palette, @as(usize, 1) << self.data.bitSizeUnsafe());
|
||||
const newPalette = main.globalAllocator.alignedAlloc(Atomic(T), .@"64", @as(usize, 1) << self.data.bitSizeUnsafe());
|
||||
@memcpy(newPalette, self.palette.raw.toSlice()[0..newPalette.len]);
|
||||
main.heap.GarbageCollection.deferredFreeSlice(main.globalAllocator, self.palette.swap(.fromSlice(newPalette), .monotonic).toSlice());
|
||||
self.paletteOccupancy = main.globalAllocator.realloc(self.paletteOccupancy, @as(usize, 1) << self.data.bitSizeUnsafe());
|
||||
}
|
||||
};
|
||||
|
@ -585,8 +585,9 @@ pub const GarbageCollection = struct { // MARK: GarbageCollection
|
||||
freeFunction: *const fn(*anyopaque) void,
|
||||
};
|
||||
const FreeSliceItem = struct {
|
||||
slice: []const u8,
|
||||
slice: []u8,
|
||||
allocator: NeverFailingAllocator,
|
||||
alignment: std.mem.Alignment,
|
||||
};
|
||||
threadlocal var lists: [4]main.ListUnmanaged(FreeItem) = undefined;
|
||||
threadlocal var sliceLists: [4]main.ListUnmanaged(FreeSliceItem) = undefined;
|
||||
@ -621,7 +622,7 @@ pub const GarbageCollection = struct { // MARK: GarbageCollection
|
||||
|
||||
fn freeItemsFromSliceList(list: *main.ListUnmanaged(FreeSliceItem)) void {
|
||||
while(list.popOrNull()) |item| {
|
||||
item.allocator.free(item.slice);
|
||||
item.allocator.rawFree(item.slice, item.alignment, @returnAddress());
|
||||
}
|
||||
}
|
||||
|
||||
@ -686,10 +687,13 @@ pub const GarbageCollection = struct { // MARK: GarbageCollection
|
||||
lists[threadCycle].append(main.globalAllocator, item);
|
||||
}
|
||||
|
||||
pub fn deferredFreeSlice(allocator: NeverFailingAllocator, comptime T: type, items: []T) void {
|
||||
pub fn deferredFreeSlice(allocator: NeverFailingAllocator, items: anytype) void {
|
||||
if(items.len == 0) return;
|
||||
const Slice = @typeInfo(@TypeOf(items)).pointer;
|
||||
sliceLists[threadCycle].append(main.globalAllocator, .{
|
||||
.slice = std.mem.sliceAsBytes(items),
|
||||
.slice = @constCast(std.mem.sliceAsBytes(items)),
|
||||
.allocator = allocator,
|
||||
.alignment = .fromByteUnits(Slice.alignment),
|
||||
});
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user