Hash :
a8b81590
Author :
Date :
2019-02-15T17:23:23
Vulkan: Free semaphores with other in flight resources ANGLE calls WindowSurfaceVk::nextSwapchainImage() to prepare for the next frame, which allocates an image (and other resources, like semaphore). However, it's possible for egl::Display::destroySurface() to be called before the next submitFrame(), which prevents the image from being returned back to the swapchain. This fix refactors swapImpl() to separate out the present work, which can be called as part of destroy() to return the allocated resources. dEQP-EGL.functional.query_context.get_current_context.* dEQP-EGL.functional.query_context.get_current_display.* dEQP-EGL.functional.query_context.get_current_surface.r* dEQP-EGL.functional.query_context.query_context.* Bug: angleproject:3057 Change-Id: Ia943f2530e4f27d1a10ee907e810f0bbdb3bfa9a Reviewed-on: https://chromium-review.googlesource.com/c/1474601 Reviewed-by: Ian Elliott <ianelliott@google.com> Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
//
// 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 OffscreenSurfaceVk : public SurfaceImpl
{
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 getAttachmentRenderTarget(const gl::Context *context,
GLenum binding,
const gl::ImageIndex &imageIndex,
FramebufferAttachmentRenderTarget **rtOut) 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);
void destroy(const egl::Display *display);
vk::ImageHelper image;
vk::ImageView imageView;
RenderTargetVk renderTarget;
};
angle::Result initializeImpl(DisplayVk *displayVk);
EGLint mWidth;
EGLint mHeight;
AttachmentImage mColorAttachment;
AttachmentImage mDepthStencilAttachment;
};
class WindowSurfaceVk : public SurfaceImpl
{
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 getAttachmentRenderTarget(const gl::Context *context,
GLenum binding,
const gl::ImageIndex &imageIndex,
FramebufferAttachmentRenderTarget **rtOut) 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);
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(DisplayVk *displayVk,
const gl::Extents &extents,
uint32_t swapHistoryIndex);
angle::Result checkForOutOfDateSwapchain(DisplayVk *displayVk,
uint32_t swapHistoryIndex,
bool presentOutOfDate);
void releaseSwapchainImages(RendererVk *renderer);
angle::Result nextSwapchainImage(DisplayVk *displayVk);
angle::Result present(DisplayVk *displayVk,
EGLint *rects,
EGLint n_rects,
bool &swapchainOutOfDate);
angle::Result swapImpl(DisplayVk *displayVk, EGLint *rects, EGLint n_rects);
angle::Result resizeSwapHistory(DisplayVk *displayVk, size_t imageCount);
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;
RenderTargetVk mColorRenderTarget;
RenderTargetVk mDepthStencilRenderTarget;
uint32_t mCurrentSwapchainImageIndex;
struct SwapchainImage : angle::NonCopyable
{
SwapchainImage();
SwapchainImage(SwapchainImage &&other);
~SwapchainImage();
vk::ImageHelper image;
vk::ImageView imageView;
vk::Framebuffer framebuffer;
};
std::vector<SwapchainImage> mSwapchainImages;
// A circular buffer, with the same size as mSwapchainImages (N), that stores the serial of the
// renderer on every swap. The CPU is throttled by waiting for the Nth previous serial to
// finish. Old swapchains are scheduled to be destroyed at the same time.
struct SwapHistory
{
Serial serial;
VkSwapchainKHR swapchain = VK_NULL_HANDLE;
};
std::vector<SwapHistory> mSwapHistory;
size_t mCurrentSwapHistoryIndex;
vk::ImageHelper mDepthStencilImage;
vk::ImageView mDepthStencilImageView;
};
} // namespace rx
#endif // LIBANGLE_RENDERER_VULKAN_SURFACEVK_H_