Skip to content

Commit

Permalink
Refactor Node Processing (WIP)
Browse files Browse the repository at this point in the history
* Node processing works on the concept of process groups.
* A node group can be inherited, run on main thread, or a sub-thread.
* Groups can be ordered.
* Process priority is now present for physics.

This is the first steps towards implementing godotengine/godot-proposals#6424.
No threading or thread guards exist yet.
  • Loading branch information
reduz committed Apr 23, 2023
1 parent 65d8659 commit 6d2dbb3
Show file tree
Hide file tree
Showing 17 changed files with 981 additions and 166 deletions.
11 changes: 11 additions & 0 deletions core/object/message_queue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,17 @@ bool CallQueue::is_flushing() const {
return flushing;
}

bool CallQueue::has_messages() const {
if (pages_used == 0) {
return false;
}
if (pages_used == 1 && page_messages[0] == 0) {
return false;
}

return true;
}

int CallQueue::get_max_buffer_usage() const {
return pages.size() * PAGE_SIZE_BYTES;
}
Expand Down
14 changes: 9 additions & 5 deletions core/object/message_queue.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@ class CallQueue {
PAGE_SIZE_BYTES = 4096
};

struct Page {
uint8_t data[PAGE_SIZE_BYTES];
};

// Needs to be public to be able to define it outside the class.
typedef PagedAllocator<Page, true> Allocator;

