Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use WorkerThreadPool for Server threads #77004

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions core/config/engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,16 @@ int Engine::get_audio_output_latency() const {
return _audio_output_latency;
}

void Engine::increment_frames_drawn() {
if (frame_server_synced) {
server_syncs++;
} else {
server_syncs = 0;
}
frame_server_synced = 0;

frames_drawn++;
}
uint64_t Engine::get_frames_drawn() {
return frames_drawn;
}
Expand Down Expand Up @@ -351,6 +361,11 @@ Engine *Engine::get_singleton() {
return singleton;
}

bool Engine::notify_frame_server_synced() {
frame_server_synced = true;
return server_syncs > server_sync_frame_count_warning;
}

Engine::Engine() {
singleton = this;
}
Expand Down
7 changes: 7 additions & 0 deletions core/config/engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ class Engine {
String write_movie_path;
String shader_cache_path;

static constexpr int server_sync_frame_count_warning = 5;
int server_syncs = 0;
bool frame_server_synced = false;

public:
static Engine *get_singleton();

Expand Down Expand Up @@ -175,6 +179,9 @@ class Engine {
bool is_generate_spirv_debug_info_enabled() const;
int32_t get_gpu_index() const;

void increment_frames_drawn();
bool notify_frame_server_synced();

Engine();
virtual ~Engine() {}
};
Expand Down
4 changes: 4 additions & 0 deletions drivers/gles3/rasterizer_gles3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@ void RasterizerGLES3::end_viewport(bool p_swap_buffers) {
}
}

void RasterizerGLES3::context_move_to_current_thread() {
DisplayServer::get_singleton()->make_rendering_thread();
}

