Change RID_Owner::get_owned_list.

This commit is contained in:
Yyf2333 2025-01-21 21:23:46 +08:00 committed by Yufeng Ying
parent 2d3bdcac35
commit 1a70a06a43
11 changed files with 74 additions and 102 deletions

View file

@ -33,7 +33,7 @@
#include "core/os/memory.h" #include "core/os/memory.h"
#include "core/os/mutex.h" #include "core/os/mutex.h"
#include "core/string/print_string.h" #include "core/string/print_string.h"
#include "core/templates/list.h" #include "core/templates/local_vector.h"
#include "core/templates/rid.h" #include "core/templates/rid.h"
#include "core/templates/safe_refcount.h" #include "core/templates/safe_refcount.h"
@ -382,19 +382,21 @@ public:
_FORCE_INLINE_ uint32_t get_rid_count() const { _FORCE_INLINE_ uint32_t get_rid_count() const {
return alloc_count; return alloc_count;
} }
void get_owned_list(List<RID> *p_owned) const { LocalVector<RID> get_owned_list() const {
LocalVector<RID> owned;
if constexpr (THREAD_SAFE) { if constexpr (THREAD_SAFE) {
mutex.lock(); mutex.lock();
} }
for (size_t i = 0; i < max_alloc; i++) { for (size_t i = 0; i < max_alloc; i++) {
uint64_t validator = chunks[i / elements_in_chunk][i % elements_in_chunk].validator; uint64_t validator = chunks[i / elements_in_chunk][i % elements_in_chunk].validator;
if (validator != 0xFFFFFFFF) { if (validator != 0xFFFFFFFF) {
p_owned->push_back(_make_from_id((validator << 32) | i)); owned.push_back(_make_from_id((validator << 32) | i));
} }
} }
if constexpr (THREAD_SAFE) { if constexpr (THREAD_SAFE) {
mutex.unlock(); mutex.unlock();
} }
return owned;
} }
//used for fast iteration in the elements or RIDs //used for fast iteration in the elements or RIDs
@ -506,8 +508,8 @@ public:
return alloc.get_rid_count(); return alloc.get_rid_count();
} }
_FORCE_INLINE_ void get_owned_list(List<RID> *p_owned) const { _FORCE_INLINE_ LocalVector<RID> get_owned_list() const {
return alloc.get_owned_list(p_owned); return alloc.get_owned_list();
} }
void fill_owned_buffer(RID *p_rid_buffer) const { void fill_owned_buffer(RID *p_rid_buffer) const {
@ -562,8 +564,8 @@ public:
return alloc.get_rid_count(); return alloc.get_rid_count();
} }
_FORCE_INLINE_ void get_owned_list(List<RID> *p_owned) const { _FORCE_INLINE_ LocalVector<RID> get_owned_list() const {
return alloc.get_owned_list(p_owned); return alloc.get_owned_list();
} }
void fill_owned_buffer(RID *p_rid_buffer) const { void fill_owned_buffer(RID *p_rid_buffer) const {
alloc.fill_owned_buffer(p_rid_buffer); alloc.fill_owned_buffer(p_rid_buffer);

View file

@ -841,13 +841,11 @@ bool ShaderGLES3::shader_cache_save_compressed_zstd = true;
bool ShaderGLES3::shader_cache_save_debug = true; bool ShaderGLES3::shader_cache_save_debug = true;
ShaderGLES3::~ShaderGLES3() { ShaderGLES3::~ShaderGLES3() {
List<RID> remaining; LocalVector<RID> remaining = version_owner.get_owned_list();
version_owner.get_owned_list(&remaining);
if (remaining.size()) { if (remaining.size()) {
ERR_PRINT(itos(remaining.size()) + " shaders of type " + name + " were never freed"); ERR_PRINT(itos(remaining.size()) + " shaders of type " + name + " were never freed");
while (remaining.size()) { for (RID &rid : remaining) {
version_free(remaining.front()->get()); version_free(rid);
remaining.pop_front();
} }
} }
} }

View file

@ -1470,10 +1470,7 @@ void TextureStorage::texture_set_detect_roughness_callback(RID p_texture, RS::Te
} }
void TextureStorage::texture_debug_usage(List<RS::TextureInfo> *r_info) { void TextureStorage::texture_debug_usage(List<RS::TextureInfo> *r_info) {
List<RID> textures; for (const RID &rid : texture_owner.get_owned_list()) {
texture_owner.get_owned_list(&textures);
for (const RID &rid : textures) {
Texture *t = texture_owner.get_or_null(rid); Texture *t = texture_owner.get_or_null(rid);
if (!t) { if (!t) {
continue; continue;

View file

@ -32,6 +32,7 @@
#include "core/os/mutex.h" #include "core/os/mutex.h"
#include "scene/main/node.h" #include "scene/main/node.h"
#include <cstdint>
#ifdef CLIPPER2_ENABLED #ifdef CLIPPER2_ENABLED
#include "nav_mesh_generator_2d.h" #include "nav_mesh_generator_2d.h"
@ -193,11 +194,12 @@ void GodotNavigationServer2D::add_command(SetCommand2D *p_command) {
TypedArray<RID> GodotNavigationServer2D::get_maps() const { TypedArray<RID> GodotNavigationServer2D::get_maps() const {
TypedArray<RID> all_map_rids; TypedArray<RID> all_map_rids;
List<RID> maps_owned; LocalVector<RID> maps_owned = map_owner.get_owned_list();
map_owner.get_owned_list(&maps_owned); uint32_t map_count = maps_owned.size();
if (maps_owned.size()) { if (map_count) {
for (const RID &E : maps_owned) { all_map_rids.resize(map_count);
all_map_rids.push_back(E); for (uint32_t i = 0; i < map_count; i++) {
all_map_rids[i] = maps_owned[i];
} }
} }
return all_map_rids; return all_map_rids;

View file

@ -94,11 +94,12 @@ void GodotNavigationServer3D::add_command(SetCommand3D *command) {
TypedArray<RID> GodotNavigationServer3D::get_maps() const { TypedArray<RID> GodotNavigationServer3D::get_maps() const {
TypedArray<RID> all_map_rids; TypedArray<RID> all_map_rids;
List<RID> maps_owned; LocalVector<RID> maps_owned = map_owner.get_owned_list();
map_owner.get_owned_list(&maps_owned); uint32_t map_count = maps_owned.size();
if (maps_owned.size()) { if (map_count) {
for (const RID &E : maps_owned) { all_map_rids.resize(map_count);
all_map_rids.push_back(E); for (uint32_t i = 0; i < map_count; i++) {
all_map_rids[i] = maps_owned[i];
} }
} }
return all_map_rids; return all_map_rids;

View file

@ -1415,9 +1415,7 @@ bool OpenXRAPI::on_state_synchronized() {
print_verbose("On state synchronized"); print_verbose("On state synchronized");
// Just in case, see if we already have active trackers... // Just in case, see if we already have active trackers...
List<RID> trackers; for (const RID &tracker : tracker_owner.get_owned_list()) {
tracker_owner.get_owned_list(&trackers);
for (const RID &tracker : trackers) {
tracker_check_profile(tracker); tracker_check_profile(tracker);
} }
@ -2066,9 +2064,7 @@ bool OpenXRAPI::poll_events() {
XrEventDataInteractionProfileChanged *event = (XrEventDataInteractionProfileChanged *)&runtimeEvent; XrEventDataInteractionProfileChanged *event = (XrEventDataInteractionProfileChanged *)&runtimeEvent;
List<RID> trackers; for (const RID &tracker : tracker_owner.get_owned_list()) {
tracker_owner.get_owned_list(&trackers);
for (const RID &tracker : trackers) {
tracker_check_profile(tracker, event->session); tracker_check_profile(tracker, event->session);
} }
@ -2897,12 +2893,10 @@ XrPath OpenXRAPI::get_xr_path(const String &p_path) {
} }
RID OpenXRAPI::get_tracker_rid(XrPath p_path) { RID OpenXRAPI::get_tracker_rid(XrPath p_path) {
List<RID> current; for (const RID &tracker_rid : tracker_owner.get_owned_list()) {
tracker_owner.get_owned_list(&current); Tracker *tracker = tracker_owner.get_or_null(tracker_rid);
for (const RID &E : current) {
Tracker *tracker = tracker_owner.get_or_null(E);
if (tracker && tracker->toplevel_path == p_path) { if (tracker && tracker->toplevel_path == p_path) {
return E; return tracker_rid;
} }
} }
@ -2910,12 +2904,10 @@ RID OpenXRAPI::get_tracker_rid(XrPath p_path) {
} }
RID OpenXRAPI::find_tracker(const String &p_name) { RID OpenXRAPI::find_tracker(const String &p_name) {
List<RID> current; for (const RID &tracker_rid : tracker_owner.get_owned_list()) {
tracker_owner.get_owned_list(&current); Tracker *tracker = tracker_owner.get_or_null(tracker_rid);
for (const RID &E : current) {
Tracker *tracker = tracker_owner.get_or_null(E);
if (tracker && tracker->name == p_name) { if (tracker && tracker->name == p_name) {
return E; return tracker_rid;
} }
} }
@ -3023,12 +3015,10 @@ RID OpenXRAPI::action_set_create(const String p_name, const String p_localized_n
} }
RID OpenXRAPI::find_action_set(const String p_name) { RID OpenXRAPI::find_action_set(const String p_name) {
List<RID> current; for (const RID &action_set_rid : action_set_owner.get_owned_list()) {
action_set_owner.get_owned_list(&current); ActionSet *action_set = action_set_owner.get_or_null(action_set_rid);
for (const RID &E : current) {
ActionSet *action_set = action_set_owner.get_or_null(E);
if (action_set && action_set->name == p_name) { if (action_set && action_set->name == p_name) {
return E; return action_set_rid;
} }
} }
@ -3127,12 +3117,10 @@ void OpenXRAPI::action_set_free(RID p_action_set) {
} }
RID OpenXRAPI::get_action_rid(XrAction p_action) { RID OpenXRAPI::get_action_rid(XrAction p_action) {
List<RID> current; for (const RID &action_rid : action_owner.get_owned_list()) {
action_owner.get_owned_list(&current); Action *action = action_owner.get_or_null(action_rid);
for (const RID &E : current) {
Action *action = action_owner.get_or_null(E);
if (action && action->handle == p_action) { if (action && action->handle == p_action) {
return E; return action_rid;
} }
} }
@ -3140,12 +3128,10 @@ RID OpenXRAPI::get_action_rid(XrAction p_action) {
} }
RID OpenXRAPI::find_action(const String &p_name, const RID &p_action_set) { RID OpenXRAPI::find_action(const String &p_name, const RID &p_action_set) {
List<RID> current; for (const RID &action_rid : action_owner.get_owned_list()) {
action_owner.get_owned_list(&current); Action *action = action_owner.get_or_null(action_rid);
for (const RID &E : current) {
Action *action = action_owner.get_or_null(E);
if (action && action->name == p_name && (p_action_set.is_null() || action->action_set_rid == p_action_set)) { if (action && action->name == p_name && (p_action_set.is_null() || action->action_set_rid == p_action_set)) {
return E; return action_rid;
} }
} }
@ -3257,12 +3243,10 @@ void OpenXRAPI::action_free(RID p_action) {
} }
RID OpenXRAPI::get_interaction_profile_rid(XrPath p_path) { RID OpenXRAPI::get_interaction_profile_rid(XrPath p_path) {
List<RID> current; for (const RID &ip_rid : interaction_profile_owner.get_owned_list()) {
interaction_profile_owner.get_owned_list(&current); InteractionProfile *ip = interaction_profile_owner.get_or_null(ip_rid);
for (const RID &E : current) {
InteractionProfile *ip = interaction_profile_owner.get_or_null(E);
if (ip && ip->path == p_path) { if (ip && ip->path == p_path) {
return E; return ip_rid;
} }
} }

View file

@ -2670,16 +2670,15 @@ bool RendererCanvasCull::free(RID p_rid) {
template <typename T> template <typename T>
void RendererCanvasCull::_free_rids(T &p_owner, const char *p_type) { void RendererCanvasCull::_free_rids(T &p_owner, const char *p_type) {
List<RID> owned; LocalVector<RID> owned = p_owner.get_owned_list();
p_owner.get_owned_list(&owned);
if (owned.size()) { if (owned.size()) {
if (owned.size() == 1) { if (owned.size() == 1) {
WARN_PRINT(vformat("1 RID of type \"%s\" was leaked.", p_type)); WARN_PRINT(vformat("1 RID of type \"%s\" was leaked.", p_type));
} else { } else {
WARN_PRINT(vformat("%d RIDs of type \"%s\" were leaked.", owned.size(), p_type)); WARN_PRINT(vformat("%d RIDs of type \"%s\" were leaked.", owned.size(), p_type));
} }
for (const RID &E : owned) { for (const RID &rid : owned) {
free(E); free(rid);
} }
} }
} }

View file

@ -748,10 +748,8 @@ void ShaderRD::enable_group(int p_group) {
group_enabled.write[p_group] = true; group_enabled.write[p_group] = true;
// Compile all versions again to include the new group. // Compile all versions again to include the new group.
List<RID> all_versions; for (const RID &version_rid : version_owner.get_owned_list()) {
version_owner.get_owned_list(&all_versions); Version *version = version_owner.get_or_null(version_rid);
for (const RID &E : all_versions) {
Version *version = version_owner.get_or_null(E);
version->mutex->lock(); version->mutex->lock();
_compile_version_start(version, p_group); _compile_version_start(version, p_group);
version->mutex->unlock(); version->mutex->unlock();
@ -907,13 +905,11 @@ bool ShaderRD::shader_cache_save_compressed_zstd = true;
bool ShaderRD::shader_cache_save_debug = true; bool ShaderRD::shader_cache_save_debug = true;
ShaderRD::~ShaderRD() { ShaderRD::~ShaderRD() {
List<RID> remaining; LocalVector<RID> remaining = version_owner.get_owned_list();
version_owner.get_owned_list(&remaining);
if (remaining.size()) { if (remaining.size()) {
ERR_PRINT(itos(remaining.size()) + " shaders of type " + name + " were never freed"); ERR_PRINT(itos(remaining.size()) + " shaders of type " + name + " were never freed");
while (remaining.size()) { for (const RID &version_rid : remaining) {
version_free(remaining.front()->get()); version_free(version_rid);
remaining.pop_front();
} }
} }
} }

View file

@ -1640,10 +1640,7 @@ void TextureStorage::texture_set_detect_roughness_callback(RID p_texture, RS::Te
} }
void TextureStorage::texture_debug_usage(List<RS::TextureInfo> *r_info) { void TextureStorage::texture_debug_usage(List<RS::TextureInfo> *r_info) {
List<RID> textures; for (const RID &rid : texture_owner.get_owned_list()) {
texture_owner.get_owned_list(&textures);
for (const RID &rid : textures) {
Texture *t = texture_owner.get_or_null(rid); Texture *t = texture_owner.get_or_null(rid);
if (!t) { if (!t) {
continue; continue;

View file

@ -6946,21 +6946,20 @@ void RenderingDevice::_save_pipeline_cache(void *p_data) {
template <typename T> template <typename T>
void RenderingDevice::_free_rids(T &p_owner, const char *p_type) { void RenderingDevice::_free_rids(T &p_owner, const char *p_type) {
List<RID> owned; LocalVector<RID> owned = p_owner.get_owned_list();
p_owner.get_owned_list(&owned);
if (owned.size()) { if (owned.size()) {
if (owned.size() == 1) { if (owned.size() == 1) {
WARN_PRINT(vformat("1 RID of type \"%s\" was leaked.", p_type)); WARN_PRINT(vformat("1 RID of type \"%s\" was leaked.", p_type));
} else { } else {
WARN_PRINT(vformat("%d RIDs of type \"%s\" were leaked.", owned.size(), p_type)); WARN_PRINT(vformat("%d RIDs of type \"%s\" were leaked.", owned.size(), p_type));
} }
for (const RID &E : owned) { for (const RID &rid : owned) {
#ifdef DEV_ENABLED #ifdef DEV_ENABLED
if (resource_names.has(E)) { if (resource_names.has(rid)) {
print_line(String(" - ") + resource_names[E]); print_line(String(" - ") + resource_names[rid]);
} }
#endif #endif
free(E); free(rid);
} }
} }
} }
@ -7157,36 +7156,35 @@ void RenderingDevice::finalize() {
_free_rids(sampler_owner, "Sampler"); _free_rids(sampler_owner, "Sampler");
{ {
// For textures it's a bit more difficult because they may be shared. // For textures it's a bit more difficult because they may be shared.
List<RID> owned; LocalVector<RID> owned = texture_owner.get_owned_list();
texture_owner.get_owned_list(&owned);
if (owned.size()) { if (owned.size()) {
if (owned.size() == 1) { if (owned.size() == 1) {
WARN_PRINT("1 RID of type \"Texture\" was leaked."); WARN_PRINT("1 RID of type \"Texture\" was leaked.");
} else { } else {
WARN_PRINT(vformat("%d RIDs of type \"Texture\" were leaked.", owned.size())); WARN_PRINT(vformat("%d RIDs of type \"Texture\" were leaked.", owned.size()));
} }
LocalVector<RID> owned_non_shared;
// Free shared first. // Free shared first.
for (List<RID>::Element *E = owned.front(); E;) { for (const RID &texture_rid : owned) {
List<RID>::Element *N = E->next(); if (texture_is_shared(texture_rid)) {
if (texture_is_shared(E->get())) {
#ifdef DEV_ENABLED #ifdef DEV_ENABLED
if (resource_names.has(E->get())) { if (resource_names.has(texture_rid)) {
print_line(String(" - ") + resource_names[E->get()]); print_line(String(" - ") + resource_names[texture_rid]);
} }
#endif #endif
free(E->get()); free(texture_rid);
owned.erase(E); } else {
owned_non_shared.push_back(texture_rid);
} }
E = N;
} }
// Free non shared second, this will avoid an error trying to free unexisting textures due to dependencies. // Free non shared second, this will avoid an error trying to free unexisting textures due to dependencies.
for (const RID &E : owned) { for (const RID &texture_rid : owned_non_shared) {
#ifdef DEV_ENABLED #ifdef DEV_ENABLED
if (resource_names.has(E)) { if (resource_names.has(texture_rid)) {
print_line(String(" - ") + resource_names[E]); print_line(String(" - ") + resource_names[texture_rid]);
} }
#endif #endif
free(E); free(texture_rid);
} }
} }
} }

View file

@ -57,9 +57,7 @@ void RendererCompositorStorage::compositor_effect_free(RID p_rid) {
ERR_FAIL_NULL(effect); ERR_FAIL_NULL(effect);
// Remove this RID from any compositor that uses it. // Remove this RID from any compositor that uses it.
List<RID> compositor_rids; for (const RID &compositor_rid : compositor_owner.get_owned_list()) {
compositor_owner.get_owned_list(&compositor_rids);
for (const RID &compositor_rid : compositor_rids) {
Compositor *compositor = compositor_owner.get_or_null(compositor_rid); Compositor *compositor = compositor_owner.get_or_null(compositor_rid);
if (compositor) { if (compositor) {
compositor->compositor_effects.erase(p_rid); compositor->compositor_effects.erase(p_rid);