BsProfilerGPU.cpp 6.4 KB

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