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