diff --git a/examples/17-drawstress/drawstress.cpp b/examples/17-drawstress/drawstress.cpp index ff035625e..83503ad42 100644 --- a/examples/17-drawstress/drawstress.cpp +++ b/examples/17-drawstress/drawstress.cpp @@ -242,6 +242,11 @@ class DrawStress : public entry::AppI imguiLabel("Draw calls: %d", m_dim*m_dim*m_dim); imguiLabel("Avg Delta Time (1 second) [ms]: %0.4f", m_deltaTimeAvgNs/1000.0f); + imguiSeparatorLine(); + const bgfx::Stats* stats = bgfx::getStats(); + imguiLabel("GPU %0.6f [ms]", double(stats->gpuTimeEnd - stats->gpuTimeBegin)*1000.0/stats->gpuTimerFreq); + imguiLabel("CPU %0.6f [ms]", double(stats->cpuTimeEnd - stats->cpuTimeBegin)*1000.0/stats->cpuTimerFreq); + imguiEndScrollArea(); imguiEndFrame(); diff --git a/include/bgfx/bgfx.h b/include/bgfx/bgfx.h index 4e7d210b2..8a22c6ea4 100644 --- a/include/bgfx/bgfx.h +++ b/include/bgfx/bgfx.h @@ -589,10 +589,12 @@ namespace bgfx /// struct Stats { - uint64_t cpuTime; //!< CPU frame time. + uint64_t cpuTimeBegin; //!< CPU frame begin time. + uint64_t cpuTimeEnd; //!< CPU frame end time. uint64_t cpuTimerFreq; //!< CPU timer frequency. - uint64_t gpuTime; //!< GPU frame time. + uint64_t gpuTimeBegin; //!< GPU frame begin time. + uint64_t gpuTimeEnd; //!< GPU frame end time. uint64_t gpuTimerFreq; //!< GPU timer frequency. }; diff --git a/src/renderer_d3d11.cpp b/src/renderer_d3d11.cpp index 3f34a9226..fe793d0bc 100644 --- a/src/renderer_d3d11.cpp +++ b/src/renderer_d3d11.cpp @@ -4475,7 +4475,7 @@ BX_PRAGMA_DIAGNOSTIC_POP(); DX_CHECK(device->CreateQuery(&query, &frame.m_disjoint) ); query.Query = D3D11_QUERY_TIMESTAMP; - DX_CHECK(device->CreateQuery(&query, &frame.m_start) ); + DX_CHECK(device->CreateQuery(&query, &frame.m_begin) ); DX_CHECK(device->CreateQuery(&query, &frame.m_end) ); } @@ -4490,7 +4490,7 @@ BX_PRAGMA_DIAGNOSTIC_POP(); { Frame& frame = m_frame[ii]; DX_RELEASE(frame.m_disjoint, 0); - DX_RELEASE(frame.m_start, 0); + DX_RELEASE(frame.m_begin, 0); DX_RELEASE(frame.m_end, 0); } } @@ -4506,7 +4506,7 @@ BX_PRAGMA_DIAGNOSTIC_POP(); Frame& frame = m_frame[m_control.m_current]; deviceCtx->Begin(frame.m_disjoint); - deviceCtx->End(frame.m_start); + deviceCtx->End(frame.m_begin); } void TimerQueryD3D11::end() @@ -4525,8 +4525,8 @@ BX_PRAGMA_DIAGNOSTIC_POP(); ID3D11DeviceContext* deviceCtx = s_renderD3D11->m_deviceCtx; Frame& frame = m_frame[m_control.m_read]; - uint64_t finish; - HRESULT hr = deviceCtx->GetData(frame.m_end, &finish, sizeof(finish), D3D11_ASYNC_GETDATA_DONOTFLUSH); + uint64_t timeEnd; + HRESULT hr = deviceCtx->GetData(frame.m_end, &timeEnd, sizeof(timeEnd), D3D11_ASYNC_GETDATA_DONOTFLUSH); if (S_OK == hr) { m_control.consume(1); @@ -4540,11 +4540,13 @@ BX_PRAGMA_DIAGNOSTIC_POP(); D3D11_QUERY_DATA_TIMESTAMP_DISJOINT disjoint; deviceCtx->GetData(frame.m_disjoint, &disjoint, sizeof(disjoint), 0); - uint64_t start; - deviceCtx->GetData(frame.m_start, &start, sizeof(start), 0); + uint64_t timeBegin; + deviceCtx->GetData(frame.m_begin, &timeBegin, sizeof(timeBegin), 0); m_frequency = disjoint.Frequency; - m_elapsed = finish - start; + m_begin = timeBegin; + m_end = timeEnd; + m_elapsed = timeEnd - timeBegin; return true; } @@ -5505,6 +5507,10 @@ BX_PRAGMA_DIAGNOSTIC_POP(); elapsed += now; static int64_t last = now; + + Stats& perfStats = _render->m_perfStats; + perfStats.cpuTimeBegin = last; + int64_t frameTime = now - last; last = now; @@ -5529,10 +5535,10 @@ BX_PRAGMA_DIAGNOSTIC_POP(); const int64_t timerFreq = bx::getHPFrequency(); - Stats& perfStats = _render->m_perfStats; - perfStats.cpuTime = frameTime; + perfStats.cpuTimeEnd = now; perfStats.cpuTimerFreq = timerFreq; - perfStats.gpuTime = m_gpuTimer.m_elapsed; + perfStats.gpuTimeBegin = m_gpuTimer.m_begin; + perfStats.gpuTimeEnd = m_gpuTimer.m_end; perfStats.gpuTimerFreq = m_gpuTimer.m_frequency; if (_render->m_debug & (BGFX_DEBUG_IFH|BGFX_DEBUG_STATS) ) diff --git a/src/renderer_d3d11.h b/src/renderer_d3d11.h index 4408f1939..dac73c422 100644 --- a/src/renderer_d3d11.h +++ b/src/renderer_d3d11.h @@ -296,10 +296,12 @@ namespace bgfx { namespace d3d11 struct Frame { ID3D11Query* m_disjoint; - ID3D11Query* m_start; + ID3D11Query* m_begin; ID3D11Query* m_end; }; + uint64_t m_begin; + uint64_t m_end; uint64_t m_elapsed; uint64_t m_frequency; diff --git a/src/renderer_d3d9.cpp b/src/renderer_d3d9.cpp index 28a258501..73ec6d93a 100644 --- a/src/renderer_d3d9.cpp +++ b/src/renderer_d3d9.cpp @@ -3318,7 +3318,7 @@ namespace bgfx { namespace d3d9 { Frame& frame = m_frame[ii]; DX_CHECK(device->CreateQuery(D3DQUERYTYPE_TIMESTAMPDISJOINT, &frame.m_disjoint) ); - DX_CHECK(device->CreateQuery(D3DQUERYTYPE_TIMESTAMP, &frame.m_start) ); + DX_CHECK(device->CreateQuery(D3DQUERYTYPE_TIMESTAMP, &frame.m_begin) ); DX_CHECK(device->CreateQuery(D3DQUERYTYPE_TIMESTAMP, &frame.m_end) ); DX_CHECK(device->CreateQuery(D3DQUERYTYPE_TIMESTAMPFREQ, &frame.m_freq) ); } @@ -3334,7 +3334,7 @@ namespace bgfx { namespace d3d9 { Frame& frame = m_frame[ii]; DX_RELEASE(frame.m_disjoint, 0); - DX_RELEASE(frame.m_start, 0); + DX_RELEASE(frame.m_begin, 0); DX_RELEASE(frame.m_end, 0); DX_RELEASE(frame.m_freq, 0); } @@ -3349,7 +3349,7 @@ namespace bgfx { namespace d3d9 Frame& frame = m_frame[m_control.m_current]; frame.m_disjoint->Issue(D3DISSUE_BEGIN); - frame.m_start->Issue(D3DISSUE_END); + frame.m_begin->Issue(D3DISSUE_END); } void TimerQueryD3D9::end() @@ -3373,14 +3373,16 @@ namespace bgfx { namespace d3d9 { m_control.consume(1); - uint64_t timeStart; - DX_CHECK(frame.m_start->GetData(&timeStart, sizeof(timeStart), 0) ); + uint64_t timeBegin; + DX_CHECK(frame.m_begin->GetData(&timeBegin, sizeof(timeBegin), 0) ); uint64_t freq; DX_CHECK(frame.m_freq->GetData(&freq, sizeof(freq), 0) ); m_frequency = freq; - m_elapsed = timeEnd - timeStart; + m_begin = timeBegin; + m_end = timeEnd; + m_elapsed = timeEnd - timeBegin; return true; } @@ -4084,6 +4086,10 @@ namespace bgfx { namespace d3d9 elapsed += now; static int64_t last = now; + + Stats& perfStats = _render->m_perfStats; + perfStats.cpuTimeBegin = last; + int64_t frameTime = now - last; last = now; @@ -4111,10 +4117,10 @@ namespace bgfx { namespace d3d9 const int64_t timerFreq = bx::getHPFrequency(); - Stats& perfStats = _render->m_perfStats; - perfStats.cpuTime = frameTime; + perfStats.cpuTimeEnd = now; perfStats.cpuTimerFreq = timerFreq; - perfStats.gpuTime = m_gpuTimer.m_elapsed; + perfStats.gpuTimeBegin = m_gpuTimer.m_begin; + perfStats.gpuTimeEnd = m_gpuTimer.m_end; perfStats.gpuTimerFreq = m_gpuTimer.m_frequency; if (_render->m_debug & (BGFX_DEBUG_IFH|BGFX_DEBUG_STATS) ) diff --git a/src/renderer_d3d9.h b/src/renderer_d3d9.h index aca8b2608..fa37e43b1 100644 --- a/src/renderer_d3d9.h +++ b/src/renderer_d3d9.h @@ -418,11 +418,13 @@ namespace bgfx { namespace d3d9 struct Frame { IDirect3DQuery9* m_disjoint; - IDirect3DQuery9* m_start; + IDirect3DQuery9* m_begin; IDirect3DQuery9* m_end; IDirect3DQuery9* m_freq; }; + uint64_t m_begin; + uint64_t m_end; uint64_t m_elapsed; uint64_t m_frequency; diff --git a/src/renderer_gl.cpp b/src/renderer_gl.cpp index f91ef102a..a6918d3f4 100644 --- a/src/renderer_gl.cpp +++ b/src/renderer_gl.cpp @@ -6274,6 +6274,10 @@ namespace bgfx { namespace gl elapsed += now; static int64_t last = now; + + Stats& perfStats = _render->m_perfStats; + perfStats.cpuTimeBegin = last; + int64_t frameTime = now - last; last = now; @@ -6301,10 +6305,10 @@ namespace bgfx { namespace gl const int64_t timerFreq = bx::getHPFrequency(); - Stats& perfStats = _render->m_perfStats; - perfStats.cpuTime = frameTime; + perfStats.cpuTimeEnd = now; perfStats.cpuTimerFreq = timerFreq; - perfStats.gpuTime = elapsedGl; + perfStats.gpuTimeBegin = m_gpuTimer.m_begin; + perfStats.gpuTimeEnd = m_gpuTimer.m_end; perfStats.gpuTimerFreq = 1000000000; if (_render->m_debug & (BGFX_DEBUG_IFH|BGFX_DEBUG_STATS) ) diff --git a/src/renderer_gl.h b/src/renderer_gl.h index 3d0c9dee4..7be0df4c7 100644 --- a/src/renderer_gl.h +++ b/src/renderer_gl.h @@ -1205,12 +1205,22 @@ namespace bgfx { namespace gl void create() { - GL_CHECK(glGenQueries(BX_COUNTOF(m_frame), m_frame) ); + for (uint32_t ii = 0; ii < BX_COUNTOF(m_frame); ++ii) + { + Frame& frame = m_frame[ii]; + GL_CHECK(glGenQueries(1, &frame.m_begin) ); + GL_CHECK(glGenQueries(1, &frame.m_elapsed) ); + } } void destroy() { - GL_CHECK(glDeleteQueries(BX_COUNTOF(m_frame), m_frame) ); + for (uint32_t ii = 0; ii < BX_COUNTOF(m_frame); ++ii) + { + Frame& frame = m_frame[ii]; + GL_CHECK(glDeleteQueries(1, &frame.m_begin) ); + GL_CHECK(glDeleteQueries(1, &frame.m_elapsed) ); + } } void begin() @@ -1220,8 +1230,13 @@ namespace bgfx { namespace gl get(); } + Frame& frame = m_frame[m_control.m_current]; + GL_CHECK(glQueryCounter(frame.m_begin + , GL_TIMESTAMP + ) ); + GL_CHECK(glBeginQuery(GL_TIME_ELAPSED - , m_frame[m_control.m_current] + , frame.m_elapsed ) ); } @@ -1235,18 +1250,26 @@ namespace bgfx { namespace gl { if (0 != m_control.available() ) { + Frame& frame = m_frame[m_control.m_read]; + GLint available; - GL_CHECK(glGetQueryObjectiv(m_frame[m_control.m_read] + GL_CHECK(glGetQueryObjectiv(frame.m_elapsed , GL_QUERY_RESULT_AVAILABLE , &available ) ); if (available) { - GL_CHECK(glGetQueryObjectui64v(m_frame[m_control.m_read] + GL_CHECK(glGetQueryObjectui64v(frame.m_begin + , GL_QUERY_RESULT + , &m_begin + ) ); + + GL_CHECK(glGetQueryObjectui64v(frame.m_elapsed , GL_QUERY_RESULT , &m_elapsed ) ); + m_end = m_begin + m_elapsed; m_control.consume(1); return true; } @@ -1255,9 +1278,17 @@ namespace bgfx { namespace gl return false; } + uint64_t m_begin; + uint64_t m_end; uint64_t m_elapsed; - GLuint m_frame[4]; + struct Frame + { + GLuint m_begin; + GLuint m_elapsed; + }; + + Frame m_frame[4]; bx::RingBufferControl m_control; };