123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210 |
- // Copyright (c) 2016 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #ifndef GPU_VULKAN_VULKAN_SWAP_CHAIN_H_
- #define GPU_VULKAN_VULKAN_SWAP_CHAIN_H_
- #include <vulkan/vulkan_core.h>
- #include <memory>
- #include <vector>
- #include "base/callback.h"
- #include "base/component_export.h"
- #include "base/containers/circular_deque.h"
- #include "base/memory/raw_ptr.h"
- #include "base/memory/scoped_refptr.h"
- #include "base/synchronization/condition_variable.h"
- #include "base/synchronization/lock.h"
- #include "base/threading/thread_checker.h"
- #include "third_party/abseil-cpp/absl/types/optional.h"
- #include "ui/gfx/geometry/rect.h"
- #include "ui/gfx/geometry/size.h"
- #include "ui/gfx/swap_result.h"
- namespace gpu {
- class VulkanDeviceQueue;
- class COMPONENT_EXPORT(VULKAN) VulkanSwapChain {
- public:
- class COMPONENT_EXPORT(VULKAN) ScopedWrite {
- public:
- explicit ScopedWrite(VulkanSwapChain* swap_chain);
- ScopedWrite(ScopedWrite&& other);
- ~ScopedWrite();
- ScopedWrite(const ScopedWrite&) = delete;
- ScopedWrite& operator=(const ScopedWrite&) = delete;
- const ScopedWrite& operator=(ScopedWrite&& other);
- void Reset();
- bool success() const { return success_; }
- VkImage image() const { return image_; }
- uint32_t image_index() const { return image_index_; }
- VkImageLayout image_layout() const { return image_layout_; }
- VkImageUsageFlags image_usage() const { return image_usage_; }
- VkSemaphore begin_semaphore() const { return begin_semaphore_; }
- VkSemaphore end_semaphore() const { return end_semaphore_; }
- private:
- VulkanSwapChain* swap_chain_ = nullptr;
- bool success_ = false;
- VkImage image_ = VK_NULL_HANDLE;
- uint32_t image_index_ = 0;
- VkImageLayout image_layout_ = VK_IMAGE_LAYOUT_UNDEFINED;
- VkImageUsageFlags image_usage_ = 0;
- VkSemaphore begin_semaphore_ = VK_NULL_HANDLE;
- VkSemaphore end_semaphore_ = VK_NULL_HANDLE;
- };
- explicit VulkanSwapChain(uint64_t acquire_next_image_timeout_ns);
- VulkanSwapChain(const VulkanSwapChain&) = delete;
- VulkanSwapChain& operator=(const VulkanSwapChain&) = delete;
- ~VulkanSwapChain();
- // min_image_count is the minimum number of presentable images.
- bool Initialize(VulkanDeviceQueue* device_queue,
- VkSurfaceKHR surface,
- const VkSurfaceFormatKHR& surface_format,
- const gfx::Size& image_size,
- uint32_t min_image_count,
- VkImageUsageFlags image_usage_flags,
- VkSurfaceTransformFlagBitsKHR pre_transform,
- VkCompositeAlphaFlagBitsKHR composite_alpha,
- std::unique_ptr<VulkanSwapChain> old_swap_chain);
- // Destroy() should be called when all related GPU tasks have been finished.
- void Destroy();
- // Present the current buffer.
- gfx::SwapResult PostSubBuffer(const gfx::Rect& rect);
- using PostSubBufferCompletionCallback =
- base::OnceCallback<void(gfx::SwapResult)>;
- void PostSubBufferAsync(const gfx::Rect& rect,
- PostSubBufferCompletionCallback callback);
- uint32_t num_images() const {
- // size of |images_| will not be changed after initializing, so it is safe
- // to read it here.
- return static_cast<uint32_t>(TS_UNCHECKED_READ(images_).size());
- }
- const gfx::Size& size() const {
- // |size_| is never changed after initialization.
- return size_;
- }
- uint32_t current_image_index() const {
- base::AutoLock auto_lock(lock_);
- DCHECK(acquired_image_);
- return *acquired_image_;
- }
- VkResult state() const {
- base::AutoLock auto_lock(lock_);
- return state_;
- }
- private:
- struct ImageData {
- VkImage image = VK_NULL_HANDLE;
- VkImageLayout image_layout = VK_IMAGE_LAYOUT_UNDEFINED;
- // Semaphore used for vkAcquireNextImageKHR()
- VkSemaphore acquire_semaphore = VK_NULL_HANDLE;
- // Semaphore used for vkQueuePresentKHR()
- VkSemaphore present_semaphore = VK_NULL_HANDLE;
- };
- bool InitializeSwapChain(VkSurfaceKHR surface,
- const VkSurfaceFormatKHR& surface_format,
- const gfx::Size& image_size,
- uint32_t min_image_count,
- VkImageUsageFlags image_usage_flags,
- VkSurfaceTransformFlagBitsKHR pre_transform,
- VkCompositeAlphaFlagBitsKHR composite_alpha,
- std::unique_ptr<VulkanSwapChain> old_swap_chain)
- EXCLUSIVE_LOCKS_REQUIRED(lock_);
- void DestroySwapChain() EXCLUSIVE_LOCKS_REQUIRED(lock_);
- bool InitializeSwapImages(const VkSurfaceFormatKHR& surface_format)
- EXCLUSIVE_LOCKS_REQUIRED(lock_);
- void DestroySwapImages() EXCLUSIVE_LOCKS_REQUIRED(lock_);
- bool BeginWriteCurrentImage(VkImage* image,
- uint32_t* image_index,
- VkImageLayout* layout,
- VkImageUsageFlags* usage,
- VkSemaphore* begin_semaphore,
- VkSemaphore* end_semaphore);
- void EndWriteCurrentImage();
- bool PresentBuffer(const gfx::Rect& rect) EXCLUSIVE_LOCKS_REQUIRED(lock_);
- bool AcquireNextImage() EXCLUSIVE_LOCKS_REQUIRED(lock_);
- // Wait until PostSubBufferAsync() is finished on ThreadPool.
- void WaitUntilPostSubBufferAsyncFinished() EXCLUSIVE_LOCKS_REQUIRED(lock_);
- bool GetOrCreateSemaphores(VkSemaphore* acquire_semaphore,
- VkSemaphore* present_semaphore)
- EXCLUSIVE_LOCKS_REQUIRED(lock_);
- void ReturnSemaphores(VkSemaphore acquire_semaphore,
- VkSemaphore present_semaphore)
- EXCLUSIVE_LOCKS_REQUIRED(lock_);
- mutable base::Lock lock_;
- const uint64_t acquire_next_image_timeout_ns_;
- raw_ptr<VulkanDeviceQueue> device_queue_ = nullptr;
- bool is_incremental_present_supported_ = false;
- VkSwapchainKHR swap_chain_ GUARDED_BY(lock_) = VK_NULL_HANDLE;
- gfx::Size size_;
- // Images in the swap chain.
- std::vector<ImageData> images_ GUARDED_BY(lock_);
- VkImageUsageFlags image_usage_ = 0;
- // True if BeginWriteCurrentImage() is called, but EndWriteCurrentImage() is
- // not.
- bool is_writing_ GUARDED_BY(lock_) = false;
- // True if the current image is new required, and BeginWriteCurrentImage() and
- // EndWriteCurrentImage() pair are not called.
- bool new_acquired_ GUARDED_BY(lock_) = true;
- // Condition variable is signalled when a PostSubBufferAsync() is finished.
- base::ConditionVariable condition_variable_{&lock_};
- // True if there is pending post sub buffer in the fly.
- bool has_pending_post_sub_buffer_ GUARDED_BY(lock_) = false;
- // The current swapchain state_.
- VkResult state_ GUARDED_BY(lock_) = VK_SUCCESS;
- // Acquired images queue.
- absl::optional<uint32_t> acquired_image_ GUARDED_BY(lock_);
- bool destroy_swapchain_will_hang_ = false;
- // For executing PosSubBufferAsync tasks off the GPU main thread.
- scoped_refptr<base::SequencedTaskRunner> post_sub_buffer_task_runner_;
- // Available semaphores can be reused when waiting semaphores is over.
- struct PendingSemaphores {
- VkSemaphore acquire_semaphore = VK_NULL_HANDLE;
- VkSemaphore present_semaphore = VK_NULL_HANDLE;
- };
- base::circular_deque<PendingSemaphores> pending_semaphores_queue_
- GUARDED_BY(lock_);
- THREAD_CHECKER(thread_checker_);
- };
- } // namespace gpu
- #endif // GPU_VULKAN_VULKAN_SWAP_CHAIN_H_
|