BsVulkanResource.h 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  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. /** Types of VulkanResource. */
  22. enum class VulkanResourceType
  23. {
  24. Generic,
  25. Image,
  26. Buffer
  27. };
  28. /**
  29. * Wraps one or multiple native Vulkan objects. Allows the object usage to be tracked in command buffers, handles
  30. * ownership transitions between different queues, and handles delayed object destruction.
  31. *
  32. * @note Thread safe
  33. */
  34. class VulkanResource
  35. {
  36. public:
  37. VulkanResource(VulkanResourceManager* owner, bool concurrency, VulkanResourceType type = VulkanResourceType::Generic);
  38. virtual ~VulkanResource();
  39. /**
  40. * Notifies the resource that it is currently bound to a command buffer. Buffer hasn't yet been submitted so the
  41. * resource isn't being used on the GPU yet.
  42. */
  43. void notifyBound();
  44. /**
  45. * Notifies the resource that it is currently being used on the provided command buffer. This means the command
  46. * buffer has actually been submitted to the queue and the resource is used by the GPU.
  47. *
  48. * A resource can only be used by a single command buffer at a time unless resource concurrency is enabled.
  49. */
  50. void notifyUsed(VulkanCmdBuffer* buffer, VulkanUseFlags useFlags);
  51. /**
  52. * Notifies the resource that it is no longer used by on the GPU. This makes the resource usable on other command
  53. * buffers again.
  54. */
  55. void notifyDone();
  56. /**
  57. * Checks is the resource currently used on a device.
  58. *
  59. * @note Resource usage is only checked at certain points of the program. This means the resource could be
  60. * done on the device but this method may still report true. If you need to know the latest state
  61. * call VulkanCommandBufferManager::refreshStates() before checking for usage.
  62. */
  63. bool isUsed() const { Lock(mMutex); return mNumUsedHandles > 0; }
  64. /**
  65. * Checks is the resource currently bound to any command buffer.
  66. *
  67. * @note Resource usage is only checked at certain points of the program. This means the resource could be
  68. * done on the device but this method may still report true. If you need to know the latest state
  69. * call VulkanCommandBufferManager::refreshStates() before checking for usage.
  70. */
  71. bool isBound() const { Lock(mMutex); return mNumBoundHandles > 0; }
  72. /** Returns the type of the object wrapped by the resource. */
  73. VulkanResourceType getType() const { Lock(mMutex); return mType; }
  74. /**
  75. * Returns the queue family the resource is currently owned by. Returns -1 if owned by no queue.
  76. *
  77. * @note If resource concurrency is enabled, then this value has no meaning as the resource can be used on
  78. * multiple queue families at once.
  79. */
  80. UINT32 getQueueFamily() const { Lock(mMutex); return mQueueFamily; }
  81. /** Returns true if the resource is only allowed to be used by a single queue family at once. */
  82. bool isExclusive() const { Lock(mMutex); return mState != State::Shared; }
  83. /**
  84. * Destroys the resource and frees its memory. If the resource is currently being used on a device, the
  85. * destruction is delayed until the device is done with it.
  86. */
  87. void destroy();
  88. protected:
  89. /** Possible states of this object. */
  90. enum class State
  91. {
  92. Normal,
  93. Shared,
  94. Destroyed
  95. };
  96. VulkanResourceManager* mOwner;
  97. UINT32 mQueueFamily;
  98. State mState;
  99. VulkanResourceType mType;
  100. VulkanUseFlags mUseFlags;
  101. UINT32 mNumUsedHandles;
  102. UINT32 mNumBoundHandles;
  103. Mutex mMutex;
  104. };
  105. /**
  106. * Creates and destroys annd VulkanResource%s on a single device.
  107. *
  108. * @note Thread safe
  109. */
  110. class VulkanResourceManager
  111. {
  112. public:
  113. VulkanResourceManager(VulkanDevice& device);
  114. ~VulkanResourceManager();
  115. /**
  116. * Creates a new Vulkan resource of the specified type. User must call VulkanResource::destroy() when done using
  117. * the resource.
  118. */
  119. template<class Type, class... Args>
  120. Type* create(Args &&...args)
  121. {
  122. Type* resource = new (bs_alloc(sizeof(Type))) Type(this, std::forward<Args>(args)...);
  123. #if BS_DEBUG_MODE
  124. Lock lock(mMutex);
  125. mResources.insert(resource);
  126. #endif
  127. return resource;
  128. }
  129. /** Returns the device that owns this manager. */
  130. VulkanDevice& getDevice() const { return mDevice; }
  131. private:
  132. friend VulkanResource;
  133. /**
  134. * Destroys a previously created Vulkan resource. Caller must ensure the resource is not currently being used
  135. * on the device.
  136. */
  137. void destroy(VulkanResource* resource);
  138. VulkanDevice& mDevice;
  139. #if BS_DEBUG_MODE
  140. UnorderedSet<VulkanResource*> mResources;
  141. Mutex mMutex;
  142. #endif
  143. };
  144. /** @} */
  145. }