BsProfilerOverlay.cpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690
  1. #include "BsProfilerOverlay.h"
  2. #include "BsSceneObject.h"
  3. #include "BsGUIWidget.h"
  4. #include "BsGUIArea.h"
  5. #include "BsGUILayout.h"
  6. #include "BsGUIElement.h"
  7. #include "BsGUILabel.h"
  8. #include "BsGUISpace.h"
  9. #include "BsViewport.h"
  10. #include "BsTime.h"
  11. #include "BsBuiltinResources.h"
  12. #include "BsProfilingManager.h"
  13. #include "BsRenderTarget.h"
  14. namespace BansheeEngine
  15. {
  16. class BasicRowFiller
  17. {
  18. public:
  19. UINT32 curIdx;
  20. GUILayout& labelLayout;
  21. GUILayout& contentLayout;
  22. GUIWidget& widget;
  23. Vector<ProfilerOverlay::BasicRow>& rows;
  24. BasicRowFiller(Vector<ProfilerOverlay::BasicRow>& _rows, GUILayout& _labelLayout, GUILayout& _contentLayout, GUIWidget& _widget)
  25. :rows(_rows), curIdx(0), labelLayout(_labelLayout), contentLayout(_contentLayout), widget(_widget)
  26. { }
  27. ~BasicRowFiller()
  28. {
  29. UINT32 excessEntries = (UINT32)rows.size() - curIdx;
  30. for(UINT32 i = 0; i < excessEntries; i++)
  31. {
  32. labelLayout.removeChildAt(labelLayout.getNumChildren() - 2); // -2 because last element is flexible space and we want to skip it
  33. contentLayout.removeChildAt(contentLayout.getNumChildren() - 2); // -2 because last element is flexible space and we want to skip it
  34. ProfilerOverlay::BasicRow& row = rows[curIdx + i];
  35. for(auto& element : row.elements)
  36. GUIElement::destroy(element);
  37. }
  38. rows.resize(curIdx);
  39. }
  40. void addData(UINT32 depth, const String& name, float pctOfParent, UINT32 numCalls, UINT64 numAllocs,
  41. UINT64 numFrees, double avgTime, double totalTime, double avgSelfTime, double totalSelfTime)
  42. {
  43. if(curIdx >= rows.size())
  44. {
  45. rows.push_back(ProfilerOverlay::BasicRow());
  46. ProfilerOverlay::BasicRow& newRow = rows.back();
  47. newRow.name = HString(L"{0}");
  48. newRow.pctOfParent = HString(L"{0} %");
  49. newRow.numCalls = HString(L"{0}");
  50. newRow.numAllocs = HString(L"{0}");
  51. newRow.numFrees = HString(L"{0}");
  52. newRow.avgTime = HString(L"{0}");
  53. newRow.totalTime = HString(L"{0}");
  54. newRow.avgTimeSelf = HString(L"{0}");
  55. newRow.totalTimeSelf = HString(L"{0}");
  56. newRow.labelLayout = &labelLayout.insertLayoutX(labelLayout.getNumChildren() - 1); // Insert before flexible space
  57. newRow.contentLayout = &contentLayout.insertLayoutX(contentLayout.getNumChildren() - 1); // Insert before flexible space
  58. GUILabel* name = GUILabel::create(newRow.name, GUIOptions(GUIOption::fixedWidth(200)));
  59. GUILabel* pctOfParent = GUILabel::create(newRow.pctOfParent, GUIOptions(GUIOption::fixedWidth(50)));
  60. GUILabel* numCalls = GUILabel::create(newRow.numCalls, GUIOptions(GUIOption::fixedWidth(50)));
  61. GUILabel* numAllocs = GUILabel::create(newRow.numAllocs, GUIOptions(GUIOption::fixedWidth(50)));
  62. GUILabel* numFrees = GUILabel::create(newRow.numFrees, GUIOptions(GUIOption::fixedWidth(50)));
  63. GUILabel* avgTime = GUILabel::create(newRow.avgTime, GUIOptions(GUIOption::fixedWidth(60)));
  64. GUILabel* totalTime = GUILabel::create(newRow.totalTime, GUIOptions(GUIOption::fixedWidth(60)));
  65. GUILabel* avgTimeSelf = GUILabel::create(newRow.avgTimeSelf, GUIOptions(GUIOption::fixedWidth(100)));
  66. GUILabel* totalTimeSelf = GUILabel::create(newRow.totalTimeSelf, GUIOptions(GUIOption::fixedWidth(100)));
  67. newRow.labelLayout->addSpace(0);
  68. newRow.labelLayout->addElement(name);
  69. newRow.contentLayout->addElement(pctOfParent);
  70. newRow.contentLayout->addElement(numCalls);
  71. newRow.contentLayout->addElement(numAllocs);
  72. newRow.contentLayout->addElement(numFrees);
  73. newRow.contentLayout->addElement(avgTime);
  74. newRow.contentLayout->addElement(totalTime);
  75. newRow.contentLayout->addElement(avgTimeSelf);
  76. newRow.contentLayout->addElement(totalTimeSelf);
  77. newRow.elements.push_back(name);
  78. newRow.elements.push_back(pctOfParent);
  79. newRow.elements.push_back(numCalls);
  80. newRow.elements.push_back(numAllocs);
  81. newRow.elements.push_back(numFrees);
  82. newRow.elements.push_back(avgTime);
  83. newRow.elements.push_back(totalTime);
  84. newRow.elements.push_back(avgTimeSelf);
  85. newRow.elements.push_back(totalTimeSelf);
  86. }
  87. ProfilerOverlay::BasicRow& row = rows[curIdx];
  88. row.labelLayout->removeChildAt(0);
  89. row.labelLayout->insertSpace(0, depth * 20);
  90. row.name.setParameter(0, toWString(name));
  91. row.pctOfParent.setParameter(0, toWString(pctOfParent * 100.0f, 2, 0, ' ', std::ios::fixed));
  92. row.numCalls.setParameter(0, toWString(numCalls));
  93. row.numAllocs.setParameter(0, toWString(numAllocs));
  94. row.numFrees.setParameter(0, toWString(numFrees));
  95. row.avgTime.setParameter(0, toWString(avgTime, 2, 0, ' ', std::ios::fixed));
  96. row.totalTime.setParameter(0, toWString(totalTime, 2, 0, ' ', std::ios::fixed));
  97. row.avgTimeSelf.setParameter(0, toWString(avgSelfTime, 2, 0, ' ', std::ios::fixed));
  98. row.totalTimeSelf.setParameter(0, toWString(totalSelfTime, 2, 0, ' ', std::ios::fixed));
  99. curIdx++;
  100. }
  101. };
  102. class PreciseRowFiller
  103. {
  104. public:
  105. UINT32 curIdx;
  106. GUILayout& labelLayout;
  107. GUILayout& contentLayout;
  108. GUIWidget& widget;
  109. Vector<ProfilerOverlay::PreciseRow>& rows;
  110. PreciseRowFiller(Vector<ProfilerOverlay::PreciseRow>& _rows, GUILayout& _labelLayout, GUILayout& _contentLayout, GUIWidget& _widget)
  111. :rows(_rows), curIdx(0), labelLayout(_labelLayout), contentLayout(_contentLayout), widget(_widget)
  112. { }
  113. ~PreciseRowFiller()
  114. {
  115. UINT32 excessEntries = (UINT32)rows.size() - curIdx;
  116. for(UINT32 i = 0; i < excessEntries; i++)
  117. {
  118. labelLayout.removeChildAt(labelLayout.getNumChildren() - i - 1); // -1 because last element is flexible space and we want to skip it
  119. contentLayout.removeChildAt(contentLayout.getNumChildren() - i - 1); // -1 because last element is flexible space and we want to skip it
  120. ProfilerOverlay::PreciseRow& row = rows[curIdx + i];
  121. for(auto& element : row.elements)
  122. GUIElement::destroy(element);
  123. }
  124. rows.resize(curIdx);
  125. }
  126. void addData(UINT32 depth, const String& name, float pctOfParent, UINT32 numCalls, UINT64 numAllocs,
  127. UINT64 numFrees, UINT64 avgCycles, UINT64 totalCycles, UINT64 avgSelfCycles, UINT64 totalSelfCycles)
  128. {
  129. if(curIdx >= rows.size())
  130. {
  131. rows.push_back(ProfilerOverlay::PreciseRow());
  132. ProfilerOverlay::PreciseRow& newRow = rows.back();
  133. newRow.name = HString(L"{0}");
  134. newRow.pctOfParent = HString(L"{0}");
  135. newRow.numCalls = HString(L"{0}");
  136. newRow.numAllocs = HString(L"{0}");
  137. newRow.numFrees = HString(L"{0}");
  138. newRow.avgCycles = HString(L"{0}");
  139. newRow.totalCycles = HString(L"{0}");
  140. newRow.avgCyclesSelf = HString(L"{0}");
  141. newRow.totalCyclesSelf = HString(L"{0}");
  142. newRow.labelLayout = &labelLayout.insertLayoutX(labelLayout.getNumChildren() - 1); // Insert before flexible space
  143. newRow.contentLayout = &contentLayout.insertLayoutX(contentLayout.getNumChildren() - 1); // Insert before flexible space
  144. GUILabel* name = GUILabel::create(newRow.name, GUIOptions(GUIOption::fixedWidth(200)));
  145. GUILabel* pctOfParent = GUILabel::create(newRow.pctOfParent, GUIOptions(GUIOption::fixedWidth(50)));
  146. GUILabel* numCalls = GUILabel::create(newRow.numCalls, GUIOptions(GUIOption::fixedWidth(50)));
  147. GUILabel* numAllocs = GUILabel::create(newRow.numAllocs, GUIOptions(GUIOption::fixedWidth(50)));
  148. GUILabel* numFrees = GUILabel::create(newRow.numFrees, GUIOptions(GUIOption::fixedWidth(50)));
  149. GUILabel* avgCycles = GUILabel::create(newRow.avgCycles,GUIOptions(GUIOption::fixedWidth(60)));
  150. GUILabel* totalCycles = GUILabel::create(newRow.totalCycles, GUIOptions(GUIOption::fixedWidth(60)));
  151. GUILabel* avgCyclesSelf = GUILabel::create(newRow.avgCyclesSelf, GUIOptions(GUIOption::fixedWidth(100)));
  152. GUILabel* totalCyclesSelf = GUILabel::create(newRow.totalCyclesSelf, GUIOptions(GUIOption::fixedWidth(100)));
  153. newRow.labelLayout->addSpace(0);
  154. newRow.labelLayout->addElement(name);
  155. newRow.contentLayout->addElement(pctOfParent);
  156. newRow.contentLayout->addElement(numCalls);
  157. newRow.contentLayout->addElement(numAllocs);
  158. newRow.contentLayout->addElement(numFrees);
  159. newRow.contentLayout->addElement(avgCycles);
  160. newRow.contentLayout->addElement(totalCycles);
  161. newRow.contentLayout->addElement(avgCyclesSelf);
  162. newRow.contentLayout->addElement(totalCyclesSelf);
  163. newRow.elements.push_back(name);
  164. newRow.elements.push_back(pctOfParent);
  165. newRow.elements.push_back(numCalls);
  166. newRow.elements.push_back(numAllocs);
  167. newRow.elements.push_back(numFrees);
  168. newRow.elements.push_back(avgCycles);
  169. newRow.elements.push_back(totalCycles);
  170. newRow.elements.push_back(avgCyclesSelf);
  171. newRow.elements.push_back(totalCyclesSelf);
  172. }
  173. ProfilerOverlay::PreciseRow& row = rows[curIdx];
  174. row.labelLayout->removeChildAt(0);
  175. row.labelLayout->insertSpace(0, depth * 20);
  176. row.name.setParameter(0, toWString(name));
  177. row.pctOfParent.setParameter(0, toWString(pctOfParent * 100.0f, 2, 0, ' ', std::ios::fixed));
  178. row.numCalls.setParameter(0, toWString(numCalls));
  179. row.numAllocs.setParameter(0, toWString(numAllocs));
  180. row.numFrees.setParameter(0, toWString(numFrees));
  181. row.avgCycles.setParameter(0, toWString(avgCycles));
  182. row.totalCycles.setParameter(0, toWString(totalCycles));
  183. row.avgCyclesSelf.setParameter(0, toWString(avgSelfCycles));
  184. row.totalCyclesSelf.setParameter(0, toWString(totalSelfCycles));
  185. curIdx++;
  186. }
  187. };
  188. class GPUSampleRowFiller
  189. {
  190. public:
  191. UINT32 curIdx;
  192. GUILayout& layout;
  193. GUIWidget& widget;
  194. Vector<ProfilerOverlay::GPUSampleRow>& rows;
  195. GPUSampleRowFiller(Vector<ProfilerOverlay::GPUSampleRow>& _rows, GUILayout& _layout, GUIWidget& _widget)
  196. :rows(_rows), curIdx(0), layout(_layout), widget(_widget)
  197. { }
  198. ~GPUSampleRowFiller()
  199. {
  200. UINT32 excessEntries = (UINT32)rows.size() - curIdx;
  201. for (UINT32 i = 0; i < excessEntries; i++)
  202. {
  203. layout.removeChildAt(layout.getNumChildren() - i);
  204. ProfilerOverlay::GPUSampleRow& row = rows[curIdx + i];
  205. for (auto& element : row.elements)
  206. GUIElement::destroy(element);
  207. }
  208. rows.resize(curIdx);
  209. }
  210. void addData(const String& name, float timeMs)
  211. {
  212. if (curIdx >= rows.size())
  213. {
  214. rows.push_back(ProfilerOverlay::GPUSampleRow());
  215. ProfilerOverlay::GPUSampleRow& newRow = rows.back();
  216. newRow.name = HString(L"{1}");
  217. newRow.time = HString(L"{0}");
  218. newRow.layout = &layout.insertLayoutX(layout.getNumChildren());
  219. GUILabel* nameLabel = GUILabel::create(newRow.name, GUIOptions(GUIOption::fixedWidth(100)));
  220. GUILabel* timeLabel = GUILabel::create(newRow.time, GUIOptions(GUIOption::fixedWidth(100)));
  221. newRow.layout->addElement(nameLabel);
  222. newRow.layout->addElement(timeLabel);
  223. newRow.elements.push_back(nameLabel);
  224. newRow.elements.push_back(timeLabel);
  225. }
  226. ProfilerOverlay::GPUSampleRow& row = rows[curIdx];
  227. row.name.setParameter(0, toWString(name));
  228. row.time.setParameter(0, toWString(timeMs));
  229. curIdx++;
  230. }
  231. };
  232. const UINT32 ProfilerOverlay::MAX_DEPTH = 4;
  233. ProfilerOverlay::ProfilerOverlay(const HSceneObject& parent, const ViewportPtr& target)
  234. :Component(parent), mIsShown(false), mType(ProfilerOverlayType::CPUSamples)
  235. {
  236. setTarget(target);
  237. }
  238. ProfilerOverlay::~ProfilerOverlay()
  239. {
  240. if(mTarget != nullptr)
  241. mTargetResizedConn.disconnect();
  242. if(mWidgetSO)
  243. mWidgetSO->destroy();
  244. }
  245. void ProfilerOverlay::setTarget(const ViewportPtr& target)
  246. {
  247. if(mTarget != nullptr)
  248. mTargetResizedConn.disconnect();
  249. mTarget = target;
  250. mTargetResizedConn = target->getTarget()->onResized.connect(std::bind(&ProfilerOverlay::targetResized, this));
  251. if(mWidgetSO)
  252. mWidgetSO->destroy();
  253. mWidgetSO = SceneObject::create("ProfilerOverlay");
  254. mWidget = mWidgetSO->addComponent<GUIWidget>(mTarget.get());
  255. mWidget->setDepth(127);
  256. mWidget->setSkin(BuiltinResources::instance().getGUISkin());
  257. // Set up CPU sample areas
  258. mCPUBasicAreaLabels = GUIArea::create(*mWidget, 0, 0);
  259. mCPUPreciseAreaLabels = GUIArea::create(*mWidget, 0, 0);
  260. mCPUBasicAreaContents = GUIArea::create(*mWidget, 0, 0);
  261. mCPUPreciseAreaContents = GUIArea::create(*mWidget, 0, 0);
  262. mBasicLayoutLabels = &mCPUBasicAreaLabels->getLayout().addLayoutY();
  263. mPreciseLayoutLabels = &mCPUPreciseAreaLabels->getLayout().addLayoutY();
  264. mBasicLayoutContents = &mCPUBasicAreaContents->getLayout().addLayoutY();
  265. mPreciseLayoutContents = &mCPUPreciseAreaContents->getLayout().addLayoutY();
  266. // Set up CPU sample title bars
  267. mTitleBasicName = GUILabel::create(HString(L"Name"), GUIOptions(GUIOption::fixedWidth(200)));
  268. mTitleBasicPctOfParent = GUILabel::create(HString(L"% parent"), GUIOptions(GUIOption::fixedWidth(50)));
  269. mTitleBasicNumCalls = GUILabel::create(HString(L"# calls"), GUIOptions(GUIOption::fixedWidth(50)));
  270. mTitleBasicNumAllocs = GUILabel::create(HString(L"# allocs"), GUIOptions(GUIOption::fixedWidth(50)));
  271. mTitleBasicNumFrees = GUILabel::create(HString(L"# frees"), GUIOptions(GUIOption::fixedWidth(50)));
  272. mTitleBasicAvgTime = GUILabel::create(HString(L"Avg. time"), GUIOptions(GUIOption::fixedWidth(60)));
  273. mTitleBasicTotalTime = GUILabel::create(HString(L"Total time"), GUIOptions(GUIOption::fixedWidth(60)));
  274. mTitleBasicAvgTitleSelf = GUILabel::create(HString(L"Avg. self time"), GUIOptions(GUIOption::fixedWidth(100)));
  275. mTitleBasicTotalTimeSelf = GUILabel::create(HString(L"Total self time"), GUIOptions(GUIOption::fixedWidth(100)));
  276. mTitlePreciseName = GUILabel::create(HString(L"Name"), GUIOptions(GUIOption::fixedWidth(200)));
  277. mTitlePrecisePctOfParent = GUILabel::create(HString(L"% parent"), GUIOptions(GUIOption::fixedWidth(50)));
  278. mTitlePreciseNumCalls = GUILabel::create(HString(L"# calls"), GUIOptions(GUIOption::fixedWidth(50)));
  279. mTitlePreciseNumAllocs = GUILabel::create(HString(L"# allocs"), GUIOptions(GUIOption::fixedWidth(50)));
  280. mTitlePreciseNumFrees = GUILabel::create(HString(L"# frees"), GUIOptions(GUIOption::fixedWidth(50)));
  281. mTitlePreciseAvgCycles = GUILabel::create(HString(L"Avg. cycles"), GUIOptions(GUIOption::fixedWidth(60)));
  282. mTitlePreciseTotalCycles = GUILabel::create(HString(L"Total cycles"), GUIOptions(GUIOption::fixedWidth(60)));
  283. mTitlePreciseAvgCyclesSelf = GUILabel::create(HString(L"Avg. self cycles"), GUIOptions(GUIOption::fixedWidth(100)));
  284. mTitlePreciseTotalCyclesSelf = GUILabel::create(HString(L"Total self cycles"), GUIOptions(GUIOption::fixedWidth(100)));
  285. GUILayout& basicTitleLabelLayout = mBasicLayoutLabels->addLayoutX();
  286. GUILayout& preciseTitleLabelLayout = mPreciseLayoutLabels->addLayoutX();
  287. GUILayout& basicTitleContentLayout = mBasicLayoutContents->addLayoutX();
  288. GUILayout& preciseTitleContentLayout = mPreciseLayoutContents->addLayoutX();
  289. basicTitleLabelLayout.addElement(mTitleBasicName);
  290. basicTitleContentLayout.addElement(mTitleBasicPctOfParent);
  291. basicTitleContentLayout.addElement(mTitleBasicNumCalls);
  292. basicTitleContentLayout.addElement(mTitleBasicNumAllocs);
  293. basicTitleContentLayout.addElement(mTitleBasicNumFrees);
  294. basicTitleContentLayout.addElement(mTitleBasicAvgTime);
  295. basicTitleContentLayout.addElement(mTitleBasicTotalTime);
  296. basicTitleContentLayout.addElement(mTitleBasicAvgTitleSelf);
  297. basicTitleContentLayout.addElement(mTitleBasicTotalTimeSelf);
  298. preciseTitleLabelLayout.addElement(mTitlePreciseName);
  299. preciseTitleContentLayout.addElement(mTitlePrecisePctOfParent);
  300. preciseTitleContentLayout.addElement(mTitlePreciseNumCalls);
  301. preciseTitleContentLayout.addElement(mTitlePreciseNumAllocs);
  302. preciseTitleContentLayout.addElement(mTitlePreciseNumFrees);
  303. preciseTitleContentLayout.addElement(mTitlePreciseAvgCycles);
  304. preciseTitleContentLayout.addElement(mTitlePreciseTotalCycles);
  305. preciseTitleContentLayout.addElement(mTitlePreciseAvgCyclesSelf);
  306. preciseTitleContentLayout.addElement(mTitlePreciseTotalCyclesSelf);
  307. mBasicLayoutLabels->addFlexibleSpace();
  308. mPreciseLayoutLabels->addFlexibleSpace();
  309. mBasicLayoutContents->addFlexibleSpace();
  310. mPreciseLayoutContents->addFlexibleSpace();
  311. // Set up GPU sample areas
  312. mGPUAreaFrameContents = GUIArea::create(*mWidget, 0, 0);
  313. mGPUAreaFrameSamples = GUIArea::create(*mWidget, 0, 0);
  314. mGPULayoutFrameContentsLeft = &mGPUAreaFrameContents->getLayout().addLayoutY();
  315. mGPULayoutFrameContentsRight = &mGPUAreaFrameContents->getLayout().addLayoutY();
  316. GUILayout& gpuSamplesMain = mGPUAreaFrameSamples->getLayout().addLayoutY();
  317. GUILayout& gpuSampleTitle = gpuSamplesMain.addLayoutY();
  318. mGPULayoutSamples = &gpuSamplesMain.addLayoutY();
  319. gpuSamplesMain.addFlexibleSpace();
  320. HString gpuSamplesStr(L"__ProfOvGPUSamples", L"Samples");
  321. gpuSampleTitle.addElement(GUILabel::create(gpuSamplesStr));
  322. gpuSampleTitle.addSpace(20);
  323. GUILayout& gpuSampleTitleRow = gpuSampleTitle.addLayoutX();
  324. HString gpuSamplesNameStr(L"__ProfOvGPUSampName", L"Name");
  325. HString gpuSamplesTimeStr(L"__ProfOvGPUSampTime", L"Time");
  326. gpuSampleTitleRow.addElement(GUILabel::create(gpuSamplesNameStr, GUIOptions(GUIOption::fixedWidth(100))));
  327. gpuSampleTitleRow.addElement(GUILabel::create(gpuSamplesTimeStr, GUIOptions(GUIOption::fixedWidth(100))));
  328. mGPUFrameNumStr = HString(L"__ProfOvFrame", L"Frame #{0}");
  329. mGPUTimeStr = HString(L"__ProfOvTime", L"Time: {0}ms");
  330. mGPUDrawCallsStr = HString(L"__ProfOvDrawCalls", L"Draw calls: {0}");
  331. mGPURenTargetChangesStr = HString(L"__ProfOvRTChanges", L"Render target changes: {0}");
  332. mGPUPresentsStr = HString(L"__ProfOvPresents", L"Presents: {0}");
  333. mGPUClearsStr = HString(L"__ProfOvClears", L"Clears: {0}");
  334. mGPUVerticesStr = HString(L"__ProfOvVertices", L"Num. vertices: {0}");
  335. mGPUPrimitivesStr = HString(L"__ProfOvPrimitives", L"Num. primitives: {0}");
  336. mGPUSamplesStr = HString(L"__ProfOvSamples", L"Samples drawn: {0}");
  337. mGPUBlendStateChangesStr = HString(L"__ProfOvBSChanges", L"Blend state changes: {0}");
  338. mGPURasterStateChangesStr = HString(L"__ProfOvRSChanges", L"Rasterizer state changes: {0}");
  339. mGPUDepthStencilStateChangesStr = HString(L"__ProfOvDSSChanges", L"Depth/stencil state changes: {0}");
  340. mGPUObjectsCreatedStr = HString(L"__ProfOvObjsCreated", L"Objects created: {0}");
  341. mGPUObjectsDestroyedStr = HString(L"__ProfOvObjsDestroyed", L"Objects destroyed: {0}");
  342. mGPUResourceWritesStr = HString(L"__ProfOvResWrites", L"Resource writes: {0}");
  343. mGPUResourceReadsStr = HString(L"__ProfOvResReads", L"Resource reads: {0}");
  344. mGPUTextureBindsStr = HString(L"__ProfOvTexBinds", L"Texture binds: {0}");
  345. mGPUSamplerBindsStr = HString(L"__ProfOvSampBinds", L"Sampler binds: {0}");
  346. mGPUVertexBufferBindsStr = HString(L"__ProfOvVBBinds", L"VB binds: {0}");
  347. mGPUIndexBufferBindsStr = HString(L"__ProfOvIBBinds", L"IB binds: {0}");
  348. mGPUGPUProgramBufferBindsStr = HString(L"__ProfOvProgBuffBinds", L"GPU program buffer binds: {0}");
  349. mGPUGPUProgramBindsStr = HString(L"__ProfOvProgBinds", L"GPU program binds: {0}");
  350. mGPULayoutFrameContentsLeft->addElement(GUILabel::create(mGPUFrameNumStr, GUIOptions(GUIOption::fixedWidth(200))));
  351. mGPULayoutFrameContentsLeft->addElement(GUILabel::create(mGPUTimeStr, GUIOptions(GUIOption::fixedWidth(200))));
  352. mGPULayoutFrameContentsLeft->addElement(GUILabel::create(mGPUDrawCallsStr, GUIOptions(GUIOption::fixedWidth(200))));
  353. mGPULayoutFrameContentsLeft->addElement(GUILabel::create(mGPURenTargetChangesStr, GUIOptions(GUIOption::fixedWidth(200))));
  354. mGPULayoutFrameContentsLeft->addElement(GUILabel::create(mGPUPresentsStr, GUIOptions(GUIOption::fixedWidth(200))));
  355. mGPULayoutFrameContentsLeft->addElement(GUILabel::create(mGPUClearsStr, GUIOptions(GUIOption::fixedWidth(200))));
  356. mGPULayoutFrameContentsLeft->addElement(GUILabel::create(mGPUVerticesStr, GUIOptions(GUIOption::fixedWidth(200))));
  357. mGPULayoutFrameContentsLeft->addElement(GUILabel::create(mGPUPrimitivesStr, GUIOptions(GUIOption::fixedWidth(200))));
  358. mGPULayoutFrameContentsLeft->addElement(GUILabel::create(mGPUSamplesStr, GUIOptions(GUIOption::fixedWidth(200))));
  359. mGPULayoutFrameContentsLeft->addElement(GUILabel::create(mGPUBlendStateChangesStr, GUIOptions(GUIOption::fixedWidth(200))));
  360. mGPULayoutFrameContentsLeft->addElement(GUILabel::create(mGPURasterStateChangesStr, GUIOptions(GUIOption::fixedWidth(200))));
  361. mGPULayoutFrameContentsLeft->addElement(GUILabel::create(mGPUDepthStencilStateChangesStr, GUIOptions(GUIOption::fixedWidth(200))));
  362. mGPULayoutFrameContentsLeft->addFlexibleSpace();
  363. mGPULayoutFrameContentsRight->addElement(GUILabel::create(mGPUObjectsCreatedStr, GUIOptions(GUIOption::fixedWidth(200))));
  364. mGPULayoutFrameContentsRight->addElement(GUILabel::create(mGPUObjectsDestroyedStr, GUIOptions(GUIOption::fixedWidth(200))));
  365. mGPULayoutFrameContentsRight->addElement(GUILabel::create(mGPUResourceWritesStr, GUIOptions(GUIOption::fixedWidth(200))));
  366. mGPULayoutFrameContentsRight->addElement(GUILabel::create(mGPUResourceReadsStr, GUIOptions(GUIOption::fixedWidth(200))));
  367. mGPULayoutFrameContentsRight->addElement(GUILabel::create(mGPUTextureBindsStr, GUIOptions(GUIOption::fixedWidth(200))));
  368. mGPULayoutFrameContentsRight->addElement(GUILabel::create(mGPUSamplerBindsStr, GUIOptions(GUIOption::fixedWidth(200))));
  369. mGPULayoutFrameContentsRight->addElement(GUILabel::create(mGPUVertexBufferBindsStr, GUIOptions(GUIOption::fixedWidth(200))));
  370. mGPULayoutFrameContentsRight->addElement(GUILabel::create(mGPUIndexBufferBindsStr, GUIOptions(GUIOption::fixedWidth(200))));
  371. mGPULayoutFrameContentsRight->addElement(GUILabel::create(mGPUGPUProgramBufferBindsStr, GUIOptions(GUIOption::fixedWidth(200))));
  372. mGPULayoutFrameContentsRight->addElement(GUILabel::create(mGPUGPUProgramBindsStr, GUIOptions(GUIOption::fixedWidth(200))));
  373. mGPULayoutFrameContentsRight->addFlexibleSpace();
  374. updateCPUSampleAreaSizes();
  375. updateGPUSampleAreaSizes();
  376. if (!mIsShown)
  377. hide();
  378. else
  379. {
  380. if (mType == ProfilerOverlayType::CPUSamples)
  381. show(ProfilerOverlayType::CPUSamples);
  382. else
  383. show(ProfilerOverlayType::GPUSamples);
  384. }
  385. }
  386. void ProfilerOverlay::show(ProfilerOverlayType type)
  387. {
  388. if (type == ProfilerOverlayType::CPUSamples)
  389. {
  390. mCPUBasicAreaLabels->enable();
  391. mCPUPreciseAreaLabels->enable();
  392. mCPUBasicAreaContents->enable();
  393. mCPUPreciseAreaContents->enable();
  394. mGPUAreaFrameContents->disable();
  395. mGPUAreaFrameSamples->disable();
  396. }
  397. else
  398. {
  399. mGPUAreaFrameContents->enable();
  400. mGPUAreaFrameSamples->enable();
  401. mCPUBasicAreaLabels->disable();
  402. mCPUPreciseAreaLabels->disable();
  403. mCPUBasicAreaContents->disable();
  404. mCPUPreciseAreaContents->disable();
  405. }
  406. mType = type;
  407. mIsShown = true;
  408. }
  409. void ProfilerOverlay::hide()
  410. {
  411. mCPUBasicAreaLabels->disable();
  412. mCPUPreciseAreaLabels->disable();
  413. mCPUBasicAreaContents->disable();
  414. mCPUPreciseAreaContents->disable();
  415. mGPUAreaFrameContents->disable();
  416. mGPUAreaFrameSamples->disable();
  417. mIsShown = false;
  418. }
  419. void ProfilerOverlay::update()
  420. {
  421. const ProfilerReport& latestSimReport = ProfilingManager::instance().getReport(ProfiledThread::Sim);
  422. const ProfilerReport& latestCoreReport = ProfilingManager::instance().getReport(ProfiledThread::Core);
  423. updateCPUSampleContents(latestSimReport, latestCoreReport);
  424. while (ProfilerGPU::instance().getNumAvailableReports() > 1)
  425. ProfilerGPU::instance().getNextReport(); // Drop any extra reports, we only want the latest
  426. if (ProfilerGPU::instance().getNumAvailableReports() > 0)
  427. {
  428. updateGPUSampleContents(ProfilerGPU::instance().getNextReport());
  429. }
  430. }
  431. void ProfilerOverlay::targetResized()
  432. {
  433. updateCPUSampleAreaSizes();
  434. updateGPUSampleAreaSizes();
  435. }
  436. void ProfilerOverlay::updateCPUSampleAreaSizes()
  437. {
  438. static const INT32 PADDING = 10;
  439. static const float LABELS_CONTENT_RATIO = 0.3f;
  440. UINT32 width = (UINT32)std::max(0, (INT32)mTarget->getWidth() - PADDING * 2);
  441. UINT32 height = (UINT32)std::max(0, (INT32)(mTarget->getHeight() - PADDING * 3)/2);
  442. UINT32 labelsWidth = Math::ceilToInt(width * LABELS_CONTENT_RATIO);
  443. UINT32 contentWidth = width - labelsWidth;
  444. mCPUBasicAreaLabels->setPosition(PADDING, PADDING);
  445. mCPUBasicAreaLabels->setSize(labelsWidth, height);
  446. mCPUPreciseAreaLabels->setPosition(PADDING, height + PADDING * 2);
  447. mCPUPreciseAreaLabels->setSize(labelsWidth, height);
  448. mCPUBasicAreaContents->setPosition(PADDING + labelsWidth, PADDING);
  449. mCPUBasicAreaContents->setSize(contentWidth, height);
  450. mCPUPreciseAreaContents->setPosition(PADDING + labelsWidth, height + PADDING * 2);
  451. mCPUPreciseAreaContents->setSize(contentWidth, height);
  452. }
  453. void ProfilerOverlay::updateGPUSampleAreaSizes()
  454. {
  455. static const INT32 PADDING = 10;
  456. static const float SAMPLES_FRAME_RATIO = 0.5f;
  457. UINT32 width = (UINT32)std::max(0, (INT32)mTarget->getWidth() - PADDING * 2);
  458. UINT32 height = (UINT32)std::max(0, (INT32)(mTarget->getHeight() - PADDING * 3));
  459. UINT32 frameHeight = Math::ceilToInt(height * SAMPLES_FRAME_RATIO);
  460. UINT32 samplesHeight = height - frameHeight;
  461. mGPUAreaFrameContents->setPosition(PADDING, PADDING);
  462. mGPUAreaFrameContents->setSize(width, frameHeight);
  463. mGPUAreaFrameSamples->setPosition(PADDING, PADDING + frameHeight + PADDING);
  464. mGPUAreaFrameSamples->setSize(width, samplesHeight);
  465. }
  466. void ProfilerOverlay::updateCPUSampleContents(const ProfilerReport& simReport, const ProfilerReport& coreReport)
  467. {
  468. static const UINT32 NUM_ROOT_ENTRIES = 2;
  469. const CPUProfilerBasicSamplingEntry& simBasicRootEntry = simReport.cpuReport.getBasicSamplingData();
  470. const CPUProfilerPreciseSamplingEntry& simPreciseRootEntry = simReport.cpuReport.getPreciseSamplingData();
  471. const CPUProfilerBasicSamplingEntry& coreBasicRootEntry = coreReport.cpuReport.getBasicSamplingData();
  472. const CPUProfilerPreciseSamplingEntry& corePreciseRootEntry = coreReport.cpuReport.getPreciseSamplingData();
  473. struct TodoBasic
  474. {
  475. TodoBasic(const CPUProfilerBasicSamplingEntry& _entry, UINT32 _depth)
  476. :entry(_entry), depth(_depth)
  477. { }
  478. const CPUProfilerBasicSamplingEntry& entry;
  479. UINT32 depth;
  480. };
  481. struct TodoPrecise
  482. {
  483. TodoPrecise(const CPUProfilerPreciseSamplingEntry& _entry, UINT32 _depth)
  484. :entry(_entry), depth(_depth)
  485. { }
  486. const CPUProfilerPreciseSamplingEntry& entry;
  487. UINT32 depth;
  488. };
  489. BasicRowFiller basicRowFiller(mBasicRows, *mBasicLayoutLabels, *mBasicLayoutContents, *mWidget);
  490. Stack<TodoBasic> todoBasic;
  491. const CPUProfilerBasicSamplingEntry* basicRootEntries[NUM_ROOT_ENTRIES];
  492. basicRootEntries[0] = &simBasicRootEntry;
  493. basicRootEntries[1] = &coreBasicRootEntry;
  494. for(UINT32 i = 0; i < NUM_ROOT_ENTRIES; i++)
  495. {
  496. todoBasic.push(TodoBasic(*basicRootEntries[i], 0));
  497. while(!todoBasic.empty())
  498. {
  499. TodoBasic curEntry = todoBasic.top();
  500. todoBasic.pop();
  501. const CPUProfilerBasicSamplingEntry::Data& data = curEntry.entry.data;
  502. basicRowFiller.addData(curEntry.depth, data.name, data.pctOfParent, data.numCalls, data.memAllocs, data.memFrees,
  503. data.avgTimeMs, data.totalTimeMs, data.avgSelfTimeMs, data.totalSelfTimeMs);
  504. if(curEntry.depth <= MAX_DEPTH)
  505. {
  506. for(auto iter = curEntry.entry.childEntries.rbegin(); iter != curEntry.entry.childEntries.rend(); ++iter)
  507. {
  508. todoBasic.push(TodoBasic(*iter, curEntry.depth + 1));
  509. }
  510. }
  511. }
  512. }
  513. PreciseRowFiller preciseRowFiller(mPreciseRows, *mBasicLayoutLabels, *mBasicLayoutContents, *mWidget);
  514. Stack<TodoPrecise> todoPrecise;
  515. const CPUProfilerPreciseSamplingEntry* preciseRootEntries[NUM_ROOT_ENTRIES];
  516. preciseRootEntries[0] = &simPreciseRootEntry;
  517. preciseRootEntries[1] = &corePreciseRootEntry;
  518. for(UINT32 i = 0; i < NUM_ROOT_ENTRIES; i++)
  519. {
  520. todoPrecise.push(TodoPrecise(*preciseRootEntries[i], 0));
  521. while(!todoBasic.empty())
  522. {
  523. TodoPrecise curEntry = todoPrecise.top();
  524. todoPrecise.pop();
  525. const CPUProfilerPreciseSamplingEntry::Data& data = curEntry.entry.data;
  526. preciseRowFiller.addData(curEntry.depth, data.name, data.pctOfParent, data.numCalls, data.memAllocs, data.memFrees,
  527. data.avgCycles, data.totalCycles, data.avgSelfCycles, data.totalSelfCycles);
  528. if(curEntry.depth <= MAX_DEPTH)
  529. {
  530. for(auto iter = curEntry.entry.childEntries.rbegin(); iter != curEntry.entry.childEntries.rend(); ++iter)
  531. {
  532. todoPrecise.push(TodoPrecise(*iter, curEntry.depth + 1));
  533. }
  534. }
  535. }
  536. }
  537. }
  538. void ProfilerOverlay::updateGPUSampleContents(const GPUProfilerReport& gpuReport)
  539. {
  540. mGPUFrameNumStr.setParameter(0, toWString((UINT64)gTime().getFrameNumber()));
  541. mGPUTimeStr.setParameter(0, toWString(gpuReport.frameSample.timeMs));
  542. mGPUDrawCallsStr.setParameter(0, toWString(gpuReport.frameSample.numDrawCalls));
  543. mGPURenTargetChangesStr.setParameter(0, toWString(gpuReport.frameSample.numRenderTargetChanges));
  544. mGPUPresentsStr.setParameter(0, toWString(gpuReport.frameSample.numPresents));
  545. mGPUClearsStr.setParameter(0, toWString(gpuReport.frameSample.numClears));
  546. mGPUVerticesStr.setParameter(0, toWString(gpuReport.frameSample.numVertices));
  547. mGPUPrimitivesStr.setParameter(0, toWString(gpuReport.frameSample.numPrimitives));
  548. mGPUSamplesStr.setParameter(0, toWString(gpuReport.frameSample.numDrawnSamples));
  549. mGPUBlendStateChangesStr.setParameter(0, toWString(gpuReport.frameSample.numBlendStateChanges));
  550. mGPURasterStateChangesStr.setParameter(0, toWString(gpuReport.frameSample.numRasterizerStateChanges));
  551. mGPUDepthStencilStateChangesStr.setParameter(0, toWString(gpuReport.frameSample.numDepthStencilStateChanges));
  552. mGPUObjectsCreatedStr.setParameter(0, toWString(gpuReport.frameSample.numObjectsCreated));
  553. mGPUObjectsDestroyedStr.setParameter(0, toWString(gpuReport.frameSample.numObjectsDestroyed));
  554. mGPUResourceWritesStr.setParameter(0, toWString(gpuReport.frameSample.numResourceWrites));
  555. mGPUResourceReadsStr.setParameter(0, toWString(gpuReport.frameSample.numResourceReads));
  556. mGPUTextureBindsStr.setParameter(0, toWString(gpuReport.frameSample.numTextureBinds));
  557. mGPUSamplerBindsStr.setParameter(0, toWString(gpuReport.frameSample.numSamplerBinds));
  558. mGPUVertexBufferBindsStr.setParameter(0, toWString(gpuReport.frameSample.numVertexBufferBinds));
  559. mGPUIndexBufferBindsStr.setParameter(0, toWString(gpuReport.frameSample.numIndexBufferBinds));
  560. mGPUGPUProgramBufferBindsStr.setParameter(0, toWString(gpuReport.frameSample.numGpuParamBufferBinds));
  561. mGPUGPUProgramBindsStr.setParameter(0, toWString(gpuReport.frameSample.numGpuProgramBinds));
  562. GPUSampleRowFiller sampleRowFiller(mGPUSampleRows, *mGPULayoutSamples, *mWidget);
  563. for (auto& sample : gpuReport.samples)
  564. {
  565. sampleRowFiller.addData(sample.name, sample.timeMs);
  566. }
  567. }
  568. }