BsVulkanOcclusionQuery.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsVulkanOcclusionQuery.h"
  4. #include "BsVulkanDevice.h"
  5. #include "Managers/BsVulkanQueryManager.h"
  6. #include "BsVulkanRenderAPI.h"
  7. #include "BsVulkanCommandBuffer.h"
  8. #include "Profiling/BsRenderStats.h"
  9. namespace bs { namespace ct
  10. {
  11. VulkanOcclusionQuery::VulkanOcclusionQuery(VulkanDevice& device, bool binary)
  12. : OcclusionQuery(binary), mDevice(device), mNumSamples(0), mQueryEndCalled(false), mQueryFinalized(false)
  13. , mQueryInterrupted(false)
  14. {
  15. BS_INC_RENDER_STAT_CAT(ResCreated, RenderStatObject_Query);
  16. }
  17. VulkanOcclusionQuery::~VulkanOcclusionQuery()
  18. {
  19. for(auto& query : mQueries)
  20. mDevice.getQueryPool().releaseQuery(query);
  21. mQueries.clear();
  22. BS_INC_RENDER_STAT_CAT(ResDestroyed, RenderStatObject_Query);
  23. }
  24. void VulkanOcclusionQuery::begin(const SPtr<CommandBuffer>& cb)
  25. {
  26. VulkanQueryPool& queryPool = mDevice.getQueryPool();
  27. // Clear any existing queries
  28. for (auto& query : mQueries)
  29. mDevice.getQueryPool().releaseQuery(query);
  30. mQueries.clear();
  31. mQueryEndCalled = false;
  32. mNumSamples = 0;
  33. // Retrieve and queue new query
  34. VulkanCommandBuffer* vulkanCB;
  35. if (cb != nullptr)
  36. vulkanCB = static_cast<VulkanCommandBuffer*>(cb.get());
  37. else
  38. vulkanCB = static_cast<VulkanCommandBuffer*>(gVulkanRenderAPI()._getMainCommandBuffer());
  39. VulkanCmdBuffer* internalCB = vulkanCB->getInternal();
  40. mQueries.push_back(queryPool.beginOcclusionQuery(internalCB, !mBinary));
  41. internalCB->registerQuery(this);
  42. setActive(true);
  43. }
  44. void VulkanOcclusionQuery::end(const SPtr<CommandBuffer>& cb)
  45. {
  46. assert(!mQueryInterrupted);
  47. if(mQueries.size() == 0)
  48. {
  49. LOGERR("end() called but query was never started.");
  50. return;
  51. }
  52. mQueryEndCalled = true;
  53. mQueryFinalized = false;
  54. VulkanCommandBuffer* vulkanCB;
  55. if (cb != nullptr)
  56. vulkanCB = static_cast<VulkanCommandBuffer*>(cb.get());
  57. else
  58. vulkanCB = static_cast<VulkanCommandBuffer*>(gVulkanRenderAPI()._getMainCommandBuffer());
  59. VulkanQueryPool& queryPool = mDevice.getQueryPool();
  60. VulkanCmdBuffer* internalCB = vulkanCB->getInternal();
  61. queryPool.endOcclusionQuery(mQueries.back(), internalCB);
  62. }
  63. bool VulkanOcclusionQuery::_isInProgress() const
  64. {
  65. return !mQueries.empty() && !mQueryEndCalled;
  66. }
  67. void VulkanOcclusionQuery::_interrupt(VulkanCmdBuffer& cb)
  68. {
  69. assert(mQueries.size() != 0 && !mQueryEndCalled);
  70. VulkanQueryPool& queryPool = mDevice.getQueryPool();
  71. queryPool.endOcclusionQuery(mQueries.back(), &cb);
  72. mQueryInterrupted = true;
  73. }
  74. void VulkanOcclusionQuery::_resume(VulkanCmdBuffer& cb)
  75. {
  76. assert(mQueryInterrupted);
  77. VulkanQueryPool& queryPool = mDevice.getQueryPool();
  78. mQueries.push_back(queryPool.beginOcclusionQuery(&cb, !mBinary));
  79. cb.registerQuery(this);
  80. mQueryInterrupted = false;
  81. }
  82. bool VulkanOcclusionQuery::isReady() const
  83. {
  84. if (!mQueryEndCalled)
  85. return false;
  86. if (mQueryFinalized)
  87. return true;
  88. UINT64 numSamples;
  89. bool ready = true;
  90. for (auto& query : mQueries)
  91. ready &= !query->isBound() && query->getResult(numSamples);
  92. return ready;
  93. }
  94. UINT32 VulkanOcclusionQuery::getNumSamples()
  95. {
  96. if(!mQueryFinalized)
  97. {
  98. UINT64 totalNumSamples = 0;
  99. bool ready = true;
  100. for (auto& query : mQueries)
  101. {
  102. UINT64 numSamples = 0;
  103. ready &= !query->isBound() && query->getResult(numSamples);
  104. totalNumSamples += numSamples;
  105. }
  106. if(ready)
  107. {
  108. mQueryFinalized = true;
  109. mNumSamples = totalNumSamples;
  110. VulkanQueryPool& queryPool = mDevice.getQueryPool();
  111. for (auto& query : mQueries)
  112. queryPool.releaseQuery(query);
  113. mQueries.clear();
  114. }
  115. }
  116. if (mBinary)
  117. return mNumSamples == 0 ? 0 : 1;
  118. return (UINT32)mNumSamples;
  119. }
  120. }}