Skip to content

Commit 57cb85a

Browse files
authored
Vulkan support in the Embedder API (flutter#29391)
1 parent e3877ce commit 57cb85a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+1873
-170
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1365,6 +1365,8 @@ FILE: ../../../flutter/shell/platform/embedder/embedder_surface_metal.h
13651365
FILE: ../../../flutter/shell/platform/embedder/embedder_surface_metal.mm
13661366
FILE: ../../../flutter/shell/platform/embedder/embedder_surface_software.cc
13671367
FILE: ../../../flutter/shell/platform/embedder/embedder_surface_software.h
1368+
FILE: ../../../flutter/shell/platform/embedder/embedder_surface_vulkan.cc
1369+
FILE: ../../../flutter/shell/platform/embedder/embedder_surface_vulkan.h
13681370
FILE: ../../../flutter/shell/platform/embedder/embedder_task_runner.cc
13691371
FILE: ../../../flutter/shell/platform/embedder/embedder_task_runner.h
13701372
FILE: ../../../flutter/shell/platform/embedder/embedder_thread_host.cc
@@ -1387,6 +1389,8 @@ FILE: ../../../flutter/shell/platform/embedder/fixtures/scene_without_custom_com
13871389
FILE: ../../../flutter/shell/platform/embedder/fixtures/snapshot_large_scene.png
13881390
FILE: ../../../flutter/shell/platform/embedder/fixtures/verifyb143464703.png
13891391
FILE: ../../../flutter/shell/platform/embedder/fixtures/verifyb143464703_soft_noxform.png
1392+
FILE: ../../../flutter/shell/platform/embedder/fixtures/vk_dpr_noxform.png
1393+
FILE: ../../../flutter/shell/platform/embedder/fixtures/vk_gradient.png
13901394
FILE: ../../../flutter/shell/platform/embedder/platform_view_embedder.cc
13911395
FILE: ../../../flutter/shell/platform/embedder/platform_view_embedder.h
13921396
FILE: ../../../flutter/shell/platform/embedder/test_utils/key_codes.h

shell/gpu/BUILD.gn

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,9 @@ source_set("gpu_surface_vulkan") {
4343
"gpu_surface_vulkan_delegate.cc",
4444
"gpu_surface_vulkan_delegate.h",
4545
]
46-
47-
deps = gpu_common_deps + [ "//flutter/vulkan" ]
46+
deps = [ "//flutter/shell/platform/embedder:embedder_headers" ]
47+
deps += gpu_common_deps
48+
public_deps = [ "//flutter/vulkan" ]
4849
}
4950

