Flutter Engine
The Flutter Engine
VkPriorityExtensionTest.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2019 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
9
10#if defined(SK_GANESH) && defined(SK_VULKAN)
11
16#include "tests/Test.h"
18
19#include <algorithm>
20#include <cstdint>
21#include <cstring>
22#include <functional>
23#include <initializer_list>
24#include <vulkan/vulkan_core.h>
25
26struct GrContextOptions;
27
28#define ACQUIRE_VK_PROC_NOCHECK(name, instance) \
29 PFN_vk##name grVk##name = \
30 reinterpret_cast<PFN_vk##name>(getProc("vk" #name, instance, VK_NULL_HANDLE))
31
32#define ACQUIRE_VK_PROC(name, instance) \
33 PFN_vk##name grVk##name = \
34 reinterpret_cast<PFN_vk##name>(getProc("vk" #name, instance, VK_NULL_HANDLE)); \
35 do { \
36 if (grVk##name == nullptr) { \
37 if (instance != VK_NULL_HANDLE) { \
38 destroy_instance(getProc, instance); \
39 } \
40 return; \
41 } \
42 } while (0)
43
44#define ACQUIRE_VK_PROC_LOCAL(name, instance) \
45 PFN_vk##name grVk##name = \
46 reinterpret_cast<PFN_vk##name>(getProc("vk" #name, instance, VK_NULL_HANDLE)); \
47 do { \
48 if (grVk##name == nullptr) { \
49 return; \
50 } \
51 } while (0)
52
53#define GET_PROC_LOCAL(F, inst) PFN_vk ## F F = (PFN_vk ## F) getProc("vk" #F, inst, VK_NULL_HANDLE)
54
55static void destroy_instance(const skgpu::VulkanGetProc& getProc, VkInstance inst) {
56 ACQUIRE_VK_PROC_LOCAL(DestroyInstance, inst);
57 grVkDestroyInstance(inst, nullptr);
58}
59
60// If the extension VK_EXT_GLOBAL_PRIORITY is supported, this test just tries to create a VkDevice
61// using the various global priorities. The test passes if no errors are reported or the test
62// doesn't crash.
63DEF_GANESH_TEST_FOR_VULKAN_CONTEXT(VulkanPriorityExtension,
65 context_info,
68 if (!sk_gpu_test::LoadVkLibraryAndGetProcAddrFuncs(&instProc)) {
69 return;
70 }
71 // This isn't the most effecient but we just use the instProc to get all ptrs.
72 auto getProc = [instProc](const char* proc_name, VkInstance instance, VkDevice) {
73 return instProc(instance, proc_name);
74 };
75
76 VkResult err;
77
78 ACQUIRE_VK_PROC_NOCHECK(EnumerateInstanceVersion, VK_NULL_HANDLE);
79 uint32_t instanceVersion = 0;
80 if (!grVkEnumerateInstanceVersion) {
81 instanceVersion = VK_MAKE_VERSION(1, 0, 0);
82 } else {
83 err = grVkEnumerateInstanceVersion(&instanceVersion);
84 if (err) {
85 ERRORF(reporter, "failed ot enumerate instance version. Err: %d", err);
86 return;
87 }
88 }
89 SkASSERT(instanceVersion >= VK_MAKE_VERSION(1, 0, 0));
90 uint32_t apiVersion = VK_MAKE_VERSION(1, 0, 0);
91 if (instanceVersion >= VK_MAKE_VERSION(1, 1, 0)) {
92 // If the instance version is 1.0 we must have the apiVersion also be 1.0. However, if the
93 // instance version is 1.1 or higher, we can set the apiVersion to be whatever the highest
94 // api we may use in skia (technically it can be arbitrary). So for now we set it to 1.1
95 // since that is the highest vulkan version.
96 apiVersion = VK_MAKE_VERSION(1, 1, 0);
97 }
98
99 instanceVersion = std::min(instanceVersion, apiVersion);
100
101 VkPhysicalDevice physDev;
102 VkDevice device;
103 VkInstance inst;
104
105 const VkApplicationInfo app_info = {
107 nullptr, // pNext
108 "vktest", // pApplicationName
109 0, // applicationVersion
110 "vktest", // pEngineName
111 0, // engineVersion
112 apiVersion, // apiVersion
113 };
114
115 const VkInstanceCreateInfo instance_create = {
117 nullptr, // pNext
118 0, // flags
119 &app_info, // pApplicationInfo
120 0, // enabledLayerNameCount
121 nullptr, // ppEnabledLayerNames
122 0, // enabledExtensionNameCount
123 nullptr, // ppEnabledExtensionNames
124 };
125
126 ACQUIRE_VK_PROC(CreateInstance, VK_NULL_HANDLE);
127 err = grVkCreateInstance(&instance_create, nullptr, &inst);
128 if (err < 0) {
129 ERRORF(reporter, "Failed to create VkInstance");
130 return;
131 }
132
133 ACQUIRE_VK_PROC(EnumeratePhysicalDevices, inst);
134 ACQUIRE_VK_PROC(GetPhysicalDeviceProperties, inst);
135 ACQUIRE_VK_PROC(GetPhysicalDeviceQueueFamilyProperties, inst);
136 ACQUIRE_VK_PROC(GetPhysicalDeviceFeatures, inst);
137 ACQUIRE_VK_PROC(CreateDevice, inst);
138 ACQUIRE_VK_PROC(GetDeviceQueue, inst);
139 ACQUIRE_VK_PROC(DeviceWaitIdle, inst);
140 ACQUIRE_VK_PROC(DestroyDevice, inst);
141
142 uint32_t gpuCount;
143 err = grVkEnumeratePhysicalDevices(inst, &gpuCount, nullptr);
144 if (err) {
145 ERRORF(reporter, "vkEnumeratePhysicalDevices failed: %d", err);
146 destroy_instance(getProc, inst);
147 return;
148 }
149 if (!gpuCount) {
150 // Don't throw and error here, because this behavior is allowed by Android CTS. A device
151 // count of 0 effectively means Vulkan is not supported.
152 destroy_instance(getProc, inst);
153 return;
154 }
155 // Just returning the first physical device instead of getting the whole array.
156 // TODO: find best match for our needs
157 gpuCount = 1;
158 err = grVkEnumeratePhysicalDevices(inst, &gpuCount, &physDev);
159 // VK_INCOMPLETE is returned when the count we provide is less than the total device count.
160 if (err && VK_INCOMPLETE != err) {
161 ERRORF(reporter, "vkEnumeratePhysicalDevices failed: %d", err);
162 destroy_instance(getProc, inst);
163 return;
164 }
165
166 // query to get the initial queue props size
167 uint32_t queueCount;
168 grVkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, nullptr);
169 if (!queueCount) {
170 ERRORF(reporter, "vkGetPhysicalDeviceQueueFamilyProperties returned no queues.");
171 destroy_instance(getProc, inst);
172 return;
173 }
174
175 SkAutoMalloc queuePropsAlloc(queueCount * sizeof(VkQueueFamilyProperties));
176 // now get the actual queue props
177 VkQueueFamilyProperties* queueProps = (VkQueueFamilyProperties*)queuePropsAlloc.get();
178
179 grVkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, queueProps);
180
181 // iterate to find the graphics queue
182 uint32_t graphicsQueueIndex = queueCount;
183 for (uint32_t i = 0; i < queueCount; i++) {
184 if (queueProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
185 graphicsQueueIndex = i;
186 break;
187 }
188 }
189 if (graphicsQueueIndex == queueCount) {
190 ERRORF(reporter, "Could not find any supported graphics queues.");
191 destroy_instance(getProc, inst);
192 return;
193 }
194
195 GET_PROC_LOCAL(EnumerateDeviceExtensionProperties, inst);
196 GET_PROC_LOCAL(EnumerateDeviceLayerProperties, inst);
197
198 if (!EnumerateDeviceExtensionProperties ||
199 !EnumerateDeviceLayerProperties) {
200 destroy_instance(getProc, inst);
201 return;
202 }
203
204 // device extensions
205 // via Vulkan implementation and implicitly enabled layers
206 uint32_t extensionCount = 0;
207 err = EnumerateDeviceExtensionProperties(physDev, nullptr, &extensionCount, nullptr);
208 if (VK_SUCCESS != err) {
209 ERRORF(reporter, "Could not enumerate device extension properties.");
210 destroy_instance(getProc, inst);
211 return;
212 }
214 err = EnumerateDeviceExtensionProperties(physDev, nullptr, &extensionCount, extensions);
215 if (VK_SUCCESS != err) {
216 delete[] extensions;
217 ERRORF(reporter, "Could not enumerate device extension properties.");
218 destroy_instance(getProc, inst);
219 return;
220 }
221 bool hasPriorityExt = false;
222 for (uint32_t i = 0; i < extensionCount; ++i) {
223 if (!strcmp(extensions[i].extensionName, VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME)) {
224 hasPriorityExt = true;
225 }
226 }
227 delete[] extensions;
228
229 if (!hasPriorityExt) {
230 destroy_instance(getProc, inst);
231 return;
232 }
233
234 const char* priorityExt = VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME;
235
236 VkPhysicalDeviceFeatures deviceFeatures;
237 grVkGetPhysicalDeviceFeatures(physDev, &deviceFeatures);
238
239 // this looks like it would slow things down,
240 // and we can't depend on it on all platforms
241 deviceFeatures.robustBufferAccess = VK_FALSE;
242
243 float queuePriorities[1] = { 0.0 };
244
245 VkDeviceQueueGlobalPriorityCreateInfoEXT queuePriorityCreateInfo;
246 queuePriorityCreateInfo.sType =
248 queuePriorityCreateInfo.pNext = nullptr;
249
250 VkDeviceQueueCreateInfo queueInfo = {
252 &queuePriorityCreateInfo, // pNext
253 0, // VkDeviceQueueCreateFlags
254 graphicsQueueIndex, // queueFamilyIndex
255 1, // queueCount
256 queuePriorities, // pQueuePriorities
257 };
258
263 queuePriorityCreateInfo.globalPriority = globalPriority;
264
265 const VkDeviceCreateInfo deviceInfo = {
267 nullptr, // pNext
268 0, // VkDeviceCreateFlags
269 1, // queueCreateInfoCount
270 &queueInfo, // pQueueCreateInfos
271 0, // layerCount
272 nullptr, // ppEnabledLayerNames
273 1, // extensionCount
274 &priorityExt, // ppEnabledExtensionNames
275 &deviceFeatures // ppEnabledFeatures
276 };
277
278 err = grVkCreateDevice(physDev, &deviceInfo, nullptr, &device);
279
280 if (err != VK_SUCCESS && err != VK_ERROR_NOT_PERMITTED_EXT) {
281 ERRORF(reporter, "CreateDevice failed: %d, priority %d", err, globalPriority);
282 destroy_instance(getProc, inst);
283 continue;
284 }
285 if (err != VK_ERROR_NOT_PERMITTED_EXT) {
286 grVkDestroyDevice(device, nullptr);
287 }
288 }
289 destroy_instance(getProc, inst);
290}
291
292#endif
reporter
Definition: FontMgrTest.cpp:39
#define GET_PROC_LOCAL(F)
#define ACQUIRE_VK_PROC_LOCAL(name, inst)
#define SkASSERT(cond)
Definition: SkAssert.h:116
#define DEF_GANESH_TEST_FOR_VULKAN_CONTEXT(name, reporter, context_info, ctsEnforcement)
Definition: Test.h:458
#define ERRORF(r,...)
Definition: Test.h:293
VkDevice device
Definition: main.cc:53
VkInstance instance
Definition: main.cc:48
static float min(float r, float g, float b)
Definition: hsl.cpp:48
inst
Definition: malisc.py:37
std::function< PFN_vkVoidFunction(const char *, VkInstance, VkDevice)> VulkanGetProc
Definition: VulkanTypes.h:30
VkQueueGlobalPriorityKHR globalPriority
Definition: vulkan_core.h:9662
#define VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME
VkQueueGlobalPriorityKHR
Definition: vulkan_core.h:9648
@ VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_EXT
Definition: vulkan_core.h:9654
@ VK_QUEUE_GLOBAL_PRIORITY_HIGH_EXT
Definition: vulkan_core.h:9655
@ VK_QUEUE_GLOBAL_PRIORITY_REALTIME_EXT
Definition: vulkan_core.h:9656
@ VK_QUEUE_GLOBAL_PRIORITY_LOW_EXT
Definition: vulkan_core.h:9653
#define VK_FALSE
Definition: vulkan_core.h:125
#define VK_MAKE_VERSION(major, minor, patch)
Definition: vulkan_core.h:78
@ VK_QUEUE_GRAPHICS_BIT
Definition: vulkan_core.h:2413
VkResult
Definition: vulkan_core.h:140
@ VK_INCOMPLETE
Definition: vulkan_core.h:146
@ VK_SUCCESS
Definition: vulkan_core.h:141
@ VK_ERROR_NOT_PERMITTED_EXT
Definition: vulkan_core.h:193
#define VK_NULL_HANDLE
Definition: vulkan_core.h:46
PFN_vkVoidFunction(VKAPI_PTR * PFN_vkGetInstanceProcAddr)(VkInstance instance, const char *pName)
Definition: vulkan_core.h:3989
@ VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO
Definition: vulkan_core.h:204
@ VK_STRUCTURE_TYPE_APPLICATION_INFO
Definition: vulkan_core.h:202
@ VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO
Definition: vulkan_core.h:203
@ VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT
Definition: vulkan_core.h:1242
@ VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO
Definition: vulkan_core.h:205