BsProfilerGPU.h 6.1 KB

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