From 656f0ba9fa69592aa0b3c109370c1124d6f16efd Mon Sep 17 00:00:00 2001 From: Relintai Date: Fri, 6 Mar 2020 14:22:04 +0100 Subject: [PATCH] build_phase() and _build_phase() in Chunk now won't return/need to return a value, as get_build_phase_done() is equivalent. Also now chunk building is actually threaded, as it seems like I managed to remove thread creation in one of the refactor commits. Also fixed a few smaller issues/inconsistencies. --- world/voxel_chunk.cpp | 114 ++++++++++++++++++++++++------------------ world/voxel_chunk.h | 9 ++-- 2 files changed, 71 insertions(+), 52 deletions(-) diff --git a/world/voxel_chunk.cpp b/world/voxel_chunk.cpp index a7b29c3..a4f16fc 100644 --- a/world/voxel_chunk.cpp +++ b/world/voxel_chunk.cpp @@ -40,7 +40,7 @@ _FORCE_INLINE_ void VoxelChunk::set_is_build_threaded(bool value) { bool VoxelChunk::get_build_phase_done() const { _build_phase_done_mutex->lock(); - bool v = _build_phase_done_mutex; + bool v = _build_phase_done; _build_phase_done_mutex->unlock(); return v; @@ -616,15 +616,20 @@ void VoxelChunk::_create_meshers() { void VoxelChunk::build_deferred() { if (_current_build_phase == BUILD_PHASE_DONE) { - _build_prioritized = false; - - set_process_internal(true); + _build_prioritized = true; wait_and_finish_thread(); + set_process_internal(true); + _is_generating = true; next_phase(); + + if (!_voxel_world->can_chunk_do_build_step()) + return; + + build_step(); } } @@ -632,53 +637,64 @@ void VoxelChunk::build_prioritized() { if (_current_build_phase == BUILD_PHASE_DONE) { _build_prioritized = true; - set_process_internal(true); - wait_and_finish_thread(); + set_process_internal(true); + _is_generating = true; next_phase(); - _build_step(); + + if (!_voxel_world->can_chunk_do_build_step()) + return; + + build_step(); } } -void VoxelChunk::_build_step() { +void VoxelChunk::build_step() { ERR_FAIL_COND(!has_next_phase()); - while (has_next_phase() && build_phase()) - ; + if (get_is_build_threaded()) { + if (_build_thread) { + wait_and_finish_thread(); + } - //call the next non-threaded phase aswell - if (has_next_phase()) + _build_thread = Thread::create(_build_step_threaded, this); + return; + } + + while (has_next_phase() && get_build_phase_done()) { build_phase(); + } } -void VoxelChunk::_build_threaded(void *_userdata) { +void VoxelChunk::_build_step_threaded(void *_userdata) { VoxelChunk *vc = (VoxelChunk *)_userdata; - while (vc->has_next_phase() && vc->build_phase()) - ; + while (vc->has_next_phase() && vc->get_build_phase_done()) { + vc->build_phase(); + } } -bool VoxelChunk::build_phase() { +void VoxelChunk::build_phase() { _THREAD_SAFE_METHOD_ if (_abort_build) - return false; + return; set_build_phase_done(false); - return call("_build_phase", _current_build_phase); + call("_build_phase", _current_build_phase); } -bool VoxelChunk::_build_phase(int phase) { - ERR_FAIL_COND_V(!_library.is_valid(), true); +void VoxelChunk::_build_phase(int phase) { + ERR_FAIL_COND(!_library.is_valid()); switch (phase) { case BUILD_PHASE_DONE: - return true; + return; case BUILD_PHASE_SETUP: { if (_meshers.size() == 0) { create_meshers(); @@ -695,7 +711,7 @@ bool VoxelChunk::_build_phase(int phase) { next_phase(); - return true; + return; } case BUILD_PHASE_TERRARIN_MESH_SETUP: { for (int i = 0; i < _meshers.size(); ++i) { @@ -708,7 +724,7 @@ bool VoxelChunk::_build_phase(int phase) { next_phase(); - return true; + return; } case BUILD_PHASE_TERRARIN_MESH_COLLIDER: { if (get_create_collider()) { @@ -727,7 +743,7 @@ bool VoxelChunk::_build_phase(int phase) { next_phase(); - return true; + return; } case BUILD_PHASE_TERRARIN_MESH: { for (int i = 0; i < _meshers.size(); ++i) { @@ -746,10 +762,6 @@ bool VoxelChunk::_build_phase(int phase) { mesher->set_library(_library); } - if (_mesh_rid == RID()) { - allocate_main_mesh(); - } - Ref mesher; for (int i = 0; i < _meshers.size(); ++i) { Ref m = _meshers.get(i); @@ -766,26 +778,35 @@ bool VoxelChunk::_build_phase(int phase) { mesher->add_mesher(m); } - ERR_FAIL_COND_V(!mesher.is_valid(), false); - ERR_FAIL_COND_V(_mesh_rid == RID(), false); + ERR_FAIL_COND(!mesher.is_valid()); - VS::get_singleton()->mesh_clear(_mesh_rid); + temp_mesh_arr = mesher->build_mesh(); - if (mesher->get_vertex_count() == 0) { + if (_mesh_rid != RID()) + VS::get_singleton()->mesh_clear(_mesh_rid); + + PoolVector3Array v = temp_mesh_arr[VisualServer::ARRAY_VERTEX]; + + if (temp_mesh_arr.size() == 0 || v.size() == 0) { + temp_mesh_arr.clear(); next_phase(); - return true; + return; } - Array arr = mesher->build_mesh(); + if (_mesh_rid == RID()) { + allocate_main_mesh(); + } - VS::get_singleton()->mesh_add_surface_from_arrays(_mesh_rid, VisualServer::PRIMITIVE_TRIANGLES, arr); + VS::get_singleton()->mesh_add_surface_from_arrays(_mesh_rid, VisualServer::PRIMITIVE_TRIANGLES, temp_mesh_arr); if (_library->get_material().is_valid()) VS::get_singleton()->mesh_surface_set_material(_mesh_rid, 0, _library->get_material()->get_rid()); + temp_mesh_arr.clear(); + next_phase(); - return true; + return; } case BUILD_PHASE_PROP_MESH: { for (int i = 0; i < _meshers.size(); ++i) { @@ -809,13 +830,13 @@ bool VoxelChunk::_build_phase(int phase) { mesher->bake_colors(this); mesher->set_material(get_library()->get_material()); - ERR_FAIL_COND_V(_prop_mesh_rid == RID(), false); + ERR_FAIL_COND(_prop_mesh_rid == RID()); VS::get_singleton()->mesh_clear(_prop_mesh_rid); if (mesher->get_vertex_count() == 0) { next_phase(); - return true; + return; } Array arr = mesher->build_mesh(); @@ -829,7 +850,7 @@ bool VoxelChunk::_build_phase(int phase) { next_phase(); - return false; + return; } case BUILD_PHASE_PROP_COLLIDER: { @@ -849,7 +870,7 @@ bool VoxelChunk::_build_phase(int phase) { next_phase(); - return true; + return; } /* case BUILD_PHASE_LIQUID: { @@ -876,12 +897,9 @@ bool VoxelChunk::_build_phase(int phase) { next_phase(); - return true; + return; } } - - return true; - //next_phase(); } bool VoxelChunk::has_next_phase() { @@ -1426,13 +1444,13 @@ void VoxelChunk::_notification(int p_what) { } } case NOTIFICATION_INTERNAL_PROCESS: { - if (has_next_phase() && get_build_phase_done()) { + if (get_is_generating() && has_next_phase() && get_build_phase_done()) { if (!_voxel_world->can_chunk_do_build_step()) return; wait_and_finish_thread(); - _build_step(); + build_step(); } } } @@ -1651,7 +1669,7 @@ void VoxelChunk::_bind_methods() { ClassDB::bind_method(D_METHOD("clear_baked_lights"), &VoxelChunk::clear_baked_lights); //Meshes - BIND_VMETHOD(MethodInfo(PropertyInfo(Variant::BOOL, "is_done"), "_build_phase", PropertyInfo(Variant::INT, "phase"))); + BIND_VMETHOD(MethodInfo("_build_phase", PropertyInfo(Variant::INT, "phase"))); ClassDB::bind_method(D_METHOD("build_deferred"), &VoxelChunk::build_deferred); ClassDB::bind_method(D_METHOD("build_prioritized"), &VoxelChunk::build_prioritized); @@ -1722,8 +1740,8 @@ void VoxelChunk::_bind_methods() { BIND_CONSTANT(BUILD_PHASE_SETUP); BIND_CONSTANT(BUILD_PHASE_TERRARIN_MESH_SETUP); BIND_CONSTANT(BUILD_PHASE_TERRARIN_MESH_COLLIDER); - BIND_CONSTANT(BUILD_PHASE_LIGHTS); BIND_CONSTANT(BUILD_PHASE_TERRARIN_MESH); + BIND_CONSTANT(BUILD_PHASE_LIGHTS); BIND_CONSTANT(BUILD_PHASE_PROP_MESH); BIND_CONSTANT(BUILD_PHASE_PROP_COLLIDER); BIND_CONSTANT(BUILD_PHASE_FINALIZE); diff --git a/world/voxel_chunk.h b/world/voxel_chunk.h index 47e50e1..a2700a5 100644 --- a/world/voxel_chunk.h +++ b/world/voxel_chunk.h @@ -236,11 +236,11 @@ public: void build_deferred(); void build_prioritized(); - static void _build_threaded(void *_userdata); + static void _build_step_threaded(void *_userdata); - bool build_phase(); - void _build_step(); - bool _build_phase(int phase); + void build_phase(); + void build_step(); + void _build_phase(int phase); bool has_next_phase(); void next_phase(); @@ -393,6 +393,7 @@ protected: Mutex *_build_phase_done_mutex; bool _build_phase_done; Thread *_build_thread; + Array temp_mesh_arr; }; VARIANT_ENUM_CAST(VoxelChunk::DefaultChannels);