Kaynağa Gözat

display: reduce GraphicsEngine traversal overhead a bit

rdb 8 yıl önce
ebeveyn
işleme
53258af876

+ 67 - 95
panda/src/display/graphicsEngine.cxx

@@ -1328,21 +1328,24 @@ cull_and_draw_together(GraphicsOutput *win, DisplayRegion *dr,
   GraphicsStateGuardian *gsg = win->get_gsg();
   nassertv(gsg != (GraphicsStateGuardian *)NULL);
 
-  DisplayRegionPipelineReader *dr_reader =
-    new DisplayRegionPipelineReader(dr, current_thread);
+  PT(SceneSetup) scene_setup;
+
+  {
+    DisplayRegionPipelineReader dr_reader(dr, current_thread);
+    win->change_scenes(&dr_reader);
+    gsg->prepare_display_region(&dr_reader);
 
-  win->change_scenes(dr_reader);
-  gsg->prepare_display_region(dr_reader);
+    if (dr_reader.is_any_clear_active()) {
+      gsg->clear(dr);
+    }
 
-  if (dr_reader->is_any_clear_active()) {
-    gsg->clear(dr);
+    scene_setup = setup_scene(gsg, &dr_reader);
   }
 
-  PT(SceneSetup) scene_setup = setup_scene(gsg, dr_reader);
   if (scene_setup == (SceneSetup *)NULL) {
     // Never mind.
 
-  } else if (dr_reader->get_object()->is_stereo()) {
+  } else if (dr->is_stereo()) {
     // Don't draw stereo DisplayRegions directly.
 
   } else if (!gsg->set_scene(scene_setup)) {
@@ -1353,9 +1356,6 @@ cull_and_draw_together(GraphicsOutput *win, DisplayRegion *dr,
   } else {
     DrawCullHandler cull_handler(gsg);
     if (gsg->begin_scene()) {
-      delete dr_reader;
-      dr_reader = NULL;
-
       CallbackObject *cbobj = dr->get_cull_callback();
       if (cbobj != (CallbackObject *)NULL) {
         // Issue the cull callback on this DisplayRegion.
@@ -1372,10 +1372,6 @@ cull_and_draw_together(GraphicsOutput *win, DisplayRegion *dr,
       gsg->end_scene();
     }
   }
-
-  if (dr_reader != (DisplayRegionPipelineReader *)NULL) {
-    delete dr_reader;
-  }
 }
 
 /**
@@ -1399,27 +1395,41 @@ cull_to_bins(const GraphicsEngine::Windows &wlist, Thread *current_thread) {
   for (size_t wi = 0; wi < wlist_size; ++wi) {
     GraphicsOutput *win = wlist[wi];
     if (win->is_active() && win->get_gsg()->is_active()) {
+      GraphicsStateGuardian *gsg = win->get_gsg();
       PStatTimer timer(win->get_cull_window_pcollector(), current_thread);
       int num_display_regions = win->get_num_active_display_regions();
       for (int i = 0; i < num_display_regions; ++i) {
         DisplayRegion *dr = win->get_active_display_region(i);
-        if (dr != (DisplayRegion *)NULL) {
-          DisplayRegionPipelineReader *dr_reader =
-            new DisplayRegionPipelineReader(dr, current_thread);
-
+        if (dr != nullptr) {
+          PT(SceneSetup) scene_setup;
+          PT(CullResult) cull_result;
           CullKey key;
-          key._gsg = win->get_gsg();
-          key._camera = dr_reader->get_camera();
-          key._lens_index = dr_reader->get_lens_index();
+          {
+            PStatTimer timer(_cull_setup_pcollector, current_thread);
+            DisplayRegionPipelineReader dr_reader(dr, current_thread);
+            scene_setup = setup_scene(gsg, &dr_reader);
+            if (scene_setup == nullptr) {
+              continue;
+            }
+
+            key._gsg = gsg;
+            key._camera = dr_reader.get_camera();
+            key._lens_index = dr_reader.get_lens_index();
+          }
 
-          AlreadyCulled::iterator aci = already_culled.insert(AlreadyCulled::value_type(key, (DisplayRegion *)NULL)).first;
-          if ((*aci).second == NULL) {
+          AlreadyCulled::iterator aci = already_culled.insert(AlreadyCulled::value_type(move(key), nullptr)).first;
+          if ((*aci).second == nullptr) {
             // We have not used this camera already in this thread.  Perform
             // the cull operation.
-            delete dr_reader;
-            dr_reader = NULL;
+            cull_result = dr->get_cull_result(current_thread);
+            if (cull_result != nullptr) {
+              cull_result = cull_result->make_next();
+            } else {
+              // This DisplayRegion has no cull results; draw it.
+              cull_result = new CullResult(gsg, dr->get_draw_region_pcollector());
+            }
             (*aci).second = dr;
-            cull_to_bins(win, dr, current_thread);
+            cull_to_bins(win, gsg, dr, scene_setup, cull_result, current_thread);
 
           } else {
             // We have already culled a scene using this camera in this
@@ -1429,14 +1439,11 @@ cull_to_bins(const GraphicsEngine::Windows &wlist, Thread *current_thread) {
             // image.)  Of course, the cull result will be the same, so just
             // use the result from the other DisplayRegion.
             DisplayRegion *other_dr = (*aci).second;
-            dr->set_cull_result(other_dr->get_cull_result(current_thread),
-                                setup_scene(win->get_gsg(), dr_reader),
-                                current_thread);
+            cull_result = other_dr->get_cull_result(current_thread);
           }
 
-          if (dr_reader != (DisplayRegionPipelineReader *)NULL) {
-            delete dr_reader;
-          }
+          // Save the results for next frame.
+          dr->set_cull_result(MOVE(cull_result), MOVE(scene_setup), current_thread);
         }
       }
     }
@@ -1447,50 +1454,26 @@ cull_to_bins(const GraphicsEngine::Windows &wlist, Thread *current_thread) {
  * Called only within the inner loop of cull_to_bins(), above.
  */
 void GraphicsEngine::
-cull_to_bins(GraphicsOutput *win, DisplayRegion *dr, Thread *current_thread) {
-  GraphicsStateGuardian *gsg = win->get_gsg();
-  if (gsg == (GraphicsStateGuardian *)NULL) {
-    return;
-  }
-
-  PT(CullResult) cull_result;
-  PT(SceneSetup) scene_setup;
-  {
-    PStatTimer timer(_cull_setup_pcollector, current_thread);
-    DisplayRegionPipelineReader dr_reader(dr, current_thread);
-    scene_setup = setup_scene(gsg, &dr_reader);
-    cull_result = dr->get_cull_result(current_thread);
-
-    if (cull_result != (CullResult *)NULL) {
-      cull_result = cull_result->make_next();
+cull_to_bins(GraphicsOutput *win, GraphicsStateGuardian *gsg,
+             DisplayRegion *dr, SceneSetup *scene_setup,
+             CullResult *cull_result, Thread *current_thread) {
 
-    } else {
-      // This DisplayRegion has no cull results; draw it.
-      cull_result = new CullResult(gsg, dr->get_draw_region_pcollector());
-    }
-  }
-
-  if (scene_setup != (SceneSetup *)NULL) {
-    BinCullHandler cull_handler(cull_result);
-    CallbackObject *cbobj = dr->get_cull_callback();
-    if (cbobj != (CallbackObject *)NULL) {
-      // Issue the cull callback on this DisplayRegion.
-      DisplayRegionCullCallbackData cbdata(&cull_handler, scene_setup);
-      cbobj->do_callback(&cbdata);
+  BinCullHandler cull_handler(cull_result);
+  CallbackObject *cbobj = dr->get_cull_callback();
+  if (cbobj != (CallbackObject *)NULL) {
+    // Issue the cull callback on this DisplayRegion.
+    DisplayRegionCullCallbackData cbdata(&cull_handler, scene_setup);
+    cbobj->do_callback(&cbdata);
 
-      // The callback has taken care of the culling.
+    // The callback has taken care of the culling.
 
-    } else {
-      // Perform the cull normally.
-      dr->do_cull(&cull_handler, scene_setup, gsg, current_thread);
-    }
-
-    PStatTimer timer(_cull_sort_pcollector, current_thread);
-    cull_result->finish_cull(scene_setup, current_thread);
+  } else {
+    // Perform the cull normally.
+    dr->do_cull(&cull_handler, scene_setup, gsg, current_thread);
   }
 
-  // Save the results for next frame.
-  dr->set_cull_result(MOVE(cull_result), MOVE(scene_setup), current_thread);
+  PStatTimer timer(_cull_sort_pcollector, current_thread);
+  cull_result->finish_cull(scene_setup, current_thread);
 }
 
 /**
@@ -1538,7 +1521,7 @@ draw_bins(const GraphicsEngine::Windows &wlist, Thread *current_thread) {
           for (int i = 0; i < num_display_regions; ++i) {
             DisplayRegion *dr = win->get_active_display_region(i);
             if (dr != (DisplayRegion *)NULL) {
-              draw_bins(win, dr, current_thread);
+              do_draw(win, gsg, dr, current_thread);
             }
           }
         }
@@ -1582,22 +1565,6 @@ draw_bins(const GraphicsEngine::Windows &wlist, Thread *current_thread) {
   }
 }
 
-/**
- * This variant on draw_bins() is only called from draw_bins(), above.  It
- * draws the cull result for a particular DisplayRegion.
- */
-void GraphicsEngine::
-draw_bins(GraphicsOutput *win, DisplayRegion *dr, Thread *current_thread) {
-  GraphicsStateGuardian *gsg = win->get_gsg();
-  if (gsg == (GraphicsStateGuardian *)NULL) {
-    return;
-  }
-
-  PT(CullResult) cull_result = dr->get_cull_result(current_thread);
-  PT(SceneSetup) scene_setup = dr->get_scene_setup(current_thread);
-  do_draw(cull_result, scene_setup, win, dr, current_thread);
-}
-
 /**
  * Called in the draw thread, this calls make_context() on each window on the
  * list to guarantee its gsg and graphics context both get created.
@@ -1899,15 +1866,20 @@ setup_scene(GraphicsStateGuardian *gsg, DisplayRegionPipelineReader *dr) {
  * Draws the previously-culled scene.
  */
 void GraphicsEngine::
-do_draw(CullResult *cull_result, SceneSetup *scene_setup,
-        GraphicsOutput *win, DisplayRegion *dr, Thread *current_thread) {
-
-  CallbackObject *cbobj;
-  GraphicsStateGuardian *gsg = win->get_gsg();
-
+do_draw(GraphicsOutput *win, GraphicsStateGuardian *gsg, DisplayRegion *dr, Thread *current_thread) {
   // Statistics
   PStatGPUTimer timer(gsg, dr->get_draw_region_pcollector(), current_thread);
 
+  PT(CullResult) cull_result;
+  PT(SceneSetup) scene_setup;
+  {
+    DisplayRegion::CDCullReader cdata(dr->_cycler_cull, current_thread);
+    cull_result = cdata->_cull_result;
+    scene_setup = cdata->_scene_setup;
+  }
+
+  CallbackObject *cbobj;
+
   {
     DisplayRegionPipelineReader dr_reader(dr, current_thread);
     win->change_scenes(&dr_reader);

+ 5 - 4
panda/src/display/graphicsEngine.h

@@ -147,9 +147,10 @@ private:
                               Thread *current_thread);
 
   void cull_to_bins(const Windows &wlist, Thread *current_thread);
-  void cull_to_bins(GraphicsOutput *win, DisplayRegion *dr, Thread *current_thread);
+  void cull_to_bins(GraphicsOutput *win, GraphicsStateGuardian *gsg,
+                    DisplayRegion *dr, SceneSetup *scene_setup,
+                    CullResult *cull_result, Thread *current_thread);
   void draw_bins(const Windows &wlist, Thread *current_thread);
-  void draw_bins(GraphicsOutput *win, DisplayRegion *dr, Thread *current_thread);
   void make_contexts(const Windows &wlist, Thread *current_thread);
 
   void process_events(const Windows &wlist, Thread *current_thread);
@@ -162,8 +163,8 @@ private:
 
   PT(SceneSetup) setup_scene(GraphicsStateGuardian *gsg,
                              DisplayRegionPipelineReader *dr);
-  void do_draw(CullResult *cull_result, SceneSetup *scene_setup,
-               GraphicsOutput *win, DisplayRegion *dr, Thread *current_thread);
+  void do_draw(GraphicsOutput *win, GraphicsStateGuardian *gsg,
+               DisplayRegion *dr, Thread *current_thread);
 
   void do_add_window(GraphicsOutput *window,
                      const GraphicsThreadingModel &threading_model);