Browse Source

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.
rdb 3 years ago
parent
commit
aea2d6ef45
1 changed files with 14 additions and 10 deletions
  1. 14 10
      panda/src/display/graphicsEngine.cxx

+ 14 - 10
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.