Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

[Impeller] Wire-up AndroidSurfaceImpellerVulkan #37249

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -2144,6 +2144,8 @@ FILE: ../../../flutter/shell/platform/android/android_surface_gl_skia.cc
FILE: ../../../flutter/shell/platform/android/android_surface_gl_skia.h
FILE: ../../../flutter/shell/platform/android/android_surface_software.cc
FILE: ../../../flutter/shell/platform/android/android_surface_software.h
FILE: ../../../flutter/shell/platform/android/android_surface_vulkan_impeller.cc
FILE: ../../../flutter/shell/platform/android/android_surface_vulkan_impeller.h
FILE: ../../../flutter/shell/platform/android/apk_asset_provider.cc
FILE: ../../../flutter/shell/platform/android/apk_asset_provider.h
FILE: ../../../flutter/shell/platform/android/apk_asset_provider_unittests.cc
Expand Down
6 changes: 6 additions & 0 deletions impeller/renderer/backend/vulkan/context_vk.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "impeller/renderer/backend/vulkan/allocator_vk.h"
#include "impeller/renderer/backend/vulkan/capabilities_vk.h"
#include "impeller/renderer/backend/vulkan/command_buffer_vk.h"
#include "impeller/renderer/backend/vulkan/formats_vk.h"
#include "impeller/renderer/backend/vulkan/surface_producer_vk.h"
#include "impeller/renderer/backend/vulkan/swapchain_details_vk.h"
#include "impeller/renderer/backend/vulkan/vk.h"
Expand Down Expand Up @@ -563,6 +564,7 @@ void ContextVK::SetupSwapchain(vk::UniqueSurfaceKHR surface) {
if (!swapchain_details) {
return;
}
surface_format_ = swapchain_details->PickSurfaceFormat().format;
swapchain_ = SwapchainVK::Create(*device_, *surface_, *swapchain_details);
auto weak_this = weak_from_this();
surface_producer_ = SurfaceProducerVK::Create(
Expand All @@ -582,4 +584,8 @@ std::shared_ptr<DescriptorPoolVK> ContextVK::GetDescriptorPool() const {
return descriptor_pool_;
}

PixelFormat ContextVK::GetColorAttachmentPixelFormat() const {
return ToPixelFormat(surface_format_);
}

} // namespace impeller
5 changes: 5 additions & 0 deletions impeller/renderer/backend/vulkan/context_vk.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "impeller/renderer/backend/vulkan/swapchain_vk.h"
#include "impeller/renderer/backend/vulkan/vk.h"
#include "impeller/renderer/context.h"
#include "impeller/renderer/formats.h"

namespace impeller {

Expand Down Expand Up @@ -85,6 +86,7 @@ class ContextVK final : public Context, public BackendCast<ContextVK, Context> {
vk::Queue transfer_queue_;
vk::Queue present_queue_;
vk::UniqueSurfaceKHR surface_;
vk::Format surface_format_;
std::unique_ptr<SwapchainVK> swapchain_;
std::unique_ptr<CommandPoolVK> graphics_command_pool_;
std::unique_ptr<SurfaceProducerVK> surface_producer_;
Expand Down Expand Up @@ -114,6 +116,9 @@ class ContextVK final : public Context, public BackendCast<ContextVK, Context> {
// |Context|
std::shared_ptr<CommandBuffer> CreateCommandBuffer() const override;

// |Context|
PixelFormat GetColorAttachmentPixelFormat() const override;

// |Context|
std::shared_ptr<WorkQueue> GetWorkQueue() const override;

Expand Down
3 changes: 2 additions & 1 deletion impeller/renderer/backend/vulkan/pipeline_library_vk.cc
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,9 @@ std::optional<vk::UniqueRenderPass> PipelineLibraryVK::CreateRenderPass(
std::vector<vk::AttachmentDescription> render_pass_attachments;
const auto sample_count = desc.GetSampleCount();
// Set the color attachment.
const auto& format = desc.GetColorAttachmentDescriptor(0)->format;
render_pass_attachments.push_back(CreatePlaceholderAttachmentDescription(
vk::Format::eB8G8R8A8Unorm, sample_count, true));
ToVKImageFormat(format), sample_count, true));

std::vector<vk::AttachmentReference> color_attachment_references;
std::vector<vk::AttachmentReference> resolve_attachment_references;
Expand Down
4 changes: 0 additions & 4 deletions impeller/renderer/backend/vulkan/surface_producer_vk.cc
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,6 @@ std::unique_ptr<Surface> SurfaceProducerVK::AcquireSurface(
return nullptr;
}

if (acuire_image_res == vk::Result::eSuboptimalKHR) {
VALIDATION_LOG << "Suboptimal image acquired.";
}

SurfaceVK::SwapCallback swap_callback = [this, current_frame, image_index]() {
return Present(current_frame, image_index);
};
Expand Down
4 changes: 4 additions & 0 deletions impeller/renderer/context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,8 @@ std::shared_ptr<GPUTracer> Context::GetGPUTracer() const {
return nullptr;
}

PixelFormat Context::GetColorAttachmentPixelFormat() const {
return PixelFormat::kDefaultColor;
}

} // namespace impeller
3 changes: 3 additions & 0 deletions impeller/renderer/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <string>

#include "flutter/fml/macros.h"
#include "impeller/renderer/formats.h"

namespace impeller {

Expand Down Expand Up @@ -45,6 +46,8 @@ class Context : public std::enable_shared_from_this<Context> {
///
virtual std::shared_ptr<GPUTracer> GetGPUTracer() const;

virtual PixelFormat GetColorAttachmentPixelFormat() const;

virtual bool HasThreadingRestrictions() const;

virtual bool SupportsOffscreenMSAA() const = 0;
Expand Down
4 changes: 2 additions & 2 deletions impeller/renderer/pipeline_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,9 @@ struct PipelineBuilder {
// Configure the sole color attachments pixel format. This is by
// convention.
ColorAttachmentDescriptor color0;
color0.format = PixelFormat::kDefaultColor;
color0.format = context.GetColorAttachmentPixelFormat();
color0.blending_enabled = true;
desc.SetColorAttachmentDescriptor(0u, std::move(color0));
desc.SetColorAttachmentDescriptor(0u, color0);
}

// Setup default stencil buffer descriptions.
Expand Down
5 changes: 4 additions & 1 deletion shell/platform/android/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import("//flutter/shell/version/version.gni")
shell_gpu_configuration("android_gpu_configuration") {
enable_software = true
enable_gl = true
enable_vulkan = false
enable_vulkan = true
enable_metal = false
}

Expand Down Expand Up @@ -85,6 +85,8 @@ source_set("flutter_shell_native_src") {
"android_surface_gl_skia.h",
"android_surface_software.cc",
"android_surface_software.h",
"android_surface_vulkan_impeller.cc",
"android_surface_vulkan_impeller.h",
"apk_asset_provider.cc",
"apk_asset_provider.h",
"flutter_main.cc",
Expand Down Expand Up @@ -123,6 +125,7 @@ source_set("flutter_shell_native_src") {
"//flutter/shell/platform/android/platform_view_android_delegate",
"//flutter/shell/platform/android/surface",
"//flutter/shell/platform/android/surface:native_window",
"//flutter/vulkan",
"//third_party/skia",
]

Expand Down
119 changes: 119 additions & 0 deletions shell/platform/android/android_surface_vulkan_impeller.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
// 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/platform/android/android_surface_vulkan_impeller.h"

#include <memory>
#include <utility>

#include "flutter/fml/concurrent_message_loop.h"
#include "flutter/fml/logging.h"
#include "flutter/fml/memory/ref_ptr.h"
#include "flutter/impeller/renderer/backend/vulkan/context_vk.h"
#include "flutter/shell/gpu/gpu_surface_vulkan_impeller.h"
#include "flutter/vulkan/vulkan_native_surface_android.h"
#include "impeller/entity/vk/entity_shaders_vk.h"

namespace flutter {

std::shared_ptr<impeller::Context> CreateImpellerContext(
const fml::RefPtr<vulkan::VulkanProcTable>& proc_table,
const std::shared_ptr<fml::ConcurrentMessageLoop>& concurrent_loop) {
std::vector<std::shared_ptr<fml::Mapping>> shader_mappings = {
std::make_shared<fml::NonOwnedMapping>(impeller_entity_shaders_vk_data,
impeller_entity_shaders_vk_length),
};

PFN_vkGetInstanceProcAddr instance_proc_addr =
proc_table->NativeGetInstanceProcAddr();

auto context =
impeller::ContextVK::Create(instance_proc_addr, //
shader_mappings, //
nullptr, //
concurrent_loop->GetTaskRunner(), //
"Android Impeller Vulkan Lib" //
);

return context;
}

AndroidSurfaceVulkanImpeller::AndroidSurfaceVulkanImpeller(
const std::shared_ptr<AndroidContext>& android_context,
const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade)
: AndroidSurface(android_context),
proc_table_(fml::MakeRefCounted<vulkan::VulkanProcTable>()),
workers_(fml::ConcurrentMessageLoop::Create()) {
impeller_context_ = CreateImpellerContext(proc_table_, workers_);
is_valid_ =
proc_table_->HasAcquiredMandatoryProcAddresses() && impeller_context_;
}

AndroidSurfaceVulkanImpeller::~AndroidSurfaceVulkanImpeller() = default;

bool AndroidSurfaceVulkanImpeller::IsValid() const {
return is_valid_;
}

void AndroidSurfaceVulkanImpeller::TeardownOnScreenContext() {
// Nothing to do.
}

std::unique_ptr<Surface> AndroidSurfaceVulkanImpeller::CreateGPUSurface(
GrDirectContext* gr_context) {
if (!IsValid()) {
return nullptr;
}

if (!native_window_ || !native_window_->IsValid()) {
return nullptr;
}

std::unique_ptr<GPUSurfaceVulkanImpeller> gpu_surface =
std::make_unique<GPUSurfaceVulkanImpeller>(impeller_context_);

if (!gpu_surface->IsValid()) {
return nullptr;
}

return gpu_surface;
}

bool AndroidSurfaceVulkanImpeller::OnScreenSurfaceResize(const SkISize& size) {
return true;
}

bool AndroidSurfaceVulkanImpeller::ResourceContextMakeCurrent() {
FML_DLOG(ERROR) << "The vulkan backend does not support resource contexts.";
return false;
}

bool AndroidSurfaceVulkanImpeller::ResourceContextClearCurrent() {
FML_DLOG(ERROR) << "The vulkan backend does not support resource contexts.";
return false;
}

bool AndroidSurfaceVulkanImpeller::SetNativeWindow(
fml::RefPtr<AndroidNativeWindow> window) {
native_window_ = std::move(window);
bool success = native_window_ && native_window_->IsValid();

if (success) {
auto& context_vk = impeller::ContextVK::Cast(*impeller_context_);
auto surface = context_vk.CreateAndroidSurface(native_window_->handle());

if (!surface) {
FML_LOG(ERROR) << "Could not create a vulkan surface.";
return false;
}

context_vk.SetupSwapchain(std::move(surface));
return true;
}

native_window_ = nullptr;
return false;
}

} // namespace flutter
56 changes: 56 additions & 0 deletions shell/platform/android/android_surface_vulkan_impeller.h
Original file line number Diff line number Diff line change
@@ -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/fml/concurrent_message_loop.h"
#include "flutter/fml/macros.h"
#include "flutter/impeller/renderer/context.h"
#include "flutter/shell/platform/android/surface/android_native_window.h"
#include "flutter/shell/platform/android/surface/android_surface.h"
#include "flutter/vulkan/procs/vulkan_proc_table.h"

namespace flutter {

class AndroidSurfaceVulkanImpeller : public AndroidSurface {
public:
AndroidSurfaceVulkanImpeller(
const std::shared_ptr<AndroidContext>& android_context,
const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade);

~AndroidSurfaceVulkanImpeller() override;

// |AndroidSurface|
bool IsValid() const override;

// |AndroidSurface|
std::unique_ptr<Surface> CreateGPUSurface(
GrDirectContext* gr_context) override;

// |AndroidSurface|
void TeardownOnScreenContext() override;

// |AndroidSurface|
bool OnScreenSurfaceResize(const SkISize& size) override;

// |AndroidSurface|
bool ResourceContextMakeCurrent() override;

// |AndroidSurface|
bool ResourceContextClearCurrent() override;

// |AndroidSurface|
bool SetNativeWindow(fml::RefPtr<AndroidNativeWindow> window) override;

private:
fml::RefPtr<vulkan::VulkanProcTable> proc_table_;
fml::RefPtr<AndroidNativeWindow> native_window_;
std::shared_ptr<fml::ConcurrentMessageLoop> workers_;
std::shared_ptr<impeller::Context> impeller_context_;
bool is_valid_ = false;

FML_DISALLOW_COPY_AND_ASSIGN(AndroidSurfaceVulkanImpeller);
};

} // namespace flutter
8 changes: 8 additions & 0 deletions shell/platform/android/platform_view_android.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "flutter/shell/platform/android/android_surface_gl_impeller.h"
#include "flutter/shell/platform/android/android_surface_gl_skia.h"
#include "flutter/shell/platform/android/android_surface_software.h"
#include "flutter/shell/platform/android/android_surface_vulkan_impeller.h"
#include "flutter/shell/platform/android/context/android_context.h"
#include "flutter/shell/platform/android/external_view_embedder/external_view_embedder.h"
#include "flutter/shell/platform/android/jni/platform_view_android_jni.h"
Expand Down Expand Up @@ -43,8 +44,15 @@ std::unique_ptr<AndroidSurface> AndroidSurfaceFactoryImpl::CreateSurface() {
jni_facade_);
case AndroidRenderingAPI::kOpenGLES:
if (enable_impeller_) {
// TODO(kaushikiska@): Enable this after wiring a preference for Vulkan backend.
#if false
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, false is a preprocessor define? TIL

return std::make_unique<AndroidSurfaceVulkanImpeller>(android_context_,
jni_facade_);

#else
return std::make_unique<AndroidSurfaceGLImpeller>(android_context_,
jni_facade_);
#endif
} else {
return std::make_unique<AndroidSurfaceGLSkia>(android_context_,
jni_facade_);
Expand Down
4 changes: 2 additions & 2 deletions tools/gn
Original file line number Diff line number Diff line change
Expand Up @@ -436,10 +436,10 @@ def to_gn_args(args):
gn_args['skia_use_metal'] = True
gn_args['shell_enable_metal'] = True

# Enable Vulkan on all platforms except for Android and iOS. This is just
# Enable Vulkan on all platforms except for iOS. This is just
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🥳

# to save on mobile binary size, as there's no reason the Vulkan embedder
# features can't work on these platforms.
if args.target_os not in ['android', 'ios']:
if args.target_os not in ['ios']:
gn_args['skia_use_vulkan'] = True
gn_args['skia_use_vma'] = False
gn_args['shell_enable_vulkan'] = True
Expand Down