BsVulkanCommandBuffer.h 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  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. /** @addtogroup Vulkan
  11. * @{
  12. */
  13. class VulkanCmdBuffer;
  14. #define BS_MAX_VULKAN_COMMAND_BUFFERS_PER_QUEUE 32
  15. /** Pool that allocates and distributes Vulkan command buffers. */
  16. class VulkanCmdBufferPool
  17. {
  18. public:
  19. VulkanCmdBufferPool(VulkanDevice& device);
  20. ~VulkanCmdBufferPool();
  21. /** Attempts to find a free command buffer, or creates a new one if not found. */
  22. VulkanCmdBuffer* getBuffer(GpuQueueType type, UINT32 queueIdx, bool secondary);
  23. private:
  24. /** Command buffer pool and related information. */
  25. struct PoolInfo
  26. {
  27. VkCommandPool pool = VK_NULL_HANDLE;
  28. UINT32 queueFamily = -1;
  29. };
  30. /** Creates a new command buffer. */
  31. VulkanCmdBuffer* createBuffer(GpuQueueType type, bool secondary);
  32. /** Returns a Vulkan command pool for the specified queue type. */
  33. const PoolInfo& getPool(GpuQueueType type);
  34. VulkanDevice& mDevice;
  35. PoolInfo mPools[GQT_COUNT];
  36. VulkanCmdBuffer* mBuffers[GQT_COUNT][BS_MAX_QUEUES_PER_TYPE][BS_MAX_VULKAN_COMMAND_BUFFERS_PER_QUEUE];
  37. UINT32 mNextId;
  38. };
  39. /**
  40. * Represents a direct wrapper over an internal Vulkan command buffer. This is unlike VulkanCommandBuffer which is a
  41. * higher level class, and it allows for re-use by internally using multiple low-level command buffers.
  42. */
  43. class VulkanCmdBuffer
  44. {
  45. /** Possible states a command buffer can be in. */
  46. enum class State
  47. {
  48. /** Buffer is ready to be re-used. */
  49. Ready,
  50. /** Buffer is currently recording commands, but isn't recording a render pass. */
  51. Recording,
  52. /** Buffer is currently recording render pass commands. */
  53. RecordingRenderPass,
  54. /** Buffer is done recording but hasn't been submitted. */
  55. RecordingDone,
  56. /** Buffer is done recording and is currently submitted on a queue. */
  57. Submitted
  58. };
  59. public:
  60. VulkanCmdBuffer(VulkanDevice& device, UINT32 id, VkCommandPool pool, UINT32 queueFamily, bool secondary);
  61. ~VulkanCmdBuffer();
  62. /** Returns an unique identifier of this command buffer. */
  63. UINT32 getId() const { return mId; }
  64. /** Returns the index of the queue family this command buffer is executing on. */
  65. UINT32 getQueueFamily() const { return mQueueFamily; }
  66. /** Makes the command buffer ready to start recording commands. */
  67. void begin();
  68. /** Ends command buffer command recording (as started with begin()). */
  69. void end();
  70. /** Begins render pass recording. Must be called within begin()/end() calls. */
  71. void beginRenderPass();
  72. /** Ends render pass recording (as started with beginRenderPass(). */
  73. void endRenderPass();
  74. /** Returns the handle to the internal Vulkan command buffer wrapped by this object. */
  75. VkCommandBuffer getHandle() const { return mCmdBuffer; }
  76. /** Returns a fence that can be used for tracking when the command buffer is done executing. */
  77. VkFence getFence() const { return mFence; }
  78. /**
  79. * Returns a semaphore that may be used for synchronizing execution between command buffers executing on different
  80. * queues.
  81. */
  82. VkSemaphore getSemaphore() const { return mSemaphore; }
  83. /** Returns true if the command buffer is currently being processed by the device. */
  84. bool isSubmitted() const { return mState == State::Submitted; }
  85. /** Returns true if the command buffer is ready to be submitted to a queue. */
  86. bool isReadyForSubmit() const { return mState == State::RecordingDone; }
  87. /** Returns a counter that gets incremented whenever the command buffer is done executing. */
  88. UINT32 getFenceCounter() const { return mFenceCounter; }
  89. /** Checks the internal fence and changes command buffer state if done executing. */
  90. void refreshFenceStatus();
  91. /**
  92. * Lets the command buffer know that the provided resource has been queued on it, and will be used by the
  93. * device when the command buffer is submitted.
  94. */
  95. void registerResource(VulkanResource* res, VulkanUseFlags flags);
  96. private:
  97. friend class VulkanCmdBufferPool;
  98. friend class VulkanCommandBuffer;
  99. /** Information about a resource currently queued for use on the command buffer. */
  100. struct ResourceInfo
  101. {
  102. VulkanUseFlags flags;
  103. };
  104. /** Called after the buffer has been submitted to the queue. */
  105. void notifySubmit();
  106. UINT32 mId;
  107. UINT32 mQueueFamily;
  108. State mState;
  109. VulkanDevice& mDevice;
  110. VkCommandPool mPool;
  111. VkCommandBuffer mCmdBuffer;
  112. VkFence mFence;
  113. VkSemaphore mSemaphore;
  114. UINT32 mFenceCounter;
  115. UnorderedMap<VulkanResource*, ResourceInfo> mResources;
  116. };
  117. /** CommandBuffer implementation for Vulkan. */
  118. class VulkanCommandBuffer : public CommandBuffer
  119. {
  120. public:
  121. /**
  122. * Submits the command buffer for execution.
  123. *
  124. * @param[in] syncMask Mask that controls which other command buffers does this command buffer depend upon
  125. * (if any). See description of @p syncMask parameter in RenderAPICore::executeCommands().
  126. */
  127. void submit(UINT32 syncMask);
  128. /** Checks if the submitted buffer finished executing, and updates state if it has. */
  129. void refreshSubmitStatus();
  130. private:
  131. friend class VulkanCommandBufferManager;
  132. VulkanCommandBuffer(VulkanDevice& device, UINT32 id, GpuQueueType type, UINT32 deviceIdx, UINT32 queueIdx,
  133. bool secondary);
  134. /**
  135. * Tasks the command buffer to find a new internal command buffer. Call this after the command buffer has been
  136. * submitted to a queue (it's not allowed to be used until the queue is done with it).
  137. */
  138. void acquireNewBuffer();
  139. VulkanCmdBuffer* mBuffer;
  140. VulkanCmdBuffer* mSubmittedBuffer;
  141. VulkanDevice& mDevice;
  142. VulkanQueue* mQueue;
  143. UINT32 mIdMask;
  144. VkSemaphore mSemaphoresTemp[BS_MAX_COMMAND_BUFFERS];
  145. };
  146. /** @} */
  147. }