diff options
| author | Rémi Verschelde <rverschelde@gmail.com> | 2024-06-28 14:43:01 +0200 |
|---|---|---|
| committer | Rémi Verschelde <rverschelde@gmail.com> | 2024-06-28 14:43:01 +0200 |
| commit | e052a53bb6a810ca5c01b037fc8993a52bd4e338 (patch) | |
| tree | 314fa10119a9f10832c2a0649911d1509ce93406 /core/io | |
| parent | a365cf59c8687689805a71748e0b7cef9df9b636 (diff) | |
| parent | ec61c5064c0abe760795a37d852e7bfc02d3fdb6 (diff) | |
| download | redot-engine-e052a53bb6a810ca5c01b037fc8993a52bd4e338.tar.gz | |
Merge pull request #93695 from RandomShaper/res_load_main_th
`ResourceLoader`: Support polling and get-before-complete on the main thread
Diffstat (limited to 'core/io')
| -rw-r--r-- | core/io/resource_loader.cpp | 37 | ||||
| -rw-r--r-- | core/io/resource_loader.h | 3 |
2 files changed, 40 insertions, 0 deletions
diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index ed5e482296..58ad61b621 100644 --- a/core/io/resource_loader.cpp +++ b/core/io/resource_loader.cpp @@ -40,6 +40,7 @@ #include "core/string/print_string.h" #include "core/string/translation.h" #include "core/variant/variant_parser.h" +#include "servers/rendering_server.h" #ifdef DEBUG_LOAD_THREADED #define print_lt(m_text) print_line(m_text) @@ -585,6 +586,16 @@ ResourceLoader::ThreadLoadStatus ResourceLoader::load_threaded_get_status(const *r_progress = _dependency_get_progress(local_path); } + // Support userland polling in a loop on the main thread. + if (Thread::is_main_thread() && status == THREAD_LOAD_IN_PROGRESS) { + uint64_t frame = Engine::get_singleton()->get_process_frames(); + if (frame == load_task.last_progress_check_main_thread_frame) { + _ensure_load_progress(); + } else { + load_task.last_progress_check_main_thread_frame = frame; + } + } + return status; } @@ -613,6 +624,21 @@ Ref<Resource> ResourceLoader::load_threaded_get(const String &p_path, Error *r_e } return Ref<Resource>(); } + + // Support userland requesting on the main thread before the load is reported to be complete. + if (Thread::is_main_thread() && !load_token->local_path.is_empty()) { + const ThreadLoadTask &load_task = thread_load_tasks[load_token->local_path]; + while (load_task.status == THREAD_LOAD_IN_PROGRESS) { + if (!_ensure_load_progress()) { + // This local poll loop is not needed. + break; + } + thread_load_lock.~MutexLock(); + OS::get_singleton()->delay_usec(1000); + new (&thread_load_lock) MutexLock(thread_load_mutex); + } + } + res = _load_complete_inner(*load_token, r_error, thread_load_lock); if (load_token->unreference()) { memdelete(load_token); @@ -731,6 +757,17 @@ Ref<Resource> ResourceLoader::_load_complete_inner(LoadToken &p_load_token, Erro } } +bool ResourceLoader::_ensure_load_progress() { + // Some servers may need a new engine iteration to allow the load to progress. + // Since the only known one is the rendering server (in single thread mode), let's keep it simple and just sync it. + // This may be refactored in the future to support other servers and have less coupling. + if (OS::get_singleton()->get_render_thread_mode() == OS::RENDER_SEPARATE_THREAD) { + return false; // Not needed. + } + RenderingServer::get_singleton()->sync(); + return true; +} + Ref<Resource> ResourceLoader::ensure_resource_ref_override_for_outer_load(const String &p_path, const String &p_res_type) { ERR_FAIL_COND_V(load_nesting == 0, Ref<Resource>()); // It makes no sense to use this from nesting level 0. const String &local_path = _validate_local_path(p_path); diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h index c48f39b5cc..46df79ea22 100644 --- a/core/io/resource_loader.h +++ b/core/io/resource_loader.h @@ -174,6 +174,7 @@ private: String type_hint; float progress = 0.0f; float max_reported_progress = 0.0f; + uint64_t last_progress_check_main_thread_frame = UINT64_MAX; ThreadLoadStatus status = THREAD_LOAD_IN_PROGRESS; ResourceFormatLoader::CacheMode cache_mode = ResourceFormatLoader::CACHE_MODE_REUSE; Error error = OK; @@ -197,6 +198,8 @@ private: static float _dependency_get_progress(const String &p_path); + static bool _ensure_load_progress(); + public: static Error load_threaded_request(const String &p_path, const String &p_type_hint = "", bool p_use_sub_threads = false, ResourceFormatLoader::CacheMode p_cache_mode = ResourceFormatLoader::CACHE_MODE_REUSE); static ThreadLoadStatus load_threaded_get_status(const String &p_path, float *r_progress = nullptr); |
