[Impeller] Implement GPU Surface Vulkan for Impeller (flutter/engine#37215)
This commit is contained in:
@@ -2114,6 +2114,8 @@ FILE: ../../../flutter/shell/gpu/gpu_surface_vulkan.cc
|
||||
FILE: ../../../flutter/shell/gpu/gpu_surface_vulkan.h
|
||||
FILE: ../../../flutter/shell/gpu/gpu_surface_vulkan_delegate.cc
|
||||
FILE: ../../../flutter/shell/gpu/gpu_surface_vulkan_delegate.h
|
||||
FILE: ../../../flutter/shell/gpu/gpu_surface_vulkan_impeller.cc
|
||||
FILE: ../../../flutter/shell/gpu/gpu_surface_vulkan_impeller.h
|
||||
FILE: ../../../flutter/shell/platform/android/AndroidManifest.xml
|
||||
FILE: ../../../flutter/shell/platform/android/android_choreographer.cc
|
||||
FILE: ../../../flutter/shell/platform/android/android_choreographer.h
|
||||
|
||||
@@ -58,6 +58,15 @@ source_set("gpu_surface_vulkan") {
|
||||
"//flutter/vulkan",
|
||||
"//flutter/vulkan/procs",
|
||||
]
|
||||
|
||||
if (impeller_enable_vulkan) {
|
||||
sources += [
|
||||
"gpu_surface_vulkan_impeller.cc",
|
||||
"gpu_surface_vulkan_impeller.h",
|
||||
]
|
||||
|
||||
public_deps += [ "//flutter/impeller" ]
|
||||
}
|
||||
}
|
||||
|
||||
source_set("gpu_surface_metal") {
|
||||
|
||||
138
engine/src/flutter/shell/gpu/gpu_surface_vulkan_impeller.cc
Normal file
138
engine/src/flutter/shell/gpu/gpu_surface_vulkan_impeller.cc
Normal file
@@ -0,0 +1,138 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flutter/shell/gpu/gpu_surface_vulkan_impeller.h"
|
||||
|
||||
#include "flutter/fml/make_copyable.h"
|
||||
#include "flutter/impeller/display_list/display_list_dispatcher.h"
|
||||
#include "flutter/impeller/renderer/renderer.h"
|
||||
#include "impeller/renderer/backend/vulkan/context_vk.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
GPUSurfaceVulkanImpeller::GPUSurfaceVulkanImpeller(
|
||||
std::shared_ptr<impeller::Context> context)
|
||||
: weak_factory_(this) {
|
||||
if (!context || !context->IsValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto renderer = std::make_shared<impeller::Renderer>(context);
|
||||
if (!renderer->IsValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto aiks_context = std::make_shared<impeller::AiksContext>(context);
|
||||
if (!aiks_context->IsValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
impeller_context_ = std::move(context);
|
||||
impeller_renderer_ = std::move(renderer);
|
||||
aiks_context_ = std::move(aiks_context);
|
||||
is_valid_ = true;
|
||||
}
|
||||
|
||||
// |Surface|
|
||||
GPUSurfaceVulkanImpeller::~GPUSurfaceVulkanImpeller() = default;
|
||||
|
||||
// |Surface|
|
||||
bool GPUSurfaceVulkanImpeller::IsValid() {
|
||||
return is_valid_;
|
||||
}
|
||||
|
||||
// |Surface|
|
||||
std::unique_ptr<SurfaceFrame> GPUSurfaceVulkanImpeller::AcquireFrame(
|
||||
const SkISize& size) {
|
||||
if (!IsValid()) {
|
||||
FML_LOG(ERROR) << "Vulkan surface was invalid.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (size.isEmpty()) {
|
||||
FML_LOG(ERROR) << "Vulkan surface was asked for an empty frame.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto& context_vk = impeller::ContextVK::Cast(*impeller_context_);
|
||||
std::unique_ptr<impeller::Surface> surface =
|
||||
context_vk.AcquireSurface(frame_num_++);
|
||||
|
||||
auto swap_callback = [weak = weak_factory_.GetWeakPtr()]() -> bool {
|
||||
if (weak) {
|
||||
// TODO (kaushikiska@): Invoke the clean-up callback.
|
||||
// Blocked by - https://github.com/flutter/flutter/issues/112387
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
SurfaceFrame::SubmitCallback submit_callback =
|
||||
fml::MakeCopyable([renderer = impeller_renderer_, //
|
||||
aiks_context = aiks_context_, //
|
||||
surface = std::move(surface) //
|
||||
](SurfaceFrame& surface_frame, SkCanvas* canvas) mutable -> bool {
|
||||
if (!aiks_context) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto display_list = surface_frame.BuildDisplayList();
|
||||
if (!display_list) {
|
||||
FML_LOG(ERROR) << "Could not build display list for surface frame.";
|
||||
return false;
|
||||
}
|
||||
|
||||
impeller::DisplayListDispatcher impeller_dispatcher;
|
||||
display_list->Dispatch(impeller_dispatcher);
|
||||
auto picture = impeller_dispatcher.EndRecordingAsPicture();
|
||||
|
||||
return renderer->Render(
|
||||
std::move(surface),
|
||||
fml::MakeCopyable(
|
||||
[aiks_context, picture = std::move(picture)](
|
||||
impeller::RenderTarget& render_target) -> bool {
|
||||
return aiks_context->Render(picture, render_target);
|
||||
}));
|
||||
});
|
||||
|
||||
return std::make_unique<SurfaceFrame>(
|
||||
nullptr, // surface
|
||||
SurfaceFrame::FramebufferInfo{}, // framebuffer info
|
||||
submit_callback, // submit callback
|
||||
size, // frame size
|
||||
nullptr, // context result
|
||||
true // display list fallback
|
||||
);
|
||||
}
|
||||
|
||||
// |Surface|
|
||||
SkMatrix GPUSurfaceVulkanImpeller::GetRootTransformation() const {
|
||||
// This backend does not currently support root surface transformations. Just
|
||||
// return identity.
|
||||
return {};
|
||||
}
|
||||
|
||||
// |Surface|
|
||||
GrDirectContext* GPUSurfaceVulkanImpeller::GetContext() {
|
||||
// Impeller != Skia.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// |Surface|
|
||||
std::unique_ptr<GLContextResult>
|
||||
GPUSurfaceVulkanImpeller::MakeRenderContextCurrent() {
|
||||
// This backend has no such concept.
|
||||
return std::make_unique<GLContextDefaultResult>(true);
|
||||
}
|
||||
|
||||
// |Surface|
|
||||
bool GPUSurfaceVulkanImpeller::EnableRasterCache() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
// |Surface|
|
||||
impeller::AiksContext* GPUSurfaceVulkanImpeller::GetAiksContext() const {
|
||||
return aiks_context_.get();
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
56
engine/src/flutter/shell/gpu/gpu_surface_vulkan_impeller.h
Normal file
56
engine/src/flutter/shell/gpu/gpu_surface_vulkan_impeller.h
Normal file
@@ -0,0 +1,56 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "flutter/common/graphics/gl_context_switch.h"
|
||||
#include "flutter/flow/surface.h"
|
||||
#include "flutter/fml/macros.h"
|
||||
#include "flutter/fml/memory/weak_ptr.h"
|
||||
#include "flutter/impeller/aiks/aiks_context.h"
|
||||
#include "flutter/impeller/renderer/context.h"
|
||||
#include "flutter/shell/gpu/gpu_surface_vulkan_delegate.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
class GPUSurfaceVulkanImpeller final : public Surface {
|
||||
public:
|
||||
explicit GPUSurfaceVulkanImpeller(std::shared_ptr<impeller::Context> context);
|
||||
|
||||
// |Surface|
|
||||
~GPUSurfaceVulkanImpeller() override;
|
||||
|
||||
// |Surface|
|
||||
bool IsValid() override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<impeller::Context> impeller_context_;
|
||||
std::shared_ptr<impeller::Renderer> impeller_renderer_;
|
||||
std::shared_ptr<impeller::AiksContext> aiks_context_;
|
||||
bool is_valid_ = false;
|
||||
uint64_t frame_num_ = 0;
|
||||
fml::WeakPtrFactory<GPUSurfaceVulkanImpeller> weak_factory_;
|
||||
|
||||
// |Surface|
|
||||
std::unique_ptr<SurfaceFrame> AcquireFrame(const SkISize& size) override;
|
||||
|
||||
// |Surface|
|
||||
SkMatrix GetRootTransformation() const override;
|
||||
|
||||
// |Surface|
|
||||
GrDirectContext* GetContext() override;
|
||||
|
||||
// |Surface|
|
||||
std::unique_ptr<GLContextResult> MakeRenderContextCurrent() override;
|
||||
|
||||
// |Surface|
|
||||
bool EnableRasterCache() const override;
|
||||
|
||||
// |Surface|
|
||||
impeller::AiksContext* GetAiksContext() const override;
|
||||
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(GPUSurfaceVulkanImpeller);
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
@@ -17,7 +17,7 @@ class VulkanNativeSurfaceAndroid : public VulkanNativeSurface {
|
||||
public:
|
||||
/// Create a native surface from the valid ANativeWindow reference. Ownership
|
||||
/// of the ANativeWindow is assumed by this instance.
|
||||
VulkanNativeSurfaceAndroid(ANativeWindow* native_window);
|
||||
explicit VulkanNativeSurfaceAndroid(ANativeWindow* native_window);
|
||||
|
||||
~VulkanNativeSurfaceAndroid();
|
||||
|
||||
|
||||
@@ -5,9 +5,12 @@
|
||||
#include "vulkan_swapchain.h"
|
||||
|
||||
#include "flutter/vulkan/procs/vulkan_proc_table.h"
|
||||
|
||||
#include "third_party/skia/include/core/SkColorSpace.h"
|
||||
#include "third_party/skia/include/gpu/GrBackendSurface.h"
|
||||
#include "third_party/skia/include/gpu/GrDirectContext.h"
|
||||
#include "third_party/skia/include/gpu/vk/GrVkTypes.h"
|
||||
|
||||
#include "vulkan_backbuffer.h"
|
||||
#include "vulkan_device.h"
|
||||
#include "vulkan_image.h"
|
||||
@@ -147,11 +150,11 @@ VulkanSwapchain::VulkanSwapchain(const VulkanProcTable& p_vk,
|
||||
return;
|
||||
}
|
||||
|
||||
swapchain_ = {swapchain, [this](VkSwapchainKHR swapchain) {
|
||||
FML_ALLOW_UNUSED_LOCAL(device_.WaitIdle());
|
||||
vk.DestroySwapchainKHR(device_.GetHandle(), swapchain,
|
||||
nullptr);
|
||||
}};
|
||||
swapchain_ = VulkanHandle<VkSwapchainKHR>{
|
||||
swapchain, [this](VkSwapchainKHR swapchain) {
|
||||
FML_ALLOW_UNUSED_LOCAL(device_.WaitIdle());
|
||||
vk.DestroySwapchainKHR(device_.GetHandle(), swapchain, nullptr);
|
||||
}};
|
||||
|
||||
if (!CreateSwapchainImages(
|
||||
skia_context, format_infos[format_index].color_type_,
|
||||
@@ -275,7 +278,11 @@ bool VulkanSwapchain::CreateSwapchainImages(GrDirectContext* skia_context,
|
||||
backbuffers_.emplace_back(std::move(backbuffer));
|
||||
|
||||
// Populate the image.
|
||||
auto vulkan_image = std::make_unique<VulkanImage>(image);
|
||||
VulkanHandle<VkImage> image_handle = VulkanHandle<VkImage>{
|
||||
image, [this](VkImage image) {
|
||||
vk.DestroyImage(device_.GetHandle(), image, nullptr);
|
||||
}};
|
||||
auto vulkan_image = std::make_unique<VulkanImage>(std::move(image_handle));
|
||||
|
||||
if (!vulkan_image->IsValid()) {
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user