From aea2d6ef4535e96ec15a593cd5fe817fb75db072 Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 15 Feb 2022 17:28:36 +0100 Subject: [PATCH] display: Release lock before notifying render thread in GraphicsEngine Otherwise the render thread will wake up only to be blocked by the mutex right away. --- panda/src/display/graphicsEngine.cxx | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/panda/src/display/graphicsEngine.cxx b/panda/src/display/graphicsEngine.cxx index b15474fc3f..4951022af7 100644 --- a/panda/src/display/graphicsEngine.cxx +++ b/panda/src/display/graphicsEngine.cxx @@ -925,10 +925,14 @@ render_frame() { for (ti = _threads.begin(); ti != _threads.end(); ++ti) { RenderThread *thread = (*ti).second; if (thread->_thread_state == TS_wait) { + // Release before notifying, otherwise the other thread will wake up + // and get blocked on the mutex straight away. thread->_thread_state = TS_do_frame; + thread->_cv_mutex.release(); thread->_cv_start.notify(); + } else { + thread->_cv_mutex.release(); } - thread->_cv_mutex.release(); } // Some threads may still be drawing, so indicate that we have to wait for @@ -1036,8 +1040,8 @@ open_windows() { } thread->_thread_state = TS_do_windows; - thread->_cv_start.notify(); thread->_cv_mutex.release(); + thread->_cv_start.notify(); } } @@ -1154,11 +1158,11 @@ extract_texture_data(Texture *tex, GraphicsStateGuardian *gsg) { thread->_gsg = gsg; thread->_texture = tex; thread->_thread_state = TS_do_extract; - thread->_cv_start.notify(); thread->_cv_mutex.release(); + thread->_cv_start.notify(); thread->_cv_mutex.acquire(); - //XXX is this necessary, or is acquiring the mutex enough? + // Wait for it to finish the extraction. while (thread->_thread_state != TS_wait) { thread->_cv_done.wait(); } @@ -1222,11 +1226,11 @@ dispatch_compute(const LVecBase3i &work_groups, const ShaderAttrib *sattr, Graph thread->_state = state.p(); thread->_work_groups = work_groups; thread->_thread_state = TS_do_compute; - thread->_cv_start.notify(); thread->_cv_mutex.release(); + thread->_cv_start.notify(); thread->_cv_mutex.acquire(); - //XXX is this necessary, or is acquiring the mutex enough? + // Wait for it to finish the compute task. while (thread->_thread_state != TS_wait) { thread->_cv_done.wait(); } @@ -1292,11 +1296,11 @@ do_get_screenshot(DisplayRegion *region, GraphicsStateGuardian *gsg) { // Now that the draw thread is idle, signal it to do the extraction task. thread->_region = region; thread->_thread_state = TS_do_screenshot; - thread->_cv_start.notify(); thread->_cv_mutex.release(); + thread->_cv_start.notify(); thread->_cv_mutex.acquire(); - //XXX is this necessary, or is acquiring the mutex enough? + // Wait for it to finish the extraction. while (thread->_thread_state != TS_wait) { thread->_cv_done.wait(); } @@ -1937,8 +1941,8 @@ do_flip_frame(Thread *current_thread) { RenderThread *thread = (*ti).second; nassertv(thread->_thread_state == TS_wait); thread->_thread_state = TS_do_flip; - thread->_cv_start.notify(); thread->_cv_mutex.release(); + thread->_cv_start.notify(); } } @@ -2365,8 +2369,8 @@ terminate_threads(Thread *current_thread) { for (ti = _threads.begin(); ti != _threads.end(); ++ti) { RenderThread *thread = (*ti).second; thread->_thread_state = TS_terminate; - thread->_cv_start.notify(); thread->_cv_mutex.release(); + thread->_cv_start.notify(); } // Finally, wait for them all to finish cleaning up.