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