Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vulkan support in the Embedder API #29391

Merged
merged 60 commits into from
Feb 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
99a8037
Rebase atop https://github.com/flutter/engine/pull/29520
bdero Oct 19, 2021
3586854
Make sksurface from vkimage
bdero Nov 14, 2021
f5a46d8
Add EmbedderSurface for Vulkan, init skia contexts, correct API callb…
bdero Nov 16, 2021
aa07175
Make GPUSurfaceVulkan use delegate (EmbedderSurfaceVulkan) and create…
bdero Nov 17, 2021
e2280fd
Build fixup
bdero Nov 17, 2021
0572e70
API change: Move backing store specific stuff out of FlutterVulkanImage
bdero Nov 18, 2021
a6a78f9
Build fixes
bdero Nov 18, 2021
73fb9a9
Format
bdero Nov 18, 2021
5bcd4df
embedder_test.cc format
bdero Nov 18, 2021
78a5f5a
Licenses
bdero Nov 18, 2021
a230d2d
Gate vk config initialization
bdero Nov 18, 2021
71465a3
Explicit constructor calls for VulkanHandle
bdero Nov 20, 2021
9e44701
Add test context that can be passed around, create a skia context for…
bdero Nov 20, 2021
6da3ce2
Format
bdero Nov 24, 2021
fa46278
Fix extension init segfault
bdero Nov 24, 2021
07adc2d
Heap alloc the test context and surface
bdero Nov 30, 2021
58c4ad0
Fix EmbedderSurfaceVulkan destruct crash
bdero Dec 2, 2021
991655b
Validate vulkan render config
bdero Dec 2, 2021
da9ee48
Allocate image memory for test surface; parameterize a GL raster test
bdero Dec 2, 2021
bec156f
vk test image
bdero Dec 9, 2021
37d698d
Fix vk gradient
bdero Dec 9, 2021
2766172
Get render target from target
bdero Dec 9, 2021
9afe4e2
Compositor gradient test
bdero Dec 9, 2021
33941fc
Add test harness compositor (never finishes frame render for some rea…
bdero Dec 9, 2021
e26ba47
Extensions
bdero Dec 9, 2021
4b28c39
Format
bdero Dec 9, 2021
ff68811
Licenses
bdero Dec 14, 2021
39b23b9
Don't test root layer xform in vulkan (not supported in the API)
bdero Dec 14, 2021
2831cba
Make TestVulkanContext destruct after the compositor, create VkImages…
bdero Dec 14, 2021
0e90172
Format
bdero Dec 14, 2021
a5f7ec7
Parameterize CanCreateEmbedderWithCustomRenderTaskRunnerTheSameAsPlat…
bdero Dec 14, 2021
3fa1598
Parameterize CompositorMustBeAbleToRenderKnownScenePixelRatioOnSurface
bdero Dec 14, 2021
9f49cb0
Parameterize PlatformViewMutatorsAreValid, intrusively refcount TestV…
bdero Dec 15, 2021
f98c46c
Make FlutterVulkanImageHandle a uint64_t and internally cast to VkImage
bdero Dec 16, 2021
2f4927c
Add format field to FlutterVulkanImage
bdero Jan 6, 2022
1624ffa
Add format cast to make windows targets happy
bdero Jan 6, 2022
d8c7003
Add Vulkan version parameter to FlutterVulkanRendererConfig
bdero Jan 6, 2022
29af39c
Fix cast
bdero Jan 6, 2022
fec4c06
Activate memory_requirements_2 if the Vulkan version is >= 1.1
bdero Jan 6, 2022
6e11d8a
Allow the embedder to optionally supply enabled instance/device exten…
bdero Jan 7, 2022
5f861aa
Make vulkan names and docstrings clearer for extensions
bdero Jan 10, 2022
fffac57
Inline vulkan image fields in FlutterVulkanBackingStore
bdero Jan 10, 2022
f207dfb
Reference issue # instead of user handle
bdero Jan 20, 2022
e4dd1c7
Explicitly release skia context on test vulkan context destruction to…
bdero Jan 21, 2022
6a76c82
Use better names and add docstrings for the test utilities
bdero Jan 21, 2022
93d67ab
Lifetime comments and remove unnecessary ref count bump
bdero Jan 22, 2022
0d1687c
Use a pointer to a const FlutterVulkanImage instead of inlining field…
bdero Jan 22, 2022
a510bfd
Force refcounted skia contexts to collect in EmbedderSurfaceVulkan
bdero Jan 22, 2022
a48c201
Fix OS defines
bdero Jan 31, 2022
aec5449
Disable swiftshader tests for FEMU
bdero Feb 1, 2022
63b879f
Revert "Disable swiftshader tests for FEMU"
bdero Feb 1, 2022
2442a95
Try falling back to libvulkan.so if swiftshader is missing
bdero Feb 1, 2022
f5bfc9a
Use NativeLibrary to detect existence of the ICD
bdero Feb 1, 2022
9f2584d
Add test debug logs to see what's going on in FEMU
bdero Feb 1, 2022
166b26a
Add log so that the ICD being used is always printed
bdero Feb 1, 2022
20a2368
Remove temp logs
bdero Feb 1, 2022
8bbacf0
Guard against null contexts in destructors
bdero Feb 2, 2022
82e8c97
Test logs
bdero Feb 2, 2022
eedf60b
Lazily create the backingstore_producer vulkan context
bdero Feb 2, 2022
63f0b5f
Revert "Test logs"
bdero Feb 2, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -1365,6 +1365,8 @@ FILE: ../../../flutter/shell/platform/embedder/embedder_surface_metal.h
FILE: ../../../flutter/shell/platform/embedder/embedder_surface_metal.mm
FILE: ../../../flutter/shell/platform/embedder/embedder_surface_software.cc
FILE: ../../../flutter/shell/platform/embedder/embedder_surface_software.h
FILE: ../../../flutter/shell/platform/embedder/embedder_surface_vulkan.cc
FILE: ../../../flutter/shell/platform/embedder/embedder_surface_vulkan.h
FILE: ../../../flutter/shell/platform/embedder/embedder_task_runner.cc
FILE: ../../../flutter/shell/platform/embedder/embedder_task_runner.h
FILE: ../../../flutter/shell/platform/embedder/embedder_thread_host.cc
Expand All @@ -1387,6 +1389,8 @@ FILE: ../../../flutter/shell/platform/embedder/fixtures/scene_without_custom_com
FILE: ../../../flutter/shell/platform/embedder/fixtures/snapshot_large_scene.png
FILE: ../../../flutter/shell/platform/embedder/fixtures/verifyb143464703.png
FILE: ../../../flutter/shell/platform/embedder/fixtures/verifyb143464703_soft_noxform.png
FILE: ../../../flutter/shell/platform/embedder/fixtures/vk_dpr_noxform.png
FILE: ../../../flutter/shell/platform/embedder/fixtures/vk_gradient.png
FILE: ../../../flutter/shell/platform/embedder/platform_view_embedder.cc
FILE: ../../../flutter/shell/platform/embedder/platform_view_embedder.h
FILE: ../../../flutter/shell/platform/embedder/test_utils/key_codes.h
Expand Down
5 changes: 3 additions & 2 deletions shell/gpu/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,9 @@ source_set("gpu_surface_vulkan") {
"gpu_surface_vulkan_delegate.cc",
"gpu_surface_vulkan_delegate.h",
]

deps = gpu_common_deps + [ "//flutter/vulkan" ]
deps = [ "//flutter/shell/platform/embedder:embedder_headers" ]
deps += gpu_common_deps
public_deps = [ "//flutter/vulkan" ]
}

