From 6480a62844b7cbf60c5f89b17bf30b1f250e107f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Thu, 2 Nov 2017 22:06:39 -0700 Subject: [PATCH] Added encoder stats. --- examples/common/example-glue.cpp | 40 +++++++++++++++++++- include/bgfx/bgfx.h | 63 +++++++++++++++++++------------- include/bgfx/c99/bgfx.h | 22 ++++++++--- src/bgfx.cpp | 3 +- src/bgfx_p.h | 36 ++++++++++++++---- 5 files changed, 123 insertions(+), 41 deletions(-) diff --git a/examples/common/example-glue.cpp b/examples/common/example-glue.cpp index 8ab7a228e..5a5bde2cb 100644 --- a/examples/common/example-glue.cpp +++ b/examples/common/example-glue.cpp @@ -197,7 +197,45 @@ void showExampleDialog(entry::AppI* _app, const char* _errorText) const float itemHeight = ImGui::GetTextLineHeightWithSpacing(); - if (ImGui::ListBoxHeader("##empty", ImVec2(ImGui::GetWindowWidth(), stats->numViews*itemHeight) ) ) + if (ImGui::ListBoxHeader("Encoders", ImVec2(ImGui::GetWindowWidth(), stats->numEncoders*itemHeight) ) ) + { + ImGuiListClipper clipper(stats->numEncoders, itemHeight); + const double toCpuMs = 1000.0/double(stats->cpuTimerFreq); + const double toGpuMs = 1000.0/double(stats->gpuTimerFreq); + const float scale = 3.0f; + + while (clipper.Step() ) + { + for (int32_t pos = clipper.DisplayStart; pos < clipper.DisplayEnd; ++pos) + { + const bgfx::EncoderStats& encoderStats = stats->encoderStats[pos]; + + ImGui::Text("%3d", pos); + ImGui::SameLine(64.0f); + + ImGui::PushStyleColor(ImGuiCol_Button, cpuColor); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, cpuColor); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, cpuColor); + + const float maxWidth = 30.0f*scale; + const float cpuMs = float( (encoderStats.cpuTimeEnd-encoderStats.cpuTimeBegin)*toCpuMs); + const float cpuWidth = bx::fclamp(cpuMs*scale, 1.0f, maxWidth); + + ImGui::Button("", ImVec2(cpuWidth, itemHeight) ); + if (ImGui::IsItemHovered() ) + { + ImGui::SetTooltip("CPU: %f [ms]", cpuMs); + } + ImGui::PopStyleColor(3); + } + } + + ImGui::ListBoxFooter(); + } + + ImGui::Separator(); + + if (ImGui::ListBoxHeader("Views", ImVec2(ImGui::GetWindowWidth(), stats->numViews*itemHeight) ) ) { ImGuiListClipper clipper(stats->numViews, itemHeight); diff --git a/include/bgfx/bgfx.h b/include/bgfx/bgfx.h index 0c2cc7ce9..d565c3d3b 100644 --- a/include/bgfx/bgfx.h +++ b/include/bgfx/bgfx.h @@ -780,10 +780,20 @@ namespace bgfx /// struct ViewStats { - char name[256]; //!< View name. - uint8_t view; //!< View id. - uint64_t cpuTimeElapsed; //!< CPU (submit) time elapsed. - uint64_t gpuTimeElapsed; //!< GPU time elapsed. + char name[256]; //!< View name. + uint8_t view; //!< View id. + int64_t cpuTimeElapsed; //!< CPU (submit) time elapsed. + int64_t gpuTimeElapsed; //!< GPU time elapsed. + }; + + /// Encoder stats. + /// + /// @attention C99 equivalent is `bgfx_encoder_stats_t`. + /// + struct EncoderStats + { + int64_t cpuTimeBegin; //!< Encoder thread CPU submit begin time. + int64_t cpuTimeEnd; //!< Encoder thread CPU submit end time. }; /// Renderer statistics data. @@ -792,33 +802,36 @@ namespace bgfx /// struct Stats { - int64_t cpuTimeFrame; //!< CPU time between two `bgfx::frame` calls. - int64_t cpuTimeBegin; //!< Render thread CPU submit begin time. - int64_t cpuTimeEnd; //!< Render thread CPU submit end time. - int64_t cpuTimerFreq; //!< CPU timer frequency. + int64_t cpuTimeFrame; //!< CPU time between two `bgfx::frame` calls. + int64_t cpuTimeBegin; //!< Render thread CPU submit begin time. + int64_t cpuTimeEnd; //!< Render thread CPU submit end time. + int64_t cpuTimerFreq; //!< CPU timer frequency. - int64_t gpuTimeBegin; //!< GPU frame begin time. - int64_t gpuTimeEnd; //!< GPU frame end time. - int64_t gpuTimerFreq; //!< GPU timer frequency. + int64_t gpuTimeBegin; //!< GPU frame begin time. + int64_t gpuTimeEnd; //!< GPU frame end time. + int64_t gpuTimerFreq; //!< GPU timer frequency. - int64_t waitRender; //!< Time spent waiting for render backend thread to finish issuing - //! draw commands to underlying graphics API. - int64_t waitSubmit; //!< Time spent waiting for submit thread to advance to next frame. + int64_t waitRender; //!< Time spent waiting for render backend thread to finish issuing + //! draw commands to underlying graphics API. + int64_t waitSubmit; //!< Time spent waiting for submit thread to advance to next frame. - uint32_t numDraw; //!< Number of draw calls submitted. - uint32_t numCompute; //!< Number of compute calls submitted. - uint32_t maxGpuLatency; //!< GPU driver latency. + uint32_t numDraw; //!< Number of draw calls submitted. + uint32_t numCompute; //!< Number of compute calls submitted. + uint32_t maxGpuLatency; //!< GPU driver latency. - int64_t gpuMemoryMax; //!< Maximum available GPU memory for application. - int64_t gpuMemoryUsed; //!< Amount of GPU memory used. + int64_t gpuMemoryMax; //!< Maximum available GPU memory for application. + int64_t gpuMemoryUsed; //!< Amount of GPU memory used. - uint16_t width; //!< Backbuffer width in pixels. - uint16_t height; //!< Backbuffer height in pixels. - uint16_t textWidth; //!< Debug text width in characters. - uint16_t textHeight; //!< Debug text height in characters. + uint16_t width; //!< Backbuffer width in pixels. + uint16_t height; //!< Backbuffer height in pixels. + uint16_t textWidth; //!< Debug text width in characters. + uint16_t textHeight; //!< Debug text height in characters. - uint16_t numViews; //!< Number of view stats. - ViewStats viewStats[256]; //!< View stats. + uint16_t numViews; //!< Number of view stats. + ViewStats* viewStats; //!< View stats. + + uint8_t numEncoders; //!< Number of encoders used during frame. + EncoderStats* encoderStats; //!< Encoder stats. }; /// Encoder for submitting draw calls from multiple threads. Use `bgfx::begin()` diff --git a/include/bgfx/c99/bgfx.h b/include/bgfx/c99/bgfx.h index a376f3e06..081c6c1f2 100644 --- a/include/bgfx/c99/bgfx.h +++ b/include/bgfx/c99/bgfx.h @@ -338,13 +338,20 @@ typedef struct bgfx_hmd /**/ typedef struct bgfx_view_stats { - char name[256]; - uint8_t view; - uint64_t cpuTimeElapsed; - uint64_t gpuTimeElapsed; + char name[256]; + uint8_t view; + int64_t cpuTimeElapsed; + int64_t gpuTimeElapsed; } bgfx_view_stats_t; +typedef struct bgfx_encoder_stats +{ + int64_t cpuTimeBegin; + int64_t cpuTimeEnd; + +} bgfx_encoder_stats_t; + /**/ typedef struct bgfx_stats { @@ -372,8 +379,11 @@ typedef struct bgfx_stats uint16_t textWidth; uint16_t textHeight; - uint16_t numViews; - bgfx_view_stats_t viewStats[256]; + uint16_t numViews; + bgfx_view_stats_t* viewStats; + + uint8_t numEncoders; + bgfx_encoder_stats_t* encoderStats; } bgfx_stats_t; diff --git a/src/bgfx.cpp b/src/bgfx.cpp index 774b9ff4b..94c8b53c5 100644 --- a/src/bgfx.cpp +++ b/src/bgfx.cpp @@ -1721,12 +1721,13 @@ namespace bgfx uint32_t Context::frame(bool _capture) { + m_encoder[0].end(); + bx::MutexScope resourceApiScope(m_resourceApiLock); encoderApiWait(); bx::MutexScope encoderApiScope(m_encoderApiLock); - m_encoder[0].end(); m_submit->m_capture = _capture; BGFX_PROFILER_SCOPE("bgfx/API thread frame", 0xff2040ff); diff --git a/src/bgfx_p.h b/src/bgfx_p.h index 2f67d83c4..dc2e69f3b 100644 --- a/src/bgfx_p.h +++ b/src/bgfx_p.h @@ -1412,7 +1412,7 @@ namespace bgfx VertexDeclHandle m_decl; }; - struct RenderBind + BX_ALIGN_DECL_CACHE_LINE(struct) RenderBind { void clear() { @@ -1428,7 +1428,7 @@ namespace bgfx Binding m_bind[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS]; }; - struct RenderDraw + BX_ALIGN_DECL_CACHE_LINE(struct) RenderDraw { void clear() { @@ -1494,7 +1494,7 @@ namespace bgfx OcclusionQueryHandle m_occlusionQuery; }; - struct RenderCompute + BX_ALIGN_DECL_CACHE_LINE(struct) RenderCompute { void clear() { @@ -1534,7 +1534,7 @@ namespace bgfx RenderCompute compute; }; - struct BlitItem + BX_ALIGN_DECL_CACHE_LINE(struct) BlitItem { uint16_t m_srcX; uint16_t m_srcY; @@ -1707,6 +1707,8 @@ namespace bgfx m_sortKeys[BGFX_CONFIG_MAX_DRAW_CALLS] = term.encodeDraw(SortKey::SortProgram); m_sortValues[BGFX_CONFIG_MAX_DRAW_CALLS] = BGFX_CONFIG_MAX_DRAW_CALLS; bx::memSet(m_occlusion, 0xff, sizeof(m_occlusion) ); + + m_perfStats.viewStats = m_viewStats; } ~Frame() @@ -1959,7 +1961,9 @@ namespace bgfx TextVideoMem* m_textVideoMem; HMD m_hmd; - Stats m_perfStats; + + Stats m_perfStats; + ViewStats m_viewStats[BGFX_CONFIG_MAX_VIEWS]; int64_t m_waitSubmit; int64_t m_waitRender; @@ -1979,6 +1983,8 @@ namespace bgfx { m_frame = _frame; + m_cpuTimeBegin = bx::getHPCounter(); + m_uniformIdx = _idx; m_uniformBegin = 0; m_uniformEnd = 0; @@ -1994,6 +2000,8 @@ namespace bgfx { m_uniformBuffer->finish(); + m_cpuTimeEnd = bx::getHPCounter(); + if (BX_ENABLED(BGFX_CONFIG_DEBUG_OCCLUSION) ) { m_occlusionQuerySet.clear(); @@ -2282,6 +2290,9 @@ namespace bgfx HandleSet m_occlusionQuerySet; UniformBuffer* m_uniformBuffer; + + int64_t m_cpuTimeBegin; + int64_t m_cpuTimeEnd; }; struct VertexDeclRef @@ -2703,6 +2714,7 @@ namespace bgfx const TextVideoMem* tvm = m_submit->m_textVideoMem; stats.textWidth = tvm->m_width; stats.textHeight = tvm->m_height; + stats.encoderStats = m_encoderStats; return &stats; } @@ -4384,11 +4396,18 @@ namespace bgfx BX_NO_INLINE void encoderApiWait() { - for (uint32_t ii = 1, num = m_numEncoders; ii < num; ++ii) + for (uint32_t ii = 0, num = m_numEncoders; ii < num; ++ii) { - m_encoderApiSem.wait(); + if (0 != ii) + { + m_encoderApiSem.wait(); + } + + m_encoderStats[ii].cpuTimeBegin = m_encoder[ii].m_cpuTimeBegin; + m_encoderStats[ii].cpuTimeEnd = m_encoder[ii].m_cpuTimeEnd; } + m_submit->m_perfStats.numEncoders = uint8_t(m_numEncoders); m_numEncoders = 1; } @@ -4422,11 +4441,12 @@ namespace bgfx } #endif // BGFX_CONFIG_MULTITHREADED + EncoderStats m_encoderStats[BGFX_CONFIG_MAX_ENCODERS]; Encoder* m_encoder0; EncoderImpl m_encoder[BGFX_CONFIG_MAX_ENCODERS]; uint32_t m_numEncoders; - Frame m_frame[1+(BGFX_CONFIG_MULTITHREADED ? 1 : 0)]; + Frame m_frame[1+(BGFX_CONFIG_MULTITHREADED ? 1 : 0)]; Frame* m_render; Frame* m_submit;