• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 "tools/gpu/vk/VkTestUtils.h"
9 
10 #ifdef SK_VULKAN
11 
12 #ifndef SK_GPU_TOOLS_VK_LIBRARY_NAME
13     #if defined _WIN32
14         #define SK_GPU_TOOLS_VK_LIBRARY_NAME "vulkan-1.dll"
15     #else
16         #define SK_GPU_TOOLS_VK_LIBRARY_NAME "libvulkan.so"
17     #endif
18 #endif
19 
20 #if defined(SK_BUILD_FOR_UNIX)
21 #include <execinfo.h>
22 #endif
23 #include "include/gpu/vk/GrVkBackendContext.h"
24 #include "include/gpu/vk/GrVkExtensions.h"
25 #include "src/core/SkAutoMalloc.h"
26 #include "src/ports/SkOSLibrary.h"
27 
28 #if defined(SK_ENABLE_SCOPED_LSAN_SUPPRESSIONS)
29 #include <sanitizer/lsan_interface.h>
30 #endif
31 
32 namespace sk_gpu_test {
33 
LoadVkLibraryAndGetProcAddrFuncs(PFN_vkGetInstanceProcAddr * instProc,PFN_vkGetDeviceProcAddr * devProc)34 bool LoadVkLibraryAndGetProcAddrFuncs(PFN_vkGetInstanceProcAddr* instProc,
35                                       PFN_vkGetDeviceProcAddr* devProc) {
36 #ifdef SK_MOLTENVK
37     // MoltenVK is a statically linked framework, so there is no Vulkan library to load.
38     *instProc = &vkGetInstanceProcAddr;
39     *devProc = &vkGetDeviceProcAddr;
40     return true;
41 #else
42     static void* vkLib = nullptr;
43     static PFN_vkGetInstanceProcAddr localInstProc = nullptr;
44     static PFN_vkGetDeviceProcAddr localDevProc = nullptr;
45     if (!vkLib) {
46         vkLib = DynamicLoadLibrary(SK_GPU_TOOLS_VK_LIBRARY_NAME);
47         if (!vkLib) {
48             return false;
49         }
50         localInstProc = (PFN_vkGetInstanceProcAddr) GetProcedureAddress(vkLib,
51                                                                         "vkGetInstanceProcAddr");
52         localDevProc = (PFN_vkGetDeviceProcAddr) GetProcedureAddress(vkLib,
53                                                                      "vkGetDeviceProcAddr");
54     }
55     if (!localInstProc || !localDevProc) {
56         return false;
57     }
58     *instProc = localInstProc;
59     *devProc = localDevProc;
60     return true;
61 #endif
62 }
63 
64 ////////////////////////////////////////////////////////////////////////////////
65 // Helper code to set up Vulkan context objects
66 
67 #ifdef SK_ENABLE_VK_LAYERS
68 const char* kDebugLayerNames[] = {
69     // single merged layer
70     "VK_LAYER_KHRONOS_validation",
71     // not included in standard_validation
72     //"VK_LAYER_LUNARG_api_dump",
73     //"VK_LAYER_LUNARG_vktrace",
74     //"VK_LAYER_LUNARG_screenshot",
75 };
76 
remove_patch_version(uint32_t specVersion)77 static uint32_t remove_patch_version(uint32_t specVersion) {
78     return (specVersion >> 12) << 12;
79 }
80 
81 // Returns the index into layers array for the layer we want. Returns -1 if not supported.
should_include_debug_layer(const char * layerName,uint32_t layerCount,VkLayerProperties * layers,uint32_t version)82 static int should_include_debug_layer(const char* layerName,
83                                        uint32_t layerCount, VkLayerProperties* layers,
84                                        uint32_t version) {
85     for (uint32_t i = 0; i < layerCount; ++i) {
86         if (!strcmp(layerName, layers[i].layerName)) {
87             // Since the layers intercept the vulkan calls and forward them on, we need to make sure
88             // layer was written against a version that isn't older than the version of Vulkan we're
89             // using so that it has all the api entry points.
90             if (version <= remove_patch_version(layers[i].specVersion)) {
91                 return i;
92             }
93             return -1;
94         }
95 
96     }
97     return -1;
98 }
99 
print_backtrace()100 static void print_backtrace() {
101 #if defined(SK_BUILD_FOR_UNIX)
102     void* stack[64];
103     int count = backtrace(stack, SK_ARRAY_COUNT(stack));
104     backtrace_symbols_fd(stack, count, 2);
105 #else
106     // Please add implementations for other platforms.
107 #endif
108 }
109 
DebugReportCallback(VkDebugReportFlagsEXT flags,VkDebugReportObjectTypeEXT objectType,uint64_t object,size_t location,int32_t messageCode,const char * pLayerPrefix,const char * pMessage,void * pUserData)110 VKAPI_ATTR VkBool32 VKAPI_CALL DebugReportCallback(
111     VkDebugReportFlagsEXT       flags,
112     VkDebugReportObjectTypeEXT  objectType,
113     uint64_t                    object,
114     size_t                      location,
115     int32_t                     messageCode,
116     const char*                 pLayerPrefix,
117     const char*                 pMessage,
118     void*                       pUserData) {
119     if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
120         SkDebugf("Vulkan error [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
121         print_backtrace();
122         SkDEBUGFAIL("Vulkan debug layer error");
123         return VK_TRUE; // skip further layers
124     } else if (flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
125         SkDebugf("Vulkan warning [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
126         print_backtrace();
127     } else if (flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) {
128         SkDebugf("Vulkan perf warning [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
129         print_backtrace();
130     } else {
131         SkDebugf("Vulkan info/debug [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
132     }
133     return VK_FALSE;
134 }
135 #endif
136 
137 #define GET_PROC_LOCAL(F, inst, device) PFN_vk ## F F = (PFN_vk ## F) getProc("vk" #F, inst, device)
138 
init_instance_extensions_and_layers(GrVkGetProc getProc,uint32_t specVersion,SkTArray<VkExtensionProperties> * instanceExtensions,SkTArray<VkLayerProperties> * instanceLayers)139 static bool init_instance_extensions_and_layers(GrVkGetProc getProc,
140                                                 uint32_t specVersion,
141                                                 SkTArray<VkExtensionProperties>* instanceExtensions,
142                                                 SkTArray<VkLayerProperties>* instanceLayers) {
143     if (getProc == nullptr) {
144         return false;
145     }
146 
147     GET_PROC_LOCAL(EnumerateInstanceExtensionProperties, VK_NULL_HANDLE, VK_NULL_HANDLE);
148     GET_PROC_LOCAL(EnumerateInstanceLayerProperties, VK_NULL_HANDLE, VK_NULL_HANDLE);
149 
150     if (!EnumerateInstanceExtensionProperties ||
151         !EnumerateInstanceLayerProperties) {
152         return false;
153     }
154 
155     VkResult res;
156     uint32_t layerCount = 0;
157 #ifdef SK_ENABLE_VK_LAYERS
158     // instance layers
159     res = EnumerateInstanceLayerProperties(&layerCount, nullptr);
160     if (VK_SUCCESS != res) {
161         return false;
162     }
163     VkLayerProperties* layers = new VkLayerProperties[layerCount];
164     res = EnumerateInstanceLayerProperties(&layerCount, layers);
165     if (VK_SUCCESS != res) {
166         delete[] layers;
167         return false;
168     }
169 
170     uint32_t nonPatchVersion = remove_patch_version(specVersion);
171     for (size_t i = 0; i < SK_ARRAY_COUNT(kDebugLayerNames); ++i) {
172         int idx = should_include_debug_layer(kDebugLayerNames[i], layerCount, layers,
173                                              nonPatchVersion);
174         if (idx != -1) {
175             instanceLayers->push_back() = layers[idx];
176         }
177     }
178     delete[] layers;
179 #endif
180 
181     // instance extensions
182     // via Vulkan implementation and implicitly enabled layers
183     uint32_t extensionCount = 0;
184     res = EnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
185     if (VK_SUCCESS != res) {
186         return false;
187     }
188     VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
189     res = EnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions);
190     if (VK_SUCCESS != res) {
191         delete[] extensions;
192         return false;
193     }
194     for (uint32_t i = 0; i < extensionCount; ++i) {
195         instanceExtensions->push_back() = extensions[i];
196     }
197     delete [] extensions;
198 
199     // via explicitly enabled layers
200     layerCount = instanceLayers->count();
201     for (uint32_t layerIndex = 0; layerIndex < layerCount; ++layerIndex) {
202         uint32_t extensionCount = 0;
203         res = EnumerateInstanceExtensionProperties((*instanceLayers)[layerIndex].layerName,
204                                                    &extensionCount, nullptr);
205         if (VK_SUCCESS != res) {
206             return false;
207         }
208         VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
209         res = EnumerateInstanceExtensionProperties((*instanceLayers)[layerIndex].layerName,
210                                                    &extensionCount, extensions);
211         if (VK_SUCCESS != res) {
212             delete[] extensions;
213             return false;
214         }
215         for (uint32_t i = 0; i < extensionCount; ++i) {
216             instanceExtensions->push_back() = extensions[i];
217         }
218         delete[] extensions;
219     }
220 
221     return true;
222 }
223 
init_device_extensions_and_layers(GrVkGetProc getProc,uint32_t specVersion,VkInstance inst,VkPhysicalDevice physDev,SkTArray<VkExtensionProperties> * deviceExtensions,SkTArray<VkLayerProperties> * deviceLayers)224 static bool init_device_extensions_and_layers(GrVkGetProc getProc, uint32_t specVersion,
225                                               VkInstance inst, VkPhysicalDevice physDev,
226                                               SkTArray<VkExtensionProperties>* deviceExtensions,
227                                               SkTArray<VkLayerProperties>* deviceLayers) {
228     if (getProc == nullptr) {
229         return false;
230     }
231 
232     GET_PROC_LOCAL(EnumerateDeviceExtensionProperties, inst, VK_NULL_HANDLE);
233     GET_PROC_LOCAL(EnumerateDeviceLayerProperties, inst, VK_NULL_HANDLE);
234 
235     if (!EnumerateDeviceExtensionProperties ||
236         !EnumerateDeviceLayerProperties) {
237         return false;
238     }
239 
240     VkResult res;
241     // device layers
242     uint32_t layerCount = 0;
243 #ifdef SK_ENABLE_VK_LAYERS
244     res = EnumerateDeviceLayerProperties(physDev, &layerCount, nullptr);
245     if (VK_SUCCESS != res) {
246         return false;
247     }
248     VkLayerProperties* layers = new VkLayerProperties[layerCount];
249     res = EnumerateDeviceLayerProperties(physDev, &layerCount, layers);
250     if (VK_SUCCESS != res) {
251         delete[] layers;
252         return false;
253     }
254 
255     uint32_t nonPatchVersion = remove_patch_version(specVersion);
256     for (size_t i = 0; i < SK_ARRAY_COUNT(kDebugLayerNames); ++i) {
257         int idx = should_include_debug_layer(kDebugLayerNames[i], layerCount, layers,
258                                              nonPatchVersion);
259         if (idx != -1) {
260             deviceLayers->push_back() = layers[idx];
261         }
262     }
263     delete[] layers;
264 #endif
265 
266     // device extensions
267     // via Vulkan implementation and implicitly enabled layers
268     uint32_t extensionCount = 0;
269     res = EnumerateDeviceExtensionProperties(physDev, nullptr, &extensionCount, nullptr);
270     if (VK_SUCCESS != res) {
271         return false;
272     }
273     VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
274     res = EnumerateDeviceExtensionProperties(physDev, nullptr, &extensionCount, extensions);
275     if (VK_SUCCESS != res) {
276         delete[] extensions;
277         return false;
278     }
279     for (uint32_t i = 0; i < extensionCount; ++i) {
280         deviceExtensions->push_back() = extensions[i];
281     }
282     delete[] extensions;
283 
284     // via explicitly enabled layers
285     layerCount = deviceLayers->count();
286     for (uint32_t layerIndex = 0; layerIndex < layerCount; ++layerIndex) {
287         uint32_t extensionCount = 0;
288         res = EnumerateDeviceExtensionProperties(physDev,
289             (*deviceLayers)[layerIndex].layerName,
290             &extensionCount, nullptr);
291         if (VK_SUCCESS != res) {
292             return false;
293         }
294         VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
295         res = EnumerateDeviceExtensionProperties(physDev,
296             (*deviceLayers)[layerIndex].layerName,
297             &extensionCount, extensions);
298         if (VK_SUCCESS != res) {
299             delete[] extensions;
300             return false;
301         }
302         for (uint32_t i = 0; i < extensionCount; ++i) {
303             deviceExtensions->push_back() = extensions[i];
304         }
305         delete[] extensions;
306     }
307 
308     return true;
309 }
310 
311 #define ACQUIRE_VK_PROC_NOCHECK(name, instance, device) \
312     PFN_vk##name grVk##name = reinterpret_cast<PFN_vk##name>(getProc("vk" #name, instance, device))
313 
314 #define ACQUIRE_VK_PROC(name, instance, device)                                    \
315     PFN_vk##name grVk##name =                                                      \
316             reinterpret_cast<PFN_vk##name>(getProc("vk" #name, instance, device)); \
317     do {                                                                           \
318         if (grVk##name == nullptr) {                                               \
319             SkDebugf("Function ptr for vk%s could not be acquired\n", #name);      \
320             if (device != VK_NULL_HANDLE) {                                        \
321                 destroy_instance(getProc, inst, debugCallback, hasDebugExtension); \
322             }                                                                      \
323             return false;                                                          \
324         }                                                                          \
325     } while (0)
326 
327 #define ACQUIRE_VK_PROC_LOCAL(name, instance, device)                              \
328     PFN_vk##name grVk##name =                                                      \
329             reinterpret_cast<PFN_vk##name>(getProc("vk" #name, instance, device)); \
330     do {                                                                           \
331         if (grVk##name == nullptr) {                                               \
332             SkDebugf("Function ptr for vk%s could not be acquired\n", #name);      \
333             return false;                                                                \
334         }                                                                          \
335     } while (0)
336 
destroy_instance(GrVkGetProc getProc,VkInstance inst,VkDebugReportCallbackEXT * debugCallback,bool hasDebugExtension)337 static bool destroy_instance(GrVkGetProc getProc, VkInstance inst,
338                              VkDebugReportCallbackEXT* debugCallback,
339                              bool hasDebugExtension) {
340     if (hasDebugExtension && *debugCallback != VK_NULL_HANDLE) {
341         ACQUIRE_VK_PROC_LOCAL(DestroyDebugReportCallbackEXT, inst, VK_NULL_HANDLE);
342         grVkDestroyDebugReportCallbackEXT(inst, *debugCallback, nullptr);
343         *debugCallback = VK_NULL_HANDLE;
344     }
345     ACQUIRE_VK_PROC_LOCAL(DestroyInstance, inst, VK_NULL_HANDLE);
346     grVkDestroyInstance(inst, nullptr);
347     return true;
348 }
349 
setup_features(GrVkGetProc getProc,VkInstance inst,VkPhysicalDevice physDev,uint32_t physDeviceVersion,GrVkExtensions * extensions,VkPhysicalDeviceFeatures2 * features,bool isProtected)350 static bool setup_features(GrVkGetProc getProc, VkInstance inst, VkPhysicalDevice physDev,
351                            uint32_t physDeviceVersion, GrVkExtensions* extensions,
352                            VkPhysicalDeviceFeatures2* features, bool isProtected) {
353     SkASSERT(physDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
354              extensions->hasExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 1));
355 
356     // Setup all extension feature structs we may want to use.
357     void** tailPNext = &features->pNext;
358 
359     // If |isProtected| is given, attach that first
360     VkPhysicalDeviceProtectedMemoryFeatures* protectedMemoryFeatures = nullptr;
361     if (isProtected) {
362         SkASSERT(physDeviceVersion >= VK_MAKE_VERSION(1, 1, 0));
363         protectedMemoryFeatures =
364           (VkPhysicalDeviceProtectedMemoryFeatures*)sk_malloc_throw(
365               sizeof(VkPhysicalDeviceProtectedMemoryFeatures));
366         protectedMemoryFeatures->sType =
367           VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES;
368         protectedMemoryFeatures->pNext = nullptr;
369         *tailPNext = protectedMemoryFeatures;
370         tailPNext = &protectedMemoryFeatures->pNext;
371     }
372 
373     VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT* blend = nullptr;
374     if (extensions->hasExtension(VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME, 2)) {
375         blend = (VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT*) sk_malloc_throw(
376                 sizeof(VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT));
377         blend->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT;
378         blend->pNext = nullptr;
379         *tailPNext = blend;
380         tailPNext = &blend->pNext;
381     }
382 
383     VkPhysicalDeviceSamplerYcbcrConversionFeatures* ycbcrFeature = nullptr;
384     if (physDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
385         extensions->hasExtension(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME, 1)) {
386         ycbcrFeature = (VkPhysicalDeviceSamplerYcbcrConversionFeatures*) sk_malloc_throw(
387                 sizeof(VkPhysicalDeviceSamplerYcbcrConversionFeatures));
388         ycbcrFeature->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES;
389         ycbcrFeature->pNext = nullptr;
390         ycbcrFeature->samplerYcbcrConversion = VK_TRUE;
391         *tailPNext = ycbcrFeature;
392         tailPNext = &ycbcrFeature->pNext;
393     }
394 
395     if (physDeviceVersion >= VK_MAKE_VERSION(1, 1, 0)) {
396         ACQUIRE_VK_PROC_LOCAL(GetPhysicalDeviceFeatures2, inst, VK_NULL_HANDLE);
397         grVkGetPhysicalDeviceFeatures2(physDev, features);
398     } else {
399         SkASSERT(extensions->hasExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
400                                           1));
401         ACQUIRE_VK_PROC_LOCAL(GetPhysicalDeviceFeatures2KHR, inst, VK_NULL_HANDLE);
402         grVkGetPhysicalDeviceFeatures2KHR(physDev, features);
403     }
404 
405     if (isProtected) {
406         if (!protectedMemoryFeatures->protectedMemory) {
407             return false;
408         }
409     }
410     return true;
411     // If we want to disable any extension features do so here.
412 }
413 
CreateVkBackendContext(GrVkGetProc getProc,GrVkBackendContext * ctx,GrVkExtensions * extensions,VkPhysicalDeviceFeatures2 * features,VkDebugReportCallbackEXT * debugCallback,uint32_t * presentQueueIndexPtr,CanPresentFn canPresent,bool isProtected)414 bool CreateVkBackendContext(GrVkGetProc getProc,
415                             GrVkBackendContext* ctx,
416                             GrVkExtensions* extensions,
417                             VkPhysicalDeviceFeatures2* features,
418                             VkDebugReportCallbackEXT* debugCallback,
419                             uint32_t* presentQueueIndexPtr,
420                             CanPresentFn canPresent,
421                             bool isProtected) {
422     VkResult err;
423 
424     ACQUIRE_VK_PROC_NOCHECK(EnumerateInstanceVersion, VK_NULL_HANDLE, VK_NULL_HANDLE);
425     uint32_t instanceVersion = 0;
426     if (!grVkEnumerateInstanceVersion) {
427         instanceVersion = VK_MAKE_VERSION(1, 0, 0);
428     } else {
429         err = grVkEnumerateInstanceVersion(&instanceVersion);
430         if (err) {
431             SkDebugf("failed to enumerate instance version. Err: %d\n", err);
432             return false;
433         }
434     }
435     SkASSERT(instanceVersion >= VK_MAKE_VERSION(1, 0, 0));
436     if (isProtected && instanceVersion < VK_MAKE_VERSION(1, 1, 0)) {
437         SkDebugf("protected requires vk instance version 1.1\n");
438         return false;
439     }
440 
441     uint32_t apiVersion = VK_MAKE_VERSION(1, 0, 0);
442     if (instanceVersion >= VK_MAKE_VERSION(1, 1, 0)) {
443         // If the instance version is 1.0 we must have the apiVersion also be 1.0. However, if the
444         // instance version is 1.1 or higher, we can set the apiVersion to be whatever the highest
445         // api we may use in skia (technically it can be arbitrary). So for now we set it to 1.1
446         // since that is the highest vulkan version.
447         apiVersion = VK_MAKE_VERSION(1, 1, 0);
448     }
449 
450     instanceVersion = std::min(instanceVersion, apiVersion);
451 
452     VkPhysicalDevice physDev;
453     VkDevice device;
454     VkInstance inst;
455 
456     const VkApplicationInfo app_info = {
457         VK_STRUCTURE_TYPE_APPLICATION_INFO, // sType
458         nullptr,                            // pNext
459         "vktest",                           // pApplicationName
460         0,                                  // applicationVersion
461         "vktest",                           // pEngineName
462         0,                                  // engineVerison
463         apiVersion,                         // apiVersion
464     };
465 
466     SkTArray<VkLayerProperties> instanceLayers;
467     SkTArray<VkExtensionProperties> instanceExtensions;
468 
469     if (!init_instance_extensions_and_layers(getProc, instanceVersion,
470                                              &instanceExtensions,
471                                              &instanceLayers)) {
472         return false;
473     }
474 
475     SkTArray<const char*> instanceLayerNames;
476     SkTArray<const char*> instanceExtensionNames;
477     for (int i = 0; i < instanceLayers.count(); ++i) {
478         instanceLayerNames.push_back(instanceLayers[i].layerName);
479     }
480     for (int i = 0; i < instanceExtensions.count(); ++i) {
481         if (strncmp(instanceExtensions[i].extensionName, "VK_KHX", 6)) {
482             instanceExtensionNames.push_back(instanceExtensions[i].extensionName);
483         }
484     }
485 
486     const VkInstanceCreateInfo instance_create = {
487         VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,    // sType
488         nullptr,                                   // pNext
489         0,                                         // flags
490         &app_info,                                 // pApplicationInfo
491         (uint32_t) instanceLayerNames.count(),     // enabledLayerNameCount
492         instanceLayerNames.begin(),                // ppEnabledLayerNames
493         (uint32_t) instanceExtensionNames.count(), // enabledExtensionNameCount
494         instanceExtensionNames.begin(),            // ppEnabledExtensionNames
495     };
496 
497     bool hasDebugExtension = false;
498 
499     ACQUIRE_VK_PROC(CreateInstance, VK_NULL_HANDLE, VK_NULL_HANDLE);
500     err = grVkCreateInstance(&instance_create, nullptr, &inst);
501     if (err < 0) {
502         SkDebugf("vkCreateInstance failed: %d\n", err);
503         return false;
504     }
505 
506 #ifdef SK_ENABLE_VK_LAYERS
507     *debugCallback = VK_NULL_HANDLE;
508     for (int i = 0; i < instanceExtensionNames.count() && !hasDebugExtension; ++i) {
509         if (!strcmp(instanceExtensionNames[i], VK_EXT_DEBUG_REPORT_EXTENSION_NAME)) {
510             hasDebugExtension = true;
511         }
512     }
513     if (hasDebugExtension) {
514         // Setup callback creation information
515         VkDebugReportCallbackCreateInfoEXT callbackCreateInfo;
516         callbackCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
517         callbackCreateInfo.pNext = nullptr;
518         callbackCreateInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT |
519                                    VK_DEBUG_REPORT_WARNING_BIT_EXT |
520                                    // VK_DEBUG_REPORT_INFORMATION_BIT_EXT |
521                                    // VK_DEBUG_REPORT_DEBUG_BIT_EXT |
522                                    VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
523         callbackCreateInfo.pfnCallback = &DebugReportCallback;
524         callbackCreateInfo.pUserData = nullptr;
525 
526         ACQUIRE_VK_PROC(CreateDebugReportCallbackEXT, inst, VK_NULL_HANDLE);
527         // Register the callback
528         grVkCreateDebugReportCallbackEXT(inst, &callbackCreateInfo, nullptr, debugCallback);
529     }
530 #endif
531 
532     ACQUIRE_VK_PROC(EnumeratePhysicalDevices, inst, VK_NULL_HANDLE);
533     ACQUIRE_VK_PROC(GetPhysicalDeviceProperties, inst, VK_NULL_HANDLE);
534     ACQUIRE_VK_PROC(GetPhysicalDeviceQueueFamilyProperties, inst, VK_NULL_HANDLE);
535     ACQUIRE_VK_PROC(GetPhysicalDeviceFeatures, inst, VK_NULL_HANDLE);
536     ACQUIRE_VK_PROC(CreateDevice, inst, VK_NULL_HANDLE);
537     ACQUIRE_VK_PROC(GetDeviceQueue, inst, VK_NULL_HANDLE);
538     ACQUIRE_VK_PROC(DeviceWaitIdle, inst, VK_NULL_HANDLE);
539     ACQUIRE_VK_PROC(DestroyDevice, inst, VK_NULL_HANDLE);
540 
541     uint32_t gpuCount;
542     err = grVkEnumeratePhysicalDevices(inst, &gpuCount, nullptr);
543     if (err) {
544         SkDebugf("vkEnumeratePhysicalDevices failed: %d\n", err);
545         destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
546         return false;
547     }
548     if (!gpuCount) {
549         SkDebugf("vkEnumeratePhysicalDevices returned no supported devices.\n");
550         destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
551         return false;
552     }
553     // Just returning the first physical device instead of getting the whole array.
554     // TODO: find best match for our needs
555     gpuCount = 1;
556     err = grVkEnumeratePhysicalDevices(inst, &gpuCount, &physDev);
557     // VK_INCOMPLETE is returned when the count we provide is less than the total device count.
558     if (err && VK_INCOMPLETE != err) {
559         SkDebugf("vkEnumeratePhysicalDevices failed: %d\n", err);
560         destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
561         return false;
562     }
563 
564     VkPhysicalDeviceProperties physDeviceProperties;
565     grVkGetPhysicalDeviceProperties(physDev, &physDeviceProperties);
566     int physDeviceVersion = std::min(physDeviceProperties.apiVersion, apiVersion);
567 
568     if (isProtected && physDeviceVersion < VK_MAKE_VERSION(1, 1, 0)) {
569         SkDebugf("protected requires vk physical device version 1.1\n");
570         destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
571         return false;
572     }
573 
574     // query to get the initial queue props size
575     uint32_t queueCount;
576     grVkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, nullptr);
577     if (!queueCount) {
578         SkDebugf("vkGetPhysicalDeviceQueueFamilyProperties returned no queues.\n");
579         destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
580         return false;
581     }
582 
583     SkAutoMalloc queuePropsAlloc(queueCount * sizeof(VkQueueFamilyProperties));
584     // now get the actual queue props
585     VkQueueFamilyProperties* queueProps = (VkQueueFamilyProperties*)queuePropsAlloc.get();
586 
587     grVkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, queueProps);
588 
589     // iterate to find the graphics queue
590     uint32_t graphicsQueueIndex = queueCount;
591     for (uint32_t i = 0; i < queueCount; i++) {
592         if (queueProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
593             graphicsQueueIndex = i;
594             break;
595         }
596     }
597     if (graphicsQueueIndex == queueCount) {
598         SkDebugf("Could not find any supported graphics queues.\n");
599         destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
600         return false;
601     }
602 
603     // iterate to find the present queue, if needed
604     uint32_t presentQueueIndex = queueCount;
605     if (presentQueueIndexPtr && canPresent) {
606         for (uint32_t i = 0; i < queueCount; i++) {
607             if (canPresent(inst, physDev, i)) {
608                 presentQueueIndex = i;
609                 break;
610             }
611         }
612         if (presentQueueIndex == queueCount) {
613             SkDebugf("Could not find any supported present queues.\n");
614             destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
615             return false;
616         }
617         *presentQueueIndexPtr = presentQueueIndex;
618     } else {
619         // Just setting this so we end up make a single queue for graphics since there was no
620         // request for a present queue.
621         presentQueueIndex = graphicsQueueIndex;
622     }
623 
624     SkTArray<VkLayerProperties> deviceLayers;
625     SkTArray<VkExtensionProperties> deviceExtensions;
626     if (!init_device_extensions_and_layers(getProc, physDeviceVersion,
627                                            inst, physDev,
628                                            &deviceExtensions,
629                                            &deviceLayers)) {
630         destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
631         return false;
632     }
633 
634     SkTArray<const char*> deviceLayerNames;
635     SkTArray<const char*> deviceExtensionNames;
636     for (int i = 0; i < deviceLayers.count(); ++i) {
637         deviceLayerNames.push_back(deviceLayers[i].layerName);
638     }
639     for (int i = 0; i < deviceExtensions.count(); ++i) {
640         // Don't use experimental extensions since they typically don't work with debug layers and
641         // often are missing dependecy requirements for other extensions. Additionally, these are
642         // often left behind in the driver even after they've been promoted to real extensions.
643         if (strncmp(deviceExtensions[i].extensionName, "VK_KHX", 6) &&
644             strncmp(deviceExtensions[i].extensionName, "VK_NVX", 6)) {
645             deviceExtensionNames.push_back(deviceExtensions[i].extensionName);
646         }
647     }
648 
649     extensions->init(getProc, inst, physDev,
650                      (uint32_t) instanceExtensionNames.count(),
651                      instanceExtensionNames.begin(),
652                      (uint32_t) deviceExtensionNames.count(),
653                      deviceExtensionNames.begin());
654 
655     memset(features, 0, sizeof(VkPhysicalDeviceFeatures2));
656     features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
657     features->pNext = nullptr;
658 
659     VkPhysicalDeviceFeatures* deviceFeatures = &features->features;
660     void* pointerToFeatures = nullptr;
661     if (physDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
662         extensions->hasExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 1)) {
663         if (!setup_features(getProc, inst, physDev, physDeviceVersion, extensions, features,
664                           isProtected)) {
665             destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
666             return false;
667         }
668 
669         // If we set the pNext of the VkDeviceCreateInfo to our VkPhysicalDeviceFeatures2 struct,
670         // the device creation will use that instead of the ppEnabledFeatures.
671         pointerToFeatures = features;
672     } else {
673         grVkGetPhysicalDeviceFeatures(physDev, deviceFeatures);
674     }
675 
676     // this looks like it would slow things down,
677     // and we can't depend on it on all platforms
678     deviceFeatures->robustBufferAccess = VK_FALSE;
679 
680     VkDeviceQueueCreateFlags flags = isProtected ? VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT : 0;
681     float queuePriorities[1] = { 0.0 };
682     // Here we assume no need for swapchain queue
683     // If one is needed, the client will need its own setup code
684     const VkDeviceQueueCreateInfo queueInfo[2] = {
685         {
686             VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
687             nullptr,                                    // pNext
688             flags,                                      // VkDeviceQueueCreateFlags
689             graphicsQueueIndex,                         // queueFamilyIndex
690             1,                                          // queueCount
691             queuePriorities,                            // pQueuePriorities
692 
693         },
694         {
695             VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
696             nullptr,                                    // pNext
697             0,                                          // VkDeviceQueueCreateFlags
698             presentQueueIndex,                          // queueFamilyIndex
699             1,                                          // queueCount
700             queuePriorities,                            // pQueuePriorities
701         }
702     };
703     uint32_t queueInfoCount = (presentQueueIndex != graphicsQueueIndex) ? 2 : 1;
704 
705     const VkDeviceCreateInfo deviceInfo = {
706         VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,        // sType
707         pointerToFeatures,                           // pNext
708         0,                                           // VkDeviceCreateFlags
709         queueInfoCount,                              // queueCreateInfoCount
710         queueInfo,                                   // pQueueCreateInfos
711         (uint32_t) deviceLayerNames.count(),         // layerCount
712         deviceLayerNames.begin(),                    // ppEnabledLayerNames
713         (uint32_t) deviceExtensionNames.count(),     // extensionCount
714         deviceExtensionNames.begin(),                // ppEnabledExtensionNames
715         pointerToFeatures ? nullptr : deviceFeatures // ppEnabledFeatures
716     };
717 
718     {
719 #if defined(SK_ENABLE_SCOPED_LSAN_SUPPRESSIONS)
720         // skia:8712
721         __lsan::ScopedDisabler lsanDisabler;
722 #endif
723         err = grVkCreateDevice(physDev, &deviceInfo, nullptr, &device);
724     }
725     if (err) {
726         SkDebugf("CreateDevice failed: %d\n", err);
727         destroy_instance(getProc, inst, debugCallback, hasDebugExtension);
728         return false;
729     }
730 
731     VkQueue queue;
732     if (isProtected) {
733         ACQUIRE_VK_PROC(GetDeviceQueue2, inst, device);
734         SkASSERT(grVkGetDeviceQueue2 != nullptr);
735         VkDeviceQueueInfo2 queue_info2 = {
736             VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2,          // sType
737             nullptr,                                        // pNext
738             VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT,           // flags
739             graphicsQueueIndex,                             // queueFamilyIndex
740             0                                               // queueIndex
741         };
742         grVkGetDeviceQueue2(device, &queue_info2, &queue);
743     } else {
744         grVkGetDeviceQueue(device, graphicsQueueIndex, 0, &queue);
745     }
746 
747     ctx->fInstance = inst;
748     ctx->fPhysicalDevice = physDev;
749     ctx->fDevice = device;
750     ctx->fQueue = queue;
751     ctx->fGraphicsQueueIndex = graphicsQueueIndex;
752     ctx->fMaxAPIVersion = apiVersion;
753     ctx->fVkExtensions = extensions;
754     ctx->fDeviceFeatures2 = features;
755     ctx->fGetProc = getProc;
756     ctx->fOwnsInstanceAndDevice = false;
757     ctx->fProtectedContext = isProtected ? GrProtected::kYes : GrProtected::kNo;
758 
759     return true;
760 }
761 
FreeVulkanFeaturesStructs(const VkPhysicalDeviceFeatures2 * features)762 void FreeVulkanFeaturesStructs(const VkPhysicalDeviceFeatures2* features) {
763     // All Vulkan structs that could be part of the features chain will start with the
764     // structure type followed by the pNext pointer. We cast to the CommonVulkanHeader
765     // so we can get access to the pNext for the next struct.
766     struct CommonVulkanHeader {
767         VkStructureType sType;
768         void*           pNext;
769     };
770 
771     void* pNext = features->pNext;
772     while (pNext) {
773         void* current = pNext;
774         pNext = static_cast<CommonVulkanHeader*>(current)->pNext;
775         sk_free(current);
776     }
777 }
778 
779 }
780 
781 #endif
782