Skip to content

Commit

Permalink
Add test context that can be passed around, create a skia context for…
Browse files Browse the repository at this point in the history
… snapshotting surfaces, create a Vulkan image wrapper for making an SkSurfaces
  • Loading branch information
bdero committed Nov 20, 2021
1 parent 3a28a65 commit 8b91867
Show file tree
Hide file tree
Showing 8 changed files with 295 additions and 47 deletions.
14 changes: 7 additions & 7 deletions shell/platform/embedder/tests/embedder_config_builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -455,25 +455,25 @@ void EmbedderConfigBuilder::InitializeVulkanRendererConfig() {
vulkan_renderer_config_.struct_size = sizeof(FlutterVulkanRendererConfig);
vulkan_renderer_config_.instance =
static_cast<EmbedderTestContextVulkan&>(context_)
.application_->GetInstance();
.context_.application_->GetInstance();
vulkan_renderer_config_.physical_device =
static_cast<EmbedderTestContextVulkan&>(context_)
.logical_device_->GetPhysicalDeviceHandle();
.context_.device_->GetPhysicalDeviceHandle();
vulkan_renderer_config_.device =
static_cast<EmbedderTestContextVulkan&>(context_)
.logical_device_->GetHandle();
.context_.device_->GetHandle();
vulkan_renderer_config_.queue_family_index =
static_cast<EmbedderTestContextVulkan&>(context_)
.logical_device_->GetGraphicsQueueIndex();
.context_.device_->GetGraphicsQueueIndex();
vulkan_renderer_config_.queue =
static_cast<EmbedderTestContextVulkan&>(context_)
.logical_device_->GetQueueHandle();
.context_.device_->GetQueueHandle();
vulkan_renderer_config_.get_instance_proc_address_callback =
[](void* context, FlutterVulkanInstanceHandle instance,
const char* name) -> void* {
return reinterpret_cast<EmbedderTestContextVulkan*>(context)
->vk_->GetInstanceProcAddr(reinterpret_cast<VkInstance>(instance),
name);
->context_.vk_->GetInstanceProcAddr(
reinterpret_cast<VkInstance>(instance), name);
};
vulkan_renderer_config_.get_next_image_callback =
[](void* context,
Expand Down
33 changes: 1 addition & 32 deletions shell/platform/embedder/tests/embedder_test_context_vulkan.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,42 +14,11 @@
#include "flutter/vulkan/vulkan_device.h"
#include "flutter/vulkan/vulkan_proc_table.h"

#ifdef OS_MACOSX
#define VULKAN_SO_PATH "libvk_swiftshader.dylib"
#elif OS_WIN
#define VULKAN_SO_PATH "vk_swiftshader.dll"
#else
#define VULKAN_SO_PATH "libvk_swiftshader.so"
#endif

namespace flutter {
namespace testing {

EmbedderTestContextVulkan::EmbedderTestContextVulkan(std::string assets_path)
: EmbedderTestContext(assets_path) {
vk_ = fml::MakeRefCounted<vulkan::VulkanProcTable>(VULKAN_SO_PATH);
if (!vk_ || !vk_->HasAcquiredMandatoryProcAddresses()) {
FML_DLOG(ERROR) << "Proc table has not acquired mandatory proc addresses.";
return;
}

application_ = std::unique_ptr<vulkan::VulkanApplication>(
new vulkan::VulkanApplication(*vk_, "Flutter Unittests", {}));
if (!application_->IsValid()) {
FML_DLOG(ERROR) << "Failed to initialize basic Vulkan state.";
return;
}
if (!vk_->AreInstanceProcsSetup()) {
FML_DLOG(ERROR) << "Failed to acquire full proc table.";
return;
}

logical_device_ = application_->AcquireFirstCompatibleLogicalDevice();
if (!logical_device_ || !logical_device_->IsValid()) {
FML_DLOG(ERROR) << "Failed to create compatible logical device.";
return;
}
}
: EmbedderTestContext(assets_path), context_() {}

EmbedderTestContextVulkan::~EmbedderTestContextVulkan() {}

Expand Down
14 changes: 6 additions & 8 deletions shell/platform/embedder/tests/embedder_test_context_vulkan.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
#ifndef FLUTTER_SHELL_PLATFORM_EMBEDDER_TESTS_EMBEDDER_CONTEXT_VULKAN_H_
#define FLUTTER_SHELL_PLATFORM_EMBEDDER_TESTS_EMBEDDER_CONTEXT_VULKAN_H_

#include "tests/embedder_test_context.h"
#include "vulkan/vulkan_application.h"
#include "flutter/shell/platform/embedder/tests/embedder_test_context.h"
#include "flutter/testing/test_vulkan_context.h"
#include "flutter/vulkan/vulkan_application.h"

namespace flutter {
namespace testing {
Expand All @@ -31,18 +32,15 @@ class EmbedderTestContextVulkan : public EmbedderTestContext {
bool PresentImage(VkImage image);

private:
// This allows the builder to access the hooks.
friend class EmbedderConfigBuilder;

fml::RefPtr<vulkan::VulkanProcTable> vk_;
std::unique_ptr<vulkan::VulkanApplication> application_;
std::unique_ptr<vulkan::VulkanDevice> logical_device_;
TestVulkanContext context_;

SkISize surface_size_ = SkISize::MakeEmpty();
size_t present_count_ = 0;

void SetupSurface(SkISize surface_size) override;

friend class EmbedderConfigBuilder;

FML_DISALLOW_COPY_AND_ASSIGN(EmbedderTestContextVulkan);
};

Expand Down
8 changes: 8 additions & 0 deletions testing/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -125,11 +125,19 @@ if (enable_unittests) {
source_set("vulkan") {
testonly = true

sources = [
"test_vulkan_context.cc",
"test_vulkan_context.h",
"test_vulkan_surface.cc",
"test_vulkan_surface.h",
]

defines = [ "TEST_VULKAN_PROCS" ]

deps = [
":skia",
"//flutter/fml",
"//flutter/shell/common",
"//flutter/vulkan",
]

Expand Down
98 changes: 98 additions & 0 deletions testing/test_vulkan_context.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// 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/testing/test_vulkan_context.h"
#include "flutter/fml/logging.h"
#include "flutter/shell/common/context_options.h"

#include "include/gpu/GrDirectContext.h"
#include "third_party/skia/include/core/SkSurface.h"

#ifdef OS_MACOSX
#define VULKAN_SO_PATH "libvk_swiftshader.dylib"
#elif OS_WIN
#define VULKAN_SO_PATH "vk_swiftshader.dll"
#else
#define VULKAN_SO_PATH "libvk_swiftshader.so"
#endif

namespace flutter {
namespace testing {

TestVulkanContext::TestVulkanContext() {
// ---------------------------------------------------------------------------
// Initialize basic Vulkan state using the Swiftshader ICD.
// ---------------------------------------------------------------------------

vk_ = fml::MakeRefCounted<vulkan::VulkanProcTable>(VULKAN_SO_PATH);
if (!vk_ || !vk_->HasAcquiredMandatoryProcAddresses()) {
FML_DLOG(ERROR) << "Proc table has not acquired mandatory proc addresses.";
return;
}

application_ = std::unique_ptr<vulkan::VulkanApplication>(
new vulkan::VulkanApplication(*vk_, "Flutter Unittests", {}));
if (!application_->IsValid()) {
FML_DLOG(ERROR) << "Failed to initialize basic Vulkan state.";
return;
}
if (!vk_->AreInstanceProcsSetup()) {
FML_DLOG(ERROR) << "Failed to acquire full proc table.";
return;
}

device_ = application_->AcquireFirstCompatibleLogicalDevice();
if (!device_ || !device_->IsValid()) {
FML_DLOG(ERROR) << "Failed to create compatible logical device.";
return;
}

// ---------------------------------------------------------------------------
// Create a Skia context.
// For creating SkSurfaces from VkImages and snapshotting them, etc.
// ---------------------------------------------------------------------------

uint32_t skia_features = 0;
if (!device_->GetPhysicalDeviceFeaturesSkia(&skia_features)) {
FML_LOG(ERROR) << "Failed to get physical device features.";

return;
}

auto get_proc = vk_->CreateSkiaGetProc();
if (get_proc == nullptr) {
FML_LOG(ERROR) << "Failed to create Vulkan getProc for Skia.";
return;
}

GrVkBackendContext backend_context = {
.fInstance = application_->GetInstance(),
.fPhysicalDevice = device_->GetPhysicalDeviceHandle(),
.fDevice = device_->GetHandle(),
.fQueue = device_->GetQueueHandle(),
.fGraphicsQueueIndex = device_->GetGraphicsQueueIndex(),
.fMinAPIVersion = VK_MAKE_VERSION(1, 0, 0),
.fMaxAPIVersion = VK_MAKE_VERSION(1, 0, 0),
.fFeatures = skia_features,
.fGetProc = get_proc,
.fOwnsInstanceAndDevice = false,
};

GrContextOptions options =
MakeDefaultContextOptions(ContextType::kRender, GrBackendApi::kVulkan);
options.fReduceOpsTaskSplitting = GrContextOptions::Enable::kNo;
context_ = GrDirectContext::MakeVulkan(backend_context, options);
}

VkImage TestVulkanContext::CreateImage(const SkISize& size) const {
assert(false); // TODO(bdero)
return nullptr;
}

sk_sp<GrDirectContext> TestVulkanContext::GetGrDirectContext() const {
return context_;
}

} // namespace testing
} // namespace flutter
44 changes: 44 additions & 0 deletions testing/test_vulkan_context.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// 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.

#ifndef FLUTTER_TESTING_TEST_VULKAN_CONTEXT_H_
#define FLUTTER_TESTING_TEST_VULKAN_CONTEXT_H_

#include "flutter/fml/macros.h"
#include "flutter/fml/memory/ref_ptr.h"
#include "flutter/vulkan/vulkan_application.h"
#include "flutter/vulkan/vulkan_device.h"
#include "flutter/vulkan/vulkan_proc_table.h"

#include "third_party/skia/include/core/SkSize.h"
#include "third_party/skia/include/gpu/GrDirectContext.h"

namespace flutter {
namespace testing {

class TestVulkanContext {
public:
TestVulkanContext();

VkImage CreateImage(const SkISize& size) const;

sk_sp<GrDirectContext> GetGrDirectContext() const;

private:
fml::RefPtr<vulkan::VulkanProcTable> vk_;
std::unique_ptr<vulkan::VulkanApplication> application_;
std::unique_ptr<vulkan::VulkanDevice> device_;

sk_sp<GrDirectContext> context_;

friend class EmbedderTestContextVulkan;
friend class EmbedderConfigBuilder;

FML_DISALLOW_COPY_AND_ASSIGN(TestVulkanContext);
};

} // namespace testing
} // namespace flutter

#endif // FLUTTER_TESTING_TEST_VULKAN_CONTEXT_H_
97 changes: 97 additions & 0 deletions testing/test_vulkan_surface.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// 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/testing/test_vulkan_surface.h"
#include "flutter/fml/logging.h"
#include "flutter/testing/test_vulkan_context.h"

#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/core/SkSurfaceProps.h"

namespace flutter {
namespace testing {

TestVulkanSurface::TestVulkanSurface(const TestVulkanContext& context,
const SkISize& surface_size) {
VkImage image = context.CreateImage(surface_size);

if (!image) {
FML_LOG(ERROR) << "Could not create VkImage.";
return;
}

GrVkImageInfo image_info = {
.fImage = static_cast<VkImage>(image),
.fImageTiling = VK_IMAGE_TILING_OPTIMAL,
.fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.fFormat = VK_FORMAT_R8G8B8A8_UNORM,
.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,
};
GrBackendTexture backend_texture(surface_size.width(), //
surface_size.height(), //
image_info //
);

SkSurfaceProps surface_properties(0, kUnknown_SkPixelGeometry);

surface_ = SkSurface::MakeFromBackendTexture(
context.GetGrDirectContext().get(), // context
backend_texture, // back-end texture
kTopLeft_GrSurfaceOrigin, // surface origin
1, // sample count
kRGBA_8888_SkColorType, // color type
SkColorSpace::MakeSRGB(), // color space
&surface_properties, // surface properties
nullptr, // release proc
nullptr // release context
);

if (!surface_) {
FML_LOG(ERROR)
<< "Could not wrap VkImage as an SkSurface Vulkan render texture.";
return;
}
}

bool TestVulkanSurface::IsValid() const {
return surface_ != nullptr;
}

sk_sp<SkImage> TestVulkanSurface::GetSurfaceSnapshot() const {
if (!IsValid()) {
return nullptr;
}

if (!surface_) {
FML_LOG(ERROR) << "Aborting snapshot because of on-screen surface "
"acquisition failure.";
return nullptr;
}

auto device_snapshot = surface_->makeImageSnapshot();

if (!device_snapshot) {
FML_LOG(ERROR) << "Could not create the device snapshot while attempting "
"to snapshot the Vulkan surface.";
return nullptr;
}

auto host_snapshot = device_snapshot->makeRasterImage();

if (!host_snapshot) {
FML_LOG(ERROR) << "Could not create the host snapshot while attempting to "
"snapshot the Vulkan surface.";
return nullptr;
}

return host_snapshot;
}

} // namespace testing
} // namespace flutter
Loading

0 comments on commit 8b91867

Please sign in to comment.