2
0

BsD3D11TimerQuery.cpp 3.1 KB

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