From bc4a27fc2f5d592a8323d5697cc18a43f8f59c8e Mon Sep 17 00:00:00 2001 From: freiling Date: Thu, 20 Feb 2020 11:37:00 -0800 Subject: [PATCH] [shell tests] Integrate Vulkan with Shell Tests (#16621) This change creates a test only implementation of flutter::Surface backed by an offscreen Vulkan GrContext. Much of the code in this test Surface was lifted from flutter::VulkanWindow which I was unable to use without extricating it from the VkSurface/VkSwapchain code which we do not want to use in offscreen tests. I would recommend refactoring VulkanWindow to separate GrContext creation and VkSwapchain creation in order to promote greater code reuse between onscreen and offscreen vulkan paths. This change is excersised thoroughly by the shell tests and was manually tested against these tests on Fuchsia on Intel. --- .../common/shell_test_platform_view_vulkan.cc | 132 +++++++++++++++++- .../common/shell_test_platform_view_vulkan.h | 38 ++++- testing/fuchsia/meta/fuchsia_test.cmx | 7 +- 3 files changed, 166 insertions(+), 11 deletions(-) diff --git a/shell/common/shell_test_platform_view_vulkan.cc b/shell/common/shell_test_platform_view_vulkan.cc index b582931748839..d6de169e7dc70 100644 --- a/shell/common/shell_test_platform_view_vulkan.cc +++ b/shell/common/shell_test_platform_view_vulkan.cc @@ -3,7 +3,6 @@ // found in the LICENSE file. #include "flutter/shell/common/shell_test_platform_view_vulkan.h" -#include "flutter/shell/gpu/gpu_surface_vulkan.h" namespace flutter { namespace testing { @@ -30,7 +29,7 @@ void ShellTestPlatformViewVulkan::SimulateVSync() { // |PlatformView| std::unique_ptr ShellTestPlatformViewVulkan::CreateRenderingSurface() { - return std::make_unique(this, nullptr, true); + return std::make_unique(proc_table_); } // |PlatformView| @@ -40,9 +39,132 @@ PointerDataDispatcherMaker ShellTestPlatformViewVulkan::GetDispatcherMaker() { }; } -// |GPUSurfaceVulkanDelegate| -fml::RefPtr ShellTestPlatformViewVulkan::vk() { - return proc_table_; +// TODO(gw280): This code was forked from vulkan_window.cc specifically for +// shell_test. +// We need to merge this functionality back into //vulkan. +// https://github.com/flutter/flutter/issues/51132 +ShellTestPlatformViewVulkan::OffScreenSurface::OffScreenSurface( + fml::RefPtr vk) + : valid_(false), vk_(std::move(vk)) { + if (!vk_ || !vk_->HasAcquiredMandatoryProcAddresses()) { + FML_DLOG(ERROR) << "Proc table has not acquired mandatory proc addresses."; + return; + } + + // Create the application instance. + std::vector extensions = {}; + + application_ = std::make_unique( + *vk_, "FlutterTest", std::move(extensions)); + + if (!application_->IsValid() || !vk_->AreInstanceProcsSetup()) { + // Make certain the application instance was created and it setup the + // instance proc table entries. + FML_DLOG(ERROR) << "Instance proc addresses have not been setup."; + return; + } + + // Create the device. + + logical_device_ = application_->AcquireFirstCompatibleLogicalDevice(); + + if (logical_device_ == nullptr || !logical_device_->IsValid() || + !vk_->AreDeviceProcsSetup()) { + // Make certain the device was created and it setup the device proc table + // entries. + FML_DLOG(ERROR) << "Device proc addresses have not been setup."; + return; + } + + // Create the Skia GrContext. + if (!CreateSkiaGrContext()) { + FML_DLOG(ERROR) << "Could not create Skia context."; + return; + } + + valid_ = true; +} + +bool ShellTestPlatformViewVulkan::OffScreenSurface::CreateSkiaGrContext() { + GrVkBackendContext backend_context; + + if (!CreateSkiaBackendContext(&backend_context)) { + FML_DLOG(ERROR) << "Could not create Skia backend context."; + return false; + } + + sk_sp context = GrContext::MakeVulkan(backend_context); + + if (context == nullptr) { + FML_DLOG(ERROR) << "Failed to create GrContext"; + return false; + } + + context->setResourceCacheLimits(vulkan::kGrCacheMaxCount, + vulkan::kGrCacheMaxByteSize); + + context_ = context; + + return true; +} + +bool ShellTestPlatformViewVulkan::OffScreenSurface::CreateSkiaBackendContext( + GrVkBackendContext* context) { + auto getProc = vk_->CreateSkiaGetProc(); + + if (getProc == nullptr) { + FML_DLOG(ERROR) << "GetProcAddress is null"; + return false; + } + + uint32_t skia_features = 0; + if (!logical_device_->GetPhysicalDeviceFeaturesSkia(&skia_features)) { + FML_DLOG(ERROR) << "Failed to get Physical Device features"; + return false; + } + + context->fInstance = application_->GetInstance(); + context->fPhysicalDevice = logical_device_->GetPhysicalDeviceHandle(); + context->fDevice = logical_device_->GetHandle(); + context->fQueue = logical_device_->GetQueueHandle(); + context->fGraphicsQueueIndex = logical_device_->GetGraphicsQueueIndex(); + context->fMinAPIVersion = application_->GetAPIVersion(); + context->fMaxAPIVersion = application_->GetAPIVersion(); + context->fFeatures = skia_features; + context->fGetProc = std::move(getProc); + context->fOwnsInstanceAndDevice = false; + return true; +} + +ShellTestPlatformViewVulkan::OffScreenSurface::~OffScreenSurface() {} + +bool ShellTestPlatformViewVulkan::OffScreenSurface::IsValid() { + return valid_; +} + +std::unique_ptr +ShellTestPlatformViewVulkan::OffScreenSurface::AcquireFrame( + const SkISize& size) { + auto image_info = SkImageInfo::Make(size, SkColorType::kRGBA_8888_SkColorType, + SkAlphaType::kOpaque_SkAlphaType); + auto surface = SkSurface::MakeRenderTarget(context_.get(), SkBudgeted::kNo, + image_info, 0, nullptr); + SurfaceFrame::SubmitCallback callback = + [](const SurfaceFrame&, SkCanvas* canvas) -> bool { return true; }; + + return std::make_unique(std::move(surface), true, + std::move(callback)); +} + +GrContext* ShellTestPlatformViewVulkan::OffScreenSurface::GetContext() { + return context_.get(); +} + +SkMatrix ShellTestPlatformViewVulkan::OffScreenSurface::GetRootTransformation() + const { + SkMatrix matrix; + matrix.reset(); + return matrix; } } // namespace testing diff --git a/shell/common/shell_test_platform_view_vulkan.h b/shell/common/shell_test_platform_view_vulkan.h index c201ff1a9f27f..38bce87fa5414 100644 --- a/shell/common/shell_test_platform_view_vulkan.h +++ b/shell/common/shell_test_platform_view_vulkan.h @@ -7,12 +7,13 @@ #include "flutter/shell/common/shell_test_platform_view.h" #include "flutter/shell/gpu/gpu_surface_vulkan_delegate.h" +#include "flutter/vulkan/vulkan_application.h" +#include "flutter/vulkan/vulkan_device.h" namespace flutter { namespace testing { -class ShellTestPlatformViewVulkan : public ShellTestPlatformView, - public GPUSurfaceVulkanDelegate { +class ShellTestPlatformViewVulkan : public ShellTestPlatformView { public: ShellTestPlatformViewVulkan(PlatformView::Delegate& delegate, TaskRunners task_runners, @@ -24,6 +25,36 @@ class ShellTestPlatformViewVulkan : public ShellTestPlatformView, void SimulateVSync() override; private: + class OffScreenSurface : public flutter::Surface { + public: + OffScreenSurface(fml::RefPtr vk); + + ~OffScreenSurface() override; + + // |Surface| + bool IsValid() override; + + // |Surface| + std::unique_ptr AcquireFrame(const SkISize& size) override; + + SkMatrix GetRootTransformation() const override; + + // |Surface| + GrContext* GetContext() override; + + private: + bool valid_; + fml::RefPtr vk_; + std::unique_ptr application_; + std::unique_ptr logical_device_; + sk_sp context_; + + bool CreateSkiaGrContext(); + bool CreateSkiaBackendContext(GrVkBackendContext* context); + + FML_DISALLOW_COPY_AND_ASSIGN(OffScreenSurface); + }; + CreateVsyncWaiter create_vsync_waiter_; std::shared_ptr vsync_clock_; @@ -39,9 +70,6 @@ class ShellTestPlatformViewVulkan : public ShellTestPlatformView, // |PlatformView| PointerDataDispatcherMaker GetDispatcherMaker() override; - // |GPUSurfaceVulkanDelegate| - fml::RefPtr vk() override; - FML_DISALLOW_COPY_AND_ASSIGN(ShellTestPlatformViewVulkan); }; diff --git a/testing/fuchsia/meta/fuchsia_test.cmx b/testing/fuchsia/meta/fuchsia_test.cmx index 1eb7a22e5ef28..7239603b3f1ff 100644 --- a/testing/fuchsia/meta/fuchsia_test.cmx +++ b/testing/fuchsia/meta/fuchsia_test.cmx @@ -9,7 +9,12 @@ ], "services": [ "fuchsia.accessibility.semantics.SemanticsManager", - "fuchsia.process.Launcher" + "fuchsia.process.Launcher", + "fuchsia.deprecatedtimezone.Timezone", + "fuchsia.netstack.Netstack", + "fuchsia.vulkan.loader.Loader", + "fuchsia.logger.LogSink", + "fuchsia.tracing.provider.Registry" ] } }