BsD3D9TimerQuery.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. #include "BsD3D9TimerQuery.h"
  2. #include "BsD3D9RenderAPI.h"
  3. #include "BsRenderStats.h"
  4. #include "BsDebug.h"
  5. namespace BansheeEngine
  6. {
  7. D3D9TimerQuery::D3D9TimerQuery()
  8. :mFinalized(false), mBeginQuery(nullptr), mFreqQuery(nullptr), mQueryIssued(false),
  9. mEndQuery(nullptr), mDisjointQuery(nullptr), mTimeDelta(0.0f), mDevice(nullptr)
  10. {
  11. createQuery();
  12. BS_INC_RENDER_STAT_CAT(ResCreated, RenderStatObject_Query);
  13. }
  14. D3D9TimerQuery::~D3D9TimerQuery()
  15. {
  16. releaseQuery();
  17. BS_INC_RENDER_STAT_CAT(ResDestroyed, RenderStatObject_Query);
  18. }
  19. void D3D9TimerQuery::createQuery()
  20. {
  21. mDevice = D3D9RenderAPI::getActiveD3D9Device();
  22. HRESULT hr = mDevice->CreateQuery(D3DQUERYTYPE_TIMESTAMPDISJOINT, &mDisjointQuery);
  23. if (hr != S_OK)
  24. {
  25. BS_EXCEPT(RenderingAPIException, "Failed to create a timer query.");
  26. }
  27. hr = mDevice->CreateQuery(D3DQUERYTYPE_TIMESTAMPFREQ, &mFreqQuery);
  28. if (hr != S_OK)
  29. {
  30. BS_EXCEPT(RenderingAPIException, "Failed to create a timer query.");
  31. }
  32. hr = mDevice->CreateQuery(D3DQUERYTYPE_TIMESTAMP, &mBeginQuery);
  33. if (hr != S_OK)
  34. {
  35. BS_EXCEPT(RenderingAPIException, "Failed to create a timer query.");
  36. }
  37. hr = mDevice->CreateQuery(D3DQUERYTYPE_TIMESTAMP, &mEndQuery);
  38. if (hr != S_OK)
  39. {
  40. BS_EXCEPT(RenderingAPIException, "Failed to create a timer query.");
  41. }
  42. }
  43. void D3D9TimerQuery::releaseQuery()
  44. {
  45. SAFE_RELEASE(mBeginQuery);
  46. SAFE_RELEASE(mEndQuery);
  47. SAFE_RELEASE(mDisjointQuery);
  48. SAFE_RELEASE(mFreqQuery);
  49. }
  50. bool D3D9TimerQuery::isQueryValid() const
  51. {
  52. return mDisjointQuery != nullptr && mBeginQuery != nullptr &&
  53. mEndQuery != nullptr && mFreqQuery != nullptr;
  54. }
  55. void D3D9TimerQuery::begin()
  56. {
  57. mQueryIssued = false;
  58. if (isQueryValid())
  59. {
  60. mDisjointQuery->Issue(D3DISSUE_BEGIN);
  61. mFreqQuery->Issue(D3DISSUE_END);
  62. mBeginQuery->Issue(D3DISSUE_END);
  63. }
  64. setActive(true);
  65. }
  66. void D3D9TimerQuery::end()
  67. {
  68. if (isQueryValid())
  69. {
  70. mEndQuery->Issue(D3DISSUE_END);
  71. mDisjointQuery->Issue(D3DISSUE_END);
  72. }
  73. mQueryIssued = true;
  74. mFinalized = false;
  75. }
  76. bool D3D9TimerQuery::isReady() const
  77. {
  78. if (!isQueryValid()) // Possibly device reset, in which case query is considered done if issued
  79. return mQueryIssued;
  80. if (!mQueryIssued)
  81. return false;
  82. BOOL queryData;
  83. return mDisjointQuery->GetData(&queryData, sizeof(BOOL), 0) == S_OK;
  84. }
  85. float D3D9TimerQuery::getTimeMs()
  86. {
  87. if(!mFinalized && isReady())
  88. {
  89. finalize();
  90. }
  91. return mTimeDelta;
  92. }
  93. void D3D9TimerQuery::finalize()
  94. {
  95. mFinalized = true;
  96. if (!isQueryValid())
  97. {
  98. mTimeDelta = 0.0f;
  99. return;
  100. }
  101. BOOL disjoint;
  102. mDisjointQuery->GetData(&disjoint, sizeof(BOOL), 0);
  103. if(!disjoint)
  104. {
  105. UINT64 frequency;
  106. mFreqQuery->GetData(&frequency, sizeof(UINT64), 0);
  107. UINT64 timeStart, timeEnd;
  108. mBeginQuery->GetData(&timeStart, sizeof(UINT64), 0);
  109. mEndQuery->GetData(&timeEnd, sizeof(UINT64), 0);
  110. UINT64 delta = timeEnd - timeStart;
  111. mTimeDelta = (delta/(float)frequency) * 1000.0f;
  112. }
  113. else
  114. {
  115. LOGWRN("Unrealiable GPU timer query detected.");
  116. }
  117. }
  118. void D3D9TimerQuery::notifyOnDeviceCreate(IDirect3DDevice9* d3d9Device)
  119. {
  120. if (d3d9Device == mDevice)
  121. createQuery();
  122. }
  123. void D3D9TimerQuery::notifyOnDeviceDestroy(IDirect3DDevice9* d3d9Device)
  124. {
  125. if (d3d9Device == mDevice)
  126. releaseQuery();
  127. }
  128. void D3D9TimerQuery::notifyOnDeviceLost(IDirect3DDevice9* d3d9Device)
  129. {
  130. if (d3d9Device == mDevice)
  131. releaseQuery();
  132. }
  133. void D3D9TimerQuery::notifyOnDeviceReset(IDirect3DDevice9* d3d9Device)
  134. {
  135. if (d3d9Device == mDevice)
  136. createQuery();
  137. }
  138. }