xref: /aosp_15_r20/external/skia/tools/gpu/vk/VkTestUtils.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2017 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/vk/VulkanInterface.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "tools/gpu/vk/VkTestMemoryAllocator.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "tools/gpu/vk/VkTestUtils.h"
11*c8dee2aaSAndroid Build Coastguard Worker 
12*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_VULKAN
13*c8dee2aaSAndroid Build Coastguard Worker 
14*c8dee2aaSAndroid Build Coastguard Worker #ifndef SK_GPU_TOOLS_VK_LIBRARY_NAME
15*c8dee2aaSAndroid Build Coastguard Worker     #if defined _WIN32
16*c8dee2aaSAndroid Build Coastguard Worker         #define SK_GPU_TOOLS_VK_LIBRARY_NAME vulkan-1.dll
17*c8dee2aaSAndroid Build Coastguard Worker     #elif defined SK_BUILD_FOR_MAC
18*c8dee2aaSAndroid Build Coastguard Worker         #define SK_GPU_TOOLS_VK_LIBRARY_NAME libvk_swiftshader.dylib
19*c8dee2aaSAndroid Build Coastguard Worker     #else
20*c8dee2aaSAndroid Build Coastguard Worker         #define SK_GPU_TOOLS_VK_LIBRARY_NAME        libvulkan.so
21*c8dee2aaSAndroid Build Coastguard Worker         #define SK_GPU_TOOLS_VK_LIBRARY_NAME_BACKUP libvulkan.so.1
22*c8dee2aaSAndroid Build Coastguard Worker     #endif
23*c8dee2aaSAndroid Build Coastguard Worker #endif
24*c8dee2aaSAndroid Build Coastguard Worker 
25*c8dee2aaSAndroid Build Coastguard Worker #define STRINGIFY2(S) #S
26*c8dee2aaSAndroid Build Coastguard Worker #define STRINGIFY(S) STRINGIFY2(S)
27*c8dee2aaSAndroid Build Coastguard Worker 
28*c8dee2aaSAndroid Build Coastguard Worker #include <algorithm>
29*c8dee2aaSAndroid Build Coastguard Worker 
30*c8dee2aaSAndroid Build Coastguard Worker #if defined(__GLIBC__)
31*c8dee2aaSAndroid Build Coastguard Worker #include <execinfo.h>
32*c8dee2aaSAndroid Build Coastguard Worker #endif
33*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/vk/VulkanBackendContext.h"
34*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/vk/VulkanExtensions.h"
35*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkAutoMalloc.h"
36*c8dee2aaSAndroid Build Coastguard Worker #include "tools/library/LoadDynamicLibrary.h"
37*c8dee2aaSAndroid Build Coastguard Worker 
38*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_ENABLE_SCOPED_LSAN_SUPPRESSIONS)
39*c8dee2aaSAndroid Build Coastguard Worker #include <sanitizer/lsan_interface.h>
40*c8dee2aaSAndroid Build Coastguard Worker #endif
41*c8dee2aaSAndroid Build Coastguard Worker 
42*c8dee2aaSAndroid Build Coastguard Worker using namespace skia_private;
43*c8dee2aaSAndroid Build Coastguard Worker 
44*c8dee2aaSAndroid Build Coastguard Worker namespace sk_gpu_test {
45*c8dee2aaSAndroid Build Coastguard Worker 
LoadVkLibraryAndGetProcAddrFuncs(PFN_vkGetInstanceProcAddr * instProc)46*c8dee2aaSAndroid Build Coastguard Worker bool LoadVkLibraryAndGetProcAddrFuncs(PFN_vkGetInstanceProcAddr* instProc) {
47*c8dee2aaSAndroid Build Coastguard Worker     static void* vkLib = nullptr;
48*c8dee2aaSAndroid Build Coastguard Worker     static PFN_vkGetInstanceProcAddr localInstProc = nullptr;
49*c8dee2aaSAndroid Build Coastguard Worker     if (!vkLib) {
50*c8dee2aaSAndroid Build Coastguard Worker         vkLib = SkLoadDynamicLibrary(STRINGIFY(SK_GPU_TOOLS_VK_LIBRARY_NAME));
51*c8dee2aaSAndroid Build Coastguard Worker         if (!vkLib) {
52*c8dee2aaSAndroid Build Coastguard Worker             // vulkaninfo tries to load the library from two places, so we do as well
53*c8dee2aaSAndroid Build Coastguard Worker             // https://github.com/KhronosGroup/Vulkan-Tools/blob/078d44e4664b7efa0b6c96ebced1995c4425d57a/vulkaninfo/vulkaninfo.h#L249
54*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_GPU_TOOLS_VK_LIBRARY_NAME_BACKUP
55*c8dee2aaSAndroid Build Coastguard Worker             vkLib = SkLoadDynamicLibrary(STRINGIFY(SK_GPU_TOOLS_VK_LIBRARY_NAME_BACKUP));
56*c8dee2aaSAndroid Build Coastguard Worker             if (!vkLib) {
57*c8dee2aaSAndroid Build Coastguard Worker                 return false;
58*c8dee2aaSAndroid Build Coastguard Worker             }
59*c8dee2aaSAndroid Build Coastguard Worker #else
60*c8dee2aaSAndroid Build Coastguard Worker             return false;
61*c8dee2aaSAndroid Build Coastguard Worker #endif
62*c8dee2aaSAndroid Build Coastguard Worker         }
63*c8dee2aaSAndroid Build Coastguard Worker         localInstProc = (PFN_vkGetInstanceProcAddr) SkGetProcedureAddress(vkLib,
64*c8dee2aaSAndroid Build Coastguard Worker                                                                           "vkGetInstanceProcAddr");
65*c8dee2aaSAndroid Build Coastguard Worker     }
66*c8dee2aaSAndroid Build Coastguard Worker     if (!localInstProc) {
67*c8dee2aaSAndroid Build Coastguard Worker         return false;
68*c8dee2aaSAndroid Build Coastguard Worker     }
69*c8dee2aaSAndroid Build Coastguard Worker     *instProc = localInstProc;
70*c8dee2aaSAndroid Build Coastguard Worker     return true;
71*c8dee2aaSAndroid Build Coastguard Worker }
72*c8dee2aaSAndroid Build Coastguard Worker 
73*c8dee2aaSAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
74*c8dee2aaSAndroid Build Coastguard Worker // Helper code to set up Vulkan context objects
75*c8dee2aaSAndroid Build Coastguard Worker 
76*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_ENABLE_VK_LAYERS
77*c8dee2aaSAndroid Build Coastguard Worker const char* kDebugLayerNames[] = {
78*c8dee2aaSAndroid Build Coastguard Worker     // single merged layer
79*c8dee2aaSAndroid Build Coastguard Worker     "VK_LAYER_KHRONOS_validation",
80*c8dee2aaSAndroid Build Coastguard Worker     // not included in standard_validation
81*c8dee2aaSAndroid Build Coastguard Worker     //"VK_LAYER_LUNARG_api_dump",
82*c8dee2aaSAndroid Build Coastguard Worker     //"VK_LAYER_LUNARG_vktrace",
83*c8dee2aaSAndroid Build Coastguard Worker     //"VK_LAYER_LUNARG_screenshot",
84*c8dee2aaSAndroid Build Coastguard Worker };
85*c8dee2aaSAndroid Build Coastguard Worker 
remove_patch_version(uint32_t specVersion)86*c8dee2aaSAndroid Build Coastguard Worker static uint32_t remove_patch_version(uint32_t specVersion) {
87*c8dee2aaSAndroid Build Coastguard Worker     return (specVersion >> 12) << 12;
88*c8dee2aaSAndroid Build Coastguard Worker }
89*c8dee2aaSAndroid Build Coastguard Worker 
90*c8dee2aaSAndroid Build Coastguard Worker // 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)91*c8dee2aaSAndroid Build Coastguard Worker static int should_include_debug_layer(const char* layerName,
92*c8dee2aaSAndroid Build Coastguard Worker                                        uint32_t layerCount, VkLayerProperties* layers,
93*c8dee2aaSAndroid Build Coastguard Worker                                        uint32_t version) {
94*c8dee2aaSAndroid Build Coastguard Worker     for (uint32_t i = 0; i < layerCount; ++i) {
95*c8dee2aaSAndroid Build Coastguard Worker         if (!strcmp(layerName, layers[i].layerName)) {
96*c8dee2aaSAndroid Build Coastguard Worker             // Since the layers intercept the vulkan calls and forward them on, we need to make sure
97*c8dee2aaSAndroid Build Coastguard Worker             // layer was written against a version that isn't older than the version of Vulkan we're
98*c8dee2aaSAndroid Build Coastguard Worker             // using so that it has all the api entry points.
99*c8dee2aaSAndroid Build Coastguard Worker             if (version <= remove_patch_version(layers[i].specVersion)) {
100*c8dee2aaSAndroid Build Coastguard Worker                 return i;
101*c8dee2aaSAndroid Build Coastguard Worker             }
102*c8dee2aaSAndroid Build Coastguard Worker             return -1;
103*c8dee2aaSAndroid Build Coastguard Worker         }
104*c8dee2aaSAndroid Build Coastguard Worker 
105*c8dee2aaSAndroid Build Coastguard Worker     }
106*c8dee2aaSAndroid Build Coastguard Worker     return -1;
107*c8dee2aaSAndroid Build Coastguard Worker }
108*c8dee2aaSAndroid Build Coastguard Worker 
print_backtrace()109*c8dee2aaSAndroid Build Coastguard Worker static void print_backtrace() {
110*c8dee2aaSAndroid Build Coastguard Worker #if defined(__GLIBC__)
111*c8dee2aaSAndroid Build Coastguard Worker     void* stack[64];
112*c8dee2aaSAndroid Build Coastguard Worker     int count = backtrace(stack, std::size(stack));
113*c8dee2aaSAndroid Build Coastguard Worker     backtrace_symbols_fd(stack, count, 2);
114*c8dee2aaSAndroid Build Coastguard Worker #else
115*c8dee2aaSAndroid Build Coastguard Worker     // Please add implementations for other platforms.
116*c8dee2aaSAndroid Build Coastguard Worker #endif
117*c8dee2aaSAndroid Build Coastguard Worker }
118*c8dee2aaSAndroid Build Coastguard Worker 
DebugReportCallback(VkDebugReportFlagsEXT flags,VkDebugReportObjectTypeEXT objectType,uint64_t object,size_t location,int32_t messageCode,const char * pLayerPrefix,const char * pMessage,void * pUserData)119*c8dee2aaSAndroid Build Coastguard Worker VKAPI_ATTR VkBool32 VKAPI_CALL DebugReportCallback(
120*c8dee2aaSAndroid Build Coastguard Worker     VkDebugReportFlagsEXT       flags,
121*c8dee2aaSAndroid Build Coastguard Worker     VkDebugReportObjectTypeEXT  objectType,
122*c8dee2aaSAndroid Build Coastguard Worker     uint64_t                    object,
123*c8dee2aaSAndroid Build Coastguard Worker     size_t                      location,
124*c8dee2aaSAndroid Build Coastguard Worker     int32_t                     messageCode,
125*c8dee2aaSAndroid Build Coastguard Worker     const char*                 pLayerPrefix,
126*c8dee2aaSAndroid Build Coastguard Worker     const char*                 pMessage,
127*c8dee2aaSAndroid Build Coastguard Worker     void*                       pUserData) {
128*c8dee2aaSAndroid Build Coastguard Worker     if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
129*c8dee2aaSAndroid Build Coastguard Worker         // See https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/1887
130*c8dee2aaSAndroid Build Coastguard Worker         if (strstr(pMessage, "VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-01521") ||
131*c8dee2aaSAndroid Build Coastguard Worker             strstr(pMessage, "VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-01522")) {
132*c8dee2aaSAndroid Build Coastguard Worker             return VK_FALSE;
133*c8dee2aaSAndroid Build Coastguard Worker         }
134*c8dee2aaSAndroid Build Coastguard Worker         // See https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/2171
135*c8dee2aaSAndroid Build Coastguard Worker         if (strstr(pMessage, "VUID-vkCmdDraw-None-02686") ||
136*c8dee2aaSAndroid Build Coastguard Worker             strstr(pMessage, "VUID-vkCmdDrawIndexed-None-02686")) {
137*c8dee2aaSAndroid Build Coastguard Worker             return VK_FALSE;
138*c8dee2aaSAndroid Build Coastguard Worker         }
139*c8dee2aaSAndroid Build Coastguard Worker         SkDebugf("Vulkan error [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
140*c8dee2aaSAndroid Build Coastguard Worker         print_backtrace();
141*c8dee2aaSAndroid Build Coastguard Worker         SkDEBUGFAIL("Vulkan debug layer error");
142*c8dee2aaSAndroid Build Coastguard Worker         return VK_TRUE; // skip further layers
143*c8dee2aaSAndroid Build Coastguard Worker     } else if (flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
144*c8dee2aaSAndroid Build Coastguard Worker         SkDebugf("Vulkan warning [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
145*c8dee2aaSAndroid Build Coastguard Worker         print_backtrace();
146*c8dee2aaSAndroid Build Coastguard Worker     } else if (flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) {
147*c8dee2aaSAndroid Build Coastguard Worker         SkDebugf("Vulkan perf warning [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
148*c8dee2aaSAndroid Build Coastguard Worker         print_backtrace();
149*c8dee2aaSAndroid Build Coastguard Worker     } else {
150*c8dee2aaSAndroid Build Coastguard Worker         SkDebugf("Vulkan info/debug [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
151*c8dee2aaSAndroid Build Coastguard Worker     }
152*c8dee2aaSAndroid Build Coastguard Worker     return VK_FALSE;
153*c8dee2aaSAndroid Build Coastguard Worker }
154*c8dee2aaSAndroid Build Coastguard Worker #endif
155*c8dee2aaSAndroid Build Coastguard Worker 
156*c8dee2aaSAndroid Build Coastguard Worker #define ACQUIRE_VK_INST_PROC_LOCAL(name, instance)                                 \
157*c8dee2aaSAndroid Build Coastguard Worker     PFN_vk##name grVk##name =                                                      \
158*c8dee2aaSAndroid Build Coastguard Worker         reinterpret_cast<PFN_vk##name>(getInstProc(instance, "vk" #name));         \
159*c8dee2aaSAndroid Build Coastguard Worker     do {                                                                           \
160*c8dee2aaSAndroid Build Coastguard Worker         if (grVk##name == nullptr) {                                               \
161*c8dee2aaSAndroid Build Coastguard Worker             SkDebugf("Function ptr for vk%s could not be acquired\n", #name);      \
162*c8dee2aaSAndroid Build Coastguard Worker             return false;                                                          \
163*c8dee2aaSAndroid Build Coastguard Worker         }                                                                          \
164*c8dee2aaSAndroid Build Coastguard Worker     } while (0)
165*c8dee2aaSAndroid Build Coastguard Worker 
166*c8dee2aaSAndroid Build Coastguard Worker // Returns the index into layers array for the layer we want. Returns -1 if not supported.
should_include_extension(const char * extensionName)167*c8dee2aaSAndroid Build Coastguard Worker static bool should_include_extension(const char* extensionName) {
168*c8dee2aaSAndroid Build Coastguard Worker     const char* kValidExtensions[] = {
169*c8dee2aaSAndroid Build Coastguard Worker             // single merged layer
170*c8dee2aaSAndroid Build Coastguard Worker             VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME,
171*c8dee2aaSAndroid Build Coastguard Worker             VK_EXT_CONSERVATIVE_RASTERIZATION_EXTENSION_NAME,
172*c8dee2aaSAndroid Build Coastguard Worker             VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
173*c8dee2aaSAndroid Build Coastguard Worker             VK_EXT_DEVICE_FAULT_EXTENSION_NAME,
174*c8dee2aaSAndroid Build Coastguard Worker             VK_EXT_FRAME_BOUNDARY_EXTENSION_NAME,
175*c8dee2aaSAndroid Build Coastguard Worker             VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME,
176*c8dee2aaSAndroid Build Coastguard Worker             VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME,
177*c8dee2aaSAndroid Build Coastguard Worker             VK_EXT_RGBA10X6_FORMATS_EXTENSION_NAME,
178*c8dee2aaSAndroid Build Coastguard Worker             VK_KHR_BIND_MEMORY_2_EXTENSION_NAME,
179*c8dee2aaSAndroid Build Coastguard Worker             VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME,
180*c8dee2aaSAndroid Build Coastguard Worker             VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME,
181*c8dee2aaSAndroid Build Coastguard Worker             VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME,
182*c8dee2aaSAndroid Build Coastguard Worker             VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME,
183*c8dee2aaSAndroid Build Coastguard Worker             VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
184*c8dee2aaSAndroid Build Coastguard Worker             VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME,
185*c8dee2aaSAndroid Build Coastguard Worker             VK_KHR_MAINTENANCE1_EXTENSION_NAME,
186*c8dee2aaSAndroid Build Coastguard Worker             VK_KHR_MAINTENANCE2_EXTENSION_NAME,
187*c8dee2aaSAndroid Build Coastguard Worker             VK_KHR_MAINTENANCE3_EXTENSION_NAME,
188*c8dee2aaSAndroid Build Coastguard Worker             VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME,
189*c8dee2aaSAndroid Build Coastguard Worker             VK_KHR_SURFACE_EXTENSION_NAME,
190*c8dee2aaSAndroid Build Coastguard Worker             VK_KHR_SWAPCHAIN_EXTENSION_NAME,
191*c8dee2aaSAndroid Build Coastguard Worker             // Below are all platform specific extensions. The name macros like we use above are
192*c8dee2aaSAndroid Build Coastguard Worker             // all defined in platform specific vulkan headers. We currently don't include these
193*c8dee2aaSAndroid Build Coastguard Worker             // headers as they are a little bit of a pain (e.g. windows headers requires including
194*c8dee2aaSAndroid Build Coastguard Worker             // <windows.h> which causes all sorts of fun annoyances/problems. So instead we are
195*c8dee2aaSAndroid Build Coastguard Worker             // just listing the strings these macros are defined to. This really shouldn't cause
196*c8dee2aaSAndroid Build Coastguard Worker             // any long term issues as the chances of the strings connected to the name macros
197*c8dee2aaSAndroid Build Coastguard Worker             // changing is next to zero.
198*c8dee2aaSAndroid Build Coastguard Worker             "VK_KHR_win32_surface", // VK_KHR_WIN32_SURFACE_EXTENSION_NAME
199*c8dee2aaSAndroid Build Coastguard Worker             "VK_KHR_xcb_surface", // VK_KHR_XCB_SURFACE_EXTENSION_NAME,
200*c8dee2aaSAndroid Build Coastguard Worker             "VK_ANDROID_external_memory_android_hardware_buffer",
201*c8dee2aaSAndroid Build Coastguard Worker             // VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME,
202*c8dee2aaSAndroid Build Coastguard Worker             "VK_KHR_android_surface", // VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
203*c8dee2aaSAndroid Build Coastguard Worker     };
204*c8dee2aaSAndroid Build Coastguard Worker 
205*c8dee2aaSAndroid Build Coastguard Worker     for (size_t i = 0; i < std::size(kValidExtensions); ++i) {
206*c8dee2aaSAndroid Build Coastguard Worker         if (!strcmp(extensionName, kValidExtensions[i])) {
207*c8dee2aaSAndroid Build Coastguard Worker             return true;
208*c8dee2aaSAndroid Build Coastguard Worker         }
209*c8dee2aaSAndroid Build Coastguard Worker     }
210*c8dee2aaSAndroid Build Coastguard Worker     return false;
211*c8dee2aaSAndroid Build Coastguard Worker }
212*c8dee2aaSAndroid Build Coastguard Worker 
init_instance_extensions_and_layers(PFN_vkGetInstanceProcAddr getInstProc,uint32_t specVersion,TArray<VkExtensionProperties> * instanceExtensions,TArray<VkLayerProperties> * instanceLayers)213*c8dee2aaSAndroid Build Coastguard Worker static bool init_instance_extensions_and_layers(PFN_vkGetInstanceProcAddr getInstProc,
214*c8dee2aaSAndroid Build Coastguard Worker                                                 uint32_t specVersion,
215*c8dee2aaSAndroid Build Coastguard Worker                                                 TArray<VkExtensionProperties>* instanceExtensions,
216*c8dee2aaSAndroid Build Coastguard Worker                                                 TArray<VkLayerProperties>* instanceLayers) {
217*c8dee2aaSAndroid Build Coastguard Worker     if (getInstProc == nullptr) {
218*c8dee2aaSAndroid Build Coastguard Worker         return false;
219*c8dee2aaSAndroid Build Coastguard Worker     }
220*c8dee2aaSAndroid Build Coastguard Worker 
221*c8dee2aaSAndroid Build Coastguard Worker     ACQUIRE_VK_INST_PROC_LOCAL(EnumerateInstanceExtensionProperties, VK_NULL_HANDLE);
222*c8dee2aaSAndroid Build Coastguard Worker     ACQUIRE_VK_INST_PROC_LOCAL(EnumerateInstanceLayerProperties, VK_NULL_HANDLE);
223*c8dee2aaSAndroid Build Coastguard Worker 
224*c8dee2aaSAndroid Build Coastguard Worker     VkResult res;
225*c8dee2aaSAndroid Build Coastguard Worker     uint32_t layerCount = 0;
226*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_ENABLE_VK_LAYERS
227*c8dee2aaSAndroid Build Coastguard Worker     // instance layers
228*c8dee2aaSAndroid Build Coastguard Worker     res = grVkEnumerateInstanceLayerProperties(&layerCount, nullptr);
229*c8dee2aaSAndroid Build Coastguard Worker     if (VK_SUCCESS != res) {
230*c8dee2aaSAndroid Build Coastguard Worker         return false;
231*c8dee2aaSAndroid Build Coastguard Worker     }
232*c8dee2aaSAndroid Build Coastguard Worker     VkLayerProperties* layers = new VkLayerProperties[layerCount];
233*c8dee2aaSAndroid Build Coastguard Worker     res = grVkEnumerateInstanceLayerProperties(&layerCount, layers);
234*c8dee2aaSAndroid Build Coastguard Worker     if (VK_SUCCESS != res) {
235*c8dee2aaSAndroid Build Coastguard Worker         delete[] layers;
236*c8dee2aaSAndroid Build Coastguard Worker         return false;
237*c8dee2aaSAndroid Build Coastguard Worker     }
238*c8dee2aaSAndroid Build Coastguard Worker 
239*c8dee2aaSAndroid Build Coastguard Worker     uint32_t nonPatchVersion = remove_patch_version(specVersion);
240*c8dee2aaSAndroid Build Coastguard Worker     for (size_t i = 0; i < std::size(kDebugLayerNames); ++i) {
241*c8dee2aaSAndroid Build Coastguard Worker         int idx = should_include_debug_layer(kDebugLayerNames[i], layerCount, layers,
242*c8dee2aaSAndroid Build Coastguard Worker                                              nonPatchVersion);
243*c8dee2aaSAndroid Build Coastguard Worker         if (idx != -1) {
244*c8dee2aaSAndroid Build Coastguard Worker             instanceLayers->push_back() = layers[idx];
245*c8dee2aaSAndroid Build Coastguard Worker         }
246*c8dee2aaSAndroid Build Coastguard Worker     }
247*c8dee2aaSAndroid Build Coastguard Worker     delete[] layers;
248*c8dee2aaSAndroid Build Coastguard Worker #endif
249*c8dee2aaSAndroid Build Coastguard Worker 
250*c8dee2aaSAndroid Build Coastguard Worker     // instance extensions
251*c8dee2aaSAndroid Build Coastguard Worker     // via Vulkan implementation and implicitly enabled layers
252*c8dee2aaSAndroid Build Coastguard Worker     {
253*c8dee2aaSAndroid Build Coastguard Worker         uint32_t extensionCount = 0;
254*c8dee2aaSAndroid Build Coastguard Worker         res = grVkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
255*c8dee2aaSAndroid Build Coastguard Worker         if (VK_SUCCESS != res) {
256*c8dee2aaSAndroid Build Coastguard Worker             return false;
257*c8dee2aaSAndroid Build Coastguard Worker         }
258*c8dee2aaSAndroid Build Coastguard Worker         VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
259*c8dee2aaSAndroid Build Coastguard Worker         res = grVkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions);
260*c8dee2aaSAndroid Build Coastguard Worker         if (VK_SUCCESS != res) {
261*c8dee2aaSAndroid Build Coastguard Worker             delete[] extensions;
262*c8dee2aaSAndroid Build Coastguard Worker             return false;
263*c8dee2aaSAndroid Build Coastguard Worker         }
264*c8dee2aaSAndroid Build Coastguard Worker         for (uint32_t i = 0; i < extensionCount; ++i) {
265*c8dee2aaSAndroid Build Coastguard Worker             if (should_include_extension(extensions[i].extensionName)) {
266*c8dee2aaSAndroid Build Coastguard Worker                 instanceExtensions->push_back() = extensions[i];
267*c8dee2aaSAndroid Build Coastguard Worker             }
268*c8dee2aaSAndroid Build Coastguard Worker         }
269*c8dee2aaSAndroid Build Coastguard Worker         delete [] extensions;
270*c8dee2aaSAndroid Build Coastguard Worker     }
271*c8dee2aaSAndroid Build Coastguard Worker 
272*c8dee2aaSAndroid Build Coastguard Worker     // via explicitly enabled layers
273*c8dee2aaSAndroid Build Coastguard Worker     layerCount = instanceLayers->size();
274*c8dee2aaSAndroid Build Coastguard Worker     for (uint32_t layerIndex = 0; layerIndex < layerCount; ++layerIndex) {
275*c8dee2aaSAndroid Build Coastguard Worker         uint32_t extensionCount = 0;
276*c8dee2aaSAndroid Build Coastguard Worker         res = grVkEnumerateInstanceExtensionProperties((*instanceLayers)[layerIndex].layerName,
277*c8dee2aaSAndroid Build Coastguard Worker                                                        &extensionCount, nullptr);
278*c8dee2aaSAndroid Build Coastguard Worker         if (VK_SUCCESS != res) {
279*c8dee2aaSAndroid Build Coastguard Worker             return false;
280*c8dee2aaSAndroid Build Coastguard Worker         }
281*c8dee2aaSAndroid Build Coastguard Worker         VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
282*c8dee2aaSAndroid Build Coastguard Worker         res = grVkEnumerateInstanceExtensionProperties((*instanceLayers)[layerIndex].layerName,
283*c8dee2aaSAndroid Build Coastguard Worker                                                        &extensionCount, extensions);
284*c8dee2aaSAndroid Build Coastguard Worker         if (VK_SUCCESS != res) {
285*c8dee2aaSAndroid Build Coastguard Worker             delete[] extensions;
286*c8dee2aaSAndroid Build Coastguard Worker             return false;
287*c8dee2aaSAndroid Build Coastguard Worker         }
288*c8dee2aaSAndroid Build Coastguard Worker         for (uint32_t i = 0; i < extensionCount; ++i) {
289*c8dee2aaSAndroid Build Coastguard Worker             if (should_include_extension(extensions[i].extensionName)) {
290*c8dee2aaSAndroid Build Coastguard Worker                 instanceExtensions->push_back() = extensions[i];
291*c8dee2aaSAndroid Build Coastguard Worker             }
292*c8dee2aaSAndroid Build Coastguard Worker         }
293*c8dee2aaSAndroid Build Coastguard Worker         delete[] extensions;
294*c8dee2aaSAndroid Build Coastguard Worker     }
295*c8dee2aaSAndroid Build Coastguard Worker 
296*c8dee2aaSAndroid Build Coastguard Worker     return true;
297*c8dee2aaSAndroid Build Coastguard Worker }
298*c8dee2aaSAndroid Build Coastguard Worker 
299*c8dee2aaSAndroid Build Coastguard Worker #define GET_PROC_LOCAL(F, inst, device) PFN_vk ## F F = (PFN_vk ## F) getProc("vk" #F, inst, device)
300*c8dee2aaSAndroid Build Coastguard Worker 
init_device_extensions_and_layers(const skgpu::VulkanGetProc & getProc,uint32_t specVersion,VkInstance inst,VkPhysicalDevice physDev,TArray<VkExtensionProperties> * deviceExtensions,TArray<VkLayerProperties> * deviceLayers)301*c8dee2aaSAndroid Build Coastguard Worker static bool init_device_extensions_and_layers(const skgpu::VulkanGetProc& getProc,
302*c8dee2aaSAndroid Build Coastguard Worker                                               uint32_t specVersion, VkInstance inst,
303*c8dee2aaSAndroid Build Coastguard Worker                                               VkPhysicalDevice physDev,
304*c8dee2aaSAndroid Build Coastguard Worker                                               TArray<VkExtensionProperties>* deviceExtensions,
305*c8dee2aaSAndroid Build Coastguard Worker                                               TArray<VkLayerProperties>* deviceLayers) {
306*c8dee2aaSAndroid Build Coastguard Worker     if (getProc == nullptr) {
307*c8dee2aaSAndroid Build Coastguard Worker         return false;
308*c8dee2aaSAndroid Build Coastguard Worker     }
309*c8dee2aaSAndroid Build Coastguard Worker 
310*c8dee2aaSAndroid Build Coastguard Worker     GET_PROC_LOCAL(EnumerateDeviceExtensionProperties, inst, VK_NULL_HANDLE);
311*c8dee2aaSAndroid Build Coastguard Worker     GET_PROC_LOCAL(EnumerateDeviceLayerProperties, inst, VK_NULL_HANDLE);
312*c8dee2aaSAndroid Build Coastguard Worker 
313*c8dee2aaSAndroid Build Coastguard Worker     if (!EnumerateDeviceExtensionProperties ||
314*c8dee2aaSAndroid Build Coastguard Worker         !EnumerateDeviceLayerProperties) {
315*c8dee2aaSAndroid Build Coastguard Worker         return false;
316*c8dee2aaSAndroid Build Coastguard Worker     }
317*c8dee2aaSAndroid Build Coastguard Worker 
318*c8dee2aaSAndroid Build Coastguard Worker     VkResult res;
319*c8dee2aaSAndroid Build Coastguard Worker     // device layers
320*c8dee2aaSAndroid Build Coastguard Worker     uint32_t layerCount = 0;
321*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_ENABLE_VK_LAYERS
322*c8dee2aaSAndroid Build Coastguard Worker     res = EnumerateDeviceLayerProperties(physDev, &layerCount, nullptr);
323*c8dee2aaSAndroid Build Coastguard Worker     if (VK_SUCCESS != res) {
324*c8dee2aaSAndroid Build Coastguard Worker         return false;
325*c8dee2aaSAndroid Build Coastguard Worker     }
326*c8dee2aaSAndroid Build Coastguard Worker     VkLayerProperties* layers = new VkLayerProperties[layerCount];
327*c8dee2aaSAndroid Build Coastguard Worker     res = EnumerateDeviceLayerProperties(physDev, &layerCount, layers);
328*c8dee2aaSAndroid Build Coastguard Worker     if (VK_SUCCESS != res) {
329*c8dee2aaSAndroid Build Coastguard Worker         delete[] layers;
330*c8dee2aaSAndroid Build Coastguard Worker         return false;
331*c8dee2aaSAndroid Build Coastguard Worker     }
332*c8dee2aaSAndroid Build Coastguard Worker 
333*c8dee2aaSAndroid Build Coastguard Worker     uint32_t nonPatchVersion = remove_patch_version(specVersion);
334*c8dee2aaSAndroid Build Coastguard Worker     for (size_t i = 0; i < std::size(kDebugLayerNames); ++i) {
335*c8dee2aaSAndroid Build Coastguard Worker         int idx = should_include_debug_layer(kDebugLayerNames[i], layerCount, layers,
336*c8dee2aaSAndroid Build Coastguard Worker                                              nonPatchVersion);
337*c8dee2aaSAndroid Build Coastguard Worker         if (idx != -1) {
338*c8dee2aaSAndroid Build Coastguard Worker             deviceLayers->push_back() = layers[idx];
339*c8dee2aaSAndroid Build Coastguard Worker         }
340*c8dee2aaSAndroid Build Coastguard Worker     }
341*c8dee2aaSAndroid Build Coastguard Worker     delete[] layers;
342*c8dee2aaSAndroid Build Coastguard Worker #endif
343*c8dee2aaSAndroid Build Coastguard Worker 
344*c8dee2aaSAndroid Build Coastguard Worker     // device extensions
345*c8dee2aaSAndroid Build Coastguard Worker     // via Vulkan implementation and implicitly enabled layers
346*c8dee2aaSAndroid Build Coastguard Worker     {
347*c8dee2aaSAndroid Build Coastguard Worker         uint32_t extensionCount = 0;
348*c8dee2aaSAndroid Build Coastguard Worker         res = EnumerateDeviceExtensionProperties(physDev, nullptr, &extensionCount, nullptr);
349*c8dee2aaSAndroid Build Coastguard Worker         if (VK_SUCCESS != res) {
350*c8dee2aaSAndroid Build Coastguard Worker             return false;
351*c8dee2aaSAndroid Build Coastguard Worker         }
352*c8dee2aaSAndroid Build Coastguard Worker         VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
353*c8dee2aaSAndroid Build Coastguard Worker         res = EnumerateDeviceExtensionProperties(physDev, nullptr, &extensionCount, extensions);
354*c8dee2aaSAndroid Build Coastguard Worker         if (VK_SUCCESS != res) {
355*c8dee2aaSAndroid Build Coastguard Worker             delete[] extensions;
356*c8dee2aaSAndroid Build Coastguard Worker             return false;
357*c8dee2aaSAndroid Build Coastguard Worker         }
358*c8dee2aaSAndroid Build Coastguard Worker         for (uint32_t i = 0; i < extensionCount; ++i) {
359*c8dee2aaSAndroid Build Coastguard Worker             if (should_include_extension(extensions[i].extensionName)) {
360*c8dee2aaSAndroid Build Coastguard Worker                 deviceExtensions->push_back() = extensions[i];
361*c8dee2aaSAndroid Build Coastguard Worker             }
362*c8dee2aaSAndroid Build Coastguard Worker         }
363*c8dee2aaSAndroid Build Coastguard Worker         delete[] extensions;
364*c8dee2aaSAndroid Build Coastguard Worker     }
365*c8dee2aaSAndroid Build Coastguard Worker 
366*c8dee2aaSAndroid Build Coastguard Worker     // via explicitly enabled layers
367*c8dee2aaSAndroid Build Coastguard Worker     layerCount = deviceLayers->size();
368*c8dee2aaSAndroid Build Coastguard Worker     for (uint32_t layerIndex = 0; layerIndex < layerCount; ++layerIndex) {
369*c8dee2aaSAndroid Build Coastguard Worker         uint32_t extensionCount = 0;
370*c8dee2aaSAndroid Build Coastguard Worker         res = EnumerateDeviceExtensionProperties(physDev,
371*c8dee2aaSAndroid Build Coastguard Worker             (*deviceLayers)[layerIndex].layerName,
372*c8dee2aaSAndroid Build Coastguard Worker             &extensionCount, nullptr);
373*c8dee2aaSAndroid Build Coastguard Worker         if (VK_SUCCESS != res) {
374*c8dee2aaSAndroid Build Coastguard Worker             return false;
375*c8dee2aaSAndroid Build Coastguard Worker         }
376*c8dee2aaSAndroid Build Coastguard Worker         VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
377*c8dee2aaSAndroid Build Coastguard Worker         res = EnumerateDeviceExtensionProperties(physDev,
378*c8dee2aaSAndroid Build Coastguard Worker             (*deviceLayers)[layerIndex].layerName,
379*c8dee2aaSAndroid Build Coastguard Worker             &extensionCount, extensions);
380*c8dee2aaSAndroid Build Coastguard Worker         if (VK_SUCCESS != res) {
381*c8dee2aaSAndroid Build Coastguard Worker             delete[] extensions;
382*c8dee2aaSAndroid Build Coastguard Worker             return false;
383*c8dee2aaSAndroid Build Coastguard Worker         }
384*c8dee2aaSAndroid Build Coastguard Worker         for (uint32_t i = 0; i < extensionCount; ++i) {
385*c8dee2aaSAndroid Build Coastguard Worker             if (should_include_extension(extensions[i].extensionName)) {
386*c8dee2aaSAndroid Build Coastguard Worker                 deviceExtensions->push_back() = extensions[i];
387*c8dee2aaSAndroid Build Coastguard Worker             }
388*c8dee2aaSAndroid Build Coastguard Worker         }
389*c8dee2aaSAndroid Build Coastguard Worker         delete[] extensions;
390*c8dee2aaSAndroid Build Coastguard Worker     }
391*c8dee2aaSAndroid Build Coastguard Worker 
392*c8dee2aaSAndroid Build Coastguard Worker     return true;
393*c8dee2aaSAndroid Build Coastguard Worker }
394*c8dee2aaSAndroid Build Coastguard Worker 
395*c8dee2aaSAndroid Build Coastguard Worker #define ACQUIRE_VK_INST_PROC_NOCHECK(name, instance) \
396*c8dee2aaSAndroid Build Coastguard Worker     PFN_vk##name grVk##name = reinterpret_cast<PFN_vk##name>(getInstProc(instance, "vk" #name))
397*c8dee2aaSAndroid Build Coastguard Worker 
398*c8dee2aaSAndroid Build Coastguard Worker #define ACQUIRE_VK_INST_PROC(name, instance) \
399*c8dee2aaSAndroid Build Coastguard Worker     PFN_vk##name grVk##name =                                                          \
400*c8dee2aaSAndroid Build Coastguard Worker         reinterpret_cast<PFN_vk##name>(getInstProc(instance, "vk" #name));             \
401*c8dee2aaSAndroid Build Coastguard Worker     do {                                                                               \
402*c8dee2aaSAndroid Build Coastguard Worker         if (grVk##name == nullptr) {                                                   \
403*c8dee2aaSAndroid Build Coastguard Worker             SkDebugf("Function ptr for vk%s could not be acquired\n", #name);          \
404*c8dee2aaSAndroid Build Coastguard Worker             if (inst != VK_NULL_HANDLE) {                                              \
405*c8dee2aaSAndroid Build Coastguard Worker                 destroy_instance(getInstProc, inst, debugCallback, hasDebugExtension); \
406*c8dee2aaSAndroid Build Coastguard Worker             }                                                                          \
407*c8dee2aaSAndroid Build Coastguard Worker             return false;                                                              \
408*c8dee2aaSAndroid Build Coastguard Worker         }                                                                              \
409*c8dee2aaSAndroid Build Coastguard Worker     } while (0)
410*c8dee2aaSAndroid Build Coastguard Worker 
411*c8dee2aaSAndroid Build Coastguard Worker #define ACQUIRE_VK_PROC_NOCHECK(name, instance, device) \
412*c8dee2aaSAndroid Build Coastguard Worker     PFN_vk##name grVk##name = reinterpret_cast<PFN_vk##name>(getProc("vk" #name, instance, device))
413*c8dee2aaSAndroid Build Coastguard Worker 
414*c8dee2aaSAndroid Build Coastguard Worker #define ACQUIRE_VK_PROC(name, instance, device)                                        \
415*c8dee2aaSAndroid Build Coastguard Worker     PFN_vk##name grVk##name =                                                          \
416*c8dee2aaSAndroid Build Coastguard Worker             reinterpret_cast<PFN_vk##name>(getProc("vk" #name, instance, device));     \
417*c8dee2aaSAndroid Build Coastguard Worker     do {                                                                               \
418*c8dee2aaSAndroid Build Coastguard Worker         if (grVk##name == nullptr) {                                                   \
419*c8dee2aaSAndroid Build Coastguard Worker             SkDebugf("Function ptr for vk%s could not be acquired\n", #name);          \
420*c8dee2aaSAndroid Build Coastguard Worker             if (inst != VK_NULL_HANDLE) {                                              \
421*c8dee2aaSAndroid Build Coastguard Worker                 destroy_instance(getInstProc, inst, debugCallback, hasDebugExtension); \
422*c8dee2aaSAndroid Build Coastguard Worker             }                                                                          \
423*c8dee2aaSAndroid Build Coastguard Worker             return false;                                                              \
424*c8dee2aaSAndroid Build Coastguard Worker         }                                                                              \
425*c8dee2aaSAndroid Build Coastguard Worker     } while (0)
426*c8dee2aaSAndroid Build Coastguard Worker 
427*c8dee2aaSAndroid Build Coastguard Worker #define ACQUIRE_VK_PROC_LOCAL(name, instance, device)                              \
428*c8dee2aaSAndroid Build Coastguard Worker     PFN_vk##name grVk##name =                                                      \
429*c8dee2aaSAndroid Build Coastguard Worker             reinterpret_cast<PFN_vk##name>(getProc("vk" #name, instance, device)); \
430*c8dee2aaSAndroid Build Coastguard Worker     do {                                                                           \
431*c8dee2aaSAndroid Build Coastguard Worker         if (grVk##name == nullptr) {                                               \
432*c8dee2aaSAndroid Build Coastguard Worker             SkDebugf("Function ptr for vk%s could not be acquired\n", #name);      \
433*c8dee2aaSAndroid Build Coastguard Worker             return false;                                                          \
434*c8dee2aaSAndroid Build Coastguard Worker         }                                                                          \
435*c8dee2aaSAndroid Build Coastguard Worker     } while (0)
436*c8dee2aaSAndroid Build Coastguard Worker 
destroy_instance(PFN_vkGetInstanceProcAddr getInstProc,VkInstance inst,VkDebugReportCallbackEXT * debugCallback,bool hasDebugExtension)437*c8dee2aaSAndroid Build Coastguard Worker static bool destroy_instance(PFN_vkGetInstanceProcAddr getInstProc, VkInstance inst,
438*c8dee2aaSAndroid Build Coastguard Worker                              VkDebugReportCallbackEXT* debugCallback,
439*c8dee2aaSAndroid Build Coastguard Worker                              bool hasDebugExtension) {
440*c8dee2aaSAndroid Build Coastguard Worker     if (hasDebugExtension && *debugCallback != VK_NULL_HANDLE) {
441*c8dee2aaSAndroid Build Coastguard Worker         ACQUIRE_VK_INST_PROC_LOCAL(DestroyDebugReportCallbackEXT, inst);
442*c8dee2aaSAndroid Build Coastguard Worker         grVkDestroyDebugReportCallbackEXT(inst, *debugCallback, nullptr);
443*c8dee2aaSAndroid Build Coastguard Worker         *debugCallback = VK_NULL_HANDLE;
444*c8dee2aaSAndroid Build Coastguard Worker     }
445*c8dee2aaSAndroid Build Coastguard Worker     ACQUIRE_VK_INST_PROC_LOCAL(DestroyInstance, inst);
446*c8dee2aaSAndroid Build Coastguard Worker     grVkDestroyInstance(inst, nullptr);
447*c8dee2aaSAndroid Build Coastguard Worker     return true;
448*c8dee2aaSAndroid Build Coastguard Worker }
449*c8dee2aaSAndroid Build Coastguard Worker 
setup_features(const skgpu::VulkanGetProc & getProc,VkInstance inst,VkPhysicalDevice physDev,uint32_t physDeviceVersion,skgpu::VulkanExtensions * extensions,VkPhysicalDeviceFeatures2 * features,bool isProtected)450*c8dee2aaSAndroid Build Coastguard Worker static bool setup_features(const skgpu::VulkanGetProc& getProc, VkInstance inst,
451*c8dee2aaSAndroid Build Coastguard Worker                            VkPhysicalDevice physDev, uint32_t physDeviceVersion,
452*c8dee2aaSAndroid Build Coastguard Worker                            skgpu::VulkanExtensions* extensions, VkPhysicalDeviceFeatures2* features,
453*c8dee2aaSAndroid Build Coastguard Worker                            bool isProtected) {
454*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(physDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
455*c8dee2aaSAndroid Build Coastguard Worker              extensions->hasExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 1));
456*c8dee2aaSAndroid Build Coastguard Worker 
457*c8dee2aaSAndroid Build Coastguard Worker     // Setup all extension feature structs we may want to use.
458*c8dee2aaSAndroid Build Coastguard Worker     void** tailPNext = &features->pNext;
459*c8dee2aaSAndroid Build Coastguard Worker 
460*c8dee2aaSAndroid Build Coastguard Worker     // If |isProtected| is given, attach that first
461*c8dee2aaSAndroid Build Coastguard Worker     VkPhysicalDeviceProtectedMemoryFeatures* protectedMemoryFeatures = nullptr;
462*c8dee2aaSAndroid Build Coastguard Worker     if (isProtected) {
463*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(physDeviceVersion >= VK_MAKE_VERSION(1, 1, 0));
464*c8dee2aaSAndroid Build Coastguard Worker         protectedMemoryFeatures =
465*c8dee2aaSAndroid Build Coastguard Worker           (VkPhysicalDeviceProtectedMemoryFeatures*)sk_malloc_throw(
466*c8dee2aaSAndroid Build Coastguard Worker               sizeof(VkPhysicalDeviceProtectedMemoryFeatures));
467*c8dee2aaSAndroid Build Coastguard Worker         protectedMemoryFeatures->sType =
468*c8dee2aaSAndroid Build Coastguard Worker           VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES;
469*c8dee2aaSAndroid Build Coastguard Worker         protectedMemoryFeatures->pNext = nullptr;
470*c8dee2aaSAndroid Build Coastguard Worker         *tailPNext = protectedMemoryFeatures;
471*c8dee2aaSAndroid Build Coastguard Worker         tailPNext = &protectedMemoryFeatures->pNext;
472*c8dee2aaSAndroid Build Coastguard Worker     }
473*c8dee2aaSAndroid Build Coastguard Worker 
474*c8dee2aaSAndroid Build Coastguard Worker     VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT* blend = nullptr;
475*c8dee2aaSAndroid Build Coastguard Worker     if (extensions->hasExtension(VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME, 2)) {
476*c8dee2aaSAndroid Build Coastguard Worker         blend = (VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT*) sk_malloc_throw(
477*c8dee2aaSAndroid Build Coastguard Worker                 sizeof(VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT));
478*c8dee2aaSAndroid Build Coastguard Worker         blend->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT;
479*c8dee2aaSAndroid Build Coastguard Worker         blend->pNext = nullptr;
480*c8dee2aaSAndroid Build Coastguard Worker         *tailPNext = blend;
481*c8dee2aaSAndroid Build Coastguard Worker         tailPNext = &blend->pNext;
482*c8dee2aaSAndroid Build Coastguard Worker     }
483*c8dee2aaSAndroid Build Coastguard Worker 
484*c8dee2aaSAndroid Build Coastguard Worker     VkPhysicalDeviceSamplerYcbcrConversionFeatures* ycbcrFeature = nullptr;
485*c8dee2aaSAndroid Build Coastguard Worker     if (physDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
486*c8dee2aaSAndroid Build Coastguard Worker         extensions->hasExtension(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME, 1)) {
487*c8dee2aaSAndroid Build Coastguard Worker         ycbcrFeature = (VkPhysicalDeviceSamplerYcbcrConversionFeatures*) sk_malloc_throw(
488*c8dee2aaSAndroid Build Coastguard Worker                 sizeof(VkPhysicalDeviceSamplerYcbcrConversionFeatures));
489*c8dee2aaSAndroid Build Coastguard Worker         ycbcrFeature->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES;
490*c8dee2aaSAndroid Build Coastguard Worker         ycbcrFeature->pNext = nullptr;
491*c8dee2aaSAndroid Build Coastguard Worker         ycbcrFeature->samplerYcbcrConversion = VK_TRUE;
492*c8dee2aaSAndroid Build Coastguard Worker         *tailPNext = ycbcrFeature;
493*c8dee2aaSAndroid Build Coastguard Worker         tailPNext = &ycbcrFeature->pNext;
494*c8dee2aaSAndroid Build Coastguard Worker     }
495*c8dee2aaSAndroid Build Coastguard Worker 
496*c8dee2aaSAndroid Build Coastguard Worker     if (physDeviceVersion >= VK_MAKE_VERSION(1, 1, 0)) {
497*c8dee2aaSAndroid Build Coastguard Worker         ACQUIRE_VK_PROC_LOCAL(GetPhysicalDeviceFeatures2, inst, VK_NULL_HANDLE);
498*c8dee2aaSAndroid Build Coastguard Worker         grVkGetPhysicalDeviceFeatures2(physDev, features);
499*c8dee2aaSAndroid Build Coastguard Worker     } else {
500*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(extensions->hasExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
501*c8dee2aaSAndroid Build Coastguard Worker                                           1));
502*c8dee2aaSAndroid Build Coastguard Worker         ACQUIRE_VK_PROC_LOCAL(GetPhysicalDeviceFeatures2KHR, inst, VK_NULL_HANDLE);
503*c8dee2aaSAndroid Build Coastguard Worker         grVkGetPhysicalDeviceFeatures2KHR(physDev, features);
504*c8dee2aaSAndroid Build Coastguard Worker     }
505*c8dee2aaSAndroid Build Coastguard Worker 
506*c8dee2aaSAndroid Build Coastguard Worker     if (isProtected) {
507*c8dee2aaSAndroid Build Coastguard Worker         if (!protectedMemoryFeatures->protectedMemory) {
508*c8dee2aaSAndroid Build Coastguard Worker             return false;
509*c8dee2aaSAndroid Build Coastguard Worker         }
510*c8dee2aaSAndroid Build Coastguard Worker     }
511*c8dee2aaSAndroid Build Coastguard Worker     return true;
512*c8dee2aaSAndroid Build Coastguard Worker     // If we want to disable any extension features do so here.
513*c8dee2aaSAndroid Build Coastguard Worker }
514*c8dee2aaSAndroid Build Coastguard Worker 
CreateVkBackendContext(PFN_vkGetInstanceProcAddr getInstProc,skgpu::VulkanBackendContext * ctx,skgpu::VulkanExtensions * extensions,VkPhysicalDeviceFeatures2 * features,VkDebugReportCallbackEXT * debugCallback,uint32_t * presentQueueIndexPtr,const CanPresentFn & canPresent,bool isProtected)515*c8dee2aaSAndroid Build Coastguard Worker bool CreateVkBackendContext(PFN_vkGetInstanceProcAddr getInstProc,
516*c8dee2aaSAndroid Build Coastguard Worker                             skgpu::VulkanBackendContext* ctx,
517*c8dee2aaSAndroid Build Coastguard Worker                             skgpu::VulkanExtensions* extensions,
518*c8dee2aaSAndroid Build Coastguard Worker                             VkPhysicalDeviceFeatures2* features,
519*c8dee2aaSAndroid Build Coastguard Worker                             VkDebugReportCallbackEXT* debugCallback,
520*c8dee2aaSAndroid Build Coastguard Worker                             uint32_t* presentQueueIndexPtr,
521*c8dee2aaSAndroid Build Coastguard Worker                             const CanPresentFn& canPresent,
522*c8dee2aaSAndroid Build Coastguard Worker                             bool isProtected) {
523*c8dee2aaSAndroid Build Coastguard Worker     VkResult err;
524*c8dee2aaSAndroid Build Coastguard Worker 
525*c8dee2aaSAndroid Build Coastguard Worker     ACQUIRE_VK_INST_PROC_NOCHECK(EnumerateInstanceVersion, VK_NULL_HANDLE);
526*c8dee2aaSAndroid Build Coastguard Worker     uint32_t instanceVersion = 0;
527*c8dee2aaSAndroid Build Coastguard Worker     if (!grVkEnumerateInstanceVersion) {
528*c8dee2aaSAndroid Build Coastguard Worker         instanceVersion = VK_MAKE_VERSION(1, 0, 0);
529*c8dee2aaSAndroid Build Coastguard Worker     } else {
530*c8dee2aaSAndroid Build Coastguard Worker         err = grVkEnumerateInstanceVersion(&instanceVersion);
531*c8dee2aaSAndroid Build Coastguard Worker         if (err) {
532*c8dee2aaSAndroid Build Coastguard Worker             SkDebugf("failed to enumerate instance version. Err: %d\n", err);
533*c8dee2aaSAndroid Build Coastguard Worker             return false;
534*c8dee2aaSAndroid Build Coastguard Worker         }
535*c8dee2aaSAndroid Build Coastguard Worker     }
536*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(instanceVersion >= VK_MAKE_VERSION(1, 0, 0));
537*c8dee2aaSAndroid Build Coastguard Worker     if (isProtected && instanceVersion < VK_MAKE_VERSION(1, 1, 0)) {
538*c8dee2aaSAndroid Build Coastguard Worker         SkDebugf("protected requires vk instance version 1.1\n");
539*c8dee2aaSAndroid Build Coastguard Worker         return false;
540*c8dee2aaSAndroid Build Coastguard Worker     }
541*c8dee2aaSAndroid Build Coastguard Worker 
542*c8dee2aaSAndroid Build Coastguard Worker     uint32_t apiVersion = VK_MAKE_VERSION(1, 0, 0);
543*c8dee2aaSAndroid Build Coastguard Worker     if (instanceVersion >= VK_MAKE_VERSION(1, 1, 0)) {
544*c8dee2aaSAndroid Build Coastguard Worker         // If the instance version is 1.0 we must have the apiVersion also be 1.0. However, if the
545*c8dee2aaSAndroid Build Coastguard Worker         // instance version is 1.1 or higher, we can set the apiVersion to be whatever the highest
546*c8dee2aaSAndroid Build Coastguard Worker         // api we may use in skia (technically it can be arbitrary). So for now we set it to 1.1
547*c8dee2aaSAndroid Build Coastguard Worker         // since that is the highest vulkan version.
548*c8dee2aaSAndroid Build Coastguard Worker         apiVersion = VK_MAKE_VERSION(1, 1, 0);
549*c8dee2aaSAndroid Build Coastguard Worker     }
550*c8dee2aaSAndroid Build Coastguard Worker 
551*c8dee2aaSAndroid Build Coastguard Worker     instanceVersion = std::min(instanceVersion, apiVersion);
552*c8dee2aaSAndroid Build Coastguard Worker 
553*c8dee2aaSAndroid Build Coastguard Worker     STArray<2, VkPhysicalDevice> physDevs;
554*c8dee2aaSAndroid Build Coastguard Worker     VkDevice device;
555*c8dee2aaSAndroid Build Coastguard Worker     VkInstance inst = VK_NULL_HANDLE;
556*c8dee2aaSAndroid Build Coastguard Worker 
557*c8dee2aaSAndroid Build Coastguard Worker     const VkApplicationInfo app_info = {
558*c8dee2aaSAndroid Build Coastguard Worker         VK_STRUCTURE_TYPE_APPLICATION_INFO, // sType
559*c8dee2aaSAndroid Build Coastguard Worker         nullptr,                            // pNext
560*c8dee2aaSAndroid Build Coastguard Worker         "vktest",                           // pApplicationName
561*c8dee2aaSAndroid Build Coastguard Worker         0,                                  // applicationVersion
562*c8dee2aaSAndroid Build Coastguard Worker         "vktest",                           // pEngineName
563*c8dee2aaSAndroid Build Coastguard Worker         0,                                  // engineVerison
564*c8dee2aaSAndroid Build Coastguard Worker         apiVersion,                         // apiVersion
565*c8dee2aaSAndroid Build Coastguard Worker     };
566*c8dee2aaSAndroid Build Coastguard Worker 
567*c8dee2aaSAndroid Build Coastguard Worker     TArray<VkLayerProperties> instanceLayers;
568*c8dee2aaSAndroid Build Coastguard Worker     TArray<VkExtensionProperties> instanceExtensions;
569*c8dee2aaSAndroid Build Coastguard Worker 
570*c8dee2aaSAndroid Build Coastguard Worker     if (!init_instance_extensions_and_layers(getInstProc, instanceVersion,
571*c8dee2aaSAndroid Build Coastguard Worker                                              &instanceExtensions,
572*c8dee2aaSAndroid Build Coastguard Worker                                              &instanceLayers)) {
573*c8dee2aaSAndroid Build Coastguard Worker         return false;
574*c8dee2aaSAndroid Build Coastguard Worker     }
575*c8dee2aaSAndroid Build Coastguard Worker 
576*c8dee2aaSAndroid Build Coastguard Worker     TArray<const char*> instanceLayerNames;
577*c8dee2aaSAndroid Build Coastguard Worker     TArray<const char*> instanceExtensionNames;
578*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < instanceLayers.size(); ++i) {
579*c8dee2aaSAndroid Build Coastguard Worker         instanceLayerNames.push_back(instanceLayers[i].layerName);
580*c8dee2aaSAndroid Build Coastguard Worker     }
581*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < instanceExtensions.size(); ++i) {
582*c8dee2aaSAndroid Build Coastguard Worker         instanceExtensionNames.push_back(instanceExtensions[i].extensionName);
583*c8dee2aaSAndroid Build Coastguard Worker     }
584*c8dee2aaSAndroid Build Coastguard Worker 
585*c8dee2aaSAndroid Build Coastguard Worker     const VkInstanceCreateInfo instance_create = {
586*c8dee2aaSAndroid Build Coastguard Worker         VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,    // sType
587*c8dee2aaSAndroid Build Coastguard Worker         nullptr,                                   // pNext
588*c8dee2aaSAndroid Build Coastguard Worker         0,                                         // flags
589*c8dee2aaSAndroid Build Coastguard Worker         &app_info,                                 // pApplicationInfo
590*c8dee2aaSAndroid Build Coastguard Worker         (uint32_t) instanceLayerNames.size(),      // enabledLayerNameCount
591*c8dee2aaSAndroid Build Coastguard Worker         instanceLayerNames.begin(),                // ppEnabledLayerNames
592*c8dee2aaSAndroid Build Coastguard Worker         (uint32_t) instanceExtensionNames.size(),  // enabledExtensionNameCount
593*c8dee2aaSAndroid Build Coastguard Worker         instanceExtensionNames.begin(),            // ppEnabledExtensionNames
594*c8dee2aaSAndroid Build Coastguard Worker     };
595*c8dee2aaSAndroid Build Coastguard Worker 
596*c8dee2aaSAndroid Build Coastguard Worker     bool hasDebugExtension = false;
597*c8dee2aaSAndroid Build Coastguard Worker 
598*c8dee2aaSAndroid Build Coastguard Worker     ACQUIRE_VK_INST_PROC(CreateInstance, VK_NULL_HANDLE);
599*c8dee2aaSAndroid Build Coastguard Worker     err = grVkCreateInstance(&instance_create, nullptr, &inst);
600*c8dee2aaSAndroid Build Coastguard Worker     if (err < 0) {
601*c8dee2aaSAndroid Build Coastguard Worker         SkDebugf("vkCreateInstance failed: %d\n", err);
602*c8dee2aaSAndroid Build Coastguard Worker         return false;
603*c8dee2aaSAndroid Build Coastguard Worker     }
604*c8dee2aaSAndroid Build Coastguard Worker 
605*c8dee2aaSAndroid Build Coastguard Worker     ACQUIRE_VK_INST_PROC(GetDeviceProcAddr, inst);
606*c8dee2aaSAndroid Build Coastguard Worker     auto getProc = [getInstProc, grVkGetDeviceProcAddr](const char* proc_name,
607*c8dee2aaSAndroid Build Coastguard Worker                                                         VkInstance instance, VkDevice device) {
608*c8dee2aaSAndroid Build Coastguard Worker         if (device != VK_NULL_HANDLE) {
609*c8dee2aaSAndroid Build Coastguard Worker             return grVkGetDeviceProcAddr(device, proc_name);
610*c8dee2aaSAndroid Build Coastguard Worker         }
611*c8dee2aaSAndroid Build Coastguard Worker         return getInstProc(instance, proc_name);
612*c8dee2aaSAndroid Build Coastguard Worker     };
613*c8dee2aaSAndroid Build Coastguard Worker 
614*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_ENABLE_VK_LAYERS
615*c8dee2aaSAndroid Build Coastguard Worker     *debugCallback = VK_NULL_HANDLE;
616*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < instanceExtensionNames.size() && !hasDebugExtension; ++i) {
617*c8dee2aaSAndroid Build Coastguard Worker         if (!strcmp(instanceExtensionNames[i], VK_EXT_DEBUG_REPORT_EXTENSION_NAME)) {
618*c8dee2aaSAndroid Build Coastguard Worker             hasDebugExtension = true;
619*c8dee2aaSAndroid Build Coastguard Worker         }
620*c8dee2aaSAndroid Build Coastguard Worker     }
621*c8dee2aaSAndroid Build Coastguard Worker     if (hasDebugExtension) {
622*c8dee2aaSAndroid Build Coastguard Worker         // Setup callback creation information
623*c8dee2aaSAndroid Build Coastguard Worker         VkDebugReportCallbackCreateInfoEXT callbackCreateInfo;
624*c8dee2aaSAndroid Build Coastguard Worker         callbackCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
625*c8dee2aaSAndroid Build Coastguard Worker         callbackCreateInfo.pNext = nullptr;
626*c8dee2aaSAndroid Build Coastguard Worker         callbackCreateInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT |
627*c8dee2aaSAndroid Build Coastguard Worker                                    VK_DEBUG_REPORT_WARNING_BIT_EXT |
628*c8dee2aaSAndroid Build Coastguard Worker                                    // VK_DEBUG_REPORT_INFORMATION_BIT_EXT |
629*c8dee2aaSAndroid Build Coastguard Worker                                    // VK_DEBUG_REPORT_DEBUG_BIT_EXT |
630*c8dee2aaSAndroid Build Coastguard Worker                                    VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
631*c8dee2aaSAndroid Build Coastguard Worker         callbackCreateInfo.pfnCallback = &DebugReportCallback;
632*c8dee2aaSAndroid Build Coastguard Worker         callbackCreateInfo.pUserData = nullptr;
633*c8dee2aaSAndroid Build Coastguard Worker 
634*c8dee2aaSAndroid Build Coastguard Worker         ACQUIRE_VK_PROC(CreateDebugReportCallbackEXT, inst, VK_NULL_HANDLE);
635*c8dee2aaSAndroid Build Coastguard Worker         // Register the callback
636*c8dee2aaSAndroid Build Coastguard Worker         grVkCreateDebugReportCallbackEXT(inst, &callbackCreateInfo, nullptr, debugCallback);
637*c8dee2aaSAndroid Build Coastguard Worker     }
638*c8dee2aaSAndroid Build Coastguard Worker #endif
639*c8dee2aaSAndroid Build Coastguard Worker 
640*c8dee2aaSAndroid Build Coastguard Worker     ACQUIRE_VK_PROC(EnumeratePhysicalDevices, inst, VK_NULL_HANDLE);
641*c8dee2aaSAndroid Build Coastguard Worker     ACQUIRE_VK_PROC(GetPhysicalDeviceProperties, inst, VK_NULL_HANDLE);
642*c8dee2aaSAndroid Build Coastguard Worker     ACQUIRE_VK_PROC(GetPhysicalDeviceQueueFamilyProperties, inst, VK_NULL_HANDLE);
643*c8dee2aaSAndroid Build Coastguard Worker     ACQUIRE_VK_PROC(GetPhysicalDeviceFeatures, inst, VK_NULL_HANDLE);
644*c8dee2aaSAndroid Build Coastguard Worker     ACQUIRE_VK_PROC(CreateDevice, inst, VK_NULL_HANDLE);
645*c8dee2aaSAndroid Build Coastguard Worker     ACQUIRE_VK_PROC(GetDeviceQueue, inst, VK_NULL_HANDLE);
646*c8dee2aaSAndroid Build Coastguard Worker     ACQUIRE_VK_PROC(DeviceWaitIdle, inst, VK_NULL_HANDLE);
647*c8dee2aaSAndroid Build Coastguard Worker     ACQUIRE_VK_PROC(DestroyDevice, inst, VK_NULL_HANDLE);
648*c8dee2aaSAndroid Build Coastguard Worker 
649*c8dee2aaSAndroid Build Coastguard Worker     uint32_t gpuCount;
650*c8dee2aaSAndroid Build Coastguard Worker     err = grVkEnumeratePhysicalDevices(inst, &gpuCount, nullptr);
651*c8dee2aaSAndroid Build Coastguard Worker     if (err) {
652*c8dee2aaSAndroid Build Coastguard Worker         SkDebugf("vkEnumeratePhysicalDevices failed: %d\n", err);
653*c8dee2aaSAndroid Build Coastguard Worker         destroy_instance(getInstProc, inst, debugCallback, hasDebugExtension);
654*c8dee2aaSAndroid Build Coastguard Worker         return false;
655*c8dee2aaSAndroid Build Coastguard Worker     }
656*c8dee2aaSAndroid Build Coastguard Worker     if (!gpuCount) {
657*c8dee2aaSAndroid Build Coastguard Worker         SkDebugf("vkEnumeratePhysicalDevices returned no supported devices.\n");
658*c8dee2aaSAndroid Build Coastguard Worker         destroy_instance(getInstProc, inst, debugCallback, hasDebugExtension);
659*c8dee2aaSAndroid Build Coastguard Worker         return false;
660*c8dee2aaSAndroid Build Coastguard Worker     }
661*c8dee2aaSAndroid Build Coastguard Worker     // Allocate enough storage for all available physical devices. We should be able to just ask for
662*c8dee2aaSAndroid Build Coastguard Worker     // the first one, but a bug in RenderDoc (https://github.com/baldurk/renderdoc/issues/2766)
663*c8dee2aaSAndroid Build Coastguard Worker     // will smash the stack if we do that.
664*c8dee2aaSAndroid Build Coastguard Worker     physDevs.resize(gpuCount);
665*c8dee2aaSAndroid Build Coastguard Worker     err = grVkEnumeratePhysicalDevices(inst, &gpuCount, physDevs.data());
666*c8dee2aaSAndroid Build Coastguard Worker     if (err) {
667*c8dee2aaSAndroid Build Coastguard Worker         SkDebugf("vkEnumeratePhysicalDevices failed: %d\n", err);
668*c8dee2aaSAndroid Build Coastguard Worker         destroy_instance(getInstProc, inst, debugCallback, hasDebugExtension);
669*c8dee2aaSAndroid Build Coastguard Worker         return false;
670*c8dee2aaSAndroid Build Coastguard Worker     }
671*c8dee2aaSAndroid Build Coastguard Worker     // We just use the first physical device.
672*c8dee2aaSAndroid Build Coastguard Worker     // TODO: find best match for our needs
673*c8dee2aaSAndroid Build Coastguard Worker     VkPhysicalDevice physDev = physDevs.front();
674*c8dee2aaSAndroid Build Coastguard Worker 
675*c8dee2aaSAndroid Build Coastguard Worker     VkPhysicalDeviceProperties physDeviceProperties;
676*c8dee2aaSAndroid Build Coastguard Worker     grVkGetPhysicalDeviceProperties(physDev, &physDeviceProperties);
677*c8dee2aaSAndroid Build Coastguard Worker     uint32_t physDeviceVersion = std::min(physDeviceProperties.apiVersion, apiVersion);
678*c8dee2aaSAndroid Build Coastguard Worker 
679*c8dee2aaSAndroid Build Coastguard Worker     if (isProtected && physDeviceVersion < VK_MAKE_VERSION(1, 1, 0)) {
680*c8dee2aaSAndroid Build Coastguard Worker         SkDebugf("protected requires vk physical device version 1.1\n");
681*c8dee2aaSAndroid Build Coastguard Worker         destroy_instance(getInstProc, inst, debugCallback, hasDebugExtension);
682*c8dee2aaSAndroid Build Coastguard Worker         return false;
683*c8dee2aaSAndroid Build Coastguard Worker     }
684*c8dee2aaSAndroid Build Coastguard Worker 
685*c8dee2aaSAndroid Build Coastguard Worker     // query to get the initial queue props size
686*c8dee2aaSAndroid Build Coastguard Worker     uint32_t queueCount;
687*c8dee2aaSAndroid Build Coastguard Worker     grVkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, nullptr);
688*c8dee2aaSAndroid Build Coastguard Worker     if (!queueCount) {
689*c8dee2aaSAndroid Build Coastguard Worker         SkDebugf("vkGetPhysicalDeviceQueueFamilyProperties returned no queues.\n");
690*c8dee2aaSAndroid Build Coastguard Worker         destroy_instance(getInstProc, inst, debugCallback, hasDebugExtension);
691*c8dee2aaSAndroid Build Coastguard Worker         return false;
692*c8dee2aaSAndroid Build Coastguard Worker     }
693*c8dee2aaSAndroid Build Coastguard Worker 
694*c8dee2aaSAndroid Build Coastguard Worker     SkAutoMalloc queuePropsAlloc(queueCount * sizeof(VkQueueFamilyProperties));
695*c8dee2aaSAndroid Build Coastguard Worker     // now get the actual queue props
696*c8dee2aaSAndroid Build Coastguard Worker     VkQueueFamilyProperties* queueProps = (VkQueueFamilyProperties*)queuePropsAlloc.get();
697*c8dee2aaSAndroid Build Coastguard Worker 
698*c8dee2aaSAndroid Build Coastguard Worker     grVkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, queueProps);
699*c8dee2aaSAndroid Build Coastguard Worker 
700*c8dee2aaSAndroid Build Coastguard Worker     // iterate to find the graphics queue
701*c8dee2aaSAndroid Build Coastguard Worker     uint32_t graphicsQueueIndex = queueCount;
702*c8dee2aaSAndroid Build Coastguard Worker     for (uint32_t i = 0; i < queueCount; i++) {
703*c8dee2aaSAndroid Build Coastguard Worker         if (queueProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
704*c8dee2aaSAndroid Build Coastguard Worker             graphicsQueueIndex = i;
705*c8dee2aaSAndroid Build Coastguard Worker             break;
706*c8dee2aaSAndroid Build Coastguard Worker         }
707*c8dee2aaSAndroid Build Coastguard Worker     }
708*c8dee2aaSAndroid Build Coastguard Worker     if (graphicsQueueIndex == queueCount) {
709*c8dee2aaSAndroid Build Coastguard Worker         SkDebugf("Could not find any supported graphics queues.\n");
710*c8dee2aaSAndroid Build Coastguard Worker         destroy_instance(getInstProc, inst, debugCallback, hasDebugExtension);
711*c8dee2aaSAndroid Build Coastguard Worker         return false;
712*c8dee2aaSAndroid Build Coastguard Worker     }
713*c8dee2aaSAndroid Build Coastguard Worker 
714*c8dee2aaSAndroid Build Coastguard Worker     // iterate to find the present queue, if needed
715*c8dee2aaSAndroid Build Coastguard Worker     uint32_t presentQueueIndex = queueCount;
716*c8dee2aaSAndroid Build Coastguard Worker     if (presentQueueIndexPtr && canPresent) {
717*c8dee2aaSAndroid Build Coastguard Worker         for (uint32_t i = 0; i < queueCount; i++) {
718*c8dee2aaSAndroid Build Coastguard Worker             if (canPresent(inst, physDev, i)) {
719*c8dee2aaSAndroid Build Coastguard Worker                 presentQueueIndex = i;
720*c8dee2aaSAndroid Build Coastguard Worker                 break;
721*c8dee2aaSAndroid Build Coastguard Worker             }
722*c8dee2aaSAndroid Build Coastguard Worker         }
723*c8dee2aaSAndroid Build Coastguard Worker         if (presentQueueIndex == queueCount) {
724*c8dee2aaSAndroid Build Coastguard Worker             SkDebugf("Could not find any supported present queues.\n");
725*c8dee2aaSAndroid Build Coastguard Worker             destroy_instance(getInstProc, inst, debugCallback, hasDebugExtension);
726*c8dee2aaSAndroid Build Coastguard Worker             return false;
727*c8dee2aaSAndroid Build Coastguard Worker         }
728*c8dee2aaSAndroid Build Coastguard Worker         *presentQueueIndexPtr = presentQueueIndex;
729*c8dee2aaSAndroid Build Coastguard Worker     } else {
730*c8dee2aaSAndroid Build Coastguard Worker         // Just setting this so we end up make a single queue for graphics since there was no
731*c8dee2aaSAndroid Build Coastguard Worker         // request for a present queue.
732*c8dee2aaSAndroid Build Coastguard Worker         presentQueueIndex = graphicsQueueIndex;
733*c8dee2aaSAndroid Build Coastguard Worker     }
734*c8dee2aaSAndroid Build Coastguard Worker 
735*c8dee2aaSAndroid Build Coastguard Worker     TArray<VkLayerProperties> deviceLayers;
736*c8dee2aaSAndroid Build Coastguard Worker     TArray<VkExtensionProperties> deviceExtensions;
737*c8dee2aaSAndroid Build Coastguard Worker     if (!init_device_extensions_and_layers(getProc, physDeviceVersion,
738*c8dee2aaSAndroid Build Coastguard Worker                                            inst, physDev,
739*c8dee2aaSAndroid Build Coastguard Worker                                            &deviceExtensions,
740*c8dee2aaSAndroid Build Coastguard Worker                                            &deviceLayers)) {
741*c8dee2aaSAndroid Build Coastguard Worker         destroy_instance(getInstProc, inst, debugCallback, hasDebugExtension);
742*c8dee2aaSAndroid Build Coastguard Worker         return false;
743*c8dee2aaSAndroid Build Coastguard Worker     }
744*c8dee2aaSAndroid Build Coastguard Worker 
745*c8dee2aaSAndroid Build Coastguard Worker     TArray<const char*> deviceLayerNames;
746*c8dee2aaSAndroid Build Coastguard Worker     TArray<const char*> deviceExtensionNames;
747*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < deviceLayers.size(); ++i) {
748*c8dee2aaSAndroid Build Coastguard Worker         deviceLayerNames.push_back(deviceLayers[i].layerName);
749*c8dee2aaSAndroid Build Coastguard Worker     }
750*c8dee2aaSAndroid Build Coastguard Worker 
751*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < deviceExtensions.size(); ++i) {
752*c8dee2aaSAndroid Build Coastguard Worker         deviceExtensionNames.push_back(deviceExtensions[i].extensionName);
753*c8dee2aaSAndroid Build Coastguard Worker     }
754*c8dee2aaSAndroid Build Coastguard Worker 
755*c8dee2aaSAndroid Build Coastguard Worker     extensions->init(getProc, inst, physDev,
756*c8dee2aaSAndroid Build Coastguard Worker                      (uint32_t) instanceExtensionNames.size(),
757*c8dee2aaSAndroid Build Coastguard Worker                      instanceExtensionNames.begin(),
758*c8dee2aaSAndroid Build Coastguard Worker                      (uint32_t) deviceExtensionNames.size(),
759*c8dee2aaSAndroid Build Coastguard Worker                      deviceExtensionNames.begin());
760*c8dee2aaSAndroid Build Coastguard Worker 
761*c8dee2aaSAndroid Build Coastguard Worker     memset(features, 0, sizeof(VkPhysicalDeviceFeatures2));
762*c8dee2aaSAndroid Build Coastguard Worker     features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
763*c8dee2aaSAndroid Build Coastguard Worker     features->pNext = nullptr;
764*c8dee2aaSAndroid Build Coastguard Worker 
765*c8dee2aaSAndroid Build Coastguard Worker     VkPhysicalDeviceFeatures* deviceFeatures = &features->features;
766*c8dee2aaSAndroid Build Coastguard Worker     void* pointerToFeatures = nullptr;
767*c8dee2aaSAndroid Build Coastguard Worker     if (physDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
768*c8dee2aaSAndroid Build Coastguard Worker         extensions->hasExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 1)) {
769*c8dee2aaSAndroid Build Coastguard Worker         if (!setup_features(getProc, inst, physDev, physDeviceVersion, extensions, features,
770*c8dee2aaSAndroid Build Coastguard Worker                             isProtected)) {
771*c8dee2aaSAndroid Build Coastguard Worker             destroy_instance(getInstProc, inst, debugCallback, hasDebugExtension);
772*c8dee2aaSAndroid Build Coastguard Worker             return false;
773*c8dee2aaSAndroid Build Coastguard Worker         }
774*c8dee2aaSAndroid Build Coastguard Worker 
775*c8dee2aaSAndroid Build Coastguard Worker         // If we set the pNext of the VkDeviceCreateInfo to our VkPhysicalDeviceFeatures2 struct,
776*c8dee2aaSAndroid Build Coastguard Worker         // the device creation will use that instead of the ppEnabledFeatures.
777*c8dee2aaSAndroid Build Coastguard Worker         pointerToFeatures = features;
778*c8dee2aaSAndroid Build Coastguard Worker     } else {
779*c8dee2aaSAndroid Build Coastguard Worker         grVkGetPhysicalDeviceFeatures(physDev, deviceFeatures);
780*c8dee2aaSAndroid Build Coastguard Worker     }
781*c8dee2aaSAndroid Build Coastguard Worker 
782*c8dee2aaSAndroid Build Coastguard Worker     // this looks like it would slow things down,
783*c8dee2aaSAndroid Build Coastguard Worker     // and we can't depend on it on all platforms
784*c8dee2aaSAndroid Build Coastguard Worker     deviceFeatures->robustBufferAccess = VK_FALSE;
785*c8dee2aaSAndroid Build Coastguard Worker 
786*c8dee2aaSAndroid Build Coastguard Worker     VkDeviceQueueCreateFlags flags = isProtected ? VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT : 0;
787*c8dee2aaSAndroid Build Coastguard Worker     float queuePriorities[1] = { 0.0 };
788*c8dee2aaSAndroid Build Coastguard Worker     // Here we assume no need for swapchain queue
789*c8dee2aaSAndroid Build Coastguard Worker     // If one is needed, the client will need its own setup code
790*c8dee2aaSAndroid Build Coastguard Worker     const VkDeviceQueueCreateInfo queueInfo[2] = {
791*c8dee2aaSAndroid Build Coastguard Worker         {
792*c8dee2aaSAndroid Build Coastguard Worker             VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
793*c8dee2aaSAndroid Build Coastguard Worker             nullptr,                                    // pNext
794*c8dee2aaSAndroid Build Coastguard Worker             flags,                                      // VkDeviceQueueCreateFlags
795*c8dee2aaSAndroid Build Coastguard Worker             graphicsQueueIndex,                         // queueFamilyIndex
796*c8dee2aaSAndroid Build Coastguard Worker             1,                                          // queueCount
797*c8dee2aaSAndroid Build Coastguard Worker             queuePriorities,                            // pQueuePriorities
798*c8dee2aaSAndroid Build Coastguard Worker 
799*c8dee2aaSAndroid Build Coastguard Worker         },
800*c8dee2aaSAndroid Build Coastguard Worker         {
801*c8dee2aaSAndroid Build Coastguard Worker             VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
802*c8dee2aaSAndroid Build Coastguard Worker             nullptr,                                    // pNext
803*c8dee2aaSAndroid Build Coastguard Worker             0,                                          // VkDeviceQueueCreateFlags
804*c8dee2aaSAndroid Build Coastguard Worker             presentQueueIndex,                          // queueFamilyIndex
805*c8dee2aaSAndroid Build Coastguard Worker             1,                                          // queueCount
806*c8dee2aaSAndroid Build Coastguard Worker             queuePriorities,                            // pQueuePriorities
807*c8dee2aaSAndroid Build Coastguard Worker         }
808*c8dee2aaSAndroid Build Coastguard Worker     };
809*c8dee2aaSAndroid Build Coastguard Worker     uint32_t queueInfoCount = (presentQueueIndex != graphicsQueueIndex) ? 2 : 1;
810*c8dee2aaSAndroid Build Coastguard Worker 
811*c8dee2aaSAndroid Build Coastguard Worker     const VkDeviceCreateInfo deviceInfo = {
812*c8dee2aaSAndroid Build Coastguard Worker         VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,        // sType
813*c8dee2aaSAndroid Build Coastguard Worker         pointerToFeatures,                           // pNext
814*c8dee2aaSAndroid Build Coastguard Worker         0,                                           // VkDeviceCreateFlags
815*c8dee2aaSAndroid Build Coastguard Worker         queueInfoCount,                              // queueCreateInfoCount
816*c8dee2aaSAndroid Build Coastguard Worker         queueInfo,                                   // pQueueCreateInfos
817*c8dee2aaSAndroid Build Coastguard Worker         (uint32_t) deviceLayerNames.size(),          // layerCount
818*c8dee2aaSAndroid Build Coastguard Worker         deviceLayerNames.begin(),                    // ppEnabledLayerNames
819*c8dee2aaSAndroid Build Coastguard Worker         (uint32_t) deviceExtensionNames.size(),      // extensionCount
820*c8dee2aaSAndroid Build Coastguard Worker         deviceExtensionNames.begin(),                // ppEnabledExtensionNames
821*c8dee2aaSAndroid Build Coastguard Worker         pointerToFeatures ? nullptr : deviceFeatures // ppEnabledFeatures
822*c8dee2aaSAndroid Build Coastguard Worker     };
823*c8dee2aaSAndroid Build Coastguard Worker 
824*c8dee2aaSAndroid Build Coastguard Worker     {
825*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_ENABLE_SCOPED_LSAN_SUPPRESSIONS)
826*c8dee2aaSAndroid Build Coastguard Worker         // skia:8712
827*c8dee2aaSAndroid Build Coastguard Worker         __lsan::ScopedDisabler lsanDisabler;
828*c8dee2aaSAndroid Build Coastguard Worker #endif
829*c8dee2aaSAndroid Build Coastguard Worker         err = grVkCreateDevice(physDev, &deviceInfo, nullptr, &device);
830*c8dee2aaSAndroid Build Coastguard Worker     }
831*c8dee2aaSAndroid Build Coastguard Worker     if (err) {
832*c8dee2aaSAndroid Build Coastguard Worker         SkDebugf("CreateDevice failed: %d\n", err);
833*c8dee2aaSAndroid Build Coastguard Worker         destroy_instance(getInstProc, inst, debugCallback, hasDebugExtension);
834*c8dee2aaSAndroid Build Coastguard Worker         return false;
835*c8dee2aaSAndroid Build Coastguard Worker     }
836*c8dee2aaSAndroid Build Coastguard Worker 
837*c8dee2aaSAndroid Build Coastguard Worker     VkQueue queue;
838*c8dee2aaSAndroid Build Coastguard Worker     if (isProtected) {
839*c8dee2aaSAndroid Build Coastguard Worker         ACQUIRE_VK_PROC(GetDeviceQueue2, inst, device);
840*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(grVkGetDeviceQueue2 != nullptr);
841*c8dee2aaSAndroid Build Coastguard Worker         VkDeviceQueueInfo2 queue_info2 = {
842*c8dee2aaSAndroid Build Coastguard Worker             VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2,          // sType
843*c8dee2aaSAndroid Build Coastguard Worker             nullptr,                                        // pNext
844*c8dee2aaSAndroid Build Coastguard Worker             VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT,           // flags
845*c8dee2aaSAndroid Build Coastguard Worker             graphicsQueueIndex,                             // queueFamilyIndex
846*c8dee2aaSAndroid Build Coastguard Worker             0                                               // queueIndex
847*c8dee2aaSAndroid Build Coastguard Worker         };
848*c8dee2aaSAndroid Build Coastguard Worker         grVkGetDeviceQueue2(device, &queue_info2, &queue);
849*c8dee2aaSAndroid Build Coastguard Worker     } else {
850*c8dee2aaSAndroid Build Coastguard Worker         grVkGetDeviceQueue(device, graphicsQueueIndex, 0, &queue);
851*c8dee2aaSAndroid Build Coastguard Worker     }
852*c8dee2aaSAndroid Build Coastguard Worker 
853*c8dee2aaSAndroid Build Coastguard Worker     skgpu::VulkanInterface interface = skgpu::VulkanInterface(
854*c8dee2aaSAndroid Build Coastguard Worker             getProc, inst, device, instanceVersion, physDeviceVersion, extensions);
855*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(interface.validate(instanceVersion, physDeviceVersion, extensions));
856*c8dee2aaSAndroid Build Coastguard Worker 
857*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<skgpu::VulkanMemoryAllocator> memoryAllocator = VkTestMemoryAllocator::Make(
858*c8dee2aaSAndroid Build Coastguard Worker             inst, physDev, device, physDeviceVersion, extensions, &interface);
859*c8dee2aaSAndroid Build Coastguard Worker 
860*c8dee2aaSAndroid Build Coastguard Worker     ctx->fInstance = inst;
861*c8dee2aaSAndroid Build Coastguard Worker     ctx->fPhysicalDevice = physDev;
862*c8dee2aaSAndroid Build Coastguard Worker     ctx->fDevice = device;
863*c8dee2aaSAndroid Build Coastguard Worker     ctx->fQueue = queue;
864*c8dee2aaSAndroid Build Coastguard Worker     ctx->fGraphicsQueueIndex = graphicsQueueIndex;
865*c8dee2aaSAndroid Build Coastguard Worker     ctx->fMaxAPIVersion = apiVersion;
866*c8dee2aaSAndroid Build Coastguard Worker     ctx->fVkExtensions = extensions;
867*c8dee2aaSAndroid Build Coastguard Worker     ctx->fDeviceFeatures2 = features;
868*c8dee2aaSAndroid Build Coastguard Worker     ctx->fGetProc = getProc;
869*c8dee2aaSAndroid Build Coastguard Worker     ctx->fProtectedContext = skgpu::Protected(isProtected);
870*c8dee2aaSAndroid Build Coastguard Worker     ctx->fMemoryAllocator = memoryAllocator;
871*c8dee2aaSAndroid Build Coastguard Worker 
872*c8dee2aaSAndroid Build Coastguard Worker     return true;
873*c8dee2aaSAndroid Build Coastguard Worker }
874*c8dee2aaSAndroid Build Coastguard Worker 
FreeVulkanFeaturesStructs(const VkPhysicalDeviceFeatures2 * features)875*c8dee2aaSAndroid Build Coastguard Worker void FreeVulkanFeaturesStructs(const VkPhysicalDeviceFeatures2* features) {
876*c8dee2aaSAndroid Build Coastguard Worker     // All Vulkan structs that could be part of the features chain will start with the
877*c8dee2aaSAndroid Build Coastguard Worker     // structure type followed by the pNext pointer. We cast to the CommonVulkanHeader
878*c8dee2aaSAndroid Build Coastguard Worker     // so we can get access to the pNext for the next struct.
879*c8dee2aaSAndroid Build Coastguard Worker     struct CommonVulkanHeader {
880*c8dee2aaSAndroid Build Coastguard Worker         VkStructureType sType;
881*c8dee2aaSAndroid Build Coastguard Worker         void*           pNext;
882*c8dee2aaSAndroid Build Coastguard Worker     };
883*c8dee2aaSAndroid Build Coastguard Worker 
884*c8dee2aaSAndroid Build Coastguard Worker     void* pNext = features->pNext;
885*c8dee2aaSAndroid Build Coastguard Worker     while (pNext) {
886*c8dee2aaSAndroid Build Coastguard Worker         void* current = pNext;
887*c8dee2aaSAndroid Build Coastguard Worker         pNext = static_cast<CommonVulkanHeader*>(current)->pNext;
888*c8dee2aaSAndroid Build Coastguard Worker         sk_free(current);
889*c8dee2aaSAndroid Build Coastguard Worker     }
890*c8dee2aaSAndroid Build Coastguard Worker }
891*c8dee2aaSAndroid Build Coastguard Worker 
892*c8dee2aaSAndroid Build Coastguard Worker }  // namespace sk_gpu_test
893*c8dee2aaSAndroid Build Coastguard Worker 
894*c8dee2aaSAndroid Build Coastguard Worker #endif
895