From 63d9361a870330e3020b0f1941a62d2e689cc698 Mon Sep 17 00:00:00 2001 From: Marc Gilleron Date: Thu, 15 Apr 2021 20:16:27 +0100 Subject: [PATCH] Split refcounts --- terrain/voxel_data_block.h | 3 +- terrain/voxel_mesh_block.h | 3 +- terrain/voxel_terrain.cpp | 42 ++++++++++++------------- terrain/voxel_terrain.h | 2 +- terrain/voxel_viewer_ref_count.h | 53 ++++++-------------------------- 5 files changed, 33 insertions(+), 70 deletions(-) diff --git a/terrain/voxel_data_block.h b/terrain/voxel_data_block.h index d87aa3af..3666334a 100644 --- a/terrain/voxel_data_block.h +++ b/terrain/voxel_data_block.h @@ -11,8 +11,7 @@ public: Ref voxels; const Vector3i position; const unsigned int lod_index = 0; - // TODO Only data view type can be used here. Split it? - VoxelViewerRefCount viewers; + VoxelRefCount viewers; static VoxelDataBlock *create(Vector3i bpos, Ref buffer, unsigned int size, unsigned int p_lod_index) { const int bs = size; diff --git a/terrain/voxel_mesh_block.h b/terrain/voxel_mesh_block.h index 9c48fb7d..2cf5fff9 100644 --- a/terrain/voxel_mesh_block.h +++ b/terrain/voxel_mesh_block.h @@ -29,7 +29,8 @@ public: Vector3i position; unsigned int lod_index = 0; bool pending_transition_update = false; - VoxelViewerRefCount viewers; + VoxelRefCount mesh_viewers; + VoxelRefCount collision_viewers; bool got_first_mesh_update = false; uint32_t last_collider_update_time = 0; diff --git a/terrain/voxel_terrain.cpp b/terrain/voxel_terrain.cpp index b71212d4..2361cfed 100644 --- a/terrain/voxel_terrain.cpp +++ b/terrain/voxel_terrain.cpp @@ -310,8 +310,7 @@ void VoxelTerrain::try_schedule_mesh_update(VoxelMeshBlock *mesh_block) { // Already in the list return; } - if (mesh_block->viewers.get(VoxelViewerRefCount::TYPE_MESH) == 0 && - mesh_block->viewers.get(VoxelViewerRefCount::TYPE_COLLISION) == 0) { + if (mesh_block->mesh_viewers.get() == 0 && mesh_block->collision_viewers.get() == 0) { // No viewers want mesh on this block (why even call this function then?) return; } @@ -346,7 +345,7 @@ void VoxelTerrain::view_data_block(Vector3i bpos) { if (loading_block == nullptr) { // First viewer to request it LoadingBlock new_loading_block; - new_loading_block.viewers.add(VoxelViewerRefCount::TYPE_DATA); + new_loading_block.viewers.add(); // Schedule a loading request _loading_blocks.set(bpos, new_loading_block); @@ -354,12 +353,12 @@ void VoxelTerrain::view_data_block(Vector3i bpos) { } else { // More viewers - loading_block->viewers.add(VoxelViewerRefCount::TYPE_DATA); + loading_block->viewers.add(); } } else { // The block is loaded - block->viewers.add(VoxelViewerRefCount::TYPE_DATA); + block->viewers.add(); // TODO viewers with varying flags during the game is not supported at the moment. // They have to be re-created, which may cause world re-load... @@ -389,7 +388,12 @@ void VoxelTerrain::view_mesh_block(Vector3i bpos, bool mesh_flag, bool collision view_data_block(data_bpos); });*/ - block->viewers.add(false, mesh_flag, collision_flag); + if (mesh_flag) { + block->mesh_viewers.add(); + } + if (collision_flag) { + block->collision_viewers.add(); + } // This is needed in case a viewer wants to view meshes in places data blocks are already present. // Before that, meshes were updated only when a data block was loaded or modified, @@ -428,9 +432,9 @@ void VoxelTerrain::unview_data_block(Vector3i bpos) { return; } - loading_block->viewers.remove(VoxelViewerRefCount::TYPE_DATA); + loading_block->viewers.remove(); - if (loading_block->viewers.get(VoxelViewerRefCount::TYPE_DATA) == 0) { + if (loading_block->viewers.get() == 0) { // No longer want to load it _loading_blocks.erase(bpos); @@ -446,11 +450,8 @@ void VoxelTerrain::unview_data_block(Vector3i bpos) { } else { // The block is loaded - VoxelViewerRefCount &viewers = block->viewers; - - viewers.remove(VoxelViewerRefCount::TYPE_DATA); - - if (viewers.get(VoxelViewerRefCount::TYPE_DATA) == 0) { + block->viewers.remove(); + if (block->viewers.get() == 0) { // The block itself is no longer wanted unload_data_block(bpos); } @@ -470,25 +471,23 @@ void VoxelTerrain::unview_mesh_block(Vector3i bpos, bool mesh_flag, bool collisi unview_data_block(data_bpos); });*/ - VoxelViewerRefCount &viewers = block->viewers; - if (mesh_flag) { - viewers.remove(VoxelViewerRefCount::TYPE_MESH); - if (viewers.get(VoxelViewerRefCount::TYPE_MESH) == 0) { + block->mesh_viewers.remove(); + if (block->mesh_viewers.get() == 0) { // Mesh no longer required block->drop_mesh(); } } if (collision_flag) { - viewers.remove(VoxelViewerRefCount::TYPE_COLLISION); - if (viewers.get(VoxelViewerRefCount::TYPE_COLLISION) == 0) { + block->collision_viewers.remove(); + if (block->collision_viewers.get() == 0) { // Collision no longer required block->drop_collision(); } } - if (viewers.get(VoxelViewerRefCount::TYPE_MESH) == 0 && viewers.get(VoxelViewerRefCount::TYPE_COLLISION) == 0) { + if (block->collision_viewers.get() == 0 && block->collision_viewers.get() == 0) { unload_mesh_block(bpos); } } @@ -1555,8 +1554,7 @@ void VoxelTerrain::_process() { collidable_surfaces.clear(); } - const bool gen_collisions = - _generate_collisions && block->viewers.get(VoxelViewerRefCount::TYPE_COLLISION) > 0; + const bool gen_collisions = _generate_collisions && block->collision_viewers.get() > 0; block->set_mesh(mesh); if (gen_collisions) { diff --git a/terrain/voxel_terrain.h b/terrain/voxel_terrain.h index f05965f7..359c6817 100644 --- a/terrain/voxel_terrain.h +++ b/terrain/voxel_terrain.h @@ -176,7 +176,7 @@ private: // Therefore, could a simple grid be better to use than a hashmap? struct LoadingBlock { - VoxelViewerRefCount viewers; + VoxelRefCount viewers; }; HashMap _loading_blocks; diff --git a/terrain/voxel_viewer_ref_count.h b/terrain/voxel_viewer_ref_count.h index 67cee174..1e046f77 100644 --- a/terrain/voxel_viewer_ref_count.h +++ b/terrain/voxel_viewer_ref_count.h @@ -3,58 +3,23 @@ #include "../util/fixed_array.h" -class VoxelViewerRefCount { +class VoxelRefCount { public: - enum ViewerType { - TYPE_DATA = 0, // This one is always counted, others are optional - TYPE_MESH, - TYPE_COLLISION, - TYPE_COUNT - }; - - VoxelViewerRefCount() { - _counts.fill(0); + inline void add() { + ++_count; } - inline void add(bool data, bool mesh, bool collision) { - if (data) { - add(TYPE_DATA); - } - if (mesh) { - add(TYPE_MESH); - } - if (collision) { - add(TYPE_COLLISION); - } + inline void remove() { + ERR_FAIL_COND_MSG(_count == 0, "Trying to decrease refcount when it's already zero"); + --_count; } - inline void remove(bool data, bool mesh, bool collision) { - if (data) { - remove(TYPE_DATA); - } - if (mesh) { - remove(TYPE_MESH); - } - if (collision) { - remove(TYPE_COLLISION); - } - } - - inline void add(ViewerType t) { - ++_counts[t]; - } - - inline void remove(ViewerType t) { - CRASH_COND_MSG(_counts[t] == 0, "Trying to remove a viewer to a block that had none"); - --_counts[t]; - } - - inline uint32_t get(ViewerType t) const { - return _counts[t]; + inline unsigned int get() const { + return _count; } private: - FixedArray _counts; + unsigned int _count = 0; }; #endif // VOXEL_VIEWER_REF_COUNT_H