source_set("gpu_surface_metal") {
Expand Down
4 changes: 2 additions & 2 deletions shell/gpu/gpu_surface_metal_delegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,14 @@ class GPUSurfaceMetalDelegate {

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

//------------------------------------------------------------------------------
/// @brief Presents the texture with `texture_id` to the "screen".
/// `texture_id` corresponds to a texture that has been obtained by an earlier
/// call to `GetMTLTexture`. This is only called when the specefied render
/// call to `GetMTLTexture`. This is only called when the specified render
/// target type is `kMTLTexture`.
///
/// @see |GPUSurfaceMetalDelegate::GetMTLTexture|
Expand Down
128 changes: 92 additions & 36 deletions shell/gpu/gpu_surface_vulkan.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,68 +5,77 @@
#include "flutter/shell/gpu/gpu_surface_vulkan.h"

#include "flutter/fml/logging.h"
#include "fml/trace_event.h"
#include "include/core/SkSize.h"
#include "third_party/swiftshader/include/vulkan/vulkan_core.h"

namespace flutter {

GPUSurfaceVulkan::GPUSurfaceVulkan(
GPUSurfaceVulkanDelegate* delegate,
std::unique_ptr<vulkan::VulkanNativeSurface> native_surface,
bool render_to_surface)
: GPUSurfaceVulkan(/*context=*/nullptr,
delegate,
std::move(native_surface),
render_to_surface) {}

GPUSurfaceVulkan::GPUSurfaceVulkan(
const sk_sp<GrDirectContext>& context,
GPUSurfaceVulkanDelegate* delegate,
std::unique_ptr<vulkan::VulkanNativeSurface> native_surface,
bool render_to_surface)
: window_(context,
delegate->vk(),
std::move(native_surface),
render_to_surface),
GPUSurfaceVulkan::GPUSurfaceVulkan(GPUSurfaceVulkanDelegate* delegate,
const sk_sp<GrDirectContext>& skia_context,
bool render_to_surface)
: delegate_(delegate),
skia_context_(skia_context),
render_to_surface_(render_to_surface),
weak_factory_(this) {}

GPUSurfaceVulkan::~GPUSurfaceVulkan() = default;

bool GPUSurfaceVulkan::IsValid() {
return window_.IsValid();
return skia_context_ != nullptr;
}

std::unique_ptr<SurfaceFrame> GPUSurfaceVulkan::AcquireFrame(
const SkISize& size) {
SurfaceFrame::FramebufferInfo framebuffer_info;
framebuffer_info.supports_readback = true;
const SkISize& frame_size) {
if (!IsValid()) {
FML_LOG(ERROR) << "Vulkan surface was invalid.";
return nullptr;
}

if (frame_size.isEmpty()) {
FML_LOG(ERROR) << "Vulkan surface was asked for an empty frame.";
return nullptr;
}

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

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

if (surface == nullptr) {
sk_sp<SkSurface> surface = CreateSurfaceFromVulkanImage(
reinterpret_cast<VkImage>(image.image),
static_cast<VkFormat>(image.format), frame_size);
if (!surface) {
FML_LOG(ERROR) << "Could not create the SkSurface from the Vulkan image.";
return nullptr;
}

SurfaceFrame::SubmitCallback callback =
[weak_this = weak_factory_.GetWeakPtr()](const SurfaceFrame&,
SkCanvas* canvas) -> bool {
// Frames are only ever acquired on the raster thread. This is also the
// thread on which the weak pointer factory is collected (as this instance
// is owned by the rasterizer). So this use of weak pointers is safe.
if (canvas == nullptr || !weak_this) {
SurfaceFrame::SubmitCallback callback = [image = image, delegate = delegate_](
const SurfaceFrame&,
SkCanvas* canvas) -> bool {
TRACE_EVENT0("flutter", "GPUSurfaceVulkan::PresentImage");
if (canvas == nullptr) {
FML_DLOG(ERROR) << "Canvas not available.";
return false;
}
return weak_this->window_.SwapBuffers();

canvas->flush();

return delegate->PresentImage(reinterpret_cast<VkImage>(image.image),
static_cast<VkFormat>(image.format));
};

SurfaceFrame::FramebufferInfo framebuffer_info{.supports_readback = true};

return std::make_unique<SurfaceFrame>(
std::move(surface), std::move(framebuffer_info), std::move(callback));
}
Expand All @@ -80,7 +89,54 @@ SkMatrix GPUSurfaceVulkan::GetRootTransformation() const {
}

GrDirectContext* GPUSurfaceVulkan::GetContext() {
return window_.GetSkiaGrContext();
return skia_context_.get();
}

sk_sp<SkSurface> GPUSurfaceVulkan::CreateSurfaceFromVulkanImage(
bdero marked this conversation as resolved.
Show resolved Hide resolved
const VkImage image,
const VkFormat format,
const SkISize& size) {
GrVkImageInfo image_info = {
.fImage = image,
.fImageTiling = VK_IMAGE_TILING_OPTIMAL,
.fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.fFormat = format,
.fImageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
VK_IMAGE_USAGE_TRANSFER_DST_BIT |
VK_IMAGE_USAGE_SAMPLED_BIT,
.fSampleCount = 1,
.fLevelCount = 1,
};
GrBackendTexture backend_texture(size.width(), //
size.height(), //
image_info //
);

SkSurfaceProps surface_properties(0, kUnknown_SkPixelGeometry);

return SkSurface::MakeFromBackendTexture(
skia_context_.get(), // context
backend_texture, // back-end texture
kTopLeft_GrSurfaceOrigin, // surface origin
1, // sample count
ColorTypeFromFormat(format), // color type
SkColorSpace::MakeSRGB(), // color space
&surface_properties // surface properties
);
}

SkColorType GPUSurfaceVulkan::ColorTypeFromFormat(const VkFormat format) {
switch (format) {
case VK_FORMAT_R8G8B8A8_UNORM:
case VK_FORMAT_R8G8B8A8_SRGB:
return SkColorType::kRGBA_8888_SkColorType;
case VK_FORMAT_B8G8R8A8_UNORM:
case VK_FORMAT_B8G8R8A8_SRGB:
return SkColorType::kBGRA_8888_SkColorType;
default:
return SkColorType::kUnknown_SkColorType;
}
}

} // namespace flutter
30 changes: 17 additions & 13 deletions shell/gpu/gpu_surface_vulkan.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,25 @@
#include "flutter/fml/macros.h"
#include "flutter/fml/memory/weak_ptr.h"
#include "flutter/shell/gpu/gpu_surface_vulkan_delegate.h"
#include "flutter/vulkan/vulkan_backbuffer.h"
#include "flutter/vulkan/vulkan_native_surface.h"
#include "flutter/vulkan/vulkan_window.h"
#include "include/core/SkRefCnt.h"

namespace flutter {

//------------------------------------------------------------------------------
/// @brief A GPU surface backed by VkImages provided by a
/// GPUSurfaceVulkanDelegate.
///
class GPUSurfaceVulkan : public Surface {
public:
//------------------------------------------------------------------------------
/// @brief Create a GPUSurfaceVulkan which implicitly creates its own
/// GrDirectContext for Skia.
///
GPUSurfaceVulkan(GPUSurfaceVulkanDelegate* delegate,
std::unique_ptr<vulkan::VulkanNativeSurface> native_surface,
bool render_to_surface);

//------------------------------------------------------------------------------
/// @brief Create a GPUSurfaceVulkan while letting it reuse an existing
/// GrDirectContext.
///
GPUSurfaceVulkan(const sk_sp<GrDirectContext>& context,
GPUSurfaceVulkanDelegate* delegate,
std::unique_ptr<vulkan::VulkanNativeSurface> native_surface,
GPUSurfaceVulkan(GPUSurfaceVulkanDelegate* delegate,
const sk_sp<GrDirectContext>& context,
bool render_to_surface);

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

static SkColorType ColorTypeFromFormat(const VkFormat format);

private:
vulkan::VulkanWindow window_;
const bool render_to_surface_;
GPUSurfaceVulkanDelegate* delegate_;
sk_sp<GrDirectContext> skia_context_;
bool render_to_surface_;

fml::WeakPtrFactory<GPUSurfaceVulkan> weak_factory_;

sk_sp<SkSurface> CreateSurfaceFromVulkanImage(const VkImage image,
const VkFormat format,
const SkISize& size);

FML_DISALLOW_COPY_AND_ASSIGN(GPUSurfaceVulkan);
};

Expand Down
33 changes: 30 additions & 3 deletions shell/gpu/gpu_surface_vulkan_delegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,43 @@
#define FLUTTER_SHELL_GPU_GPU_SURFACE_VULKAN_DELEGATE_H_

#include "flutter/fml/memory/ref_ptr.h"
#include "flutter/shell/platform/embedder/embedder.h"
#include "flutter/vulkan/vulkan_device.h"
#include "flutter/vulkan/vulkan_image.h"
#include "flutter/vulkan/vulkan_proc_table.h"
#include "third_party/skia/include/core/SkSize.h"

namespace flutter {

//------------------------------------------------------------------------------
/// @brief Interface implemented by all platform surfaces that can present
/// a Vulkan backing store to the "screen". The GPU surface
/// abstraction (which abstracts the client rendering API) uses this
/// delegation pattern to tell the platform surface (which abstracts
/// how backing stores fulfilled by the selected client rendering
/// API end up on the "screen" on a particular platform) when the
/// rasterizer needs to allocate and present the Vulkan backing
/// store.
///
/// @see |EmbedderSurfaceVulkan|.
///
class GPUSurfaceVulkanDelegate {
public:
~GPUSurfaceVulkanDelegate();
virtual ~GPUSurfaceVulkanDelegate();

// Obtain a reference to the Vulkan implementation's proc table.
virtual fml::RefPtr<vulkan::VulkanProcTable> vk() = 0;
/// @brief Obtain a reference to the Vulkan implementation's proc table.
///
virtual const vulkan::VulkanProcTable& vk() = 0;

/// @brief Called by the engine to fetch a VkImage for writing the next
/// frame.
///
virtual FlutterVulkanImage AcquireImage(const SkISize& size) = 0;

/// @brief Called by the engine once a frame has been rendered to the image
/// and it's ready to be bound for further reading/writing.
///
virtual bool PresentImage(VkImage image, VkFormat format) = 0;
};

} // namespace flutter
Expand Down
16 changes: 16 additions & 0 deletions shell/platform/embedder/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,13 @@ template("embedder_source_set") {
deps += [ "//flutter/shell/platform/darwin/graphics" ]
}

if (embedder_enable_vulkan) {
sources += [
"embedder_surface_vulkan.cc",
"embedder_surface_vulkan.h",
]
}

public_deps = [ ":embedder_headers" ]

public_configs += [
Expand Down Expand Up @@ -168,6 +175,8 @@ test_fixtures("fixtures") {
"fixtures/dpr_noxform.png",
"fixtures/dpr_xform.png",
"fixtures/gradient.png",
"fixtures/vk_dpr_noxform.png",
"fixtures/vk_gradient.png",
"fixtures/gradient_metal.png",
"fixtures/external_texture_metal.png",
"fixtures/gradient_xform.png",
Expand Down Expand Up @@ -250,6 +259,13 @@ if (enable_unittests) {
}

if (test_enable_vulkan) {
sources += [
"tests/embedder_test_compositor_vulkan.cc",
"tests/embedder_test_compositor_vulkan.h",
"tests/embedder_test_context_vulkan.cc",
"tests/embedder_test_context_vulkan.h",
]

deps += [
"//flutter/testing:vulkan",
"//flutter/vulkan",
Expand Down
Loading