godot_voxel/streams/voxel_stream_cache.cpp
Marc Gilleron 1464286660 Add experimental key caching in VoxelStreamSQlite.
Not enabled by default, will test this in the future because it might
optimize multithreaded query speed in worlds with sparse saves.
2022-06-18 23:28:30 +01:00

106 lines
2.6 KiB
C++

#include "voxel_stream_cache.h"
namespace zylann::voxel {
bool VoxelStreamCache::load_voxel_block(Vector3i position, uint8_t lod_index, VoxelBufferInternal &out_voxels) {
const Lod &lod = _cache[lod_index];
RWLockRead rlock(lod.rw_lock);
auto it = lod.blocks.find(position);
if (it == lod.blocks.end()) {
// Not in cache, will have to query
return false;
} else {
// In cache, serve it
const VoxelBufferInternal &vb = it->second.voxels;
// Copying is required since the cache has ownership on its data,
// and the requests wants us to populate the buffer it provides
vb.duplicate_to(out_voxels, true);
return true;
}
}
void VoxelStreamCache::save_voxel_block(Vector3i position, uint8_t lod_index, VoxelBufferInternal &voxels) {
Lod &lod = _cache[lod_index];
RWLockWrite wlock(lod.rw_lock);
auto it = lod.blocks.find(position);
if (it == lod.blocks.end()) {
// Not cached yet, create an entry
Block b;
b.position = position;
b.lod = lod_index;
// TODO Optimization: if we know the buffer is not shared, we could use move instead
voxels.duplicate_to(b.voxels, true);
b.has_voxels = true;
lod.blocks.insert(std::make_pair(position, std::move(b)));
++_count;
} else {
// Cached already, overwrite
voxels.move_to(it->second.voxels);
it->second.has_voxels = true;
}
}
bool VoxelStreamCache::load_instance_block(
Vector3i position, uint8_t lod_index, UniquePtr<InstanceBlockData> &out_instances) {
const Lod &lod = _cache[lod_index];
lod.rw_lock.read_lock();
auto it = lod.blocks.find(position);
if (it == lod.blocks.end()) {
// Not in cache, will have to query
lod.rw_lock.read_unlock();
return false;
} else {
// In cache, serve it
if (it->second.instances == nullptr) {
out_instances = nullptr;
} else {
// Copying is required since the cache has ownership on its data
out_instances = make_unique_instance<InstanceBlockData>();
it->second.instances->copy_to(*out_instances);
}
lod.rw_lock.read_unlock();
return true;
}
}
void VoxelStreamCache::save_instance_block(
Vector3i position, uint8_t lod_index, UniquePtr<InstanceBlockData> instances) {
Lod &lod = _cache[lod_index];
RWLockWrite wlock(lod.rw_lock);
auto it = lod.blocks.find(position);
if (it == lod.blocks.end()) {
// Not cached yet, create an entry
Block b;
b.position = position;
b.lod = lod_index;
b.instances = std::move(instances);
lod.blocks.insert(std::make_pair(position, std::move(b)));
++_count;
} else {
// Cached already, overwrite
it->second.instances = std::move(instances);
}
}
unsigned int VoxelStreamCache::get_indicative_block_count() const {
return _count;
}
} // namespace zylann::voxel