2
0

BsProfilerGPU.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. #include "BsProfilerGPU.h"
  2. #include "BsRenderStats.h"
  3. #include "BsTimerQuery.h"
  4. #include "BsOcclusionQuery.h"
  5. #include "BsException.h"
  6. namespace BansheeEngine
  7. {
  8. ProfilerGPU::ProfilerGPU()
  9. :mIsFrameActive(false)
  10. { }
  11. void ProfilerGPU::beginFrame()
  12. {
  13. if (mIsFrameActive)
  14. BS_EXCEPT(InvalidStateException, "Cannot begin a frame because another frame is active.");
  15. mActiveFrame = ActiveFrame();
  16. mActiveFrame.frameSample.sampleName = "Frame";
  17. beginSampleInternal(mActiveFrame.frameSample);
  18. mIsFrameActive = true;
  19. }
  20. void ProfilerGPU::endFrame()
  21. {
  22. if (mActiveSampleIndexes.size() > 0)
  23. BS_EXCEPT(InvalidStateException, "Attempting to end a frame while a sample is active.");
  24. if (!mIsFrameActive)
  25. return;
  26. endSampleInternal(mActiveFrame.frameSample);
  27. mUnresolvedFrames.push(mActiveFrame);
  28. mIsFrameActive = false;
  29. }
  30. void ProfilerGPU::beginSample(const ProfilerString& name)
  31. {
  32. if (!mIsFrameActive)
  33. BS_EXCEPT(InvalidStateException, "Cannot begin a sample because no frame is active.");
  34. mActiveFrame.samples.push_back(ActiveSample());
  35. ActiveSample& sample = mActiveFrame.samples.back();
  36. sample.sampleName = name;
  37. beginSampleInternal(sample);
  38. mActiveSampleIndexes.push((UINT32)mActiveFrame.samples.size() - 1);
  39. }
  40. void ProfilerGPU::endSample(const ProfilerString& name)
  41. {
  42. if (mActiveSampleIndexes.size() == 0)
  43. return;
  44. UINT32 lastSampleIdx = mActiveSampleIndexes.top();
  45. ActiveSample& sample = mActiveFrame.samples[lastSampleIdx];
  46. if (sample.sampleName != name)
  47. {
  48. String errorStr = "Attempting to end a sample that doesn't match. Got: " +
  49. String(name.c_str()) + ". Expected: " + String(sample.sampleName.c_str());
  50. BS_EXCEPT(InvalidStateException, errorStr);
  51. }
  52. endSampleInternal(sample);
  53. mActiveSampleIndexes.pop();
  54. }
  55. UINT32 ProfilerGPU::getNumAvailableReports()
  56. {
  57. BS_LOCK_MUTEX(mMutex);
  58. return (UINT32)mReadyReports.size();
  59. }
  60. GPUProfilerReport ProfilerGPU::getNextReport()
  61. {
  62. BS_LOCK_MUTEX(mMutex);
  63. if (mReadyReports.empty())
  64. BS_EXCEPT(InvalidStateException, "No reports are available.")
  65. GPUProfilerReport report = mReadyReports.front();
  66. mReadyReports.pop();
  67. return report;
  68. }
  69. void ProfilerGPU::_update()
  70. {
  71. while (!mUnresolvedFrames.empty())
  72. {
  73. ActiveFrame& frame = mUnresolvedFrames.front();
  74. // Frame sample timer query is the last query we issued
  75. // so if it is complete, we may assume all queries are complete.
  76. if (frame.frameSample.activeTimeQuery->isReady())
  77. {
  78. GPUProfilerReport report = resolveFrame(frame);
  79. mUnresolvedFrames.pop();
  80. {
  81. BS_LOCK_MUTEX(mMutex);
  82. mReadyReports.push(report);
  83. }
  84. }
  85. else
  86. break;
  87. }
  88. }
  89. GPUProfilerReport ProfilerGPU::resolveFrame(ActiveFrame& frame)
  90. {
  91. GPUProfilerReport report;
  92. resolveSample(frame.frameSample, report.frameSample);
  93. for (auto& sample : frame.samples)
  94. {
  95. report.samples.push_back(GPUProfileSample());
  96. GPUProfileSample& newSample = report.samples.back();
  97. resolveSample(sample, newSample);
  98. }
  99. return report;
  100. }
  101. void ProfilerGPU::resolveSample(const ActiveSample& sample, GPUProfileSample& reportSample)
  102. {
  103. reportSample.name = String(sample.sampleName.c_str());
  104. reportSample.timeMs = sample.activeTimeQuery->getTimeMs();
  105. reportSample.numDrawnSamples = sample.activeOcclusionQuery->getNumSamples();
  106. reportSample.numDrawCalls = (UINT32)(sample.endStats.numDrawCalls - sample.startStats.numDrawCalls);
  107. reportSample.numRenderTargetChanges = (UINT32)(sample.endStats.numRenderTargetChanges - sample.startStats.numRenderTargetChanges);
  108. reportSample.numPresents = (UINT32)(sample.endStats.numPresents - sample.startStats.numPresents);
  109. reportSample.numClears = (UINT32)(sample.endStats.numClears - sample.startStats.numClears);
  110. reportSample.numVertices = (UINT32)(sample.endStats.numVertices - sample.startStats.numVertices);
  111. reportSample.numPrimitives = (UINT32)(sample.endStats.numPrimitives - sample.startStats.numPrimitives);
  112. reportSample.numBlendStateChanges = (UINT32)(sample.endStats.numBlendStateChanges - sample.startStats.numBlendStateChanges);
  113. reportSample.numRasterizerStateChanges = (UINT32)(sample.endStats.numRasterizerStateChanges - sample.startStats.numRasterizerStateChanges);
  114. reportSample.numDepthStencilStateChanges = (UINT32)(sample.endStats.numDepthStencilStateChanges - sample.startStats.numDepthStencilStateChanges);
  115. reportSample.numTextureBinds = (UINT32)(sample.endStats.numTextureBinds - sample.startStats.numTextureBinds);
  116. reportSample.numSamplerBinds = (UINT32)(sample.endStats.numSamplerBinds - sample.startStats.numSamplerBinds);
  117. reportSample.numVertexBufferBinds = (UINT32)(sample.endStats.numVertexBufferBinds - sample.startStats.numVertexBufferBinds);
  118. reportSample.numIndexBufferBinds = (UINT32)(sample.endStats.numIndexBufferBinds - sample.startStats.numIndexBufferBinds);
  119. reportSample.numGpuParamBufferBinds = (UINT32)(sample.endStats.numGpuParamBufferBinds - sample.startStats.numGpuParamBufferBinds);
  120. reportSample.numGpuProgramBinds = (UINT32)(sample.endStats.numGpuProgramBinds - sample.startStats.numGpuProgramBinds);
  121. reportSample.numResourceWrites = (UINT32)(sample.endStats.numResourceWrites - sample.startStats.numResourceWrites);
  122. reportSample.numResourceReads = (UINT32)(sample.endStats.numResourceReads - sample.startStats.numResourceReads);
  123. reportSample.numObjectsCreated = (UINT32)(sample.endStats.numObjectsCreated - sample.startStats.numObjectsCreated);
  124. reportSample.numObjectsDestroyed = (UINT32)(sample.endStats.numObjectsDestroyed - sample.startStats.numObjectsDestroyed);
  125. mFreeTimerQueries.push(sample.activeTimeQuery);
  126. mFreeOcclusionQueries.push(sample.activeOcclusionQuery);
  127. }
  128. void ProfilerGPU::beginSampleInternal(ActiveSample& sample)
  129. {
  130. sample.startStats = RenderStats::instance().getData();
  131. sample.activeTimeQuery = getTimerQuery();
  132. sample.activeTimeQuery->begin();
  133. sample.activeOcclusionQuery = getOcclusionQuery();
  134. sample.activeOcclusionQuery->begin();
  135. }
  136. void ProfilerGPU::endSampleInternal(ActiveSample& sample)
  137. {
  138. sample.endStats = RenderStats::instance().getData();
  139. sample.activeOcclusionQuery->end();
  140. sample.activeTimeQuery->end();
  141. }
  142. TimerQueryPtr ProfilerGPU::getTimerQuery() const
  143. {
  144. if (!mFreeTimerQueries.empty())
  145. {
  146. TimerQueryPtr timerQuery = mFreeTimerQueries.top();
  147. mFreeTimerQueries.pop();
  148. return timerQuery;
  149. }
  150. return TimerQuery::create();
  151. }
  152. OcclusionQueryPtr ProfilerGPU::getOcclusionQuery() const
  153. {
  154. if (!mFreeOcclusionQueries.empty())
  155. {
  156. OcclusionQueryPtr occlusionQuery = mFreeOcclusionQueries.top();
  157. mFreeOcclusionQueries.pop();
  158. return occlusionQuery;
  159. }
  160. return OcclusionQuery::create(false);
  161. }
  162. }