BsD3D11TimerQuery.cpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. #include "BsD3D11TimerQuery.h"
  2. #include "BsD3D11RenderAPI.h"
  3. #include "BsD3D11Device.h"
  4. #include "BsRenderStats.h"
  5. #include "BsDebug.h"
  6. namespace BansheeEngine
  7. {
  8. D3D11TimerQuery::D3D11TimerQuery()
  9. :mFinalized(false), mContext(nullptr), mBeginQuery(nullptr),
  10. mEndQuery(nullptr), mDisjointQuery(nullptr), mTimeDelta(0.0f), mQueryEndCalled(false)
  11. {
  12. D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPICore::instancePtr());
  13. D3D11Device& device = rs->getPrimaryDevice();
  14. D3D11_QUERY_DESC queryDesc;
  15. queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
  16. queryDesc.MiscFlags = 0;
  17. HRESULT hr = device.getD3D11Device()->CreateQuery(&queryDesc, &mDisjointQuery);
  18. if(hr != S_OK)
  19. {
  20. BS_EXCEPT(RenderingAPIException, "Failed to create a timer query.");
  21. }
  22. queryDesc.Query = D3D11_QUERY_TIMESTAMP;
  23. hr = device.getD3D11Device()->CreateQuery(&queryDesc, &mBeginQuery);
  24. if(hr != S_OK)
  25. {
  26. BS_EXCEPT(RenderingAPIException, "Failed to create a timer query.");
  27. }
  28. hr = device.getD3D11Device()->CreateQuery(&queryDesc, &mEndQuery);
  29. if(hr != S_OK)
  30. {
  31. BS_EXCEPT(RenderingAPIException, "Failed to create a timer query.");
  32. }
  33. mContext = device.getImmediateContext();
  34. BS_INC_RENDER_STAT_CAT(ResCreated, RenderStatObject_Query);
  35. }
  36. D3D11TimerQuery::~D3D11TimerQuery()
  37. {
  38. if(mBeginQuery != nullptr)
  39. mBeginQuery->Release();
  40. if(mEndQuery != nullptr)
  41. mEndQuery->Release();
  42. if(mDisjointQuery != nullptr)
  43. mDisjointQuery->Release();
  44. BS_INC_RENDER_STAT_CAT(ResDestroyed, RenderStatObject_Query);
  45. }
  46. void D3D11TimerQuery::begin()
  47. {
  48. mContext->Begin(mDisjointQuery);
  49. mContext->End(mBeginQuery);
  50. mQueryEndCalled = false;
  51. setActive(true);
  52. }
  53. void D3D11TimerQuery::end()
  54. {
  55. mContext->End(mEndQuery);
  56. mContext->End(mDisjointQuery);
  57. mQueryEndCalled = true;
  58. mFinalized = false;
  59. }
  60. bool D3D11TimerQuery::isReady() const
  61. {
  62. if (!mQueryEndCalled)
  63. return false;
  64. D3D11_QUERY_DATA_TIMESTAMP_DISJOINT disjointData;
  65. return mContext->GetData(mDisjointQuery, &disjointData, sizeof(disjointData), 0) == S_OK;
  66. }
  67. float D3D11TimerQuery::getTimeMs()
  68. {
  69. if(!mFinalized && isReady())
  70. {
  71. finalize();
  72. }
  73. return mTimeDelta;
  74. }
  75. void D3D11TimerQuery::finalize()
  76. {
  77. UINT64 timeStart, timeEnd;
  78. mContext->GetData(mBeginQuery, &timeStart, sizeof(timeStart), 0);
  79. mContext->GetData(mEndQuery, &timeEnd, sizeof(timeEnd), 0);
  80. D3D11_QUERY_DATA_TIMESTAMP_DISJOINT disjointData;
  81. mContext->GetData(mDisjointQuery, &disjointData, sizeof(disjointData), 0);
  82. float time = 0.0f;
  83. if(disjointData.Disjoint == FALSE)
  84. {
  85. float frequency = static_cast<float>(disjointData.Frequency);
  86. UINT64 delta = timeEnd - timeStart;
  87. mTimeDelta = (delta / (float)frequency) * 1000.0f;
  88. }
  89. else
  90. {
  91. LOGWRN("Unrealiable GPU timer query detected.");
  92. }
  93. }
  94. }