vulkan_swap_chain.h 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. // Copyright (c) 2016 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef GPU_VULKAN_VULKAN_SWAP_CHAIN_H_
  5. #define GPU_VULKAN_VULKAN_SWAP_CHAIN_H_
  6. #include <vulkan/vulkan_core.h>
  7. #include <memory>
  8. #include <vector>
  9. #include "base/callback.h"
  10. #include "base/component_export.h"
  11. #include "base/containers/circular_deque.h"
  12. #include "base/memory/raw_ptr.h"
  13. #include "base/memory/scoped_refptr.h"
  14. #include "base/synchronization/condition_variable.h"
  15. #include "base/synchronization/lock.h"
  16. #include "base/threading/thread_checker.h"
  17. #include "third_party/abseil-cpp/absl/types/optional.h"
  18. #include "ui/gfx/geometry/rect.h"
  19. #include "ui/gfx/geometry/size.h"
  20. #include "ui/gfx/swap_result.h"
  21. namespace gpu {
  22. class VulkanDeviceQueue;
  23. class COMPONENT_EXPORT(VULKAN) VulkanSwapChain {
  24. public:
  25. class COMPONENT_EXPORT(VULKAN) ScopedWrite {
  26. public:
  27. explicit ScopedWrite(VulkanSwapChain* swap_chain);
  28. ScopedWrite(ScopedWrite&& other);
  29. ~ScopedWrite();
  30. ScopedWrite(const ScopedWrite&) = delete;
  31. ScopedWrite& operator=(const ScopedWrite&) = delete;
  32. const ScopedWrite& operator=(ScopedWrite&& other);
  33. void Reset();
  34. bool success() const { return success_; }
  35. VkImage image() const { return image_; }
  36. uint32_t image_index() const { return image_index_; }
  37. VkImageLayout image_layout() const { return image_layout_; }
  38. VkImageUsageFlags image_usage() const { return image_usage_; }
  39. VkSemaphore begin_semaphore() const { return begin_semaphore_; }
  40. VkSemaphore end_semaphore() const { return end_semaphore_; }
  41. private:
  42. VulkanSwapChain* swap_chain_ = nullptr;
  43. bool success_ = false;
  44. VkImage image_ = VK_NULL_HANDLE;
  45. uint32_t image_index_ = 0;
  46. VkImageLayout image_layout_ = VK_IMAGE_LAYOUT_UNDEFINED;
  47. VkImageUsageFlags image_usage_ = 0;
  48. VkSemaphore begin_semaphore_ = VK_NULL_HANDLE;
  49. VkSemaphore end_semaphore_ = VK_NULL_HANDLE;
  50. };
  51. explicit VulkanSwapChain(uint64_t acquire_next_image_timeout_ns);
  52. VulkanSwapChain(const VulkanSwapChain&) = delete;
  53. VulkanSwapChain& operator=(const VulkanSwapChain&) = delete;
  54. ~VulkanSwapChain();
  55. // min_image_count is the minimum number of presentable images.
  56. bool Initialize(VulkanDeviceQueue* device_queue,
  57. VkSurfaceKHR surface,
  58. const VkSurfaceFormatKHR& surface_format,
  59. const gfx::Size& image_size,
  60. uint32_t min_image_count,
  61. VkImageUsageFlags image_usage_flags,
  62. VkSurfaceTransformFlagBitsKHR pre_transform,
  63. VkCompositeAlphaFlagBitsKHR composite_alpha,
  64. std::unique_ptr<VulkanSwapChain> old_swap_chain);
  65. // Destroy() should be called when all related GPU tasks have been finished.
  66. void Destroy();
  67. // Present the current buffer.
  68. gfx::SwapResult PostSubBuffer(const gfx::Rect& rect);
  69. using PostSubBufferCompletionCallback =
  70. base::OnceCallback<void(gfx::SwapResult)>;
  71. void PostSubBufferAsync(const gfx::Rect& rect,
  72. PostSubBufferCompletionCallback callback);
  73. uint32_t num_images() const {
  74. // size of |images_| will not be changed after initializing, so it is safe
  75. // to read it here.
  76. return static_cast<uint32_t>(TS_UNCHECKED_READ(images_).size());
  77. }
  78. const gfx::Size& size() const {
  79. // |size_| is never changed after initialization.
  80. return size_;
  81. }
  82. uint32_t current_image_index() const {
  83. base::AutoLock auto_lock(lock_);
  84. DCHECK(acquired_image_);
  85. return *acquired_image_;
  86. }
  87. VkResult state() const {
  88. base::AutoLock auto_lock(lock_);
  89. return state_;
  90. }
  91. private:
  92. struct ImageData {
  93. VkImage image = VK_NULL_HANDLE;
  94. VkImageLayout image_layout = VK_IMAGE_LAYOUT_UNDEFINED;
  95. // Semaphore used for vkAcquireNextImageKHR()
  96. VkSemaphore acquire_semaphore = VK_NULL_HANDLE;
  97. // Semaphore used for vkQueuePresentKHR()
  98. VkSemaphore present_semaphore = VK_NULL_HANDLE;
  99. };
  100. bool InitializeSwapChain(VkSurfaceKHR surface,
  101. const VkSurfaceFormatKHR& surface_format,
  102. const gfx::Size& image_size,
  103. uint32_t min_image_count,
  104. VkImageUsageFlags image_usage_flags,
  105. VkSurfaceTransformFlagBitsKHR pre_transform,
  106. VkCompositeAlphaFlagBitsKHR composite_alpha,
  107. std::unique_ptr<VulkanSwapChain> old_swap_chain)
  108. EXCLUSIVE_LOCKS_REQUIRED(lock_);
  109. void DestroySwapChain() EXCLUSIVE_LOCKS_REQUIRED(lock_);
  110. bool InitializeSwapImages(const VkSurfaceFormatKHR& surface_format)
  111. EXCLUSIVE_LOCKS_REQUIRED(lock_);
  112. void DestroySwapImages() EXCLUSIVE_LOCKS_REQUIRED(lock_);
  113. bool BeginWriteCurrentImage(VkImage* image,
  114. uint32_t* image_index,
  115. VkImageLayout* layout,
  116. VkImageUsageFlags* usage,
  117. VkSemaphore* begin_semaphore,
  118. VkSemaphore* end_semaphore);
  119. void EndWriteCurrentImage();
  120. bool PresentBuffer(const gfx::Rect& rect) EXCLUSIVE_LOCKS_REQUIRED(lock_);
  121. bool AcquireNextImage() EXCLUSIVE_LOCKS_REQUIRED(lock_);
  122. // Wait until PostSubBufferAsync() is finished on ThreadPool.
  123. void WaitUntilPostSubBufferAsyncFinished() EXCLUSIVE_LOCKS_REQUIRED(lock_);
  124. bool GetOrCreateSemaphores(VkSemaphore* acquire_semaphore,
  125. VkSemaphore* present_semaphore)
  126. EXCLUSIVE_LOCKS_REQUIRED(lock_);
  127. void ReturnSemaphores(VkSemaphore acquire_semaphore,
  128. VkSemaphore present_semaphore)
  129. EXCLUSIVE_LOCKS_REQUIRED(lock_);
  130. mutable base::Lock lock_;
  131. const uint64_t acquire_next_image_timeout_ns_;
  132. raw_ptr<VulkanDeviceQueue> device_queue_ = nullptr;
  133. bool is_incremental_present_supported_ = false;
  134. VkSwapchainKHR swap_chain_ GUARDED_BY(lock_) = VK_NULL_HANDLE;
  135. gfx::Size size_;
  136. // Images in the swap chain.
  137. std::vector<ImageData> images_ GUARDED_BY(lock_);
  138. VkImageUsageFlags image_usage_ = 0;
  139. // True if BeginWriteCurrentImage() is called, but EndWriteCurrentImage() is
  140. // not.
  141. bool is_writing_ GUARDED_BY(lock_) = false;
  142. // True if the current image is new required, and BeginWriteCurrentImage() and
  143. // EndWriteCurrentImage() pair are not called.
  144. bool new_acquired_ GUARDED_BY(lock_) = true;
  145. // Condition variable is signalled when a PostSubBufferAsync() is finished.
  146. base::ConditionVariable condition_variable_{&lock_};
  147. // True if there is pending post sub buffer in the fly.
  148. bool has_pending_post_sub_buffer_ GUARDED_BY(lock_) = false;
  149. // The current swapchain state_.
  150. VkResult state_ GUARDED_BY(lock_) = VK_SUCCESS;
  151. // Acquired images queue.
  152. absl::optional<uint32_t> acquired_image_ GUARDED_BY(lock_);
  153. bool destroy_swapchain_will_hang_ = false;
  154. // For executing PosSubBufferAsync tasks off the GPU main thread.
  155. scoped_refptr<base::SequencedTaskRunner> post_sub_buffer_task_runner_;
  156. // Available semaphores can be reused when waiting semaphores is over.
  157. struct PendingSemaphores {
  158. VkSemaphore acquire_semaphore = VK_NULL_HANDLE;
  159. VkSemaphore present_semaphore = VK_NULL_HANDLE;
  160. };
  161. base::circular_deque<PendingSemaphores> pending_semaphores_queue_
  162. GUARDED_BY(lock_);
  163. THREAD_CHECKER(thread_checker_);
  164. };
  165. } // namespace gpu
  166. #endif // GPU_VULKAN_VULKAN_SWAP_CHAIN_H_