diff options
author | Rémi Verschelde <remi@verschelde.fr> | 2024-04-15 10:12:00 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-04-15 10:12:00 +0200 |
commit | c951421c996467dcb7106a33774410a7b5258690 (patch) | |
tree | 10bf3ef87a62987b6303d7dca63adc809ebbb05b /servers | |
parent | a44b0b6dc1ccd6dc364bb72c426e844d6c85744e (diff) | |
parent | 65686dedf9778e829287f63c7179a523d44fa085 (diff) | |
download | redot-engine-c951421c996467dcb7106a33774410a7b5258690.tar.gz |
Merge pull request #90268 from RandomShaper/wtp_servers
Use WorkerThreadPool for Server threads (enhanced)
Diffstat (limited to 'servers')
-rw-r--r-- | servers/display_server.cpp | 4 | ||||
-rw-r--r-- | servers/display_server.h | 1 | ||||
-rw-r--r-- | servers/physics_server_2d_wrap_mt.cpp | 55 | ||||
-rw-r--r-- | servers/physics_server_2d_wrap_mt.h | 38 | ||||
-rw-r--r-- | servers/physics_server_3d_wrap_mt.cpp | 49 | ||||
-rw-r--r-- | servers/physics_server_3d_wrap_mt.h | 38 | ||||
-rw-r--r-- | servers/rendering/renderer_rd/storage_rd/particles_storage.cpp | 6 | ||||
-rw-r--r-- | servers/rendering/rendering_server_default.cpp | 65 | ||||
-rw-r--r-- | servers/rendering/rendering_server_default.h | 21 | ||||
-rw-r--r-- | servers/rendering_server.cpp | 9 | ||||
-rw-r--r-- | servers/server_wrap_mt_common.h | 45 |
11 files changed, 152 insertions, 179 deletions
diff --git a/servers/display_server.cpp b/servers/display_server.cpp index 9ceb6909fe..351c03c158 100644 --- a/servers/display_server.cpp +++ b/servers/display_server.cpp @@ -697,10 +697,6 @@ void DisplayServer::release_rendering_thread() { WARN_PRINT("Rendering thread not supported by this display server."); } -void DisplayServer::make_rendering_thread() { - WARN_PRINT("Rendering thread not supported by this display server."); -} - void DisplayServer::swap_buffers() { WARN_PRINT("Swap buffers not supported by this display server."); } diff --git a/servers/display_server.h b/servers/display_server.h index f1a98c2c17..aab51644c0 100644 --- a/servers/display_server.h +++ b/servers/display_server.h @@ -559,7 +559,6 @@ public: virtual void force_process_and_drop_events(); virtual void release_rendering_thread(); - virtual void make_rendering_thread(); virtual void swap_buffers(); virtual void set_native_icon(const String &p_filename); diff --git a/servers/physics_server_2d_wrap_mt.cpp b/servers/physics_server_2d_wrap_mt.cpp index a23bb5e701..4548bb91cb 100644 --- a/servers/physics_server_2d_wrap_mt.cpp +++ b/servers/physics_server_2d_wrap_mt.cpp @@ -33,7 +33,7 @@ #include "core/os/os.h" void PhysicsServer2DWrapMT::thread_exit() { - exit.set(); + exit = true; } void PhysicsServer2DWrapMT::thread_step(real_t p_delta) { @@ -41,25 +41,18 @@ void PhysicsServer2DWrapMT::thread_step(real_t p_delta) { step_sem.post(); } -void PhysicsServer2DWrapMT::_thread_callback(void *_instance) { - PhysicsServer2DWrapMT *vsmt = reinterpret_cast<PhysicsServer2DWrapMT *>(_instance); - - vsmt->thread_loop(); -} - void PhysicsServer2DWrapMT::thread_loop() { server_thread = Thread::get_caller_id(); physics_server_2d->init(); - exit.clear(); - step_thread_up.set(); - while (!exit.is_set()) { - // flush commands one by one, until exit is requested - command_queue.wait_and_flush(); + command_queue.set_pump_task_id(server_task_id); + while (!exit) { + WorkerThreadPool::get_singleton()->yield(); + command_queue.flush_all(); } - command_queue.flush_all(); // flush all + command_queue.flush_all(); physics_server_2d->finish(); } @@ -70,18 +63,14 @@ void PhysicsServer2DWrapMT::step(real_t p_step) { if (create_thread) { command_queue.push(this, &PhysicsServer2DWrapMT::thread_step, p_step); } else { - command_queue.flush_all(); //flush all pending from other threads + command_queue.flush_all(); // Flush all pending from other threads. physics_server_2d->step(p_step); } } void PhysicsServer2DWrapMT::sync() { if (create_thread) { - if (first_frame) { - first_frame = false; - } else { - step_sem.wait(); //must not wait if a step was not issued - } + step_sem.wait(); } physics_server_2d->sync(); } @@ -96,40 +85,34 @@ void PhysicsServer2DWrapMT::end_sync() { void PhysicsServer2DWrapMT::init() { if (create_thread) { - //OS::get_singleton()->release_rendering_thread(); - thread.start(_thread_callback, this); - while (!step_thread_up.is_set()) { - OS::get_singleton()->delay_usec(1000); - } + exit = false; + server_task_id = WorkerThreadPool::get_singleton()->add_task(callable_mp(this, &PhysicsServer2DWrapMT::thread_loop), true); + step_sem.post(); } else { physics_server_2d->init(); } } void PhysicsServer2DWrapMT::finish() { - if (thread.is_started()) { + if (create_thread) { command_queue.push(this, &PhysicsServer2DWrapMT::thread_exit); - thread.wait_to_finish(); + if (server_task_id != WorkerThreadPool::INVALID_TASK_ID) { + WorkerThreadPool::get_singleton()->wait_for_task_completion(server_task_id); + server_task_id = WorkerThreadPool::INVALID_TASK_ID; + } } else { physics_server_2d->finish(); } } -PhysicsServer2DWrapMT::PhysicsServer2DWrapMT(PhysicsServer2D *p_contained, bool p_create_thread) : - command_queue(p_create_thread) { +PhysicsServer2DWrapMT::PhysicsServer2DWrapMT(PhysicsServer2D *p_contained, bool p_create_thread) { physics_server_2d = p_contained; create_thread = p_create_thread; - - if (!p_create_thread) { - server_thread = Thread::get_caller_id(); - } else { - server_thread = 0; + if (!create_thread) { + server_thread = Thread::MAIN_ID; } - - main_thread = Thread::get_caller_id(); } PhysicsServer2DWrapMT::~PhysicsServer2DWrapMT() { memdelete(physics_server_2d); - //finish(); } diff --git a/servers/physics_server_2d_wrap_mt.h b/servers/physics_server_2d_wrap_mt.h index 3bebe5df85..5e2b3b4086 100644 --- a/servers/physics_server_2d_wrap_mt.h +++ b/servers/physics_server_2d_wrap_mt.h @@ -32,6 +32,7 @@ #define PHYSICS_SERVER_2D_WRAP_MT_H #include "core/config/project_settings.h" +#include "core/object/worker_thread_pool.h" #include "core/os/thread.h" #include "core/templates/command_queue_mt.h" #include "core/templates/safe_refcount.h" @@ -43,30 +44,27 @@ #define SYNC_DEBUG #endif +#ifdef DEBUG_ENABLED +#define MAIN_THREAD_SYNC_WARN WARN_PRINT("Call to " + String(__FUNCTION__) + " causing PhysicsServer2D synchronizations on every frame. This significantly affects performance."); +#endif + class PhysicsServer2DWrapMT : public PhysicsServer2D { - mutable PhysicsServer2D *physics_server_2d; + mutable PhysicsServer2D *physics_server_2d = nullptr; mutable CommandQueueMT command_queue; - static void _thread_callback(void *_instance); void thread_loop(); - Thread::ID server_thread; - Thread::ID main_thread; - SafeFlag exit; - Thread thread; - SafeFlag step_thread_up; + Thread::ID server_thread = Thread::UNASSIGNED_ID; + WorkerThreadPool::TaskID server_task_id = WorkerThreadPool::INVALID_TASK_ID; + bool exit = false; + Semaphore step_sem; bool create_thread = false; - Semaphore step_sem; void thread_step(real_t p_delta); void thread_exit(); - bool first_frame = true; - - Mutex alloc_mutex; - public: #define ServerName PhysicsServer2D #define ServerNameWrapMT PhysicsServer2DWrapMT @@ -94,7 +92,7 @@ public: //these work well, but should be used from the main thread only bool shape_collide(RID p_shape_A, const Transform2D &p_xform_A, const Vector2 &p_motion_A, RID p_shape_B, const Transform2D &p_xform_B, const Vector2 &p_motion_B, Vector2 *r_results, int p_result_max, int &r_result_count) override { - ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false); + ERR_FAIL_COND_V(!Thread::is_main_thread(), false); return physics_server_2d->shape_collide(p_shape_A, p_xform_A, p_motion_A, p_shape_B, p_xform_B, p_motion_B, r_results, p_result_max, r_result_count); } @@ -109,18 +107,18 @@ public: // this function only works on physics process, errors and returns null otherwise PhysicsDirectSpaceState2D *space_get_direct_state(RID p_space) override { - ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), nullptr); + ERR_FAIL_COND_V(!Thread::is_main_thread(), nullptr); return physics_server_2d->space_get_direct_state(p_space); } FUNC2(space_set_debug_contacts, RID, int); virtual Vector<Vector2> space_get_contacts(RID p_space) const override { - ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), Vector<Vector2>()); + ERR_FAIL_COND_V(!Thread::is_main_thread(), Vector<Vector2>()); return physics_server_2d->space_get_contacts(p_space); } virtual int space_get_contact_count(RID p_space) const override { - ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), 0); + ERR_FAIL_COND_V(!Thread::is_main_thread(), 0); return physics_server_2d->space_get_contact_count(p_space); } @@ -261,13 +259,13 @@ public: FUNC2(body_set_pickable, RID, bool); bool body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result = nullptr) override { - ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false); + ERR_FAIL_COND_V(!Thread::is_main_thread(), false); return physics_server_2d->body_test_motion(p_body, p_parameters, r_result); } // this function only works on physics process, errors and returns null otherwise PhysicsDirectBodyState2D *body_get_direct_state(RID p_body) override { - ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), nullptr); + ERR_FAIL_COND_V(!Thread::is_main_thread(), nullptr); return physics_server_2d->body_get_direct_state(p_body); } @@ -338,4 +336,8 @@ public: #endif #undef SYNC_DEBUG +#ifdef DEBUG_ENABLED +#undef MAIN_THREAD_SYNC_WARN +#endif + #endif // PHYSICS_SERVER_2D_WRAP_MT_H diff --git a/servers/physics_server_3d_wrap_mt.cpp b/servers/physics_server_3d_wrap_mt.cpp index feb17cad84..f8f60281a7 100644 --- a/servers/physics_server_3d_wrap_mt.cpp +++ b/servers/physics_server_3d_wrap_mt.cpp @@ -41,22 +41,15 @@ void PhysicsServer3DWrapMT::thread_step(real_t p_delta) { step_sem.post(); } -void PhysicsServer3DWrapMT::_thread_callback(void *_instance) { - PhysicsServer3DWrapMT *vsmt = reinterpret_cast<PhysicsServer3DWrapMT *>(_instance); - - vsmt->thread_loop(); -} - void PhysicsServer3DWrapMT::thread_loop() { server_thread = Thread::get_caller_id(); physics_server_3d->init(); - exit = false; - step_thread_up = true; + command_queue.set_pump_task_id(server_task_id); while (!exit) { - // flush commands one by one, until exit is requested - command_queue.wait_and_flush(); + WorkerThreadPool::get_singleton()->yield(); + command_queue.flush_all(); } command_queue.flush_all(); // flush all @@ -70,18 +63,14 @@ void PhysicsServer3DWrapMT::step(real_t p_step) { if (create_thread) { command_queue.push(this, &PhysicsServer3DWrapMT::thread_step, p_step); } else { - command_queue.flush_all(); //flush all pending from other threads + command_queue.flush_all(); // Flush all pending from other threads. physics_server_3d->step(p_step); } } void PhysicsServer3DWrapMT::sync() { if (create_thread) { - if (first_frame) { - first_frame = false; - } else { - step_sem.wait(); //must not wait if a step was not issued - } + step_sem.wait(); } physics_server_3d->sync(); } @@ -96,40 +85,34 @@ void PhysicsServer3DWrapMT::end_sync() { void PhysicsServer3DWrapMT::init() { if (create_thread) { - //OS::get_singleton()->release_rendering_thread(); - thread.start(_thread_callback, this); - while (!step_thread_up) { - OS::get_singleton()->delay_usec(1000); - } + exit = false; + server_task_id = WorkerThreadPool::get_singleton()->add_task(callable_mp(this, &PhysicsServer3DWrapMT::thread_loop), true); + step_sem.post(); } else { physics_server_3d->init(); } } void PhysicsServer3DWrapMT::finish() { - if (thread.is_started()) { + if (create_thread) { command_queue.push(this, &PhysicsServer3DWrapMT::thread_exit); - thread.wait_to_finish(); + if (server_task_id != WorkerThreadPool::INVALID_TASK_ID) { + WorkerThreadPool::get_singleton()->wait_for_task_completion(server_task_id); + server_task_id = WorkerThreadPool::INVALID_TASK_ID; + } } else { physics_server_3d->finish(); } } -PhysicsServer3DWrapMT::PhysicsServer3DWrapMT(PhysicsServer3D *p_contained, bool p_create_thread) : - command_queue(p_create_thread) { +PhysicsServer3DWrapMT::PhysicsServer3DWrapMT(PhysicsServer3D *p_contained, bool p_create_thread) { physics_server_3d = p_contained; create_thread = p_create_thread; - - if (!p_create_thread) { - server_thread = Thread::get_caller_id(); - } else { - server_thread = 0; + if (!create_thread) { + server_thread = Thread::MAIN_ID; } - - main_thread = Thread::get_caller_id(); } PhysicsServer3DWrapMT::~PhysicsServer3DWrapMT() { memdelete(physics_server_3d); - //finish(); } diff --git a/servers/physics_server_3d_wrap_mt.h b/servers/physics_server_3d_wrap_mt.h index fc8930977d..22f3ee0e45 100644 --- a/servers/physics_server_3d_wrap_mt.h +++ b/servers/physics_server_3d_wrap_mt.h @@ -32,6 +32,7 @@ #define PHYSICS_SERVER_3D_WRAP_MT_H #include "core/config/project_settings.h" +#include "core/object/worker_thread_pool.h" #include "core/os/thread.h" #include "core/templates/command_queue_mt.h" #include "servers/physics_server_3d.h" @@ -42,30 +43,27 @@ #define SYNC_DEBUG #endif +#ifdef DEBUG_ENABLED +#define MAIN_THREAD_SYNC_WARN WARN_PRINT("Call to " + String(__FUNCTION__) + " causing PhysicsServer3D synchronizations on every frame. This significantly affects performance."); +#endif + class PhysicsServer3DWrapMT : public PhysicsServer3D { - mutable PhysicsServer3D *physics_server_3d; + mutable PhysicsServer3D *physics_server_3d = nullptr; mutable CommandQueueMT command_queue; - static void _thread_callback(void *_instance); void thread_loop(); - Thread::ID server_thread; - Thread::ID main_thread; - volatile bool exit = false; - Thread thread; - volatile bool step_thread_up = false; + Thread::ID server_thread = Thread::UNASSIGNED_ID; + WorkerThreadPool::TaskID server_task_id = WorkerThreadPool::INVALID_TASK_ID; + bool exit = false; + Semaphore step_sem; bool create_thread = false; - Semaphore step_sem; void thread_step(real_t p_delta); void thread_exit(); - bool first_frame = true; - - Mutex alloc_mutex; - public: #define ServerName PhysicsServer3D #define ServerNameWrapMT PhysicsServer3DWrapMT @@ -98,7 +96,7 @@ public: #if 0 //these work well, but should be used from the main thread only bool shape_collide(RID p_shape_A, const Transform &p_xform_A, const Vector3 &p_motion_A, RID p_shape_B, const Transform &p_xform_B, const Vector3 &p_motion_B, Vector3 *r_results, int p_result_max, int &r_result_count) { - ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false); + ERR_FAIL_COND_V(!Thread::is_main_thread(), false); return physics_server_3d->shape_collide(p_shape_A, p_xform_A, p_motion_A, p_shape_B, p_xform_B, p_motion_B, r_results, p_result_max, r_result_count); } #endif @@ -113,18 +111,18 @@ public: // this function only works on physics process, errors and returns null otherwise PhysicsDirectSpaceState3D *space_get_direct_state(RID p_space) override { - ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), nullptr); + ERR_FAIL_COND_V(!Thread::is_main_thread(), nullptr); return physics_server_3d->space_get_direct_state(p_space); } FUNC2(space_set_debug_contacts, RID, int); virtual Vector<Vector3> space_get_contacts(RID p_space) const override { - ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), Vector<Vector3>()); + ERR_FAIL_COND_V(!Thread::is_main_thread(), Vector<Vector3>()); return physics_server_3d->space_get_contacts(p_space); } virtual int space_get_contact_count(RID p_space) const override { - ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), 0); + ERR_FAIL_COND_V(!Thread::is_main_thread(), 0); return physics_server_3d->space_get_contact_count(p_space); } @@ -260,13 +258,13 @@ public: FUNC2(body_set_ray_pickable, RID, bool); bool body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result = nullptr) override { - ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false); + ERR_FAIL_COND_V(!Thread::is_main_thread(), false); return physics_server_3d->body_test_motion(p_body, p_parameters, r_result); } // this function only works on physics process, errors and returns null otherwise PhysicsDirectBodyState3D *body_get_direct_state(RID p_body) override { - ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), nullptr); + ERR_FAIL_COND_V(!Thread::is_main_thread(), nullptr); return physics_server_3d->body_get_direct_state(p_body); } @@ -411,4 +409,8 @@ public: #endif #undef SYNC_DEBUG +#ifdef DEBUG_ENABLED +#undef MAIN_THREAD_SYNC_WARN +#endif + #endif // PHYSICS_SERVER_3D_WRAP_MT_H diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp index c9c7c53d04..f7b28e7a1e 100644 --- a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp @@ -257,7 +257,6 @@ void ParticlesStorage::particles_set_emitting(RID p_particles, bool p_emitting) } bool ParticlesStorage::particles_get_emitting(RID p_particles) { - ERR_FAIL_COND_V_MSG(RSG::threaded, false, "This function should never be used with threaded rendering, as it stalls the renderer."); Particles *particles = particles_owner.get_or_null(p_particles); ERR_FAIL_NULL_V(particles, false); @@ -608,10 +607,6 @@ void ParticlesStorage::particles_request_process(RID p_particles) { } AABB ParticlesStorage::particles_get_current_aabb(RID p_particles) { - if (RSG::threaded) { - WARN_PRINT_ONCE("Calling this function with threaded rendering enabled stalls the renderer, use with care."); - } - const Particles *particles = particles_owner.get_or_null(p_particles); ERR_FAIL_NULL_V(particles, AABB()); @@ -1642,7 +1637,6 @@ Dependency *ParticlesStorage::particles_get_dependency(RID p_particles) const { } bool ParticlesStorage::particles_is_inactive(RID p_particles) const { - ERR_FAIL_COND_V_MSG(RSG::threaded, false, "This function should never be used with threaded rendering, as it stalls the renderer."); const Particles *particles = particles_owner.get_or_null(p_particles); ERR_FAIL_NULL_V(particles, false); return !particles->emitting && particles->inactive; diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp index 5bf0ab0ba6..7e5ccee0e3 100644 --- a/servers/rendering/rendering_server_default.cpp +++ b/servers/rendering/rendering_server_default.cpp @@ -69,9 +69,6 @@ void RenderingServerDefault::request_frame_drawn_callback(const Callable &p_call } void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) { - //needs to be done before changes is reset to 0, to not force the editor to redraw - RS::get_singleton()->emit_signal(SNAME("frame_pre_draw")); - changes = 0; RSG::rasterizer->begin_frame(frame_step); @@ -220,16 +217,9 @@ void RenderingServerDefault::_finish() { void RenderingServerDefault::init() { if (create_thread) { - print_verbose("RenderingServerWrapMT: Creating render thread"); + print_verbose("RenderingServerWrapMT: Starting render thread"); DisplayServer::get_singleton()->release_rendering_thread(); - if (create_thread) { - thread.start(_thread_callback, this); - print_verbose("RenderingServerWrapMT: Starting render thread"); - } - while (!draw_thread_up.is_set()) { - OS::get_singleton()->delay_usec(1000); - } - print_verbose("RenderingServerWrapMT: Finished render thread"); + server_task_id = WorkerThreadPool::get_singleton()->add_task(callable_mp(this, &RenderingServerDefault::_thread_loop), true); } else { _init(); } @@ -238,8 +228,9 @@ void RenderingServerDefault::init() { void RenderingServerDefault::finish() { if (create_thread) { command_queue.push(this, &RenderingServerDefault::_thread_exit); - if (thread.is_started()) { - thread.wait_to_finish(); + if (server_task_id != WorkerThreadPool::INVALID_TASK_ID) { + WorkerThreadPool::get_singleton()->wait_for_task_completion(server_task_id); + server_task_id = WorkerThreadPool::INVALID_TASK_ID; } } else { _finish(); @@ -337,38 +328,29 @@ Size2i RenderingServerDefault::get_maximum_viewport_size() const { } void RenderingServerDefault::_thread_exit() { - exit.set(); + exit = true; } void RenderingServerDefault::_thread_draw(bool p_swap_buffers, double frame_step) { _draw(p_swap_buffers, frame_step); } -void RenderingServerDefault::_thread_flush() { -} - -void RenderingServerDefault::_thread_callback(void *_instance) { - RenderingServerDefault *vsmt = reinterpret_cast<RenderingServerDefault *>(_instance); - - vsmt->_thread_loop(); -} - void RenderingServerDefault::_thread_loop() { server_thread = Thread::get_caller_id(); - DisplayServer::get_singleton()->make_rendering_thread(); - + DisplayServer::get_singleton()->gl_window_make_current(DisplayServer::MAIN_WINDOW_ID); // Move GL to this thread. _init(); - draw_thread_up.set(); - while (!exit.is_set()) { - // flush commands one by one, until exit is requested - command_queue.wait_and_flush(); + command_queue.set_pump_task_id(server_task_id); + while (!exit) { + WorkerThreadPool::get_singleton()->yield(); + command_queue.flush_all(); } - command_queue.flush_all(); // flush all + command_queue.flush_all(); _finish(); + DisplayServer::get_singleton()->release_rendering_thread(); } /* INTERPOLATION */ @@ -384,15 +366,15 @@ void RenderingServerDefault::set_physics_interpolation_enabled(bool p_enabled) { /* EVENT QUEUING */ void RenderingServerDefault::sync() { - if (create_thread) { - command_queue.push_and_sync(this, &RenderingServerDefault::_thread_flush); - } else { - command_queue.flush_all(); //flush all pending from other threads + if (!create_thread) { + command_queue.flush_all(); // Flush all pending from other threads. } } void RenderingServerDefault::draw(bool p_swap_buffers, double frame_step) { ERR_FAIL_COND_MSG(!Thread::is_main_thread(), "Manually triggering the draw function from the RenderingServer can only be done on the main thread. Call this function from the main thread or use call_deferred()."); + // Needs to be done before changes is reset to 0, to not force the editor to redraw. + RS::get_singleton()->emit_signal(SNAME("frame_pre_draw")); if (create_thread) { command_queue.push(this, &RenderingServerDefault::_thread_draw, p_swap_buffers, frame_step); } else { @@ -404,21 +386,14 @@ void RenderingServerDefault::_call_on_render_thread(const Callable &p_callable) p_callable.call(); } -RenderingServerDefault::RenderingServerDefault(bool p_create_thread) : - command_queue(p_create_thread) { +RenderingServerDefault::RenderingServerDefault(bool p_create_thread) { RenderingServer::init(); -#ifdef THREADS_ENABLED create_thread = p_create_thread; if (!create_thread) { - server_thread = Thread::get_caller_id(); - } else { - server_thread = 0; + server_thread = Thread::MAIN_ID; } -#else - create_thread = false; - server_thread = Thread::get_main_id(); -#endif + RSG::threaded = create_thread; RSG::canvas = memnew(RendererCanvasCull); diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index c50472c0cd..f94323f198 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -31,6 +31,7 @@ #ifndef RENDERING_SERVER_DEFAULT_H #define RENDERING_SERVER_DEFAULT_H +#include "core/object/worker_thread_pool.h" #include "core/os/thread.h" #include "core/templates/command_queue_mt.h" #include "core/templates/hash_map.h" @@ -75,22 +76,17 @@ class RenderingServerDefault : public RenderingServer { mutable CommandQueueMT command_queue; - static void _thread_callback(void *_instance); void _thread_loop(); - Thread::ID server_thread = 0; - SafeFlag exit; - Thread thread; - SafeFlag draw_thread_up; - bool create_thread; + Thread::ID server_thread = Thread::UNASSIGNED_ID; + WorkerThreadPool::TaskID server_task_id = WorkerThreadPool::INVALID_TASK_ID; + bool exit = false; + bool create_thread = false; void _thread_draw(bool p_swap_buffers, double frame_step); - void _thread_flush(); void _thread_exit(); - Mutex alloc_mutex; - void _draw(bool p_swap_buffers, double frame_step); void _init(); void _finish(); @@ -127,6 +123,10 @@ public: #define SYNC_DEBUG #endif +#ifdef DEBUG_ENABLED +#define MAIN_THREAD_SYNC_WARN WARN_PRINT("Call to " + String(__FUNCTION__) + " causing RenderingServer synchronizations on every frame. This significantly affects performance."); +#endif + #include "servers/server_wrap_mt_common.h" /* TEXTURE API */ @@ -1013,6 +1013,9 @@ public: #undef ServerName #undef WRITE_ACTION #undef SYNC_DEBUG +#ifdef DEBUG_ENABLED +#undef MAIN_THREAD_SYNC_WARN +#endif virtual uint64_t get_rendering_info(RenderingInfo p_info) override; virtual RenderingDevice::DeviceType get_video_adapter_type() const override; diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index 96d317ebd3..bbe6b1ad0d 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -83,25 +83,16 @@ static PackedInt64Array to_int_array(const Vector<ObjectID> &ids) { } PackedInt64Array RenderingServer::_instances_cull_aabb_bind(const AABB &p_aabb, RID p_scenario) const { - if (RSG::threaded) { - WARN_PRINT_ONCE("Using this function with a threaded renderer hurts performance, as it causes a server stall."); - } Vector<ObjectID> ids = instances_cull_aabb(p_aabb, p_scenario); return to_int_array(ids); } PackedInt64Array RenderingServer::_instances_cull_ray_bind(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario) const { - if (RSG::threaded) { - WARN_PRINT_ONCE("Using this function with a threaded renderer hurts performance, as it causes a server stall."); - } Vector<ObjectID> ids = instances_cull_ray(p_from, p_to, p_scenario); return to_int_array(ids); } PackedInt64Array RenderingServer::_instances_cull_convex_bind(const TypedArray<Plane> &p_convex, RID p_scenario) const { - if (RSG::threaded) { - WARN_PRINT_ONCE("Using this function with a threaded renderer hurts performance, as it causes a server stall."); - } Vector<Plane> planes; for (int i = 0; i < p_convex.size(); ++i) { const Variant &v = p_convex[i]; diff --git a/servers/server_wrap_mt_common.h b/servers/server_wrap_mt_common.h index 1a73c97fc7..40867490ca 100644 --- a/servers/server_wrap_mt_common.h +++ b/servers/server_wrap_mt_common.h @@ -31,12 +31,22 @@ #ifndef SERVER_WRAP_MT_COMMON_H #define SERVER_WRAP_MT_COMMON_H +#ifdef DEBIG_ENABLED +#define MAIN_THREAD_SYNC_CHECK \ + if (unlikely(Thread::is_main_thread() && Engine::get_singleton()->notify_frame_server_synced())) { \ + MAIN_THREAD_SYNC_WARN \ + } +#else +#define MAIN_THREAD_SYNC_CHECK +#endif + #define FUNC0R(m_r, m_type) \ virtual m_r m_type() override { \ if (Thread::get_caller_id() != server_thread) { \ m_r ret; \ command_queue.push_and_ret(server_name, &ServerName::m_type, &ret); \ SYNC_DEBUG \ + MAIN_THREAD_SYNC_CHECK \ return ret; \ } else { \ command_queue.flush_if_pending(); \ @@ -68,6 +78,7 @@ m_r ret; \ command_queue.push_and_ret(server_name, &ServerName::m_type, &ret); \ SYNC_DEBUG \ + MAIN_THREAD_SYNC_CHECK \ return ret; \ } else { \ command_queue.flush_if_pending(); \ @@ -102,6 +113,7 @@ if (Thread::get_caller_id() != server_thread) { \ command_queue.push_and_sync(server_name, &ServerName::m_type); \ SYNC_DEBUG \ + MAIN_THREAD_SYNC_CHECK \ } else { \ command_queue.flush_if_pending(); \ server_name->m_type(); \ @@ -113,6 +125,7 @@ if (Thread::get_caller_id() != server_thread) { \ command_queue.push_and_sync(server_name, &ServerName::m_type); \ SYNC_DEBUG \ + MAIN_THREAD_SYNC_CHECK \ } else { \ command_queue.flush_if_pending(); \ server_name->m_type(); \ @@ -128,6 +141,7 @@ m_r ret; \ command_queue.push_and_ret(server_name, &ServerName::m_type, p1, &ret); \ SYNC_DEBUG \ + MAIN_THREAD_SYNC_CHECK \ return ret; \ } else { \ command_queue.flush_if_pending(); \ @@ -141,6 +155,7 @@ m_r ret; \ command_queue.push_and_ret(server_name, &ServerName::m_type, p1, &ret); \ SYNC_DEBUG \ + MAIN_THREAD_SYNC_CHECK \ return ret; \ } else { \ command_queue.flush_if_pending(); \ @@ -154,6 +169,7 @@ if (Thread::get_caller_id() != server_thread) { \ command_queue.push_and_sync(server_name, &ServerName::m_type, p1); \ SYNC_DEBUG \ + MAIN_THREAD_SYNC_CHECK \ } else { \ command_queue.flush_if_pending(); \ server_name->m_type(p1); \ @@ -165,6 +181,7 @@ if (Thread::get_caller_id() != server_thread) { \ command_queue.push_and_sync(server_name, &ServerName::m_type, p1); \ SYNC_DEBUG \ + MAIN_THREAD_SYNC_CHECK \ } else { \ command_queue.flush_if_pending(); \ server_name->m_type(p1); \ @@ -199,6 +216,7 @@ m_r ret; \ command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, &ret); \ SYNC_DEBUG \ + MAIN_THREAD_SYNC_CHECK \ return ret; \ } else { \ command_queue.flush_if_pending(); \ @@ -212,6 +230,7 @@ m_r ret; \ command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, &ret); \ SYNC_DEBUG \ + MAIN_THREAD_SYNC_CHECK \ return ret; \ } else { \ command_queue.flush_if_pending(); \ @@ -225,6 +244,7 @@ if (Thread::get_caller_id() != server_thread) { \ command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2); \ SYNC_DEBUG \ + MAIN_THREAD_SYNC_CHECK \ } else { \ command_queue.flush_if_pending(); \ server_name->m_type(p1, p2); \ @@ -236,6 +256,7 @@ if (Thread::get_caller_id() != server_thread) { \ command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2); \ SYNC_DEBUG \ + MAIN_THREAD_SYNC_CHECK \ } else { \ command_queue.flush_if_pending(); \ server_name->m_type(p1, p2); \ @@ -270,6 +291,7 @@ m_r ret; \ command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, &ret); \ SYNC_DEBUG \ + MAIN_THREAD_SYNC_CHECK \ return ret; \ } else { \ command_queue.flush_if_pending(); \ @@ -283,6 +305,7 @@ m_r ret; \ command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, &ret); \ SYNC_DEBUG \ + MAIN_THREAD_SYNC_CHECK \ return ret; \ } else { \ command_queue.flush_if_pending(); \ @@ -296,6 +319,7 @@ if (Thread::get_caller_id() != server_thread) { \ command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3); \ SYNC_DEBUG \ + MAIN_THREAD_SYNC_CHECK \ } else { \ command_queue.flush_if_pending(); \ server_name->m_type(p1, p2, p3); \ @@ -307,6 +331,7 @@ if (Thread::get_caller_id() != server_thread) { \ command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3); \ SYNC_DEBUG \ + MAIN_THREAD_SYNC_CHECK \ } else { \ command_queue.flush_if_pending(); \ server_name->m_type(p1, p2, p3); \ @@ -341,6 +366,7 @@ m_r ret; \ command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, &ret); \ SYNC_DEBUG \ + MAIN_THREAD_SYNC_CHECK \ return ret; \ } else { \ command_queue.flush_if_pending(); \ @@ -354,6 +380,7 @@ m_r ret; \ command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, &ret); \ SYNC_DEBUG \ + MAIN_THREAD_SYNC_CHECK \ return ret; \ } else { \ command_queue.flush_if_pending(); \ @@ -367,6 +394,7 @@ if (Thread::get_caller_id() != server_thread) { \ command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4); \ SYNC_DEBUG \ + MAIN_THREAD_SYNC_CHECK \ } else { \ command_queue.flush_if_pending(); \ server_name->m_type(p1, p2, p3, p4); \ @@ -378,6 +406,7 @@ if (Thread::get_caller_id() != server_thread) { \ command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4); \ SYNC_DEBUG \ + MAIN_THREAD_SYNC_CHECK \ } else { \ command_queue.flush_if_pending(); \ server_name->m_type(p1, p2, p3, p4); \ @@ -412,6 +441,7 @@ m_r ret; \ command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, &ret); \ SYNC_DEBUG \ + MAIN_THREAD_SYNC_CHECK \ return ret; \ } else { \ command_queue.flush_if_pending(); \ @@ -425,6 +455,7 @@ m_r ret; \ command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, &ret); \ SYNC_DEBUG \ + MAIN_THREAD_SYNC_CHECK \ return ret; \ } else { \ command_queue.flush_if_pending(); \ @@ -438,6 +469,7 @@ if (Thread::get_caller_id() != server_thread) { \ command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5); \ SYNC_DEBUG \ + MAIN_THREAD_SYNC_CHECK \ } else { \ command_queue.flush_if_pending(); \ server_name->m_type(p1, p2, p3, p4, p5); \ @@ -449,6 +481,7 @@ if (Thread::get_caller_id() != server_thread) { \ command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5); \ SYNC_DEBUG \ + MAIN_THREAD_SYNC_CHECK \ } else { \ command_queue.flush_if_pending(); \ server_name->m_type(p1, p2, p3, p4, p5); \ @@ -483,6 +516,7 @@ m_r ret; \ command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, &ret); \ SYNC_DEBUG \ + MAIN_THREAD_SYNC_CHECK \ return ret; \ } else { \ command_queue.flush_if_pending(); \ @@ -496,6 +530,7 @@ m_r ret; \ command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, &ret); \ SYNC_DEBUG \ + MAIN_THREAD_SYNC_CHECK \ return ret; \ } else { \ command_queue.flush_if_pending(); \ @@ -509,6 +544,7 @@ if (Thread::get_caller_id() != server_thread) { \ command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6); \ SYNC_DEBUG \ + MAIN_THREAD_SYNC_CHECK \ } else { \ command_queue.flush_if_pending(); \ server_name->m_type(p1, p2, p3, p4, p5, p6); \ @@ -520,6 +556,7 @@ if (Thread::get_caller_id() != server_thread) { \ command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6); \ SYNC_DEBUG \ + MAIN_THREAD_SYNC_CHECK \ } else { \ command_queue.flush_if_pending(); \ server_name->m_type(p1, p2, p3, p4, p5, p6); \ @@ -554,6 +591,7 @@ m_r ret; \ command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, &ret); \ SYNC_DEBUG \ + MAIN_THREAD_SYNC_CHECK \ return ret; \ } else { \ command_queue.flush_if_pending(); \ @@ -567,6 +605,7 @@ m_r ret; \ command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, &ret); \ SYNC_DEBUG \ + MAIN_THREAD_SYNC_CHECK \ return ret; \ } else { \ command_queue.flush_if_pending(); \ @@ -580,6 +619,7 @@ if (Thread::get_caller_id() != server_thread) { \ command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7); \ SYNC_DEBUG \ + MAIN_THREAD_SYNC_CHECK \ } else { \ command_queue.flush_if_pending(); \ server_name->m_type(p1, p2, p3, p4, p5, p6, p7); \ @@ -591,6 +631,7 @@ if (Thread::get_caller_id() != server_thread) { \ command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7); \ SYNC_DEBUG \ + MAIN_THREAD_SYNC_CHECK \ } else { \ command_queue.flush_if_pending(); \ server_name->m_type(p1, p2, p3, p4, p5, p6, p7); \ @@ -625,6 +666,7 @@ m_r ret; \ command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, &ret); \ SYNC_DEBUG \ + MAIN_THREAD_SYNC_CHECK \ return ret; \ } else { \ command_queue.flush_if_pending(); \ @@ -638,6 +680,7 @@ m_r ret; \ command_queue.push_and_ret(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8, &ret); \ SYNC_DEBUG \ + MAIN_THREAD_SYNC_CHECK \ return ret; \ } else { \ command_queue.flush_if_pending(); \ @@ -651,6 +694,7 @@ if (Thread::get_caller_id() != server_thread) { \ command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8); \ SYNC_DEBUG \ + MAIN_THREAD_SYNC_CHECK \ } else { \ command_queue.flush_if_pending(); \ server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8); \ @@ -662,6 +706,7 @@ if (Thread::get_caller_id() != server_thread) { \ command_queue.push_and_sync(server_name, &ServerName::m_type, p1, p2, p3, p4, p5, p6, p7, p8); \ SYNC_DEBUG \ + MAIN_THREAD_SYNC_CHECK \ } else { \ command_queue.flush_if_pending(); \ server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8); \ |