Block mutability for aligned bitfields (1.16 style)
TODO: "In versions prior to 1.16, the full range of bits is used, where the remaining bits of a block index continue on the next long value."
This commit is contained in:
parent
b15e039d61
commit
b218552cc4
|
@ -246,10 +246,17 @@ namespace Feather
|
|||
sections.WriteVarInt(sect.blockStates.palette.ByID(j));
|
||||
}
|
||||
|
||||
// Block State Data
|
||||
|
||||
sections.WriteVarInt(dataLength);
|
||||
// Can't just copy because endian-ness!
|
||||
for (size_t i = 0; i < dataLength; i++)
|
||||
sections.Write<uint64_t>(sect.blockStates.data[i]);
|
||||
|
||||
{
|
||||
auto [data, lock] = sect.blockStates.data.borrow();
|
||||
|
||||
// Can't just copy because endian-ness!
|
||||
for (size_t i = 0; i < dataLength; i++)
|
||||
sections.Write<uint64_t>(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
//Log::Trace("Section bits: {:#b}", sectionsBits);
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#include <mutex>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <array>
|
||||
|
||||
namespace Feather
|
||||
{
|
||||
|
@ -25,4 +27,10 @@ namespace Feather
|
|||
|
||||
template <typename T>
|
||||
using LockableList = Lockable<std::list<T>>;
|
||||
|
||||
template <typename Key, typename T>
|
||||
using LockableMap = Lockable<std::map<Key, T>>;
|
||||
|
||||
template <typename T, size_t Size>
|
||||
using LockableArray = Lockable<std::array<T, Size>>;
|
||||
}
|
||||
|
|
|
@ -46,6 +46,11 @@ namespace Feather
|
|||
return m_IDtoValue.at(id);
|
||||
}
|
||||
|
||||
inline bool HasValue(const T& value) const
|
||||
{
|
||||
return m_ValueToID.contains(value);
|
||||
}
|
||||
|
||||
inline size_t Size() const
|
||||
{
|
||||
return m_IDtoValue.size();
|
||||
|
@ -53,4 +58,4 @@ namespace Feather
|
|||
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -96,8 +96,12 @@ namespace Feather
|
|||
|
||||
Assert(blockStates.GetLength() < section->blockStates.GetNumLongs());
|
||||
|
||||
for (size_t i = 0; i < blockStates.GetLength(); i++)
|
||||
section->blockStates.data[i] = blockStates[i];
|
||||
{
|
||||
auto [data, lock] = section->blockStates.data.borrow();
|
||||
|
||||
for (size_t i = 0; i < blockStates.GetLength(); i++)
|
||||
data[i] = blockStates[i];
|
||||
}
|
||||
|
||||
section->blockStates.SetBits(Math::CeilDiv(blockStates.GetLength() * bitsizeof(int64), ChunkSection::NUM_BLOCKS));
|
||||
|
||||
|
@ -108,11 +112,40 @@ namespace Feather
|
|||
|
||||
}
|
||||
|
||||
bool Chunk::SetBlock(BlockPos& pos, BlockState& state)
|
||||
bool Chunk::SetBlock(const BlockPos& pos, const BlockState& state)
|
||||
{
|
||||
ChunkSection& section = sections[GetSection(pos)];
|
||||
int i = GetSection(pos);
|
||||
ChunkSection& section = sections[i];
|
||||
|
||||
Log::Debug("Chunk::SetBlock: ({}, {}, {}) -> ({}, {}, {}) Chunk Local",
|
||||
pos.x, pos.y, pos.z,
|
||||
pos.x & 0xF, pos.y & 0xF, pos.z & 0xF
|
||||
);
|
||||
|
||||
int index = GetSectionIndex(pos);
|
||||
|
||||
Log::Debug("Chunk::SetBlock -> section {}, index {}", i, index);
|
||||
|
||||
//if (!section.blockStates.palette.HasValue(state))
|
||||
|
||||
return false;
|
||||
// TODO: temp code. use BlockState instead of global ID
|
||||
{
|
||||
int id = World::GLOBAL_PALETTE.GetID(state);
|
||||
|
||||
if (!section.blockStates.palette.HasValue(id)) {
|
||||
Log::Warn("Chunk::SetBlock for block that is not in section's local palette. NYI");
|
||||
return false;
|
||||
}
|
||||
|
||||
int localId = section.blockStates.palette.GetID(id);
|
||||
|
||||
uint prev = section.blockStates.GetAndSet(index, localId);
|
||||
|
||||
Log::Debug("Chunk::SetBlock changed block from {} to {}", prev, localId);
|
||||
}
|
||||
|
||||
//section.blockStates.GetAndSet(GetSectionIndex(pos), )
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,8 +44,17 @@ namespace Feather
|
|||
|
||||
Chunk(ChunkPos& pos, std::unique_ptr<NBT::CompoundTag> tag);
|
||||
|
||||
inline int GetSection(BlockPos& pos) { return pos.y >> 4; }
|
||||
inline int GetSection(const BlockPos& pos) { return pos.y >> 4; }
|
||||
|
||||
bool SetBlock(BlockPos& pos, BlockState& state);
|
||||
inline int GetSectionIndex(const BlockPos& pos)
|
||||
{
|
||||
int x = pos.x & 0xF;
|
||||
int y = pos.y & 0xF;
|
||||
int z = pos.z & 0xF;
|
||||
|
||||
return y << 8 | z << 4 | x;
|
||||
}
|
||||
|
||||
bool SetBlock(const BlockPos& pos, const BlockState& state);
|
||||
};
|
||||
};
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
|
||||
#include "Common.h"
|
||||
#include "Palette.h"
|
||||
|
||||
#include <array>
|
||||
#include "Lockable.h"
|
||||
|
||||
namespace Feather
|
||||
{
|
||||
|
@ -15,7 +14,9 @@ namespace Feather
|
|||
|
||||
static constexpr size_t NUM_LONGS = Math::CeilDiv(MaxSize * MaxBits, bitsizeof(uint64));
|
||||
|
||||
std::array<uint64, NUM_LONGS> data;
|
||||
static constexpr size_t BITS_PER_CELL = bitsizeof(uint64);
|
||||
|
||||
LockableArray<uint64, NUM_LONGS> data;
|
||||
|
||||
// TODO: this could eventually be Palette<BlockState> to avoid double lookup
|
||||
// Palette of local indexs to indexs in the global palette
|
||||
|
@ -23,11 +24,53 @@ namespace Feather
|
|||
|
||||
uint size = MaxSize;
|
||||
uint8 bits = MaxBits;
|
||||
uint64 mask = 0;
|
||||
uint valuesPerCell = 0;
|
||||
|
||||
public:
|
||||
PalettedContainer(uint size, uint8 bits) : size(size), bits(bits), data() {}
|
||||
PalettedContainer(uint size, uint8 bits) : size(size), data() { SetBits(bits); }
|
||||
|
||||
inline void SetBits(uint8 nbits) { bits = nbits; }
|
||||
inline void SetBits(uint8 nbits)
|
||||
{
|
||||
bits = nbits;
|
||||
mask = (1 << bits) - 1;
|
||||
valuesPerCell = BITS_PER_CELL / bits;
|
||||
|
||||
Log::Debug("PalettedContainer::SetBits: {}, mask = {:#b}, valuesPerCell = {}", bits, mask, valuesPerCell);
|
||||
}
|
||||
|
||||
// TODO: optimize all math here
|
||||
|
||||
inline int CellIndex(int index)
|
||||
{
|
||||
return index / valuesPerCell;
|
||||
}
|
||||
|
||||
// Update value, returns previous value
|
||||
// TODO: change from uint to const T&
|
||||
inline uint GetAndSet(int index, uint value)
|
||||
{
|
||||
auto [d, lock] = data.borrow();
|
||||
|
||||
int id = value; // palette.GetID(value);
|
||||
int cellIndex = CellIndex(index);
|
||||
uint64 shift = (index - cellIndex * valuesPerCell) * bits;//(index % valuesPerCell) * bits;
|
||||
|
||||
Log::Debug("PalettedContainer::GetAndSet: index {} -> cell {}, [{}:{}]", index, cellIndex, shift, shift + bits);
|
||||
|
||||
uint64 cell = d[cellIndex];
|
||||
int prev = (cell >> shift) & mask;
|
||||
|
||||
//d[cellIndex] = ((cell & (mask << shift ^ 0xFFFFFFFFFFFFFFFFL)) | (uint64(id) & mask)) << shift;
|
||||
|
||||
d[cellIndex] &= ~(mask << shift); // clear target bits
|
||||
d[cellIndex] |= ((uint64)id & mask) << shift; // set target bits
|
||||
|
||||
//Log::Debug("Changed from {:#b} to {:#b}", cell, d[cellIndex]);
|
||||
Log::Debug("Changed from {} (g: {}) to {} (g: {})", prev, palette.ByID(prev), value, palette.ByID(value));
|
||||
|
||||
return (uint)prev; // palette.ByID(prev);
|
||||
}
|
||||
|
||||
inline constexpr size_t GetNumLongs() { return NUM_LONGS; }
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue