Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
test_vulkan_context.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <cassert>
6#include <memory>
7#include <optional>
8
9#include "flutter/flutter_vma/flutter_skia_vma.h"
10#include "flutter/fml/logging.h"
11#include "flutter/shell/common/context_options.h"
12#include "flutter/testing/test_vulkan_context.h"
13#include "flutter/vulkan/vulkan_skia_proc_table.h"
14
15#include "flutter/fml/memory/ref_ptr.h"
16#include "flutter/fml/native_library.h"
17#include "flutter/vulkan/swiftshader_path.h"
22#include "vulkan/vulkan_core.h"
23
24namespace flutter {
25namespace testing {
26
28 // ---------------------------------------------------------------------------
29 // Initialize basic Vulkan state using the Swiftshader ICD.
30 // ---------------------------------------------------------------------------
31
32 const char* vulkan_icd = VULKAN_SO_PATH;
33
34 // TODO(96949): Clean this up and pass a native library directly to
35 // VulkanProcTable.
37 FML_LOG(ERROR) << "Couldn't find Vulkan ICD \"" << vulkan_icd
38 << "\", trying \"libvulkan.so\" instead.";
39 vulkan_icd = "libvulkan.so";
40 }
41
42 FML_LOG(INFO) << "Using Vulkan ICD: " << vulkan_icd;
43
44 vk_ = fml::MakeRefCounted<vulkan::VulkanProcTable>(vulkan_icd);
45 if (!vk_ || !vk_->HasAcquiredMandatoryProcAddresses()) {
46 FML_LOG(ERROR) << "Proc table has not acquired mandatory proc addresses.";
47 return;
48 }
49
50 application_ = std::make_unique<vulkan::VulkanApplication>(
51 *vk_, "Flutter Unittests", std::vector<std::string>{},
52 VK_MAKE_VERSION(1, 0, 0), VK_MAKE_VERSION(1, 0, 0), true);
53 if (!application_->IsValid()) {
54 FML_LOG(ERROR) << "Failed to initialize basic Vulkan state.";
55 return;
56 }
57 if (!vk_->AreInstanceProcsSetup()) {
58 FML_LOG(ERROR) << "Failed to acquire full proc table.";
59 return;
60 }
61
62 device_ = application_->AcquireFirstCompatibleLogicalDevice();
63 if (!device_ || !device_->IsValid()) {
64 FML_LOG(ERROR) << "Failed to create compatible logical device.";
65 return;
66 }
67
68 // ---------------------------------------------------------------------------
69 // Create a Skia context.
70 // For creating SkSurfaces from VkImages and snapshotting them, etc.
71 // ---------------------------------------------------------------------------
72
73 uint32_t skia_features = 0;
74 if (!device_->GetPhysicalDeviceFeaturesSkia(&skia_features)) {
75 FML_LOG(ERROR) << "Failed to get physical device features.";
76
77 return;
78 }
79
80 auto get_proc = vulkan::CreateSkiaGetProc(vk_);
81 if (get_proc == nullptr) {
82 FML_LOG(ERROR) << "Failed to create Vulkan getProc for Skia.";
83 return;
84 }
85
88 VK_MAKE_VERSION(1, 0, 0), application_->GetInstance(),
89 device_->GetPhysicalDeviceHandle(), device_->GetHandle(), vk_, true);
90
91 GrVkExtensions extensions;
92
93 GrVkBackendContext backend_context = {};
94 backend_context.fInstance = application_->GetInstance();
95 backend_context.fPhysicalDevice = device_->GetPhysicalDeviceHandle();
96 backend_context.fDevice = device_->GetHandle();
97 backend_context.fQueue = device_->GetQueueHandle();
98 backend_context.fGraphicsQueueIndex = device_->GetGraphicsQueueIndex();
99 backend_context.fMinAPIVersion = VK_MAKE_VERSION(1, 0, 0);
100 backend_context.fMaxAPIVersion = VK_MAKE_VERSION(1, 0, 0);
101 backend_context.fFeatures = skia_features;
102 backend_context.fVkExtensions = &extensions;
103 backend_context.fGetProc = get_proc;
104 backend_context.fOwnsInstanceAndDevice = false;
105 backend_context.fMemoryAllocator = allocator;
106
109 options.fReduceOpsTaskSplitting = GrContextOptions::Enable::kNo;
110 context_ = GrDirectContexts::MakeVulkan(backend_context, options);
111}
112
114 if (context_) {
116 }
117}
118
119std::optional<TestVulkanImage> TestVulkanContext::CreateImage(
120 const SkISize& size) const {
122
125 .pNext = nullptr,
126 .flags = 0,
127 .imageType = VK_IMAGE_TYPE_2D,
128 .format = VK_FORMAT_R8G8B8A8_UNORM,
129 .extent = VkExtent3D{static_cast<uint32_t>(size.width()),
130 static_cast<uint32_t>(size.height()), 1},
131 .mipLevels = 1,
132 .arrayLayers = 1,
133 .samples = VK_SAMPLE_COUNT_1_BIT,
134 .tiling = VK_IMAGE_TILING_OPTIMAL,
138 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
139 .queueFamilyIndexCount = 0,
140 .pQueueFamilyIndices = nullptr,
141 .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
142 };
143
144 VkImage image;
146 vk_->CreateImage(device_->GetHandle(), &info, nullptr, &image)))) {
147 return std::nullopt;
148 }
149
151 image, [&vk = vk_, &device = device_](VkImage image) {
152 vk->DestroyImage(device->GetHandle(), image, nullptr);
153 });
154
155 VkMemoryRequirements mem_req;
156 vk_->GetImageMemoryRequirements(device_->GetHandle(), image, &mem_req);
157 VkMemoryAllocateInfo alloc_info{};
159 alloc_info.allocationSize = mem_req.size;
160 alloc_info.memoryTypeIndex = static_cast<uint32_t>(__builtin_ctz(
161 mem_req.memoryTypeBits & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
162
163 VkDeviceMemory memory;
164 if (VK_CALL_LOG_ERROR(vk_->AllocateMemory(device_->GetHandle(), &alloc_info,
165 nullptr, &memory)) != VK_SUCCESS) {
166 return std::nullopt;
167 }
168
170 memory, [&vk = vk_, &device = device_](VkDeviceMemory memory) {
171 vk->FreeMemory(device->GetHandle(), memory, nullptr);
172 }};
173
174 if (VK_CALL_LOG_ERROR(VK_CALL_LOG_ERROR(vk_->BindImageMemory(
175 device_->GetHandle(), result.image_, result.memory_, 0)))) {
176 return std::nullopt;
177 }
178
179 result.context_ =
181
182 return result;
183}
184
188
189} // namespace testing
190} // namespace flutter
const char * options
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition DM.cpp:213
void releaseResourcesAndAbandonContext()
static sk_sp< VulkanMemoryAllocator > Make(uint32_t vulkan_api_version, VkInstance instance, VkPhysicalDevice physicalDevice, VkDevice device, const fml::RefPtr< vulkan::VulkanProcTable > &vk, bool mustUseCoherentHostVisibleMemory)
sk_sp< GrDirectContext > GetGrDirectContext() const
std::optional< TestVulkanImage > CreateImage(const SkISize &size) const
Captures the lifetime of a test VkImage along with its bound memory.
static fml::RefPtr< NativeLibrary > Create(const char *path)
bool HasAcquiredMandatoryProcAddresses() const
VkDevice device
Definition main.cc:53
sk_sp< SkImage > image
Definition examples.cpp:29
GAsyncResult * result
#define FML_LOG(severity)
Definition logging.h:82
SK_API sk_sp< GrDirectContext > MakeVulkan(const GrVkBackendContext &, const GrContextOptions &)
GrContextOptions MakeDefaultContextOptions(ContextType type, std::optional< GrBackendApi > api)
Initializes GrContextOptions with values suitable for Flutter. The options can be further tweaked bef...
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition switches.h:259
GrVkGetProc CreateSkiaGetProc(const fml::RefPtr< vulkan::VulkanProcTable > &vk)
const skgpu::VulkanExtensions * fVkExtensions
VkPhysicalDevice fPhysicalDevice
skgpu::VulkanGetProc fGetProc
sk_sp< skgpu::VulkanMemoryAllocator > fMemoryAllocator
VkStructureType sType
VkStructureType sType
#define VULKAN_SO_PATH
#define ERROR(message)
@ VK_IMAGE_LAYOUT_UNDEFINED
@ VK_SHARING_MODE_EXCLUSIVE
@ VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
@ VK_IMAGE_TILING_OPTIMAL
@ VK_IMAGE_USAGE_TRANSFER_DST_BIT
@ VK_IMAGE_USAGE_SAMPLED_BIT
@ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
@ VK_IMAGE_USAGE_TRANSFER_SRC_BIT
@ VK_SAMPLE_COUNT_1_BIT
#define VK_MAKE_VERSION(major, minor, patch)
Definition vulkan_core.h:78
@ VK_IMAGE_TYPE_2D
@ VK_SUCCESS
@ VK_FORMAT_R8G8B8A8_UNORM
@ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
@ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO
#define VK_CALL_LOG_ERROR(expression)