Skip to content

Commit 8166870

Browse files
committed
Avoid some locking and extra calculations when checking all blocks in area
1 parent b670b8e commit 8166870

File tree

3 files changed

+25
-5
lines changed

3 files changed

+25
-5
lines changed

storage/voxel_data.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -582,9 +582,16 @@ bool VoxelData::has_block(Vector3i bpos, unsigned int lod_index) const {
582582

583583
bool VoxelData::has_all_blocks_in_area(Box3i data_blocks_box, unsigned int lod_index) const {
584584
ZN_PROFILE_SCOPE();
585+
// TODO get_bounds locks a mutex, it may be better for all callers to prefer the unbound version and clip
586+
// themselves, especially when doing this many times
585587
const Box3i bounds_in_blocks = get_bounds().downscaled(get_block_size() << lod_index);
586588
data_blocks_box = data_blocks_box.clipped(bounds_in_blocks);
587589

590+
return has_all_blocks_in_area_unbound(data_blocks_box, lod_index);
591+
}
592+
593+
bool VoxelData::has_all_blocks_in_area_unbound(Box3i data_blocks_box, unsigned int lod_index) const {
594+
// ZN_PROFILE_SCOPE();
588595
const Lod &data_lod = _lods[lod_index];
589596
RWLockRead rlock(data_lod.map_lock);
590597

storage/voxel_data.h

+5
Original file line numberDiff line numberDiff line change
@@ -205,8 +205,13 @@ class VoxelData {
205205
bool has_block(Vector3i bpos, unsigned int lod_index) const;
206206

207207
// Tests if all blocks in an area are loaded. If any isn't, returns false. Otherwise, returns true.
208+
// Accounts for data boundaries, but is slower as a result.
208209
bool has_all_blocks_in_area(Box3i data_blocks_box, unsigned int lod_index) const;
209210

211+
// Tests if all blocks in an area are loaded. If any isn't, returns false. Otherwise, returns true.
212+
// Doesn't account for data boundaries, so if the given box overlaps outside, it will return false.
213+
bool has_all_blocks_in_area_unbound(Box3i data_blocks_box, unsigned int lod_index) const;
214+
210215
// Gets the total amount of allocated blocks. This includes blocks having no voxel data.
211216
unsigned int get_block_count() const;
212217

terrain/variable_lod/voxel_lod_terrain_update_clipbox_streaming.cpp

+13-5
Original file line numberDiff line numberDiff line change
@@ -636,11 +636,16 @@ inline void schedule_mesh_load(std::vector<VoxelLodTerrainUpdateData::MeshToUpda
636636

637637
void view_mesh_box(const Box3i box_to_add, VoxelLodTerrainUpdateData::Lod &lod, unsigned int lod_index,
638638
bool is_full_load_mode, int mesh_to_data_factor, const VoxelData &voxel_data, bool require_visuals) {
639+
ZN_PROFILE_SCOPE();
640+
641+
const Box3i bounds_in_data_blocks = voxel_data.get_bounds().downscaled(voxel_data.get_block_size() << lod_index);
642+
639643
box_to_add.for_each_cell([&lod, //
640644
is_full_load_mode, //
641645
mesh_to_data_factor, //
642646
&voxel_data, lod_index, //
643-
require_visuals](Vector3i bpos) {
647+
require_visuals, //
648+
bounds_in_data_blocks](Vector3i bpos) {
644649
VoxelLodTerrainUpdateData::MeshBlockState *mesh_block;
645650
auto mesh_block_it = lod.mesh_map_state.map.find(bpos);
646651

@@ -694,13 +699,14 @@ void view_mesh_box(const Box3i box_to_add, VoxelLodTerrainUpdateData::Lod &lod,
694699
// or modified, so changing block size or viewer flags did not make meshes appear. Having two viewer
695700
// regions meet also caused problems.
696701

697-
const Box3i data_box =
698-
Box3i(bpos * mesh_to_data_factor, Vector3iUtil::create(mesh_to_data_factor)).padded(1);
702+
const Box3i data_box = Box3i(bpos * mesh_to_data_factor, Vector3iUtil::create(mesh_to_data_factor))
703+
.padded(1)
704+
.clipped(bounds_in_data_blocks);
699705

700706
// If we get an empty box at this point, something is wrong with the caller
701707
ZN_ASSERT_RETURN(!data_box.is_empty());
702708

703-
const bool data_available = voxel_data.has_all_blocks_in_area(data_box, lod_index);
709+
const bool data_available = voxel_data.has_all_blocks_in_area_unbound(data_box, lod_index);
704710

705711
if (data_available) {
706712
schedule_mesh_load(lod.mesh_blocks_pending_update, bpos, *mesh_block, require_visuals);
@@ -1043,6 +1049,8 @@ void process_loaded_data_blocks_trigger_meshing(const VoxelData &data, VoxelLodT
10431049

10441050
data_neighboring.for_each_cell([data_to_mesh_shift, &checked_mesh_blocks, &lod, &data, lod_index,
10451051
&bounds_in_data_blocks](Vector3i data_bpos) {
1052+
// ZN_PROFILE_SCOPE_NAMED("Cell");
1053+
10461054
const Vector3i mesh_block_pos = data_bpos >> data_to_mesh_shift;
10471055
if (!checked_mesh_blocks.insert(mesh_block_pos).second) {
10481056
// Already checked
@@ -1073,7 +1081,7 @@ void process_loaded_data_blocks_trigger_meshing(const VoxelData &data, VoxelLodT
10731081
Vector3iUtil::create((1 << data_to_mesh_shift) + 2))
10741082
.clipped(bounds_in_data_blocks);
10751083
// TODO Do a single grid query up-front, they will overlap so we do redundant lookups!
1076-
data_available = data.has_all_blocks_in_area(data_box, lod_index);
1084+
data_available = data.has_all_blocks_in_area_unbound(data_box, lod_index);
10771085
// } else {
10781086
// if (!data.is_full_load_completed()) {
10791087
// ZN_PRINT_ERROR("This function should not run until full load has completed");

0 commit comments

Comments
 (0)