void RasterizerGLES3::clear_depth(float p_depth) {
#ifdef GL_API_ENABLED
if (is_gles_over_gl()) {
Expand Down
2 changes: 2 additions & 0 deletions drivers/gles3/rasterizer_gles3.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ class RasterizerGLES3 : public RendererCompositor {
_ALWAYS_INLINE_ double get_frame_delta_time() const { return delta; }
_ALWAYS_INLINE_ double get_total_time() const { return time_total; }

virtual void context_move_to_current_thread();

static RasterizerGLES3 *get_singleton() { return singleton; }
RasterizerGLES3();
~RasterizerGLES3();
Expand Down
4 changes: 2 additions & 2 deletions main/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3799,11 +3799,11 @@ bool Main::iteration() {
if ((!force_redraw_requested) && OS::get_singleton()->is_in_low_processor_usage_mode()) {
if (RenderingServer::get_singleton()->has_changed()) {
RenderingServer::get_singleton()->draw(true, scaled_step); // flush visual commands
Engine::get_singleton()->frames_drawn++;
Engine::get_singleton()->increment_frames_drawn();
}
} else {
RenderingServer::get_singleton()->draw(true, scaled_step); // flush visual commands
Engine::get_singleton()->frames_drawn++;
Engine::get_singleton()->increment_frames_drawn();
force_redraw_requested = false;
}
}
Expand Down
67 changes: 21 additions & 46 deletions servers/physics_server_2d_wrap_mt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,43 +32,28 @@

#include "core/os/os.h"

void PhysicsServer2DWrapMT::thread_exit() {
exit.set();
}

void PhysicsServer2DWrapMT::thread_step(real_t p_delta) {
server_thread = Thread::get_caller_id();
command_queue.flush_all();
physics_server_2d->step(p_delta);
step_sem.post();
}

void PhysicsServer2DWrapMT::_thread_callback(void *_instance) {
PhysicsServer2DWrapMT *vsmt = reinterpret_cast<PhysicsServer2DWrapMT *>(_instance);

vsmt->thread_loop();
command_queue.flush_all(); // Flush pending commands before and after
server_thread = Thread::UNASSIGNED_ID;
}

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();
void PhysicsServer2DWrapMT::_main_thread_sync() {
if (task_id != WorkerThreadPool::INVALID_TASK_ID) {
WorkerThreadPool::get_singleton()->wait_for_task_completion(task_id);
task_id = WorkerThreadPool::INVALID_TASK_ID;
}

command_queue.flush_all(); // flush all

physics_server_2d->finish();
server_thread = Thread::MAIN_ID;
}

/* EVENT QUEUING */

void PhysicsServer2DWrapMT::step(real_t p_step) {
if (create_thread) {
command_queue.push(this, &PhysicsServer2DWrapMT::thread_step, p_step);
task_id = WorkerThreadPool::get_singleton()->add_task(callable_mp(this, &PhysicsServer2DWrapMT::thread_step).bind(p_step), true);
} else {
command_queue.flush_all(); //flush all pending from other threads
physics_server_2d->step(p_step);
Expand All @@ -77,10 +62,9 @@ void PhysicsServer2DWrapMT::step(real_t 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
if (task_id != WorkerThreadPool::INVALID_TASK_ID) {
WorkerThreadPool::get_singleton()->wait_for_task_completion(task_id);
task_id = WorkerThreadPool::INVALID_TASK_ID;
}
}
physics_server_2d->sync();
Expand All @@ -95,24 +79,15 @@ 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);
}
} else {
physics_server_2d->init();
}
physics_server_2d->init();
}

void PhysicsServer2DWrapMT::finish() {
if (thread.is_started()) {
command_queue.push(this, &PhysicsServer2DWrapMT::thread_exit);
thread.wait_to_finish();
} else {
physics_server_2d->finish();
if (task_id != WorkerThreadPool::INVALID_TASK_ID) {
WorkerThreadPool::get_singleton()->wait_for_task_completion(task_id);
task_id = WorkerThreadPool::INVALID_TASK_ID;
}
physics_server_2d->finish();
}

PhysicsServer2DWrapMT::PhysicsServer2DWrapMT(PhysicsServer2D *p_contained, bool p_create_thread) :
Expand All @@ -121,12 +96,12 @@ PhysicsServer2DWrapMT::PhysicsServer2DWrapMT(PhysicsServer2D *p_contained, bool
create_thread = p_create_thread;

if (!p_create_thread) {
server_thread = Thread::get_caller_id();
server_thread = Thread::MAIN_ID;
} else {
server_thread = 0;
server_thread = Thread::UNASSIGNED_ID;
}

main_thread = Thread::get_caller_id();
main_thread = Thread::MAIN_ID;
}

PhysicsServer2DWrapMT::~PhysicsServer2DWrapMT() {
Expand Down
21 changes: 16 additions & 5 deletions servers/physics_server_2d_wrap_mt.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -43,29 +44,38 @@
#define SYNC_DEBUG
#endif

#ifdef DEBUG_ENABLED
#define MAIN_THREAD_SYNC \
if (Engine::get_singleton()->notify_frame_server_synced()) { \
WARN_PRINT("Call to " + String(__FUNCTION__) + " causing PhysicsServer2D synchronizations on every frame. This significantly affects performance."); \
} \
const_cast<PhysicsServer2DWrapMT *>(this)->_main_thread_sync();
#else
#define MAIN_THREAD_SYNC const_cast<PhysicsServer2DWrapMT *>(this)->_main_thread_sync();
#endif

class PhysicsServer2DWrapMT : public PhysicsServer2D {
mutable PhysicsServer2D *physics_server_2d;

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;
bool create_thread = false;
WorkerThreadPool::TaskID task_id = WorkerThreadPool::INVALID_TASK_ID;

Semaphore step_sem;
void thread_step(real_t p_delta);

void thread_exit();

void _main_thread_sync();

bool first_frame = true;

Mutex alloc_mutex;
int pool_max_size = 0;

public:
#define ServerName PhysicsServer2D
Expand Down Expand Up @@ -337,5 +347,6 @@ class PhysicsServer2DWrapMT : public PhysicsServer2D {
#undef DEBUG_SYNC
#endif
#undef SYNC_DEBUG
#undef MAIN_THREAD_SYNC

#endif // PHYSICS_SERVER_2D_WRAP_MT_H
67 changes: 21 additions & 46 deletions servers/physics_server_3d_wrap_mt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,43 +32,28 @@

#include "core/os/os.h"

void PhysicsServer3DWrapMT::thread_exit() {
exit = true;
}

void PhysicsServer3DWrapMT::thread_step(real_t p_delta) {
server_thread = Thread::get_caller_id();
command_queue.flush_all();
physics_server_3d->step(p_delta);
step_sem.post();
}

void PhysicsServer3DWrapMT::_thread_callback(void *_instance) {
PhysicsServer3DWrapMT *vsmt = reinterpret_cast<PhysicsServer3DWrapMT *>(_instance);

vsmt->thread_loop();
command_queue.flush_all(); // Flush pending commands before and after
server_thread = Thread::UNASSIGNED_ID;
}

void PhysicsServer3DWrapMT::thread_loop() {
server_thread = Thread::get_caller_id();

physics_server_3d->init();

exit = false;
step_thread_up = true;
while (!exit) {
// flush commands one by one, until exit is requested
command_queue.wait_and_flush();
void PhysicsServer3DWrapMT::_main_thread_sync() {
if (task_id != WorkerThreadPool::INVALID_TASK_ID) {
WorkerThreadPool::get_singleton()->wait_for_task_completion(task_id);
task_id = WorkerThreadPool::INVALID_TASK_ID;
}

command_queue.flush_all(); // flush all

physics_server_3d->finish();
server_thread = Thread::MAIN_ID;
}

/* EVENT QUEUING */

void PhysicsServer3DWrapMT::step(real_t p_step) {
if (create_thread) {
command_queue.push(this, &PhysicsServer3DWrapMT::thread_step, p_step);
task_id = WorkerThreadPool::get_singleton()->add_task(callable_mp(this, &PhysicsServer3DWrapMT::thread_step).bind(p_step), true);
} else {
command_queue.flush_all(); //flush all pending from other threads
physics_server_3d->step(p_step);
Expand All @@ -77,10 +62,9 @@ void PhysicsServer3DWrapMT::step(real_t 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
if (task_id != WorkerThreadPool::INVALID_TASK_ID) {
WorkerThreadPool::get_singleton()->wait_for_task_completion(task_id);
task_id = WorkerThreadPool::INVALID_TASK_ID;
}
}
physics_server_3d->sync();
Expand All @@ -95,24 +79,15 @@ 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);
}
} else {
physics_server_3d->init();
}
physics_server_3d->init();
}

void PhysicsServer3DWrapMT::finish() {
if (thread.is_started()) {
command_queue.push(this, &PhysicsServer3DWrapMT::thread_exit);
thread.wait_to_finish();
} else {
physics_server_3d->finish();
if (task_id != WorkerThreadPool::INVALID_TASK_ID) {
WorkerThreadPool::get_singleton()->wait_for_task_completion(task_id);
task_id = WorkerThreadPool::INVALID_TASK_ID;
}
physics_server_3d->finish();
}

PhysicsServer3DWrapMT::PhysicsServer3DWrapMT(PhysicsServer3D *p_contained, bool p_create_thread) :
Expand All @@ -121,12 +96,12 @@ PhysicsServer3DWrapMT::PhysicsServer3DWrapMT(PhysicsServer3D *p_contained, bool
create_thread = p_create_thread;

if (!p_create_thread) {
server_thread = Thread::get_caller_id();
server_thread = Thread::MAIN_ID;
} else {
server_thread = 0;
server_thread = Thread::UNASSIGNED_ID;
}

main_thread = Thread::get_caller_id();
main_thread = Thread::MAIN_ID;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one can go away, can't it?

}

PhysicsServer3DWrapMT::~PhysicsServer3DWrapMT() {
Expand Down
Loading
Loading