blob: b3a3665b1d68669e19f3a8b22b24b5fd8a6d64b5 [file] [log] [blame]
Greg Daniel35970ec2017-11-10 10:03:05 -05001/*
2 * Copyright 2017 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
8#include "VkTestUtils.h"
9
10#ifdef SK_VULKAN
11
Greg Danielf730c182018-07-02 20:15:37 +000012#include "SkAutoMalloc.h"
13#include "vk/GrVkBackendContext.h"
14#include "vk/GrVkExtensions.h"
Greg Daniel35970ec2017-11-10 10:03:05 -050015#include "../ports/SkOSLibrary.h"
16
17namespace sk_gpu_test {
18
19bool LoadVkLibraryAndGetProcAddrFuncs(PFN_vkGetInstanceProcAddr* instProc,
Greg Danield3e65aa2018-08-01 09:19:45 -040020 PFN_vkGetDeviceProcAddr* devProc) {
Chris Dalton3a67b8e2018-05-03 09:30:29 -060021#ifdef SK_MOLTENVK
22 // MoltenVK is a statically linked framework, so there is no Vulkan library to load.
23 *instProc = &vkGetInstanceProcAddr;
24 *devProc = &vkGetDeviceProcAddr;
25 return true;
26#else
Greg Daniel35970ec2017-11-10 10:03:05 -050027 static void* vkLib = nullptr;
28 static PFN_vkGetInstanceProcAddr localInstProc = nullptr;
29 static PFN_vkGetDeviceProcAddr localDevProc = nullptr;
30 if (!vkLib) {
31#if defined _WIN32
32 vkLib = DynamicLoadLibrary("vulkan-1.dll");
33#else
34 vkLib = DynamicLoadLibrary("libvulkan.so");
35#endif
36 if (!vkLib) {
37 return false;
38 }
39 localInstProc = (PFN_vkGetInstanceProcAddr) GetProcedureAddress(vkLib,
40 "vkGetInstanceProcAddr");
41 localDevProc = (PFN_vkGetDeviceProcAddr) GetProcedureAddress(vkLib,
42 "vkGetDeviceProcAddr");
43 }
44 if (!localInstProc || !localDevProc) {
45 return false;
46 }
47 *instProc = localInstProc;
48 *devProc = localDevProc;
49 return true;
Chris Dalton3a67b8e2018-05-03 09:30:29 -060050#endif
Greg Daniel35970ec2017-11-10 10:03:05 -050051}
Greg Danielf730c182018-07-02 20:15:37 +000052
53////////////////////////////////////////////////////////////////////////////////
54// Helper code to set up Vulkan context objects
55
56#ifdef SK_ENABLE_VK_LAYERS
57const char* kDebugLayerNames[] = {
58 // elements of VK_LAYER_LUNARG_standard_validation
59 "VK_LAYER_GOOGLE_threading",
60 "VK_LAYER_LUNARG_parameter_validation",
61 "VK_LAYER_LUNARG_object_tracker",
Greg Danielf730c182018-07-02 20:15:37 +000062 "VK_LAYER_LUNARG_core_validation",
Greg Danielf730c182018-07-02 20:15:37 +000063 "VK_LAYER_GOOGLE_unique_objects",
64 // not included in standard_validation
65 //"VK_LAYER_LUNARG_api_dump",
66 //"VK_LAYER_LUNARG_vktrace",
67 //"VK_LAYER_LUNARG_screenshot",
68};
Greg Danielf730c182018-07-02 20:15:37 +000069
Greg Daniel98bffae2018-08-01 13:25:41 -040070static bool should_include_debug_layer(const VkLayerProperties& layerProps) {
71 for (size_t i = 0; i < SK_ARRAY_COUNT(kDebugLayerNames); ++i) {
72 if (!strcmp(layerProps.layerName, kDebugLayerNames[i])) {
73 return true;
74 }
Greg Danielf730c182018-07-02 20:15:37 +000075 }
Greg Daniel98bffae2018-08-01 13:25:41 -040076 return false;
77}
Greg Daniel37329b32018-07-02 20:16:44 +000078VKAPI_ATTR VkBool32 VKAPI_CALL DebugReportCallback(
79 VkDebugReportFlagsEXT flags,
80 VkDebugReportObjectTypeEXT objectType,
81 uint64_t object,
82 size_t location,
83 int32_t messageCode,
84 const char* pLayerPrefix,
85 const char* pMessage,
86 void* pUserData) {
87 if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
88 SkDebugf("Vulkan error [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
89 return VK_TRUE; // skip further layers
90 } else if (flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
91 SkDebugf("Vulkan warning [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
92 } else if (flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) {
93 SkDebugf("Vulkan perf warning [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
94 } else {
95 SkDebugf("Vulkan info/debug [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
96 }
97 return VK_FALSE;
98}
99#endif
100
Greg Daniel98bffae2018-08-01 13:25:41 -0400101#define GET_PROC_LOCAL(F, inst, device) PFN_vk ## F F = (PFN_vk ## F) getProc("vk" #F, inst, device)
102
103#ifdef SK_ENABLE_VK_LAYERS
104static uint32_t remove_patch_version(uint32_t specVersion) {
105 return (specVersion >> 12) << 12;
106}
107#endif
108
109static bool init_instance_extensions_and_layers(GrVkGetProc getProc,
110 uint32_t specVersion,
111 SkTArray<VkExtensionProperties>* instanceExtensions,
112 SkTArray<VkLayerProperties>* instanceLayers) {
113 if (getProc == nullptr) {
114 return false;
115 }
116
117 GET_PROC_LOCAL(EnumerateInstanceExtensionProperties, VK_NULL_HANDLE, VK_NULL_HANDLE);
118 GET_PROC_LOCAL(EnumerateInstanceLayerProperties, VK_NULL_HANDLE, VK_NULL_HANDLE);
119
120 if (!EnumerateInstanceExtensionProperties ||
121 !EnumerateInstanceLayerProperties) {
122 return false;
123 }
124
125 VkResult res;
126 uint32_t layerCount = 0;
127#ifdef SK_ENABLE_VK_LAYERS
128 // instance layers
129 res = EnumerateInstanceLayerProperties(&layerCount, nullptr);
130 if (VK_SUCCESS != res) {
131 return false;
132 }
133 VkLayerProperties* layers = new VkLayerProperties[layerCount];
134 res = EnumerateInstanceLayerProperties(&layerCount, layers);
135 if (VK_SUCCESS != res) {
136 delete[] layers;
137 return false;
138 }
139
140 uint32_t nonPatchVersion = remove_patch_version(specVersion);
141 for (uint32_t i = 0; i < layerCount; ++i) {
142 if (nonPatchVersion <= remove_patch_version(layers[i].specVersion) &&
143 should_include_debug_layer(layers[i])) {
144 instanceLayers->push_back() = layers[i];
145 }
146 }
147 delete[] layers;
148#endif
149
150 // instance extensions
151 // via Vulkan implementation and implicitly enabled layers
152 uint32_t extensionCount = 0;
153 res = EnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
154 if (VK_SUCCESS != res) {
155 return false;
156 }
157 VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
158 res = EnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions);
159 if (VK_SUCCESS != res) {
160 delete[] extensions;
161 return false;
162 }
163 for (uint32_t i = 0; i < extensionCount; ++i) {
164 instanceExtensions->push_back() = extensions[i];
165 }
166 delete [] extensions;
167
168 // via explicitly enabled layers
169 layerCount = instanceLayers->count();
170 for (uint32_t layerIndex = 0; layerIndex < layerCount; ++layerIndex) {
171 uint32_t extensionCount = 0;
172 res = EnumerateInstanceExtensionProperties((*instanceLayers)[layerIndex].layerName,
173 &extensionCount, nullptr);
174 if (VK_SUCCESS != res) {
175 return false;
176 }
177 VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
178 res = EnumerateInstanceExtensionProperties((*instanceLayers)[layerIndex].layerName,
179 &extensionCount, extensions);
180 if (VK_SUCCESS != res) {
181 delete[] extensions;
182 return false;
183 }
184 for (uint32_t i = 0; i < extensionCount; ++i) {
185 instanceExtensions->push_back() = extensions[i];
186 }
187 delete[] extensions;
188 }
189
190 return true;
191}
192
193static bool init_device_extensions_and_layers(GrVkGetProc getProc, uint32_t specVersion,
194 VkInstance inst, VkPhysicalDevice physDev,
195 SkTArray<VkExtensionProperties>* deviceExtensions,
196 SkTArray<VkLayerProperties>* deviceLayers) {
197 if (getProc == nullptr) {
198 return false;
199 }
200
201 GET_PROC_LOCAL(EnumerateDeviceExtensionProperties, inst, VK_NULL_HANDLE);
202 GET_PROC_LOCAL(EnumerateDeviceLayerProperties, inst, VK_NULL_HANDLE);
203
204 if (!EnumerateDeviceExtensionProperties ||
205 !EnumerateDeviceLayerProperties) {
206 return false;
207 }
208
209 VkResult res;
210 // device layers
211 uint32_t layerCount = 0;
212#ifdef SK_ENABLE_VK_LAYERS
213 res = EnumerateDeviceLayerProperties(physDev, &layerCount, nullptr);
214 if (VK_SUCCESS != res) {
215 return false;
216 }
217 VkLayerProperties* layers = new VkLayerProperties[layerCount];
218 res = EnumerateDeviceLayerProperties(physDev, &layerCount, layers);
219 if (VK_SUCCESS != res) {
220 delete[] layers;
221 return false;
222 }
223
224 uint32_t nonPatchVersion = remove_patch_version(specVersion);
225 for (uint32_t i = 0; i < layerCount; ++i) {
226 if (nonPatchVersion <= remove_patch_version(layers[i].specVersion) &&
227 should_include_debug_layer(layers[i])) {
228 deviceLayers->push_back() = layers[i];
229 }
230 }
231 delete[] layers;
232#endif
233
234 // device extensions
235 // via Vulkan implementation and implicitly enabled layers
236 uint32_t extensionCount = 0;
237 res = EnumerateDeviceExtensionProperties(physDev, nullptr, &extensionCount, nullptr);
238 if (VK_SUCCESS != res) {
239 return false;
240 }
241 VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
242 res = EnumerateDeviceExtensionProperties(physDev, nullptr, &extensionCount, extensions);
243 if (VK_SUCCESS != res) {
244 delete[] extensions;
245 return false;
246 }
247 for (uint32_t i = 0; i < extensionCount; ++i) {
248 deviceExtensions->push_back() = extensions[i];
249 }
250 delete[] extensions;
251
252 // via explicitly enabled layers
253 layerCount = deviceLayers->count();
254 for (uint32_t layerIndex = 0; layerIndex < layerCount; ++layerIndex) {
255 uint32_t extensionCount = 0;
256 res = EnumerateDeviceExtensionProperties(physDev,
257 (*deviceLayers)[layerIndex].layerName,
258 &extensionCount, nullptr);
259 if (VK_SUCCESS != res) {
260 return false;
261 }
262 VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
263 res = EnumerateDeviceExtensionProperties(physDev,
264 (*deviceLayers)[layerIndex].layerName,
265 &extensionCount, extensions);
266 if (VK_SUCCESS != res) {
267 delete[] extensions;
268 return false;
269 }
270 for (uint32_t i = 0; i < extensionCount; ++i) {
271 deviceExtensions->push_back() = extensions[i];
272 }
273 delete[] extensions;
274 }
275
276 return true;
277}
278
279// the minimum version of Vulkan supported
280#ifdef SK_BUILD_FOR_ANDROID
281const uint32_t kGrVkMinimumVersion = VK_MAKE_VERSION(1, 0, 3);
282#else
283const uint32_t kGrVkMinimumVersion = VK_MAKE_VERSION(1, 0, 8);
284#endif
285
286#define ACQUIRE_VK_PROC(name, instance, device) \
287 PFN_vk##name grVk##name = \
288 reinterpret_cast<PFN_vk##name>(getProc("vk" #name, instance, device)); \
289 if (grVk##name == nullptr) { \
290 SkDebugf("Function ptr for vk%s could not be acquired\n", #name); \
291 if (device != VK_NULL_HANDLE) { \
292 destroy_instance(getProc, inst, debugCallback, hasDebugExtension); \
293 } \
294 return false; \
295 }
296
Greg Daniel37329b32018-07-02 20:16:44 +0000297#define ACQUIRE_VK_PROC_LOCAL(name, instance, device) \
298 PFN_vk##name grVk##name = \
299 reinterpret_cast<PFN_vk##name>(getProc("vk" #name, instance, device)); \
300 if (grVk##name == nullptr) { \
301 SkDebugf("Function ptr for vk%s could not be acquired\n", #name); \
302 return; \
303 }
304
Greg Danield3e65aa2018-08-01 09:19:45 -0400305static void destroy_instance(GrVkGetProc getProc, VkInstance inst,
Greg Daniel37329b32018-07-02 20:16:44 +0000306 VkDebugReportCallbackEXT* debugCallback,
307 bool hasDebugExtension) {
308 if (hasDebugExtension && *debugCallback != VK_NULL_HANDLE) {
309 ACQUIRE_VK_PROC_LOCAL(DestroyDebugReportCallbackEXT, inst, VK_NULL_HANDLE);
310 grVkDestroyDebugReportCallbackEXT(inst, *debugCallback, nullptr);
311 *debugCallback = VK_NULL_HANDLE;
312 }
313 ACQUIRE_VK_PROC_LOCAL(DestroyInstance, inst, VK_NULL_HANDLE);
314 grVkDestroyInstance(inst, nullptr);
315}
316
Greg Danield3e65aa2018-08-01 09:19:45 -0400317bool CreateVkBackendContext(GrVkGetProc getProc,
Greg Danielf730c182018-07-02 20:15:37 +0000318 GrVkBackendContext* ctx,
Greg Daniel98bffae2018-08-01 13:25:41 -0400319 GrVkExtensions* extensions,
Greg Daniel37329b32018-07-02 20:16:44 +0000320 VkDebugReportCallbackEXT* debugCallback,
Greg Danielf730c182018-07-02 20:15:37 +0000321 uint32_t* presentQueueIndexPtr,
322 CanPresentFn canPresent) {
Greg Danielf730c182018-07-02 20:15:37 +0000323 VkPhysicalDevice physDev;
324 VkDevice device;
325 VkInstance inst;
326 VkResult err;
327
328 const VkApplicationInfo app_info = {
329 VK_STRUCTURE_TYPE_APPLICATION_INFO, // sType
330 nullptr, // pNext
331 "vktest", // pApplicationName
332 0, // applicationVersion
333 "vktest", // pEngineName
334 0, // engineVerison
335 kGrVkMinimumVersion, // apiVersion
336 };
337
Greg Daniel98bffae2018-08-01 13:25:41 -0400338 SkTArray<VkLayerProperties> instanceLayers;
339 SkTArray<VkExtensionProperties> instanceExtensions;
340
341 if (!init_instance_extensions_and_layers(getProc, kGrVkMinimumVersion,
342 &instanceExtensions,
343 &instanceLayers)) {
344 return false;
345 }
Greg Danielf730c182018-07-02 20:15:37 +0000346
347 SkTArray<const char*> instanceLayerNames;
348 SkTArray<const char*> instanceExtensionNames;
Greg Daniel98bffae2018-08-01 13:25:41 -0400349 for (int i = 0; i < instanceLayers.count(); ++i) {
350 instanceLayerNames.push_back(instanceLayers[i].layerName);
351 }
352 for (int i = 0; i < instanceExtensions.count(); ++i) {
353 if (strncmp(instanceExtensions[i].extensionName, "VK_KHX", 6)) {
354 instanceExtensionNames.push_back(instanceExtensions[i].extensionName);
Greg Danielf730c182018-07-02 20:15:37 +0000355 }
356 }
Greg Danielf730c182018-07-02 20:15:37 +0000357
358 const VkInstanceCreateInfo instance_create = {
359 VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // sType
360 nullptr, // pNext
361 0, // flags
362 &app_info, // pApplicationInfo
363 (uint32_t) instanceLayerNames.count(), // enabledLayerNameCount
364 instanceLayerNames.begin(), // ppEnabledLayerNames
365 (uint32_t) instanceExtensionNames.count(), // enabledExtensionNameCount
366 instanceExtensionNames.begin(), // ppEnabledExtensionNames
367 };
368
Greg Daniel98bffae2018-08-01 13:25:41 -0400369 bool hasDebugExtension = false;
370
Greg Danielf730c182018-07-02 20:15:37 +0000371 ACQUIRE_VK_PROC(CreateInstance, VK_NULL_HANDLE, VK_NULL_HANDLE);
372 err = grVkCreateInstance(&instance_create, nullptr, &inst);
373 if (err < 0) {
374 SkDebugf("vkCreateInstance failed: %d\n", err);
375 return false;
376 }
377
Greg Daniel37329b32018-07-02 20:16:44 +0000378#ifdef SK_ENABLE_VK_LAYERS
379 *debugCallback = VK_NULL_HANDLE;
380 for (int i = 0; i < instanceExtensionNames.count() && !hasDebugExtension; ++i) {
381 if (!strcmp(instanceExtensionNames[i], VK_EXT_DEBUG_REPORT_EXTENSION_NAME)) {
382 hasDebugExtension = true;
383 }
384 }
385 if (hasDebugExtension) {
386 // Setup callback creation information
387 VkDebugReportCallbackCreateInfoEXT callbackCreateInfo;
388 callbackCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
389 callbackCreateInfo.pNext = nullptr;
390 callbackCreateInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT |
391 VK_DEBUG_REPORT_WARNING_BIT_EXT |
392 // VK_DEBUG_REPORT_INFORMATION_BIT_EXT |
393 // VK_DEBUG_REPORT_DEBUG_BIT_EXT |
394 VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
395 callbackCreateInfo.pfnCallback = &DebugReportCallback;
396 callbackCreateInfo.pUserData = nullptr;
397
398 ACQUIRE_VK_PROC(CreateDebugReportCallbackEXT, inst, VK_NULL_HANDLE);
399 // Register the callback
400 grVkCreateDebugReportCallbackEXT(inst, &callbackCreateInfo, nullptr, debugCallback);
401 }
402#endif
403
Greg Danielf730c182018-07-02 20:15:37 +0000404 ACQUIRE_VK_PROC(EnumeratePhysicalDevices, inst, VK_NULL_HANDLE);
405 ACQUIRE_VK_PROC(GetPhysicalDeviceQueueFamilyProperties, inst, VK_NULL_HANDLE);
406 ACQUIRE_VK_PROC(GetPhysicalDeviceFeatures, inst, VK_NULL_HANDLE);
407 ACQUIRE_VK_PROC(CreateDevice, inst, VK_NULL_HANDLE);
408 ACQUIRE_VK_PROC(GetDeviceQueue, inst, VK_NULL_HANDLE);
409 ACQUIRE_VK_PROC(DeviceWaitIdle, inst, VK_NULL_HANDLE);
410 ACQUIRE_VK_PROC(DestroyDevice, inst, VK_NULL_HANDLE);
411
412 uint32_t gpuCount;
413 err = grVkEnumeratePhysicalDevices(inst, &gpuCount, nullptr);
414 if (err) {
415 SkDebugf("vkEnumeratePhysicalDevices failed: %d\n", err);
Greg Daniel37329b32018-07-02 20:16:44 +0000416 destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
Greg Danielf730c182018-07-02 20:15:37 +0000417 return false;
418 }
419 if (!gpuCount) {
420 SkDebugf("vkEnumeratePhysicalDevices returned no supported devices.\n");
Greg Daniel37329b32018-07-02 20:16:44 +0000421 destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
Greg Danielf730c182018-07-02 20:15:37 +0000422 return false;
423 }
424 // Just returning the first physical device instead of getting the whole array.
425 // TODO: find best match for our needs
426 gpuCount = 1;
427 err = grVkEnumeratePhysicalDevices(inst, &gpuCount, &physDev);
428 // VK_INCOMPLETE is returned when the count we provide is less than the total device count.
429 if (err && VK_INCOMPLETE != err) {
430 SkDebugf("vkEnumeratePhysicalDevices failed: %d\n", err);
Greg Daniel37329b32018-07-02 20:16:44 +0000431 destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
Greg Danielf730c182018-07-02 20:15:37 +0000432 return false;
433 }
434
435 // query to get the initial queue props size
436 uint32_t queueCount;
437 grVkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, nullptr);
438 if (!queueCount) {
439 SkDebugf("vkGetPhysicalDeviceQueueFamilyProperties returned no queues.\n");
Greg Daniel37329b32018-07-02 20:16:44 +0000440 destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
Greg Danielf730c182018-07-02 20:15:37 +0000441 return false;
442 }
443
444 SkAutoMalloc queuePropsAlloc(queueCount * sizeof(VkQueueFamilyProperties));
445 // now get the actual queue props
446 VkQueueFamilyProperties* queueProps = (VkQueueFamilyProperties*)queuePropsAlloc.get();
447
448 grVkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, queueProps);
449
450 // iterate to find the graphics queue
451 uint32_t graphicsQueueIndex = queueCount;
452 for (uint32_t i = 0; i < queueCount; i++) {
453 if (queueProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
454 graphicsQueueIndex = i;
455 break;
456 }
457 }
458 if (graphicsQueueIndex == queueCount) {
459 SkDebugf("Could not find any supported graphics queues.\n");
Greg Daniel37329b32018-07-02 20:16:44 +0000460 destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
Greg Danielf730c182018-07-02 20:15:37 +0000461 return false;
462 }
463
464 // iterate to find the present queue, if needed
465 uint32_t presentQueueIndex = queueCount;
466 if (presentQueueIndexPtr && canPresent) {
467 for (uint32_t i = 0; i < queueCount; i++) {
468 if (canPresent(inst, physDev, i)) {
469 presentQueueIndex = i;
470 break;
471 }
472 }
473 if (presentQueueIndex == queueCount) {
474 SkDebugf("Could not find any supported present queues.\n");
Greg Daniel37329b32018-07-02 20:16:44 +0000475 destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
Greg Danielf730c182018-07-02 20:15:37 +0000476 return false;
477 }
478 *presentQueueIndexPtr = presentQueueIndex;
479 } else {
480 // Just setting this so we end up make a single queue for graphics since there was no
481 // request for a present queue.
482 presentQueueIndex = graphicsQueueIndex;
483 }
484
Greg Daniel98bffae2018-08-01 13:25:41 -0400485 SkTArray<VkLayerProperties> deviceLayers;
486 SkTArray<VkExtensionProperties> deviceExtensions;
487 if (!init_device_extensions_and_layers(getProc, kGrVkMinimumVersion,
488 inst, physDev,
489 &deviceExtensions,
490 &deviceLayers)) {
491 destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
492 return false;
493 }
Greg Danielf730c182018-07-02 20:15:37 +0000494
495 SkTArray<const char*> deviceLayerNames;
496 SkTArray<const char*> deviceExtensionNames;
Greg Daniel98bffae2018-08-01 13:25:41 -0400497 for (int i = 0; i < deviceLayers.count(); ++i) {
498 deviceLayerNames.push_back(deviceLayers[i].layerName);
Greg Danielf730c182018-07-02 20:15:37 +0000499 }
Greg Daniel98bffae2018-08-01 13:25:41 -0400500 for (int i = 0; i < deviceExtensions.count(); ++i) {
501 // Don't use experimental extensions since they typically don't work with debug layers and
502 // often are missing dependecy requirements for other extensions. Additionally, these are
503 // often left behind in the driver even after they've been promoted to real extensions.
504 if (strncmp(deviceExtensions[i].extensionName, "VK_KHX", 6) &&
505 strncmp(deviceExtensions[i].extensionName, "VK_NVX", 6)) {
506 deviceExtensionNames.push_back(deviceExtensions[i].extensionName);
507 }
Greg Danielf730c182018-07-02 20:15:37 +0000508 }
509
510 // query to get the physical device properties
511 VkPhysicalDeviceFeatures deviceFeatures;
512 grVkGetPhysicalDeviceFeatures(physDev, &deviceFeatures);
513 // this looks like it would slow things down,
514 // and we can't depend on it on all platforms
515 deviceFeatures.robustBufferAccess = VK_FALSE;
516
517 uint32_t featureFlags = 0;
518 if (deviceFeatures.geometryShader) {
519 featureFlags |= kGeometryShader_GrVkFeatureFlag;
520 }
521 if (deviceFeatures.dualSrcBlend) {
522 featureFlags |= kDualSrcBlend_GrVkFeatureFlag;
523 }
524 if (deviceFeatures.sampleRateShading) {
525 featureFlags |= kSampleRateShading_GrVkFeatureFlag;
526 }
527
528 float queuePriorities[1] = { 0.0 };
529 // Here we assume no need for swapchain queue
530 // If one is needed, the client will need its own setup code
531 const VkDeviceQueueCreateInfo queueInfo[2] = {
532 {
533 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
534 nullptr, // pNext
535 0, // VkDeviceQueueCreateFlags
536 graphicsQueueIndex, // queueFamilyIndex
537 1, // queueCount
538 queuePriorities, // pQueuePriorities
539 },
540 {
541 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
542 nullptr, // pNext
543 0, // VkDeviceQueueCreateFlags
544 presentQueueIndex, // queueFamilyIndex
545 1, // queueCount
546 queuePriorities, // pQueuePriorities
547 }
548 };
549 uint32_t queueInfoCount = (presentQueueIndex != graphicsQueueIndex) ? 2 : 1;
550
551 const VkDeviceCreateInfo deviceInfo = {
552 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // sType
553 nullptr, // pNext
554 0, // VkDeviceCreateFlags
555 queueInfoCount, // queueCreateInfoCount
556 queueInfo, // pQueueCreateInfos
557 (uint32_t) deviceLayerNames.count(), // layerCount
558 deviceLayerNames.begin(), // ppEnabledLayerNames
559 (uint32_t) deviceExtensionNames.count(), // extensionCount
560 deviceExtensionNames.begin(), // ppEnabledExtensionNames
561 &deviceFeatures // ppEnabledFeatures
562 };
563
564 err = grVkCreateDevice(physDev, &deviceInfo, nullptr, &device);
565 if (err) {
566 SkDebugf("CreateDevice failed: %d\n", err);
Greg Daniel37329b32018-07-02 20:16:44 +0000567 destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
Greg Danielf730c182018-07-02 20:15:37 +0000568 return false;
569 }
570
Greg Danielf730c182018-07-02 20:15:37 +0000571 VkQueue queue;
572 grVkGetDeviceQueue(device, graphicsQueueIndex, 0, &queue);
573
Greg Daniel98bffae2018-08-01 13:25:41 -0400574 extensions->init((uint32_t) instanceExtensionNames.count(),
575 instanceExtensionNames.begin(),
576 (uint32_t) deviceExtensionNames.count(),
577 deviceExtensionNames.begin());
578
Greg Danielf730c182018-07-02 20:15:37 +0000579 ctx->fInstance = inst;
580 ctx->fPhysicalDevice = physDev;
581 ctx->fDevice = device;
582 ctx->fQueue = queue;
583 ctx->fGraphicsQueueIndex = graphicsQueueIndex;
584 ctx->fMinAPIVersion = kGrVkMinimumVersion;
Greg Daniel98bffae2018-08-01 13:25:41 -0400585 ctx->fVkExtensions = extensions;
Greg Danielf730c182018-07-02 20:15:37 +0000586 ctx->fFeatures = featureFlags;
Greg Danielc8cd45a2018-07-12 10:02:37 -0400587 ctx->fGetProc = getProc;
Greg Danielf730c182018-07-02 20:15:37 +0000588 ctx->fOwnsInstanceAndDevice = false;
589
590 return true;
Greg Danielf730c182018-07-02 20:15:37 +0000591}
592
Greg Daniel35970ec2017-11-10 10:03:05 -0500593}
594
595#endif