• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2016 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // SurfaceVk.h:
7 //    Defines the class interface for SurfaceVk, implementing SurfaceImpl.
8 //
9 
10 #ifndef LIBANGLE_RENDERER_VULKAN_SURFACEVK_H_
11 #define LIBANGLE_RENDERER_VULKAN_SURFACEVK_H_
12 
13 #include "volk.h"
14 
15 #include "libANGLE/renderer/SurfaceImpl.h"
16 #include "libANGLE/renderer/vulkan/RenderTargetVk.h"
17 #include "libANGLE/renderer/vulkan/vk_helpers.h"
18 
19 namespace rx
20 {
21 class RendererVk;
22 
23 class SurfaceVk : public SurfaceImpl
24 {
25   public:
26     angle::Result getAttachmentRenderTarget(const gl::Context *context,
27                                             GLenum binding,
28                                             const gl::ImageIndex &imageIndex,
29                                             GLsizei samples,
30                                             FramebufferAttachmentRenderTarget **rtOut) override;
31 
32   protected:
33     SurfaceVk(const egl::SurfaceState &surfaceState);
34     ~SurfaceVk() override;
35 
36     RenderTargetVk mColorRenderTarget;
37     RenderTargetVk mDepthStencilRenderTarget;
38 };
39 
40 class OffscreenSurfaceVk : public SurfaceVk
41 {
42   public:
43     OffscreenSurfaceVk(const egl::SurfaceState &surfaceState);
44     ~OffscreenSurfaceVk() override;
45 
46     egl::Error initialize(const egl::Display *display) override;
47     void destroy(const egl::Display *display) override;
48 
49     FramebufferImpl *createDefaultFramebuffer(const gl::Context *context,
50                                               const gl::FramebufferState &state) override;
51     egl::Error swap(const gl::Context *context) override;
52     egl::Error postSubBuffer(const gl::Context *context,
53                              EGLint x,
54                              EGLint y,
55                              EGLint width,
56                              EGLint height) override;
57     egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
58     egl::Error bindTexImage(const gl::Context *context,
59                             gl::Texture *texture,
60                             EGLint buffer) override;
61     egl::Error releaseTexImage(const gl::Context *context, EGLint buffer) override;
62     egl::Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) override;
63     egl::Error getMscRate(EGLint *numerator, EGLint *denominator) override;
64     void setSwapInterval(EGLint interval) override;
65 
66     // width and height can change with client window resizing
67     EGLint getWidth() const override;
68     EGLint getHeight() const override;
69 
70     EGLint isPostSubBufferSupported() const override;
71     EGLint getSwapBehavior() const override;
72 
73     angle::Result initializeContents(const gl::Context *context,
74                                      const gl::ImageIndex &imageIndex) override;
75 
76     vk::ImageHelper *getColorAttachmentImage();
77 
78   protected:
79     struct AttachmentImage final : angle::NonCopyable
80     {
81         AttachmentImage();
82         ~AttachmentImage();
83 
84         angle::Result initialize(DisplayVk *displayVk,
85                                  EGLint width,
86                                  EGLint height,
87                                  const vk::Format &vkFormat,
88                                  GLint samples);
89 
90         angle::Result initializeWithExternalMemory(DisplayVk *displayVk,
91                                                    EGLint width,
92                                                    EGLint height,
93                                                    const vk::Format &vkFormat,
94                                                    GLint samples,
95                                                    void *buffer);
96 
97         void destroy(const egl::Display *display);
98 
99         vk::ImageHelper image;
100         vk::ImageViewHelper imageViews;
101     };
102 
103     virtual angle::Result initializeImpl(DisplayVk *displayVk);
104 
105     EGLint mWidth;
106     EGLint mHeight;
107 
108     AttachmentImage mColorAttachment;
109     AttachmentImage mDepthStencilAttachment;
110 };
111 
112 // Data structures used in WindowSurfaceVk
113 namespace impl
114 {
115 // The submission fence of the context used to throttle the CPU.
116 struct SwapHistory : angle::NonCopyable
117 {
118     SwapHistory();
119     SwapHistory(SwapHistory &&other) = delete;
120     SwapHistory &operator=(SwapHistory &&other) = delete;
121     ~SwapHistory();
122 
123     void destroy(RendererVk *renderer);
124 
125     angle::Result waitFence(ContextVk *contextVk);
126 
127     // Fence associated with the last submitted work to render to this swapchain image.
128     vk::Shared<vk::Fence> sharedFence;
129 };
130 static constexpr size_t kSwapHistorySize = 2;
131 
132 // Old swapchain and associated present semaphores that need to be scheduled for destruction when
133 // appropriate.
134 struct SwapchainCleanupData : angle::NonCopyable
135 {
136     SwapchainCleanupData();
137     SwapchainCleanupData(SwapchainCleanupData &&other);
138     ~SwapchainCleanupData();
139 
140     void destroy(VkDevice device, vk::Recycler<vk::Semaphore> *semaphoreRecycler);
141 
142     // The swapchain to be destroyed.
143     VkSwapchainKHR swapchain = VK_NULL_HANDLE;
144     // Any present semaphores that were pending destruction at the time the swapchain was
145     // recreated will be scheduled for destruction at the same time as the swapchain.
146     std::vector<vk::Semaphore> semaphores;
147 };
148 
149 // A circular buffer per image stores the semaphores used for presenting that image.  Taking the
150 // swap history into account, only the oldest semaphore is guaranteed to be no longer in use by the
151 // presentation engine.  See doc/PresentSemaphores.md for details.
152 //
153 // Old swapchains are scheduled to be destroyed at the same time as the first semaphore used to
154 // present an image of the new swapchain.  This is to ensure that the presentation engine is no
155 // longer presenting an image from the old swapchain.
156 struct ImagePresentHistory : angle::NonCopyable
157 {
158     ImagePresentHistory();
159     ImagePresentHistory(ImagePresentHistory &&other);
160     ~ImagePresentHistory();
161 
162     vk::Semaphore semaphore;
163     std::vector<SwapchainCleanupData> oldSwapchains;
164 };
165 
166 // Swapchain images and their associated objects.
167 struct SwapchainImage : angle::NonCopyable
168 {
169     SwapchainImage();
170     SwapchainImage(SwapchainImage &&other);
171     ~SwapchainImage();
172 
173     vk::ImageHelper image;
174     vk::ImageViewHelper imageViews;
175     vk::Framebuffer framebuffer;
176 
177     // A circular array of semaphores used for presenting this image.
178     static constexpr size_t kPresentHistorySize = kSwapHistorySize + 1;
179     std::array<ImagePresentHistory, kPresentHistorySize> presentHistory;
180     size_t currentPresentHistoryIndex = 0;
181 };
182 }  // namespace impl
183 
184 class WindowSurfaceVk : public SurfaceVk
185 {
186   public:
187     WindowSurfaceVk(const egl::SurfaceState &surfaceState, EGLNativeWindowType window);
188     ~WindowSurfaceVk() override;
189 
190     void destroy(const egl::Display *display) override;
191 
192     egl::Error initialize(const egl::Display *display) override;
193     FramebufferImpl *createDefaultFramebuffer(const gl::Context *context,
194                                               const gl::FramebufferState &state) override;
195     egl::Error swap(const gl::Context *context) override;
196     egl::Error swapWithDamage(const gl::Context *context, EGLint *rects, EGLint n_rects) override;
197     egl::Error postSubBuffer(const gl::Context *context,
198                              EGLint x,
199                              EGLint y,
200                              EGLint width,
201                              EGLint height) override;
202     egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
203     egl::Error bindTexImage(const gl::Context *context,
204                             gl::Texture *texture,
205                             EGLint buffer) override;
206     egl::Error releaseTexImage(const gl::Context *context, EGLint buffer) override;
207     egl::Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) override;
208     egl::Error getMscRate(EGLint *numerator, EGLint *denominator) override;
209     void setSwapInterval(EGLint interval) override;
210 
211     // width and height can change with client window resizing
212     EGLint getWidth() const override;
213     EGLint getHeight() const override;
214 
215     EGLint isPostSubBufferSupported() const override;
216     EGLint getSwapBehavior() const override;
217 
218     angle::Result initializeContents(const gl::Context *context,
219                                      const gl::ImageIndex &imageIndex) override;
220 
221     angle::Result getCurrentFramebuffer(ContextVk *context,
222                                         const vk::RenderPass &compatibleRenderPass,
223                                         vk::Framebuffer **framebufferOut);
224 
225     vk::Semaphore getAcquireImageSemaphore();
226 
getPreTransform()227     VkSurfaceTransformFlagBitsKHR getPreTransform() { return mPreTransform; }
228 
229   protected:
230     angle::Result swapImpl(const gl::Context *context,
231                            EGLint *rects,
232                            EGLint n_rects,
233                            const void *pNextChain);
234 
235     EGLNativeWindowType mNativeWindowType;
236     VkSurfaceKHR mSurface;
237     VkSurfaceCapabilitiesKHR mSurfaceCaps;
238 
239   private:
240     virtual angle::Result createSurfaceVk(vk::Context *context, gl::Extents *extentsOut)      = 0;
241     virtual angle::Result getCurrentWindowSize(vk::Context *context, gl::Extents *extentsOut) = 0;
242 
243     angle::Result initializeImpl(DisplayVk *displayVk);
244     angle::Result recreateSwapchain(ContextVk *contextVk,
245                                     const gl::Extents &extents,
246                                     uint32_t swapHistoryIndex);
247     angle::Result createSwapChain(vk::Context *context,
248                                   const gl::Extents &extents,
249                                   VkSwapchainKHR oldSwapchain);
250     angle::Result checkForOutOfDateSwapchain(ContextVk *contextVk,
251                                              uint32_t swapHistoryIndex,
252                                              bool presentOutOfDate);
253     angle::Result resizeSwapchainImages(vk::Context *context, uint32_t imageCount);
254     void releaseSwapchainImages(ContextVk *contextVk);
255     void destroySwapChainImages(DisplayVk *displayVk);
256     VkResult nextSwapchainImage(vk::Context *context);
257     angle::Result present(ContextVk *contextVk,
258                           EGLint *rects,
259                           EGLint n_rects,
260                           const void *pNextChain,
261                           bool *presentOutOfDate);
262 
263     void updateOverlay(ContextVk *contextVk) const;
264     bool overlayHasEnabledWidget(ContextVk *contextVk) const;
265     angle::Result drawOverlay(ContextVk *contextVk, impl::SwapchainImage *image) const;
266 
267     angle::Result newPresentSemaphore(vk::Context *context, vk::Semaphore *semaphoreOut);
268 
269     bool isMultiSampled() const;
270 
271     std::vector<VkPresentModeKHR> mPresentModes;
272 
273     VkSwapchainKHR mSwapchain;
274     // Cached information used to recreate swapchains.
275     VkPresentModeKHR mSwapchainPresentMode;         // Current swapchain mode
276     VkPresentModeKHR mDesiredSwapchainPresentMode;  // Desired mode set through setSwapInterval()
277     uint32_t mMinImageCount;
278     VkSurfaceTransformFlagBitsKHR mPreTransform;
279     VkCompositeAlphaFlagBitsKHR mCompositeAlpha;
280 
281     // A circular buffer that stores the submission fence of the context on every swap.  The CPU is
282     // throttled by waiting for the 2nd previous serial to finish.
283     std::array<impl::SwapHistory, impl::kSwapHistorySize> mSwapHistory;
284     size_t mCurrentSwapHistoryIndex;
285 
286     // The previous swapchain which needs to be scheduled for destruction when appropriate.  This
287     // will be done when the first image of the current swapchain is presented.  If there were
288     // older swapchains pending destruction when the swapchain is recreated, they will accumulate
289     // and be destroyed with the previous swapchain.
290     //
291     // Note that if the user resizes the window such that the swapchain is recreated every frame,
292     // this array can go grow indefinitely.
293     std::vector<impl::SwapchainCleanupData> mOldSwapchains;
294 
295     std::vector<impl::SwapchainImage> mSwapchainImages;
296     vk::Semaphore mAcquireImageSemaphore;
297     uint32_t mCurrentSwapchainImageIndex;
298 
299     vk::Recycler<vk::Semaphore> mPresentSemaphoreRecycler;
300 
301     // Depth/stencil image.  Possibly multisampled.
302     vk::ImageHelper mDepthStencilImage;
303     vk::ImageViewHelper mDepthStencilImageViews;
304 
305     // Multisample color image, view and framebuffer, if multisampling enabled.
306     vk::ImageHelper mColorImageMS;
307     vk::ImageViewHelper mColorImageMSViews;
308     vk::Framebuffer mFramebufferMS;
309 };
310 
311 }  // namespace rx
312 
313 #endif  // LIBANGLE_RENDERER_VULKAN_SURFACEVK_H_
314