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 
5 #ifndef GPU_VULKAN_VULKAN_SWAP_CHAIN_H_
6 #define GPU_VULKAN_VULKAN_SWAP_CHAIN_H_
7 
8 #include <vulkan/vulkan.h>
9 
10 #include <memory>
11 #include <vector>
12 
13 #include "base/containers/circular_deque.h"
14 #include "base/logging.h"
15 #include "base/optional.h"
16 #include "gpu/vulkan/vulkan_export.h"
17 #include "ui/gfx/geometry/rect.h"
18 #include "ui/gfx/geometry/size.h"
19 #include "ui/gfx/swap_result.h"
20 
21 namespace gpu {
22 
23 class VulkanCommandBuffer;
24 class VulkanCommandPool;
25 class VulkanDeviceQueue;
26 
27 class VULKAN_EXPORT VulkanSwapChain {
28  public:
29   class VULKAN_EXPORT ScopedWrite {
30    public:
31     explicit ScopedWrite(VulkanSwapChain* swap_chain);
32     ~ScopedWrite();
33 
success()34     bool success() const { return success_; }
image()35     VkImage image() const { return image_; }
image_index()36     uint32_t image_index() const { return image_index_; }
image_layout()37     VkImageLayout image_layout() const { return image_layout_; }
set_image_layout(VkImageLayout layout)38     void set_image_layout(VkImageLayout layout) { image_layout_ = layout; }
39 
40     // Take the begin write semaphore. The ownership of the semaphore will be
41     // transferred to the caller.
42     VkSemaphore TakeBeginSemaphore();
43 
44     // Get the end write semaphore.
45     VkSemaphore GetEndSemaphore();
46 
47    private:
48     VulkanSwapChain* const swap_chain_;
49     bool success_ = false;
50     VkImage image_ = VK_NULL_HANDLE;
51     uint32_t image_index_ = 0;
52     VkImageLayout image_layout_ = VK_IMAGE_LAYOUT_UNDEFINED;
53     VkSemaphore begin_semaphore_ = VK_NULL_HANDLE;
54     VkSemaphore end_semaphore_ = VK_NULL_HANDLE;
55 
56     DISALLOW_COPY_AND_ASSIGN(ScopedWrite);
57   };
58 
59   VulkanSwapChain();
60   ~VulkanSwapChain();
61 
62   // min_image_count is the minimum number of presentable images.
63   bool Initialize(VulkanDeviceQueue* device_queue,
64                   VkSurfaceKHR surface,
65                   const VkSurfaceFormatKHR& surface_format,
66                   const gfx::Size& image_size,
67                   uint32_t min_image_count,
68                   VkSurfaceTransformFlagBitsKHR pre_transform,
69                   bool use_protected_memory,
70                   std::unique_ptr<VulkanSwapChain> old_swap_chain);
71 
72   // Destroy() should be called when all related GPU tasks have been finished.
73   void Destroy();
74 
75   // Present the current buffer.
76   gfx::SwapResult PresentBuffer(const gfx::Rect& rect);
77 
num_images()78   uint32_t num_images() const { return static_cast<uint32_t>(images_.size()); }
size()79   const gfx::Size& size() const { return size_; }
use_protected_memory()80   bool use_protected_memory() const { return use_protected_memory_; }
81 
82  private:
83   bool InitializeSwapChain(VkSurfaceKHR surface,
84                            const VkSurfaceFormatKHR& surface_format,
85                            const gfx::Size& image_size,
86                            uint32_t min_image_count,
87                            VkSurfaceTransformFlagBitsKHR pre_transform,
88                            bool use_protected_memory,
89                            std::unique_ptr<VulkanSwapChain> old_swap_chain);
90   void DestroySwapChain();
91 
92   bool InitializeSwapImages(const VkSurfaceFormatKHR& surface_format);
93   void DestroySwapImages();
94 
95   bool BeginWriteCurrentImage(VkImage* image,
96                               uint32_t* image_index,
97                               VkImageLayout* layout,
98                               VkSemaphore* semaphore);
99   void EndWriteCurrentImage(VkImageLayout layout, VkSemaphore semaphore);
100   bool AcquireNextImage();
101 
102   bool use_protected_memory_ = false;
103   VulkanDeviceQueue* device_queue_ = nullptr;
104   bool is_incremental_present_supported_ = false;
105   VkSwapchainKHR swap_chain_ = VK_NULL_HANDLE;
106 
107   std::unique_ptr<VulkanCommandPool> command_pool_;
108 
109   gfx::Size size_;
110 
111   struct ImageData {
112     ImageData();
113     ImageData(ImageData&& other);
114     ~ImageData();
115 
116     ImageData& operator=(ImageData&& other);
117 
118     VkImage image = VK_NULL_HANDLE;
119     VkImageLayout layout = VK_IMAGE_LAYOUT_UNDEFINED;
120     std::unique_ptr<VulkanCommandBuffer> command_buffer;
121     // Semaphore passed to vkQueuePresentKHR to wait on.
122     VkSemaphore present_begin_semaphore = VK_NULL_HANDLE;
123     // Semaphore signaled when present engine is done with the image.
124     VkSemaphore present_end_semaphore = VK_NULL_HANDLE;
125   };
126   std::vector<ImageData> images_;
127 
128   // Acquired image index.
129   base::circular_deque<uint32_t> in_present_images_;
130   base::Optional<uint32_t> acquired_image_;
131   bool is_writing_ = false;
132   VkSemaphore end_write_semaphore_ = VK_NULL_HANDLE;
133 
134   DISALLOW_COPY_AND_ASSIGN(VulkanSwapChain);
135 };
136 
137 }  // namespace gpu
138 
139 #endif  // GPU_VULKAN_VULKAN_SWAP_CHAIN_H_
140