flutter_flutter/engine/src/flutter/shell/gpu/gpu_surface_vulkan.cc
Dan Field 1e318d57d4 [Impeller] flutter_tester --enable-impeller (flutter/engine#46389)
This patch does the following:

- Updates `flutter_tester` to set up an Impeller rendering context and surface if `--enable-impeller` is set to true, using the Vulkan backend with Swiftshader.
- Updates `run_tests.py` to run all tests except the smoke test (that one really has no rendering impact whatsoever) with and without `--enable-impeller`.
- Updates a few tests to work that were trivial:
  - A couple tests needed updated goldens for very minor rendering differences. Filed https://github.com/flutter/flutter/issues/135684 to track using Skia gold for this instead.
  - Disabled SKP screenshotting if Impeller is enabled, and updated the test checking that to verify an error is thrown if an SKP is requested.
  - The Dart GPU based test now asserts that the gpu context is available if Impeller is enabled, and does not deadlock if run in a single threaded mode.
  - We were missing some trace events around `Canvas::SaveLayer` for Impeller as compared to Skia.
  - A couple other tests had strict checks about exception messages that are slightly different between Skia and Impeller.
- I've filed bugs for other tests that may require a little more work, and skipped them for now. For FragmentProgram on Vulkan I reused an existing bug.

This is part of my attempt to address https://github.com/flutter/flutter/issues/135693, although @chinmaygarde and I had slightly different ideas about how to do this.

The goals here are:

- Run the Dart unit tests we already have with Impeller enabled.
- Enable running more of the framework tests (including gold tests) with Impeller enabled.
- Run all of these tests via public `dart:ui` API rather than mucking around in C++ internals in the engine.
2023-10-11 21:42:24 +00:00

153 lines
5.0 KiB
C++

// 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.h"
#include "flutter/fml/logging.h"
#include "flutter/fml/trace_event.h"
#include "third_party/skia/include/core/SkColorSpace.h"
#include "third_party/skia/include/core/SkSize.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/gpu/GrBackendSurface.h"
#include "third_party/skia/include/gpu/GrDirectContext.h"
#include "third_party/skia/include/gpu/ganesh/SkSurfaceGanesh.h"
#include "third_party/skia/include/gpu/ganesh/vk/GrVkBackendSurface.h"
#include "vulkan/vulkan_core.h"
namespace flutter {
GPUSurfaceVulkan::GPUSurfaceVulkan(GPUSurfaceVulkanDelegate* delegate,
const sk_sp<GrDirectContext>& skia_context,
bool render_to_surface)
: delegate_(delegate),
skia_context_(skia_context),
render_to_surface_(render_to_surface),
weak_factory_(this) {}
GPUSurfaceVulkan::~GPUSurfaceVulkan() = default;
bool GPUSurfaceVulkan::IsValid() {
return skia_context_ != nullptr;
}
std::unique_ptr<SurfaceFrame> GPUSurfaceVulkan::AcquireFrame(
const SkISize& frame_size) {
if (!IsValid()) {
FML_LOG(ERROR) << "Vulkan surface was invalid.";
return nullptr;
}
if (frame_size.isEmpty()) {
FML_LOG(ERROR) << "Vulkan surface was asked for an empty frame.";
return nullptr;
}
if (!render_to_surface_) {
return std::make_unique<SurfaceFrame>(
nullptr, SurfaceFrame::FramebufferInfo(),
[](const SurfaceFrame& surface_frame, DlCanvas* canvas) {
return true;
},
frame_size);
}
FlutterVulkanImage image = delegate_->AcquireImage(frame_size);
if (!image.image) {
FML_LOG(ERROR) << "Invalid VkImage given by the embedder.";
return nullptr;
}
sk_sp<SkSurface> surface = CreateSurfaceFromVulkanImage(
reinterpret_cast<VkImage>(image.image),
static_cast<VkFormat>(image.format), frame_size);
if (!surface) {
FML_LOG(ERROR) << "Could not create the SkSurface from the Vulkan image.";
return nullptr;
}
SurfaceFrame::SubmitCallback callback = [image = image, delegate = delegate_](
const SurfaceFrame&,
DlCanvas* canvas) -> bool {
TRACE_EVENT0("flutter", "GPUSurfaceVulkan::PresentImage");
if (canvas == nullptr) {
FML_DLOG(ERROR) << "Canvas not available.";
return false;
}
canvas->Flush();
return delegate->PresentImage(reinterpret_cast<VkImage>(image.image),
static_cast<VkFormat>(image.format));
};
SurfaceFrame::FramebufferInfo framebuffer_info{.supports_readback = true};
return std::make_unique<SurfaceFrame>(std::move(surface), framebuffer_info,
std::move(callback), frame_size);
}
SkMatrix GPUSurfaceVulkan::GetRootTransformation() const {
// This backend does not support delegating to the underlying platform to
// query for root surface transformations. Just return identity.
SkMatrix matrix;
matrix.reset();
return matrix;
}
GrDirectContext* GPUSurfaceVulkan::GetContext() {
return skia_context_.get();
}
sk_sp<SkSurface> GPUSurfaceVulkan::CreateSurfaceFromVulkanImage(
const VkImage image,
const VkFormat format,
const SkISize& size) {
#ifdef SK_VULKAN
GrVkImageInfo image_info = {
.fImage = image,
.fImageTiling = VK_IMAGE_TILING_OPTIMAL,
.fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.fFormat = format,
.fImageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
VK_IMAGE_USAGE_TRANSFER_DST_BIT |
VK_IMAGE_USAGE_SAMPLED_BIT,
.fSampleCount = 1,
.fLevelCount = 1,
};
auto backend_texture =
GrBackendTextures::MakeVk(size.width(), size.height(), image_info);
SkSurfaceProps surface_properties(0, kUnknown_SkPixelGeometry);
return SkSurfaces::WrapBackendTexture(
skia_context_.get(), // context
backend_texture, // back-end texture
kTopLeft_GrSurfaceOrigin, // surface origin
1, // sample count
ColorTypeFromFormat(format), // color type
SkColorSpace::MakeSRGB(), // color space
&surface_properties // surface properties
);
#else
return nullptr;
#endif // SK_VULKAN
}
SkColorType GPUSurfaceVulkan::ColorTypeFromFormat(const VkFormat format) {
switch (format) {
case VK_FORMAT_R8G8B8A8_UNORM:
case VK_FORMAT_R8G8B8A8_SRGB:
return SkColorType::kRGBA_8888_SkColorType;
case VK_FORMAT_B8G8R8A8_UNORM:
case VK_FORMAT_B8G8R8A8_SRGB:
return SkColorType::kBGRA_8888_SkColorType;
default:
return SkColorType::kUnknown_SkColorType;
}
}
} // namespace flutter