BsVulkanCommandBuffer.h 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  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 "BsCommandBuffer.h"
  6. #include "BsVulkanRenderAPI.h"
  7. #include "BsVulkanResource.h"
  8. namespace BansheeEngine
  9. {
  10. class VulkanImage;
  11. /** @addtogroup Vulkan
  12. * @{
  13. */
  14. class VulkanCmdBuffer;
  15. #define BS_MAX_VULKAN_CB_PER_QUEUE_FAMILY BS_MAX_QUEUES_PER_TYPE * 32
  16. /** Pool that allocates and distributes Vulkan command buffers. */
  17. class VulkanCmdBufferPool
  18. {
  19. public:
  20. VulkanCmdBufferPool(VulkanDevice& device);
  21. ~VulkanCmdBufferPool();
  22. /**
  23. * Attempts to find a free command buffer, or creates a new one if not found. Caller must guarantee the provided
  24. * queue family is valid.
  25. */
  26. VulkanCmdBuffer* getBuffer(UINT32 queueFamily, bool secondary);
  27. private:
  28. /** Command buffer pool and related information. */
  29. struct PoolInfo
  30. {
  31. VkCommandPool pool = VK_NULL_HANDLE;
  32. VulkanCmdBuffer* buffers[BS_MAX_VULKAN_CB_PER_QUEUE_FAMILY];
  33. UINT32 queueFamily = -1;
  34. };
  35. /** Creates a new command buffer. */
  36. VulkanCmdBuffer* createBuffer(UINT32 queueFamily, bool secondary);
  37. VulkanDevice& mDevice;
  38. UnorderedMap<UINT32, PoolInfo> mPools;
  39. UINT32 mNextId;
  40. };
  41. /**
  42. * Represents a direct wrapper over an internal Vulkan command buffer. This is unlike VulkanCommandBuffer which is a
  43. * higher level class, and it allows for re-use by internally using multiple low-level command buffers.
  44. */
  45. class VulkanCmdBuffer
  46. {
  47. /** Possible states a command buffer can be in. */
  48. enum class State
  49. {
  50. /** Buffer is ready to be re-used. */
  51. Ready,
  52. /** Buffer is currently recording commands, but isn't recording a render pass. */
  53. Recording,
  54. /** Buffer is currently recording render pass commands. */
  55. RecordingRenderPass,
  56. /** Buffer is done recording but hasn't been submitted. */
  57. RecordingDone,
  58. /** Buffer is done recording and is currently submitted on a queue. */
  59. Submitted
  60. };
  61. public:
  62. VulkanCmdBuffer(VulkanDevice& device, UINT32 id, VkCommandPool pool, UINT32 queueFamily, bool secondary);
  63. ~VulkanCmdBuffer();
  64. /** Returns an unique identifier of this command buffer. */
  65. UINT32 getId() const { return mId; }
  66. /** Returns the index of the queue family this command buffer is executing on. */
  67. UINT32 getQueueFamily() const { return mQueueFamily; }
  68. /** Returns the index of the device this command buffer will execute on. */
  69. UINT32 getDeviceIdx() const;
  70. /** Makes the command buffer ready to start recording commands. */
  71. void begin();
  72. /** Ends command buffer command recording (as started with begin()). */
  73. void end();
  74. /** Begins render pass recording. Must be called within begin()/end() calls. */
  75. void beginRenderPass();
  76. /** Ends render pass recording (as started with beginRenderPass(). */
  77. void endRenderPass();
  78. /**
  79. * Submits the command buffer for execution.
  80. *
  81. * @param[in] queue Queue to submit the command buffer on.
  82. * @param[in] queueIdx Index of the queue the command buffer was submitted on. Note that this may be different
  83. * from the actual VulkanQueue index since multiple command buffer queue indices can map
  84. * to the same queue.
  85. * @param[in] syncMask Mask that controls which other command buffers does this command buffer depend upon
  86. * (if any). See description of @p syncMask parameter in RenderAPICore::executeCommands().
  87. */
  88. void submit(VulkanQueue* queue, UINT32 queueIdx, UINT32 syncMask);
  89. /** Returns the handle to the internal Vulkan command buffer wrapped by this object. */
  90. VkCommandBuffer getHandle() const { return mCmdBuffer; }
  91. /** Returns a fence that can be used for tracking when the command buffer is done executing. */
  92. VkFence getFence() const { return mFence; }
  93. /**
  94. * Returns a semaphore that may be used for synchronizing execution between command buffers executing on different
  95. * queues.
  96. */
  97. VkSemaphore getSemaphore() const { return mSemaphore; }
  98. /** Returns true if the command buffer is currently being processed by the device. */
  99. bool isSubmitted() const { return mState == State::Submitted; }
  100. /** Returns true if the command buffer is ready to be submitted to a queue. */
  101. bool isReadyForSubmit() const { return mState == State::RecordingDone; }
  102. /** Returns true if the command buffer is currently recording a render pass. */
  103. bool isInRenderPass() const { return mState == State::RecordingRenderPass; }
  104. /** Returns a counter that gets incremented whenever the command buffer is done executing. */
  105. UINT32 getFenceCounter() const { return mFenceCounter; }
  106. /** Checks the internal fence and changes command buffer state if done executing. */
  107. void refreshFenceStatus();
  108. /**
  109. * Assigns a render target the the command buffer. This render target's framebuffer and render pass will be used
  110. * when beginRenderPass() is called. Command buffer must not be currently recording a render pass.
  111. */
  112. void setRenderTarget(const SPtr<RenderTargetCore>& rt);
  113. /**
  114. * Lets the command buffer know that the provided resource has been queued on it, and will be used by the
  115. * device when the command buffer is submitted. If a resource is an image or a buffer use the more specific
  116. * registerResource() overload.
  117. */
  118. void registerResource(VulkanResource* res, VulkanUseFlags flags);
  119. /**
  120. * Lets the command buffer know that the provided image resource has been queued on it, and will be used by the
  121. * device when the command buffer is submitted. If a resource is an image or a buffer use the more specific
  122. * registerResource() overload.
  123. */
  124. void registerResource(VulkanImage* res, VkAccessFlags accessFlags, VkImageLayout layout,
  125. const VkImageSubresourceRange& range, VulkanUseFlags flags);
  126. /**
  127. * Lets the command buffer know that the provided image resource has been queued on it, and will be used by the
  128. * device when the command buffer is submitted. If a resource is an image or a buffer use the more specific
  129. * registerResource() overload.
  130. */
  131. void registerResource(VulkanBuffer* res, VkAccessFlags accessFlags, VulkanUseFlags flags);
  132. private:
  133. friend class VulkanCmdBufferPool;
  134. friend class VulkanCommandBuffer;
  135. /** Contains information about a single Vulkan resource bound/used on this command buffer. */
  136. struct ResourceUseHandle
  137. {
  138. bool used;
  139. VulkanUseFlags flags;
  140. };
  141. /** Contains information about a single Vulkan buffer resource bound/used on this command buffer. */
  142. struct BufferInfo
  143. {
  144. VkAccessFlags accessFlags;
  145. ResourceUseHandle useHandle;
  146. };
  147. /** Contains information about a single Vulkan image resource bound/used on this command buffer. */
  148. struct ImageInfo
  149. {
  150. VkAccessFlags accessFlags;
  151. VkImageLayout layout;
  152. VkImageSubresourceRange range;
  153. ResourceUseHandle useHandle;
  154. };
  155. UINT32 mId;
  156. UINT32 mQueueFamily;
  157. State mState;
  158. VulkanDevice& mDevice;
  159. VkCommandPool mPool;
  160. VkCommandBuffer mCmdBuffer;
  161. VkFence mFence;
  162. VkSemaphore mSemaphore;
  163. UINT32 mFenceCounter;
  164. VkFramebuffer mFramebuffer;
  165. VkRenderPass mRenderPass;
  166. VkSemaphore mPresentSemaphore;
  167. UINT32 mRenderTargetWidth;
  168. UINT32 mRenderTargetHeight;
  169. UnorderedMap<VulkanResource*, ResourceUseHandle> mResources;
  170. UnorderedMap<VulkanResource*, ImageInfo> mImages;
  171. UnorderedMap<VulkanResource*, BufferInfo> mBuffers;
  172. UINT32 mGlobalQueueIdx;
  173. VkSemaphore mSemaphoresTemp[BS_MAX_UNIQUE_QUEUES + 1]; // +1 for present semaphore
  174. UnorderedMap<UINT32, TransitionInfo> mTransitionInfoTemp;
  175. };
  176. /** CommandBuffer implementation for Vulkan. */
  177. class VulkanCommandBuffer : public CommandBuffer
  178. {
  179. public:
  180. /**
  181. * Submits the command buffer for execution.
  182. *
  183. * @param[in] syncMask Mask that controls which other command buffers does this command buffer depend upon
  184. * (if any). See description of @p syncMask parameter in RenderAPICore::executeCommands().
  185. */
  186. void submit(UINT32 syncMask);
  187. /**
  188. * Returns the internal command buffer.
  189. *
  190. * @note This buffer will change after a submit() call.
  191. */
  192. VulkanCmdBuffer* getInternal() const { return mBuffer; }
  193. private:
  194. friend class VulkanCommandBufferManager;
  195. VulkanCommandBuffer(VulkanDevice& device, GpuQueueType type, UINT32 deviceIdx, UINT32 queueIdx,
  196. bool secondary);
  197. /**
  198. * Tasks the command buffer to find a new internal command buffer. Call this after the command buffer has been
  199. * submitted to a queue (it's not allowed to be used until the queue is done with it).
  200. */
  201. void acquireNewBuffer();
  202. VulkanCmdBuffer* mBuffer;
  203. VulkanDevice& mDevice;
  204. VulkanQueue* mQueue;
  205. UINT32 mIdMask;
  206. VkSemaphore mSemaphoresTemp[BS_MAX_UNIQUE_QUEUES];
  207. UnorderedMap<UINT32, TransitionInfo> mTransitionInfoTemp;
  208. };
  209. /** @} */
  210. }