feat: updated godot version
This commit is contained in:
parent
0c508b0831
commit
42b028dbb5
4694 changed files with 236470 additions and 401376 deletions
|
|
@ -30,15 +30,11 @@
|
|||
|
||||
#include "resource_loader.h"
|
||||
|
||||
#include "core/config/engine.h"
|
||||
#include "core/config/project_settings.h"
|
||||
#include "core/core_bind.h"
|
||||
#include "core/io/dir_access.h"
|
||||
#include "core/io/file_access.h"
|
||||
#include "core/io/resource_importer.h"
|
||||
#include "core/object/callable_mp.h"
|
||||
#include "core/object/class_db.h"
|
||||
#include "core/object/message_queue.h"
|
||||
#include "core/object/script_language.h"
|
||||
#include "core/os/condition_variable.h"
|
||||
#include "core/os/os.h"
|
||||
|
|
@ -222,6 +218,26 @@ void ResourceFormatLoader::_bind_methods() {
|
|||
GDVIRTUAL_BIND(_load, "path", "original_path", "use_sub_threads", "cache_mode");
|
||||
}
|
||||
|
||||
///////////////////////////////////
|
||||
|
||||
// These are used before and after a wait for a WorkerThreadPool task
|
||||
// because that can lead to another load started in the same thread,
|
||||
// something we must treat as a different stack for the purposes
|
||||
// of tracking nesting.
|
||||
|
||||
#define PREPARE_FOR_WTP_WAIT \
|
||||
int load_nesting_backup = ResourceLoader::load_nesting; \
|
||||
Vector<String> load_paths_stack_backup = ResourceLoader::load_paths_stack; \
|
||||
ResourceLoader::load_nesting = 0; \
|
||||
ResourceLoader::load_paths_stack.clear();
|
||||
|
||||
#define RESTORE_AFTER_WTP_WAIT \
|
||||
DEV_ASSERT(ResourceLoader::load_nesting == 0); \
|
||||
DEV_ASSERT(ResourceLoader::load_paths_stack.is_empty()); \
|
||||
ResourceLoader::load_nesting = load_nesting_backup; \
|
||||
ResourceLoader::load_paths_stack = load_paths_stack_backup; \
|
||||
load_paths_stack_backup.clear();
|
||||
|
||||
// This should be robust enough to be called redundantly without issues.
|
||||
void ResourceLoader::LoadToken::clear() {
|
||||
WorkerThreadPool::TaskID task_to_await = 0;
|
||||
|
|
@ -260,11 +276,9 @@ void ResourceLoader::LoadToken::clear() {
|
|||
|
||||
// If task is unused, await it here, locally, now the token data is consistent.
|
||||
if (task_to_await) {
|
||||
int load_nesting_backup = load_nesting;
|
||||
load_nesting = 0;
|
||||
PREPARE_FOR_WTP_WAIT
|
||||
WorkerThreadPool::get_singleton()->wait_for_task_completion(task_to_await);
|
||||
DEV_ASSERT(load_nesting == 0);
|
||||
load_nesting = load_nesting_backup;
|
||||
RESTORE_AFTER_WTP_WAIT
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -272,9 +286,20 @@ ResourceLoader::LoadToken::~LoadToken() {
|
|||
clear();
|
||||
}
|
||||
|
||||
Ref<Resource> ResourceLoader::_load(const String &p_path, const String &p_original_path, const String &p_type_hint, CacheMode p_cache_mode, Error *r_error, bool p_use_sub_threads, float *r_progress) {
|
||||
Ref<Resource> ResourceLoader::_load(const String &p_path, const String &p_original_path, const String &p_type_hint, ResourceFormatLoader::CacheMode p_cache_mode, Error *r_error, bool p_use_sub_threads, float *r_progress) {
|
||||
const String &original_path = p_original_path.is_empty() ? p_path : p_original_path;
|
||||
load_nesting++;
|
||||
if (load_paths_stack.size()) {
|
||||
MutexLock thread_load_lock(thread_load_mutex);
|
||||
const String &parent_task_path = load_paths_stack.get(load_paths_stack.size() - 1);
|
||||
HashMap<String, ThreadLoadTask>::Iterator E = thread_load_tasks.find(parent_task_path);
|
||||
// Avoid double-tracking, for progress reporting, resources that boil down to a remapped path containing the real payload (e.g., imported resources).
|
||||
bool is_remapped_load = original_path == parent_task_path;
|
||||
if (E && !is_remapped_load) {
|
||||
E->value.sub_tasks.insert(original_path);
|
||||
}
|
||||
}
|
||||
load_paths_stack.push_back(original_path);
|
||||
|
||||
print_verbose(vformat("Loading resource: %s", p_path));
|
||||
|
||||
|
|
@ -292,6 +317,7 @@ Ref<Resource> ResourceLoader::_load(const String &p_path, const String &p_origin
|
|||
}
|
||||
}
|
||||
|
||||
load_paths_stack.resize(load_paths_stack.size() - 1);
|
||||
res_ref_overrides.erase(load_nesting);
|
||||
load_nesting--;
|
||||
|
||||
|
|
@ -351,6 +377,7 @@ void ResourceLoader::_run_load_task(void *p_userdata) {
|
|||
// Thread-safe either if it's the current thread or a brand new one.
|
||||
CallQueue *own_mq_override = nullptr;
|
||||
if (load_nesting == 0) {
|
||||
DEV_ASSERT(load_paths_stack.is_empty());
|
||||
if (!Thread::is_main_thread()) {
|
||||
// Let the caller thread use its own, for added flexibility. Provide one otherwise.
|
||||
if (MessageQueue::get_singleton() == MessageQueue::get_main_singleton()) {
|
||||
|
|
@ -388,8 +415,8 @@ void ResourceLoader::_run_load_task(void *p_userdata) {
|
|||
}
|
||||
load_task.need_wait = false;
|
||||
|
||||
bool ignoring = load_task.cache_mode == CACHE_MODE_IGNORE || load_task.cache_mode == CACHE_MODE_IGNORE_DEEP;
|
||||
bool replacing = load_task.cache_mode == CACHE_MODE_REPLACE || load_task.cache_mode == CACHE_MODE_REPLACE_DEEP;
|
||||
bool ignoring = load_task.cache_mode == ResourceFormatLoader::CACHE_MODE_IGNORE || load_task.cache_mode == ResourceFormatLoader::CACHE_MODE_IGNORE_DEEP;
|
||||
bool replacing = load_task.cache_mode == ResourceFormatLoader::CACHE_MODE_REPLACE || load_task.cache_mode == ResourceFormatLoader::CACHE_MODE_REPLACE_DEEP;
|
||||
bool unlock_pending = true;
|
||||
if (load_task.resource.is_valid()) {
|
||||
// From now on, no critical section needed as no one will write to the task anymore.
|
||||
|
|
@ -469,6 +496,7 @@ void ResourceLoader::_run_load_task(void *p_userdata) {
|
|||
MessageQueue::set_thread_singleton_override(nullptr);
|
||||
memdelete(own_mq_override);
|
||||
}
|
||||
DEV_ASSERT(load_paths_stack.is_empty());
|
||||
}
|
||||
|
||||
curr_load_task = curr_load_task_backup;
|
||||
|
|
@ -485,7 +513,7 @@ String ResourceLoader::_validate_local_path(const String &p_path) {
|
|||
}
|
||||
}
|
||||
|
||||
Error ResourceLoader::load_threaded_request(const String &p_path, const String &p_type_hint, bool p_use_sub_threads, CacheMode p_cache_mode) {
|
||||
Error ResourceLoader::load_threaded_request(const String &p_path, const String &p_type_hint, bool p_use_sub_threads, ResourceFormatLoader::CacheMode p_cache_mode) {
|
||||
Ref<ResourceLoader::LoadToken> token = _load_start(p_path, p_type_hint, p_use_sub_threads ? LOAD_THREAD_DISTRIBUTE : LOAD_THREAD_SPAWN_SINGLE, p_cache_mode, true);
|
||||
return token.is_valid() ? OK : FAILED;
|
||||
}
|
||||
|
|
@ -510,7 +538,7 @@ void ResourceLoader::_load_threaded_request_setup_user_token(LoadToken *p_token,
|
|||
print_lt("REQUEST: user load tokens: " + itos(user_load_tokens.size()));
|
||||
}
|
||||
|
||||
Ref<Resource> ResourceLoader::load(const String &p_path, const String &p_type_hint, CacheMode p_cache_mode, Error *r_error) {
|
||||
Ref<Resource> ResourceLoader::load(const String &p_path, const String &p_type_hint, ResourceFormatLoader::CacheMode p_cache_mode, Error *r_error) {
|
||||
if (r_error) {
|
||||
*r_error = OK;
|
||||
}
|
||||
|
|
@ -535,11 +563,11 @@ Ref<Resource> ResourceLoader::load(const String &p_path, const String &p_type_hi
|
|||
return res;
|
||||
}
|
||||
|
||||
Ref<ResourceLoader::LoadToken> ResourceLoader::_load_start(const String &p_path, const String &p_type_hint, LoadThreadMode p_thread_mode, CacheMode p_cache_mode, bool p_for_user) {
|
||||
Ref<ResourceLoader::LoadToken> ResourceLoader::_load_start(const String &p_path, const String &p_type_hint, LoadThreadMode p_thread_mode, ResourceFormatLoader::CacheMode p_cache_mode, bool p_for_user) {
|
||||
String local_path = _validate_local_path(p_path);
|
||||
ERR_FAIL_COND_V(local_path.is_empty(), Ref<ResourceLoader::LoadToken>());
|
||||
|
||||
bool ignoring_cache = p_cache_mode == CACHE_MODE_IGNORE || p_cache_mode == CACHE_MODE_IGNORE_DEEP;
|
||||
bool ignoring_cache = p_cache_mode == ResourceFormatLoader::CACHE_MODE_IGNORE || p_cache_mode == ResourceFormatLoader::CACHE_MODE_IGNORE_DEEP;
|
||||
|
||||
Ref<LoadToken> load_token;
|
||||
bool must_not_register = false;
|
||||
|
|
@ -585,7 +613,7 @@ Ref<ResourceLoader::LoadToken> ResourceLoader::_load_start(const String &p_path,
|
|||
load_task.type_hint = p_type_hint;
|
||||
load_task.cache_mode = p_cache_mode;
|
||||
load_task.use_sub_threads = p_thread_mode == LOAD_THREAD_DISTRIBUTE;
|
||||
if (p_cache_mode == CACHE_MODE_REUSE) {
|
||||
if (p_cache_mode == ResourceFormatLoader::CACHE_MODE_REUSE) {
|
||||
Ref<Resource> existing = ResourceCache::get_ref(local_path);
|
||||
if (existing.is_valid()) {
|
||||
//referencing is fine
|
||||
|
|
@ -598,12 +626,6 @@ Ref<ResourceLoader::LoadToken> ResourceLoader::_load_start(const String &p_path,
|
|||
}
|
||||
}
|
||||
|
||||
// Task hierarchy
|
||||
if (curr_load_task) {
|
||||
load_task.parent_task = curr_load_task;
|
||||
curr_load_task->sub_tasks.insert(load_task.local_path);
|
||||
}
|
||||
|
||||
// If we want to ignore cache, but there's another task loading it, we can't add this one to the map.
|
||||
must_not_register = ignoring_cache && thread_load_tasks.has(local_path);
|
||||
if (must_not_register) {
|
||||
|
|
@ -793,22 +815,6 @@ void ResourceLoader::set_is_import_thread(bool p_import_thread) {
|
|||
import_thread = p_import_thread;
|
||||
}
|
||||
|
||||
void ResourceLoader::notify_load_error(const String &p_err) {
|
||||
if (err_notify) {
|
||||
MessageQueue::get_main_singleton()->push_callable(callable_mp_static(err_notify).bind(p_err));
|
||||
}
|
||||
}
|
||||
|
||||
void ResourceLoader::notify_dependency_error(const String &p_path, const String &p_dependency, const String &p_type) {
|
||||
if (dep_err_notify) {
|
||||
if (Thread::get_caller_id() == Thread::get_main_id()) {
|
||||
dep_err_notify(p_path, p_dependency, p_type);
|
||||
} else {
|
||||
MessageQueue::get_main_singleton()->push_callable(callable_mp_static(dep_err_notify).bind(p_path, p_dependency, p_type));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ref<Resource> ResourceLoader::_load_complete_inner(LoadToken &p_load_token, Error *r_error, MutexLock<SafeBinaryMutex<BINARY_MUTEX_TAG>> &p_thread_load_lock) {
|
||||
if (r_error) {
|
||||
*r_error = OK;
|
||||
|
|
@ -845,11 +851,9 @@ Ref<Resource> ResourceLoader::_load_complete_inner(LoadToken &p_load_token, Erro
|
|||
// Loading thread is in the worker pool.
|
||||
p_thread_load_lock.temp_unlock();
|
||||
|
||||
int load_nesting_backup = load_nesting;
|
||||
load_nesting = 0;
|
||||
PREPARE_FOR_WTP_WAIT
|
||||
Error wait_err = WorkerThreadPool::get_singleton()->wait_for_task_completion(load_task.task_id);
|
||||
DEV_ASSERT(load_nesting == 0);
|
||||
load_nesting = load_nesting_backup;
|
||||
RESTORE_AFTER_WTP_WAIT
|
||||
|
||||
DEV_ASSERT(!wait_err || wait_err == ERR_BUSY);
|
||||
if (wait_err == ERR_BUSY) {
|
||||
|
|
@ -900,21 +904,21 @@ Ref<Resource> ResourceLoader::_load_complete_inner(LoadToken &p_load_token, Erro
|
|||
load_task_ptr = &load_task;
|
||||
}
|
||||
|
||||
p_thread_load_lock.temp_unlock();
|
||||
|
||||
Ref<Resource> resource = load_task_ptr->resource;
|
||||
if (r_error) {
|
||||
*r_error = load_task_ptr->error;
|
||||
}
|
||||
|
||||
if (resource.is_valid()) {
|
||||
if (load_task_ptr->parent_task) {
|
||||
if (curr_load_task) {
|
||||
// A task awaiting another => Let the awaiter accumulate the resource changed connections.
|
||||
DEV_ASSERT(load_task_ptr->parent_task != load_task_ptr);
|
||||
DEV_ASSERT(curr_load_task != load_task_ptr);
|
||||
for (const ThreadLoadTask::ResourceChangedConnection &rcc : load_task_ptr->resource_changed_connections) {
|
||||
load_task_ptr->parent_task->resource_changed_connections.push_back(rcc);
|
||||
curr_load_task->resource_changed_connections.push_back(rcc);
|
||||
}
|
||||
} else {
|
||||
p_thread_load_lock.temp_unlock();
|
||||
|
||||
// A leaf task being awaited => Propagate the resource changed connections.
|
||||
if (Thread::is_main_thread()) {
|
||||
// On the main thread it's safe to migrate the connections to the standard signal mechanism.
|
||||
|
|
@ -938,11 +942,11 @@ Ref<Resource> ResourceLoader::_load_complete_inner(LoadToken &p_load_token, Erro
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
p_thread_load_lock.temp_relock();
|
||||
}
|
||||
}
|
||||
|
||||
p_thread_load_lock.temp_relock();
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
|
|
@ -1564,6 +1568,7 @@ bool ResourceLoader::timestamp_on_load = false;
|
|||
|
||||
thread_local bool ResourceLoader::import_thread = false;
|
||||
thread_local int ResourceLoader::load_nesting = 0;
|
||||
thread_local Vector<String> ResourceLoader::load_paths_stack;
|
||||
thread_local HashMap<int, HashMap<String, Ref<Resource>>> ResourceLoader::res_ref_overrides;
|
||||
thread_local ResourceLoader::ThreadLoadTask *ResourceLoader::curr_load_task = nullptr;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue