Browse Source

Allow calling dispatch_compute directly to GraphicsEngine

rdb 11 years ago
parent
commit
f8675fcd7b
2 changed files with 55 additions and 1 deletions
  1. 52 1
      panda/src/display/graphicsEngine.cxx
  2. 3 0
      panda/src/display/graphicsEngine.h

+ 52 - 1
panda/src/display/graphicsEngine.cxx

@@ -1093,7 +1093,58 @@ extract_texture_data(Texture *tex, GraphicsStateGuardian *gsg) {
     return gsg->extract_texture_data(tex);
   }
 }
- 
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsEngine::dispatch_compute
+//       Access: Published
+//  Description: Asks the indicated GraphicsStateGuardian to dispatch
+//               the compute shader in the given ShaderAttrib using
+//               the given work group counts.  This can act as an
+//               interface for running a one-off compute shader,
+//               without having to store it in the scene graph using
+//               a ComputeNode.
+//
+//               Since this requires a round-trip to the draw thread,
+//               it may require waiting for the current thread to
+//               finish rendering if it is called in a multithreaded
+//               environment.  However, you can call this several
+//               consecutive times on different textures for little
+//               additional cost.
+//
+//               The return value is true if the operation is
+//               successful, false otherwise.
+////////////////////////////////////////////////////////////////////
+void GraphicsEngine::
+dispatch_compute(const LVecBase3i &work_groups, const ShaderAttrib *sattr, GraphicsStateGuardian *gsg) {
+  ReMutexHolder holder(_lock);
+
+  CPT(RenderState) state = RenderState::make(sattr);
+
+  string draw_name = gsg->get_threading_model().get_draw_name();
+  if (draw_name.empty()) {
+    // A single-threaded environment.  No problem.
+
+  } else {
+    // A multi-threaded environment.  We have to wait until the draw
+    // thread has finished its current task.
+    WindowRenderer *wr = get_window_renderer(draw_name, 0);
+    RenderThread *thread = (RenderThread *)wr;
+    MutexHolder holder2(thread->_cv_mutex);
+      
+    while (thread->_thread_state != TS_wait) {
+      thread->_cv_done.wait();
+    }
+
+    // OK, now the draw thread is idle.  That's really good enough for
+    // our purposes; we don't *actually* need to make the draw thread
+    // do the work--it's sufficient that it's not doing anything else
+    // while we access the GSG.
+  }
+
+  gsg->set_state_and_transform(state, TransformState::make_identity());
+  gsg->dispatch_compute(work_groups[0], work_groups[1], work_groups[2]);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsEngine::get_global_ptr
 //       Access: Published, Static

+ 3 - 0
panda/src/display/graphicsEngine.h

@@ -108,6 +108,9 @@ PUBLISHED:
   BLOCKING void flip_frame();
 
   bool extract_texture_data(Texture *tex, GraphicsStateGuardian *gsg);
+  void dispatch_compute(const LVecBase3i &work_groups,
+                        const ShaderAttrib *sattr,
+                        GraphicsStateGuardian *gsg);
 
   static GraphicsEngine *get_global_ptr();