BsProfilerGPU.h 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #pragma once
  4. #include "BsCorePrerequisites.h"
  5. #include "BsModule.h"
  6. #include "BsRenderStats.h"
  7. namespace bs
  8. {
  9. /** @addtogroup Profiling
  10. * @{
  11. */
  12. /** Contains various profiler statistics about a single GPU profiling sample. */
  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 numPipelineStateChanges; /**< How many times did the pipeline state change. */
  25. UINT32 numGpuParamBinds; /**< How many times were GPU parameters 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 numResourceWrites; /**< How many times were GPU resources written to. */
  29. UINT32 numResourceReads; /**< How many times were GPU resources read from. */
  30. UINT32 numObjectsCreated; /**< How many GPU objects were created. */
  31. UINT32 numObjectsDestroyed; /**< How many GPU objects were destroyed. */
  32. };
  33. /** Profiler report containing information about GPU sampling data from a single frame. */
  34. struct GPUProfilerReport
  35. {
  36. GPUProfileSample frameSample; /**< Sample containing data for entire frame. */
  37. Vector<GPUProfileSample> samples;
  38. };
  39. /**
  40. * Profiler that measures time and amount of various GPU operations.
  41. *
  42. * @note Core thread only except where noted otherwise.
  43. */
  44. class BS_CORE_EXPORT ProfilerGPU : public Module<ProfilerGPU>
  45. {
  46. private:
  47. struct ActiveSample
  48. {
  49. ProfilerString sampleName;
  50. RenderStatsData startStats;
  51. RenderStatsData endStats;
  52. SPtr<ct::TimerQuery> activeTimeQuery;
  53. SPtr<ct::OcclusionQuery> activeOcclusionQuery;
  54. };
  55. struct ActiveFrame
  56. {
  57. ActiveSample frameSample;
  58. Vector<ActiveSample> samples;
  59. };
  60. public:
  61. ProfilerGPU();
  62. ~ProfilerGPU();
  63. /**
  64. * Signals a start of a new frame. Every frame will generate a separate profiling report. This call must be followed
  65. * by endFrame(), and any sampling operations must happen between beginFrame() and endFrame().
  66. */
  67. void beginFrame();
  68. /**
  69. * Signals an end of the currently sampled frame. Results of the sampling will be available once
  70. * getNumAvailableReports increments. This may take a while as the sampling is scheduled on the core thread and
  71. * on the GPU.
  72. */
  73. void endFrame();
  74. /**
  75. * Begins sample measurement. Must be followed by endSample().
  76. *
  77. * @param[in] name Unique name for the sample you can later use to find the sampling data.
  78. *
  79. * @note Must be called between beginFrame()/endFrame() calls.
  80. */
  81. void beginSample(const ProfilerString& name);
  82. /**
  83. * Ends sample measurement.
  84. *
  85. * @param[in] name Unique name for the sample.
  86. *
  87. * @note
  88. * Unique name is primarily needed to more easily identify mismatched begin/end sample pairs. Otherwise the name in
  89. * beginSample() would be enough. Must be called between beginFrame()/endFrame() calls.
  90. */
  91. void endSample(const ProfilerString& name);
  92. /**
  93. * Returns number of profiling reports that are ready but haven't been retrieved yet.
  94. *
  95. * @note
  96. * There is an internal limit of maximum number of available reports, where oldest ones will get deleted so make
  97. * sure to call this often if you don't want to miss some.
  98. * @note
  99. * Thread safe.
  100. */
  101. UINT32 getNumAvailableReports();
  102. /**
  103. * Gets the oldest report available and removes it from the internal list. Throws an exception if no reports are
  104. * available.
  105. *
  106. * @note Thread safe.
  107. */
  108. GPUProfilerReport getNextReport();
  109. public:
  110. // ***** INTERNAL ******
  111. /** @name Internal
  112. * @{
  113. */
  114. /**
  115. * To be called once per frame from the Core thread.
  116. */
  117. void _update();
  118. /** @} */
  119. private:
  120. /** Assigns start values for the provided sample. */
  121. void beginSampleInternal(ActiveSample& sample);
  122. /** Assigns end values for the provided sample. */
  123. void endSampleInternal(ActiveSample& sample);
  124. /** Creates a new timer query or returns an existing free query. */
  125. SPtr<ct::TimerQuery> getTimerQuery() const;
  126. /** Creates a new occlusion query or returns an existing free query. */
  127. SPtr<ct::OcclusionQuery> getOcclusionQuery() const;
  128. /**
  129. * Interprets the active frame results and generates a profiler report for the frame. Provided frame queries must
  130. * have finished before calling this.
  131. */
  132. GPUProfilerReport resolveFrame(ActiveFrame& frame);
  133. /** Resolves an active sample and converts it to report sample. */
  134. void resolveSample(const ActiveSample& sample, GPUProfileSample& reportSample);
  135. private:
  136. ActiveFrame mActiveFrame;
  137. bool mIsFrameActive;
  138. Stack<UINT32> mActiveSampleIndexes;
  139. Queue<ActiveFrame> mUnresolvedFrames;
  140. GPUProfilerReport* mReadyReports;
  141. static const UINT32 MAX_QUEUE_ELEMENTS;
  142. UINT32 mReportHeadPos;
  143. UINT32 mReportCount;
  144. mutable Stack<SPtr<ct::TimerQuery>> mFreeTimerQueries;
  145. mutable Stack<SPtr<ct::OcclusionQuery>> mFreeOcclusionQueries;
  146. Mutex mMutex;
  147. };
  148. /** Provides global access to ProfilerGPU instance. */
  149. BS_CORE_EXPORT ProfilerGPU& gProfilerGPU();
  150. /** @} */
  151. }