blob: 2816f0a81667214f41438c3827a96197caa9214a [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 Daniel92aef4b2018-08-02 13:55:49 -040078
Greg Daniel37329b32018-07-02 20:16:44 +000079VKAPI_ATTR VkBool32 VKAPI_CALL DebugReportCallback(
80 VkDebugReportFlagsEXT flags,
81 VkDebugReportObjectTypeEXT objectType,
82 uint64_t object,
83 size_t location,
84 int32_t messageCode,
85 const char* pLayerPrefix,
86 const char* pMessage,
87 void* pUserData) {
88 if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
89 SkDebugf("Vulkan error [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
90 return VK_TRUE; // skip further layers
91 } else if (flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
92 SkDebugf("Vulkan warning [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
93 } else if (flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) {
94 SkDebugf("Vulkan perf warning [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
95 } else {
96 SkDebugf("Vulkan info/debug [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
97 }
98 return VK_FALSE;
99}
100#endif
101
Greg Daniel98bffae2018-08-01 13:25:41 -0400102#define GET_PROC_LOCAL(F, inst, device) PFN_vk ## F F = (PFN_vk ## F) getProc("vk" #F, inst, device)
103
104#ifdef SK_ENABLE_VK_LAYERS
105static uint32_t remove_patch_version(uint32_t specVersion) {
106 return (specVersion >> 12) << 12;
107}
108#endif
109
110static bool init_instance_extensions_and_layers(GrVkGetProc getProc,
111 uint32_t specVersion,
112 SkTArray<VkExtensionProperties>* instanceExtensions,
113 SkTArray<VkLayerProperties>* instanceLayers) {
114 if (getProc == nullptr) {
115 return false;
116 }
117
118 GET_PROC_LOCAL(EnumerateInstanceExtensionProperties, VK_NULL_HANDLE, VK_NULL_HANDLE);
119 GET_PROC_LOCAL(EnumerateInstanceLayerProperties, VK_NULL_HANDLE, VK_NULL_HANDLE);
120
121 if (!EnumerateInstanceExtensionProperties ||
122 !EnumerateInstanceLayerProperties) {
123 return false;
124 }
125
126 VkResult res;
127 uint32_t layerCount = 0;
128#ifdef SK_ENABLE_VK_LAYERS
129 // instance layers
130 res = EnumerateInstanceLayerProperties(&layerCount, nullptr);
131 if (VK_SUCCESS != res) {
132 return false;
133 }
134 VkLayerProperties* layers = new VkLayerProperties[layerCount];
135 res = EnumerateInstanceLayerProperties(&layerCount, layers);
136 if (VK_SUCCESS != res) {
137 delete[] layers;
138 return false;
139 }
140
141 uint32_t nonPatchVersion = remove_patch_version(specVersion);
142 for (uint32_t i = 0; i < layerCount; ++i) {
143 if (nonPatchVersion <= remove_patch_version(layers[i].specVersion) &&
144 should_include_debug_layer(layers[i])) {
145 instanceLayers->push_back() = layers[i];
146 }
147 }
148 delete[] layers;
149#endif
150
151 // instance extensions
152 // via Vulkan implementation and implicitly enabled layers
153 uint32_t extensionCount = 0;
154 res = EnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
155 if (VK_SUCCESS != res) {
156 return false;
157 }
158 VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
159 res = EnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions);
160 if (VK_SUCCESS != res) {
161 delete[] extensions;
162 return false;
163 }
164 for (uint32_t i = 0; i < extensionCount; ++i) {
165 instanceExtensions->push_back() = extensions[i];
166 }
167 delete [] extensions;
168
169 // via explicitly enabled layers
170 layerCount = instanceLayers->count();
171 for (uint32_t layerIndex = 0; layerIndex < layerCount; ++layerIndex) {
172 uint32_t extensionCount = 0;
173 res = EnumerateInstanceExtensionProperties((*instanceLayers)[layerIndex].layerName,
174 &extensionCount, nullptr);
175 if (VK_SUCCESS != res) {
176 return false;
177 }
178 VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
179 res = EnumerateInstanceExtensionProperties((*instanceLayers)[layerIndex].layerName,
180 &extensionCount, extensions);
181 if (VK_SUCCESS != res) {
182 delete[] extensions;
183 return false;
184 }
185 for (uint32_t i = 0; i < extensionCount; ++i) {
186 instanceExtensions->push_back() = extensions[i];
187 }
188 delete[] extensions;
189 }
190
191 return true;
192}
193
194static bool init_device_extensions_and_layers(GrVkGetProc getProc, uint32_t specVersion,
195 VkInstance inst, VkPhysicalDevice physDev,
196 SkTArray<VkExtensionProperties>* deviceExtensions,
197 SkTArray<VkLayerProperties>* deviceLayers) {
198 if (getProc == nullptr) {
199 return false;
200 }
201
202 GET_PROC_LOCAL(EnumerateDeviceExtensionProperties, inst, VK_NULL_HANDLE);
203 GET_PROC_LOCAL(EnumerateDeviceLayerProperties, inst, VK_NULL_HANDLE);
204
205 if (!EnumerateDeviceExtensionProperties ||
206 !EnumerateDeviceLayerProperties) {
207 return false;
208 }
209
210 VkResult res;
211 // device layers
212 uint32_t layerCount = 0;
213#ifdef SK_ENABLE_VK_LAYERS
214 res = EnumerateDeviceLayerProperties(physDev, &layerCount, nullptr);
215 if (VK_SUCCESS != res) {
216 return false;
217 }
218 VkLayerProperties* layers = new VkLayerProperties[layerCount];
219 res = EnumerateDeviceLayerProperties(physDev, &layerCount, layers);
220 if (VK_SUCCESS != res) {
221 delete[] layers;
222 return false;
223 }
224
225 uint32_t nonPatchVersion = remove_patch_version(specVersion);
226 for (uint32_t i = 0; i < layerCount; ++i) {
227 if (nonPatchVersion <= remove_patch_version(layers[i].specVersion) &&
228 should_include_debug_layer(layers[i])) {
229 deviceLayers->push_back() = layers[i];
230 }
231 }
232 delete[] layers;
233#endif
234
235 // device extensions
236 // via Vulkan implementation and implicitly enabled layers
237 uint32_t extensionCount = 0;
238 res = EnumerateDeviceExtensionProperties(physDev, nullptr, &extensionCount, nullptr);
239 if (VK_SUCCESS != res) {
240 return false;
241 }
242 VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
243 res = EnumerateDeviceExtensionProperties(physDev, nullptr, &extensionCount, extensions);
244 if (VK_SUCCESS != res) {
245 delete[] extensions;
246 return false;
247 }
248 for (uint32_t i = 0; i < extensionCount; ++i) {
249 deviceExtensions->push_back() = extensions[i];
250 }
251 delete[] extensions;
252
253 // via explicitly enabled layers
254 layerCount = deviceLayers->count();
255 for (uint32_t layerIndex = 0; layerIndex < layerCount; ++layerIndex) {
256 uint32_t extensionCount = 0;
257 res = EnumerateDeviceExtensionProperties(physDev,
258 (*deviceLayers)[layerIndex].layerName,
259 &extensionCount, nullptr);
260 if (VK_SUCCESS != res) {
261 return false;
262 }
263 VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
264 res = EnumerateDeviceExtensionProperties(physDev,
265 (*deviceLayers)[layerIndex].layerName,
266 &extensionCount, extensions);
267 if (VK_SUCCESS != res) {
268 delete[] extensions;
269 return false;
270 }
271 for (uint32_t i = 0; i < extensionCount; ++i) {
272 deviceExtensions->push_back() = extensions[i];
273 }
274 delete[] extensions;
275 }
276
277 return true;
278}
279
Greg Daniel92aef4b2018-08-02 13:55:49 -0400280#define ACQUIRE_VK_PROC_NOCHECK(name, instance, device) \
281 PFN_vk##name grVk##name = \
282 reinterpret_cast<PFN_vk##name>(getProc("vk" #name, instance, device));
283
Greg Daniel98bffae2018-08-01 13:25:41 -0400284
285#define ACQUIRE_VK_PROC(name, instance, device) \
286 PFN_vk##name grVk##name = \
287 reinterpret_cast<PFN_vk##name>(getProc("vk" #name, instance, device)); \
288 if (grVk##name == nullptr) { \
289 SkDebugf("Function ptr for vk%s could not be acquired\n", #name); \
290 if (device != VK_NULL_HANDLE) { \
291 destroy_instance(getProc, inst, debugCallback, hasDebugExtension); \
292 } \
293 return false; \
294 }
295
Greg Daniel37329b32018-07-02 20:16:44 +0000296#define ACQUIRE_VK_PROC_LOCAL(name, instance, device) \
297 PFN_vk##name grVk##name = \
298 reinterpret_cast<PFN_vk##name>(getProc("vk" #name, instance, device)); \
299 if (grVk##name == nullptr) { \
300 SkDebugf("Function ptr for vk%s could not be acquired\n", #name); \
301 return; \
302 }
303
Greg Danield3e65aa2018-08-01 09:19:45 -0400304static void destroy_instance(GrVkGetProc getProc, VkInstance inst,
Greg Daniel37329b32018-07-02 20:16:44 +0000305 VkDebugReportCallbackEXT* debugCallback,
306 bool hasDebugExtension) {
307 if (hasDebugExtension && *debugCallback != VK_NULL_HANDLE) {
308 ACQUIRE_VK_PROC_LOCAL(DestroyDebugReportCallbackEXT, inst, VK_NULL_HANDLE);
309 grVkDestroyDebugReportCallbackEXT(inst, *debugCallback, nullptr);
310 *debugCallback = VK_NULL_HANDLE;
311 }
312 ACQUIRE_VK_PROC_LOCAL(DestroyInstance, inst, VK_NULL_HANDLE);
313 grVkDestroyInstance(inst, nullptr);
314}
315
Greg Danield3e65aa2018-08-01 09:19:45 -0400316bool CreateVkBackendContext(GrVkGetProc getProc,
Greg Danielf730c182018-07-02 20:15:37 +0000317 GrVkBackendContext* ctx,
Greg Daniel98bffae2018-08-01 13:25:41 -0400318 GrVkExtensions* extensions,
Greg Daniel37329b32018-07-02 20:16:44 +0000319 VkDebugReportCallbackEXT* debugCallback,
Greg Danielf730c182018-07-02 20:15:37 +0000320 uint32_t* presentQueueIndexPtr,
321 CanPresentFn canPresent) {
Greg Daniel92aef4b2018-08-02 13:55:49 -0400322 VkResult err;
323
324 ACQUIRE_VK_PROC_NOCHECK(EnumerateInstanceVersion, VK_NULL_HANDLE, VK_NULL_HANDLE);
325 uint32_t instanceVersion = 0;
326 if (!grVkEnumerateInstanceVersion) {
327 instanceVersion = VK_MAKE_VERSION(1, 0, 0);
328 } else {
329 err = grVkEnumerateInstanceVersion(&instanceVersion);
330 if (err) {
331 SkDebugf("failed ot enumerate instance version. Err: %d\n", err);
332 return false;
333 }
334 }
335 SkASSERT(instanceVersion >= VK_MAKE_VERSION(1, 0, 0));
336
Greg Danielf730c182018-07-02 20:15:37 +0000337 VkPhysicalDevice physDev;
338 VkDevice device;
339 VkInstance inst;
Greg Danielf730c182018-07-02 20:15:37 +0000340
341 const VkApplicationInfo app_info = {
342 VK_STRUCTURE_TYPE_APPLICATION_INFO, // sType
343 nullptr, // pNext
344 "vktest", // pApplicationName
345 0, // applicationVersion
346 "vktest", // pEngineName
347 0, // engineVerison
Greg Daniel92aef4b2018-08-02 13:55:49 -0400348 instanceVersion, // apiVersion
Greg Danielf730c182018-07-02 20:15:37 +0000349 };
350
Greg Daniel98bffae2018-08-01 13:25:41 -0400351 SkTArray<VkLayerProperties> instanceLayers;
352 SkTArray<VkExtensionProperties> instanceExtensions;
353
Greg Daniel92aef4b2018-08-02 13:55:49 -0400354 if (!init_instance_extensions_and_layers(getProc, instanceVersion,
Greg Daniel98bffae2018-08-01 13:25:41 -0400355 &instanceExtensions,
356 &instanceLayers)) {
357 return false;
358 }
Greg Danielf730c182018-07-02 20:15:37 +0000359
360 SkTArray<const char*> instanceLayerNames;
361 SkTArray<const char*> instanceExtensionNames;
Greg Daniel98bffae2018-08-01 13:25:41 -0400362 for (int i = 0; i < instanceLayers.count(); ++i) {
363 instanceLayerNames.push_back(instanceLayers[i].layerName);
364 }
365 for (int i = 0; i < instanceExtensions.count(); ++i) {
366 if (strncmp(instanceExtensions[i].extensionName, "VK_KHX", 6)) {
367 instanceExtensionNames.push_back(instanceExtensions[i].extensionName);
Greg Danielf730c182018-07-02 20:15:37 +0000368 }
369 }
Greg Danielf730c182018-07-02 20:15:37 +0000370
371 const VkInstanceCreateInfo instance_create = {
372 VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // sType
373 nullptr, // pNext
374 0, // flags
375 &app_info, // pApplicationInfo
376 (uint32_t) instanceLayerNames.count(), // enabledLayerNameCount
377 instanceLayerNames.begin(), // ppEnabledLayerNames
378 (uint32_t) instanceExtensionNames.count(), // enabledExtensionNameCount
379 instanceExtensionNames.begin(), // ppEnabledExtensionNames
380 };
381
Greg Daniel98bffae2018-08-01 13:25:41 -0400382 bool hasDebugExtension = false;
383
Greg Danielf730c182018-07-02 20:15:37 +0000384 ACQUIRE_VK_PROC(CreateInstance, VK_NULL_HANDLE, VK_NULL_HANDLE);
385 err = grVkCreateInstance(&instance_create, nullptr, &inst);
386 if (err < 0) {
387 SkDebugf("vkCreateInstance failed: %d\n", err);
388 return false;
389 }
390
Greg Daniel37329b32018-07-02 20:16:44 +0000391#ifdef SK_ENABLE_VK_LAYERS
392 *debugCallback = VK_NULL_HANDLE;
393 for (int i = 0; i < instanceExtensionNames.count() && !hasDebugExtension; ++i) {
394 if (!strcmp(instanceExtensionNames[i], VK_EXT_DEBUG_REPORT_EXTENSION_NAME)) {
395 hasDebugExtension = true;
396 }
397 }
398 if (hasDebugExtension) {
399 // Setup callback creation information
400 VkDebugReportCallbackCreateInfoEXT callbackCreateInfo;
401 callbackCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
402 callbackCreateInfo.pNext = nullptr;
403 callbackCreateInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT |
404 VK_DEBUG_REPORT_WARNING_BIT_EXT |
405 // VK_DEBUG_REPORT_INFORMATION_BIT_EXT |
406 // VK_DEBUG_REPORT_DEBUG_BIT_EXT |
407 VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
408 callbackCreateInfo.pfnCallback = &DebugReportCallback;
409 callbackCreateInfo.pUserData = nullptr;
410
411 ACQUIRE_VK_PROC(CreateDebugReportCallbackEXT, inst, VK_NULL_HANDLE);
412 // Register the callback
413 grVkCreateDebugReportCallbackEXT(inst, &callbackCreateInfo, nullptr, debugCallback);
414 }
415#endif
416
Greg Danielf730c182018-07-02 20:15:37 +0000417 ACQUIRE_VK_PROC(EnumeratePhysicalDevices, inst, VK_NULL_HANDLE);
Greg Daniel92aef4b2018-08-02 13:55:49 -0400418 ACQUIRE_VK_PROC(GetPhysicalDeviceProperties, inst, VK_NULL_HANDLE);
Greg Danielf730c182018-07-02 20:15:37 +0000419 ACQUIRE_VK_PROC(GetPhysicalDeviceQueueFamilyProperties, inst, VK_NULL_HANDLE);
420 ACQUIRE_VK_PROC(GetPhysicalDeviceFeatures, inst, VK_NULL_HANDLE);
421 ACQUIRE_VK_PROC(CreateDevice, inst, VK_NULL_HANDLE);
422 ACQUIRE_VK_PROC(GetDeviceQueue, inst, VK_NULL_HANDLE);
423 ACQUIRE_VK_PROC(DeviceWaitIdle, inst, VK_NULL_HANDLE);
424 ACQUIRE_VK_PROC(DestroyDevice, inst, VK_NULL_HANDLE);
425
426 uint32_t gpuCount;
427 err = grVkEnumeratePhysicalDevices(inst, &gpuCount, nullptr);
428 if (err) {
429 SkDebugf("vkEnumeratePhysicalDevices failed: %d\n", err);
Greg Daniel37329b32018-07-02 20:16:44 +0000430 destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
Greg Danielf730c182018-07-02 20:15:37 +0000431 return false;
432 }
433 if (!gpuCount) {
434 SkDebugf("vkEnumeratePhysicalDevices returned no supported devices.\n");
Greg Daniel37329b32018-07-02 20:16:44 +0000435 destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
Greg Danielf730c182018-07-02 20:15:37 +0000436 return false;
437 }
438 // Just returning the first physical device instead of getting the whole array.
439 // TODO: find best match for our needs
440 gpuCount = 1;
441 err = grVkEnumeratePhysicalDevices(inst, &gpuCount, &physDev);
442 // VK_INCOMPLETE is returned when the count we provide is less than the total device count.
443 if (err && VK_INCOMPLETE != err) {
444 SkDebugf("vkEnumeratePhysicalDevices failed: %d\n", err);
Greg Daniel37329b32018-07-02 20:16:44 +0000445 destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
Greg Danielf730c182018-07-02 20:15:37 +0000446 return false;
447 }
448
Greg Daniel92aef4b2018-08-02 13:55:49 -0400449 VkPhysicalDeviceProperties physDeviceProperties;
450 grVkGetPhysicalDeviceProperties(physDev, &physDeviceProperties);
451 int physDeviceVersion = physDeviceProperties.apiVersion;
452
Greg Danielf730c182018-07-02 20:15:37 +0000453 // query to get the initial queue props size
454 uint32_t queueCount;
455 grVkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, nullptr);
456 if (!queueCount) {
457 SkDebugf("vkGetPhysicalDeviceQueueFamilyProperties returned no queues.\n");
Greg Daniel37329b32018-07-02 20:16:44 +0000458 destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
Greg Danielf730c182018-07-02 20:15:37 +0000459 return false;
460 }
461
462 SkAutoMalloc queuePropsAlloc(queueCount * sizeof(VkQueueFamilyProperties));
463 // now get the actual queue props
464 VkQueueFamilyProperties* queueProps = (VkQueueFamilyProperties*)queuePropsAlloc.get();
465
466 grVkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, queueProps);
467
468 // iterate to find the graphics queue
469 uint32_t graphicsQueueIndex = queueCount;
470 for (uint32_t i = 0; i < queueCount; i++) {
471 if (queueProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
472 graphicsQueueIndex = i;
473 break;
474 }
475 }
476 if (graphicsQueueIndex == queueCount) {
477 SkDebugf("Could not find any supported graphics queues.\n");
Greg Daniel37329b32018-07-02 20:16:44 +0000478 destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
Greg Danielf730c182018-07-02 20:15:37 +0000479 return false;
480 }
481
482 // iterate to find the present queue, if needed
483 uint32_t presentQueueIndex = queueCount;
484 if (presentQueueIndexPtr && canPresent) {
485 for (uint32_t i = 0; i < queueCount; i++) {
486 if (canPresent(inst, physDev, i)) {
487 presentQueueIndex = i;
488 break;
489 }
490 }
491 if (presentQueueIndex == queueCount) {
492 SkDebugf("Could not find any supported present queues.\n");
Greg Daniel37329b32018-07-02 20:16:44 +0000493 destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
Greg Danielf730c182018-07-02 20:15:37 +0000494 return false;
495 }
496 *presentQueueIndexPtr = presentQueueIndex;
497 } else {
498 // Just setting this so we end up make a single queue for graphics since there was no
499 // request for a present queue.
500 presentQueueIndex = graphicsQueueIndex;
501 }
502
Greg Daniel98bffae2018-08-01 13:25:41 -0400503 SkTArray<VkLayerProperties> deviceLayers;
504 SkTArray<VkExtensionProperties> deviceExtensions;
Greg Daniel92aef4b2018-08-02 13:55:49 -0400505 if (!init_device_extensions_and_layers(getProc, physDeviceVersion,
Greg Daniel98bffae2018-08-01 13:25:41 -0400506 inst, physDev,
507 &deviceExtensions,
508 &deviceLayers)) {
509 destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
510 return false;
511 }
Greg Danielf730c182018-07-02 20:15:37 +0000512
513 SkTArray<const char*> deviceLayerNames;
514 SkTArray<const char*> deviceExtensionNames;
Greg Daniel98bffae2018-08-01 13:25:41 -0400515 for (int i = 0; i < deviceLayers.count(); ++i) {
516 deviceLayerNames.push_back(deviceLayers[i].layerName);
Greg Danielf730c182018-07-02 20:15:37 +0000517 }
Greg Daniel98bffae2018-08-01 13:25:41 -0400518 for (int i = 0; i < deviceExtensions.count(); ++i) {
519 // Don't use experimental extensions since they typically don't work with debug layers and
520 // often are missing dependecy requirements for other extensions. Additionally, these are
521 // often left behind in the driver even after they've been promoted to real extensions.
522 if (strncmp(deviceExtensions[i].extensionName, "VK_KHX", 6) &&
523 strncmp(deviceExtensions[i].extensionName, "VK_NVX", 6)) {
524 deviceExtensionNames.push_back(deviceExtensions[i].extensionName);
525 }
Greg Danielf730c182018-07-02 20:15:37 +0000526 }
527
528 // query to get the physical device properties
529 VkPhysicalDeviceFeatures deviceFeatures;
530 grVkGetPhysicalDeviceFeatures(physDev, &deviceFeatures);
531 // this looks like it would slow things down,
532 // and we can't depend on it on all platforms
533 deviceFeatures.robustBufferAccess = VK_FALSE;
534
Greg Danielf730c182018-07-02 20:15:37 +0000535 float queuePriorities[1] = { 0.0 };
536 // Here we assume no need for swapchain queue
537 // If one is needed, the client will need its own setup code
538 const VkDeviceQueueCreateInfo queueInfo[2] = {
539 {
540 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
541 nullptr, // pNext
542 0, // VkDeviceQueueCreateFlags
543 graphicsQueueIndex, // queueFamilyIndex
544 1, // queueCount
545 queuePriorities, // pQueuePriorities
546 },
547 {
548 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
549 nullptr, // pNext
550 0, // VkDeviceQueueCreateFlags
551 presentQueueIndex, // queueFamilyIndex
552 1, // queueCount
553 queuePriorities, // pQueuePriorities
554 }
555 };
556 uint32_t queueInfoCount = (presentQueueIndex != graphicsQueueIndex) ? 2 : 1;
557
558 const VkDeviceCreateInfo deviceInfo = {
559 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // sType
560 nullptr, // pNext
561 0, // VkDeviceCreateFlags
562 queueInfoCount, // queueCreateInfoCount
563 queueInfo, // pQueueCreateInfos
564 (uint32_t) deviceLayerNames.count(), // layerCount
565 deviceLayerNames.begin(), // ppEnabledLayerNames
566 (uint32_t) deviceExtensionNames.count(), // extensionCount
567 deviceExtensionNames.begin(), // ppEnabledExtensionNames
568 &deviceFeatures // ppEnabledFeatures
569 };
570
571 err = grVkCreateDevice(physDev, &deviceInfo, nullptr, &device);
572 if (err) {
573 SkDebugf("CreateDevice failed: %d\n", err);
Greg Daniel37329b32018-07-02 20:16:44 +0000574 destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
Greg Danielf730c182018-07-02 20:15:37 +0000575 return false;
576 }
577
Greg Danielf730c182018-07-02 20:15:37 +0000578 VkQueue queue;
579 grVkGetDeviceQueue(device, graphicsQueueIndex, 0, &queue);
580
Greg Daniela31f4e52018-08-01 16:48:52 -0400581 extensions->init(getProc, inst, physDev,
582 (uint32_t) instanceExtensionNames.count(),
Greg Daniel98bffae2018-08-01 13:25:41 -0400583 instanceExtensionNames.begin(),
584 (uint32_t) deviceExtensionNames.count(),
585 deviceExtensionNames.begin());
586
Greg Danielf730c182018-07-02 20:15:37 +0000587 ctx->fInstance = inst;
588 ctx->fPhysicalDevice = physDev;
589 ctx->fDevice = device;
590 ctx->fQueue = queue;
591 ctx->fGraphicsQueueIndex = graphicsQueueIndex;
Greg Daniel92aef4b2018-08-02 13:55:49 -0400592 ctx->fInstanceVersion = instanceVersion;
Greg Daniel98bffae2018-08-01 13:25:41 -0400593 ctx->fVkExtensions = extensions;
Greg Daniel36443602018-08-02 12:51:52 -0400594 ctx->fDeviceFeatures = deviceFeatures;
Greg Danielc8cd45a2018-07-12 10:02:37 -0400595 ctx->fGetProc = getProc;
Greg Danielf730c182018-07-02 20:15:37 +0000596 ctx->fOwnsInstanceAndDevice = false;
597
598 return true;
Greg Danielf730c182018-07-02 20:15:37 +0000599}
600
Greg Daniel35970ec2017-11-10 10:03:05 -0500601}
602
603#endif