BsVulkanResource.h 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #pragma once
  4. #include "BsVulkanPrerequisites.h"
  5. #include "BsStaticAlloc.h"
  6. namespace BansheeEngine
  7. {
  8. /** @addtogroup Vulkan
  9. * @{
  10. */
  11. /** Flags that determine how is a resource being used by the GPU. */
  12. enum class VulkanUseFlag
  13. {
  14. None = 0,
  15. Read = 0x1,
  16. Write = 0x2
  17. };
  18. class VulkanResourceManager;
  19. typedef Flags<VulkanUseFlag> VulkanUseFlags;
  20. BS_FLAGS_OPERATORS(VulkanUseFlag);
  21. /**
  22. * Wraps one or multiple native Vulkan objects. Allows the object usage to be tracked in command buffers, handles
  23. * ownership transitions between different queues, and handles delayed object destruction.
  24. *
  25. * @note Thread safe
  26. */
  27. class VulkanResource
  28. {
  29. public:
  30. VulkanResource(VulkanResourceManager* owner, bool concurrency);
  31. virtual ~VulkanResource();
  32. /**
  33. * Notifies the resource that it is currently bound to a command buffer. Buffer hasn't yet been submitted so the
  34. * resource isn't being used on the GPU yet.
  35. *
  36. * Must eventually be followed by a notifyUsed() or notifyUnbound().
  37. */
  38. void notifyBound();
  39. /**
  40. * Notifies the resource that it is currently being used on the provided command buffer. This means the command
  41. * buffer has actually been submitted to the queue and the resource is used by the GPU.
  42. *
  43. * A resource can only be used by a single command buffer at a time unless resource concurrency is enabled.
  44. *
  45. * Must follow a notifyBound(). Must eventually be followed by a notifyDone().
  46. */
  47. void notifyUsed(VulkanCmdBuffer* buffer, VulkanUseFlags useFlags);
  48. /**
  49. * Notifies the resource that it is no longer used by on the GPU. This makes the resource usable on other command
  50. * buffers again.
  51. *
  52. * Must follow a notifyUsed().
  53. */
  54. void notifyDone();
  55. /**
  56. * Notifies the resource that it is no longer queued on the command buffer. This is similar to notifyDone(), but
  57. * should only be called if resource never got submitted to the GPU (e.g. command buffer was destroyed before
  58. * being submitted).
  59. *
  60. * Must follow a notifyBound() if notifyUsed() wasn't called.
  61. */
  62. void notifyUnbound();
  63. /**
  64. * Checks is the resource currently used on a device.
  65. *
  66. * @note Resource usage is only checked at certain points of the program. This means the resource could be
  67. * done on the device but this method may still report true. If you need to know the latest state
  68. * call VulkanCommandBufferManager::refreshStates() before checking for usage.
  69. */
  70. bool isUsed() const { Lock(mMutex); return mNumUsedHandles > 0; }
  71. /**
  72. * Checks is the resource currently bound to any command buffer.
  73. *
  74. * @note Resource usage is only checked at certain points of the program. This means the resource could be
  75. * done on the device but this method may still report true. If you need to know the latest state
  76. * call VulkanCommandBufferManager::refreshStates() before checking for usage.
  77. */
  78. bool isBound() const { Lock(mMutex); return mNumBoundHandles > 0; }
  79. /**
  80. * Returns the queue family the resource is currently owned by. Returns -1 if owned by no queue.
  81. *
  82. * @note If resource concurrency is enabled, then this value has no meaning as the resource can be used on
  83. * multiple queue families at once.
  84. */
  85. UINT32 getQueueFamily() const { Lock(mMutex); return mQueueFamily; }
  86. /** Returns true if the resource is only allowed to be used by a single queue family at once. */
  87. bool isExclusive() const { Lock(mMutex); return mState != State::Shared; }
  88. /**
  89. * Destroys the resource and frees its memory. If the resource is currently being used on a device, the
  90. * destruction is delayed until the device is done with it.
  91. */
  92. void destroy();
  93. protected:
  94. /** Possible states of this object. */
  95. enum class State
  96. {
  97. Normal,
  98. Shared,
  99. Destroyed
  100. };
  101. VulkanResourceManager* mOwner;
  102. UINT32 mQueueFamily;
  103. State mState;
  104. VulkanUseFlags mUseFlags;
  105. UINT32 mNumUsedHandles;
  106. UINT32 mNumBoundHandles;
  107. Mutex mMutex;
  108. };
  109. /**
  110. * Creates and destroys annd VulkanResource%s on a single device.
  111. *
  112. * @note Thread safe
  113. */
  114. class VulkanResourceManager
  115. {
  116. public:
  117. VulkanResourceManager(VulkanDevice& device);
  118. ~VulkanResourceManager();
  119. /**
  120. * Creates a new Vulkan resource of the specified type. User must call VulkanResource::destroy() when done using
  121. * the resource.
  122. */
  123. template<class Type, class... Args>
  124. Type* create(Args &&...args)
  125. {
  126. Type* resource = new (bs_alloc(sizeof(Type))) Type(this, std::forward<Args>(args)...);
  127. #if BS_DEBUG_MODE
  128. Lock lock(mMutex);
  129. mResources.insert(resource);
  130. #endif
  131. return resource;
  132. }
  133. /** Returns the device that owns this manager. */
  134. VulkanDevice& getDevice() const { return mDevice; }
  135. private:
  136. friend VulkanResource;
  137. /**
  138. * Destroys a previously created Vulkan resource. Caller must ensure the resource is not currently being used
  139. * on the device.
  140. */
  141. void destroy(VulkanResource* resource);
  142. VulkanDevice& mDevice;
  143. #if BS_DEBUG_MODE
  144. UnorderedSet<VulkanResource*> mResources;
  145. Mutex mMutex;
  146. #endif
  147. };
  148. /** @} */
  149. }