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