5051
source_set("gpu_surface_metal") {

shell/gpu/gpu_surface_metal_delegate.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,14 +75,14 @@ class GPUSurfaceMetalDelegate {
7575

7676
//------------------------------------------------------------------------------
7777
/// @brief Returns the handle to the MTLTexture to render to. This is only
78-
/// called when the specefied render target type is `kMTLTexture`.
78+
/// called when the specified render target type is `kMTLTexture`.
7979
///
8080
virtual GPUMTLTextureInfo GetMTLTexture(const SkISize& frame_info) const = 0;
8181

8282
//------------------------------------------------------------------------------
8383
/// @brief Presents the texture with `texture_id` to the "screen".
8484
/// `texture_id` corresponds to a texture that has been obtained by an earlier
85-
/// call to `GetMTLTexture`. This is only called when the specefied render
85+
/// call to `GetMTLTexture`. This is only called when the specified render
8686
/// target type is `kMTLTexture`.
8787
///
8888
/// @see |GPUSurfaceMetalDelegate::GetMTLTexture|

shell/gpu/gpu_surface_vulkan.cc

Lines changed: 92 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -5,68 +5,77 @@
55
#include "flutter/shell/gpu/gpu_surface_vulkan.h"
66

77
#include "flutter/fml/logging.h"
8+
#include "fml/trace_event.h"
9+
#include "include/core/SkSize.h"
10+
#include "third_party/swiftshader/include/vulkan/vulkan_core.h"
811

912
namespace flutter {
1013

11-
GPUSurfaceVulkan::GPUSurfaceVulkan(
12-
GPUSurfaceVulkanDelegate* delegate,
13-
std::unique_ptr<vulkan::VulkanNativeSurface> native_surface,
14-
bool render_to_surface)
15-
: GPUSurfaceVulkan(/*context=*/nullptr,
16-
delegate,
17-
std::move(native_surface),
18-
render_to_surface) {}
19-
20-
GPUSurfaceVulkan::GPUSurfaceVulkan(
21-
const sk_sp<GrDirectContext>& context,
22-
GPUSurfaceVulkanDelegate* delegate,
23-
std::unique_ptr<vulkan::VulkanNativeSurface> native_surface,
24-
bool render_to_surface)
25-
: window_(context,
26-
delegate->vk(),
27-
std::move(native_surface),
28-
render_to_surface),
14+
GPUSurfaceVulkan::GPUSurfaceVulkan(GPUSurfaceVulkanDelegate* delegate,
15+
const sk_sp<GrDirectContext>& skia_context,
16+
bool render_to_surface)
17+
: delegate_(delegate),
18+
skia_context_(skia_context),
2919
render_to_surface_(render_to_surface),
3020
weak_factory_(this) {}
3121

3222
GPUSurfaceVulkan::~GPUSurfaceVulkan() = default;
3323

3424
bool GPUSurfaceVulkan::IsValid() {
35-
return window_.IsValid();
25+
return skia_context_ != nullptr;
3626
}
3727

3828
std::unique_ptr<SurfaceFrame> GPUSurfaceVulkan::AcquireFrame(
39-
const SkISize& size) {
40-
SurfaceFrame::FramebufferInfo framebuffer_info;
41-
framebuffer_info.supports_readback = true;
29+
const SkISize& frame_size) {
30+
if (!IsValid()) {
31+
FML_LOG(ERROR) << "Vulkan surface was invalid.";
32+
return nullptr;
33+
}
34+
35+
if (frame_size.isEmpty()) {
36+
FML_LOG(ERROR) << "Vulkan surface was asked for an empty frame.";
37+
return nullptr;
38+
}
4239

43-
// TODO(38466): Refactor GPU surface APIs take into account the fact that an
44-
// external view embedder may want to render to the root surface.
4540
if (!render_to_surface_) {
4641
return std::make_unique<SurfaceFrame>(
47-
nullptr, std::move(framebuffer_info),
42+
nullptr, SurfaceFrame::FramebufferInfo(),
4843
[](const SurfaceFrame& surface_frame, SkCanvas* canvas) {
4944
return true;
5045
});
5146
}
5247

53-
auto surface = window_.AcquireSurface();
48+
FlutterVulkanImage image = delegate_->AcquireImage(frame_size);
49+
if (!image.image) {
50+
FML_LOG(ERROR) << "Invalid VkImage given by the embedder.";
51+
return nullptr;
52+
}
5453

55-
if (surface == nullptr) {
54+
sk_sp<SkSurface> surface = CreateSurfaceFromVulkanImage(
55+
reinterpret_cast<VkImage>(image.image),
56+
static_cast<VkFormat>(image.format), frame_size);
57+
if (!surface) {
58+
FML_LOG(ERROR) << "Could not create the SkSurface from the Vulkan image.";
5659
return nullptr;
5760
}
5861

59-
SurfaceFrame::SubmitCallback callback =
60-
[weak_this = weak_factory_.GetWeakPtr()](const SurfaceFrame&,
61-
SkCanvas* canvas) -> bool {
62-
// Frames are only ever acquired on the raster thread. This is also the
63-
// thread on which the weak pointer factory is collected (as this instance
64-
// is owned by the rasterizer). So this use of weak pointers is safe.
65-
if (canvas == nullptr || !weak_this) {
62+
SurfaceFrame::SubmitCallback callback = [image = image, delegate = delegate_](
63+
const SurfaceFrame&,
64+
SkCanvas* canvas) -> bool {
65+
TRACE_EVENT0("flutter", "GPUSurfaceVulkan::PresentImage");
66+
if (canvas == nullptr) {
67+
FML_DLOG(ERROR) << "Canvas not available.";
6668
return false;
6769
}
68-
return weak_this->window_.SwapBuffers();
70+
71+
canvas->flush();
72+
73+
return delegate->PresentImage(reinterpret_cast<VkImage>(image.image),
74+
static_cast<VkFormat>(image.format));
6975
};
76+
77+
SurfaceFrame::FramebufferInfo framebuffer_info{.supports_readback = true};
78+
7079
return std::make_unique<SurfaceFrame>(
7180
std::move(surface), std::move(framebuffer_info), std::move(callback));
7281
}
@@ -80,7 +89,54 @@ SkMatrix GPUSurfaceVulkan::GetRootTransformation() const {
8089
}
8190

8291
GrDirectContext* GPUSurfaceVulkan::GetContext() {
83-
return window_.GetSkiaGrContext();
92+
return skia_context_.get();
93+
}
94+
95+
sk_sp<SkSurface> GPUSurfaceVulkan::CreateSurfaceFromVulkanImage(
96+
const VkImage image,
97+
const VkFormat format,
98+
const SkISize& size) {
99+
GrVkImageInfo image_info = {
100+
.fImage = image,
101+
.fImageTiling = VK_IMAGE_TILING_OPTIMAL,
102+
.fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED,
103+
.fFormat = format,
104+
.fImageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
105+
VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
106+
VK_IMAGE_USAGE_TRANSFER_DST_BIT |
107+
VK_IMAGE_USAGE_SAMPLED_BIT,
108+
.fSampleCount = 1,
109+
.fLevelCount = 1,
110+
};
111+
GrBackendTexture backend_texture(size.width(), //
112+
size.height(), //
113+
image_info //
114+
);
115+
116+
SkSurfaceProps surface_properties(0, kUnknown_SkPixelGeometry);
117+
118+
return SkSurface::MakeFromBackendTexture(
119+
skia_context_.get(), // context
120+
backend_texture, // back-end texture
121+
kTopLeft_GrSurfaceOrigin, // surface origin
122+
1, // sample count
123+
ColorTypeFromFormat(format), // color type
124+
SkColorSpace::MakeSRGB(), // color space
125+
&surface_properties // surface properties
126+
);
127+
}
128+
129+
SkColorType GPUSurfaceVulkan::ColorTypeFromFormat(const VkFormat format) {
130+
switch (format) {
131+
case VK_FORMAT_R8G8B8A8_UNORM:
132+
case VK_FORMAT_R8G8B8A8_SRGB:
133+
return SkColorType::kRGBA_8888_SkColorType;
134+
case VK_FORMAT_B8G8R8A8_UNORM:
135+
case VK_FORMAT_B8G8R8A8_SRGB:
136+
return SkColorType::kBGRA_8888_SkColorType;
137+
default:
138+
return SkColorType::kUnknown_SkColorType;
139+
}
84140
}
85141

86142
} // namespace flutter

shell/gpu/gpu_surface_vulkan.h

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,29 +11,25 @@
1111
#include "flutter/fml/macros.h"
1212
#include "flutter/fml/memory/weak_ptr.h"
1313
#include "flutter/shell/gpu/gpu_surface_vulkan_delegate.h"
14+
#include "flutter/vulkan/vulkan_backbuffer.h"
1415
#include "flutter/vulkan/vulkan_native_surface.h"
1516
#include "flutter/vulkan/vulkan_window.h"
1617
#include "include/core/SkRefCnt.h"
1718

1819
namespace flutter {
1920

21+
//------------------------------------------------------------------------------
22+
/// @brief A GPU surface backed by VkImages provided by a
23+
/// GPUSurfaceVulkanDelegate.
24+
///
2025
class GPUSurfaceVulkan : public Surface {
2126
public:
22-
//------------------------------------------------------------------------------
23-
/// @brief Create a GPUSurfaceVulkan which implicitly creates its own
24-
/// GrDirectContext for Skia.
25-
///
26-
GPUSurfaceVulkan(GPUSurfaceVulkanDelegate* delegate,
27-
std::unique_ptr<vulkan::VulkanNativeSurface> native_surface,
28-
bool render_to_surface);
29-
3027
//------------------------------------------------------------------------------
3128
/// @brief Create a GPUSurfaceVulkan while letting it reuse an existing
3229
/// GrDirectContext.
3330
///
34-
GPUSurfaceVulkan(const sk_sp<GrDirectContext>& context,
35-
GPUSurfaceVulkanDelegate* delegate,
36-
std::unique_ptr<vulkan::VulkanNativeSurface> native_surface,
31+
GPUSurfaceVulkan(GPUSurfaceVulkanDelegate* delegate,
32+
const sk_sp<GrDirectContext>& context,
3733
bool render_to_surface);
3834

3935
~GPUSurfaceVulkan() override;
@@ -50,11 +46,19 @@ class GPUSurfaceVulkan : public Surface {
5046
// |Surface|
5147
GrDirectContext* GetContext() override;
5248

49+
static SkColorType ColorTypeFromFormat(const VkFormat format);
50+
5351
private:
54-
vulkan::VulkanWindow window_;
55-
const bool render_to_surface_;
52+
GPUSurfaceVulkanDelegate* delegate_;
53+
sk_sp<GrDirectContext> skia_context_;
54+
bool render_to_surface_;
5655

5756
fml::WeakPtrFactory<GPUSurfaceVulkan> weak_factory_;
57+
58+
sk_sp<SkSurface> CreateSurfaceFromVulkanImage(const VkImage image,
59+
const VkFormat format,
60+
const SkISize& size);
61+
5862
FML_DISALLOW_COPY_AND_ASSIGN(GPUSurfaceVulkan);
5963
};
6064

shell/gpu/gpu_surface_vulkan_delegate.h

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,43 @@
66
#define FLUTTER_SHELL_GPU_GPU_SURFACE_VULKAN_DELEGATE_H_
77

88
#include "flutter/fml/memory/ref_ptr.h"
9+
#include "flutter/shell/platform/embedder/embedder.h"
10+
#include "flutter/vulkan/vulkan_device.h"
11+
#include "flutter/vulkan/vulkan_image.h"
912
#include "flutter/vulkan/vulkan_proc_table.h"
13+
#include "third_party/skia/include/core/SkSize.h"
1014

1115
namespace flutter {
1216

17+
//------------------------------------------------------------------------------
18+
/// @brief Interface implemented by all platform surfaces that can present
19+
/// a Vulkan backing store to the "screen". The GPU surface
20+
/// abstraction (which abstracts the client rendering API) uses this
21+
/// delegation pattern to tell the platform surface (which abstracts
22+
/// how backing stores fulfilled by the selected client rendering
23+
/// API end up on the "screen" on a particular platform) when the
24+
/// rasterizer needs to allocate and present the Vulkan backing
25+
/// store.
26+
///
27+
/// @see |EmbedderSurfaceVulkan|.
28+
///
1329
class GPUSurfaceVulkanDelegate {
1430
public:
15-
~GPUSurfaceVulkanDelegate();
31+
virtual ~GPUSurfaceVulkanDelegate();
1632

17-
// Obtain a reference to the Vulkan implementation's proc table.
18-
virtual fml::RefPtr<vulkan::VulkanProcTable> vk() = 0;
33+
/// @brief Obtain a reference to the Vulkan implementation's proc table.
34+
///
35+
virtual const vulkan::VulkanProcTable& vk() = 0;
36+
37+
/// @brief Called by the engine to fetch a VkImage for writing the next
38+
/// frame.
39+
///
40+
virtual FlutterVulkanImage AcquireImage(const SkISize& size) = 0;
41+
42+
/// @brief Called by the engine once a frame has been rendered to the image
43+
/// and it's ready to be bound for further reading/writing.
44+
///
45+
virtual bool PresentImage(VkImage image, VkFormat format) = 0;
1946
};
2047

2148
} // namespace flutter

shell/platform/embedder/BUILD.gn

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,13 @@ template("embedder_source_set") {
109109
deps += [ "//flutter/shell/platform/darwin/graphics" ]
110110
}
111111

112+
if (embedder_enable_vulkan) {
113+
sources += [
114+
"embedder_surface_vulkan.cc",
115+
"embedder_surface_vulkan.h",
116+
]
117+
}
118+
112119
public_deps = [ ":embedder_headers" ]
113120

114121
public_configs += [
@@ -168,6 +175,8 @@ test_fixtures("fixtures") {
168175
"fixtures/dpr_noxform.png",
169176
"fixtures/dpr_xform.png",
170177
"fixtures/gradient.png",
178+
"fixtures/vk_dpr_noxform.png",
179+
"fixtures/vk_gradient.png",
171180
"fixtures/gradient_metal.png",
172181
"fixtures/external_texture_metal.png",
173182
"fixtures/gradient_xform.png",
@@ -250,6 +259,13 @@ if (enable_unittests) {
250259
}
251260

252261
if (test_enable_vulkan) {
262+
sources += [
263+
"tests/embedder_test_compositor_vulkan.cc",
264+
"tests/embedder_test_compositor_vulkan.h",
265+
"tests/embedder_test_context_vulkan.cc",
266+
"tests/embedder_test_context_vulkan.h",
267+
]
268+
253269
deps += [
254270
"//flutter/testing:vulkan",
255271
"//flutter/vulkan",

0 commit comments

Comments
 (0)