BsVulkanResource.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsVulkanResource.h"
  4. #include "BsVulkanCommandBuffer.h"
  5. #include "CoreThread/BsCoreThread.h"
  6. namespace bs { namespace ct
  7. {
  8. VulkanResource::VulkanResource(VulkanResourceManager* owner, bool concurrency)
  9. {
  10. Lock lock(mMutex);
  11. mOwner = owner;
  12. mQueueFamily = -1;
  13. mState = concurrency ? State::Shared : State::Normal;
  14. mNumUsedHandles = 0;
  15. mNumBoundHandles = 0;
  16. bs_zero_out(mReadUses);
  17. bs_zero_out(mWriteUses);
  18. }
  19. VulkanResource::~VulkanResource()
  20. {
  21. THROW_IF_NOT_CORE_THREAD
  22. Lock lock(mMutex);
  23. assert(mState == State::Destroyed && "Vulkan resource getting destructed without destroy() called first.");
  24. }
  25. void VulkanResource::notifyBound()
  26. {
  27. Lock lock(mMutex);
  28. assert(mState != State::Destroyed);
  29. mNumBoundHandles++;
  30. }
  31. void VulkanResource::notifyUsed(UINT32 globalQueueIdx, UINT32 queueFamily, VulkanUseFlags useFlags)
  32. {
  33. Lock lock(mMutex);
  34. assert(useFlags != VulkanUseFlag::None);
  35. bool isUsed = mNumUsedHandles > 0;
  36. if(isUsed && mState == State::Normal) // Used without support for concurrency
  37. {
  38. assert(mQueueFamily == queueFamily &&
  39. "Vulkan resource without concurrency support can only be used by one queue family at once.");
  40. }
  41. mNumUsedHandles++;
  42. mQueueFamily = queueFamily;
  43. assert(globalQueueIdx < MAX_UNIQUE_QUEUES);
  44. if (useFlags.isSet(VulkanUseFlag::Read))
  45. {
  46. assert(mReadUses[globalQueueIdx] < 255 && "Resource used in too many command buffers at once.");
  47. mReadUses[globalQueueIdx]++;
  48. }
  49. if(useFlags.isSet(VulkanUseFlag::Write))
  50. {
  51. assert(mWriteUses[globalQueueIdx] < 255 && "Resource used in too many command buffers at once.");
  52. mWriteUses[globalQueueIdx]++;
  53. }
  54. }
  55. void VulkanResource::notifyDone(UINT32 globalQueueIdx, VulkanUseFlags useFlags)
  56. {
  57. bool destroy;
  58. {
  59. Lock lock(mMutex);
  60. mNumUsedHandles--;
  61. mNumBoundHandles--;
  62. if (useFlags.isSet(VulkanUseFlag::Read))
  63. {
  64. assert(mReadUses[globalQueueIdx] > 0);
  65. mReadUses[globalQueueIdx]--;
  66. }
  67. if (useFlags.isSet(VulkanUseFlag::Write))
  68. {
  69. assert(mWriteUses[globalQueueIdx] > 0);
  70. mWriteUses[globalQueueIdx]--;
  71. }
  72. bool isBound = mNumBoundHandles > 0;
  73. destroy = !isBound && mState == State::Destroyed; // Queued for destruction
  74. }
  75. // (Safe to check outside of mutex as we guarantee that once queued for destruction, state cannot be changed)
  76. if (destroy)
  77. mOwner->destroy(this);
  78. }
  79. void VulkanResource::notifyUnbound()
  80. {
  81. bool destroy;
  82. {
  83. Lock lock(mMutex);
  84. mNumBoundHandles--;
  85. bool isBound = mNumBoundHandles > 0;
  86. destroy = !isBound && mState == State::Destroyed; // Queued for destruction
  87. }
  88. // (Safe to check outside of mutex as we guarantee that once queued for destruction, state cannot be changed)
  89. if (destroy)
  90. mOwner->destroy(this);
  91. }
  92. UINT32 VulkanResource::getUseInfo(VulkanUseFlags useFlags) const
  93. {
  94. UINT32 mask = 0;
  95. if(useFlags.isSet(VulkanUseFlag::Read))
  96. {
  97. for (UINT32 i = 0; i < MAX_UNIQUE_QUEUES; i++)
  98. {
  99. if (mReadUses[i] > 0)
  100. mask |= 1 << i;
  101. }
  102. }
  103. if (useFlags.isSet(VulkanUseFlag::Write))
  104. {
  105. for (UINT32 i = 0; i < MAX_UNIQUE_QUEUES; i++)
  106. {
  107. if (mWriteUses[i] > 0)
  108. mask |= 1 << i;
  109. }
  110. }
  111. return mask;
  112. }
  113. void VulkanResource::destroy()
  114. {
  115. bool destroy;
  116. {
  117. Lock lock(mMutex);
  118. assert(mState != State::Destroyed && "Vulkan resource destroy() called more than once.");
  119. mState = State::Destroyed;
  120. // If not bound anyhwere, destroy right away, otherwise check when it is reported as finished on the device
  121. bool isBound = mNumBoundHandles > 0;
  122. destroy = !isBound;
  123. }
  124. // (Safe to check outside of mutex as we guarantee that once queued for destruction, state cannot be changed)
  125. if (destroy)
  126. mOwner->destroy(this);
  127. }
  128. VulkanResourceManager::VulkanResourceManager(VulkanDevice& device)
  129. :mDevice(device)
  130. { }
  131. VulkanResourceManager::~VulkanResourceManager()
  132. {
  133. #if BS_DEBUG_MODE
  134. Lock lock(mMutex);
  135. assert(mResources.empty() && "Resource manager shutting down but not all resources were released.");
  136. #endif
  137. }
  138. void VulkanResourceManager::destroy(VulkanResource* resource)
  139. {
  140. #if BS_DEBUG_MODE
  141. {
  142. Lock lock(mMutex);
  143. mResources.erase(resource);
  144. }
  145. #endif
  146. bs_delete(resource);
  147. }
  148. }}