Skip to content

Commit 68422ab

Browse files
committed
Merge pull request godotengine#90913 from RandomShaper/wtp_servers_pro
Apply additional fixes to servers' threading
2 parents 2042420 + 1589433 commit 68422ab

15 files changed

+167
-157
lines changed

core/object/object.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2307,9 +2307,9 @@ void ObjectDB::setup() {
23072307
}
23082308

23092309
void ObjectDB::cleanup() {
2310-
if (slot_count > 0) {
2311-
spin_lock.lock();
2310+
spin_lock.lock();
23122311

2312+
if (slot_count > 0) {
23132313
WARN_PRINT("ObjectDB instances leaked at exit (run with --verbose for details).");
23142314
if (OS::get_singleton()->is_stdout_verbose()) {
23152315
// Ensure calling the native classes because if a leaked instance has a script
@@ -2340,10 +2340,11 @@ void ObjectDB::cleanup() {
23402340
}
23412341
print_line("Hint: Leaked instances typically happen when nodes are removed from the scene tree (with `remove_child()`) but not freed (with `free()` or `queue_free()`).");
23422342
}
2343-
spin_lock.unlock();
23442343
}
23452344

23462345
if (object_slots) {
23472346
memfree(object_slots);
23482347
}
2348+
2349+
spin_lock.unlock();
23492350
}

core/templates/command_queue_mt.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ class CommandQueueMT {
302302
struct CommandBase {
303303
bool sync = false;
304304
virtual void call() = 0;
305-
virtual ~CommandBase() = default; // Won't be called.
305+
virtual ~CommandBase() = default;
306306
};
307307

308308
struct SyncCommand : public CommandBase {
@@ -368,6 +368,10 @@ class CommandQueueMT {
368368
sync_cond_var.notify_all();
369369
}
370370

371+
// If the command involved reallocating the buffer, the address may have changed.
372+
cmd = reinterpret_cast<CommandBase *>(&command_mem[flush_read_ptr]);
373+
cmd->~CommandBase();
374+
371375
flush_read_ptr += size;
372376
}
373377
WorkerThreadPool::thread_exit_command_queue_mt_flush();
@@ -384,6 +388,8 @@ class CommandQueueMT {
384388
} while (sync_head != sync_head_goal); // Can't use lower-than because of wraparound.
385389
}
386390

391+
void _no_op() {}
392+
387393
public:
388394
void lock();
389395
void unlock();
@@ -405,18 +411,25 @@ class CommandQueueMT {
405411
_flush();
406412
}
407413
}
414+
408415
void flush_all() {
409416
_flush();
410417
}
411418

419+
void sync() {
420+
push_and_sync(this, &CommandQueueMT::_no_op);
421+
}
422+
412423
void wait_and_flush() {
413424
ERR_FAIL_COND(pump_task_id == WorkerThreadPool::INVALID_TASK_ID);
414425
WorkerThreadPool::get_singleton()->wait_for_task_completion(pump_task_id);
415426
_flush();
416427
}
417428

418429
void set_pump_task_id(WorkerThreadPool::TaskID p_task_id) {
430+
lock();
419431
pump_task_id = p_task_id;
432+
unlock();
420433
}
421434

422435
CommandQueueMT();

drivers/gles3/rasterizer_gles3.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -395,10 +395,13 @@ void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, Display
395395
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
396396

