From 7654e7852eccd25c9a05d9f2f2dde75d2acb8fd3 Mon Sep 17 00:00:00 2001 From: bitsawer Date: Tue, 26 Sep 2023 21:53:17 +0300 Subject: [PATCH] Fix RaycastOcclusionCull World3D scenario memory leak --- modules/raycast/raycast_occlusion_cull.cpp | 72 +++++++++------------- modules/raycast/raycast_occlusion_cull.h | 4 +- 2 files changed, 31 insertions(+), 45 deletions(-) diff --git a/modules/raycast/raycast_occlusion_cull.cpp b/modules/raycast/raycast_occlusion_cull.cpp index 234c2d161f9..5005000eae1 100644 --- a/modules/raycast/raycast_occlusion_cull.cpp +++ b/modules/raycast/raycast_occlusion_cull.cpp @@ -250,17 +250,15 @@ void RaycastOcclusionCull::free_occluder(RID p_occluder) { //////////////////////////////////////////////////////// void RaycastOcclusionCull::add_scenario(RID p_scenario) { - if (scenarios.has(p_scenario)) { - scenarios[p_scenario].removed = false; - } else { - scenarios[p_scenario] = Scenario(); - } + ERR_FAIL_COND(scenarios.has(p_scenario)); + scenarios[p_scenario] = Scenario(); } void RaycastOcclusionCull::remove_scenario(RID p_scenario) { - ERR_FAIL_COND(!scenarios.has(p_scenario)); - Scenario &scenario = scenarios[p_scenario]; - scenario.removed = true; + Scenario *scenario = scenarios.getptr(p_scenario); + ERR_FAIL_NULL(scenario); + scenario->free(); + scenarios.erase(p_scenario); } void RaycastOcclusionCull::scenario_set_instance(RID p_scenario, RID p_instance, RID p_occluder, const Transform3D &p_xform, bool p_enabled) { @@ -390,6 +388,23 @@ void RaycastOcclusionCull::Scenario::_transform_vertices_range(const Vector3 *p_ } } +void RaycastOcclusionCull::Scenario::free() { + if (commit_thread) { + if (commit_thread->is_started()) { + commit_thread->wait_to_finish(); + } + memdelete(commit_thread); + commit_thread = nullptr; + } + + for (int i = 0; i < 2; i++) { + if (ebr_scene[i]) { + rtcReleaseScene(ebr_scene[i]); + ebr_scene[i] = nullptr; + } + } +} + void RaycastOcclusionCull::Scenario::_commit_scene(void *p_ud) { Scenario *scenario = (Scenario *)p_ud; int commit_idx = 1 - (scenario->current_scene_idx); @@ -397,8 +412,8 @@ void RaycastOcclusionCull::Scenario::_commit_scene(void *p_ud) { scenario->commit_done = true; } -bool RaycastOcclusionCull::Scenario::update() { - ERR_FAIL_NULL_V(singleton, false); +void RaycastOcclusionCull::Scenario::update() { + ERR_FAIL_NULL(singleton); if (commit_thread == nullptr) { commit_thread = memnew(Thread); @@ -409,22 +424,12 @@ bool RaycastOcclusionCull::Scenario::update() { commit_thread->wait_to_finish(); current_scene_idx = 1 - current_scene_idx; } else { - return false; + return; } } - if (removed) { - if (ebr_scene[0]) { - rtcReleaseScene(ebr_scene[0]); - } - if (ebr_scene[1]) { - rtcReleaseScene(ebr_scene[1]); - } - return true; - } - if (!dirty && removed_instances.is_empty() && dirty_instances_array.is_empty()) { - return false; + return; } for (const RID &scenario : removed_instances) { @@ -480,7 +485,6 @@ bool RaycastOcclusionCull::Scenario::update() { dirty = false; commit_done = false; commit_thread->start(&Scenario::_commit_scene, this); - return false; } void RaycastOcclusionCull::Scenario::_raycast(uint32_t p_idx, const RaycastThreadData *p_raycast_data) const { @@ -544,13 +548,7 @@ void RaycastOcclusionCull::buffer_update(RID p_buffer, const Transform3D &p_cam_ } Scenario &scenario = scenarios[buffer.scenario_rid]; - - bool removed = scenario.update(); - - if (removed) { - scenarios.erase(buffer.scenario_rid); - return; - } + scenario.update(); buffer.update_camera_rays(p_cam_transform, p_cam_projection, p_cam_orthogonal); @@ -603,19 +601,7 @@ RaycastOcclusionCull::RaycastOcclusionCull() { RaycastOcclusionCull::~RaycastOcclusionCull() { for (KeyValue &K : scenarios) { - Scenario &scenario = K.value; - if (scenario.commit_thread) { - if (scenario.commit_thread->is_started()) { - scenario.commit_thread->wait_to_finish(); - } - memdelete(scenario.commit_thread); - } - - for (int i = 0; i < 2; i++) { - if (scenario.ebr_scene[i]) { - rtcReleaseScene(scenario.ebr_scene[i]); - } - } + K.value.free(); } if (ebr_device != nullptr) { diff --git a/modules/raycast/raycast_occlusion_cull.h b/modules/raycast/raycast_occlusion_cull.h index c4e733b6645..ab5eb4eaf04 100644 --- a/modules/raycast/raycast_occlusion_cull.h +++ b/modules/raycast/raycast_occlusion_cull.h @@ -132,7 +132,6 @@ private: Thread *commit_thread = nullptr; bool commit_done = true; bool dirty = false; - bool removed = false; RTCScene ebr_scene[2] = { nullptr, nullptr }; int current_scene_idx = 0; @@ -147,7 +146,8 @@ private: void _transform_vertices_thread(uint32_t p_thread, TransformThreadData *p_data); void _transform_vertices_range(const Vector3 *p_read, Vector3 *p_write, const Transform3D &p_xform, int p_from, int p_to); static void _commit_scene(void *p_ud); - bool update(); + void free(); + void update(); void _raycast(uint32_t p_thread, const RaycastThreadData *p_raycast_data) const; void raycast(CameraRayTile *r_rays, const uint32_t *p_valid_masks, uint32_t p_tile_count) const;