| // |
| // Copyright 2016 The ANGLE Project Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| // |
| // SurfaceVk.h: |
| // Defines the class interface for SurfaceVk, implementing SurfaceImpl. |
| // |
| |
| #ifndef LIBANGLE_RENDERER_VULKAN_SURFACEVK_H_ |
| #define LIBANGLE_RENDERER_VULKAN_SURFACEVK_H_ |
| |
| #include <vulkan/vulkan.h> |
| |
| #include "libANGLE/renderer/SurfaceImpl.h" |
| #include "libANGLE/renderer/vulkan/RenderTargetVk.h" |
| #include "libANGLE/renderer/vulkan/vk_helpers.h" |
| |
| namespace rx |
| { |
| class RendererVk; |
| |
| class SurfaceVk : public SurfaceImpl |
| { |
| public: |
| angle::Result getAttachmentRenderTarget(const gl::Context *context, |
| GLenum binding, |
| const gl::ImageIndex &imageIndex, |
| GLsizei samples, |
| FramebufferAttachmentRenderTarget **rtOut) override; |
| |
| protected: |
| SurfaceVk(const egl::SurfaceState &surfaceState); |
| ~SurfaceVk() override; |
| |
| RenderTargetVk mColorRenderTarget; |
| RenderTargetVk mDepthStencilRenderTarget; |
| }; |
| |
| class OffscreenSurfaceVk : public SurfaceVk |
| { |
| public: |
| OffscreenSurfaceVk(const egl::SurfaceState &surfaceState, EGLint width, EGLint height); |
| ~OffscreenSurfaceVk() override; |
| |
| egl::Error initialize(const egl::Display *display) override; |
| void destroy(const egl::Display *display) override; |
| |
| FramebufferImpl *createDefaultFramebuffer(const gl::Context *context, |
| const gl::FramebufferState &state) override; |
| egl::Error swap(const gl::Context *context) override; |
| egl::Error postSubBuffer(const gl::Context *context, |
| EGLint x, |
| EGLint y, |
| EGLint width, |
| EGLint height) override; |
| egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override; |
| egl::Error bindTexImage(const gl::Context *context, |
| gl::Texture *texture, |
| EGLint buffer) override; |
| egl::Error releaseTexImage(const gl::Context *context, EGLint buffer) override; |
| egl::Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) override; |
| void setSwapInterval(EGLint interval) override; |
| |
| // width and height can change with client window resizing |
| EGLint getWidth() const override; |
| EGLint getHeight() const override; |
| |
| EGLint isPostSubBufferSupported() const override; |
| EGLint getSwapBehavior() const override; |
| |
| angle::Result initializeContents(const gl::Context *context, |
| const gl::ImageIndex &imageIndex) override; |
| |
| vk::ImageHelper *getColorAttachmentImage(); |
| |
| private: |
| struct AttachmentImage final : angle::NonCopyable |
| { |
| AttachmentImage(); |
| ~AttachmentImage(); |
| |
| angle::Result initialize(DisplayVk *displayVk, |
| EGLint width, |
| EGLint height, |
| const vk::Format &vkFormat, |
| GLint samples); |
| void destroy(const egl::Display *display); |
| |
| vk::ImageHelper image; |
| vk::ImageView imageView; |
| }; |
| |
| angle::Result initializeImpl(DisplayVk *displayVk); |
| |
| EGLint mWidth; |
| EGLint mHeight; |
| |
| AttachmentImage mColorAttachment; |
| AttachmentImage mDepthStencilAttachment; |
| }; |
| |
| // Data structures used in WindowSurfaceVk |
| namespace impl |
| { |
| // The submission fence of the context used to throttle the CPU. |
| struct SwapHistory : angle::NonCopyable |
| { |
| SwapHistory(); |
| SwapHistory(SwapHistory &&other) = delete; |
| SwapHistory &operator=(SwapHistory &&other) = delete; |
| ~SwapHistory(); |
| |
| void destroy(RendererVk *renderer); |
| |
| angle::Result waitFence(ContextVk *contextVk); |
| |
| // Fence associated with the last submitted work to render to this swapchain image. |
| vk::Shared<vk::Fence> sharedFence; |
| }; |
| static constexpr size_t kSwapHistorySize = 2; |
| |
| // Old swapchain and associated present semaphores that need to be scheduled for destruction when |
| // appropriate. |
| struct SwapchainCleanupData : angle::NonCopyable |
| { |
| SwapchainCleanupData(); |
| SwapchainCleanupData(SwapchainCleanupData &&other); |
| ~SwapchainCleanupData(); |
| |
| void destroy(VkDevice device, vk::Recycler<vk::Semaphore> *semaphoreRecycler); |
| |
| // The swapchain to be destroyed. |
| VkSwapchainKHR swapchain = VK_NULL_HANDLE; |
| // Any present semaphores that were pending destruction at the time the swapchain was |
| // recreated will be scheduled for destruction at the same time as the swapchain. |
| std::vector<vk::Semaphore> semaphores; |
| }; |
| |
| // A circular buffer per image stores the semaphores used for presenting that image. Taking the |
| // swap history into account, only the oldest semaphore is guaranteed to be no longer in use by the |
| // presentation engine. See doc/PresentSemaphores.md for details. |
| // |
| // Old swapchains are scheduled to be destroyed at the same time as the first semaphore used to |
| // present an image of the new swapchain. This is to ensure that the presentation engine is no |
| // longer presenting an image from the old swapchain. |
| struct ImagePresentHistory : angle::NonCopyable |
| { |
| ImagePresentHistory(); |
| ImagePresentHistory(ImagePresentHistory &&other); |
| ~ImagePresentHistory(); |
| |
| vk::Semaphore semaphore; |
| std::vector<SwapchainCleanupData> oldSwapchains; |
| }; |
| |
| // Swapchain images and their associated objects. |
| struct SwapchainImage : angle::NonCopyable |
| { |
| SwapchainImage(); |
| SwapchainImage(SwapchainImage &&other); |
| ~SwapchainImage(); |
| |
| vk::ImageHelper image; |
| vk::ImageView imageView; |
| vk::Framebuffer framebuffer; |
| |
| // A circular array of semaphores used for presenting this image. |
| static constexpr size_t kPresentHistorySize = kSwapHistorySize + 1; |
| std::array<ImagePresentHistory, kPresentHistorySize> presentHistory; |
| size_t currentPresentHistoryIndex = 0; |
| }; |
| } // namespace impl |
| |
| class WindowSurfaceVk : public SurfaceVk |
| { |
| public: |
| WindowSurfaceVk(const egl::SurfaceState &surfaceState, |
| EGLNativeWindowType window, |
| EGLint width, |
| EGLint height); |
| ~WindowSurfaceVk() override; |
| |
| void destroy(const egl::Display *display) override; |
| |
| egl::Error initialize(const egl::Display *display) override; |
| FramebufferImpl *createDefaultFramebuffer(const gl::Context *context, |
| const gl::FramebufferState &state) override; |
| egl::Error swap(const gl::Context *context) override; |
| egl::Error swapWithDamage(const gl::Context *context, EGLint *rects, EGLint n_rects) override; |
| egl::Error postSubBuffer(const gl::Context *context, |
| EGLint x, |
| EGLint y, |
| EGLint width, |
| EGLint height) override; |
| egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override; |
| egl::Error bindTexImage(const gl::Context *context, |
| gl::Texture *texture, |
| EGLint buffer) override; |
| egl::Error releaseTexImage(const gl::Context *context, EGLint buffer) override; |
| egl::Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) override; |
| void setSwapInterval(EGLint interval) override; |
| |
| // width and height can change with client window resizing |
| EGLint getWidth() const override; |
| EGLint getHeight() const override; |
| |
| EGLint isPostSubBufferSupported() const override; |
| EGLint getSwapBehavior() const override; |
| |
| angle::Result initializeContents(const gl::Context *context, |
| const gl::ImageIndex &imageIndex) override; |
| |
| angle::Result getCurrentFramebuffer(vk::Context *context, |
| const vk::RenderPass &compatibleRenderPass, |
| vk::Framebuffer **framebufferOut); |
| |
| vk::Semaphore getAcquireImageSemaphore(); |
| |
| protected: |
| EGLNativeWindowType mNativeWindowType; |
| VkSurfaceKHR mSurface; |
| VkInstance mInstance; |
| |
| private: |
| virtual angle::Result createSurfaceVk(vk::Context *context, gl::Extents *extentsOut) = 0; |
| virtual angle::Result getCurrentWindowSize(vk::Context *context, gl::Extents *extentsOut) = 0; |
| |
| angle::Result initializeImpl(DisplayVk *displayVk); |
| angle::Result recreateSwapchain(ContextVk *contextVk, |
| const gl::Extents &extents, |
| uint32_t swapHistoryIndex); |
| angle::Result createSwapChain(vk::Context *context, |
| const gl::Extents &extents, |
| VkSwapchainKHR oldSwapchain); |
| angle::Result checkForOutOfDateSwapchain(ContextVk *contextVk, |
| uint32_t swapHistoryIndex, |
| bool presentOutOfDate); |
| angle::Result resizeSwapchainImages(vk::Context *context, uint32_t imageCount); |
| void releaseSwapchainImages(ContextVk *contextVk); |
| void destroySwapChainImages(DisplayVk *displayVk); |
| VkResult nextSwapchainImage(vk::Context *context); |
| angle::Result present(ContextVk *contextVk, |
| EGLint *rects, |
| EGLint n_rects, |
| bool *presentOutOfDate); |
| |
| angle::Result updateAndDrawOverlay(ContextVk *contextVk, impl::SwapchainImage *image) const; |
| |
| angle::Result swapImpl(const gl::Context *context, EGLint *rects, EGLint n_rects); |
| |
| angle::Result newPresentSemaphore(vk::Context *context, vk::Semaphore *semaphoreOut); |
| |
| bool isMultiSampled() const; |
| |
| VkSurfaceCapabilitiesKHR mSurfaceCaps; |
| std::vector<VkPresentModeKHR> mPresentModes; |
| |
| VkSwapchainKHR mSwapchain; |
| // Cached information used to recreate swapchains. |
| VkPresentModeKHR mSwapchainPresentMode; // Current swapchain mode |
| VkPresentModeKHR mDesiredSwapchainPresentMode; // Desired mode set through setSwapInterval() |
| uint32_t mMinImageCount; |
| VkSurfaceTransformFlagBitsKHR mPreTransform; |
| VkCompositeAlphaFlagBitsKHR mCompositeAlpha; |
| |
| // A circular buffer that stores the submission fence of the context on every swap. The CPU is |
| // throttled by waiting for the 2nd previous serial to finish. |
| std::array<impl::SwapHistory, impl::kSwapHistorySize> mSwapHistory; |
| size_t mCurrentSwapHistoryIndex; |
| |
| // The previous swapchain which needs to be scheduled for destruction when appropriate. This |
| // will be done when the first image of the current swapchain is presented. If there were |
| // older swapchains pending destruction when the swapchain is recreated, they will accumulate |
| // and be destroyed with the previous swapchain. |
| // |
| // Note that if the user resizes the window such that the swapchain is recreated every frame, |
| // this array can go grow indefinitely. |
| std::vector<impl::SwapchainCleanupData> mOldSwapchains; |
| |
| std::vector<impl::SwapchainImage> mSwapchainImages; |
| vk::Semaphore mAcquireImageSemaphore; |
| uint32_t mCurrentSwapchainImageIndex; |
| |
| vk::Recycler<vk::Semaphore> mPresentSemaphoreRecycler; |
| |
| // Depth/stencil image. Possibly multisampled. |
| vk::ImageHelper mDepthStencilImage; |
| vk::ImageView mDepthStencilImageView; |
| |
| // Multisample color image, view and framebuffer, if multisampling enabled. |
| vk::ImageHelper mColorImageMS; |
| vk::ImageView mColorImageViewMS; |
| vk::Framebuffer mFramebufferMS; |
| }; |
| |
| } // namespace rx |
| |
| #endif // LIBANGLE_RENDERER_VULKAN_SURFACEVK_H_ |