397397
if (p_first) {
398-
Size2i win_size = DisplayServer::get_singleton()->window_get_size();
399398
if (p_screen_rect.position != Vector2() || p_screen_rect.size != rt->size) {
400399
// Viewport doesn't cover entire window so clear window to black before blitting.
401-
glViewport(0, 0, win_size.width, win_size.height);
400+
// Querying the actual window size from the DisplayServer would deadlock in separate render thread mode,
401+
// so let's set the biggest viewport the implementation supports, to be sure the window is fully covered.
402+
GLsizei max_vp[2] = {};
403+
glGetIntegerv(GL_MAX_VIEWPORT_DIMS, max_vp);
404+
glViewport(0, 0, max_vp[0], max_vp[1]);
402405
glClearColor(0.0, 0.0, 0.0, 1.0);
403406
glClear(GL_COLOR_BUFFER_BIT);
404407
}

drivers/gles3/storage/texture_storage.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2312,9 +2312,11 @@ void TextureStorage::_clear_render_target(RenderTarget *rt) {
23122312

23132313
if (rt->backbuffer_fbo != 0) {
23142314
glDeleteFramebuffers(1, &rt->backbuffer_fbo);
2315+
rt->backbuffer_fbo = 0;
2316+
}
2317+
if (rt->backbuffer != 0) {
23152318
GLES3::Utilities::get_singleton()->texture_free_data(rt->backbuffer);
23162319
rt->backbuffer = 0;
2317-
rt->backbuffer_fbo = 0;
23182320
}
23192321
if (rt->backbuffer_depth != 0) {
23202322
GLES3::Utilities::get_singleton()->texture_free_data(rt->backbuffer_depth);

platform/linuxbsd/x11/display_server_x11.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4268,6 +4268,8 @@ bool DisplayServerX11::_window_focus_check() {
42684268
}
42694269

42704270
void DisplayServerX11::process_events() {
4271+
ERR_FAIL_COND(!Thread::is_main_thread());
4272+
42714273
_THREAD_SAFE_LOCK_
42724274

42734275
#ifdef DISPLAY_SERVER_X11_DEBUG_LOGS_ENABLED

platform/macos/display_server_macos.mm

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2985,7 +2985,7 @@
29852985
}
29862986

29872987
void DisplayServerMacOS::process_events() {
2988-
_THREAD_SAFE_LOCK_
2988+
ERR_FAIL_COND(!Thread::is_main_thread());
29892989

29902990
while (true) {
29912991
NSEvent *event = [NSApp
@@ -3018,11 +3018,11 @@
30183018

30193019
if (!drop_events) {
30203020
_process_key_events();
3021-
_THREAD_SAFE_UNLOCK_
30223021
Input::get_singleton()->flush_buffered_events();
3023-
_THREAD_SAFE_LOCK_
30243022
}
30253023

3024+
_THREAD_SAFE_LOCK_
3025+
30263026
for (KeyValue<WindowID, WindowData> &E : windows) {
30273027
WindowData &wd = E.value;
30283028
if (wd.mpass) {
@@ -3051,7 +3051,7 @@
30513051
}
30523052

30533053
void DisplayServerMacOS::force_process_and_drop_events() {
3054-
_THREAD_SAFE_METHOD_
3054+
ERR_FAIL_COND(!Thread::is_main_thread());
30553055

30563056
drop_events = true;
30573057
process_events();

platform/windows/display_server_windows.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2962,30 +2962,28 @@ String DisplayServerWindows::keyboard_get_layout_name(int p_index) const {
29622962
}
29632963

29642964
void DisplayServerWindows::process_events() {
2965-
_THREAD_SAFE_LOCK_
2966-
2967-
MSG msg;
2965+
ERR_FAIL_COND(!Thread::is_main_thread());
29682966

29692967
if (!drop_events) {
29702968
joypad->process_joypads();
29712969
}
29722970

2971+
_THREAD_SAFE_LOCK_
2972+
MSG msg = {};
29732973
while (PeekMessageW(&msg, nullptr, 0, 0, PM_REMOVE)) {
29742974
TranslateMessage(&msg);
29752975
DispatchMessageW(&msg);
29762976
}
2977+
_THREAD_SAFE_UNLOCK_
29772978

29782979
if (!drop_events) {
29792980
_process_key_events();
2980-
_THREAD_SAFE_UNLOCK_
29812981
Input::get_singleton()->flush_buffered_events();
2982-
} else {
2983-
_THREAD_SAFE_UNLOCK_
29842982
}
29852983
}
29862984

29872985
void DisplayServerWindows::force_process_and_drop_events() {
2988-
_THREAD_SAFE_METHOD_
2986+
ERR_FAIL_COND(!Thread::is_main_thread());
29892987

29902988
drop_events = true;
29912989
process_events();
@@ -4664,10 +4662,12 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
46644662
} break;
46654663
case WM_TIMER: {
46664664
if (wParam == windows[window_id].move_timer_id) {
4665+
_THREAD_SAFE_UNLOCK_
46674666
_process_key_events();
46684667
if (!Main::is_iterating()) {
46694668
Main::iteration();
46704669
}
4670+
_THREAD_SAFE_LOCK_
46714671
} else if (wParam == windows[window_id].activate_timer_id) {
46724672
_process_activate_event(window_id);
46734673
KillTimer(windows[window_id].hWnd, windows[window_id].activate_timer_id);

servers/physics_server_2d_wrap_mt.cpp

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -32,45 +32,37 @@
3232

3333
#include "core/os/os.h"
3434

35-
void PhysicsServer2DWrapMT::thread_exit() {
36-
exit = true;
35+
void PhysicsServer2DWrapMT::_assign_mt_ids(WorkerThreadPool::TaskID p_pump_task_id) {
36+
server_thread = Thread::get_caller_id();
37+
server_task_id = p_pump_task_id;
3738
}
3839

39-
void PhysicsServer2DWrapMT::thread_step(real_t p_delta) {
40-
physics_server_2d->step(p_delta);
41-
step_sem.post();
40+
void PhysicsServer2DWrapMT::_thread_exit() {
41+
exit = true;
4242
}
4343

44-
void PhysicsServer2DWrapMT::thread_loop() {
45-
server_thread = Thread::get_caller_id();
46-
47-
physics_server_2d->init();
48-
49-
command_queue.set_pump_task_id(server_task_id);
44+
void PhysicsServer2DWrapMT::_thread_loop() {
5045
while (!exit) {
5146
WorkerThreadPool::get_singleton()->yield();
5247
command_queue.flush_all();
5348
}
54-
55-
command_queue.flush_all();
56-
57-
physics_server_2d->finish();
5849
}
5950

6051
/* EVENT QUEUING */
6152

6253
void PhysicsServer2DWrapMT::step(real_t p_step) {
6354
if (create_thread) {
64-
command_queue.push(this, &PhysicsServer2DWrapMT::thread_step, p_step);
55+
command_queue.push(physics_server_2d, &PhysicsServer2D::step, p_step);
6556
} else {
66-
command_queue.flush_all(); // Flush all pending from other threads.
6757
physics_server_2d->step(p_step);
6858
}
6959
}
7060

7161
void PhysicsServer2DWrapMT::sync() {
7262
if (create_thread) {
73-
step_sem.wait();
63+
command_queue.sync();
64+
} else {
65+
command_queue.flush_all(); // Flush all pending from other threads.
7466
}
7567
physics_server_2d->sync();
7668
}
@@ -85,21 +77,26 @@ void PhysicsServer2DWrapMT::end_sync() {
8577

8678
void PhysicsServer2DWrapMT::init() {
8779
if (create_thread) {
88-
exit = false;
89-
server_task_id = WorkerThreadPool::get_singleton()->add_task(callable_mp(this, &PhysicsServer2DWrapMT::thread_loop), true);
90-
step_sem.post();
80+
WorkerThreadPool::TaskID tid = WorkerThreadPool::get_singleton()->add_task(callable_mp(this, &PhysicsServer2DWrapMT::_thread_loop), true);
81+
command_queue.set_pump_task_id(tid);
82+
command_queue.push(this, &PhysicsServer2DWrapMT::_assign_mt_ids, tid);
83+
command_queue.push_and_sync(physics_server_2d, &PhysicsServer2D::init);
84+
DEV_ASSERT(server_task_id == tid);
9185
} else {
86+
server_thread = Thread::MAIN_ID;
9287
physics_server_2d->init();
9388
}
9489
}
9590

9691
void PhysicsServer2DWrapMT::finish() {
9792
if (create_thread) {
98-
command_queue.push(this, &PhysicsServer2DWrapMT::thread_exit);
93+
command_queue.push(physics_server_2d, &PhysicsServer2D::finish);
94+
command_queue.push(this, &PhysicsServer2DWrapMT::_thread_exit);
9995
if (server_task_id != WorkerThreadPool::INVALID_TASK_ID) {
10096
WorkerThreadPool::get_singleton()->wait_for_task_completion(server_task_id);
10197
server_task_id = WorkerThreadPool::INVALID_TASK_ID;
10298
}
99+
server_thread = Thread::MAIN_ID;
103100
} else {
104101
physics_server_2d->finish();
105102
}
@@ -108,9 +105,6 @@ void PhysicsServer2DWrapMT::finish() {
108105
PhysicsServer2DWrapMT::PhysicsServer2DWrapMT(PhysicsServer2D *p_contained, bool p_create_thread) {
109106
physics_server_2d = p_contained;
110107
create_thread = p_create_thread;
111-
if (!create_thread) {
112-
server_thread = Thread::MAIN_ID;
113-
}
114108
}
115109

116110
PhysicsServer2DWrapMT::~PhysicsServer2DWrapMT() {

servers/physics_server_2d_wrap_mt.h

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,17 +53,14 @@ class PhysicsServer2DWrapMT : public PhysicsServer2D {
5353

5454
mutable CommandQueueMT command_queue;
5555

56-
void thread_loop();
57-
5856
Thread::ID server_thread = Thread::UNASSIGNED_ID;
5957
WorkerThreadPool::TaskID server_task_id = WorkerThreadPool::INVALID_TASK_ID;
6058
bool exit = false;
61-
Semaphore step_sem;
6259
bool create_thread = false;
6360

64-
void thread_step(real_t p_delta);
65-
66-
void thread_exit();
61+
void _assign_mt_ids(WorkerThreadPool::TaskID p_pump_task_id);
62+
void _thread_exit();
63+
void _thread_loop();
6764

6865
public:
6966
#define ServerName PhysicsServer2D

0 commit comments

Comments
 (0)