BsD3D9TimerQuery.cpp 3.8 KB

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