diff --git a/panda/src/display/graphicsEngine.I b/panda/src/display/graphicsEngine.I index da203c973d..a7078dbac6 100644 --- a/panda/src/display/graphicsEngine.I +++ b/panda/src/display/graphicsEngine.I @@ -22,11 +22,9 @@ // Access: Published // Description: Set this flag true to indicate the GraphicsEngine // should automatically cause windows to sync and flip -// at the end of render_frame(). -// -// This only applies to a single-threaded rendering -// model. In the presence of threading, the windows are -// never auto-flipped, regardless of this flag. +// as soon as they have finished drawing, rather than +// waiting for all of the windows to finish drawing +// first so they can flip together. // // This only affects the timing of when the flip occurs. // If this is true (the default), the flip occurs before diff --git a/panda/src/display/graphicsEngine.cxx b/panda/src/display/graphicsEngine.cxx index 5f204aa3eb..b2a8e66ef1 100644 --- a/panda/src/display/graphicsEngine.cxx +++ b/panda/src/display/graphicsEngine.cxx @@ -47,6 +47,8 @@ PStatCollector GraphicsEngine::_cull_pcollector("Cull"); PStatCollector GraphicsEngine::_draw_pcollector("Draw"); PStatCollector GraphicsEngine::_sync_pcollector("Draw:Sync"); PStatCollector GraphicsEngine::_flip_pcollector("Draw:Flip"); +PStatCollector GraphicsEngine::_flip_begin_pcollector("Draw:Flip:Begin"); +PStatCollector GraphicsEngine::_flip_end_pcollector("Draw:Flip:End"); PStatCollector GraphicsEngine::_transform_states_pcollector("TransformStates"); PStatCollector GraphicsEngine::_transform_states_unused_pcollector("TransformStates:Unused"); PStatCollector GraphicsEngine::_render_states_pcollector("RenderStates"); @@ -492,13 +494,7 @@ render_frame() { // Some threads may still be drawing, so indicate that we have to // wait for those threads before we can flip. - _flip_state = FS_draw; - - // But if we don't have any threads, go ahead and flip the frame - // now. No point in waiting if we're single-threaded. - if (_threads.empty() && _auto_flip) { - do_flip_frame(); - } + _flip_state = _auto_flip ? FS_flip : FS_draw; if (yield_timeslice) { // Nap for a moment to yield the timeslice, to be polite to other @@ -706,6 +702,19 @@ cull_and_draw_together(const GraphicsEngine::Windows &wlist) { cull_and_draw_together(win->get_gsg(), dr); } win->end_frame(); + + if (_auto_flip) { + if (win->flip_ready()) { + { + PStatTimer timer(GraphicsEngine::_flip_begin_pcollector); + win->begin_flip(); + } + { + PStatTimer timer(GraphicsEngine::_flip_end_pcollector); + win->end_flip(); + } + } + } } } } @@ -762,8 +771,20 @@ cull_bin_draw(const GraphicsEngine::Windows &wlist) { DisplayRegion *dr = win->get_display_region(i); cull_bin_draw(win->get_gsg(), dr); } - win->end_frame(); + + if (_auto_flip) { + if (win->flip_ready()) { + { + PStatTimer timer(GraphicsEngine::_flip_begin_pcollector); + win->begin_flip(); + } + { + PStatTimer timer(GraphicsEngine::_flip_end_pcollector); + win->end_flip(); + } + } + } } } } @@ -850,12 +871,14 @@ flip_windows(const GraphicsEngine::Windows &wlist) { for (wi = wlist.begin(); wi != wlist.end(); ++wi) { GraphicsOutput *win = (*wi); if (win->flip_ready()) { + PStatTimer timer(GraphicsEngine::_flip_begin_pcollector); win->begin_flip(); } } for (wi = wlist.begin(); wi != wlist.end(); ++wi) { GraphicsOutput *win = (*wi); if (win->flip_ready()) { + PStatTimer timer(GraphicsEngine::_flip_end_pcollector); win->end_flip(); } } diff --git a/panda/src/display/graphicsEngine.h b/panda/src/display/graphicsEngine.h index 1f9f9a7da4..1c324242ce 100644 --- a/panda/src/display/graphicsEngine.h +++ b/panda/src/display/graphicsEngine.h @@ -241,6 +241,8 @@ private: static PStatCollector _draw_pcollector; static PStatCollector _sync_pcollector; static PStatCollector _flip_pcollector; + static PStatCollector _flip_begin_pcollector; + static PStatCollector _flip_end_pcollector; static PStatCollector _transform_states_pcollector; static PStatCollector _transform_states_unused_pcollector; static PStatCollector _render_states_pcollector; diff --git a/panda/src/display/graphicsOutput.cxx b/panda/src/display/graphicsOutput.cxx index f92adef186..3ab9701cfb 100644 --- a/panda/src/display/graphicsOutput.cxx +++ b/panda/src/display/graphicsOutput.cxx @@ -23,11 +23,13 @@ #include "mutexHolder.h" #include "hardwareChannel.h" #include "renderBuffer.h" +#include "pStatTimer.h" TypeHandle GraphicsOutput::_type_handle; #ifndef CPPPARSER PStatCollector GraphicsOutput::_make_current_pcollector("Draw:Make current"); +PStatCollector GraphicsOutput::_copy_texture_pcollector("Draw:Copy texture"); #endif // CPPPARSER //////////////////////////////////////////////////////////////////// @@ -560,6 +562,7 @@ end_frame() { // directly into texture memory don't need to do this; they will set // _copy_texture to false. if (_copy_texture) { + PStatTimer timer(_copy_texture_pcollector); nassertv(has_texture()); DisplayRegion dr(this, _x_size, _y_size); RenderBuffer buffer = _gsg->get_render_buffer(get_draw_buffer_type()); diff --git a/panda/src/display/graphicsOutput.h b/panda/src/display/graphicsOutput.h index c256440bfd..4b9e8fcdf8 100644 --- a/panda/src/display/graphicsOutput.h +++ b/panda/src/display/graphicsOutput.h @@ -179,6 +179,7 @@ protected: bool _is_valid; static PStatCollector _make_current_pcollector; + static PStatCollector _copy_texture_pcollector; public: static TypeHandle get_class_type() { diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index 5d90f3f079..2f7a396fbf 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -60,6 +60,7 @@ PStatCollector GraphicsStateGuardian::_texture_state_pcollector("State changes:T PStatCollector GraphicsStateGuardian::_other_state_pcollector("State changes:Other"); PStatCollector GraphicsStateGuardian::_draw_primitive_pcollector("Draw:Primitive"); PStatCollector GraphicsStateGuardian::_clear_pcollector("Draw:Clear"); +PStatCollector GraphicsStateGuardian::_flush_pcollector("Draw:Flush"); #endif diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index 99a3e2e8b1..65497a1240 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/panda/src/display/graphicsStateGuardian.h @@ -295,6 +295,7 @@ public: static PStatCollector _other_state_pcollector; static PStatCollector _draw_primitive_pcollector; static PStatCollector _clear_pcollector; + static PStatCollector _flush_pcollector; private: class LightInfo { diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 65196842e1..d5dbc117cd 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -627,11 +627,14 @@ void CLP(GraphicsStateGuardian):: end_frame() { GraphicsStateGuardian::end_frame(); - // Calling glFlush() at the end of the frame is particularly - // necessary if this is a single-buffered visual, so that the frame - // will be finished drawing before we return to the application. - // It's not clear what effect this has on our total frame time. - GLP(Flush)(); + { + PStatTimer timer(_flush_pcollector); + // Calling glFlush() at the end of the frame is particularly + // necessary if this is a single-buffered visual, so that the frame + // will be finished drawing before we return to the application. + // It's not clear what effect this has on our total frame time. + GLP(Flush)(); + } report_my_gl_errors(); } diff --git a/panda/src/pstatclient/pStatProperties.cxx b/panda/src/pstatclient/pStatProperties.cxx index 9a71eadceb..00adbda494 100644 --- a/panda/src/pstatclient/pStatProperties.cxx +++ b/panda/src/pstatclient/pStatProperties.cxx @@ -123,9 +123,13 @@ static TimeCollectorProperties time_properties[] = { { 1, "Cull:Bins", { 0.3, 0.6, 0.3 } }, { 1, "Draw", { 1.0, 0.0, 0.0 }, 1.0 / 30.0 }, { 1, "Draw:Make current", { 0.4, 0.2, 0.6 } }, + { 1, "Draw:Copy texture", { 0.2, 0.6, 0.4 } }, { 1, "Draw:Clear", { 0.0, 0.8, 0.6 } }, + { 1, "Draw:Flush", { 0.9, 0.2, 0.7 } }, { 1, "Draw:Sync", { 0.5, 0.7, 0.7 } }, { 1, "Draw:Flip", { 1.0, 0.6, 0.3 } }, + { 1, "Draw:Flip:Begin", { 0.3, 0.3, 0.9 } }, + { 1, "Draw:Flip:End", { 0.9, 0.3, 0.6 } }, { 1, "Draw:Bins", { 0.3, 0.6, 0.0 } }, { 0, "Draw:Primitive", { 0.0, 0.0, 0.5 } }, { 0, NULL } diff --git a/panda/src/wgldisplay/wglGraphicsWindow.cxx b/panda/src/wgldisplay/wglGraphicsWindow.cxx index a599eb4177..4c0cdabcc6 100644 --- a/panda/src/wgldisplay/wglGraphicsWindow.cxx +++ b/panda/src/wgldisplay/wglGraphicsWindow.cxx @@ -224,15 +224,12 @@ release_gsg() { void wglGraphicsWindow:: begin_flip() { if (_hdc) { - // It turns out that if we don't call make_current() before - // calling SwapBuffers() on a Matrix card, we crash a horrible - // death. This is a pity since make_current() seems unnecessary - // on other cards, and does incur some performance overhead. - - // Let's see if this is still necessary now that we guarantee - // begin_flip() is not called until end_frame() has successfully - // rendered. - //make_current(); + // The documentation on SwapBuffers() is not at all clear on + // whether the GL context needs to be current before it can be + // called. Empirically, it appears that it is not necessary in + // many cases, but it definitely is necessary at least in the case + // of Mesa on Windows. + make_current(); SwapBuffers(_hdc); }