private:
enum {
TYPE_CALL,
Expand All @@ -56,12 +63,7 @@ class CallQueue {
FLAG_MASK = FLAG_NULL_IS_OK - 1,
};

struct Page {
uint8_t data[PAGE_SIZE_BYTES];
};

Mutex mutex;
typedef PagedAllocator<Page, true> Allocator;

Allocator *allocator = nullptr;
bool allocator_is_custom = false;
Expand Down Expand Up @@ -140,6 +142,8 @@ class CallQueue {
void clear();
void statistics();

bool has_messages() const;

bool is_flushing() const;
int get_max_buffer_usage() const;

Expand Down
5 changes: 5 additions & 0 deletions core/object/object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,10 @@ bool Object::_predelete() {
return _predelete_ok;
}

void Object::cancel_free() {
_predelete_ok = false;
}

void Object::_postinitialize() {
_class_name_ptr = _get_class_namev(); // Set the direct pointer, which is much faster to obtain, but can only happen after postinitialize.
_initialize_classv();
Expand Down Expand Up @@ -1551,6 +1555,7 @@ void Object::_bind_methods() {
ClassDB::bind_method(D_METHOD("tr_n", "message", "plural_message", "n", "context"), &Object::tr_n, DEFVAL(""));

ClassDB::bind_method(D_METHOD("is_queued_for_deletion"), &Object::is_queued_for_deletion);
ClassDB::bind_method(D_METHOD("cancel_free"), &Object::cancel_free);

ClassDB::add_virtual_method("Object", MethodInfo("free"), false);

Expand Down
2 changes: 2 additions & 0 deletions core/object/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -924,6 +924,8 @@ class Object {

_ALWAYS_INLINE_ bool is_ref_counted() const { return type_is_reference; }

void cancel_free();

Object();
virtual ~Object();
};
Expand Down
2 changes: 1 addition & 1 deletion core/os/thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ void Thread::_set_platform_functions(const PlatformFunctions &p_functions) {
}

void Thread::callback(ID p_caller_id, const Settings &p_settings, Callback p_callback, void *p_userdata) {
Thread::caller_id = p_caller_id;
Thread::caller_id = _thread_id_hash(std::this_thread::get_id());
if (platform_functions.set_priority) {
platform_functions.set_priority(p_settings.priority);
}
Expand Down
2 changes: 2 additions & 0 deletions core/os/thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ class Thread {
// get the ID of the main thread
_FORCE_INLINE_ static ID get_main_id() { return main_thread_id; }

_FORCE_INLINE_ static bool is_main_thread() { return main_thread_id == caller_id; }

static Error set_name(const String &p_name);

void start(Thread::Callback p_callback, void *p_user, const Settings &p_settings = Settings());
Expand Down
4 changes: 2 additions & 2 deletions core/templates/hash_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ class HashMap {
}

bool _lookup_pos(const TKey &p_key, uint32_t &r_pos) const {
if (elements == nullptr) {
if (elements == nullptr || num_elements == 0) {
return false; // Failed lookups, no elements
}

Expand Down Expand Up @@ -252,7 +252,7 @@ class HashMap {
}

void clear() {
if (elements == nullptr) {
if (elements == nullptr || num_elements == 0) {
return;
}
uint32_t capacity = hash_table_size_primes[capacity_index];
Expand Down
4 changes: 2 additions & 2 deletions core/templates/hash_set.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ class HashSet {
}

bool _lookup_pos(const TKey &p_key, uint32_t &r_pos) const {
if (keys == nullptr) {
if (keys == nullptr || num_elements == 0) {
return false; // Failed lookups, no elements
}

Expand Down Expand Up @@ -237,7 +237,7 @@ class HashSet {
}

void clear() {
if (keys == nullptr) {
if (keys == nullptr || num_elements == 0) {
return;
}
uint32_t capacity = hash_table_size_primes[capacity_index];
Expand Down
4 changes: 3 additions & 1 deletion core/templates/local_vector.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,13 @@ class LocalVector {
}
}

void erase(const T &p_val) {
_FORCE_INLINE_ bool erase(const T &p_val) {
int64_t idx = find(p_val);
if (idx >= 0) {
remove_at(idx);
return true;
}
return false;
}

void invert() {
Expand Down
5 changes: 4 additions & 1 deletion core/templates/vector.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,15 @@ class Vector {
void fill(T p_elem);

void remove_at(int p_index) { _cowdata.remove_at(p_index); }
void erase(const T &p_val) {
_FORCE_INLINE_ bool erase(const T &p_val) {
int idx = find(p_val);
if (idx >= 0) {
remove_at(idx);
return true;
}
return false;
}

void reverse();

_FORCE_INLINE_ T *ptrw() { return _cowdata.ptrw(); }
Expand Down
2 changes: 2 additions & 0 deletions editor/editor_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,8 @@ void EditorNode::_notification(int p_what) {
} break;

case NOTIFICATION_ENTER_TREE: {
get_tree()->set_disable_node_threading(true); // No node threading while running editor.

Engine::get_singleton()->set_editor_hint(true);

Window *window = get_window();
Expand Down
8 changes: 8 additions & 0 deletions main/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ static int converter_max_line_length = 100000;

HashMap<Main::CLIScope, Vector<String>> forwardable_cli_arguments;
#endif
static bool single_threaded_scene = false;
bool use_startup_benchmark = false;
String startup_benchmark_file;

Expand Down Expand Up @@ -423,6 +424,7 @@ void Main::print_help(const char *p_binary) {
OS::get_singleton()->print(" --gpu-abort Abort on graphics API usage errors (usually validation layer errors). May help see the problem if your system freezes.\n");
#endif
OS::get_singleton()->print(" --remote-debug <uri> Remote debug (<protocol>://<host/IP>[:<port>], e.g. tcp://127.0.0.1:6007).\n");
OS::get_singleton()->print(" --single-threaded-scene Scene tree runs in single-threaded mode. Sub-thread groups are disabled and run on the main thread.\n");
#if defined(DEBUG_ENABLED)
OS::get_singleton()->print(" --debug-collisions Show collision shapes when running the scene.\n");
OS::get_singleton()->print(" --debug-paths Show path lines when running the scene.\n");
Expand Down Expand Up @@ -1104,6 +1106,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
OS::get_singleton()->print("Missing remote debug server uri, aborting.\n");
goto error;
}
} else if (I->get() == "--single-threaded-scene") {
single_threaded_scene = true;
} else if (I->get() == "--build-solutions") { // Build the scripting solution such C#

auto_build_solutions = true;
Expand Down Expand Up @@ -2775,6 +2779,10 @@ bool Main::start() {
}
#endif

if (single_threaded_scene) {
sml->set_disable_node_threading(true);
}

bool embed_subwindows = GLOBAL_GET("display/window/subwindows/embed_subwindows");

if (single_window || (!project_manager && !editor && embed_subwindows) || !DisplayServer::get_singleton()->has_feature(DisplayServer::Feature::FEATURE_SUBWINDOWS)) {
Expand Down
9 changes: 8 additions & 1 deletion scene/3d/skeleton_3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,11 @@ void Skeleton3D::_update_process_order() {

void Skeleton3D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
if (dirty) {
notification(NOTIFICATION_UPDATE_SKELETON);
}
} break;
case NOTIFICATION_UPDATE_SKELETON: {
RenderingServer *rs = RenderingServer::get_singleton();
Bone *bonesptr = bones.ptrw();
Expand Down Expand Up @@ -629,7 +634,9 @@ void Skeleton3D::_make_dirty() {
return;
}

MessageQueue::get_singleton()->push_notification(this, NOTIFICATION_UPDATE_SKELETON);
if (is_inside_tree()) {
notify_deferred_thread_group(NOTIFICATION_UPDATE_SKELETON);
}
dirty = true;
}

Expand Down
Loading

0 comments on commit 6d2dbb3

Please sign in to comment.