StatsUiNode.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. // Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <AnKi/Scene/StatsUiNode.h>
  6. #include <AnKi/Scene/Components/UiComponent.h>
  7. #include <AnKi/Core/StatsSet.h>
  8. #include <AnKi/Core/App.h>
  9. #include <AnKi/Ui/UiManager.h>
  10. #include <AnKi/Ui/Font.h>
  11. #include <AnKi/Renderer/Renderer.h>
  12. namespace anki {
  13. static void labelBytes(PtrSize val, CString name)
  14. {
  15. PtrSize gb, mb, kb, b;
  16. gb = val / 1_GB;
  17. val -= gb * 1_GB;
  18. mb = val / 1_MB;
  19. val -= mb * 1_MB;
  20. kb = val / 1_KB;
  21. val -= kb * 1_KB;
  22. b = val;
  23. UiString timestamp;
  24. if(gb)
  25. {
  26. timestamp.sprintf("%s: %zu,%04zu,%04zu,%04zu", name.cstr(), gb, mb, kb, b);
  27. }
  28. else if(mb)
  29. {
  30. timestamp.sprintf("%s: %zu,%04zu,%04zu", name.cstr(), mb, kb, b);
  31. }
  32. else if(kb)
  33. {
  34. timestamp.sprintf("%s: %zu,%04zu", name.cstr(), kb, b);
  35. }
  36. else
  37. {
  38. timestamp.sprintf("%s: %zu", name.cstr(), b);
  39. }
  40. ImGui::TextUnformatted(timestamp.cstr());
  41. }
  42. class StatsUiNode::Value
  43. {
  44. public:
  45. F64 m_avg = 0.0;
  46. F64 m_rollingAvg = 0.0;
  47. void update(F64 x, Bool flush)
  48. {
  49. m_rollingAvg += x / F64(kBufferedFrames);
  50. if(flush)
  51. {
  52. m_avg = m_rollingAvg;
  53. m_rollingAvg = 0.0;
  54. }
  55. }
  56. };
  57. StatsUiNode::StatsUiNode(CString name)
  58. : SceneNode(name)
  59. {
  60. UiComponent* uic = newComponent<UiComponent>();
  61. uic->init(
  62. [](CanvasPtr& canvas, void* ud) {
  63. static_cast<StatsUiNode*>(ud)->draw(canvas);
  64. },
  65. this);
  66. if(StatsSet::getSingleton().getCounterCount())
  67. {
  68. m_averageValues.resize(StatsSet::getSingleton().getCounterCount());
  69. }
  70. ANKI_CHECKF(UiManager::getSingleton().newInstance(m_font, "EngineAssets/UbuntuMonoRegular.ttf", Array<U32, 1>{24}));
  71. }
  72. StatsUiNode::~StatsUiNode()
  73. {
  74. }
  75. void StatsUiNode::draw(CanvasPtr& canvas)
  76. {
  77. Bool flush = false;
  78. if(m_bufferedFrames == kBufferedFrames)
  79. {
  80. flush = true;
  81. m_bufferedFrames = 0;
  82. }
  83. ++m_bufferedFrames;
  84. canvas->pushFont(m_font, 24);
  85. const Vec4 oldWindowColor = ImGui::GetStyle().Colors[ImGuiCol_WindowBg];
  86. ImGui::GetStyle().Colors[ImGuiCol_WindowBg].w = 0.3f;
  87. if(ImGui::Begin("Stats", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_AlwaysAutoResize))
  88. {
  89. ImGui::SetWindowPos(Vec2(5.0f, 5.0f));
  90. ImGui::SetWindowSize(Vec2(230.0f, 450.0f));
  91. if(!m_fpsOnly)
  92. {
  93. StatCategory category = StatCategory::kCount;
  94. U32 count = 0;
  95. StatsSet::getSingleton().iterateStats(
  96. [&](StatCategory c, const Char* name, U64 value, StatFlag flags) {
  97. if(category != c)
  98. {
  99. category = c;
  100. ImGui::Text("-- %s --", kStatCategoryTexts[c].cstr());
  101. // Hack
  102. if(c == StatCategory::kMisc)
  103. {
  104. ImGui::Text("Frame: %zu", GlobalFrameIndex::getSingleton().m_value);
  105. }
  106. }
  107. if(!!(flags & StatFlag::kBytes))
  108. {
  109. labelBytes(value, name);
  110. }
  111. else
  112. {
  113. ImGui::Text("%s: %zu", name, value);
  114. }
  115. ++count;
  116. },
  117. [&](StatCategory c, const Char* name, F64 value, StatFlag flags) {
  118. if(category != c)
  119. {
  120. category = c;
  121. ImGui::Text("-- %s --", kStatCategoryTexts[c].cstr());
  122. }
  123. if(!!(flags & StatFlag::kShowAverage))
  124. {
  125. m_averageValues[count].update(value, flush);
  126. value = m_averageValues[count].m_avg;
  127. }
  128. ImGui::Text("%s: %f", name, value);
  129. ++count;
  130. });
  131. }
  132. else
  133. {
  134. const Second maxTime = max(g_svarCpuTotalTime.getValue<F64>(), g_svarRendererGpuTime.getValue<F64>()) / 1000.0;
  135. const F32 fps = F32(1.0 / maxTime);
  136. const Bool cpuBound = g_svarCpuTotalTime.getValue<F64>() > g_svarRendererGpuTime.getValue<F64>();
  137. ImGui::TextColored((cpuBound) ? Vec4(1.0f, 0.5f, 0.5f, 1.0f) : Vec4(0.5f, 1.0f, 0.5f, 1.0f), "FPS %.1f", fps);
  138. }
  139. }
  140. ImGui::End();
  141. ImGui::GetStyle().Colors[ImGuiCol_WindowBg] = oldWindowColor;
  142. canvas->popFont();
  143. }
  144. } // end namespace anki