BsD3D11TimerQuery.cpp 3.1 KB

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