2
0

BsD3D11TimerQuery.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  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 "BsD3D11CommandBuffer.h"
  7. #include "Profiling/BsRenderStats.h"
  8. #include "Debug/BsDebug.h"
  9. namespace bs { namespace ct
  10. {
  11. D3D11TimerQuery::D3D11TimerQuery(UINT32 deviceIdx)
  12. :mFinalized(false), mContext(nullptr), mBeginQuery(nullptr),
  13. mEndQuery(nullptr), mDisjointQuery(nullptr), mTimeDelta(0.0f), mQueryEndCalled(false)
  14. {
  15. assert(deviceIdx == 0 && "Multiple GPUs not supported natively on DirectX 11.");
  16. D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPI::instancePtr());
  17. D3D11Device& device = rs->getPrimaryDevice();
  18. D3D11_QUERY_DESC queryDesc;
  19. queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
  20. queryDesc.MiscFlags = 0;
  21. HRESULT hr = device.getD3D11Device()->CreateQuery(&queryDesc, &mDisjointQuery);
  22. if(hr != S_OK)
  23. {
  24. BS_EXCEPT(RenderingAPIException, "Failed to create a timer query.");
  25. }
  26. queryDesc.Query = D3D11_QUERY_TIMESTAMP;
  27. hr = device.getD3D11Device()->CreateQuery(&queryDesc, &mBeginQuery);
  28. if(hr != S_OK)
  29. {
  30. BS_EXCEPT(RenderingAPIException, "Failed to create a timer query.");
  31. }
  32. hr = device.getD3D11Device()->CreateQuery(&queryDesc, &mEndQuery);
  33. if(hr != S_OK)
  34. {
  35. BS_EXCEPT(RenderingAPIException, "Failed to create a timer query.");
  36. }
  37. mContext = device.getImmediateContext();
  38. BS_INC_RENDER_STAT_CAT(ResCreated, RenderStatObject_Query);
  39. }
  40. D3D11TimerQuery::~D3D11TimerQuery()
  41. {
  42. if(mBeginQuery != nullptr)
  43. mBeginQuery->Release();
  44. if(mEndQuery != nullptr)
  45. mEndQuery->Release();
  46. if(mDisjointQuery != nullptr)
  47. mDisjointQuery->Release();
  48. BS_INC_RENDER_STAT_CAT(ResDestroyed, RenderStatObject_Query);
  49. }
  50. void D3D11TimerQuery::begin(const SPtr<CommandBuffer>& cb)
  51. {
  52. auto execute = [&]()
  53. {
  54. mContext->Begin(mDisjointQuery);
  55. mContext->End(mBeginQuery);
  56. mQueryEndCalled = false;
  57. setActive(true);
  58. };
  59. if (cb == nullptr)
  60. execute();
  61. else
  62. {
  63. SPtr<D3D11CommandBuffer> d3d11cb = std::static_pointer_cast<D3D11CommandBuffer>(cb);
  64. d3d11cb->queueCommand(execute);
  65. }
  66. }
  67. void D3D11TimerQuery::end(const SPtr<CommandBuffer>& cb)
  68. {
  69. auto execute = [&]()
  70. {
  71. mContext->End(mEndQuery);
  72. mContext->End(mDisjointQuery);
  73. mQueryEndCalled = true;
  74. mFinalized = false;
  75. };
  76. if (cb == nullptr)
  77. execute();
  78. else
  79. {
  80. SPtr<D3D11CommandBuffer> d3d11cb = std::static_pointer_cast<D3D11CommandBuffer>(cb);
  81. d3d11cb->queueCommand(execute);
  82. }
  83. }
  84. bool D3D11TimerQuery::isReady() const
  85. {
  86. if (!mQueryEndCalled)
  87. return false;
  88. D3D11_QUERY_DATA_TIMESTAMP_DISJOINT disjointData;
  89. return mContext->GetData(mDisjointQuery, &disjointData, sizeof(disjointData), 0) == S_OK;
  90. }
  91. float D3D11TimerQuery::getTimeMs()
  92. {
  93. if(!mFinalized && isReady())
  94. {
  95. finalize();
  96. }
  97. return mTimeDelta;
  98. }
  99. void D3D11TimerQuery::finalize()
  100. {
  101. UINT64 timeStart, timeEnd;
  102. mContext->GetData(mBeginQuery, &timeStart, sizeof(timeStart), 0);
  103. mContext->GetData(mEndQuery, &timeEnd, sizeof(timeEnd), 0);
  104. D3D11_QUERY_DATA_TIMESTAMP_DISJOINT disjointData;
  105. mContext->GetData(mDisjointQuery, &disjointData, sizeof(disjointData), 0);
  106. float time = 0.0f;
  107. if(disjointData.Disjoint == FALSE)
  108. {
  109. float frequency = static_cast<float>(disjointData.Frequency);
  110. UINT64 delta = timeEnd - timeStart;
  111. mTimeDelta = (delta / (float)frequency) * 1000.0f;
  112. }
  113. else
  114. {
  115. LOGWRN_VERBOSE("Unrealiable GPU timer query detected.");
  116. }
  117. }
  118. }}