diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index daa47fd894e85..f446b4fa82102 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -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 diff --git a/impeller/renderer/backend/vulkan/context_vk.cc b/impeller/renderer/backend/vulkan/context_vk.cc index 495a532ebcc7f..58508e8793d75 100644 --- a/impeller/renderer/backend/vulkan/context_vk.cc +++ b/impeller/renderer/backend/vulkan/context_vk.cc @@ -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" @@ -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( @@ -582,4 +584,8 @@ std::shared_ptr ContextVK::GetDescriptorPool() const { return descriptor_pool_; } +PixelFormat ContextVK::GetColorAttachmentPixelFormat() const { + return ToPixelFormat(surface_format_); +} + } // namespace impeller diff --git a/impeller/renderer/backend/vulkan/context_vk.h b/impeller/renderer/backend/vulkan/context_vk.h index 4c9cdefc35fc8..f99ef0e28d41b 100644 --- a/impeller/renderer/backend/vulkan/context_vk.h +++ b/impeller/renderer/backend/vulkan/context_vk.h @@ -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 { @@ -85,6 +86,7 @@ class ContextVK final : public Context, public BackendCast { vk::Queue transfer_queue_; vk::Queue present_queue_; vk::UniqueSurfaceKHR surface_; + vk::Format surface_format_; std::unique_ptr swapchain_; std::unique_ptr graphics_command_pool_; std::unique_ptr surface_producer_; @@ -114,6 +116,9 @@ class ContextVK final : public Context, public BackendCast { // |Context| std::shared_ptr CreateCommandBuffer() const override; + // |Context| + PixelFormat GetColorAttachmentPixelFormat() const override; + // |Context| std::shared_ptr GetWorkQueue() const override; diff --git a/impeller/renderer/backend/vulkan/pipeline_library_vk.cc b/impeller/renderer/backend/vulkan/pipeline_library_vk.cc index 41f04108932d2..9f0912a68c397 100644 --- a/impeller/renderer/backend/vulkan/pipeline_library_vk.cc +++ b/impeller/renderer/backend/vulkan/pipeline_library_vk.cc @@ -147,8 +147,9 @@ std::optional PipelineLibraryVK::CreateRenderPass( std::vector 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 color_attachment_references; std::vector resolve_attachment_references; diff --git a/impeller/renderer/backend/vulkan/surface_producer_vk.cc b/impeller/renderer/backend/vulkan/surface_producer_vk.cc index ad1b7cf2f26a6..e92c27617d442 100644 --- a/impeller/renderer/backend/vulkan/surface_producer_vk.cc +++ b/impeller/renderer/backend/vulkan/surface_producer_vk.cc @@ -65,10 +65,6 @@ std::unique_ptr 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); }; diff --git a/impeller/renderer/context.cc b/impeller/renderer/context.cc index 6752da6874b63..e278e3e156ad1 100644 --- a/impeller/renderer/context.cc +++ b/impeller/renderer/context.cc @@ -18,4 +18,8 @@ std::shared_ptr Context::GetGPUTracer() const { return nullptr; } +PixelFormat Context::GetColorAttachmentPixelFormat() const { + return PixelFormat::kDefaultColor; +} + } // namespace impeller diff --git a/impeller/renderer/context.h b/impeller/renderer/context.h index 4f70f24c40fe2..8ba839b8612c0 100644 --- a/impeller/renderer/context.h +++ b/impeller/renderer/context.h @@ -8,6 +8,7 @@ #include #include "flutter/fml/macros.h" +#include "impeller/renderer/formats.h" namespace impeller { @@ -45,6 +46,8 @@ class Context : public std::enable_shared_from_this { /// virtual std::shared_ptr GetGPUTracer() const; + virtual PixelFormat GetColorAttachmentPixelFormat() const; + virtual bool HasThreadingRestrictions() const; virtual bool SupportsOffscreenMSAA() const = 0; diff --git a/impeller/renderer/pipeline_builder.h b/impeller/renderer/pipeline_builder.h index e583b88300c8b..f41e0e337c180 100644 --- a/impeller/renderer/pipeline_builder.h +++ b/impeller/renderer/pipeline_builder.h @@ -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. diff --git a/shell/platform/android/BUILD.gn b/shell/platform/android/BUILD.gn index 7ecb585569368..d59de0d939715 100644 --- a/shell/platform/android/BUILD.gn +++ b/shell/platform/android/BUILD.gn @@ -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 } @@ -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", @@ -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", ] diff --git a/shell/platform/android/android_surface_vulkan_impeller.cc b/shell/platform/android/android_surface_vulkan_impeller.cc new file mode 100644 index 0000000000000..e4f5637d1eef4 --- /dev/null +++ b/shell/platform/android/android_surface_vulkan_impeller.cc @@ -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 +#include + +#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 CreateImpellerContext( + const fml::RefPtr& proc_table, + const std::shared_ptr& concurrent_loop) { + std::vector> shader_mappings = { + std::make_shared(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& android_context, + const std::shared_ptr& jni_facade) + : AndroidSurface(android_context), + proc_table_(fml::MakeRefCounted()), + 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 AndroidSurfaceVulkanImpeller::CreateGPUSurface( + GrDirectContext* gr_context) { + if (!IsValid()) { + return nullptr; + } + + if (!native_window_ || !native_window_->IsValid()) { + return nullptr; + } + + std::unique_ptr gpu_surface = + std::make_unique(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 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 diff --git a/shell/platform/android/android_surface_vulkan_impeller.h b/shell/platform/android/android_surface_vulkan_impeller.h new file mode 100644 index 0000000000000..f5012dbf61e1d --- /dev/null +++ b/shell/platform/android/android_surface_vulkan_impeller.h @@ -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& android_context, + const std::shared_ptr& jni_facade); + + ~AndroidSurfaceVulkanImpeller() override; + + // |AndroidSurface| + bool IsValid() const override; + + // |AndroidSurface| + std::unique_ptr 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 window) override; + + private: + fml::RefPtr proc_table_; + fml::RefPtr native_window_; + std::shared_ptr workers_; + std::shared_ptr impeller_context_; + bool is_valid_ = false; + + FML_DISALLOW_COPY_AND_ASSIGN(AndroidSurfaceVulkanImpeller); +}; + +} // namespace flutter diff --git a/shell/platform/android/platform_view_android.cc b/shell/platform/android/platform_view_android.cc index 5e0ab4be7f2e7..eec2de08dbf80 100644 --- a/shell/platform/android/platform_view_android.cc +++ b/shell/platform/android/platform_view_android.cc @@ -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" @@ -43,8 +44,15 @@ std::unique_ptr AndroidSurfaceFactoryImpl::CreateSurface() { jni_facade_); case AndroidRenderingAPI::kOpenGLES: if (enable_impeller_) { +// TODO(kaushikiska@): Enable this after wiring a preference for Vulkan backend. +#if false + return std::make_unique(android_context_, + jni_facade_); + +#else return std::make_unique(android_context_, jni_facade_); +#endif } else { return std::make_unique(android_context_, jni_facade_); diff --git a/tools/gn b/tools/gn index 678bca26cf251..aa762ef6e5e8a 100755 --- a/tools/gn +++ b/tools/gn @@ -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 # 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