display: reduce GraphicsEngine traversal overhead a bit

This commit is contained in:
rdb 2017-02-20 00:23:21 +01:00
parent 4a8819b0bd
commit 53258af876
2 changed files with 75 additions and 102 deletions

View File

@ -1328,21 +1328,24 @@ cull_and_draw_together(GraphicsOutput *win, DisplayRegion *dr,
GraphicsStateGuardian *gsg = win->get_gsg(); GraphicsStateGuardian *gsg = win->get_gsg();
nassertv(gsg != (GraphicsStateGuardian *)NULL); nassertv(gsg != (GraphicsStateGuardian *)NULL);
DisplayRegionPipelineReader *dr_reader = PT(SceneSetup) scene_setup;
new DisplayRegionPipelineReader(dr, current_thread);
win->change_scenes(dr_reader); {
gsg->prepare_display_region(dr_reader); DisplayRegionPipelineReader dr_reader(dr, current_thread);
win->change_scenes(&dr_reader);
gsg->prepare_display_region(&dr_reader);
if (dr_reader->is_any_clear_active()) { if (dr_reader.is_any_clear_active()) {
gsg->clear(dr); gsg->clear(dr);
}
scene_setup = setup_scene(gsg, &dr_reader);
} }
PT(SceneSetup) scene_setup = setup_scene(gsg, dr_reader);
if (scene_setup == (SceneSetup *)NULL) { if (scene_setup == (SceneSetup *)NULL) {
// Never mind. // Never mind.
} else if (dr_reader->get_object()->is_stereo()) { } else if (dr->is_stereo()) {
// Don't draw stereo DisplayRegions directly. // Don't draw stereo DisplayRegions directly.
} else if (!gsg->set_scene(scene_setup)) { } else if (!gsg->set_scene(scene_setup)) {
@ -1353,9 +1356,6 @@ cull_and_draw_together(GraphicsOutput *win, DisplayRegion *dr,
} else { } else {
DrawCullHandler cull_handler(gsg); DrawCullHandler cull_handler(gsg);
if (gsg->begin_scene()) { if (gsg->begin_scene()) {
delete dr_reader;
dr_reader = NULL;
CallbackObject *cbobj = dr->get_cull_callback(); CallbackObject *cbobj = dr->get_cull_callback();
if (cbobj != (CallbackObject *)NULL) { if (cbobj != (CallbackObject *)NULL) {
// Issue the cull callback on this DisplayRegion. // Issue the cull callback on this DisplayRegion.
@ -1372,10 +1372,6 @@ cull_and_draw_together(GraphicsOutput *win, DisplayRegion *dr,
gsg->end_scene(); 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) { for (size_t wi = 0; wi < wlist_size; ++wi) {
GraphicsOutput *win = wlist[wi]; GraphicsOutput *win = wlist[wi];
if (win->is_active() && win->get_gsg()->is_active()) { if (win->is_active() && win->get_gsg()->is_active()) {
GraphicsStateGuardian *gsg = win->get_gsg();
PStatTimer timer(win->get_cull_window_pcollector(), current_thread); PStatTimer timer(win->get_cull_window_pcollector(), current_thread);
int num_display_regions = win->get_num_active_display_regions(); int num_display_regions = win->get_num_active_display_regions();
for (int i = 0; i < num_display_regions; ++i) { for (int i = 0; i < num_display_regions; ++i) {
DisplayRegion *dr = win->get_active_display_region(i); DisplayRegion *dr = win->get_active_display_region(i);
if (dr != (DisplayRegion *)NULL) { if (dr != nullptr) {
DisplayRegionPipelineReader *dr_reader = PT(SceneSetup) scene_setup;
new DisplayRegionPipelineReader(dr, current_thread); PT(CullResult) cull_result;
CullKey key; CullKey key;
key._gsg = win->get_gsg(); {
key._camera = dr_reader->get_camera(); PStatTimer timer(_cull_setup_pcollector, current_thread);
key._lens_index = dr_reader->get_lens_index(); DisplayRegionPipelineReader dr_reader(dr, current_thread);
scene_setup = setup_scene(gsg, &dr_reader);
if (scene_setup == nullptr) {
continue;
}
AlreadyCulled::iterator aci = already_culled.insert(AlreadyCulled::value_type(key, (DisplayRegion *)NULL)).first; key._gsg = gsg;
if ((*aci).second == NULL) { key._camera = dr_reader.get_camera();
key._lens_index = dr_reader.get_lens_index();
}
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 // We have not used this camera already in this thread. Perform
// the cull operation. // the cull operation.
delete dr_reader; cull_result = dr->get_cull_result(current_thread);
dr_reader = NULL; 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; (*aci).second = dr;
cull_to_bins(win, dr, current_thread); cull_to_bins(win, gsg, dr, scene_setup, cull_result, current_thread);
} else { } else {
// We have already culled a scene using this camera in this // 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 // image.) Of course, the cull result will be the same, so just
// use the result from the other DisplayRegion. // use the result from the other DisplayRegion.
DisplayRegion *other_dr = (*aci).second; DisplayRegion *other_dr = (*aci).second;
dr->set_cull_result(other_dr->get_cull_result(current_thread), cull_result = other_dr->get_cull_result(current_thread);
setup_scene(win->get_gsg(), dr_reader),
current_thread);
} }
if (dr_reader != (DisplayRegionPipelineReader *)NULL) { // Save the results for next frame.
delete dr_reader; 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. * Called only within the inner loop of cull_to_bins(), above.
*/ */
void GraphicsEngine:: void GraphicsEngine::
cull_to_bins(GraphicsOutput *win, DisplayRegion *dr, Thread *current_thread) { cull_to_bins(GraphicsOutput *win, GraphicsStateGuardian *gsg,
GraphicsStateGuardian *gsg = win->get_gsg(); DisplayRegion *dr, SceneSetup *scene_setup,
if (gsg == (GraphicsStateGuardian *)NULL) { CullResult *cull_result, Thread *current_thread) {
return;
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.
} else {
// Perform the cull normally.
dr->do_cull(&cull_handler, scene_setup, gsg, current_thread);
} }
PT(CullResult) cull_result; PStatTimer timer(_cull_sort_pcollector, current_thread);
PT(SceneSetup) scene_setup; cull_result->finish_cull(scene_setup, current_thread);
{
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();
} 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);
// 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);
}
// Save the results for next frame.
dr->set_cull_result(MOVE(cull_result), MOVE(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) { for (int i = 0; i < num_display_regions; ++i) {
DisplayRegion *dr = win->get_active_display_region(i); DisplayRegion *dr = win->get_active_display_region(i);
if (dr != (DisplayRegion *)NULL) { 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 * 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. * 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. * Draws the previously-culled scene.
*/ */
void GraphicsEngine:: void GraphicsEngine::
do_draw(CullResult *cull_result, SceneSetup *scene_setup, do_draw(GraphicsOutput *win, GraphicsStateGuardian *gsg, DisplayRegion *dr, Thread *current_thread) {
GraphicsOutput *win, DisplayRegion *dr, Thread *current_thread) {
CallbackObject *cbobj;
GraphicsStateGuardian *gsg = win->get_gsg();
// Statistics // Statistics
PStatGPUTimer timer(gsg, dr->get_draw_region_pcollector(), current_thread); 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); DisplayRegionPipelineReader dr_reader(dr, current_thread);
win->change_scenes(&dr_reader); win->change_scenes(&dr_reader);

View File

@ -147,9 +147,10 @@ private:
Thread *current_thread); Thread *current_thread);
void cull_to_bins(const Windows &wlist, 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(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 make_contexts(const Windows &wlist, Thread *current_thread);
void process_events(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, PT(SceneSetup) setup_scene(GraphicsStateGuardian *gsg,
DisplayRegionPipelineReader *dr); DisplayRegionPipelineReader *dr);
void do_draw(CullResult *cull_result, SceneSetup *scene_setup, void do_draw(GraphicsOutput *win, GraphicsStateGuardian *gsg,
GraphicsOutput *win, DisplayRegion *dr, Thread *current_thread); DisplayRegion *dr, Thread *current_thread);
void do_add_window(GraphicsOutput *window, void do_add_window(GraphicsOutput *window,
const GraphicsThreadingModel &threading_model); const GraphicsThreadingModel &threading_model);