From 594f6608276cbcb7be2b89defcfb6eef03321fad Mon Sep 17 00:00:00 2001 From: Forrest Reiling Date: Fri, 14 Feb 2020 11:29:59 -0800 Subject: [PATCH] [shell tests] Integrate Vulkan with Shell Tests 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 | 128 +++++++++++++++++- .../common/shell_test_platform_view_vulkan.h | 37 ++++- testing/fuchsia/meta/fuchsia_test.cmx | 7 +- 3 files changed, 162 insertions(+), 10 deletions(-) diff --git a/shell/common/shell_test_platform_view_vulkan.cc b/shell/common/shell_test_platform_view_vulkan.cc index b58293174..95c987d38 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,128 @@ PointerDataDispatcherMaker ShellTestPlatformViewVulkan::GetDispatcherMaker() { }; } -// |GPUSurfaceVulkanDelegate| -fml::RefPtr ShellTestPlatformViewVulkan::vk() { - return proc_table_; +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 c201ff1a9..47570c281 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,8 +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 1eb7a22e5..7239603b3 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" ] } } -- GitLab