BsVulkanResource.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  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. if(isUsed() && mState == State::Normal) // Used without support for concurrency
  36. {
  37. assert(mQueueFamily == queueFamily &&
  38. "Vulkan resource without concurrency support can only be used by one queue family at once.");
  39. }
  40. mNumUsedHandles++;
  41. mQueueFamily = queueFamily;
  42. assert(globalQueueIdx < MAX_UNIQUE_QUEUES);
  43. if (useFlags.isSet(VulkanUseFlag::Read))
  44. {
  45. assert(mReadUses[globalQueueIdx] < 255 && "Resource used in too many command buffers at once.");
  46. mReadUses[globalQueueIdx]++;
  47. }
  48. if(useFlags.isSet(VulkanUseFlag::Write))
  49. {
  50. assert(mWriteUses[globalQueueIdx] < 255 && "Resource used in too many command buffers at once.");
  51. mWriteUses[globalQueueIdx]++;
  52. }
  53. }
  54. void VulkanResource::notifyDone(UINT32 globalQueueIdx, VulkanUseFlags useFlags)
  55. {
  56. bool destroy;
  57. {
  58. Lock lock(mMutex);
  59. mNumUsedHandles--;
  60. mNumBoundHandles--;
  61. if (useFlags.isSet(VulkanUseFlag::Read))
  62. {
  63. assert(mReadUses[globalQueueIdx] > 0);
  64. mReadUses[globalQueueIdx]--;
  65. }
  66. if (useFlags.isSet(VulkanUseFlag::Write))
  67. {
  68. assert(mWriteUses[globalQueueIdx] > 0);
  69. mWriteUses[globalQueueIdx]--;
  70. }
  71. destroy = !isBound() && mState == State::Destroyed; // Queued for destruction
  72. }
  73. // (Safe to check outside of mutex as we guarantee that once queued for destruction, state cannot be changed)
  74. if (destroy)
  75. mOwner->destroy(this);
  76. }
  77. void VulkanResource::notifyUnbound()
  78. {
  79. bool destroy;
  80. {
  81. Lock lock(mMutex);
  82. mNumBoundHandles--;
  83. destroy = !isBound() && mState == State::Destroyed; // Queued for destruction
  84. }
  85. // (Safe to check outside of mutex as we guarantee that once queued for destruction, state cannot be changed)
  86. if (destroy)
  87. mOwner->destroy(this);
  88. }
  89. UINT32 VulkanResource::getUseInfo(VulkanUseFlags useFlags) const
  90. {
  91. UINT32 mask = 0;
  92. if(useFlags.isSet(VulkanUseFlag::Read))
  93. {
  94. for (UINT32 i = 0; i < MAX_UNIQUE_QUEUES; i++)
  95. {
  96. if (mReadUses[i] > 0)
  97. mask |= 1 << i;
  98. }
  99. }
  100. if (useFlags.isSet(VulkanUseFlag::Write))
  101. {
  102. for (UINT32 i = 0; i < MAX_UNIQUE_QUEUES; i++)
  103. {
  104. if (mWriteUses[i] > 0)
  105. mask |= 1 << i;
  106. }
  107. }
  108. return mask;
  109. }
  110. void VulkanResource::destroy()
  111. {
  112. bool destroy;
  113. {
  114. Lock lock(mMutex);
  115. assert(mState != State::Destroyed && "Vulkan resource destroy() called more than once.");
  116. mState = State::Destroyed;
  117. // If not bound anyhwere, destroy right away, otherwise check when it is reported as finished on the device
  118. destroy = !isBound();
  119. }
  120. // (Safe to check outside of mutex as we guarantee that once queued for destruction, state cannot be changed)
  121. if (destroy)
  122. mOwner->destroy(this);
  123. }
  124. VulkanResourceManager::VulkanResourceManager(VulkanDevice& device)
  125. :mDevice(device)
  126. { }
  127. VulkanResourceManager::~VulkanResourceManager()
  128. {
  129. #if BS_DEBUG_MODE
  130. Lock lock(mMutex);
  131. assert(mResources.empty() && "Resource manager shutting down but not all resources were released.");
  132. #endif
  133. }
  134. void VulkanResourceManager::destroy(VulkanResource* resource)
  135. {
  136. #if BS_DEBUG_MODE
  137. {
  138. Lock lock(mMutex);
  139. mResources.erase(resource);
  140. }
  141. #endif
  142. bs_delete(resource);
  143. }
  144. }}