Flutter Engine
The Flutter Engine
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
74 if (!device_->GetPhysicalDeviceFeatures(&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
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.fMaxAPIVersion = VK_MAKE_VERSION(1, 0, 0);
100 backend_context.fDeviceFeatures = &features;
101 backend_context.fVkExtensions = &extensions;
102 backend_context.fGetProc = get_proc;
103 backend_context.fMemoryAllocator = allocator;
104
107 options.fReduceOpsTaskSplitting = GrContextOptions::Enable::kNo;
108 context_ = GrDirectContexts::MakeVulkan(backend_context, options);
109}
110
112 if (context_) {
114 }
115}
116
117std::optional<TestVulkanImage> TestVulkanContext::CreateImage(
118 const SkISize& size) const {
120
123 .pNext = nullptr,
124 .flags = 0,
125 .imageType = VK_IMAGE_TYPE_2D,
126 .format = VK_FORMAT_R8G8B8A8_UNORM,
127 .extent = VkExtent3D{static_cast<uint32_t>(size.width()),
128 static_cast<uint32_t>(size.height()), 1},
129 .mipLevels = 1,
130 .arrayLayers = 1,
131 .samples = VK_SAMPLE_COUNT_1_BIT,
132 .tiling = VK_IMAGE_TILING_OPTIMAL,
136 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
137 .queueFamilyIndexCount = 0,
138 .pQueueFamilyIndices = nullptr,
139 .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
140 };
141
142 VkImage image;
144 vk_->CreateImage(device_->GetHandle(), &info, nullptr, &image)))) {
145 return std::nullopt;
146 }
147
149 image, [&vk = vk_, &device = device_](VkImage image) {
150 vk->DestroyImage(device->GetHandle(), image, nullptr);
151 });
152
153 VkMemoryRequirements mem_req;
154 vk_->GetImageMemoryRequirements(device_->GetHandle(), image, &mem_req);
155 VkMemoryAllocateInfo alloc_info{};
157 alloc_info.allocationSize = mem_req.size;
158 alloc_info.memoryTypeIndex = static_cast<uint32_t>(__builtin_ctz(
159 mem_req.memoryTypeBits & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
160
161 VkDeviceMemory memory;
162 if (VK_CALL_LOG_ERROR(vk_->AllocateMemory(device_->GetHandle(), &alloc_info,
163 nullptr, &memory)) != VK_SUCCESS) {
164 return std::nullopt;
165 }
166
168 memory, [&vk = vk_, &device = device_](VkDeviceMemory memory) {
169 vk->FreeMemory(device->GetHandle(), memory, nullptr);
170 }};
171
172 if (VK_CALL_LOG_ERROR(VK_CALL_LOG_ERROR(vk_->BindImageMemory(
173 device_->GetHandle(), result.image_, result.memory_, 0)))) {
174 return std::nullopt;
175 }
176
177 result.context_ =
179
180 return result;
181}
182
184 return context_;
185}
186
187} // namespace testing
188} // 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
bool AreInstanceProcsSetup() const
VkDevice device
Definition: main.cc:53
GAsyncResult * result
#define FML_LOG(severity)
Definition: logging.h:82
SK_API sk_sp< GrDirectContext > MakeVulkan(const skgpu::VulkanBackendContext &, const GrContextOptions &)
sk_sp< const SkImage > image
Definition: SkRecords.h:269
GrContextOptions MakeDefaultContextOptions(ContextType type, std::optional< GrBackendApi > api)
Initializes GrContextOptions with values suitable for Flutter. The options can be further tweaked bef...
@ kRender
The context is used to render to a texture or renderbuffer.
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
vk
Definition: malisc.py:42
GrVkGetProc CreateSkiaGetProc(const fml::RefPtr< vulkan::VulkanProcTable > &vk)
Definition: SkSize.h:16
VkStructureType sType
Definition: vulkan_core.h:3303
sk_sp< VulkanMemoryAllocator > fMemoryAllocator
const VkPhysicalDeviceFeatures * fDeviceFeatures
const skgpu::VulkanExtensions * fVkExtensions
#define VULKAN_SO_PATH
#define ERROR(message)
Definition: elf_loader.cc:260
@ VK_IMAGE_LAYOUT_UNDEFINED
Definition: vulkan_core.h:1331
@ VK_SHARING_MODE_EXCLUSIVE
Definition: vulkan_core.h:1813
@ VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
Definition: vulkan_core.h:2399
@ VK_IMAGE_TILING_OPTIMAL
Definition: vulkan_core.h:1767
@ VK_IMAGE_USAGE_TRANSFER_DST_BIT
Definition: vulkan_core.h:2353
@ VK_IMAGE_USAGE_SAMPLED_BIT
Definition: vulkan_core.h:2354
@ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
Definition: vulkan_core.h:2356
@ VK_IMAGE_USAGE_TRANSFER_SRC_BIT
Definition: vulkan_core.h:2352
@ VK_SAMPLE_COUNT_1_BIT
Definition: vulkan_core.h:2340
#define VK_MAKE_VERSION(major, minor, patch)
Definition: vulkan_core.h:78
@ VK_IMAGE_TYPE_2D
Definition: vulkan_core.h:1775
@ VK_SUCCESS
Definition: vulkan_core.h:141
@ VK_FORMAT_R8G8B8A8_UNORM
Definition: vulkan_core.h:1496
@ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
Definition: vulkan_core.h:216
@ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO
Definition: vulkan_core.h:207
#define VK_CALL_LOG_ERROR(expression)