BsProfilerGPU.h 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. #pragma once
  2. #include "BsCorePrerequisites.h"
  3. #include "BsModule.h"
  4. #include "BsRenderStats.h"
  5. namespace BansheeEngine
  6. {
  7. /**
  8. * @brief Contains various profiler statistics about a single GPU profiling sample
  9. */
  10. struct GPUProfileSample
  11. {
  12. String name; /**< Name of the sample for easier identification. */
  13. float timeMs; /**< Time in milliseconds it took to execute the sampled block. */
  14. UINT32 numDrawCalls; /**< Number of draw calls that happened. */
  15. UINT32 numRenderTargetChanges; /**< How many times was render target changed. */
  16. UINT32 numPresents; /**< How many times did a buffer swap happen on a double buffered render target. */
  17. UINT32 numClears; /**< How many times was render target cleared. */
  18. UINT32 numVertices; /**< Total number of vertices sent to the GPU. */
  19. UINT32 numPrimitives; /**< Total number of primitives sent to the GPU. */
  20. UINT32 numDrawnSamples; /**< Number of samples drawn by the GPU. */
  21. UINT32 numBlendStateChanges; /**< How many times did the blend state change. */
  22. UINT32 numRasterizerStateChanges; /**< How many times did the rasterizer state change. */
  23. UINT32 numDepthStencilStateChanges; /**< How many times did the depth stencil state change. */
  24. UINT32 numTextureBinds; /**< How many times was a texture bound. */
  25. UINT32 numSamplerBinds; /**< How many times was a sampler bound. */
  26. UINT32 numVertexBufferBinds; /**< How many times was a vertex buffer bound. */
  27. UINT32 numIndexBufferBinds; /**< How many times was an index buffer bound. */
  28. UINT32 numGpuParamBufferBinds; /**< How many times was an GPU parameter buffer bound. */
  29. UINT32 numGpuProgramBinds; /**< How many times was a GPU program bound. */
  30. UINT32 numResourceWrites; /**< How many times were GPU resources written to. */
  31. UINT32 numResourceReads; /**< How many times were GPU resources read from. */
  32. UINT32 numObjectsCreated; /**< How many GPU objects were created. */
  33. UINT32 numObjectsDestroyed; /**< How many GPU objects were destroyed. */
  34. };
  35. /**
  36. * @brief Profiler report containing information about GPU sampling data
  37. * from a single frame.
  38. */
  39. struct GPUProfilerReport
  40. {
  41. GPUProfileSample frameSample; /**< Sample containing data for entire frame. */
  42. Vector<GPUProfileSample> samples;
  43. };
  44. /**
  45. * @brief Profiler that measures time and amount of various GPU operations.
  46. *
  47. * @note Core thread only except where noted otherwise.
  48. */
  49. class BS_CORE_EXPORT ProfilerGPU : public Module<ProfilerGPU>
  50. {
  51. private:
  52. struct ActiveSample
  53. {
  54. ProfilerString sampleName;
  55. RenderStatsData startStats;
  56. RenderStatsData endStats;
  57. TimerQueryPtr activeTimeQuery;
  58. OcclusionQueryPtr activeOcclusionQuery;
  59. };
  60. struct ActiveFrame
  61. {
  62. ActiveSample frameSample;
  63. Vector<ActiveSample> samples;
  64. };
  65. public:
  66. ProfilerGPU();
  67. /**
  68. * @brief Signals a start of a new frame. Every frame will generate a separate profiling report.
  69. * This call must be followed by "endFrame", and any sampling operations must happen between
  70. * beginFrame and endFrame.
  71. */
  72. void beginFrame();
  73. /**
  74. * @brief Signals an end of the currently sampled frame. Results of the sampling will be available
  75. * once getNumAvailableReports increments. This may take a while as the sampling is scheduled on
  76. * the core thread and on the GPU.
  77. */
  78. void endFrame();
  79. /**
  80. * @brief Begins sample measurement. Must be followed by endSample.
  81. *
  82. * @param name Unique name for the sample you can later use to find the sampling data.
  83. *
  84. * @note Must be called between beginFrame/endFrame calls.
  85. */
  86. void beginSample(const ProfilerString& name);
  87. /**
  88. * @brief Ends sample measurement.
  89. *
  90. * @param name Unique name for the sample.
  91. *
  92. * @note Unique name is primarily needed to more easily identify mismatched
  93. * begin/end sample pairs. Otherwise the name in beginSample would be enough.
  94. * Must be called between beginFrame/endFrame calls.
  95. */
  96. void endSample(const ProfilerString& name);
  97. /**
  98. * @brief Returns number of profiling reports that are ready but haven't been
  99. * retrieved yet.
  100. *
  101. * @note There is an internal limit of maximum number of available reports, where oldest ones will
  102. * get deleted so make sure to call this often if you don't want to miss some.
  103. *
  104. * Thread safe.
  105. */
  106. UINT32 getNumAvailableReports();
  107. /**
  108. * @brief Gets the oldest report available and removes it from the internal list.
  109. * Throws an exception if no reports are available.
  110. *
  111. * @note Thread safe.
  112. */
  113. GPUProfilerReport getNextReport();
  114. /**
  115. * @brief To be called once per frame from the Core thread.
  116. *
  117. * @note Internal method.
  118. */
  119. void _update();
  120. private:
  121. /**
  122. * @brief Assigns start values for the provided sample.
  123. */
  124. void beginSampleInternal(ActiveSample& sample);
  125. /**
  126. * @brief Assigns end values for the provided sample.
  127. */
  128. void endSampleInternal(ActiveSample& sample);
  129. /**
  130. * @brief Creates a new timer query or returns an existing free query.
  131. */
  132. TimerQueryPtr getTimerQuery() const;
  133. /**
  134. * @brief Creates a new occlusion query or returns an existing free query.
  135. */
  136. OcclusionQueryPtr getOcclusionQuery() const;
  137. /**
  138. * @brief Interprets the active frame results and generates a profiler report for
  139. * the frame. Provided frame queries must have finished before calling this.
  140. */
  141. GPUProfilerReport resolveFrame(ActiveFrame& frame);
  142. /**
  143. * @brief Resolves an active sample and converts it to report sample.
  144. */
  145. void resolveSample(const ActiveSample& sample, GPUProfileSample& reportSample);
  146. private:
  147. ActiveFrame mActiveFrame;
  148. bool mIsFrameActive;
  149. Stack<UINT32> mActiveSampleIndexes;
  150. Queue<ActiveFrame> mUnresolvedFrames;
  151. Queue<GPUProfilerReport> mReadyReports;
  152. mutable Stack<TimerQueryPtr> mFreeTimerQueries;
  153. mutable Stack<OcclusionQueryPtr> mFreeOcclusionQueries;
  154. BS_MUTEX(mMutex);
  155. };
  156. }