1 /* 2 * 3 * Copyright (c) 2014-2018 The Khronos Group Inc. 4 * Copyright (c) 2014-2018 Valve Corporation 5 * Copyright (c) 2014-2018 LunarG, Inc. 6 * Copyright (C) 2015 Google Inc. 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 20 * 21 * Author: Jon Ashburn <jon (at) lunarg.com> 22 * Author: Courtney Goeltzenleuchter <courtney (at) LunarG.com> 23 * Author: Mark Young <marky (at) lunarg.com> 24 * Author: Lenny Komow <lenny (at) lunarg.com> 25 * 26 */ 27 28 #define _GNU_SOURCE 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <stdarg.h> 32 #include <stdbool.h> 33 #include <string.h> 34 #include <stddef.h> 35 36 #include <sys/types.h> 37 #if defined(_WIN32) 38 #include "dirent_on_windows.h" 39 #else // _WIN32 40 #include <dirent.h> 41 #endif // _WIN32 42 #include "vk_loader_platform.h" 43 #include "loader.h" 44 #include "gpa_helper.h" 45 #include "debug_report.h" 46 #include "wsi.h" 47 #include "vulkan/vk_icd.h" 48 #include "cJSON.h" 49 #include "murmurhash.h" 50 51 #if defined(_WIN32) 52 #include <Cfgmgr32.h> 53 #include <initguid.h> 54 #include <Devpkey.h> 55 #endif 56 57 // This is a CMake generated file with #defines for any functions/includes 58 // that it found present. This is currently necessary to properly determine 59 // if secure_getenv or __secure_getenv are present 60 #if !defined(VULKAN_NON_CMAKE_BUILD) 61 #include "loader_cmake_config.h" 62 #endif // !defined(VULKAN_NON_CMAKE_BUILD) 63 64 // Generated file containing all the extension data 65 #include "vk_loader_extensions.c" 66 67 struct loader_struct loader = {0}; 68 // TLS for instance for alloc/free callbacks 69 THREAD_LOCAL_DECL struct loader_instance *tls_instance; 70 71 static size_t loader_platform_combine_path(char *dest, size_t len, ...); 72 73 struct loader_phys_dev_per_icd { 74 uint32_t count; 75 VkPhysicalDevice *phys_devs; 76 struct loader_icd_term *this_icd_term; 77 }; 78 79 enum loader_debug { 80 LOADER_INFO_BIT = 0x01, 81 LOADER_WARN_BIT = 0x02, 82 LOADER_PERF_BIT = 0x04, 83 LOADER_ERROR_BIT = 0x08, 84 LOADER_DEBUG_BIT = 0x10, 85 }; 86 87 uint32_t g_loader_debug = 0; 88 uint32_t g_loader_log_msgs = 0; 89 90 // thread safety lock for accessing global data structures such as "loader" 91 // all entrypoints on the instance chain need to be locked except GPA 92 // additionally CreateDevice and DestroyDevice needs to be locked 93 loader_platform_thread_mutex loader_lock; 94 loader_platform_thread_mutex loader_json_lock; 95 96 LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_init); 97 98 void *loader_instance_heap_alloc(const struct loader_instance *instance, size_t size, VkSystemAllocationScope alloc_scope) { 99 void *pMemory = NULL; 100 #if (DEBUG_DISABLE_APP_ALLOCATORS == 1) 101 { 102 #else 103 if (instance && instance->alloc_callbacks.pfnAllocation) { 104 // These are internal structures, so it's best to align everything to 105 // the largest unit size which is the size of a uint64_t. 106 pMemory = instance->alloc_callbacks.pfnAllocation(instance->alloc_callbacks.pUserData, size, sizeof(uint64_t), alloc_scope); 107 } else { 108 #endif 109 pMemory = malloc(size); 110 } 111 112 return pMemory; 113 } 114 115 void loader_instance_heap_free(const struct loader_instance *instance, void *pMemory) { 116 if (pMemory != NULL) { 117 #if (DEBUG_DISABLE_APP_ALLOCATORS == 1) 118 { 119 #else 120 if (instance && instance->alloc_callbacks.pfnFree) { 121 instance->alloc_callbacks.pfnFree(instance->alloc_callbacks.pUserData, pMemory); 122 } else { 123 #endif 124 free(pMemory); 125 } 126 } 127 } 128 129 void *loader_instance_heap_realloc(const struct loader_instance *instance, void *pMemory, size_t orig_size, size_t size, 130 VkSystemAllocationScope alloc_scope) { 131 void *pNewMem = NULL; 132 if (pMemory == NULL || orig_size == 0) { 133 pNewMem = loader_instance_heap_alloc(instance, size, alloc_scope); 134 } else if (size == 0) { 135 loader_instance_heap_free(instance, pMemory); 136 #if (DEBUG_DISABLE_APP_ALLOCATORS == 1) 137 #else 138 } else if (instance && instance->alloc_callbacks.pfnReallocation) { 139 // These are internal structures, so it's best to align everything to 140 // the largest unit size which is the size of a uint64_t. 141 pNewMem = instance->alloc_callbacks.pfnReallocation(instance->alloc_callbacks.pUserData, pMemory, size, sizeof(uint64_t), 142 alloc_scope); 143 #endif 144 } else { 145 pNewMem = realloc(pMemory, size); 146 } 147 return pNewMem; 148 } 149 150 void *loader_instance_tls_heap_alloc(size_t size) { 151 return loader_instance_heap_alloc(tls_instance, size, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 152 } 153 154 void loader_instance_tls_heap_free(void *pMemory) { loader_instance_heap_free(tls_instance, pMemory); } 155 156 void *loader_device_heap_alloc(const struct loader_device *device, size_t size, VkSystemAllocationScope alloc_scope) { 157 void *pMemory = NULL; 158 #if (DEBUG_DISABLE_APP_ALLOCATORS == 1) 159 { 160 #else 161 if (device && device->alloc_callbacks.pfnAllocation) { 162 // These are internal structures, so it's best to align everything to 163 // the largest unit size which is the size of a uint64_t. 164 pMemory = device->alloc_callbacks.pfnAllocation(device->alloc_callbacks.pUserData, size, sizeof(uint64_t), alloc_scope); 165 } else { 166 #endif 167 pMemory = malloc(size); 168 } 169 return pMemory; 170 } 171 172 void loader_device_heap_free(const struct loader_device *device, void *pMemory) { 173 if (pMemory != NULL) { 174 #if (DEBUG_DISABLE_APP_ALLOCATORS == 1) 175 { 176 #else 177 if (device && device->alloc_callbacks.pfnFree) { 178 device->alloc_callbacks.pfnFree(device->alloc_callbacks.pUserData, pMemory); 179 } else { 180 #endif 181 free(pMemory); 182 } 183 } 184 } 185 186 void *loader_device_heap_realloc(const struct loader_device *device, void *pMemory, size_t orig_size, size_t size, 187 VkSystemAllocationScope alloc_scope) { 188 void *pNewMem = NULL; 189 if (pMemory == NULL || orig_size == 0) { 190 pNewMem = loader_device_heap_alloc(device, size, alloc_scope); 191 } else if (size == 0) { 192 loader_device_heap_free(device, pMemory); 193 #if (DEBUG_DISABLE_APP_ALLOCATORS == 1) 194 #else 195 } else if (device && device->alloc_callbacks.pfnReallocation) { 196 // These are internal structures, so it's best to align everything to 197 // the largest unit size which is the size of a uint64_t. 198 pNewMem = device->alloc_callbacks.pfnReallocation(device->alloc_callbacks.pUserData, pMemory, size, sizeof(uint64_t), 199 alloc_scope); 200 #endif 201 } else { 202 pNewMem = realloc(pMemory, size); 203 } 204 return pNewMem; 205 } 206 207 // Environment variables 208 #if defined(__linux__) 209 210 static inline char *loader_getenv(const char *name, const struct loader_instance *inst) { 211 // No allocation of memory necessary for Linux, but we should at least touch 212 // the inst pointer to get rid of compiler warnings. 213 (void)inst; 214 return getenv(name); 215 } 216 217 static inline char *loader_secure_getenv(const char *name, const struct loader_instance *inst) { 218 // No allocation of memory necessary for Linux, but we should at least touch 219 // the inst pointer to get rid of compiler warnings. 220 (void)inst; 221 222 #ifdef HAVE_SECURE_GETENV 223 return secure_getenv(name); 224 #elif defined(HAVE___SECURE_GETENV) 225 return __secure_getenv(name); 226 #else 227 #pragma message( \ 228 "Warning: Falling back to non-secure getenv for environmental lookups! Consider" \ 229 " updating to a different libc.") 230 return loader_getenv(name, inst); 231 #endif 232 } 233 234 static inline void loader_free_getenv(char *val, const struct loader_instance *inst) { 235 // No freeing of memory necessary for Linux, but we should at least touch 236 // the val and inst pointers to get rid of compiler warnings. 237 (void)val; 238 (void)inst; 239 } 240 241 #elif defined(WIN32) 242 243 static inline char *loader_getenv(const char *name, const struct loader_instance *inst) { 244 char *retVal; 245 DWORD valSize; 246 247 valSize = GetEnvironmentVariableA(name, NULL, 0); 248 249 // valSize DOES include the null terminator, so for any set variable 250 // will always be at least 1. If it's 0, the variable wasn't set. 251 if (valSize == 0) return NULL; 252 253 // Allocate the space necessary for the registry entry 254 if (NULL != inst && NULL != inst->alloc_callbacks.pfnAllocation) { 255 retVal = (char *)inst->alloc_callbacks.pfnAllocation(inst->alloc_callbacks.pUserData, valSize, sizeof(char *), 256 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 257 } else { 258 retVal = (char *)malloc(valSize); 259 } 260 261 if (NULL != retVal) { 262 GetEnvironmentVariableA(name, retVal, valSize); 263 } 264 265 return retVal; 266 } 267 268 static inline char *loader_secure_getenv(const char *name, const struct loader_instance *inst) { 269 // No secure version for Windows as far as I know 270 return loader_getenv(name, inst); 271 } 272 273 static inline void loader_free_getenv(char *val, const struct loader_instance *inst) { 274 if (NULL != inst && NULL != inst->alloc_callbacks.pfnFree) { 275 inst->alloc_callbacks.pfnFree(inst->alloc_callbacks.pUserData, val); 276 } else { 277 free((void *)val); 278 } 279 } 280 281 #else 282 283 static inline char *loader_getenv(const char *name, const struct loader_instance *inst) { 284 // stub func 285 (void)inst; 286 (void)name; 287 return NULL; 288 } 289 static inline void loader_free_getenv(char *val, const struct loader_instance *inst) { 290 // stub func 291 (void)val; 292 (void)inst; 293 } 294 295 #endif 296 297 void loader_log(const struct loader_instance *inst, VkFlags msg_type, int32_t msg_code, const char *format, ...) { 298 char msg[512]; 299 char cmd_line_msg[512]; 300 size_t cmd_line_size = sizeof(cmd_line_msg); 301 va_list ap; 302 int ret; 303 304 va_start(ap, format); 305 ret = vsnprintf(msg, sizeof(msg), format, ap); 306 if ((ret >= (int)sizeof(msg)) || ret < 0) { 307 msg[sizeof(msg) - 1] = '\0'; 308 } 309 va_end(ap); 310 311 if (inst) { 312 util_DebugReportMessage(inst, msg_type, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, (uint64_t)(uintptr_t)inst, 0, msg_code, 313 "loader", msg); 314 } 315 316 if (!(msg_type & g_loader_log_msgs)) { 317 return; 318 } 319 320 cmd_line_msg[0] = '\0'; 321 cmd_line_size -= 1; 322 size_t original_size = cmd_line_size; 323 324 va_start(ap, format); 325 if ((msg_type & LOADER_INFO_BIT) != 0) { 326 strncat(cmd_line_msg, "INFO", cmd_line_size); 327 cmd_line_size -= 4; 328 } 329 if ((msg_type & LOADER_WARN_BIT) != 0) { 330 if (cmd_line_size != original_size) { 331 strncat(cmd_line_msg, " | ", cmd_line_size); 332 cmd_line_size -= 3; 333 } 334 strncat(cmd_line_msg, "WARNING", cmd_line_size); 335 cmd_line_size -= 7; 336 } 337 if ((msg_type & LOADER_PERF_BIT) != 0) { 338 if (cmd_line_size != original_size) { 339 strncat(cmd_line_msg, " | ", cmd_line_size); 340 cmd_line_size -= 3; 341 } 342 strncat(cmd_line_msg, "PERF", cmd_line_size); 343 cmd_line_size -= 4; 344 } 345 if ((msg_type & LOADER_ERROR_BIT) != 0) { 346 if (cmd_line_size != original_size) { 347 strncat(cmd_line_msg, " | ", cmd_line_size); 348 cmd_line_size -= 3; 349 } 350 strncat(cmd_line_msg, "ERROR", cmd_line_size); 351 cmd_line_size -= 5; 352 } 353 if ((msg_type & LOADER_DEBUG_BIT) != 0) { 354 if (cmd_line_size != original_size) { 355 strncat(cmd_line_msg, " | ", cmd_line_size); 356 cmd_line_size -= 3; 357 } 358 strncat(cmd_line_msg, "DEBUG", cmd_line_size); 359 cmd_line_size -= 5; 360 } 361 if (cmd_line_size != original_size) { 362 strncat(cmd_line_msg, ": ", cmd_line_size); 363 cmd_line_size -= 2; 364 } 365 366 if (0 < cmd_line_size) { 367 // If the message is too long, trim it down 368 if (strlen(msg) > cmd_line_size) { 369 msg[cmd_line_size - 1] = '\0'; 370 } 371 strncat(cmd_line_msg, msg, cmd_line_size); 372 } else { 373 // Shouldn't get here, but check to make sure if we've already overrun 374 // the string boundary 375 assert(false); 376 } 377 378 #if defined(WIN32) 379 OutputDebugString(cmd_line_msg); 380 OutputDebugString("\n"); 381 #endif 382 383 fputs(cmd_line_msg, stderr); 384 fputc('\n', stderr); 385 } 386 387 VKAPI_ATTR VkResult VKAPI_CALL vkSetInstanceDispatch(VkInstance instance, void *object) { 388 struct loader_instance *inst = loader_get_instance(instance); 389 if (!inst) { 390 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 391 "vkSetInstanceDispatch: Can not retrieve Instance " 392 "dispatch table."); 393 return VK_ERROR_INITIALIZATION_FAILED; 394 } 395 loader_set_dispatch(object, inst->disp); 396 return VK_SUCCESS; 397 } 398 399 VKAPI_ATTR VkResult VKAPI_CALL vkSetDeviceDispatch(VkDevice device, void *object) { 400 struct loader_device *dev; 401 struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev, NULL); 402 403 if (NULL == icd_term) { 404 return VK_ERROR_INITIALIZATION_FAILED; 405 } 406 loader_set_dispatch(object, &dev->loader_dispatch); 407 return VK_SUCCESS; 408 } 409 410 #if defined(_WIN32) 411 412 // Append the JSON path data to the list and allocate/grow the list if it's not large enough. 413 // Function returns true if filename was appended to reg_data list. 414 // Caller should free reg_data. 415 static bool loaderAddJsonEntry(const struct loader_instance *inst, 416 char **reg_data, // list of JSON files 417 PDWORD total_size, // size of reg_data 418 LPCTSTR key_name, // key name - used for debug prints - i.e. VulkanDriverName 419 DWORD key_type, // key data type 420 LPSTR json_path, // JSON string to add to the list reg_data 421 DWORD json_size, // size in bytes of json_path 422 VkResult *result) { 423 if (NULL == *reg_data) { 424 *reg_data = loader_instance_heap_alloc(inst, *total_size, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 425 if (NULL == *reg_data) { 426 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 427 "loaderAddJsonEntry: Failed to allocate space for registry data for key %s", json_path); 428 *result = VK_ERROR_OUT_OF_HOST_MEMORY; 429 return false; 430 } 431 *reg_data[0] = '\0'; 432 } else if (strlen(*reg_data) + json_size + 1 > *total_size) { 433 void *new_ptr = 434 loader_instance_heap_realloc(inst, *reg_data, *total_size, *total_size * 2, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 435 if (NULL == new_ptr) { 436 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 437 "loaderAddJsonEntry: Failed to reallocate space for registry value of size %d for key %s", *total_size * 2, 438 json_path); 439 *result = VK_ERROR_OUT_OF_HOST_MEMORY; 440 return false; 441 } 442 *reg_data = new_ptr; 443 *total_size *= 2; 444 } 445 446 for (char *curr_filename = json_path; curr_filename[0] != '\0'; curr_filename += strlen(curr_filename) + 1) { 447 if (strlen(*reg_data) == 0) { 448 (void)snprintf(*reg_data, json_size + 1, "%s", curr_filename); 449 } else { 450 (void)snprintf(*reg_data + strlen(*reg_data), json_size + 2, "%c%s", PATH_SEPARATOR, curr_filename); 451 } 452 loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, "%s: Located json file \"%s\" from PnP registry: %s", __FUNCTION__, 453 curr_filename, key_name); 454 455 if (key_type == REG_SZ) { 456 break; 457 } 458 } 459 return true; 460 } 461 462 // Find the list of registry files (names VulkanDriverName/VulkanDriverNameWow) in hkr. 463 // 464 // This function looks for filename in given device handle, filename is then added to return list 465 // function return true if filename was appended to reg_data list 466 // If error occures result is updated with failure reason 467 bool loaderGetDeviceRegistryEntry(const struct loader_instance *inst, char **reg_data, PDWORD total_size, DEVINST dev_id, LPCTSTR value_name, VkResult *result) 468 { 469 HKEY hkrKey = INVALID_HANDLE_VALUE; 470 DWORD requiredSize, data_type; 471 char *manifest_path = NULL; 472 bool found = false; 473 474 if (NULL == total_size || NULL == reg_data) { 475 *result = VK_ERROR_INITIALIZATION_FAILED; 476 return false; 477 } 478 479 CONFIGRET status = CM_Open_DevNode_Key(dev_id, KEY_QUERY_VALUE, 0, RegDisposition_OpenExisting, &hkrKey, CM_REGISTRY_SOFTWARE); 480 if (status != CR_SUCCESS) { 481 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 482 "loaderGetDeviceRegistryEntry: Failed to open registry key for DeviceID(%d)", dev_id); 483 *result = VK_ERROR_INITIALIZATION_FAILED; 484 return false; 485 } 486 487 // query value 488 LSTATUS ret = RegQueryValueEx( 489 hkrKey, 490 value_name, 491 NULL, 492 NULL, 493 NULL, 494 &requiredSize); 495 496 if (ret != ERROR_SUCCESS) { 497 if (ret == ERROR_FILE_NOT_FOUND) { 498 loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, 499 "loaderGetDeviceRegistryEntry: Device ID(%d) Does not contain a value for \"%s\"", dev_id, value_name); 500 } else { 501 loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, 502 "loaderGetDeviceRegistryEntry: DeviceID(%d) Failed to obtain %s size", dev_id, value_name); 503 } 504 goto out; 505 } 506 507 manifest_path = loader_instance_heap_alloc(inst, requiredSize, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 508 if (manifest_path == NULL) { 509 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 510 "loaderGetDeviceRegistryEntry: Failed to allocate space for DriverName."); 511 *result = VK_ERROR_OUT_OF_HOST_MEMORY; 512 goto out; 513 } 514 515 ret = RegQueryValueEx( 516 hkrKey, 517 value_name, 518 NULL, 519 &data_type, 520 (BYTE *)manifest_path, 521 &requiredSize 522 ); 523 524 if (ret != ERROR_SUCCESS) { 525 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 526 "loaderGetDeviceRegistryEntry: DeviceID(%d) Failed to obtain %s", value_name); 527 528 *result = VK_ERROR_INITIALIZATION_FAILED; 529 goto out; 530 } 531 532 if (data_type != REG_SZ && data_type != REG_MULTI_SZ) { 533 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 534 "loaderGetDeviceRegistryEntry: Invalid %s data type. Expected REG_SZ or REG_MULTI_SZ.", value_name); 535 *result = VK_ERROR_INITIALIZATION_FAILED; 536 goto out; 537 } 538 539 found = loaderAddJsonEntry(inst, reg_data, total_size, value_name, data_type, manifest_path, requiredSize, result); 540 541 out: 542 if (manifest_path != NULL) { 543 loader_instance_heap_free(inst, manifest_path); 544 } 545 RegCloseKey(hkrKey); 546 return found; 547 } 548 549 // Find the list of registry files (names VulkanDriverName/VulkanDriverNameWow) in hkr . 550 // 551 // This function looks for display devices and childish software components 552 // for a list of files which are added to a returned list (function return 553 // value). 554 // Function return is a string with a ';' separated list of filenames. 555 // Function return is NULL if no valid name/value pairs are found in the key, 556 // or the key is not found. 557 // 558 // *reg_data contains a string list of filenames as pointer. 559 // When done using the returned string list, the caller should free the pointer. 560 VkResult loaderGetDeviceRegistryFiles(const struct loader_instance *inst, char **reg_data, PDWORD reg_data_size, LPCTSTR value_name) { 561 static const wchar_t *softwareComponentGUID = L"{5c4c3332-344d-483c-8739-259e934c9cc8}"; 562 static const wchar_t *displayGUID = L"{4d36e968-e325-11ce-bfc1-08002be10318}"; 563 const ULONG flags = CM_GETIDLIST_FILTER_CLASS | CM_GETIDLIST_FILTER_PRESENT; 564 565 wchar_t childGuid[MAX_GUID_STRING_LEN + 2]; // +2 for brackets {} 566 ULONG childGuidSize = sizeof(childGuid); 567 568 DEVINST devID = 0, childID = 0; 569 wchar_t *pDeviceNames = NULL; 570 ULONG deviceNamesSize = 0; 571 VkResult result = VK_SUCCESS; 572 bool found = false; 573 574 if (NULL == reg_data) { 575 result = VK_ERROR_INITIALIZATION_FAILED; 576 return result; 577 } 578 579 // if after obtaining the DeviceNameSize, new device is added start over 580 do { 581 CM_Get_Device_ID_List_SizeW(&deviceNamesSize, displayGUID, flags); 582 583 if (pDeviceNames != NULL) { 584 loader_instance_heap_free(inst, pDeviceNames); 585 } 586 587 pDeviceNames = loader_instance_heap_alloc(inst, deviceNamesSize * sizeof(wchar_t), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 588 if (pDeviceNames == NULL) { 589 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 590 "loaderGetDeviceRegistryFiles: Failed to allocate space for display device names."); 591 result = VK_ERROR_OUT_OF_HOST_MEMORY; 592 return result; 593 } 594 } while (CM_Get_Device_ID_ListW(displayGUID, pDeviceNames, deviceNamesSize, flags) == CR_BUFFER_SMALL); 595 596 if (pDeviceNames) { 597 for (wchar_t *deviceName = pDeviceNames; *deviceName; deviceName += wcslen(deviceName) + 1) { 598 CONFIGRET status = CM_Locate_DevNodeW(&devID, deviceName, CM_LOCATE_DEVNODE_NORMAL); 599 if (CR_SUCCESS != status) { 600 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "loaderGetDeviceRegistryFiles: failed to open DevNode %s", 601 deviceName); 602 continue; 603 } 604 ULONG ulStatus, ulProblem; 605 status = CM_Get_DevNode_Status(&ulStatus, &ulProblem, devID, 0); 606 607 if (CR_SUCCESS != status) 608 { 609 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "loaderGetDeviceRegistryFiles: failed to probe device status %s", 610 deviceName); 611 continue; 612 } 613 if ((ulStatus & DN_HAS_PROBLEM) && (ulProblem == CM_PROB_NEED_RESTART || ulProblem == DN_NEED_RESTART)) 614 { 615 loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, 616 "loaderGetDeviceRegistryFiles: device %s is pending reboot, skipping ...", deviceName); 617 continue; 618 } 619 620 loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, "loaderGetDeviceRegistryFiles: opening device %s", deviceName); 621 622 if (loaderGetDeviceRegistryEntry(inst, reg_data, reg_data_size, devID, value_name, &result)) { 623 found = true; 624 continue; 625 } 626 else if (result == VK_ERROR_OUT_OF_HOST_MEMORY) { 627 break; 628 } 629 630 status = CM_Get_Child(&childID, devID, 0); 631 if (status != CR_SUCCESS) { 632 loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, 633 "loaderGetDeviceRegistryFiles: unable to open child-device error:%d", status); 634 continue; 635 } 636 637 do { 638 wchar_t buffer[MAX_DEVICE_ID_LEN]; 639 CM_Get_Device_IDW(childID, buffer, MAX_DEVICE_ID_LEN, 0); 640 641 loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, 642 "loaderGetDeviceRegistryFiles: Opening child device %d - %s", childID, buffer); 643 644 status = CM_Get_DevNode_Registry_PropertyW(childID, CM_DRP_CLASSGUID, NULL, &childGuid, &childGuidSize, 0); 645 if (status != CR_SUCCESS) { 646 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 647 "loaderGetDeviceRegistryFiles: unable to obtain GUID for:%d error:%d", childID, status); 648 649 result = VK_ERROR_INITIALIZATION_FAILED; 650 continue; 651 } 652 653 if (wcscmp(childGuid, softwareComponentGUID) != 0) { 654 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, 655 "loaderGetDeviceRegistryFiles: GUID for %d is not SoftwareComponent skipping", childID); 656 continue; 657 } 658 659 if (loaderGetDeviceRegistryEntry(inst, reg_data, reg_data_size, childID, value_name, &result)) { 660 found = true; 661 break; // check next-display-device 662 } 663 664 } while (CM_Get_Sibling(&childID, childID, 0) == CR_SUCCESS); 665 } 666 667 loader_instance_heap_free(inst, pDeviceNames); 668 } 669 670 if (!found && result != VK_ERROR_OUT_OF_HOST_MEMORY) { 671 result = VK_ERROR_INITIALIZATION_FAILED; 672 } 673 674 return result; 675 } 676 677 static char *loader_get_next_path(char *path); 678 679 // Find the list of registry files (names within a key) in key "location". 680 // 681 // This function looks in the registry (hive = DEFAULT_VK_REGISTRY_HIVE) key as 682 // given in "location" 683 // for a list or name/values which are added to a returned list (function return 684 // value). 685 // The DWORD values within the key must be 0 or they are skipped. 686 // Function return is a string with a ';' separated list of filenames. 687 // Function return is NULL if no valid name/value pairs are found in the key, 688 // or the key is not found. 689 // 690 // *reg_data contains a string list of filenames as pointer. 691 // When done using the returned string list, the caller should free the pointer. 692 VkResult loaderGetRegistryFiles(const struct loader_instance *inst, char *location, bool use_secondary_hive, char **reg_data, PDWORD reg_data_size) { 693 LONG rtn_value; 694 HKEY hive = DEFAULT_VK_REGISTRY_HIVE, key; 695 DWORD access_flags; 696 char name[2048]; 697 char *loc = location; 698 char *next; 699 DWORD idx; 700 DWORD name_size = sizeof(name); 701 DWORD value; 702 DWORD value_size = sizeof(value); 703 VkResult result = VK_SUCCESS; 704 bool found = false; 705 706 if (NULL == reg_data) { 707 result = VK_ERROR_INITIALIZATION_FAILED; 708 goto out; 709 } 710 711 while (*loc) { 712 next = loader_get_next_path(loc); 713 access_flags = KEY_QUERY_VALUE; 714 rtn_value = RegOpenKeyEx(hive, loc, 0, access_flags, &key); 715 if (ERROR_SUCCESS == rtn_value) { 716 idx = 0; 717 while ((rtn_value = RegEnumValue(key, idx++, name, &name_size, NULL, NULL, (LPBYTE)&value, &value_size)) == 718 ERROR_SUCCESS) { 719 if (value_size == sizeof(value) && value == 0) { 720 if (NULL == *reg_data) { 721 *reg_data = loader_instance_heap_alloc(inst, *reg_data_size, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 722 if (NULL == *reg_data) { 723 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 724 "loaderGetRegistryFiles: Failed to allocate space for registry data for key %s", name); 725 RegCloseKey(key); 726 result = VK_ERROR_OUT_OF_HOST_MEMORY; 727 goto out; 728 } 729 *reg_data[0] = '\0'; 730 } else if (strlen(*reg_data) + name_size + 1 > *reg_data_size) { 731 void *new_ptr = loader_instance_heap_realloc(inst, *reg_data, *reg_data_size, *reg_data_size * 2, 732 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 733 if (NULL == new_ptr) { 734 loader_log( 735 inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 736 "loaderGetRegistryFiles: Failed to reallocate space for registry value of size %d for key %s", 737 *reg_data_size * 2, name); 738 RegCloseKey(key); 739 result = VK_ERROR_OUT_OF_HOST_MEMORY; 740 goto out; 741 } 742 *reg_data = new_ptr; 743 *reg_data_size *= 2; 744 } 745 loader_log( 746 inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, "Located json file \"%s\" from registry \"%s\\%s\"", name, 747 hive == DEFAULT_VK_REGISTRY_HIVE ? DEFAULT_VK_REGISTRY_HIVE_STR : SECONDARY_VK_REGISTRY_HIVE_STR, location); 748 if (strlen(*reg_data) == 0) { 749 // The list is emtpy. Add the first entry. 750 (void)snprintf(*reg_data, name_size + 1, "%s", name); 751 found = true; 752 } else { 753 // At this point the reg_data variable contains other JSON paths, likely from the PNP/device section 754 // of the registry that we want to have precendence over this non-device specific section of the registry. 755 // To make sure we avoid enumerating old JSON files/drivers that might be present in the non-device specific 756 // area of the registry when a newer device specific JSON file is present, do a check before adding. 757 // Find the file name, without path, of the JSON file found in the non-device specific registry location. 758 // If the same JSON file name is already found in the list, don't add it again. 759 bool foundDuplicate = false; 760 char *pLastSlashName = strrchr(name, '\\'); 761 if (pLastSlashName != NULL) { 762 char *foundMatch = strstr(*reg_data, pLastSlashName + 1); 763 if (foundMatch != NULL) { 764 foundDuplicate = true; 765 } 766 } 767 768 if (foundDuplicate == false) { 769 // Add the new entry to the list. 770 (void)snprintf(*reg_data + strlen(*reg_data), name_size + 2, "%c%s", PATH_SEPARATOR, name); 771 found = true; 772 } else { 773 loader_log( 774 inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, 775 "Skipping adding of json file \"%s\" from registry \"%s\\%s\" to the list due to duplication", name, 776 hive == DEFAULT_VK_REGISTRY_HIVE ? DEFAULT_VK_REGISTRY_HIVE_STR : SECONDARY_VK_REGISTRY_HIVE_STR, 777 location); 778 } 779 } 780 } 781 name_size = 2048; 782 } 783 RegCloseKey(key); 784 } 785 786 // Advance the location - if the next location is in the secondary hive, then reset the locations and advance the hive 787 if (use_secondary_hive && (hive == DEFAULT_VK_REGISTRY_HIVE) && (*next == '\0')) { 788 loc = location; 789 hive = SECONDARY_VK_REGISTRY_HIVE; 790 } else { 791 loc = next; 792 } 793 } 794 795 if (!found && result != VK_ERROR_OUT_OF_HOST_MEMORY) { 796 result = VK_ERROR_INITIALIZATION_FAILED; 797 } 798 799 out: 800 801 return result; 802 } 803 804 #endif // WIN32 805 806 // Combine path elements, separating each element with the platform-specific 807 // directory separator, and save the combined string to a destination buffer, 808 // not exceeding the given length. Path elements are given as variable args, 809 // with a NULL element terminating the list. 810 // 811 // \returns the total length of the combined string, not including an ASCII 812 // NUL termination character. This length may exceed the available storage: 813 // in this case, the written string will be truncated to avoid a buffer 814 // overrun, and the return value will greater than or equal to the storage 815 // size. A NULL argument may be provided as the destination buffer in order 816 // to determine the required string length without actually writing a string. 817 static size_t loader_platform_combine_path(char *dest, size_t len, ...) { 818 size_t required_len = 0; 819 va_list ap; 820 const char *component; 821 822 va_start(ap, len); 823 824 while ((component = va_arg(ap, const char *))) { 825 if (required_len > 0) { 826 // This path element is not the first non-empty element; prepend 827 // a directory separator if space allows 828 if (dest && required_len + 1 < len) { 829 (void)snprintf(dest + required_len, len - required_len, "%c", DIRECTORY_SYMBOL); 830 } 831 required_len++; 832 } 833 834 if (dest && required_len < len) { 835 strncpy(dest + required_len, component, len - required_len); 836 } 837 required_len += strlen(component); 838 } 839 840 va_end(ap); 841 842 // strncpy(3) won't add a NUL terminating byte in the event of truncation. 843 if (dest && required_len >= len) { 844 dest[len - 1] = '\0'; 845 } 846 847 return required_len; 848 } 849 850 // Given string of three part form "maj.min.pat" convert to a vulkan version number. 851 static uint32_t loader_make_version(char *vers_str) { 852 uint32_t vers = 0, major = 0, minor = 0, patch = 0; 853 char *vers_tok; 854 855 if (!vers_str) { 856 return vers; 857 } 858 859 vers_tok = strtok(vers_str, ".\"\n\r"); 860 if (NULL != vers_tok) { 861 major = (uint16_t)atoi(vers_tok); 862 vers_tok = strtok(NULL, ".\"\n\r"); 863 if (NULL != vers_tok) { 864 minor = (uint16_t)atoi(vers_tok); 865 vers_tok = strtok(NULL, ".\"\n\r"); 866 if (NULL != vers_tok) { 867 patch = (uint16_t)atoi(vers_tok); 868 } 869 } 870 } 871 872 return VK_MAKE_VERSION(major, minor, patch); 873 } 874 875 bool compare_vk_extension_properties(const VkExtensionProperties *op1, const VkExtensionProperties *op2) { 876 return strcmp(op1->extensionName, op2->extensionName) == 0 ? true : false; 877 } 878 879 // Search the given ext_array for an extension matching the given vk_ext_prop 880 bool has_vk_extension_property_array(const VkExtensionProperties *vk_ext_prop, const uint32_t count, 881 const VkExtensionProperties *ext_array) { 882 for (uint32_t i = 0; i < count; i++) { 883 if (compare_vk_extension_properties(vk_ext_prop, &ext_array[i])) return true; 884 } 885 return false; 886 } 887 888 // Search the given ext_list for an extension matching the given vk_ext_prop 889 bool has_vk_extension_property(const VkExtensionProperties *vk_ext_prop, const struct loader_extension_list *ext_list) { 890 for (uint32_t i = 0; i < ext_list->count; i++) { 891 if (compare_vk_extension_properties(&ext_list->list[i], vk_ext_prop)) return true; 892 } 893 return false; 894 } 895 896 // Search the given ext_list for a device extension matching the given ext_prop 897 bool has_vk_dev_ext_property(const VkExtensionProperties *ext_prop, const struct loader_device_extension_list *ext_list) { 898 for (uint32_t i = 0; i < ext_list->count; i++) { 899 if (compare_vk_extension_properties(&ext_list->list[i].props, ext_prop)) return true; 900 } 901 return false; 902 } 903 904 // Search the given layer list for a layer matching the given layer name 905 static struct loader_layer_properties *loader_get_layer_property(const char *name, const struct loader_layer_list *layer_list) { 906 for (uint32_t i = 0; i < layer_list->count; i++) { 907 const VkLayerProperties *item = &layer_list->list[i].info; 908 if (strcmp(name, item->layerName) == 0) return &layer_list->list[i]; 909 } 910 return NULL; 911 } 912 913 // Get the next unused layer property in the list. Init the property to zero. 914 static struct loader_layer_properties *loader_get_next_layer_property(const struct loader_instance *inst, 915 struct loader_layer_list *layer_list) { 916 if (layer_list->capacity == 0) { 917 layer_list->list = 918 loader_instance_heap_alloc(inst, sizeof(struct loader_layer_properties) * 64, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 919 if (layer_list->list == NULL) { 920 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 921 "loader_get_next_layer_property: Out of memory can " 922 "not add any layer properties to list"); 923 return NULL; 924 } 925 memset(layer_list->list, 0, sizeof(struct loader_layer_properties) * 64); 926 layer_list->capacity = sizeof(struct loader_layer_properties) * 64; 927 } 928 929 // Ensure enough room to add an entry 930 if ((layer_list->count + 1) * sizeof(struct loader_layer_properties) > layer_list->capacity) { 931 void *new_ptr = loader_instance_heap_realloc(inst, layer_list->list, layer_list->capacity, layer_list->capacity * 2, 932 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 933 if (NULL == new_ptr) { 934 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "loader_get_next_layer_property: realloc failed for layer list"); 935 return NULL; 936 } 937 layer_list->list = new_ptr; 938 layer_list->capacity *= 2; 939 } 940 941 layer_list->count++; 942 return &(layer_list->list[layer_list->count - 1]); 943 } 944 945 // Remove all layer properties entries from the list 946 void loader_delete_layer_properties(const struct loader_instance *inst, struct loader_layer_list *layer_list) { 947 uint32_t i, j, k; 948 struct loader_device_extension_list *dev_ext_list; 949 struct loader_dev_ext_props *ext_props; 950 if (!layer_list) return; 951 952 for (i = 0; i < layer_list->count; i++) { 953 if (NULL != layer_list->list[i].component_layer_names) { 954 loader_instance_heap_free(inst, layer_list->list[i].component_layer_names); 955 layer_list->list[i].component_layer_names = NULL; 956 } 957 loader_destroy_generic_list(inst, (struct loader_generic_list *)&layer_list->list[i].instance_extension_list); 958 dev_ext_list = &layer_list->list[i].device_extension_list; 959 if (dev_ext_list->capacity > 0 && NULL != dev_ext_list->list) { 960 for (j = 0; j < dev_ext_list->count; j++) { 961 ext_props = &dev_ext_list->list[j]; 962 if (ext_props->entrypoint_count > 0) { 963 for (k = 0; k < ext_props->entrypoint_count; k++) { 964 loader_instance_heap_free(inst, ext_props->entrypoints[k]); 965 } 966 loader_instance_heap_free(inst, ext_props->entrypoints); 967 } 968 } 969 } 970 loader_destroy_generic_list(inst, (struct loader_generic_list *)dev_ext_list); 971 } 972 layer_list->count = 0; 973 974 if (layer_list->capacity > 0) { 975 layer_list->capacity = 0; 976 loader_instance_heap_free(inst, layer_list->list); 977 } 978 } 979 980 static VkResult loader_add_instance_extensions(const struct loader_instance *inst, 981 const PFN_vkEnumerateInstanceExtensionProperties fp_get_props, const char *lib_name, 982 struct loader_extension_list *ext_list) { 983 uint32_t i, count = 0; 984 VkExtensionProperties *ext_props; 985 VkResult res = VK_SUCCESS; 986 987 if (!fp_get_props) { 988 // No EnumerateInstanceExtensionProperties defined 989 goto out; 990 } 991 992 res = fp_get_props(NULL, &count, NULL); 993 if (res != VK_SUCCESS) { 994 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 995 "loader_add_instance_extensions: Error getting Instance " 996 "extension count from %s", 997 lib_name); 998 goto out; 999 } 1000 1001 if (count == 0) { 1002 // No ExtensionProperties to report 1003 goto out; 1004 } 1005 1006 ext_props = loader_stack_alloc(count * sizeof(VkExtensionProperties)); 1007 if (NULL == ext_props) { 1008 res = VK_ERROR_OUT_OF_HOST_MEMORY; 1009 goto out; 1010 } 1011 1012 res = fp_get_props(NULL, &count, ext_props); 1013 if (res != VK_SUCCESS) { 1014 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 1015 "loader_add_instance_extensions: Error getting Instance " 1016 "extensions from %s", 1017 lib_name); 1018 goto out; 1019 } 1020 1021 for (i = 0; i < count; i++) { 1022 char spec_version[64]; 1023 1024 bool ext_unsupported = wsi_unsupported_instance_extension(&ext_props[i]); 1025 if (!ext_unsupported) { 1026 (void)snprintf(spec_version, sizeof(spec_version), "%d.%d.%d", VK_VERSION_MAJOR(ext_props[i].specVersion), 1027 VK_VERSION_MINOR(ext_props[i].specVersion), VK_VERSION_PATCH(ext_props[i].specVersion)); 1028 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Instance Extension: %s (%s) version %s", ext_props[i].extensionName, 1029 lib_name, spec_version); 1030 1031 res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]); 1032 if (res != VK_SUCCESS) { 1033 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 1034 "loader_add_instance_extensions: Failed to add %s " 1035 "to Instance extension list", 1036 lib_name); 1037 goto out; 1038 } 1039 } 1040 } 1041 1042 out: 1043 return res; 1044 } 1045 1046 // Initialize ext_list with the physical device extensions. 1047 // The extension properties are passed as inputs in count and ext_props. 1048 static VkResult loader_init_device_extensions(const struct loader_instance *inst, struct loader_physical_device_term *phys_dev_term, 1049 uint32_t count, VkExtensionProperties *ext_props, 1050 struct loader_extension_list *ext_list) { 1051 VkResult res; 1052 uint32_t i; 1053 1054 res = loader_init_generic_list(inst, (struct loader_generic_list *)ext_list, sizeof(VkExtensionProperties)); 1055 if (VK_SUCCESS != res) { 1056 return res; 1057 } 1058 1059 for (i = 0; i < count; i++) { 1060 char spec_version[64]; 1061 (void)snprintf(spec_version, sizeof(spec_version), "%d.%d.%d", VK_VERSION_MAJOR(ext_props[i].specVersion), 1062 VK_VERSION_MINOR(ext_props[i].specVersion), VK_VERSION_PATCH(ext_props[i].specVersion)); 1063 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Device Extension: %s (%s) version %s", ext_props[i].extensionName, 1064 phys_dev_term->this_icd_term->scanned_icd->lib_name, spec_version); 1065 res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]); 1066 if (res != VK_SUCCESS) return res; 1067 } 1068 1069 return VK_SUCCESS; 1070 } 1071 1072 VkResult loader_add_device_extensions(const struct loader_instance *inst, 1073 PFN_vkEnumerateDeviceExtensionProperties fpEnumerateDeviceExtensionProperties, 1074 VkPhysicalDevice physical_device, const char *lib_name, 1075 struct loader_extension_list *ext_list) { 1076 uint32_t i, count; 1077 VkResult res; 1078 VkExtensionProperties *ext_props; 1079 1080 res = fpEnumerateDeviceExtensionProperties(physical_device, NULL, &count, NULL); 1081 if (res == VK_SUCCESS && count > 0) { 1082 ext_props = loader_stack_alloc(count * sizeof(VkExtensionProperties)); 1083 if (!ext_props) { 1084 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 1085 "loader_add_device_extensions: Failed to allocate space" 1086 " for device extension properties."); 1087 return VK_ERROR_OUT_OF_HOST_MEMORY; 1088 } 1089 res = fpEnumerateDeviceExtensionProperties(physical_device, NULL, &count, ext_props); 1090 if (res != VK_SUCCESS) { 1091 return res; 1092 } 1093 for (i = 0; i < count; i++) { 1094 char spec_version[64]; 1095 (void)snprintf(spec_version, sizeof(spec_version), "%d.%d.%d", VK_VERSION_MAJOR(ext_props[i].specVersion), 1096 VK_VERSION_MINOR(ext_props[i].specVersion), VK_VERSION_PATCH(ext_props[i].specVersion)); 1097 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Device Extension: %s (%s) version %s", ext_props[i].extensionName, 1098 lib_name, spec_version); 1099 res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]); 1100 if (res != VK_SUCCESS) { 1101 return res; 1102 } 1103 } 1104 } else { 1105 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 1106 "loader_add_device_extensions: Error getting physical " 1107 "device extension info count from library %s", 1108 lib_name); 1109 return res; 1110 } 1111 1112 return VK_SUCCESS; 1113 } 1114 1115 VkResult loader_init_generic_list(const struct loader_instance *inst, struct loader_generic_list *list_info, size_t element_size) { 1116 size_t capacity = 32 * element_size; 1117 list_info->count = 0; 1118 list_info->capacity = 0; 1119 list_info->list = loader_instance_heap_alloc(inst, capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1120 if (list_info->list == NULL) { 1121 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 1122 "loader_init_generic_list: Failed to allocate space " 1123 "for generic list"); 1124 return VK_ERROR_OUT_OF_HOST_MEMORY; 1125 } 1126 memset(list_info->list, 0, capacity); 1127 list_info->capacity = capacity; 1128 return VK_SUCCESS; 1129 } 1130 1131 void loader_destroy_generic_list(const struct loader_instance *inst, struct loader_generic_list *list) { 1132 loader_instance_heap_free(inst, list->list); 1133 list->count = 0; 1134 list->capacity = 0; 1135 } 1136 1137 // Append non-duplicate extension properties defined in props to the given ext_list. 1138 // Return - Vk_SUCCESS on success 1139 VkResult loader_add_to_ext_list(const struct loader_instance *inst, struct loader_extension_list *ext_list, 1140 uint32_t prop_list_count, const VkExtensionProperties *props) { 1141 uint32_t i; 1142 const VkExtensionProperties *cur_ext; 1143 1144 if (ext_list->list == NULL || ext_list->capacity == 0) { 1145 VkResult res = loader_init_generic_list(inst, (struct loader_generic_list *)ext_list, sizeof(VkExtensionProperties)); 1146 if (VK_SUCCESS != res) { 1147 return res; 1148 } 1149 } 1150 1151 for (i = 0; i < prop_list_count; i++) { 1152 cur_ext = &props[i]; 1153 1154 // look for duplicates 1155 if (has_vk_extension_property(cur_ext, ext_list)) { 1156 continue; 1157 } 1158 1159 // add to list at end 1160 // check for enough capacity 1161 if (ext_list->count * sizeof(VkExtensionProperties) >= ext_list->capacity) { 1162 void *new_ptr = loader_instance_heap_realloc(inst, ext_list->list, ext_list->capacity, ext_list->capacity * 2, 1163 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1164 if (new_ptr == NULL) { 1165 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 1166 "loader_add_to_ext_list: Failed to reallocate " 1167 "space for extension list"); 1168 return VK_ERROR_OUT_OF_HOST_MEMORY; 1169 } 1170 ext_list->list = new_ptr; 1171 1172 // double capacity 1173 ext_list->capacity *= 2; 1174 } 1175 1176 memcpy(&ext_list->list[ext_list->count], cur_ext, sizeof(VkExtensionProperties)); 1177 ext_list->count++; 1178 } 1179 return VK_SUCCESS; 1180 } 1181 1182 // Append one extension property defined in props with entrypoints defined in entries to the given 1183 // ext_list. Do not append if a duplicate. 1184 // Return - Vk_SUCCESS on success 1185 VkResult loader_add_to_dev_ext_list(const struct loader_instance *inst, struct loader_device_extension_list *ext_list, 1186 const VkExtensionProperties *props, uint32_t entry_count, char **entrys) { 1187 uint32_t idx; 1188 if (ext_list->list == NULL || ext_list->capacity == 0) { 1189 VkResult res = loader_init_generic_list(inst, (struct loader_generic_list *)ext_list, sizeof(struct loader_dev_ext_props)); 1190 if (VK_SUCCESS != res) { 1191 return res; 1192 } 1193 } 1194 1195 // look for duplicates 1196 if (has_vk_dev_ext_property(props, ext_list)) { 1197 return VK_SUCCESS; 1198 } 1199 1200 idx = ext_list->count; 1201 // add to list at end 1202 // check for enough capacity 1203 if (idx * sizeof(struct loader_dev_ext_props) >= ext_list->capacity) { 1204 void *new_ptr = loader_instance_heap_realloc(inst, ext_list->list, ext_list->capacity, ext_list->capacity * 2, 1205 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1206 1207 if (NULL == new_ptr) { 1208 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 1209 "loader_add_to_dev_ext_list: Failed to reallocate space for device extension list"); 1210 return VK_ERROR_OUT_OF_HOST_MEMORY; 1211 } 1212 ext_list->list = new_ptr; 1213 1214 // double capacity 1215 ext_list->capacity *= 2; 1216 } 1217 1218 memcpy(&ext_list->list[idx].props, props, sizeof(*props)); 1219 ext_list->list[idx].entrypoint_count = entry_count; 1220 if (entry_count == 0) { 1221 ext_list->list[idx].entrypoints = NULL; 1222 } else { 1223 ext_list->list[idx].entrypoints = 1224 loader_instance_heap_alloc(inst, sizeof(char *) * entry_count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1225 if (ext_list->list[idx].entrypoints == NULL) { 1226 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 1227 "loader_add_to_dev_ext_list: Failed to allocate space " 1228 "for device extension entrypoint list in list %d", 1229 idx); 1230 ext_list->list[idx].entrypoint_count = 0; 1231 return VK_ERROR_OUT_OF_HOST_MEMORY; 1232 } 1233 for (uint32_t i = 0; i < entry_count; i++) { 1234 ext_list->list[idx].entrypoints[i] = 1235 loader_instance_heap_alloc(inst, strlen(entrys[i]) + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1236 if (ext_list->list[idx].entrypoints[i] == NULL) { 1237 for (uint32_t j = 0; j < i; j++) { 1238 loader_instance_heap_free(inst, ext_list->list[idx].entrypoints[j]); 1239 } 1240 loader_instance_heap_free(inst, ext_list->list[idx].entrypoints); 1241 ext_list->list[idx].entrypoint_count = 0; 1242 ext_list->list[idx].entrypoints = NULL; 1243 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 1244 "loader_add_to_dev_ext_list: Failed to allocate space " 1245 "for device extension entrypoint %d name", 1246 i); 1247 return VK_ERROR_OUT_OF_HOST_MEMORY; 1248 } 1249 strcpy(ext_list->list[idx].entrypoints[i], entrys[i]); 1250 } 1251 } 1252 ext_list->count++; 1253 1254 return VK_SUCCESS; 1255 } 1256 1257 // Prototype of loader_add_meta_layer function since we use it in the loader_add_implicit_layer, but can also 1258 // call loader_add_implicit_layer from loader_add_meta_layer. 1259 bool loader_add_meta_layer(const struct loader_instance *inst, const struct loader_layer_properties *prop, 1260 struct loader_layer_list *target_list, struct loader_layer_list *expanded_target_list, 1261 const struct loader_layer_list *source_list); 1262 1263 // Search the given layer list for a list matching the given VkLayerProperties 1264 bool has_vk_layer_property(const VkLayerProperties *vk_layer_prop, const struct loader_layer_list *list) { 1265 for (uint32_t i = 0; i < list->count; i++) { 1266 if (strcmp(vk_layer_prop->layerName, list->list[i].info.layerName) == 0) return true; 1267 } 1268 return false; 1269 } 1270 1271 // Search the given layer list for a layer matching the given name 1272 bool has_layer_name(const char *name, const struct loader_layer_list *list) { 1273 for (uint32_t i = 0; i < list->count; i++) { 1274 if (strcmp(name, list->list[i].info.layerName) == 0) return true; 1275 } 1276 return false; 1277 } 1278 1279 // Search the given search_list for any layers in the props list. Add these to the 1280 // output layer_list. Don't add duplicates to the output layer_list. 1281 static VkResult loader_add_layer_names_to_list(const struct loader_instance *inst, struct loader_layer_list *output_list, 1282 struct loader_layer_list *expanded_output_list, uint32_t name_count, 1283 const char *const *names, const struct loader_layer_list *source_list) { 1284 struct loader_layer_properties *layer_prop; 1285 VkResult err = VK_SUCCESS; 1286 1287 for (uint32_t i = 0; i < name_count; i++) { 1288 const char *source_name = names[i]; 1289 layer_prop = loader_get_layer_property(source_name, source_list); 1290 if (NULL == layer_prop) { 1291 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 1292 "loader_add_layer_names_to_list: Unable to find layer" 1293 " %s", 1294 source_name); 1295 err = VK_ERROR_LAYER_NOT_PRESENT; 1296 continue; 1297 } 1298 1299 // If not a meta-layer, simply add it. 1300 if (0 == (layer_prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER)) { 1301 if (!has_vk_layer_property(&layer_prop->info, output_list)) { 1302 loader_add_to_layer_list(inst, output_list, 1, layer_prop); 1303 } 1304 if (!has_vk_layer_property(&layer_prop->info, expanded_output_list)) { 1305 loader_add_to_layer_list(inst, expanded_output_list, 1, layer_prop); 1306 } 1307 } else { 1308 if (!has_vk_layer_property(&layer_prop->info, output_list) || 1309 !has_vk_layer_property(&layer_prop->info, expanded_output_list)) { 1310 loader_add_meta_layer(inst, layer_prop, output_list, expanded_output_list, source_list); 1311 } 1312 } 1313 } 1314 1315 return err; 1316 } 1317 1318 // Manage lists of VkLayerProperties 1319 static bool loader_init_layer_list(const struct loader_instance *inst, struct loader_layer_list *list) { 1320 list->capacity = 32 * sizeof(struct loader_layer_properties); 1321 list->list = loader_instance_heap_alloc(inst, list->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1322 if (list->list == NULL) { 1323 return false; 1324 } 1325 memset(list->list, 0, list->capacity); 1326 list->count = 0; 1327 return true; 1328 } 1329 1330 void loader_destroy_layer_list(const struct loader_instance *inst, struct loader_device *device, 1331 struct loader_layer_list *layer_list) { 1332 if (device) { 1333 loader_device_heap_free(device, layer_list->list); 1334 } else { 1335 loader_instance_heap_free(inst, layer_list->list); 1336 } 1337 layer_list->count = 0; 1338 layer_list->capacity = 0; 1339 } 1340 1341 // Append non-duplicate layer properties defined in prop_list to the given layer_info list 1342 VkResult loader_add_to_layer_list(const struct loader_instance *inst, struct loader_layer_list *list, uint32_t prop_list_count, 1343 const struct loader_layer_properties *props) { 1344 uint32_t i; 1345 struct loader_layer_properties *layer; 1346 1347 if (list->list == NULL || list->capacity == 0) { 1348 loader_init_layer_list(inst, list); 1349 } 1350 1351 if (list->list == NULL) return VK_SUCCESS; 1352 1353 for (i = 0; i < prop_list_count; i++) { 1354 layer = (struct loader_layer_properties *)&props[i]; 1355 1356 // Look for duplicates, and skip 1357 if (has_vk_layer_property(&layer->info, list)) { 1358 continue; 1359 } 1360 1361 // Check for enough capacity 1362 if (((list->count + 1) * sizeof(struct loader_layer_properties)) >= list->capacity) { 1363 size_t new_capacity = list->capacity * 2; 1364 void *new_ptr = 1365 loader_instance_heap_realloc(inst, list->list, list->capacity, new_capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1366 if (NULL == new_ptr) { 1367 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 1368 "loader_add_to_layer_list: Realloc failed for when attempting to add new layer"); 1369 return VK_ERROR_OUT_OF_HOST_MEMORY; 1370 } 1371 list->list = new_ptr; 1372 list->capacity = new_capacity; 1373 } 1374 1375 memcpy(&list->list[list->count], layer, sizeof(struct loader_layer_properties)); 1376 list->count++; 1377 } 1378 1379 return VK_SUCCESS; 1380 } 1381 1382 // Check the individual implicit layer for the enable/disable environment variable settings. Only add it after 1383 // every check has passed indicating it should be used. 1384 static void loader_add_implicit_layer(const struct loader_instance *inst, const struct loader_layer_properties *prop, 1385 struct loader_layer_list *target_list, struct loader_layer_list *expanded_target_list, 1386 const struct loader_layer_list *source_list) { 1387 bool enable = loader_is_implicit_layer_enabled(inst, prop); 1388 if (enable) { 1389 if (0 == (prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER)) { 1390 if (NULL != target_list && !has_vk_layer_property(&prop->info, target_list)) { 1391 loader_add_to_layer_list(inst, target_list, 1, prop); 1392 } 1393 if (NULL != expanded_target_list && !has_vk_layer_property(&prop->info, expanded_target_list)) { 1394 loader_add_to_layer_list(inst, expanded_target_list, 1, prop); 1395 } 1396 } else { 1397 if (!has_vk_layer_property(&prop->info, target_list) || 1398 (NULL != expanded_target_list && !has_vk_layer_property(&prop->info, expanded_target_list))) { 1399 loader_add_meta_layer(inst, prop, target_list, expanded_target_list, source_list); 1400 } 1401 } 1402 } 1403 } 1404 1405 // Add the component layers of a meta-layer to the active list of layers 1406 bool loader_add_meta_layer(const struct loader_instance *inst, const struct loader_layer_properties *prop, 1407 struct loader_layer_list *target_list, struct loader_layer_list *expanded_target_list, 1408 const struct loader_layer_list *source_list) { 1409 bool found = true; 1410 1411 // We need to add all the individual component layers 1412 for (uint32_t comp_layer = 0; comp_layer < prop->num_component_layers; comp_layer++) { 1413 bool found_comp = false; 1414 const struct loader_layer_properties *search_prop = 1415 loader_get_layer_property(prop->component_layer_names[comp_layer], source_list); 1416 if (search_prop != NULL) { 1417 found_comp = true; 1418 1419 // If the component layer is itself an implicit layer, we need to do the implicit layer enable 1420 // checks 1421 if (0 == (search_prop->type_flags & VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER)) { 1422 loader_add_implicit_layer(inst, search_prop, target_list, expanded_target_list, source_list); 1423 } else { 1424 if (NULL != expanded_target_list && !has_vk_layer_property(&search_prop->info, expanded_target_list)) { 1425 loader_add_to_layer_list(inst, expanded_target_list, 1, search_prop); 1426 } 1427 } 1428 } 1429 if (!found_comp) { 1430 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 1431 "loader_add_meta_layer: Failed to find layer name %s component layer " 1432 "%s to activate", 1433 search_prop->info.layerName, prop->component_layer_names[comp_layer]); 1434 found = false; 1435 } 1436 } 1437 1438 // Add this layer to the overall target list (not the expanded one) 1439 if (found && !has_vk_layer_property(&prop->info, target_list)) { 1440 loader_add_to_layer_list(inst, target_list, 1, prop); 1441 } 1442 1443 return found; 1444 } 1445 1446 // Search the source_list for any layer with a name that matches the given name and a type 1447 // that matches the given type. Add all matching layers to the target_list. 1448 // Do not add if found loader_layer_properties is already on the target_list. 1449 void loader_find_layer_name_add_list(const struct loader_instance *inst, const char *name, const enum layer_type_flags type_flags, 1450 const struct loader_layer_list *source_list, struct loader_layer_list *target_list, 1451 struct loader_layer_list *expanded_target_list) { 1452 bool found = false; 1453 for (uint32_t i = 0; i < source_list->count; i++) { 1454 struct loader_layer_properties *source_prop = &source_list->list[i]; 1455 if (0 == strcmp(source_prop->info.layerName, name) && (source_prop->type_flags & type_flags) == type_flags) { 1456 // If not a meta-layer, simply add it. 1457 if (0 == (source_prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER)) { 1458 if (NULL != target_list && !has_vk_layer_property(&source_prop->info, target_list) && 1459 VK_SUCCESS == loader_add_to_layer_list(inst, target_list, 1, source_prop)) { 1460 found = true; 1461 } 1462 if (NULL != expanded_target_list && !has_vk_layer_property(&source_prop->info, expanded_target_list) && 1463 VK_SUCCESS == loader_add_to_layer_list(inst, expanded_target_list, 1, source_prop)) { 1464 found = true; 1465 } 1466 } else { 1467 found = loader_add_meta_layer(inst, source_prop, target_list, expanded_target_list, source_list); 1468 } 1469 } 1470 } 1471 if (!found) { 1472 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 1473 "loader_find_layer_name_add_list: Failed to find layer name %s to activate", name); 1474 } 1475 } 1476 1477 static VkExtensionProperties *get_extension_property(const char *name, const struct loader_extension_list *list) { 1478 for (uint32_t i = 0; i < list->count; i++) { 1479 if (strcmp(name, list->list[i].extensionName) == 0) return &list->list[i]; 1480 } 1481 return NULL; 1482 } 1483 1484 static VkExtensionProperties *get_dev_extension_property(const char *name, const struct loader_device_extension_list *list) { 1485 for (uint32_t i = 0; i < list->count; i++) { 1486 if (strcmp(name, list->list[i].props.extensionName) == 0) return &list->list[i].props; 1487 } 1488 return NULL; 1489 } 1490 1491 // For Instance extensions implemented within the loader (i.e. DEBUG_REPORT 1492 // the extension must provide two entry points for the loader to use: 1493 // - "trampoline" entry point - this is the address returned by GetProcAddr 1494 // and will always do what's necessary to support a 1495 // global call. 1496 // - "terminator" function - this function will be put at the end of the 1497 // instance chain and will contain the necessary logic 1498 // to call / process the extension for the appropriate 1499 // ICDs that are available. 1500 // There is no generic mechanism for including these functions, the references 1501 // must be placed into the appropriate loader entry points. 1502 // GetInstanceProcAddr: call extension GetInstanceProcAddr to check for GetProcAddr 1503 // requests 1504 // loader_coalesce_extensions(void) - add extension records to the list of global 1505 // extension available to the app. 1506 // instance_disp - add function pointer for terminator function 1507 // to this array. 1508 // The extension itself should be in a separate file that will be linked directly 1509 // with the loader. 1510 VkResult loader_get_icd_loader_instance_extensions(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list, 1511 struct loader_extension_list *inst_exts) { 1512 struct loader_extension_list icd_exts; 1513 VkResult res = VK_SUCCESS; 1514 char *env_value; 1515 bool filter_extensions = true; 1516 1517 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Build ICD instance extension list"); 1518 1519 // Check if a user wants to disable the instance extension filtering behavior 1520 env_value = loader_getenv("VK_LOADER_DISABLE_INST_EXT_FILTER", inst); 1521 if (NULL != env_value && atoi(env_value) != 0) { 1522 filter_extensions = false; 1523 } 1524 loader_free_getenv(env_value, inst); 1525 1526 // traverse scanned icd list adding non-duplicate extensions to the list 1527 for (uint32_t i = 0; i < icd_tramp_list->count; i++) { 1528 res = loader_init_generic_list(inst, (struct loader_generic_list *)&icd_exts, sizeof(VkExtensionProperties)); 1529 if (VK_SUCCESS != res) { 1530 goto out; 1531 } 1532 res = loader_add_instance_extensions(inst, icd_tramp_list->scanned_list[i].EnumerateInstanceExtensionProperties, 1533 icd_tramp_list->scanned_list[i].lib_name, &icd_exts); 1534 if (VK_SUCCESS == res) { 1535 if (filter_extensions) { 1536 // Remove any extensions not recognized by the loader 1537 for (int32_t j = 0; j < (int32_t)icd_exts.count; j++) { 1538 // See if the extension is in the list of supported extensions 1539 bool found = false; 1540 for (uint32_t k = 0; LOADER_INSTANCE_EXTENSIONS[k] != NULL; k++) { 1541 if (strcmp(icd_exts.list[j].extensionName, LOADER_INSTANCE_EXTENSIONS[k]) == 0) { 1542 found = true; 1543 break; 1544 } 1545 } 1546 1547 // If it isn't in the list, remove it 1548 if (!found) { 1549 for (uint32_t k = j + 1; k < icd_exts.count; k++) { 1550 icd_exts.list[k - 1] = icd_exts.list[k]; 1551 } 1552 --icd_exts.count; 1553 --j; 1554 } 1555 } 1556 } 1557 1558 res = loader_add_to_ext_list(inst, inst_exts, icd_exts.count, icd_exts.list); 1559 } 1560 loader_destroy_generic_list(inst, (struct loader_generic_list *)&icd_exts); 1561 if (VK_SUCCESS != res) { 1562 goto out; 1563 } 1564 }; 1565 1566 // Traverse loader's extensions, adding non-duplicate extensions to the list 1567 debug_report_add_instance_extensions(inst, inst_exts); 1568 1569 out: 1570 return res; 1571 } 1572 1573 struct loader_icd_term *loader_get_icd_and_device(const VkDevice device, struct loader_device **found_dev, uint32_t *icd_index) { 1574 *found_dev = NULL; 1575 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) { 1576 uint32_t index = 0; 1577 for (struct loader_icd_term *icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) { 1578 for (struct loader_device *dev = icd_term->logical_device_list; dev; dev = dev->next) 1579 // Value comparison of device prevents object wrapping by layers 1580 if (loader_get_dispatch(dev->icd_device) == loader_get_dispatch(device) || 1581 loader_get_dispatch(dev->chain_device) == loader_get_dispatch(device)) { 1582 *found_dev = dev; 1583 if (NULL != icd_index) { 1584 *icd_index = index; 1585 } 1586 return icd_term; 1587 } 1588 index++; 1589 } 1590 } 1591 return NULL; 1592 } 1593 1594 void loader_destroy_logical_device(const struct loader_instance *inst, struct loader_device *dev, 1595 const VkAllocationCallbacks *pAllocator) { 1596 if (pAllocator) { 1597 dev->alloc_callbacks = *pAllocator; 1598 } 1599 if (NULL != dev->expanded_activated_layer_list.list) { 1600 loader_deactivate_layers(inst, dev, &dev->expanded_activated_layer_list); 1601 } 1602 if (NULL != dev->app_activated_layer_list.list) { 1603 loader_destroy_layer_list(inst, dev, &dev->app_activated_layer_list); 1604 } 1605 loader_device_heap_free(dev, dev); 1606 } 1607 1608 struct loader_device *loader_create_logical_device(const struct loader_instance *inst, const VkAllocationCallbacks *pAllocator) { 1609 struct loader_device *new_dev; 1610 #if (DEBUG_DISABLE_APP_ALLOCATORS == 1) 1611 { 1612 #else 1613 if (pAllocator) { 1614 new_dev = (struct loader_device *)pAllocator->pfnAllocation(pAllocator->pUserData, sizeof(struct loader_device), 1615 sizeof(int *), VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); 1616 } else { 1617 #endif 1618 new_dev = (struct loader_device *)malloc(sizeof(struct loader_device)); 1619 } 1620 1621 if (!new_dev) { 1622 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 1623 "loader_create_logical_device: Failed to alloc struct " 1624 "loader_device"); 1625 return NULL; 1626 } 1627 1628 memset(new_dev, 0, sizeof(struct loader_device)); 1629 if (pAllocator) { 1630 new_dev->alloc_callbacks = *pAllocator; 1631 } 1632 1633 return new_dev; 1634 } 1635 1636 void loader_add_logical_device(const struct loader_instance *inst, struct loader_icd_term *icd_term, struct loader_device *dev) { 1637 dev->next = icd_term->logical_device_list; 1638 icd_term->logical_device_list = dev; 1639 } 1640 1641 void loader_remove_logical_device(const struct loader_instance *inst, struct loader_icd_term *icd_term, 1642 struct loader_device *found_dev, const VkAllocationCallbacks *pAllocator) { 1643 struct loader_device *dev, *prev_dev; 1644 1645 if (!icd_term || !found_dev) return; 1646 1647 prev_dev = NULL; 1648 dev = icd_term->logical_device_list; 1649 while (dev && dev != found_dev) { 1650 prev_dev = dev; 1651 dev = dev->next; 1652 } 1653 1654 if (prev_dev) 1655 prev_dev->next = found_dev->next; 1656 else 1657 icd_term->logical_device_list = found_dev->next; 1658 loader_destroy_logical_device(inst, found_dev, pAllocator); 1659 } 1660 1661 static void loader_icd_destroy(struct loader_instance *ptr_inst, struct loader_icd_term *icd_term, 1662 const VkAllocationCallbacks *pAllocator) { 1663 ptr_inst->total_icd_count--; 1664 for (struct loader_device *dev = icd_term->logical_device_list; dev;) { 1665 struct loader_device *next_dev = dev->next; 1666 loader_destroy_logical_device(ptr_inst, dev, pAllocator); 1667 dev = next_dev; 1668 } 1669 1670 loader_instance_heap_free(ptr_inst, icd_term); 1671 } 1672 1673 static struct loader_icd_term *loader_icd_create(const struct loader_instance *inst) { 1674 struct loader_icd_term *icd_term; 1675 1676 icd_term = loader_instance_heap_alloc(inst, sizeof(struct loader_icd_term), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1677 if (!icd_term) { 1678 return NULL; 1679 } 1680 1681 memset(icd_term, 0, sizeof(struct loader_icd_term)); 1682 1683 return icd_term; 1684 } 1685 1686 static struct loader_icd_term *loader_icd_add(struct loader_instance *ptr_inst, const struct loader_scanned_icd *scanned_icd) { 1687 struct loader_icd_term *icd_term; 1688 1689 icd_term = loader_icd_create(ptr_inst); 1690 if (!icd_term) { 1691 return NULL; 1692 } 1693 1694 icd_term->scanned_icd = scanned_icd; 1695 icd_term->this_instance = ptr_inst; 1696 1697 // Prepend to the list 1698 icd_term->next = ptr_inst->icd_terms; 1699 ptr_inst->icd_terms = icd_term; 1700 ptr_inst->total_icd_count++; 1701 1702 return icd_term; 1703 } 1704 1705 // Determine the ICD interface version to use. 1706 // @param icd 1707 // @param pVersion Output parameter indicating which version to use or 0 if 1708 // the negotiation API is not supported by the ICD 1709 // @return bool indicating true if the selected interface version is supported 1710 // by the loader, false indicates the version is not supported 1711 bool loader_get_icd_interface_version(PFN_vkNegotiateLoaderICDInterfaceVersion fp_negotiate_icd_version, uint32_t *pVersion) { 1712 if (fp_negotiate_icd_version == NULL) { 1713 // ICD does not support the negotiation API, it supports version 0 or 1 1714 // calling code must determine if it is version 0 or 1 1715 *pVersion = 0; 1716 } else { 1717 // ICD supports the negotiation API, so call it with the loader's 1718 // latest version supported 1719 *pVersion = CURRENT_LOADER_ICD_INTERFACE_VERSION; 1720 VkResult result = fp_negotiate_icd_version(pVersion); 1721 1722 if (result == VK_ERROR_INCOMPATIBLE_DRIVER) { 1723 // ICD no longer supports the loader's latest interface version so 1724 // fail loading the ICD 1725 return false; 1726 } 1727 } 1728 1729 #if MIN_SUPPORTED_LOADER_ICD_INTERFACE_VERSION > 0 1730 if (*pVersion < MIN_SUPPORTED_LOADER_ICD_INTERFACE_VERSION) { 1731 // Loader no longer supports the ICD's latest interface version so fail 1732 // loading the ICD 1733 return false; 1734 } 1735 #endif 1736 return true; 1737 } 1738 1739 void loader_scanned_icd_clear(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list) { 1740 if (0 != icd_tramp_list->capacity) { 1741 for (uint32_t i = 0; i < icd_tramp_list->count; i++) { 1742 loader_platform_close_library(icd_tramp_list->scanned_list[i].handle); 1743 loader_instance_heap_free(inst, icd_tramp_list->scanned_list[i].lib_name); 1744 } 1745 loader_instance_heap_free(inst, icd_tramp_list->scanned_list); 1746 icd_tramp_list->capacity = 0; 1747 icd_tramp_list->count = 0; 1748 icd_tramp_list->scanned_list = NULL; 1749 } 1750 } 1751 1752 static VkResult loader_scanned_icd_init(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list) { 1753 VkResult err = VK_SUCCESS; 1754 loader_scanned_icd_clear(inst, icd_tramp_list); 1755 icd_tramp_list->capacity = 8 * sizeof(struct loader_scanned_icd); 1756 icd_tramp_list->scanned_list = loader_instance_heap_alloc(inst, icd_tramp_list->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1757 if (NULL == icd_tramp_list->scanned_list) { 1758 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 1759 "loader_scanned_icd_init: Realloc failed for layer list when " 1760 "attempting to add new layer"); 1761 err = VK_ERROR_OUT_OF_HOST_MEMORY; 1762 } 1763 return err; 1764 } 1765 1766 static VkResult loader_scanned_icd_add(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list, 1767 const char *filename, uint32_t api_version) { 1768 loader_platform_dl_handle handle; 1769 PFN_vkCreateInstance fp_create_inst; 1770 PFN_vkEnumerateInstanceExtensionProperties fp_get_inst_ext_props; 1771 PFN_vkGetInstanceProcAddr fp_get_proc_addr; 1772 PFN_GetPhysicalDeviceProcAddr fp_get_phys_dev_proc_addr = NULL; 1773 PFN_vkNegotiateLoaderICDInterfaceVersion fp_negotiate_icd_version; 1774 struct loader_scanned_icd *new_scanned_icd; 1775 uint32_t interface_vers; 1776 VkResult res = VK_SUCCESS; 1777 1778 // TODO implement smarter opening/closing of libraries. For now this 1779 // function leaves libraries open and the scanned_icd_clear closes them 1780 handle = loader_platform_open_library(filename); 1781 if (NULL == handle) { 1782 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, loader_platform_open_library_error(filename)); 1783 goto out; 1784 } 1785 1786 // Get and settle on an ICD interface version 1787 fp_negotiate_icd_version = loader_platform_get_proc_address(handle, "vk_icdNegotiateLoaderICDInterfaceVersion"); 1788 1789 if (!loader_get_icd_interface_version(fp_negotiate_icd_version, &interface_vers)) { 1790 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 1791 "loader_scanned_icd_add: ICD %s doesn't support interface" 1792 " version compatible with loader, skip this ICD.", 1793 filename); 1794 goto out; 1795 } 1796 1797 fp_get_proc_addr = loader_platform_get_proc_address(handle, "vk_icdGetInstanceProcAddr"); 1798 if (NULL == fp_get_proc_addr) { 1799 assert(interface_vers == 0); 1800 // Use deprecated interface from version 0 1801 fp_get_proc_addr = loader_platform_get_proc_address(handle, "vkGetInstanceProcAddr"); 1802 if (NULL == fp_get_proc_addr) { 1803 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 1804 "loader_scanned_icd_add: Attempt to retrieve either " 1805 "\'vkGetInstanceProcAddr\' or " 1806 "\'vk_icdGetInstanceProcAddr\' from ICD %s failed.", 1807 filename); 1808 goto out; 1809 } else { 1810 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 1811 "loader_scanned_icd_add: Using deprecated ICD " 1812 "interface of \'vkGetInstanceProcAddr\' instead of " 1813 "\'vk_icdGetInstanceProcAddr\' for ICD %s", 1814 filename); 1815 } 1816 fp_create_inst = loader_platform_get_proc_address(handle, "vkCreateInstance"); 1817 if (NULL == fp_create_inst) { 1818 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 1819 "loader_scanned_icd_add: Failed querying " 1820 "\'vkCreateInstance\' via dlsym/loadlibrary for " 1821 "ICD %s", 1822 filename); 1823 goto out; 1824 } 1825 fp_get_inst_ext_props = loader_platform_get_proc_address(handle, "vkEnumerateInstanceExtensionProperties"); 1826 if (NULL == fp_get_inst_ext_props) { 1827 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 1828 "loader_scanned_icd_add: Could not get \'vkEnumerate" 1829 "InstanceExtensionProperties\' via dlsym/loadlibrary " 1830 "for ICD %s", 1831 filename); 1832 goto out; 1833 } 1834 } else { 1835 // Use newer interface version 1 or later 1836 if (interface_vers == 0) { 1837 interface_vers = 1; 1838 } 1839 1840 fp_create_inst = (PFN_vkCreateInstance)fp_get_proc_addr(NULL, "vkCreateInstance"); 1841 if (NULL == fp_create_inst) { 1842 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 1843 "loader_scanned_icd_add: Could not get " 1844 "\'vkCreateInstance\' via \'vk_icdGetInstanceProcAddr\'" 1845 " for ICD %s", 1846 filename); 1847 goto out; 1848 } 1849 fp_get_inst_ext_props = 1850 (PFN_vkEnumerateInstanceExtensionProperties)fp_get_proc_addr(NULL, "vkEnumerateInstanceExtensionProperties"); 1851 if (NULL == fp_get_inst_ext_props) { 1852 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 1853 "loader_scanned_icd_add: Could not get \'vkEnumerate" 1854 "InstanceExtensionProperties\' via " 1855 "\'vk_icdGetInstanceProcAddr\' for ICD %s", 1856 filename); 1857 goto out; 1858 } 1859 fp_get_phys_dev_proc_addr = loader_platform_get_proc_address(handle, "vk_icdGetPhysicalDeviceProcAddr"); 1860 } 1861 1862 // check for enough capacity 1863 if ((icd_tramp_list->count * sizeof(struct loader_scanned_icd)) >= icd_tramp_list->capacity) { 1864 void *new_ptr = loader_instance_heap_realloc(inst, icd_tramp_list->scanned_list, icd_tramp_list->capacity, 1865 icd_tramp_list->capacity * 2, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1866 if (NULL == new_ptr) { 1867 res = VK_ERROR_OUT_OF_HOST_MEMORY; 1868 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 1869 "loader_scanned_icd_add: Realloc failed on icd library list for ICD %s", filename); 1870 goto out; 1871 } 1872 icd_tramp_list->scanned_list = new_ptr; 1873 1874 // double capacity 1875 icd_tramp_list->capacity *= 2; 1876 } 1877 1878 new_scanned_icd = &(icd_tramp_list->scanned_list[icd_tramp_list->count]); 1879 new_scanned_icd->handle = handle; 1880 new_scanned_icd->api_version = api_version; 1881 new_scanned_icd->GetInstanceProcAddr = fp_get_proc_addr; 1882 new_scanned_icd->GetPhysicalDeviceProcAddr = fp_get_phys_dev_proc_addr; 1883 new_scanned_icd->EnumerateInstanceExtensionProperties = fp_get_inst_ext_props; 1884 new_scanned_icd->CreateInstance = fp_create_inst; 1885 new_scanned_icd->interface_version = interface_vers; 1886 1887 new_scanned_icd->lib_name = (char *)loader_instance_heap_alloc(inst, strlen(filename) + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1888 if (NULL == new_scanned_icd->lib_name) { 1889 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "loader_scanned_icd_add: Out of memory can't add ICD %s", filename); 1890 res = VK_ERROR_OUT_OF_HOST_MEMORY; 1891 goto out; 1892 } 1893 strcpy(new_scanned_icd->lib_name, filename); 1894 icd_tramp_list->count++; 1895 1896 out: 1897 1898 return res; 1899 } 1900 1901 static void loader_debug_init(void) { 1902 char *env, *orig; 1903 1904 if (g_loader_debug > 0) return; 1905 1906 g_loader_debug = 0; 1907 1908 // Parse comma-separated debug options 1909 orig = env = loader_getenv("VK_LOADER_DEBUG", NULL); 1910 while (env) { 1911 char *p = strchr(env, ','); 1912 size_t len; 1913 1914 if (p) 1915 len = p - env; 1916 else 1917 len = strlen(env); 1918 1919 if (len > 0) { 1920 if (strncmp(env, "all", len) == 0) { 1921 g_loader_debug = ~0u; 1922 g_loader_log_msgs = ~0u; 1923 } else if (strncmp(env, "warn", len) == 0) { 1924 g_loader_debug |= LOADER_WARN_BIT; 1925 g_loader_log_msgs |= VK_DEBUG_REPORT_WARNING_BIT_EXT; 1926 } else if (strncmp(env, "info", len) == 0) { 1927 g_loader_debug |= LOADER_INFO_BIT; 1928 g_loader_log_msgs |= VK_DEBUG_REPORT_INFORMATION_BIT_EXT; 1929 } else if (strncmp(env, "perf", len) == 0) { 1930 g_loader_debug |= LOADER_PERF_BIT; 1931 g_loader_log_msgs |= VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT; 1932 } else if (strncmp(env, "error", len) == 0) { 1933 g_loader_debug |= LOADER_ERROR_BIT; 1934 g_loader_log_msgs |= VK_DEBUG_REPORT_ERROR_BIT_EXT; 1935 } else if (strncmp(env, "debug", len) == 0) { 1936 g_loader_debug |= LOADER_DEBUG_BIT; 1937 g_loader_log_msgs |= VK_DEBUG_REPORT_DEBUG_BIT_EXT; 1938 } 1939 } 1940 1941 if (!p) break; 1942 1943 env = p + 1; 1944 } 1945 1946 loader_free_getenv(orig, NULL); 1947 } 1948 1949 void loader_initialize(void) { 1950 // initialize mutexs 1951 loader_platform_thread_create_mutex(&loader_lock); 1952 loader_platform_thread_create_mutex(&loader_json_lock); 1953 1954 // initialize logging 1955 loader_debug_init(); 1956 1957 // initial cJSON to use alloc callbacks 1958 cJSON_Hooks alloc_fns = { 1959 .malloc_fn = loader_instance_tls_heap_alloc, .free_fn = loader_instance_tls_heap_free, 1960 }; 1961 cJSON_InitHooks(&alloc_fns); 1962 } 1963 1964 struct loader_manifest_files { 1965 uint32_t count; 1966 char **filename_list; 1967 }; 1968 1969 void loader_release() { 1970 // release mutexs 1971 loader_platform_thread_delete_mutex(&loader_lock); 1972 loader_platform_thread_delete_mutex(&loader_json_lock); 1973 } 1974 1975 // Get next file or dirname given a string list or registry key path 1976 // 1977 // \returns 1978 // A pointer to first char in the next path. 1979 // The next path (or NULL) in the list is returned in next_path. 1980 // Note: input string is modified in some cases. PASS IN A COPY! 1981 static char *loader_get_next_path(char *path) { 1982 uint32_t len; 1983 char *next; 1984 1985 if (path == NULL) return NULL; 1986 next = strchr(path, PATH_SEPARATOR); 1987 if (next == NULL) { 1988 len = (uint32_t)strlen(path); 1989 next = path + len; 1990 } else { 1991 *next = '\0'; 1992 next++; 1993 } 1994 1995 return next; 1996 } 1997 1998 // Given a path which is absolute or relative, expand the path if relative or 1999 // leave the path unmodified if absolute. The base path to prepend to relative 2000 // paths is given in rel_base. 2001 // 2002 // @return - A string in out_fullpath of the full absolute path 2003 static void loader_expand_path(const char *path, const char *rel_base, size_t out_size, char *out_fullpath) { 2004 if (loader_platform_is_path_absolute(path)) { 2005 // do not prepend a base to an absolute path 2006 rel_base = ""; 2007 } 2008 2009 loader_platform_combine_path(out_fullpath, out_size, rel_base, path, NULL); 2010 } 2011 2012 // Given a filename (file) and a list of paths (dir), try to find an existing 2013 // file in the paths. If filename already is a path then no searching in the given paths. 2014 // 2015 // @return - A string in out_fullpath of either the full path or file. 2016 static void loader_get_fullpath(const char *file, const char *dirs, size_t out_size, char *out_fullpath) { 2017 if (!loader_platform_is_path(file) && *dirs) { 2018 char *dirs_copy, *dir, *next_dir; 2019 2020 dirs_copy = loader_stack_alloc(strlen(dirs) + 1); 2021 strcpy(dirs_copy, dirs); 2022 2023 // find if file exists after prepending paths in given list 2024 for (dir = dirs_copy; *dir && (next_dir = loader_get_next_path(dir)); dir = next_dir) { 2025 loader_platform_combine_path(out_fullpath, out_size, dir, file, NULL); 2026 if (loader_platform_file_exists(out_fullpath)) { 2027 return; 2028 } 2029 } 2030 } 2031 2032 (void)snprintf(out_fullpath, out_size, "%s", file); 2033 } 2034 2035 // Read a JSON file into a buffer. 2036 // 2037 // @return - A pointer to a cJSON object representing the JSON parse tree. 2038 // This returned buffer should be freed by caller. 2039 static VkResult loader_get_json(const struct loader_instance *inst, const char *filename, cJSON **json) { 2040 FILE *file = NULL; 2041 char *json_buf; 2042 size_t len; 2043 VkResult res = VK_SUCCESS; 2044 2045 if (NULL == json) { 2046 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "loader_get_json: Received invalid JSON file"); 2047 res = VK_ERROR_INITIALIZATION_FAILED; 2048 goto out; 2049 } 2050 2051 *json = NULL; 2052 2053 file = fopen(filename, "rb"); 2054 if (!file) { 2055 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "loader_get_json: Failed to open JSON file %s", filename); 2056 res = VK_ERROR_INITIALIZATION_FAILED; 2057 goto out; 2058 } 2059 fseek(file, 0, SEEK_END); 2060 len = ftell(file); 2061 fseek(file, 0, SEEK_SET); 2062 json_buf = (char *)loader_stack_alloc(len + 1); 2063 if (json_buf == NULL) { 2064 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2065 "loader_get_json: Failed to allocate space for " 2066 "JSON file %s buffer of length %d", 2067 filename, len); 2068 res = VK_ERROR_OUT_OF_HOST_MEMORY; 2069 goto out; 2070 } 2071 if (fread(json_buf, sizeof(char), len, file) != len) { 2072 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "loader_get_json: Failed to read JSON file %s.", filename); 2073 res = VK_ERROR_INITIALIZATION_FAILED; 2074 goto out; 2075 } 2076 json_buf[len] = '\0'; 2077 2078 // Parse text from file 2079 *json = cJSON_Parse(json_buf); 2080 if (*json == NULL) { 2081 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2082 "loader_get_json: Failed to parse JSON file %s, " 2083 "this is usually because something ran out of " 2084 "memory.", 2085 filename); 2086 res = VK_ERROR_OUT_OF_HOST_MEMORY; 2087 goto out; 2088 } 2089 2090 out: 2091 if (NULL != file) { 2092 fclose(file); 2093 } 2094 2095 return res; 2096 } 2097 2098 // Do a deep copy of the loader_layer_properties structure. 2099 VkResult loader_copy_layer_properties(const struct loader_instance *inst, struct loader_layer_properties *dst, 2100 struct loader_layer_properties *src) { 2101 uint32_t cnt, i; 2102 memcpy(dst, src, sizeof(*src)); 2103 dst->instance_extension_list.list = loader_instance_heap_alloc( 2104 inst, sizeof(VkExtensionProperties) * src->instance_extension_list.count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 2105 if (NULL == dst->instance_extension_list.list) { 2106 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2107 "loader_copy_layer_properties: Failed to allocate space " 2108 "for instance extension list of size %d.", 2109 src->instance_extension_list.count); 2110 return VK_ERROR_OUT_OF_HOST_MEMORY; 2111 } 2112 dst->instance_extension_list.capacity = sizeof(VkExtensionProperties) * src->instance_extension_list.count; 2113 memcpy(dst->instance_extension_list.list, src->instance_extension_list.list, dst->instance_extension_list.capacity); 2114 dst->device_extension_list.list = loader_instance_heap_alloc( 2115 inst, sizeof(struct loader_dev_ext_props) * src->device_extension_list.count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 2116 if (NULL == dst->device_extension_list.list) { 2117 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2118 "loader_copy_layer_properties: Failed to allocate space " 2119 "for device extension list of size %d.", 2120 src->device_extension_list.count); 2121 return VK_ERROR_OUT_OF_HOST_MEMORY; 2122 } 2123 memset(dst->device_extension_list.list, 0, sizeof(struct loader_dev_ext_props) * src->device_extension_list.count); 2124 2125 dst->device_extension_list.capacity = sizeof(struct loader_dev_ext_props) * src->device_extension_list.count; 2126 memcpy(dst->device_extension_list.list, src->device_extension_list.list, dst->device_extension_list.capacity); 2127 if (src->device_extension_list.count > 0 && src->device_extension_list.list->entrypoint_count > 0) { 2128 cnt = src->device_extension_list.list->entrypoint_count; 2129 dst->device_extension_list.list->entrypoints = 2130 loader_instance_heap_alloc(inst, sizeof(char *) * cnt, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 2131 if (NULL == dst->device_extension_list.list->entrypoints) { 2132 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2133 "loader_copy_layer_properties: Failed to allocate space " 2134 "for device extension entrypoint list of size %d.", 2135 cnt); 2136 return VK_ERROR_OUT_OF_HOST_MEMORY; 2137 } 2138 memset(dst->device_extension_list.list->entrypoints, 0, sizeof(char *) * cnt); 2139 2140 for (i = 0; i < cnt; i++) { 2141 dst->device_extension_list.list->entrypoints[i] = loader_instance_heap_alloc( 2142 inst, strlen(src->device_extension_list.list->entrypoints[i]) + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 2143 if (NULL == dst->device_extension_list.list->entrypoints[i]) { 2144 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2145 "loader_copy_layer_properties: Failed to " 2146 "allocate space for device extension entrypoint " 2147 "%d name of length", 2148 i); 2149 return VK_ERROR_OUT_OF_HOST_MEMORY; 2150 } 2151 strcpy(dst->device_extension_list.list->entrypoints[i], src->device_extension_list.list->entrypoints[i]); 2152 } 2153 } 2154 2155 return VK_SUCCESS; 2156 } 2157 2158 static bool loader_find_layer_name_list(const char *name, const struct loader_layer_list *layer_list) { 2159 if (NULL == layer_list) { 2160 return false; 2161 } 2162 for (uint32_t j = 0; j < layer_list->count; j++) { 2163 if (!strcmp(name, layer_list->list[j].info.layerName)) { 2164 return true; 2165 } 2166 } 2167 return false; 2168 } 2169 2170 bool loader_find_layer_name_array(const char *name, uint32_t layer_count, const char layer_list[][VK_MAX_EXTENSION_NAME_SIZE]) { 2171 if (!layer_list) return false; 2172 for (uint32_t j = 0; j < layer_count; j++) 2173 if (!strcmp(name, layer_list[j])) return true; 2174 return false; 2175 } 2176 2177 const char *std_validation_str = "VK_LAYER_LUNARG_standard_validation"; 2178 2179 // Adds the legacy VK_LAYER_LUNARG_standard_validation as a meta-layer if it 2180 // fails to find it in the list already. This is usually an indication that a 2181 // newer loader is being used with an older layer set. 2182 static bool loader_add_legacy_std_val_layer(const struct loader_instance *inst, struct loader_layer_list *layer_instance_list) { 2183 uint32_t i; 2184 bool success = true; 2185 struct loader_layer_properties *props = loader_get_next_layer_property(inst, layer_instance_list); 2186 const char std_validation_names[6][VK_MAX_EXTENSION_NAME_SIZE] = { 2187 "VK_LAYER_GOOGLE_threading", "VK_LAYER_LUNARG_parameter_validation", "VK_LAYER_LUNARG_object_tracker", 2188 "VK_LAYER_LUNARG_core_validation", "VK_LAYER_GOOGLE_unique_objects"}; 2189 uint32_t layer_count = sizeof(std_validation_names) / sizeof(std_validation_names[0]); 2190 2191 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, 2192 "Adding VK_LAYER_LUNARG_standard_validation using the loader legacy path. This is" 2193 " not an error."); 2194 2195 if (NULL == props) { 2196 goto out; 2197 } 2198 2199 memset(props, 0, sizeof(struct loader_layer_properties)); 2200 props->type_flags = VK_LAYER_TYPE_FLAG_INSTANCE_LAYER | VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER | VK_LAYER_TYPE_FLAG_META_LAYER; 2201 strncpy(props->info.description, "LunarG Standard Validation Layer", sizeof(props->info.description)); 2202 props->info.implementationVersion = 1; 2203 strncpy(props->info.layerName, std_validation_str, sizeof(props->info.layerName)); 2204 props->info.specVersion = VK_MAKE_VERSION(1, 0, VK_HEADER_VERSION); 2205 2206 props->component_layer_names = 2207 loader_instance_heap_alloc(inst, sizeof(char[MAX_STRING_SIZE]) * layer_count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 2208 if (NULL == props->component_layer_names) { 2209 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2210 "Failed to allocate space for legacy VK_LAYER_LUNARG_standard_validation" 2211 " meta-layer component_layers information."); 2212 success = false; 2213 goto out; 2214 } 2215 for (i = 0; i < layer_count; i++) { 2216 strncpy(props->component_layer_names[i], std_validation_names[i], MAX_STRING_SIZE - 1); 2217 props->component_layer_names[i][MAX_STRING_SIZE - 1] = '\0'; 2218 } 2219 2220 out: 2221 2222 if (!success && NULL != props && NULL != props->component_layer_names) { 2223 loader_instance_heap_free(inst, props->component_layer_names); 2224 props->component_layer_names = NULL; 2225 } 2226 2227 return success; 2228 } 2229 2230 // Verify that all component layers in a meta-layer are valid. 2231 static bool verify_meta_layer_comp_layers(const struct loader_instance *inst, struct loader_layer_properties *prop, 2232 struct loader_layer_list *instance_layers) { 2233 bool success = true; 2234 const uint32_t expected_major = VK_VERSION_MAJOR(prop->info.specVersion); 2235 const uint32_t expected_minor = VK_VERSION_MINOR(prop->info.specVersion); 2236 2237 for (uint32_t comp_layer = 0; comp_layer < prop->num_component_layers; comp_layer++) { 2238 if (!loader_find_layer_name_list(prop->component_layer_names[comp_layer], instance_layers)) { 2239 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 2240 "Meta-layer %s can't find component layer %s at index %d." 2241 " Skipping this layer.", 2242 prop->info.layerName, prop->component_layer_names[comp_layer], comp_layer); 2243 success = false; 2244 break; 2245 } else { 2246 struct loader_layer_properties *comp_prop = 2247 loader_get_layer_property(prop->component_layer_names[comp_layer], instance_layers); 2248 if (comp_prop == NULL) { 2249 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 2250 "Meta-layer %s can't find property for component layer %s at index %d." 2251 " Skipping this layer.", 2252 prop->info.layerName, prop->component_layer_names[comp_layer], comp_layer); 2253 success = false; 2254 break; 2255 } 2256 2257 // Check the version of each layer, they need to at least match MAJOR and MINOR 2258 uint32_t cur_major = VK_VERSION_MAJOR(comp_prop->info.specVersion); 2259 uint32_t cur_minor = VK_VERSION_MINOR(comp_prop->info.specVersion); 2260 if (cur_major != expected_major || cur_minor != expected_minor) { 2261 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 2262 "Meta-layer uses API version %d.%d, but component layer %d uses API " 2263 "version %d.%d. Skipping this layer.", 2264 expected_major, expected_minor, comp_layer, cur_major, cur_minor); 2265 success = false; 2266 break; 2267 } 2268 2269 // Make sure the layer isn't using it's own name 2270 if (!strcmp(prop->info.layerName, prop->component_layer_names[comp_layer])) { 2271 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 2272 "Meta-layer %s lists itself in its component layer list at index %d." 2273 " Skipping this layer.", 2274 prop->info.layerName, comp_layer); 2275 success = false; 2276 break; 2277 } 2278 if (comp_prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER) { 2279 loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, 2280 "verify_meta_layer_comp_layers: Adding meta-layer %s which also contains meta-layer %s", 2281 prop->info.layerName, comp_prop->info.layerName); 2282 2283 // Make sure if the layer is using a meta-layer in its component list that we also verify that. 2284 if (!verify_meta_layer_comp_layers(inst, comp_prop, instance_layers)) { 2285 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 2286 "Meta-layer %s component layer %s can not find all component layers." 2287 " Skipping this layer.", 2288 prop->info.layerName, prop->component_layer_names[comp_layer]); 2289 success = false; 2290 break; 2291 } 2292 } 2293 2294 // Add any instance and device extensions from component layers to this layer 2295 // list, so that anyone querying extensions will only need to look at the meta-layer 2296 for (uint32_t ext = 0; ext < comp_prop->instance_extension_list.count; ext++) { 2297 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Meta-layer %s component layer %s adding instance extension %s", 2298 prop->info.layerName, prop->component_layer_names[comp_layer], 2299 comp_prop->instance_extension_list.list[ext].extensionName); 2300 if (!has_vk_extension_property(&comp_prop->instance_extension_list.list[ext], &prop->instance_extension_list)) { 2301 loader_add_to_ext_list(inst, &prop->instance_extension_list, 1, &comp_prop->instance_extension_list.list[ext]); 2302 } 2303 } 2304 2305 for (uint32_t ext = 0; ext < comp_prop->device_extension_list.count; ext++) { 2306 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Meta-layer %s component layer %s adding device extension %s", 2307 prop->info.layerName, prop->component_layer_names[comp_layer], 2308 comp_prop->device_extension_list.list[ext].props.extensionName); 2309 if (!has_vk_dev_ext_property(&comp_prop->device_extension_list.list[ext].props, &prop->device_extension_list)) { 2310 loader_add_to_dev_ext_list(inst, &prop->device_extension_list, 2311 &comp_prop->device_extension_list.list[ext].props, 0, NULL); 2312 } 2313 } 2314 } 2315 } 2316 if (success) { 2317 loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, "Meta-layer %s all %d component layers appear to be valid.", 2318 prop->info.layerName, prop->num_component_layers); 2319 } 2320 return success; 2321 } 2322 2323 // Verify that all meta-layers in a layer list are valid. 2324 static void verify_all_meta_layers(const struct loader_instance *inst, struct loader_layer_list *instance_layers) { 2325 for (int32_t i = 0; i < (int32_t)instance_layers->count; i++) { 2326 struct loader_layer_properties *prop = &instance_layers->list[i]; 2327 2328 // If this is a meta-layer, make sure it is valid 2329 if ((prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER) && !verify_meta_layer_comp_layers(inst, prop, instance_layers)) { 2330 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, 2331 "Removing meta-layer %s from instance layer list since it appears invalid.", prop->info.layerName); 2332 2333 // Delete the component layers 2334 loader_instance_heap_free(inst, prop->component_layer_names); 2335 2336 // Remove the current invalid meta-layer from the layer list. Use memmove since we are 2337 // overlapping the source and destination addresses. 2338 memmove(&instance_layers->list[i], &instance_layers->list[i + 1], 2339 sizeof(struct loader_layer_properties) * (instance_layers->count - 1 - i)); 2340 2341 // Decrement the count (because we now have one less) and decrement the loop index since we need to 2342 // re-check this index. 2343 instance_layers->count--; 2344 i--; 2345 } 2346 } 2347 } 2348 2349 // This structure is used to store the json file version 2350 // in a more manageable way. 2351 typedef struct { 2352 uint16_t major; 2353 uint16_t minor; 2354 uint16_t patch; 2355 } layer_json_version; 2356 2357 static inline bool is_valid_layer_json_version(const layer_json_version *layer_json) { 2358 // Supported versions are: 1.0.0, 1.0.1, 1.1.0, 1.1.1, and 1.1.2. 2359 if ((layer_json->major == 1 && layer_json->minor == 1 && layer_json->patch < 3) || 2360 (layer_json->major == 1 && layer_json->minor == 0 && layer_json->patch < 2)) { 2361 return true; 2362 } 2363 return false; 2364 } 2365 2366 static inline bool layer_json_supports_layers_tag(const layer_json_version *layer_json) { 2367 // Supported versions started in 1.0.1, so anything newer 2368 if ((layer_json->major > 1 || layer_json->minor > 0 || layer_json->patch > 1)) { 2369 return true; 2370 } 2371 return false; 2372 } 2373 2374 static inline bool layer_json_supports_pre_instance_tag(const layer_json_version *layer_json) { 2375 // Supported versions started in 1.1.2, so anything newer 2376 return layer_json->major > 1 || layer_json->minor > 1 || (layer_json->minor == 1 && layer_json->patch > 1); 2377 } 2378 2379 static VkResult loader_read_json_layer(const struct loader_instance *inst, struct loader_layer_list *layer_instance_list, 2380 cJSON *layer_node, layer_json_version version, cJSON *item, cJSON *disable_environment, 2381 bool is_implicit, char *filename) { 2382 char *temp; 2383 char *name, *type, *library_path_str, *api_version; 2384 char *implementation_version, *description; 2385 cJSON *ext_item, *library_path, *component_layers; 2386 VkExtensionProperties ext_prop; 2387 VkResult result = VK_ERROR_INITIALIZATION_FAILED; 2388 struct loader_layer_properties *props = NULL; 2389 int i, j; 2390 2391 // The following are required in the "layer" object: 2392 // (required) "name" 2393 // (required) "type" 2394 // (required) "library_path" 2395 // (required) "api_version" 2396 // (required) "implementation_version" 2397 // (required) "description" 2398 // (required for implicit layers) "disable_environment" 2399 #define GET_JSON_OBJECT(node, var) \ 2400 { \ 2401 var = cJSON_GetObjectItem(node, #var); \ 2402 if (var == NULL) { \ 2403 layer_node = layer_node->next; \ 2404 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, \ 2405 "Didn't find required layer object %s in manifest " \ 2406 "JSON file, skipping this layer", \ 2407 #var); \ 2408 goto out; \ 2409 } \ 2410 } 2411 #define GET_JSON_ITEM(node, var) \ 2412 { \ 2413 item = cJSON_GetObjectItem(node, #var); \ 2414 if (item == NULL) { \ 2415 layer_node = layer_node->next; \ 2416 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, \ 2417 "Didn't find required layer value %s in manifest JSON " \ 2418 "file, skipping this layer", \ 2419 #var); \ 2420 goto out; \ 2421 } \ 2422 temp = cJSON_Print(item); \ 2423 if (temp == NULL) { \ 2424 layer_node = layer_node->next; \ 2425 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, \ 2426 "Problem accessing layer value %s in manifest JSON " \ 2427 "file, skipping this layer", \ 2428 #var); \ 2429 result = VK_ERROR_OUT_OF_HOST_MEMORY; \ 2430 goto out; \ 2431 } \ 2432 temp[strlen(temp) - 1] = '\0'; \ 2433 var = loader_stack_alloc(strlen(temp) + 1); \ 2434 strcpy(var, &temp[1]); \ 2435 cJSON_Free(temp); \ 2436 } 2437 GET_JSON_ITEM(layer_node, name) 2438 GET_JSON_ITEM(layer_node, type) 2439 GET_JSON_ITEM(layer_node, api_version) 2440 GET_JSON_ITEM(layer_node, implementation_version) 2441 GET_JSON_ITEM(layer_node, description) 2442 2443 // Add list entry 2444 if (!strcmp(type, "DEVICE")) { 2445 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, "Device layers are deprecated skipping this layer"); 2446 layer_node = layer_node->next; 2447 goto out; 2448 } 2449 2450 // Allow either GLOBAL or INSTANCE type interchangeably to handle 2451 // layers that must work with older loaders 2452 if (!strcmp(type, "INSTANCE") || !strcmp(type, "GLOBAL")) { 2453 if (layer_instance_list == NULL) { 2454 layer_node = layer_node->next; 2455 goto out; 2456 } 2457 props = loader_get_next_layer_property(inst, layer_instance_list); 2458 if (NULL == props) { 2459 // Error already triggered in loader_get_next_layer_property. 2460 result = VK_ERROR_OUT_OF_HOST_MEMORY; 2461 goto out; 2462 } 2463 props->type_flags = VK_LAYER_TYPE_FLAG_INSTANCE_LAYER; 2464 if (!is_implicit) { 2465 props->type_flags |= VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER; 2466 } 2467 } else { 2468 layer_node = layer_node->next; 2469 goto out; 2470 } 2471 2472 // Library path no longer required unless component_layers is also not defined 2473 library_path = cJSON_GetObjectItem(layer_node, "library_path"); 2474 component_layers = cJSON_GetObjectItem(layer_node, "component_layers"); 2475 if (NULL != library_path) { 2476 if (NULL != component_layers) { 2477 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 2478 "Indicating meta-layer-specific component_layers, but also " 2479 "defining layer library path. Both are not compatible, so " 2480 "skipping this layer"); 2481 goto out; 2482 } 2483 props->num_component_layers = 0; 2484 props->component_layer_names = NULL; 2485 2486 temp = cJSON_Print(library_path); 2487 if (NULL == temp) { 2488 layer_node = layer_node->next; 2489 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 2490 "Problem accessing layer value library_path in manifest JSON " 2491 "file, skipping this layer"); 2492 result = VK_ERROR_OUT_OF_HOST_MEMORY; 2493 goto out; 2494 } 2495 temp[strlen(temp) - 1] = '\0'; 2496 library_path_str = loader_stack_alloc(strlen(temp) + 1); 2497 strcpy(library_path_str, &temp[1]); 2498 cJSON_Free(temp); 2499 2500 char *fullpath = props->lib_name; 2501 char *rel_base; 2502 if (NULL != library_path_str) { 2503 if (loader_platform_is_path(library_path_str)) { 2504 // A relative or absolute path 2505 char *name_copy = loader_stack_alloc(strlen(filename) + 1); 2506 strcpy(name_copy, filename); 2507 rel_base = loader_platform_dirname(name_copy); 2508 loader_expand_path(library_path_str, rel_base, MAX_STRING_SIZE, fullpath); 2509 } else { 2510 // A filename which is assumed in a system directory 2511 loader_get_fullpath(library_path_str, DEFAULT_VK_LAYERS_PATH, MAX_STRING_SIZE, fullpath); 2512 } 2513 } 2514 } else if (NULL != component_layers) { 2515 if (version.major == 1 && (version.minor < 1 || version.patch < 1)) { 2516 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 2517 "Indicating meta-layer-specific component_layers, but using older " 2518 "JSON file version."); 2519 } 2520 int count = cJSON_GetArraySize(component_layers); 2521 props->num_component_layers = count; 2522 2523 // Allocate buffer for layer names 2524 props->component_layer_names = 2525 loader_instance_heap_alloc(inst, sizeof(char[MAX_STRING_SIZE]) * count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 2526 if (NULL == props->component_layer_names) { 2527 result = VK_ERROR_OUT_OF_HOST_MEMORY; 2528 goto out; 2529 } 2530 2531 // Copy the component layers into the array 2532 for (i = 0; i < count; i++) { 2533 cJSON *comp_layer = cJSON_GetArrayItem(component_layers, i); 2534 if (NULL != comp_layer) { 2535 temp = cJSON_Print(comp_layer); 2536 if (NULL == temp) { 2537 result = VK_ERROR_OUT_OF_HOST_MEMORY; 2538 goto out; 2539 } 2540 temp[strlen(temp) - 1] = '\0'; 2541 strncpy(props->component_layer_names[i], temp + 1, MAX_STRING_SIZE - 1); 2542 props->component_layer_names[i][MAX_STRING_SIZE - 1] = '\0'; 2543 cJSON_Free(temp); 2544 } 2545 } 2546 2547 // This is now, officially, a meta-layer 2548 props->type_flags |= VK_LAYER_TYPE_FLAG_META_LAYER; 2549 loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, "Encountered meta-layer %s", name); 2550 2551 // Make sure we set up other things so we head down the correct branches below 2552 library_path_str = NULL; 2553 } else { 2554 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 2555 "Layer missing both library_path and component_layers fields. One or the " 2556 "other MUST be defined. Skipping this layer"); 2557 goto out; 2558 } 2559 2560 if (is_implicit) { 2561 GET_JSON_OBJECT(layer_node, disable_environment) 2562 } 2563 #undef GET_JSON_ITEM 2564 #undef GET_JSON_OBJECT 2565 2566 strncpy(props->info.layerName, name, sizeof(props->info.layerName)); 2567 props->info.layerName[sizeof(props->info.layerName) - 1] = '\0'; 2568 props->info.specVersion = loader_make_version(api_version); 2569 props->info.implementationVersion = atoi(implementation_version); 2570 strncpy((char *)props->info.description, description, sizeof(props->info.description)); 2571 props->info.description[sizeof(props->info.description) - 1] = '\0'; 2572 if (is_implicit) { 2573 if (!disable_environment || !disable_environment->child) { 2574 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 2575 "Didn't find required layer child value disable_environment" 2576 "in manifest JSON file, skipping this layer"); 2577 layer_node = layer_node->next; 2578 goto out; 2579 } 2580 strncpy(props->disable_env_var.name, disable_environment->child->string, sizeof(props->disable_env_var.name)); 2581 props->disable_env_var.name[sizeof(props->disable_env_var.name) - 1] = '\0'; 2582 strncpy(props->disable_env_var.value, disable_environment->child->valuestring, sizeof(props->disable_env_var.value)); 2583 props->disable_env_var.value[sizeof(props->disable_env_var.value) - 1] = '\0'; 2584 } 2585 2586 // Now get all optional items and objects and put in list: 2587 // functions 2588 // instance_extensions 2589 // device_extensions 2590 // enable_environment (implicit layers only) 2591 #define GET_JSON_OBJECT(node, var) \ 2592 { var = cJSON_GetObjectItem(node, #var); } 2593 #define GET_JSON_ITEM(node, var) \ 2594 { \ 2595 item = cJSON_GetObjectItem(node, #var); \ 2596 if (item != NULL) { \ 2597 temp = cJSON_Print(item); \ 2598 if (temp != NULL) { \ 2599 temp[strlen(temp) - 1] = '\0'; \ 2600 var = loader_stack_alloc(strlen(temp) + 1); \ 2601 strcpy(var, &temp[1]); \ 2602 cJSON_Free(temp); \ 2603 } else { \ 2604 result = VK_ERROR_OUT_OF_HOST_MEMORY; \ 2605 goto out; \ 2606 } \ 2607 } \ 2608 } 2609 2610 cJSON *instance_extensions, *device_extensions, *functions, *enable_environment; 2611 cJSON *entrypoints = NULL; 2612 char *vkGetInstanceProcAddr = NULL; 2613 char *vkGetDeviceProcAddr = NULL; 2614 char *vkNegotiateLoaderLayerInterfaceVersion = NULL; 2615 char *spec_version = NULL; 2616 char **entry_array = NULL; 2617 2618 // Layer interface functions 2619 // vkGetInstanceProcAddr 2620 // vkGetDeviceProcAddr 2621 // vkNegotiateLoaderLayerInterfaceVersion (starting with JSON file 1.1.0) 2622 GET_JSON_OBJECT(layer_node, functions) 2623 if (functions != NULL) { 2624 if (version.major > 1 || version.minor >= 1) { 2625 GET_JSON_ITEM(functions, vkNegotiateLoaderLayerInterfaceVersion) 2626 if (vkNegotiateLoaderLayerInterfaceVersion != NULL) 2627 strncpy(props->functions.str_negotiate_interface, vkNegotiateLoaderLayerInterfaceVersion, 2628 sizeof(props->functions.str_negotiate_interface)); 2629 props->functions.str_negotiate_interface[sizeof(props->functions.str_negotiate_interface) - 1] = '\0'; 2630 } else { 2631 props->functions.str_negotiate_interface[0] = '\0'; 2632 } 2633 GET_JSON_ITEM(functions, vkGetInstanceProcAddr) 2634 GET_JSON_ITEM(functions, vkGetDeviceProcAddr) 2635 if (vkGetInstanceProcAddr != NULL) { 2636 strncpy(props->functions.str_gipa, vkGetInstanceProcAddr, sizeof(props->functions.str_gipa)); 2637 if (version.major > 1 || version.minor >= 1) { 2638 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 2639 "Indicating layer-specific vkGetInstanceProcAddr " 2640 "function is deprecated starting with JSON file " 2641 "version 1.1.0. Instead, use the new " 2642 "vkNegotiateLayerInterfaceVersion function to " 2643 "return the GetInstanceProcAddr function for this" 2644 "layer"); 2645 } 2646 } 2647 props->functions.str_gipa[sizeof(props->functions.str_gipa) - 1] = '\0'; 2648 if (vkGetDeviceProcAddr != NULL) { 2649 strncpy(props->functions.str_gdpa, vkGetDeviceProcAddr, sizeof(props->functions.str_gdpa)); 2650 if (version.major > 1 || version.minor >= 1) { 2651 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 2652 "Indicating layer-specific vkGetDeviceProcAddr " 2653 "function is deprecated starting with JSON file " 2654 "version 1.1.0. Instead, use the new " 2655 "vkNegotiateLayerInterfaceVersion function to " 2656 "return the GetDeviceProcAddr function for this" 2657 "layer"); 2658 } 2659 } 2660 props->functions.str_gdpa[sizeof(props->functions.str_gdpa) - 1] = '\0'; 2661 } 2662 2663 // instance_extensions 2664 // array of { 2665 // name 2666 // spec_version 2667 // } 2668 GET_JSON_OBJECT(layer_node, instance_extensions) 2669 if (instance_extensions != NULL) { 2670 int count = cJSON_GetArraySize(instance_extensions); 2671 for (i = 0; i < count; i++) { 2672 ext_item = cJSON_GetArrayItem(instance_extensions, i); 2673 GET_JSON_ITEM(ext_item, name) 2674 if (name != NULL) { 2675 strncpy(ext_prop.extensionName, name, sizeof(ext_prop.extensionName)); 2676 ext_prop.extensionName[sizeof(ext_prop.extensionName) - 1] = '\0'; 2677 } 2678 GET_JSON_ITEM(ext_item, spec_version) 2679 if (NULL != spec_version) { 2680 ext_prop.specVersion = atoi(spec_version); 2681 } else { 2682 ext_prop.specVersion = 0; 2683 } 2684 bool ext_unsupported = wsi_unsupported_instance_extension(&ext_prop); 2685 if (!ext_unsupported) { 2686 loader_add_to_ext_list(inst, &props->instance_extension_list, 1, &ext_prop); 2687 } 2688 } 2689 } 2690 2691 // device_extensions 2692 // array of { 2693 // name 2694 // spec_version 2695 // entrypoints 2696 // } 2697 GET_JSON_OBJECT(layer_node, device_extensions) 2698 if (device_extensions != NULL) { 2699 int count = cJSON_GetArraySize(device_extensions); 2700 for (i = 0; i < count; i++) { 2701 ext_item = cJSON_GetArrayItem(device_extensions, i); 2702 GET_JSON_ITEM(ext_item, name) 2703 GET_JSON_ITEM(ext_item, spec_version) 2704 if (name != NULL) { 2705 strncpy(ext_prop.extensionName, name, sizeof(ext_prop.extensionName)); 2706 ext_prop.extensionName[sizeof(ext_prop.extensionName) - 1] = '\0'; 2707 } 2708 if (NULL != spec_version) { 2709 ext_prop.specVersion = atoi(spec_version); 2710 } else { 2711 ext_prop.specVersion = 0; 2712 } 2713 // entrypoints = cJSON_GetObjectItem(ext_item, "entrypoints"); 2714 GET_JSON_OBJECT(ext_item, entrypoints) 2715 int entry_count; 2716 if (entrypoints == NULL) { 2717 loader_add_to_dev_ext_list(inst, &props->device_extension_list, &ext_prop, 0, NULL); 2718 continue; 2719 } 2720 entry_count = cJSON_GetArraySize(entrypoints); 2721 if (entry_count) { 2722 entry_array = (char **)loader_stack_alloc(sizeof(char *) * entry_count); 2723 } 2724 for (j = 0; j < entry_count; j++) { 2725 ext_item = cJSON_GetArrayItem(entrypoints, j); 2726 if (ext_item != NULL) { 2727 temp = cJSON_Print(ext_item); 2728 if (NULL == temp) { 2729 entry_array[j] = NULL; 2730 result = VK_ERROR_OUT_OF_HOST_MEMORY; 2731 goto out; 2732 } 2733 temp[strlen(temp) - 1] = '\0'; 2734 entry_array[j] = loader_stack_alloc(strlen(temp) + 1); 2735 strcpy(entry_array[j], &temp[1]); 2736 cJSON_Free(temp); 2737 } 2738 } 2739 loader_add_to_dev_ext_list(inst, &props->device_extension_list, &ext_prop, entry_count, entry_array); 2740 } 2741 } 2742 if (is_implicit) { 2743 GET_JSON_OBJECT(layer_node, enable_environment) 2744 2745 // enable_environment is optional 2746 if (enable_environment) { 2747 strncpy(props->enable_env_var.name, enable_environment->child->string, sizeof(props->enable_env_var.name)); 2748 props->enable_env_var.name[sizeof(props->enable_env_var.name) - 1] = '\0'; 2749 strncpy(props->enable_env_var.value, enable_environment->child->valuestring, sizeof(props->enable_env_var.value)); 2750 props->enable_env_var.value[sizeof(props->enable_env_var.value) - 1] = '\0'; 2751 } 2752 } 2753 2754 // Read in the pre-instance stuff 2755 cJSON *pre_instance = cJSON_GetObjectItem(layer_node, "pre_instance_functions"); 2756 if (pre_instance) { 2757 if (!layer_json_supports_pre_instance_tag(&version)) { 2758 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2759 "Found pre_instance_functions section in layer from \"%s\". " 2760 "This section is only valid in manifest version 1.1.2 or later. The section will be ignored", 2761 filename); 2762 } else if (!is_implicit) { 2763 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 2764 "Found pre_instance_functions section in explicit layer from " 2765 "\"%s\". This section is only valid in implicit layers. The section will be ignored", 2766 filename); 2767 } else { 2768 cJSON *inst_ext_json = cJSON_GetObjectItem(pre_instance, "vkEnumerateInstanceExtensionProperties"); 2769 if (inst_ext_json) { 2770 char *inst_ext_name = cJSON_Print(inst_ext_json); 2771 size_t len = strlen(inst_ext_name) >= MAX_STRING_SIZE ? MAX_STRING_SIZE - 3 : strlen(inst_ext_name) - 2; 2772 strncpy(props->pre_instance_functions.enumerate_instance_extension_properties, inst_ext_name + 1, len); 2773 props->pre_instance_functions.enumerate_instance_extension_properties[len] = '\0'; 2774 cJSON_Free(inst_ext_name); 2775 } 2776 2777 cJSON *inst_layer_json = cJSON_GetObjectItem(pre_instance, "vkEnumerateInstanceLayerProperties"); 2778 if (inst_layer_json) { 2779 char *inst_layer_name = cJSON_Print(inst_layer_json); 2780 size_t len = strlen(inst_layer_name) >= MAX_STRING_SIZE ? MAX_STRING_SIZE - 3 : strlen(inst_layer_name) - 2; 2781 strncpy(props->pre_instance_functions.enumerate_instance_layer_properties, inst_layer_name + 1, len); 2782 props->pre_instance_functions.enumerate_instance_layer_properties[len] = '\0'; 2783 cJSON_Free(inst_layer_name); 2784 } 2785 } 2786 } 2787 2788 result = VK_SUCCESS; 2789 2790 out: 2791 2792 #undef GET_JSON_ITEM 2793 #undef GET_JSON_OBJECT 2794 2795 if (VK_SUCCESS != result && NULL != props) { 2796 props->num_component_layers = 0; 2797 if (NULL != props->component_layer_names) { 2798 loader_instance_heap_free(inst, props->component_layer_names); 2799 } 2800 props->component_layer_names = NULL; 2801 } 2802 2803 return result; 2804 } 2805 2806 // Given a cJSON struct (json) of the top level JSON object from layer manifest 2807 // file, add entry to the layer_list. Fill out the layer_properties in this list 2808 // entry from the input cJSON object. 2809 // 2810 // \returns 2811 // void 2812 // layer_list has a new entry and initialized accordingly. 2813 // If the json input object does not have all the required fields no entry 2814 // is added to the list. 2815 static VkResult loader_add_layer_properties(const struct loader_instance *inst, struct loader_layer_list *layer_instance_list, 2816 cJSON *json, bool is_implicit, char *filename) { 2817 // The following Fields in layer manifest file that are required: 2818 // - "file_format_version" 2819 // - If more than one "layer" object are used, then the "layers" array is 2820 // required 2821 VkResult result = VK_ERROR_INITIALIZATION_FAILED; 2822 cJSON *item, *layers_node, *layer_node; 2823 layer_json_version json_version = {0, 0, 0}; 2824 char *vers_tok; 2825 cJSON *disable_environment = NULL; 2826 item = cJSON_GetObjectItem(json, "file_format_version"); 2827 if (item == NULL) { 2828 goto out; 2829 } 2830 char *file_vers = cJSON_PrintUnformatted(item); 2831 if (NULL == file_vers) { 2832 goto out; 2833 } 2834 loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, "Found manifest file %s, version %s", filename, file_vers); 2835 // Get the major/minor/and patch as integers for easier comparison 2836 vers_tok = strtok(file_vers, ".\"\n\r"); 2837 if (NULL != vers_tok) { 2838 json_version.major = (uint16_t)atoi(vers_tok); 2839 vers_tok = strtok(NULL, ".\"\n\r"); 2840 if (NULL != vers_tok) { 2841 json_version.minor = (uint16_t)atoi(vers_tok); 2842 vers_tok = strtok(NULL, ".\"\n\r"); 2843 if (NULL != vers_tok) { 2844 json_version.patch = (uint16_t)atoi(vers_tok); 2845 } 2846 } 2847 } 2848 2849 if (!is_valid_layer_json_version(&json_version)) { 2850 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 2851 "loader_add_layer_properties: %s invalid layer " 2852 "manifest file version %d.%d.%d. May cause errors.", 2853 filename, json_version.major, json_version.minor, json_version.patch); 2854 } 2855 cJSON_Free(file_vers); 2856 2857 // If "layers" is present, read in the array of layer objects 2858 layers_node = cJSON_GetObjectItem(json, "layers"); 2859 if (layers_node != NULL) { 2860 int numItems = cJSON_GetArraySize(layers_node); 2861 if (!layer_json_supports_layers_tag(&json_version)) { 2862 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 2863 "loader_add_layer_properties: \'layers\' tag not " 2864 "supported until file version 1.0.1, but %s is " 2865 "reporting version %s", 2866 filename, file_vers); 2867 } 2868 for (int curLayer = 0; curLayer < numItems; curLayer++) { 2869 layer_node = cJSON_GetArrayItem(layers_node, curLayer); 2870 if (layer_node == NULL) { 2871 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 2872 "loader_add_layer_properties: Can not find " 2873 "\'layers\' array element %d object in manifest " 2874 "JSON file %s. Skipping this file", 2875 curLayer, filename); 2876 goto out; 2877 } 2878 result = loader_read_json_layer(inst, layer_instance_list, layer_node, json_version, item, disable_environment, 2879 is_implicit, filename); 2880 } 2881 } else { 2882 // Otherwise, try to read in individual layers 2883 layer_node = cJSON_GetObjectItem(json, "layer"); 2884 if (layer_node == NULL) { 2885 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 2886 "loader_add_layer_properties: Can not find \'layer\' " 2887 "object in manifest JSON file %s. Skipping this file.", 2888 filename); 2889 goto out; 2890 } 2891 // Loop through all "layer" objects in the file to get a count of them 2892 // first. 2893 uint16_t layer_count = 0; 2894 cJSON *tempNode = layer_node; 2895 do { 2896 tempNode = tempNode->next; 2897 layer_count++; 2898 } while (tempNode != NULL); 2899 2900 // Throw a warning if we encounter multiple "layer" objects in file 2901 // versions newer than 1.0.0. Having multiple objects with the same 2902 // name at the same level is actually a JSON standard violation. 2903 if (layer_count > 1 && layer_json_supports_layers_tag(&json_version)) { 2904 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2905 "loader_add_layer_properties: Multiple \'layer\' nodes" 2906 " are deprecated starting in file version \"1.0.1\". " 2907 "Please use \'layers\' : [] array instead in %s.", 2908 filename); 2909 } else { 2910 do { 2911 result = loader_read_json_layer(inst, layer_instance_list, layer_node, json_version, item, disable_environment, 2912 is_implicit, filename); 2913 layer_node = layer_node->next; 2914 } while (layer_node != NULL); 2915 } 2916 } 2917 2918 out: 2919 2920 return result; 2921 } 2922 2923 // Find the Vulkan library manifest files. 2924 // 2925 // This function scans the "location" or "env_override" directories/files 2926 // for a list of JSON manifest files. If env_override is non-NULL 2927 // and has a valid value. Then the location is ignored. Otherwise 2928 // location is used to look for manifest files. The location 2929 // is interpreted as Registry path on Windows and a directory path(s) 2930 // on Linux. "home_location" is an additional directory in the users home 2931 // directory to look at. It is expanded into the dir path 2932 // $XDG_DATA_HOME/home_location or $HOME/.local/share/home_location depending 2933 // on environment variables. This "home_location" is only used on Linux. 2934 // 2935 // \returns 2936 // VKResult 2937 // A string list of manifest files to be opened in out_files param. 2938 // List has a pointer to string for each manifest filename. 2939 // When done using the list in out_files, pointers should be freed. 2940 // Location or override string lists can be either files or directories as 2941 // follows: 2942 // | location | override 2943 // -------------------------------- 2944 // Win ICD | files | files 2945 // Win Layer | files | dirs 2946 // Linux ICD | dirs | files 2947 // Linux Layer| dirs | dirs 2948 static VkResult loader_get_manifest_files(const struct loader_instance *inst, const char *env_override, const char *source_override, 2949 bool is_layer, bool warn_if_not_present, const char *location, 2950 const char *relative_location, struct loader_manifest_files *out_files) { 2951 const char *override = NULL; 2952 char *override_getenv = NULL; 2953 char *loc, *orig_loc = NULL; 2954 char *reg = NULL; 2955 char *file, *next_file, *name; 2956 size_t alloced_count = 64; 2957 char full_path[2048]; 2958 DIR *sysdir = NULL; 2959 bool list_is_dirs = false; 2960 struct dirent *dent; 2961 VkResult res = VK_SUCCESS; 2962 2963 out_files->count = 0; 2964 out_files->filename_list = NULL; 2965 2966 if (source_override != NULL) { 2967 override = source_override; 2968 } else if (env_override != NULL) { 2969 #if !defined(_WIN32) 2970 if (geteuid() != getuid() || getegid() != getgid()) { 2971 // Don't allow setuid apps to use the env var: 2972 env_override = NULL; 2973 } 2974 #endif 2975 if (env_override != NULL) { 2976 override = override_getenv = loader_secure_getenv(env_override, inst); 2977 } 2978 } 2979 2980 #if !defined(_WIN32) 2981 if (relative_location == NULL) { 2982 #else 2983 relative_location = NULL; 2984 if (location == NULL) { 2985 #endif 2986 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2987 "loader_get_manifest_files: Can not get manifest files with " 2988 "NULL location, env_override=%s", 2989 (env_override != NULL) ? env_override : ""); 2990 res = VK_ERROR_INITIALIZATION_FAILED; 2991 goto out; 2992 } 2993 2994 #if defined(_WIN32) 2995 list_is_dirs = (is_layer && override != NULL) ? true : false; 2996 #else 2997 list_is_dirs = (override == NULL || is_layer) ? true : false; 2998 #endif 2999 // Make a copy of the input we are using so it is not modified 3000 // Also handle getting the location(s) from registry on Windows 3001 if (override == NULL) { 3002 size_t loc_size = 0; 3003 #if !defined(_WIN32) 3004 const char *xdgconfdirs = loader_secure_getenv("XDG_CONFIG_DIRS", inst); 3005 const char *xdgdatadirs = loader_secure_getenv("XDG_DATA_DIRS", inst); 3006 if (xdgconfdirs == NULL || xdgconfdirs[0] == '\0') xdgconfdirs = FALLBACK_CONFIG_DIRS; 3007 if (xdgdatadirs == NULL || xdgdatadirs[0] == '\0') xdgdatadirs = FALLBACK_DATA_DIRS; 3008 const size_t rel_size = strlen(relative_location); 3009 // Leave space for trailing separators 3010 loc_size += strlen(xdgconfdirs) + strlen(xdgdatadirs) + 2 * rel_size + 2; 3011 for (const char *x = xdgconfdirs; *x; ++x) 3012 if (*x == PATH_SEPARATOR) loc_size += rel_size; 3013 for (const char *x = xdgdatadirs; *x; ++x) 3014 if (*x == PATH_SEPARATOR) loc_size += rel_size; 3015 loc_size += strlen(SYSCONFDIR) + rel_size + 1; 3016 #if defined(EXTRASYSCONFDIR) 3017 loc_size += strlen(EXTRASYSCONFDIR) + rel_size + 1; 3018 #endif 3019 #else 3020 loc_size += strlen(location) + 1; 3021 #endif 3022 loc = loader_stack_alloc(loc_size); 3023 if (loc == NULL) { 3024 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 3025 "loader_get_manifest_files: Failed to allocate " 3026 "%d bytes for manifest file location.", 3027 loc_size); 3028 res = VK_ERROR_OUT_OF_HOST_MEMORY; 3029 goto out; 3030 } 3031 char *loc_write = loc; 3032 #if !defined(_WIN32) 3033 const char *loc_read; 3034 size_t start, stop; 3035 3036 loc_read = &xdgconfdirs[0]; 3037 start = 0; 3038 while (loc_read[start] != '\0') { 3039 while (loc_read[start] == PATH_SEPARATOR) { 3040 start++; 3041 } 3042 stop = start; 3043 while (loc_read[stop] != PATH_SEPARATOR && loc_read[stop] != '\0') { 3044 stop++; 3045 } 3046 const size_t s = stop - start; 3047 if (s) { 3048 memcpy(loc_write, &loc_read[start], s); 3049 loc_write += s; 3050 memcpy(loc_write, relative_location, rel_size); 3051 loc_write += rel_size; 3052 *loc_write++ = PATH_SEPARATOR; 3053 start = stop; 3054 } 3055 } 3056 3057 memcpy(loc_write, SYSCONFDIR, strlen(SYSCONFDIR)); 3058 loc_write += strlen(SYSCONFDIR); 3059 memcpy(loc_write, relative_location, rel_size); 3060 loc_write += rel_size; 3061 *loc_write++ = PATH_SEPARATOR; 3062 3063 #if defined(EXTRASYSCONFDIR) 3064 memcpy(loc_write, EXTRASYSCONFDIR, strlen(EXTRASYSCONFDIR)); 3065 loc_write += strlen(EXTRASYSCONFDIR); 3066 memcpy(loc_write, relative_location, rel_size); 3067 loc_write += rel_size; 3068 *loc_write++ = PATH_SEPARATOR; 3069 #endif 3070 3071 loc_read = &xdgdatadirs[0]; 3072 start = 0; 3073 while (loc_read[start] != '\0') { 3074 while (loc_read[start] == PATH_SEPARATOR) { 3075 start++; 3076 } 3077 stop = start; 3078 while (loc_read[stop] != PATH_SEPARATOR && loc_read[stop] != '\0') { 3079 stop++; 3080 } 3081 const size_t s = stop - start; 3082 if (s) { 3083 memcpy(loc_write, &loc_read[start], s); 3084 loc_write += s; 3085 memcpy(loc_write, relative_location, rel_size); 3086 loc_write += rel_size; 3087 *loc_write++ = PATH_SEPARATOR; 3088 start = stop; 3089 } 3090 } 3091 3092 --loc_write; 3093 #else 3094 memcpy(loc_write, location, strlen(location)); 3095 loc_write += strlen(location); 3096 #endif 3097 assert(loc_write - loc < (ptrdiff_t)loc_size); 3098 *loc_write = '\0'; 3099 3100 #if defined(_WIN32) 3101 VkResult regHKR_result = VK_SUCCESS; 3102 3103 DWORD reg_size = 4096; 3104 3105 // These calls look at the PNP/Device section of the registry. 3106 if (!strncmp(loc, DEFAULT_VK_DRIVERS_INFO, sizeof(DEFAULT_VK_DRIVERS_INFO))) { 3107 regHKR_result = loaderGetDeviceRegistryFiles(inst, ®, ®_size, LoaderPnpDriverRegistry()); 3108 } else if (!strncmp(loc, DEFAULT_VK_ELAYERS_INFO, sizeof(DEFAULT_VK_ELAYERS_INFO))) { 3109 regHKR_result = loaderGetDeviceRegistryFiles(inst, ®, ®_size, LoaderPnpELayerRegistry()); 3110 } else if (!strncmp(loc, DEFAULT_VK_ILAYERS_INFO, sizeof(DEFAULT_VK_ILAYERS_INFO))) { 3111 regHKR_result = loaderGetDeviceRegistryFiles(inst, ®, ®_size, LoaderPnpILayerRegistry()); 3112 } 3113 3114 // This call looks into the Khronos non-device specific section of the registry. 3115 VkResult reg_result = loaderGetRegistryFiles(inst, loc, is_layer, ®, ®_size); 3116 3117 if ((VK_SUCCESS != reg_result && VK_SUCCESS != regHKR_result) || NULL == reg) { 3118 if (!is_layer) { 3119 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 3120 "loader_get_manifest_files: Registry lookup failed " 3121 "to get ICD manifest files. Possibly missing Vulkan" 3122 " driver?"); 3123 if (VK_SUCCESS == regHKR_result || VK_ERROR_OUT_OF_HOST_MEMORY == regHKR_result) { 3124 res = regHKR_result; 3125 } else if (VK_SUCCESS == reg_result || VK_ERROR_OUT_OF_HOST_MEMORY == reg_result) { 3126 res = reg_result; 3127 } else { 3128 res = VK_ERROR_INCOMPATIBLE_DRIVER; 3129 } 3130 } else { 3131 if (warn_if_not_present) { 3132 // This is only a warning for layers 3133 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 3134 "loader_get_manifest_files: Registry lookup failed " 3135 "to get layer manifest files."); 3136 } 3137 if (reg_result == VK_ERROR_OUT_OF_HOST_MEMORY) { 3138 res = reg_result; 3139 } else { 3140 // Return success for now since it's not critical for layers 3141 res = VK_SUCCESS; 3142 } 3143 } 3144 goto out; 3145 } 3146 orig_loc = loc; 3147 loc = reg; 3148 #endif 3149 } else { 3150 loc = loader_stack_alloc(strlen(override) + 1); 3151 if (loc == NULL) { 3152 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 3153 "loader_get_manifest_files: Failed to allocate space for " 3154 "override environment variable of length %d", 3155 strlen(override) + 1); 3156 res = VK_ERROR_OUT_OF_HOST_MEMORY; 3157 goto out; 3158 } 3159 strcpy(loc, override); 3160 } 3161 3162 // Print out the paths being searched if debugging is enabled 3163 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Searching the following paths for manifest files: %s\n", loc); 3164 3165 file = loc; 3166 while (*file) { 3167 next_file = loader_get_next_path(file); 3168 if (list_is_dirs) { 3169 sysdir = opendir(file); 3170 name = NULL; 3171 if (sysdir) { 3172 dent = readdir(sysdir); 3173 if (dent == NULL) break; 3174 name = &(dent->d_name[0]); 3175 loader_get_fullpath(name, file, sizeof(full_path), full_path); 3176 name = full_path; 3177 } 3178 } else { 3179 #if defined(_WIN32) 3180 name = file; 3181 #else 3182 // only Linux has relative paths 3183 char *dir; 3184 // make a copy of location so it isn't modified 3185 dir = loader_stack_alloc(strlen(loc) + 1); 3186 if (dir == NULL) { 3187 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 3188 "loader_get_manifest_files: Failed to allocate " 3189 "space for relative location path length %d", 3190 strlen(loc) + 1); 3191 goto out; 3192 } 3193 strcpy(dir, loc); 3194 3195 loader_get_fullpath(file, dir, sizeof(full_path), full_path); 3196 3197 name = full_path; 3198 #endif 3199 } 3200 while (name) { 3201 // Look for files ending with ".json" suffix 3202 uint32_t nlen = (uint32_t)strlen(name); 3203 const char *suf = name + nlen - 5; 3204 3205 // Check if the file is already present 3206 bool file_already_loaded = false; 3207 for (uint32_t i = 0; i < out_files->count; ++i) { 3208 if (!strcmp(out_files->filename_list[i], name)) { 3209 file_already_loaded = true; 3210 } 3211 } 3212 3213 if (!file_already_loaded && (nlen > 5) && !strncmp(suf, ".json", 5)) { 3214 if (out_files->count == 0) { 3215 out_files->filename_list = 3216 loader_instance_heap_alloc(inst, alloced_count * sizeof(char *), VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 3217 if (NULL == out_files->filename_list) { 3218 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 3219 "loader_get_manifest_files: Failed to allocate space for manifest file name list"); 3220 res = VK_ERROR_OUT_OF_HOST_MEMORY; 3221 goto out; 3222 } 3223 } else if (out_files->count == alloced_count) { 3224 void *new_ptr = 3225 loader_instance_heap_realloc(inst, out_files->filename_list, alloced_count * sizeof(char *), 3226 alloced_count * sizeof(char *) * 2, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 3227 if (NULL == new_ptr) { 3228 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 3229 "loader_get_manifest_files: Failed to reallocate space for manifest file name list"); 3230 res = VK_ERROR_OUT_OF_HOST_MEMORY; 3231 goto out; 3232 } 3233 out_files->filename_list = new_ptr; 3234 alloced_count *= 2; 3235 } 3236 out_files->filename_list[out_files->count] = 3237 loader_instance_heap_alloc(inst, strlen(name) + 1, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 3238 if (out_files->filename_list[out_files->count] == NULL) { 3239 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 3240 "loader_get_manifest_files: Failed to allocate " 3241 "space for manifest file %d list", 3242 out_files->count); 3243 res = VK_ERROR_OUT_OF_HOST_MEMORY; 3244 goto out; 3245 } 3246 strcpy(out_files->filename_list[out_files->count], name); 3247 out_files->count++; 3248 } else if(file_already_loaded) { 3249 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 3250 "Skipping manifest file %s - The file has already been read once", name); 3251 } else if (!list_is_dirs) { 3252 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, "Skipping manifest file %s, file name must end in .json", 3253 name); 3254 } 3255 if (list_is_dirs) { 3256 dent = readdir(sysdir); 3257 if (dent == NULL) { 3258 break; 3259 } 3260 name = &(dent->d_name[0]); 3261 loader_get_fullpath(name, file, sizeof(full_path), full_path); 3262 name = full_path; 3263 } else { 3264 break; 3265 } 3266 } 3267 if (sysdir) { 3268 closedir(sysdir); 3269 sysdir = NULL; 3270 } 3271 file = next_file; 3272 #if !defined(_WIN32) 3273 if (relative_location != NULL && (next_file == NULL || *next_file == '\0') && override == NULL) { 3274 char *xdgdatahome = loader_secure_getenv("XDG_DATA_HOME", inst); 3275 size_t len; 3276 if (xdgdatahome != NULL) { 3277 size_t alloc_len = strlen(xdgdatahome) + 2 + strlen(relative_location); 3278 char *home_loc = loader_stack_alloc(alloc_len); 3279 if (home_loc == NULL) { 3280 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 3281 "loader_get_manifest_files: Failed to allocate " 3282 "space for manifest file XDG Home location"); 3283 res = VK_ERROR_OUT_OF_HOST_MEMORY; 3284 goto out; 3285 } 3286 strcpy(home_loc, xdgdatahome); 3287 // Add directory separator if needed 3288 if (relative_location[0] != DIRECTORY_SYMBOL) { 3289 len = strlen(home_loc); 3290 home_loc[len] = DIRECTORY_SYMBOL; 3291 home_loc[len + 1] = '\0'; 3292 } 3293 strncat(home_loc, relative_location, alloc_len); 3294 file = home_loc; 3295 next_file = loader_get_next_path(file); 3296 relative_location = NULL; 3297 3298 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Searching the following path for manifest files: %s\n", 3299 home_loc); 3300 list_is_dirs = true; 3301 3302 } else { 3303 char *home = loader_secure_getenv("HOME", inst); 3304 if (home != NULL) { 3305 size_t alloc_len = strlen(home) + 16 + strlen(relative_location); 3306 char *home_loc = loader_stack_alloc(alloc_len); 3307 if (home_loc == NULL) { 3308 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 3309 "loader_get_manifest_files: Failed to allocate " 3310 "space for manifest file Home location"); 3311 res = VK_ERROR_OUT_OF_HOST_MEMORY; 3312 goto out; 3313 } 3314 strncpy(home_loc, home, alloc_len); 3315 3316 len = strlen(home); 3317 if (home[len] != DIRECTORY_SYMBOL) { 3318 home_loc[len] = DIRECTORY_SYMBOL; 3319 home_loc[len + 1] = '\0'; 3320 } 3321 strncat(home_loc, ".local/share", alloc_len); 3322 3323 if (relative_location[0] != DIRECTORY_SYMBOL) { 3324 len = strlen(home_loc); 3325 home_loc[len] = DIRECTORY_SYMBOL; 3326 home_loc[len + 1] = '\0'; 3327 } 3328 strncat(home_loc, relative_location, alloc_len); 3329 file = home_loc; 3330 next_file = loader_get_next_path(file); 3331 relative_location = NULL; 3332 3333 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Searching the following path for manifest files: %s\n", 3334 home_loc); 3335 list_is_dirs = true; 3336 } else { 3337 // without knowing HOME, we just.. give up 3338 } 3339 } 3340 } 3341 #endif 3342 } 3343 3344 out: 3345 if (VK_SUCCESS != res && NULL != out_files->filename_list) { 3346 for (uint32_t remove = 0; remove < out_files->count; remove++) { 3347 loader_instance_heap_free(inst, out_files->filename_list[remove]); 3348 } 3349 loader_instance_heap_free(inst, out_files->filename_list); 3350 out_files->count = 0; 3351 out_files->filename_list = NULL; 3352 } 3353 3354 if (NULL != sysdir) { 3355 closedir(sysdir); 3356 } 3357 3358 if (override_getenv != NULL) { 3359 loader_free_getenv(override_getenv, inst); 3360 } 3361 3362 if (NULL != reg && reg != orig_loc) { 3363 loader_instance_heap_free(inst, reg); 3364 } 3365 return res; 3366 } 3367 3368 void loader_init_icd_lib_list() {} 3369 3370 void loader_destroy_icd_lib_list() {} 3371 3372 // Try to find the Vulkan ICD driver(s). 3373 // 3374 // This function scans the default system loader path(s) or path 3375 // specified by the \c VK_ICD_FILENAMES environment variable in 3376 // order to find loadable VK ICDs manifest files. From these 3377 // manifest files it finds the ICD libraries. 3378 // 3379 // \returns 3380 // Vulkan result 3381 // (on result == VK_SUCCESS) a list of icds that were discovered 3382 VkResult loader_icd_scan(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list) { 3383 char *file_str; 3384 uint16_t file_major_vers = 0; 3385 uint16_t file_minor_vers = 0; 3386 uint16_t file_patch_vers = 0; 3387 char *vers_tok; 3388 struct loader_manifest_files manifest_files; 3389 VkResult res = VK_SUCCESS; 3390 bool lockedMutex = false; 3391 cJSON *json = NULL; 3392 uint32_t num_good_icds = 0; 3393 3394 memset(&manifest_files, 0, sizeof(struct loader_manifest_files)); 3395 3396 res = loader_scanned_icd_init(inst, icd_tramp_list); 3397 if (VK_SUCCESS != res) { 3398 goto out; 3399 } 3400 3401 // Get a list of manifest files for ICDs 3402 res = loader_get_manifest_files(inst, "VK_ICD_FILENAMES", NULL, false, true, DEFAULT_VK_DRIVERS_INFO, RELATIVE_VK_DRIVERS_INFO, 3403 &manifest_files); 3404 if (VK_SUCCESS != res || manifest_files.count == 0) { 3405 goto out; 3406 } 3407 3408 loader_platform_thread_lock_mutex(&loader_json_lock); 3409 lockedMutex = true; 3410 for (uint32_t i = 0; i < manifest_files.count; i++) { 3411 file_str = manifest_files.filename_list[i]; 3412 if (file_str == NULL) { 3413 continue; 3414 } 3415 3416 VkResult temp_res = loader_get_json(inst, file_str, &json); 3417 if (NULL == json || temp_res != VK_SUCCESS) { 3418 if (NULL != json) { 3419 cJSON_Delete(json); 3420 json = NULL; 3421 } 3422 // If we haven't already found an ICD, copy this result to 3423 // the returned result. 3424 if (num_good_icds == 0) { 3425 res = temp_res; 3426 } 3427 if (temp_res == VK_ERROR_OUT_OF_HOST_MEMORY) { 3428 break; 3429 } else { 3430 continue; 3431 } 3432 } 3433 res = temp_res; 3434 3435 cJSON *item, *itemICD; 3436 item = cJSON_GetObjectItem(json, "file_format_version"); 3437 if (item == NULL) { 3438 if (num_good_icds == 0) { 3439 res = VK_ERROR_INITIALIZATION_FAILED; 3440 } 3441 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 3442 "loader_icd_scan: ICD JSON %s does not have a" 3443 " \'file_format_version\' field. Skipping ICD JSON.", 3444 file_str); 3445 cJSON_Delete(json); 3446 json = NULL; 3447 continue; 3448 } 3449 3450 char *file_vers = cJSON_Print(item); 3451 if (NULL == file_vers) { 3452 // Only reason the print can fail is if there was an allocation issue 3453 if (num_good_icds == 0) { 3454 res = VK_ERROR_OUT_OF_HOST_MEMORY; 3455 } 3456 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 3457 "loader_icd_scan: Failed retrieving ICD JSON %s" 3458 " \'file_format_version\' field. Skipping ICD JSON", 3459 file_str); 3460 cJSON_Delete(json); 3461 json = NULL; 3462 continue; 3463 } 3464 loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, "Found ICD manifest file %s, version %s", file_str, file_vers); 3465 3466 // Get the major/minor/and patch as integers for easier comparison 3467 vers_tok = strtok(file_vers, ".\"\n\r"); 3468 if (NULL != vers_tok) { 3469 file_major_vers = (uint16_t)atoi(vers_tok); 3470 vers_tok = strtok(NULL, ".\"\n\r"); 3471 if (NULL != vers_tok) { 3472 file_minor_vers = (uint16_t)atoi(vers_tok); 3473 vers_tok = strtok(NULL, ".\"\n\r"); 3474 if (NULL != vers_tok) { 3475 file_patch_vers = (uint16_t)atoi(vers_tok); 3476 } 3477 } 3478 } 3479 3480 if (file_major_vers != 1 || file_minor_vers != 0 || file_patch_vers > 1) { 3481 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 3482 "loader_icd_scan: Unexpected manifest file version " 3483 "(expected 1.0.0 or 1.0.1), may cause errors"); 3484 } 3485 cJSON_Free(file_vers); 3486 3487 itemICD = cJSON_GetObjectItem(json, "ICD"); 3488 if (itemICD != NULL) { 3489 item = cJSON_GetObjectItem(itemICD, "library_path"); 3490 if (item != NULL) { 3491 char *temp = cJSON_Print(item); 3492 if (!temp || strlen(temp) == 0) { 3493 if (num_good_icds == 0) { 3494 res = VK_ERROR_OUT_OF_HOST_MEMORY; 3495 } 3496 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 3497 "loader_icd_scan: Failed retrieving ICD JSON %s" 3498 " \'library_path\' field. Skipping ICD JSON.", 3499 file_str); 3500 cJSON_Free(temp); 3501 cJSON_Delete(json); 3502 json = NULL; 3503 continue; 3504 } 3505 // strip out extra quotes 3506 temp[strlen(temp) - 1] = '\0'; 3507 char *library_path = loader_stack_alloc(strlen(temp) + 1); 3508 if (NULL == library_path) { 3509 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 3510 "loader_icd_scan: Failed to allocate space for " 3511 "ICD JSON %s \'library_path\' value. Skipping " 3512 "ICD JSON.", 3513 file_str); 3514 res = VK_ERROR_OUT_OF_HOST_MEMORY; 3515 cJSON_Free(temp); 3516 cJSON_Delete(json); 3517 json = NULL; 3518 goto out; 3519 } 3520 strcpy(library_path, &temp[1]); 3521 cJSON_Free(temp); 3522 if (strlen(library_path) == 0) { 3523 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 3524 "loader_icd_scan: ICD JSON %s \'library_path\'" 3525 " field is empty. Skipping ICD JSON.", 3526 file_str); 3527 cJSON_Delete(json); 3528 json = NULL; 3529 continue; 3530 } 3531 char fullpath[MAX_STRING_SIZE]; 3532 // Print out the paths being searched if debugging is enabled 3533 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Searching for ICD drivers named %s, using default dir %s", 3534 library_path, DEFAULT_VK_DRIVERS_PATH); 3535 if (loader_platform_is_path(library_path)) { 3536 // a relative or absolute path 3537 char *name_copy = loader_stack_alloc(strlen(file_str) + 1); 3538 char *rel_base; 3539 strcpy(name_copy, file_str); 3540 rel_base = loader_platform_dirname(name_copy); 3541 loader_expand_path(library_path, rel_base, sizeof(fullpath), fullpath); 3542 } else { 3543 // a filename which is assumed in a system directory 3544 loader_get_fullpath(library_path, DEFAULT_VK_DRIVERS_PATH, sizeof(fullpath), fullpath); 3545 } 3546 3547 uint32_t vers = 0; 3548 item = cJSON_GetObjectItem(itemICD, "api_version"); 3549 if (item != NULL) { 3550 temp = cJSON_Print(item); 3551 if (NULL == temp) { 3552 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 3553 "loader_icd_scan: Failed retrieving ICD JSON %s" 3554 " \'api_version\' field. Skipping ICD JSON.", 3555 file_str); 3556 3557 // Only reason the print can fail is if there was an 3558 // allocation issue 3559 if (num_good_icds == 0) { 3560 res = VK_ERROR_OUT_OF_HOST_MEMORY; 3561 } 3562 3563 cJSON_Free(temp); 3564 cJSON_Delete(json); 3565 json = NULL; 3566 continue; 3567 } 3568 vers = loader_make_version(temp); 3569 cJSON_Free(temp); 3570 } else { 3571 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 3572 "loader_icd_scan: ICD JSON %s does not have an" 3573 " \'api_version\' field.", 3574 file_str); 3575 } 3576 3577 res = loader_scanned_icd_add(inst, icd_tramp_list, fullpath, vers); 3578 if (VK_SUCCESS != res) { 3579 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 3580 "loader_icd_scan: Failed to add ICD JSON %s. " 3581 " Skipping ICD JSON.", 3582 fullpath); 3583 cJSON_Delete(json); 3584 json = NULL; 3585 continue; 3586 } 3587 num_good_icds++; 3588 } else { 3589 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 3590 "loader_icd_scan: Failed to find \'library_path\' " 3591 "object in ICD JSON file %s. Skipping ICD JSON.", 3592 file_str); 3593 } 3594 } else { 3595 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 3596 "loader_icd_scan: Can not find \'ICD\' object in ICD JSON " 3597 "file %s. Skipping ICD JSON", 3598 file_str); 3599 } 3600 3601 cJSON_Delete(json); 3602 json = NULL; 3603 } 3604 3605 out: 3606 3607 if (NULL != json) { 3608 cJSON_Delete(json); 3609 } 3610 3611 if (NULL != manifest_files.filename_list) { 3612 for (uint32_t i = 0; i < manifest_files.count; i++) { 3613 if (NULL != manifest_files.filename_list[i]) { 3614 loader_instance_heap_free(inst, manifest_files.filename_list[i]); 3615 } 3616 } 3617 loader_instance_heap_free(inst, manifest_files.filename_list); 3618 } 3619 if (lockedMutex) { 3620 loader_platform_thread_unlock_mutex(&loader_json_lock); 3621 } 3622 3623 return res; 3624 } 3625 3626 void loader_layer_scan(const struct loader_instance *inst, struct loader_layer_list *instance_layers) { 3627 char *file_str; 3628 struct loader_manifest_files manifest_files[2]; // [0] = explicit, [1] = implicit 3629 cJSON *json; 3630 uint32_t implicit; 3631 bool lockedMutex = false; 3632 3633 memset(manifest_files, 0, sizeof(struct loader_manifest_files) * 2); 3634 3635 // Get a list of manifest files for explicit layers 3636 if (VK_SUCCESS != loader_get_manifest_files(inst, LAYERS_PATH_ENV, LAYERS_SOURCE_PATH, true, true, DEFAULT_VK_ELAYERS_INFO, 3637 RELATIVE_VK_ELAYERS_INFO, &manifest_files[0])) { 3638 goto out; 3639 } 3640 3641 // Get a list of manifest files for any implicit layers 3642 // Pass NULL for environment variable override - implicit layers are not 3643 // overridden by LAYERS_PATH_ENV 3644 if (VK_SUCCESS != loader_get_manifest_files(inst, NULL, NULL, true, false, DEFAULT_VK_ILAYERS_INFO, RELATIVE_VK_ILAYERS_INFO, 3645 &manifest_files[1])) { 3646 goto out; 3647 } 3648 3649 // Make sure we have at least one layer, if not, go ahead and return 3650 if (manifest_files[0].count == 0 && manifest_files[1].count == 0) { 3651 goto out; 3652 } 3653 3654 // cleanup any previously scanned libraries 3655 loader_delete_layer_properties(inst, instance_layers); 3656 3657 loader_platform_thread_lock_mutex(&loader_json_lock); 3658 lockedMutex = true; 3659 for (implicit = 0; implicit < 2; implicit++) { 3660 for (uint32_t i = 0; i < manifest_files[implicit].count; i++) { 3661 file_str = manifest_files[implicit].filename_list[i]; 3662 if (file_str == NULL) continue; 3663 3664 // parse file into JSON struct 3665 VkResult res = loader_get_json(inst, file_str, &json); 3666 if (VK_ERROR_OUT_OF_HOST_MEMORY == res) { 3667 break; 3668 } else if (VK_SUCCESS != res || NULL == json) { 3669 continue; 3670 } 3671 3672 VkResult local_res = loader_add_layer_properties(inst, instance_layers, json, (implicit == 1), file_str); 3673 cJSON_Delete(json); 3674 3675 // If the error is anything other than out of memory we still want to try to load the other layers 3676 if (VK_ERROR_OUT_OF_HOST_MEMORY == local_res) { 3677 goto out; 3678 } 3679 } 3680 } 3681 3682 // See if "VK_LAYER_LUNARG_standard_validation" already in list. 3683 bool found_std_val = false; 3684 for (uint32_t i = 0; i < instance_layers->count; i++) { 3685 struct loader_layer_properties *props = &instance_layers->list[i]; 3686 if (strcmp(props->info.layerName, std_validation_str) == 0) { 3687 found_std_val = true; 3688 break; 3689 } 3690 } 3691 3692 // If we didn't find the VK_LAYER_LUNARG_standard_validation meta-layer in 3693 // the list, then we need to add it manually. This is likely because we're 3694 // dealing with a new loader, but an old layer folder. 3695 if (!found_std_val && !loader_add_legacy_std_val_layer(inst, instance_layers)) { 3696 goto out; 3697 } 3698 3699 // Verify any meta-layers in the list are valid and all the component layers are 3700 // actually present in the available layer list 3701 verify_all_meta_layers(inst, instance_layers); 3702 3703 out: 3704 3705 for (uint32_t manFile = 0; manFile < 2; manFile++) { 3706 if (NULL != manifest_files[manFile].filename_list) { 3707 for (uint32_t i = 0; i < manifest_files[manFile].count; i++) { 3708 if (NULL != manifest_files[manFile].filename_list[i]) { 3709 loader_instance_heap_free(inst, manifest_files[manFile].filename_list[i]); 3710 } 3711 } 3712 loader_instance_heap_free(inst, manifest_files[manFile].filename_list); 3713 } 3714 } 3715 if (lockedMutex) { 3716 loader_platform_thread_unlock_mutex(&loader_json_lock); 3717 } 3718 } 3719 3720 void loader_implicit_layer_scan(const struct loader_instance *inst, struct loader_layer_list *instance_layers) { 3721 char *file_str; 3722 struct loader_manifest_files manifest_files; 3723 cJSON *json; 3724 uint32_t i; 3725 3726 // Pass NULL for environment variable override - implicit layers are not 3727 // overridden by LAYERS_PATH_ENV 3728 VkResult res = loader_get_manifest_files(inst, NULL, NULL, true, false, DEFAULT_VK_ILAYERS_INFO, RELATIVE_VK_ILAYERS_INFO, 3729 &manifest_files); 3730 if (VK_SUCCESS != res || manifest_files.count == 0) { 3731 return; 3732 } 3733 3734 // Cleanup any previously scanned libraries 3735 loader_delete_layer_properties(inst, instance_layers); 3736 3737 loader_platform_thread_lock_mutex(&loader_json_lock); 3738 3739 for (i = 0; i < manifest_files.count; i++) { 3740 file_str = manifest_files.filename_list[i]; 3741 if (file_str == NULL) { 3742 continue; 3743 } 3744 3745 // parse file into JSON struct 3746 res = loader_get_json(inst, file_str, &json); 3747 if (VK_ERROR_OUT_OF_HOST_MEMORY == res) { 3748 break; 3749 } else if (VK_SUCCESS != res || NULL == json) { 3750 continue; 3751 } 3752 3753 res = loader_add_layer_properties(inst, instance_layers, json, true, file_str); 3754 3755 loader_instance_heap_free(inst, file_str); 3756 cJSON_Delete(json); 3757 3758 if (VK_ERROR_OUT_OF_HOST_MEMORY == res) { 3759 break; 3760 } 3761 } 3762 loader_instance_heap_free(inst, manifest_files.filename_list); 3763 loader_platform_thread_unlock_mutex(&loader_json_lock); 3764 } 3765 3766 // Check if an implicit layer should be enabled. 3767 bool loader_is_implicit_layer_enabled(const struct loader_instance *inst, const struct loader_layer_properties *prop) { 3768 bool enable = false; 3769 char *env_value = NULL; 3770 3771 // if no enable_environment variable is specified, this implicit layer 3772 // should always be enabled. Otherwise check if the variable is set 3773 if (prop->enable_env_var.name[0] == 0) { 3774 enable = true; 3775 } else { 3776 env_value = loader_secure_getenv(prop->enable_env_var.name, inst); 3777 if (env_value && !strcmp(prop->enable_env_var.value, env_value)) enable = true; 3778 loader_free_getenv(env_value, inst); 3779 } 3780 3781 // disable_environment has priority, i.e. if both enable and disable 3782 // environment variables are set, the layer is disabled. Implicit 3783 // layers are required to have a disable_environment variables 3784 env_value = loader_secure_getenv(prop->disable_env_var.name, inst); 3785 if (env_value && !strcmp(prop->disable_env_var.value, env_value)) enable = false; 3786 loader_free_getenv(env_value, inst); 3787 3788 return enable; 3789 } 3790 3791 static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL loader_gpdpa_instance_internal(VkInstance inst, const char *pName) { 3792 // inst is not wrapped 3793 if (inst == VK_NULL_HANDLE) { 3794 return NULL; 3795 } 3796 VkLayerInstanceDispatchTable *disp_table = *(VkLayerInstanceDispatchTable **)inst; 3797 void *addr; 3798 3799 if (disp_table == NULL) return NULL; 3800 3801 bool found_name; 3802 addr = loader_lookup_instance_dispatch_table(disp_table, pName, &found_name); 3803 if (found_name) { 3804 return addr; 3805 } 3806 3807 if (loader_phys_dev_ext_gpa(loader_get_instance(inst), pName, true, NULL, &addr)) return addr; 3808 3809 // Don't call down the chain, this would be an infinite loop 3810 loader_log(NULL, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, "loader_gpdpa_instance_internal() unrecognized name %s", pName); 3811 return NULL; 3812 } 3813 3814 static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL loader_gpdpa_instance_terminator(VkInstance inst, const char *pName) { 3815 // inst is not wrapped 3816 if (inst == VK_NULL_HANDLE) { 3817 return NULL; 3818 } 3819 VkLayerInstanceDispatchTable *disp_table = *(VkLayerInstanceDispatchTable **)inst; 3820 void *addr; 3821 3822 if (disp_table == NULL) return NULL; 3823 3824 bool found_name; 3825 addr = loader_lookup_instance_dispatch_table(disp_table, pName, &found_name); 3826 if (found_name) { 3827 return addr; 3828 } 3829 3830 // Get the terminator, but don't perform checking since it should already 3831 // have been setup if we get here. 3832 if (loader_phys_dev_ext_gpa(loader_get_instance(inst), pName, false, NULL, &addr)) { 3833 return addr; 3834 } 3835 3836 // Don't call down the chain, this would be an infinite loop 3837 loader_log(NULL, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, "loader_gpdpa_instance_terminator() unrecognized name %s", pName); 3838 return NULL; 3839 } 3840 3841 static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL loader_gpa_instance_internal(VkInstance inst, const char *pName) { 3842 if (!strcmp(pName, "vkGetInstanceProcAddr")) { 3843 return (PFN_vkVoidFunction)loader_gpa_instance_internal; 3844 } 3845 if (!strcmp(pName, "vk_layerGetPhysicalDeviceProcAddr")) { 3846 return (PFN_vkVoidFunction)loader_gpdpa_instance_terminator; 3847 } 3848 if (!strcmp(pName, "vkCreateInstance")) { 3849 return (PFN_vkVoidFunction)terminator_CreateInstance; 3850 } 3851 if (!strcmp(pName, "vkCreateDevice")) { 3852 return (PFN_vkVoidFunction)terminator_CreateDevice; 3853 } 3854 3855 // inst is not wrapped 3856 if (inst == VK_NULL_HANDLE) { 3857 return NULL; 3858 } 3859 VkLayerInstanceDispatchTable *disp_table = *(VkLayerInstanceDispatchTable **)inst; 3860 void *addr; 3861 3862 if (disp_table == NULL) return NULL; 3863 3864 bool found_name; 3865 addr = loader_lookup_instance_dispatch_table(disp_table, pName, &found_name); 3866 if (found_name) { 3867 return addr; 3868 } 3869 3870 // Don't call down the chain, this would be an infinite loop 3871 loader_log(NULL, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, "loader_gpa_instance_internal() unrecognized name %s", pName); 3872 return NULL; 3873 } 3874 3875 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL loader_gpa_device_internal(VkDevice device, const char *pName) { 3876 struct loader_device *dev; 3877 struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev, NULL); 3878 3879 // Return this function if a layer above here is asking for the vkGetDeviceProcAddr. 3880 // This is so we can properly intercept any device commands needing a terminator. 3881 if (!strcmp(pName, "vkGetDeviceProcAddr")) { 3882 return (PFN_vkVoidFunction)loader_gpa_device_internal; 3883 } 3884 3885 // NOTE: Device Funcs needing Trampoline/Terminator. 3886 // Overrides for device functions needing a trampoline and 3887 // a terminator because certain device entry-points still need to go 3888 // through a terminator before hitting the ICD. This could be for 3889 // several reasons, but the main one is currently unwrapping an 3890 // object before passing the appropriate info along to the ICD. 3891 // This is why we also have to override the direct ICD call to 3892 // vkGetDeviceProcAddr to intercept those calls. 3893 PFN_vkVoidFunction addr = get_extension_device_proc_terminator(pName); 3894 if (NULL != addr) { 3895 return addr; 3896 } 3897 3898 return icd_term->dispatch.GetDeviceProcAddr(device, pName); 3899 } 3900 3901 // Initialize device_ext dispatch table entry as follows: 3902 // If dev == NULL find all logical devices created within this instance and 3903 // init the entry (given by idx) in the ext dispatch table. 3904 // If dev != NULL only initialize the entry in the given dev's dispatch table. 3905 // The initialization value is gotten by calling down the device chain with 3906 // GDPA. 3907 // If GDPA returns NULL then don't initialize the dispatch table entry. 3908 static void loader_init_dispatch_dev_ext_entry(struct loader_instance *inst, struct loader_device *dev, uint32_t idx, 3909 const char *funcName) 3910 3911 { 3912 void *gdpa_value; 3913 if (dev != NULL) { 3914 gdpa_value = dev->loader_dispatch.core_dispatch.GetDeviceProcAddr(dev->chain_device, funcName); 3915 if (gdpa_value != NULL) dev->loader_dispatch.ext_dispatch.dev_ext[idx] = (PFN_vkDevExt)gdpa_value; 3916 } else { 3917 for (struct loader_icd_term *icd_term = inst->icd_terms; icd_term != NULL; icd_term = icd_term->next) { 3918 struct loader_device *ldev = icd_term->logical_device_list; 3919 while (ldev) { 3920 gdpa_value = ldev->loader_dispatch.core_dispatch.GetDeviceProcAddr(ldev->chain_device, funcName); 3921 if (gdpa_value != NULL) ldev->loader_dispatch.ext_dispatch.dev_ext[idx] = (PFN_vkDevExt)gdpa_value; 3922 ldev = ldev->next; 3923 } 3924 } 3925 } 3926 } 3927 3928 // Find all dev extension in the hash table and initialize the dispatch table 3929 // for dev for each of those extension entrypoints found in hash table. 3930 void loader_init_dispatch_dev_ext(struct loader_instance *inst, struct loader_device *dev) { 3931 for (uint32_t i = 0; i < MAX_NUM_UNKNOWN_EXTS; i++) { 3932 if (inst->dev_ext_disp_hash[i].func_name != NULL) 3933 loader_init_dispatch_dev_ext_entry(inst, dev, i, inst->dev_ext_disp_hash[i].func_name); 3934 } 3935 } 3936 3937 static bool loader_check_icds_for_dev_ext_address(struct loader_instance *inst, const char *funcName) { 3938 struct loader_icd_term *icd_term; 3939 icd_term = inst->icd_terms; 3940 while (NULL != icd_term) { 3941 if (icd_term->scanned_icd->GetInstanceProcAddr(icd_term->instance, funcName)) 3942 // this icd supports funcName 3943 return true; 3944 icd_term = icd_term->next; 3945 } 3946 3947 return false; 3948 } 3949 3950 static bool loader_check_layer_list_for_dev_ext_address(const struct loader_layer_list *const layers, const char *funcName) { 3951 // Iterate over the layers. 3952 for (uint32_t layer = 0; layer < layers->count; ++layer) { 3953 // Iterate over the extensions. 3954 const struct loader_device_extension_list *const extensions = &(layers->list[layer].device_extension_list); 3955 for (uint32_t extension = 0; extension < extensions->count; ++extension) { 3956 // Iterate over the entry points. 3957 const struct loader_dev_ext_props *const property = &(extensions->list[extension]); 3958 for (uint32_t entry = 0; entry < property->entrypoint_count; ++entry) { 3959 if (strcmp(property->entrypoints[entry], funcName) == 0) { 3960 return true; 3961 } 3962 } 3963 } 3964 } 3965 3966 return false; 3967 } 3968 3969 static void loader_free_dev_ext_table(struct loader_instance *inst) { 3970 for (uint32_t i = 0; i < MAX_NUM_UNKNOWN_EXTS; i++) { 3971 loader_instance_heap_free(inst, inst->dev_ext_disp_hash[i].func_name); 3972 loader_instance_heap_free(inst, inst->dev_ext_disp_hash[i].list.index); 3973 } 3974 memset(inst->dev_ext_disp_hash, 0, sizeof(inst->dev_ext_disp_hash)); 3975 } 3976 3977 static bool loader_add_dev_ext_table(struct loader_instance *inst, uint32_t *ptr_idx, const char *funcName) { 3978 uint32_t i; 3979 uint32_t idx = *ptr_idx; 3980 struct loader_dispatch_hash_list *list = &inst->dev_ext_disp_hash[idx].list; 3981 3982 if (!inst->dev_ext_disp_hash[idx].func_name) { 3983 // no entry here at this idx, so use it 3984 assert(list->capacity == 0); 3985 inst->dev_ext_disp_hash[idx].func_name = 3986 (char *)loader_instance_heap_alloc(inst, strlen(funcName) + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 3987 if (inst->dev_ext_disp_hash[idx].func_name == NULL) { 3988 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 3989 "loader_add_dev_ext_table: Failed to allocate memory " 3990 "for func_name %s", 3991 funcName); 3992 return false; 3993 } 3994 strncpy(inst->dev_ext_disp_hash[idx].func_name, funcName, strlen(funcName) + 1); 3995 return true; 3996 } 3997 3998 // check for enough capacity 3999 if (list->capacity == 0) { 4000 list->index = loader_instance_heap_alloc(inst, 8 * sizeof(*(list->index)), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 4001 if (list->index == NULL) { 4002 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "loader_add_dev_ext_table: Failed to allocate memory for list index", 4003 funcName); 4004 return false; 4005 } 4006 list->capacity = 8 * sizeof(*(list->index)); 4007 } else if (list->capacity < (list->count + 1) * sizeof(*(list->index))) { 4008 void *new_ptr = loader_instance_heap_realloc(inst, list->index, list->capacity, list->capacity * 2, 4009 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 4010 if (NULL == new_ptr) { 4011 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 4012 "loader_add_dev_ext_table: Failed to reallocate memory for list index", funcName); 4013 return false; 4014 } 4015 list->index = new_ptr; 4016 list->capacity *= 2; 4017 } 4018 4019 // find an unused index in the hash table and use it 4020 i = (idx + 1) % MAX_NUM_UNKNOWN_EXTS; 4021 do { 4022 if (!inst->dev_ext_disp_hash[i].func_name) { 4023 assert(inst->dev_ext_disp_hash[i].list.capacity == 0); 4024 inst->dev_ext_disp_hash[i].func_name = 4025 (char *)loader_instance_heap_alloc(inst, strlen(funcName) + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 4026 if (inst->dev_ext_disp_hash[i].func_name == NULL) { 4027 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 4028 "loader_add_dev_ext_table: Failed to allocate memory " 4029 "for func_name %s", 4030 funcName); 4031 return false; 4032 } 4033 strncpy(inst->dev_ext_disp_hash[i].func_name, funcName, strlen(funcName) + 1); 4034 list->index[list->count] = i; 4035 list->count++; 4036 *ptr_idx = i; 4037 return true; 4038 } 4039 i = (i + 1) % MAX_NUM_UNKNOWN_EXTS; 4040 } while (i != idx); 4041 4042 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 4043 "loader_add_dev_ext_table: Could not insert into hash table; is " 4044 "it full?"); 4045 4046 return false; 4047 } 4048 4049 static bool loader_name_in_dev_ext_table(struct loader_instance *inst, uint32_t *idx, const char *funcName) { 4050 uint32_t alt_idx; 4051 if (inst->dev_ext_disp_hash[*idx].func_name && !strcmp(inst->dev_ext_disp_hash[*idx].func_name, funcName)) return true; 4052 4053 // funcName wasn't at the primary spot in the hash table 4054 // search the list of secondary locations (shallow search, not deep search) 4055 for (uint32_t i = 0; i < inst->dev_ext_disp_hash[*idx].list.count; i++) { 4056 alt_idx = inst->dev_ext_disp_hash[*idx].list.index[i]; 4057 if (!strcmp(inst->dev_ext_disp_hash[*idx].func_name, funcName)) { 4058 *idx = alt_idx; 4059 return true; 4060 } 4061 } 4062 4063 return false; 4064 } 4065 4066 // This function returns generic trampoline code address for unknown entry 4067 // points. 4068 // Presumably, these unknown entry points (as given by funcName) are device 4069 // extension entrypoints. A hash table is used to keep a list of unknown entry 4070 // points and their mapping to the device extension dispatch table 4071 // (struct loader_dev_ext_dispatch_table). 4072 // \returns 4073 // For a given entry point string (funcName), if an existing mapping is found 4074 // the 4075 // trampoline address for that mapping is returned. Otherwise, this unknown 4076 // entry point 4077 // has not been seen yet. Next check if a layer or ICD supports it. If so then 4078 // a 4079 // new entry in the hash table is initialized and that trampoline address for 4080 // the new entry is returned. Null is returned if the hash table is full or 4081 // if no discovered layer or ICD returns a non-NULL GetProcAddr for it. 4082 void *loader_dev_ext_gpa(struct loader_instance *inst, const char *funcName) { 4083 uint32_t idx; 4084 uint32_t seed = 0; 4085 4086 idx = murmurhash(funcName, strlen(funcName), seed) % MAX_NUM_UNKNOWN_EXTS; 4087 4088 if (loader_name_in_dev_ext_table(inst, &idx, funcName)) 4089 // found funcName already in hash 4090 return loader_get_dev_ext_trampoline(idx); 4091 4092 // Check if funcName is supported in either ICDs or a layer library 4093 if (!loader_check_icds_for_dev_ext_address(inst, funcName) && 4094 !loader_check_layer_list_for_dev_ext_address(&inst->app_activated_layer_list, funcName)) { 4095 // if support found in layers continue on 4096 return NULL; 4097 } 4098 4099 if (loader_add_dev_ext_table(inst, &idx, funcName)) { 4100 // successfully added new table entry 4101 // init any dev dispatch table entries as needed 4102 loader_init_dispatch_dev_ext_entry(inst, NULL, idx, funcName); 4103 return loader_get_dev_ext_trampoline(idx); 4104 } 4105 4106 return NULL; 4107 } 4108 4109 static bool loader_check_icds_for_phys_dev_ext_address(struct loader_instance *inst, const char *funcName) { 4110 struct loader_icd_term *icd_term; 4111 icd_term = inst->icd_terms; 4112 while (NULL != icd_term) { 4113 if (icd_term->scanned_icd->interface_version >= MIN_PHYS_DEV_EXTENSION_ICD_INTERFACE_VERSION && 4114 icd_term->scanned_icd->GetPhysicalDeviceProcAddr(icd_term->instance, funcName)) 4115 // this icd supports funcName 4116 return true; 4117 icd_term = icd_term->next; 4118 } 4119 4120 return false; 4121 } 4122 4123 static bool loader_check_layer_list_for_phys_dev_ext_address(struct loader_instance *inst, const char *funcName) { 4124 struct loader_layer_properties *layer_prop_list = inst->expanded_activated_layer_list.list; 4125 for (uint32_t layer = 0; layer < inst->expanded_activated_layer_list.count; ++layer) { 4126 // If this layer supports the vk_layerGetPhysicalDeviceProcAddr, then call 4127 // it and see if it returns a valid pointer for this function name. 4128 if (layer_prop_list[layer].interface_version > 1) { 4129 const struct loader_layer_functions *const functions = &(layer_prop_list[layer].functions); 4130 if (NULL != functions->get_physical_device_proc_addr && 4131 NULL != functions->get_physical_device_proc_addr((VkInstance)inst->instance, funcName)) { 4132 return true; 4133 } 4134 } 4135 } 4136 4137 return false; 4138 } 4139 4140 static void loader_free_phys_dev_ext_table(struct loader_instance *inst) { 4141 for (uint32_t i = 0; i < MAX_NUM_UNKNOWN_EXTS; i++) { 4142 loader_instance_heap_free(inst, inst->phys_dev_ext_disp_hash[i].func_name); 4143 loader_instance_heap_free(inst, inst->phys_dev_ext_disp_hash[i].list.index); 4144 } 4145 memset(inst->phys_dev_ext_disp_hash, 0, sizeof(inst->phys_dev_ext_disp_hash)); 4146 } 4147 4148 static bool loader_add_phys_dev_ext_table(struct loader_instance *inst, uint32_t *ptr_idx, const char *funcName) { 4149 uint32_t i; 4150 uint32_t idx = *ptr_idx; 4151 struct loader_dispatch_hash_list *list = &inst->phys_dev_ext_disp_hash[idx].list; 4152 4153 if (!inst->phys_dev_ext_disp_hash[idx].func_name) { 4154 // no entry here at this idx, so use it 4155 assert(list->capacity == 0); 4156 inst->phys_dev_ext_disp_hash[idx].func_name = 4157 (char *)loader_instance_heap_alloc(inst, strlen(funcName) + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 4158 if (inst->phys_dev_ext_disp_hash[idx].func_name == NULL) { 4159 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 4160 "loader_add_phys_dev_ext_table() can't allocate memory for " 4161 "func_name"); 4162 return false; 4163 } 4164 strncpy(inst->phys_dev_ext_disp_hash[idx].func_name, funcName, strlen(funcName) + 1); 4165 return true; 4166 } 4167 4168 // check for enough capacity 4169 if (list->capacity == 0) { 4170 list->index = loader_instance_heap_alloc(inst, 8 * sizeof(*(list->index)), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 4171 if (list->index == NULL) { 4172 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "loader_add_phys_dev_ext_table() can't allocate list memory"); 4173 return false; 4174 } 4175 list->capacity = 8 * sizeof(*(list->index)); 4176 } else if (list->capacity < (list->count + 1) * sizeof(*(list->index))) { 4177 void *new_ptr = loader_instance_heap_realloc(inst, list->index, list->capacity, list->capacity * 2, 4178 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 4179 if (NULL == new_ptr) { 4180 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "loader_add_phys_dev_ext_table() can't reallocate list memory"); 4181 return false; 4182 } 4183 list->index = new_ptr; 4184 list->capacity *= 2; 4185 } 4186 4187 // find an unused index in the hash table and use it 4188 i = (idx + 1) % MAX_NUM_UNKNOWN_EXTS; 4189 do { 4190 if (!inst->phys_dev_ext_disp_hash[i].func_name) { 4191 assert(inst->phys_dev_ext_disp_hash[i].list.capacity == 0); 4192 inst->phys_dev_ext_disp_hash[i].func_name = 4193 (char *)loader_instance_heap_alloc(inst, strlen(funcName) + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 4194 if (inst->phys_dev_ext_disp_hash[i].func_name == NULL) { 4195 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 4196 "loader_add_dev_ext_table() can't reallocate " 4197 "func_name memory"); 4198 return false; 4199 } 4200 strncpy(inst->phys_dev_ext_disp_hash[i].func_name, funcName, strlen(funcName) + 1); 4201 list->index[list->count] = i; 4202 list->count++; 4203 *ptr_idx = i; 4204 return true; 4205 } 4206 i = (i + 1) % MAX_NUM_UNKNOWN_EXTS; 4207 } while (i != idx); 4208 4209 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 4210 "loader_add_phys_dev_ext_table() couldn't insert into hash table; is " 4211 "it full?"); 4212 return false; 4213 } 4214 4215 static bool loader_name_in_phys_dev_ext_table(struct loader_instance *inst, uint32_t *idx, const char *funcName) { 4216 uint32_t alt_idx; 4217 if (inst->phys_dev_ext_disp_hash[*idx].func_name && !strcmp(inst->phys_dev_ext_disp_hash[*idx].func_name, funcName)) 4218 return true; 4219 4220 // funcName wasn't at the primary spot in the hash table 4221 // search the list of secondary locations (shallow search, not deep search) 4222 for (uint32_t i = 0; i < inst->phys_dev_ext_disp_hash[*idx].list.count; i++) { 4223 alt_idx = inst->phys_dev_ext_disp_hash[*idx].list.index[i]; 4224 if (!strcmp(inst->phys_dev_ext_disp_hash[*idx].func_name, funcName)) { 4225 *idx = alt_idx; 4226 return true; 4227 } 4228 } 4229 4230 return false; 4231 } 4232 4233 // This function returns a generic trampoline and/or terminator function 4234 // address for any unknown physical device extension commands. A hash 4235 // table is used to keep a list of unknown entry points and their 4236 // mapping to the physical device extension dispatch table (struct 4237 // loader_phys_dev_ext_dispatch_table). 4238 // For a given entry point string (funcName), if an existing mapping is 4239 // found, then the trampoline address for that mapping is returned in 4240 // tramp_addr (if it is not NULL) and the terminator address for that 4241 // mapping is returned in term_addr (if it is not NULL). Otherwise, 4242 // this unknown entry point has not been seen yet. 4243 // If it has not been seen before, and perform_checking is 'true', 4244 // check if a layer or and ICD supports it. If so then a new entry in 4245 // the hash table is initialized and the trampoline and/or terminator 4246 // addresses are returned. 4247 // Null is returned if the hash table is full or if no discovered layer or 4248 // ICD returns a non-NULL GetProcAddr for it. 4249 bool loader_phys_dev_ext_gpa(struct loader_instance *inst, const char *funcName, bool perform_checking, void **tramp_addr, 4250 void **term_addr) { 4251 uint32_t idx; 4252 uint32_t seed = 0; 4253 bool success = false; 4254 4255 if (inst == NULL) { 4256 goto out; 4257 } 4258 4259 if (NULL != tramp_addr) { 4260 *tramp_addr = NULL; 4261 } 4262 if (NULL != term_addr) { 4263 *term_addr = NULL; 4264 } 4265 4266 // We should always check to see if any ICD supports it. 4267 if (!loader_check_icds_for_phys_dev_ext_address(inst, funcName)) { 4268 // If we're not checking layers, or we are and it's not in a layer, just 4269 // return 4270 if (!perform_checking || !loader_check_layer_list_for_phys_dev_ext_address(inst, funcName)) { 4271 goto out; 4272 } 4273 } 4274 4275 idx = murmurhash(funcName, strlen(funcName), seed) % MAX_NUM_UNKNOWN_EXTS; 4276 if (perform_checking && !loader_name_in_phys_dev_ext_table(inst, &idx, funcName)) { 4277 uint32_t i; 4278 bool added = false; 4279 4280 // Only need to add first one to get index in Instance. Others will use 4281 // the same index. 4282 if (!added && loader_add_phys_dev_ext_table(inst, &idx, funcName)) { 4283 added = true; 4284 } 4285 4286 // Setup the ICD function pointers 4287 struct loader_icd_term *icd_term = inst->icd_terms; 4288 while (NULL != icd_term) { 4289 if (MIN_PHYS_DEV_EXTENSION_ICD_INTERFACE_VERSION <= icd_term->scanned_icd->interface_version && 4290 NULL != icd_term->scanned_icd->GetPhysicalDeviceProcAddr) { 4291 icd_term->phys_dev_ext[idx] = 4292 (PFN_PhysDevExt)icd_term->scanned_icd->GetPhysicalDeviceProcAddr(icd_term->instance, funcName); 4293 4294 // Make sure we set the instance dispatch to point to the 4295 // loader's terminator now since we can at least handle it 4296 // in one ICD. 4297 inst->disp->phys_dev_ext[idx] = loader_get_phys_dev_ext_termin(idx); 4298 } else { 4299 icd_term->phys_dev_ext[idx] = NULL; 4300 } 4301 4302 icd_term = icd_term->next; 4303 } 4304 4305 // Now, search for the first layer attached and query using it to get 4306 // the first entry point. 4307 for (i = 0; i < inst->expanded_activated_layer_list.count; i++) { 4308 struct loader_layer_properties *layer_prop = &inst->expanded_activated_layer_list.list[i]; 4309 if (layer_prop->interface_version > 1 && NULL != layer_prop->functions.get_physical_device_proc_addr) { 4310 inst->disp->phys_dev_ext[idx] = 4311 (PFN_PhysDevExt)layer_prop->functions.get_physical_device_proc_addr((VkInstance)inst->instance, funcName); 4312 if (NULL != inst->disp->phys_dev_ext[idx]) { 4313 break; 4314 } 4315 } 4316 } 4317 } 4318 4319 if (NULL != tramp_addr) { 4320 *tramp_addr = loader_get_phys_dev_ext_tramp(idx); 4321 } 4322 4323 if (NULL != term_addr) { 4324 *term_addr = loader_get_phys_dev_ext_termin(idx); 4325 } 4326 4327 success = true; 4328 4329 out: 4330 return success; 4331 } 4332 4333 struct loader_instance *loader_get_instance(const VkInstance instance) { 4334 // look up the loader_instance in our list by comparing dispatch tables, as 4335 // there is no guarantee the instance is still a loader_instance* after any 4336 // layers which wrap the instance object. 4337 const VkLayerInstanceDispatchTable *disp; 4338 struct loader_instance *ptr_instance = NULL; 4339 disp = loader_get_instance_layer_dispatch(instance); 4340 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) { 4341 if (&inst->disp->layer_inst_disp == disp) { 4342 ptr_instance = inst; 4343 break; 4344 } 4345 } 4346 return ptr_instance; 4347 } 4348 4349 static loader_platform_dl_handle loader_open_layer_lib(const struct loader_instance *inst, const char *chain_type, 4350 struct loader_layer_properties *prop) { 4351 if ((prop->lib_handle = loader_platform_open_library(prop->lib_name)) == NULL) { 4352 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, loader_platform_open_library_error(prop->lib_name)); 4353 } else { 4354 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Loading layer library %s", prop->lib_name); 4355 } 4356 4357 return prop->lib_handle; 4358 } 4359 4360 static void loader_close_layer_lib(const struct loader_instance *inst, struct loader_layer_properties *prop) { 4361 if (prop->lib_handle) { 4362 loader_platform_close_library(prop->lib_handle); 4363 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Unloading layer library %s", prop->lib_name); 4364 prop->lib_handle = NULL; 4365 } 4366 } 4367 4368 void loader_deactivate_layers(const struct loader_instance *instance, struct loader_device *device, 4369 struct loader_layer_list *list) { 4370 // Delete instance list of enabled layers and close any layer libraries 4371 for (uint32_t i = 0; i < list->count; i++) { 4372 struct loader_layer_properties *layer_prop = &list->list[i]; 4373 4374 loader_close_layer_lib(instance, layer_prop); 4375 } 4376 loader_destroy_layer_list(instance, device, list); 4377 } 4378 4379 // Go through the search_list and find any layers which match type. If layer 4380 // type match is found in then add it to ext_list. 4381 static void loader_add_implicit_layers(const struct loader_instance *inst, struct loader_layer_list *target_list, 4382 struct loader_layer_list *expanded_target_list, 4383 const struct loader_layer_list *source_list) { 4384 for (uint32_t src_layer = 0; src_layer < source_list->count; src_layer++) { 4385 const struct loader_layer_properties *prop = &source_list->list[src_layer]; 4386 if (0 == (prop->type_flags & VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER)) { 4387 loader_add_implicit_layer(inst, prop, target_list, expanded_target_list, source_list); 4388 } 4389 } 4390 } 4391 4392 // Get the layer name(s) from the env_name environment variable. If layer is found in 4393 // search_list then add it to layer_list. But only add it to layer_list if type_flags matches. 4394 static void loader_add_env_layers(const struct loader_instance *inst, const enum layer_type_flags type_flags, const char *env_name, 4395 struct loader_layer_list *target_list, struct loader_layer_list *expanded_target_list, 4396 const struct loader_layer_list *source_list) { 4397 char *next, *name; 4398 char *layer_env = loader_secure_getenv(env_name, inst); 4399 if (layer_env == NULL) { 4400 goto out; 4401 } 4402 name = loader_stack_alloc(strlen(layer_env) + 1); 4403 if (name == NULL) { 4404 goto out; 4405 } 4406 strcpy(name, layer_env); 4407 4408 while (name && *name) { 4409 next = loader_get_next_path(name); 4410 loader_find_layer_name_add_list(inst, name, type_flags, source_list, target_list, expanded_target_list); 4411 name = next; 4412 } 4413 4414 out: 4415 4416 if (layer_env != NULL) { 4417 loader_free_getenv(layer_env, inst); 4418 } 4419 4420 return; 4421 } 4422 4423 VkResult loader_enable_instance_layers(struct loader_instance *inst, const VkInstanceCreateInfo *pCreateInfo, 4424 const struct loader_layer_list *instance_layers) { 4425 VkResult err; 4426 4427 assert(inst && "Cannot have null instance"); 4428 4429 if (!loader_init_layer_list(inst, &inst->app_activated_layer_list)) { 4430 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 4431 "loader_enable_instance_layers: Failed to initialize" 4432 " application version of the layer list"); 4433 return VK_ERROR_OUT_OF_HOST_MEMORY; 4434 } 4435 4436 if (!loader_init_layer_list(inst, &inst->expanded_activated_layer_list)) { 4437 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 4438 "loader_enable_instance_layers: Failed to initialize" 4439 " expanded version of the layer list"); 4440 return VK_ERROR_OUT_OF_HOST_MEMORY; 4441 } 4442 4443 // Add any implicit layers first 4444 loader_add_implicit_layers(inst, &inst->app_activated_layer_list, &inst->expanded_activated_layer_list, instance_layers); 4445 4446 // Add any layers specified via environment variable next 4447 loader_add_env_layers(inst, VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER, ENABLED_LAYERS_ENV, &inst->app_activated_layer_list, 4448 &inst->expanded_activated_layer_list, instance_layers); 4449 4450 // Add layers specified by the application 4451 err = loader_add_layer_names_to_list(inst, &inst->app_activated_layer_list, &inst->expanded_activated_layer_list, 4452 pCreateInfo->enabledLayerCount, pCreateInfo->ppEnabledLayerNames, instance_layers); 4453 4454 return err; 4455 } 4456 4457 // Determine the layer interface version to use. 4458 bool loader_get_layer_interface_version(PFN_vkNegotiateLoaderLayerInterfaceVersion fp_negotiate_layer_version, 4459 VkNegotiateLayerInterface *interface_struct) { 4460 memset(interface_struct, 0, sizeof(VkNegotiateLayerInterface)); 4461 interface_struct->sType = LAYER_NEGOTIATE_INTERFACE_STRUCT; 4462 interface_struct->loaderLayerInterfaceVersion = 1; 4463 4464 if (fp_negotiate_layer_version != NULL) { 4465 // Layer supports the negotiation API, so call it with the loader's 4466 // latest version supported 4467 interface_struct->loaderLayerInterfaceVersion = CURRENT_LOADER_LAYER_INTERFACE_VERSION; 4468 VkResult result = fp_negotiate_layer_version(interface_struct); 4469 4470 if (result != VK_SUCCESS) { 4471 // Layer no longer supports the loader's latest interface version so 4472 // fail loading the Layer 4473 return false; 4474 } 4475 } 4476 4477 if (interface_struct->loaderLayerInterfaceVersion < MIN_SUPPORTED_LOADER_LAYER_INTERFACE_VERSION) { 4478 // Loader no longer supports the layer's latest interface version so 4479 // fail loading the layer 4480 return false; 4481 } 4482 4483 return true; 4484 } 4485 4486 // Given the list of layers to activate in the loader_instance 4487 // structure. This function will add a VkLayerInstanceCreateInfo 4488 // structure to the VkInstanceCreateInfo.pNext pointer. 4489 // Each activated layer will have it's own VkLayerInstanceLink 4490 // structure that tells the layer what Get*ProcAddr to call to 4491 // get function pointers to the next layer down. 4492 // Once the chain info has been created this function will 4493 // execute the CreateInstance call chain. Each layer will 4494 // then have an opportunity in it's CreateInstance function 4495 // to setup it's dispatch table when the lower layer returns 4496 // successfully. 4497 // Each layer can wrap or not-wrap the returned VkInstance object 4498 // as it sees fit. 4499 // The instance chain is terminated by a loader function 4500 // that will call CreateInstance on all available ICD's and 4501 // cache those VkInstance objects for future use. 4502 VkResult loader_create_instance_chain(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, 4503 struct loader_instance *inst, VkInstance *created_instance) { 4504 uint32_t activated_layers = 0; 4505 VkLayerInstanceCreateInfo chain_info; 4506 VkLayerInstanceLink *layer_instance_link_info = NULL; 4507 VkInstanceCreateInfo loader_create_info; 4508 VkResult res; 4509 4510 PFN_vkGetInstanceProcAddr next_gipa = loader_gpa_instance_internal; 4511 PFN_vkGetInstanceProcAddr cur_gipa = loader_gpa_instance_internal; 4512 PFN_GetPhysicalDeviceProcAddr next_gpdpa = loader_gpdpa_instance_internal; 4513 PFN_GetPhysicalDeviceProcAddr cur_gpdpa = loader_gpdpa_instance_internal; 4514 4515 memcpy(&loader_create_info, pCreateInfo, sizeof(VkInstanceCreateInfo)); 4516 4517 if (inst->expanded_activated_layer_list.count > 0) { 4518 chain_info.u.pLayerInfo = NULL; 4519 chain_info.pNext = pCreateInfo->pNext; 4520 chain_info.sType = VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO; 4521 chain_info.function = VK_LAYER_LINK_INFO; 4522 loader_create_info.pNext = &chain_info; 4523 4524 layer_instance_link_info = loader_stack_alloc(sizeof(VkLayerInstanceLink) * inst->expanded_activated_layer_list.count); 4525 if (!layer_instance_link_info) { 4526 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 4527 "loader_create_instance_chain: Failed to alloc Instance" 4528 " objects for layer"); 4529 return VK_ERROR_OUT_OF_HOST_MEMORY; 4530 } 4531 4532 // Create instance chain of enabled layers 4533 for (int32_t i = inst->expanded_activated_layer_list.count - 1; i >= 0; i--) { 4534 struct loader_layer_properties *layer_prop = &inst->expanded_activated_layer_list.list[i]; 4535 loader_platform_dl_handle lib_handle; 4536 4537 lib_handle = loader_open_layer_lib(inst, "instance", layer_prop); 4538 if (!lib_handle) { 4539 continue; 4540 } 4541 4542 if (NULL == layer_prop->functions.negotiate_layer_interface) { 4543 PFN_vkNegotiateLoaderLayerInterfaceVersion negotiate_interface = NULL; 4544 bool functions_in_interface = false; 4545 if (strlen(layer_prop->functions.str_negotiate_interface) == 0) { 4546 negotiate_interface = (PFN_vkNegotiateLoaderLayerInterfaceVersion)loader_platform_get_proc_address( 4547 lib_handle, "vkNegotiateLoaderLayerInterfaceVersion"); 4548 } else { 4549 negotiate_interface = (PFN_vkNegotiateLoaderLayerInterfaceVersion)loader_platform_get_proc_address( 4550 lib_handle, layer_prop->functions.str_negotiate_interface); 4551 } 4552 4553 // If we can negotiate an interface version, then we can also 4554 // get everything we need from the one function call, so try 4555 // that first, and see if we can get all the function pointers 4556 // necessary from that one call. 4557 if (NULL != negotiate_interface) { 4558 layer_prop->functions.negotiate_layer_interface = negotiate_interface; 4559 4560 VkNegotiateLayerInterface interface_struct; 4561 4562 if (loader_get_layer_interface_version(negotiate_interface, &interface_struct)) { 4563 // Go ahead and set the properties version to the 4564 // correct value. 4565 layer_prop->interface_version = interface_struct.loaderLayerInterfaceVersion; 4566 4567 // If the interface is 2 or newer, we have access to the 4568 // new GetPhysicalDeviceProcAddr function, so grab it, 4569 // and the other necessary functions, from the 4570 // structure. 4571 if (interface_struct.loaderLayerInterfaceVersion > 1) { 4572 cur_gipa = interface_struct.pfnGetInstanceProcAddr; 4573 cur_gpdpa = interface_struct.pfnGetPhysicalDeviceProcAddr; 4574 if (cur_gipa != NULL) { 4575 // We've set the functions, so make sure we 4576 // don't do the unnecessary calls later. 4577 functions_in_interface = true; 4578 } 4579 } 4580 } 4581 } 4582 4583 if (!functions_in_interface) { 4584 if ((cur_gipa = layer_prop->functions.get_instance_proc_addr) == NULL) { 4585 if (strlen(layer_prop->functions.str_gipa) == 0) { 4586 cur_gipa = 4587 (PFN_vkGetInstanceProcAddr)loader_platform_get_proc_address(lib_handle, "vkGetInstanceProcAddr"); 4588 layer_prop->functions.get_instance_proc_addr = cur_gipa; 4589 } else { 4590 cur_gipa = (PFN_vkGetInstanceProcAddr)loader_platform_get_proc_address(lib_handle, 4591 layer_prop->functions.str_gipa); 4592 } 4593 4594 if (NULL == cur_gipa) { 4595 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 4596 "loader_create_instance_chain: Failed to" 4597 " find \'vkGetInstanceProcAddr\' in " 4598 "layer %s", 4599 layer_prop->lib_name); 4600 continue; 4601 } 4602 } 4603 } 4604 } 4605 4606 layer_instance_link_info[activated_layers].pNext = chain_info.u.pLayerInfo; 4607 layer_instance_link_info[activated_layers].pfnNextGetInstanceProcAddr = next_gipa; 4608 layer_instance_link_info[activated_layers].pfnNextGetPhysicalDeviceProcAddr = next_gpdpa; 4609 next_gipa = cur_gipa; 4610 if (layer_prop->interface_version > 1 && cur_gpdpa != NULL) { 4611 layer_prop->functions.get_physical_device_proc_addr = cur_gpdpa; 4612 next_gpdpa = cur_gpdpa; 4613 } 4614 4615 chain_info.u.pLayerInfo = &layer_instance_link_info[activated_layers]; 4616 4617 loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, "Insert instance layer %s (%s)", layer_prop->info.layerName, 4618 layer_prop->lib_name); 4619 4620 activated_layers++; 4621 } 4622 } 4623 4624 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)next_gipa(*created_instance, "vkCreateInstance"); 4625 if (fpCreateInstance) { 4626 VkLayerInstanceCreateInfo create_info_disp; 4627 4628 create_info_disp.sType = VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO; 4629 create_info_disp.function = VK_LOADER_DATA_CALLBACK; 4630 4631 create_info_disp.u.pfnSetInstanceLoaderData = vkSetInstanceDispatch; 4632 4633 create_info_disp.pNext = loader_create_info.pNext; 4634 loader_create_info.pNext = &create_info_disp; 4635 res = fpCreateInstance(&loader_create_info, pAllocator, created_instance); 4636 } else { 4637 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 4638 "loader_create_instance_chain: Failed to find " 4639 "\'vkCreateInstance\'"); 4640 // Couldn't find CreateInstance function! 4641 res = VK_ERROR_INITIALIZATION_FAILED; 4642 } 4643 4644 if (res == VK_SUCCESS) { 4645 loader_init_instance_core_dispatch_table(&inst->disp->layer_inst_disp, next_gipa, *created_instance); 4646 inst->instance = *created_instance; 4647 } 4648 4649 return res; 4650 } 4651 4652 void loader_activate_instance_layer_extensions(struct loader_instance *inst, VkInstance created_inst) { 4653 loader_init_instance_extension_dispatch_table(&inst->disp->layer_inst_disp, inst->disp->layer_inst_disp.GetInstanceProcAddr, 4654 created_inst); 4655 } 4656 4657 VkResult loader_create_device_chain(const struct loader_physical_device_tramp *pd, const VkDeviceCreateInfo *pCreateInfo, 4658 const VkAllocationCallbacks *pAllocator, const struct loader_instance *inst, 4659 struct loader_device *dev) { 4660 uint32_t activated_layers = 0; 4661 VkLayerDeviceLink *layer_device_link_info; 4662 VkLayerDeviceCreateInfo chain_info; 4663 VkDeviceCreateInfo loader_create_info; 4664 VkResult res; 4665 4666 PFN_vkGetDeviceProcAddr fpGDPA = NULL, nextGDPA = loader_gpa_device_internal; 4667 PFN_vkGetInstanceProcAddr fpGIPA = NULL, nextGIPA = loader_gpa_instance_internal; 4668 4669 memcpy(&loader_create_info, pCreateInfo, sizeof(VkDeviceCreateInfo)); 4670 4671 // Before we continue, we need to find out if the KHX_device_group extension is in the enabled list. If it is, we then 4672 // need to look for the corresponding VkDeviceGroupDeviceCreateInfoKHX struct in the device list. This is because we 4673 // need to replace all the incoming physical device values (which are really loader trampoline physical device values) 4674 // with the layer/ICD version. 4675 if (inst->enabled_known_extensions.khx_device_group_creation == 1) { 4676 struct VkStructureHeader *pNext = (struct VkStructureHeader *)loader_create_info.pNext; 4677 struct VkStructureHeader *pPrev = (struct VkStructureHeader *)&loader_create_info; 4678 while (NULL != pNext) { 4679 if (VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHX == pNext->sType) { 4680 VkDeviceGroupDeviceCreateInfoKHX *cur_struct = (VkDeviceGroupDeviceCreateInfoKHX *)pNext; 4681 if (0 < cur_struct->physicalDeviceCount && NULL != cur_struct->pPhysicalDevices) { 4682 VkDeviceGroupDeviceCreateInfoKHX *temp_struct = loader_stack_alloc(sizeof(VkDeviceGroupDeviceCreateInfoKHX)); 4683 VkPhysicalDevice *phys_dev_array = NULL; 4684 if (NULL == temp_struct) { 4685 return VK_ERROR_OUT_OF_HOST_MEMORY; 4686 } 4687 memcpy(temp_struct, cur_struct, sizeof(VkDeviceGroupDeviceCreateInfoKHX)); 4688 phys_dev_array = loader_stack_alloc(sizeof(VkPhysicalDevice) * cur_struct->physicalDeviceCount); 4689 if (NULL == phys_dev_array) { 4690 return VK_ERROR_OUT_OF_HOST_MEMORY; 4691 } 4692 4693 // Before calling down, replace the incoming physical device values (which are really loader trampoline 4694 // physical devices) with the next layer (or possibly even the terminator) physical device values. 4695 struct loader_physical_device_tramp *cur_tramp; 4696 for (uint32_t phys_dev = 0; phys_dev < cur_struct->physicalDeviceCount; phys_dev++) { 4697 cur_tramp = (struct loader_physical_device_tramp *)cur_struct->pPhysicalDevices[phys_dev]; 4698 phys_dev_array[phys_dev] = cur_tramp->phys_dev; 4699 } 4700 temp_struct->pPhysicalDevices = phys_dev_array; 4701 4702 // Replace the old struct in the pNext chain with this one. 4703 pPrev->pNext = (const void *)temp_struct; 4704 pNext = (struct VkStructureHeader *)(temp_struct); 4705 } 4706 break; 4707 } 4708 4709 pPrev = pNext; 4710 pNext = (struct VkStructureHeader *)(pPrev->pNext); 4711 } 4712 } 4713 4714 layer_device_link_info = loader_stack_alloc(sizeof(VkLayerDeviceLink) * dev->expanded_activated_layer_list.count); 4715 if (!layer_device_link_info) { 4716 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 4717 "loader_create_device_chain: Failed to alloc Device objects" 4718 " for layer. Skipping Layer."); 4719 return VK_ERROR_OUT_OF_HOST_MEMORY; 4720 } 4721 4722 if (dev->expanded_activated_layer_list.count > 0) { 4723 chain_info.sType = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO; 4724 chain_info.function = VK_LAYER_LINK_INFO; 4725 chain_info.u.pLayerInfo = NULL; 4726 chain_info.pNext = loader_create_info.pNext; 4727 loader_create_info.pNext = &chain_info; 4728 4729 // Create instance chain of enabled layers 4730 for (int32_t i = dev->expanded_activated_layer_list.count - 1; i >= 0; i--) { 4731 struct loader_layer_properties *layer_prop = &dev->expanded_activated_layer_list.list[i]; 4732 loader_platform_dl_handle lib_handle; 4733 bool functions_in_interface = false; 4734 4735 lib_handle = loader_open_layer_lib(inst, "device", layer_prop); 4736 if (!lib_handle) { 4737 continue; 4738 } 4739 4740 // If we can negotiate an interface version, then we can also get everything we need from the one function 4741 // call, so try that first, and see if we can get all the function pointers necessary from that one call. 4742 if (NULL == layer_prop->functions.negotiate_layer_interface) { 4743 PFN_vkNegotiateLoaderLayerInterfaceVersion negotiate_interface = NULL; 4744 if (strlen(layer_prop->functions.str_negotiate_interface) == 0) { 4745 negotiate_interface = (PFN_vkNegotiateLoaderLayerInterfaceVersion)loader_platform_get_proc_address( 4746 lib_handle, "vkNegotiateLoaderLayerInterfaceVersion"); 4747 } else { 4748 negotiate_interface = (PFN_vkNegotiateLoaderLayerInterfaceVersion)loader_platform_get_proc_address( 4749 lib_handle, layer_prop->functions.str_negotiate_interface); 4750 } 4751 4752 if (NULL != negotiate_interface) { 4753 layer_prop->functions.negotiate_layer_interface = negotiate_interface; 4754 4755 VkNegotiateLayerInterface interface_struct; 4756 4757 if (loader_get_layer_interface_version(negotiate_interface, &interface_struct)) { 4758 // Go ahead and set the properties version to the correct value. 4759 layer_prop->interface_version = interface_struct.loaderLayerInterfaceVersion; 4760 4761 // If the interface is 2 or newer, we have access to the new GetPhysicalDeviceProcAddr 4762 // function, so grab it, and the other necessary functions, from the structure. 4763 if (interface_struct.loaderLayerInterfaceVersion > 1) { 4764 fpGIPA = interface_struct.pfnGetInstanceProcAddr; 4765 fpGDPA = interface_struct.pfnGetDeviceProcAddr; 4766 if (fpGIPA != NULL && fpGDPA) { 4767 // We've set the functions, so make sure we 4768 // don't do the unnecessary calls later. 4769 functions_in_interface = true; 4770 } 4771 } 4772 } 4773 } 4774 } 4775 4776 if (!functions_in_interface) { 4777 if ((fpGIPA = layer_prop->functions.get_instance_proc_addr) == NULL) { 4778 if (strlen(layer_prop->functions.str_gipa) == 0) { 4779 fpGIPA = (PFN_vkGetInstanceProcAddr)loader_platform_get_proc_address(lib_handle, "vkGetInstanceProcAddr"); 4780 layer_prop->functions.get_instance_proc_addr = fpGIPA; 4781 } else 4782 fpGIPA = 4783 (PFN_vkGetInstanceProcAddr)loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gipa); 4784 if (!fpGIPA) { 4785 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 4786 "loader_create_device_chain: Failed to find " 4787 "\'vkGetInstanceProcAddr\' in layer %s. Skipping" 4788 " layer.", 4789 layer_prop->lib_name); 4790 continue; 4791 } 4792 } 4793 if ((fpGDPA = layer_prop->functions.get_device_proc_addr) == NULL) { 4794 if (strlen(layer_prop->functions.str_gdpa) == 0) { 4795 fpGDPA = (PFN_vkGetDeviceProcAddr)loader_platform_get_proc_address(lib_handle, "vkGetDeviceProcAddr"); 4796 layer_prop->functions.get_device_proc_addr = fpGDPA; 4797 } else 4798 fpGDPA = 4799 (PFN_vkGetDeviceProcAddr)loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gdpa); 4800 if (!fpGDPA) { 4801 loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, "Failed to find vkGetDeviceProcAddr in layer %s", 4802 layer_prop->lib_name); 4803 continue; 4804 } 4805 } 4806 } 4807 layer_device_link_info[activated_layers].pNext = chain_info.u.pLayerInfo; 4808 layer_device_link_info[activated_layers].pfnNextGetInstanceProcAddr = nextGIPA; 4809 layer_device_link_info[activated_layers].pfnNextGetDeviceProcAddr = nextGDPA; 4810 chain_info.u.pLayerInfo = &layer_device_link_info[activated_layers]; 4811 nextGIPA = fpGIPA; 4812 nextGDPA = fpGDPA; 4813 4814 loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, "Inserted device layer %s (%s)", layer_prop->info.layerName, 4815 layer_prop->lib_name); 4816 4817 activated_layers++; 4818 } 4819 } 4820 4821 VkDevice created_device = (VkDevice)dev; 4822 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)nextGIPA(inst->instance, "vkCreateDevice"); 4823 if (fpCreateDevice) { 4824 VkLayerDeviceCreateInfo create_info_disp; 4825 4826 create_info_disp.sType = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO; 4827 create_info_disp.function = VK_LOADER_DATA_CALLBACK; 4828 4829 create_info_disp.u.pfnSetDeviceLoaderData = vkSetDeviceDispatch; 4830 4831 create_info_disp.pNext = loader_create_info.pNext; 4832 loader_create_info.pNext = &create_info_disp; 4833 res = fpCreateDevice(pd->phys_dev, &loader_create_info, pAllocator, &created_device); 4834 if (res != VK_SUCCESS) { 4835 return res; 4836 } 4837 dev->chain_device = created_device; 4838 } else { 4839 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 4840 "loader_create_device_chain: Failed to find \'vkCreateDevice\' " 4841 "in layer %s"); 4842 // Couldn't find CreateDevice function! 4843 return VK_ERROR_INITIALIZATION_FAILED; 4844 } 4845 4846 // Initialize device dispatch table 4847 loader_init_device_dispatch_table(&dev->loader_dispatch, nextGDPA, dev->chain_device); 4848 4849 return res; 4850 } 4851 4852 VkResult loader_validate_layers(const struct loader_instance *inst, const uint32_t layer_count, 4853 const char *const *ppEnabledLayerNames, const struct loader_layer_list *list) { 4854 struct loader_layer_properties *prop; 4855 4856 for (uint32_t i = 0; i < layer_count; i++) { 4857 VkStringErrorFlags result = vk_string_validate(MaxLoaderStringLength, ppEnabledLayerNames[i]); 4858 if (result != VK_STRING_ERROR_NONE) { 4859 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 4860 "loader_validate_layers: Device ppEnabledLayerNames " 4861 "contains string that is too long or is badly formed"); 4862 return VK_ERROR_LAYER_NOT_PRESENT; 4863 } 4864 4865 prop = loader_get_layer_property(ppEnabledLayerNames[i], list); 4866 if (NULL == prop) { 4867 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 4868 "loader_validate_layers: Layer %d does not exist in the list of available layers", i); 4869 return VK_ERROR_LAYER_NOT_PRESENT; 4870 } 4871 } 4872 return VK_SUCCESS; 4873 } 4874 4875 VkResult loader_validate_instance_extensions(const struct loader_instance *inst, const struct loader_extension_list *icd_exts, 4876 const struct loader_layer_list *instance_layers, 4877 const VkInstanceCreateInfo *pCreateInfo) { 4878 VkExtensionProperties *extension_prop; 4879 char *env_value; 4880 bool check_if_known = true; 4881 VkResult res = VK_SUCCESS; 4882 4883 struct loader_layer_list active_layers; 4884 struct loader_layer_list expanded_layers; 4885 memset(&active_layers, 0, sizeof(active_layers)); 4886 memset(&expanded_layers, 0, sizeof(expanded_layers)); 4887 if (!loader_init_layer_list(inst, &active_layers)) { 4888 res = VK_ERROR_OUT_OF_HOST_MEMORY; 4889 goto out; 4890 } 4891 if (!loader_init_layer_list(inst, &expanded_layers)) { 4892 res = VK_ERROR_OUT_OF_HOST_MEMORY; 4893 goto out; 4894 } 4895 4896 // Build the lists of active layers (including metalayers) and expanded layers (with metalayers resolved to their components) 4897 loader_add_implicit_layers(inst, &active_layers, &expanded_layers, instance_layers); 4898 loader_add_env_layers(inst, VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER, ENABLED_LAYERS_ENV, &active_layers, &expanded_layers, 4899 instance_layers); 4900 res = loader_add_layer_names_to_list(inst, &active_layers, &expanded_layers, pCreateInfo->enabledLayerCount, 4901 pCreateInfo->ppEnabledLayerNames, instance_layers); 4902 if (VK_SUCCESS != res) { 4903 goto out; 4904 } 4905 4906 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) { 4907 VkStringErrorFlags result = vk_string_validate(MaxLoaderStringLength, pCreateInfo->ppEnabledExtensionNames[i]); 4908 if (result != VK_STRING_ERROR_NONE) { 4909 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 4910 "loader_validate_instance_extensions: Instance ppEnabledExtensionNames contains " 4911 "string that is too long or is badly formed"); 4912 res = VK_ERROR_EXTENSION_NOT_PRESENT; 4913 goto out; 4914 } 4915 4916 // Check if a user wants to disable the instance extension filtering behavior 4917 env_value = loader_getenv("VK_LOADER_DISABLE_INST_EXT_FILTER", inst); 4918 if (NULL != env_value && atoi(env_value) != 0) { 4919 check_if_known = false; 4920 } 4921 loader_free_getenv(env_value, inst); 4922 4923 if (check_if_known) { 4924 // See if the extension is in the list of supported extensions 4925 bool found = false; 4926 for (uint32_t j = 0; LOADER_INSTANCE_EXTENSIONS[j] != NULL; j++) { 4927 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], LOADER_INSTANCE_EXTENSIONS[j]) == 0) { 4928 found = true; 4929 break; 4930 } 4931 } 4932 4933 // If it isn't in the list, return an error 4934 if (!found) { 4935 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 4936 "loader_validate_instance_extensions: Extension %s not found in list of known instance extensions.", 4937 pCreateInfo->ppEnabledExtensionNames[i]); 4938 res = VK_ERROR_EXTENSION_NOT_PRESENT; 4939 goto out; 4940 } 4941 } 4942 4943 extension_prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i], icd_exts); 4944 4945 if (extension_prop) { 4946 continue; 4947 } 4948 4949 extension_prop = NULL; 4950 4951 // Not in global list, search expanded layer extension list 4952 for (uint32_t j = 0; NULL == extension_prop && j < expanded_layers.count; ++j) { 4953 extension_prop = 4954 get_extension_property(pCreateInfo->ppEnabledExtensionNames[i], &expanded_layers.list[j].instance_extension_list); 4955 } 4956 4957 if (!extension_prop) { 4958 // Didn't find extension name in any of the global layers, error out 4959 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 4960 "loader_validate_instance_extensions: Instance extension %s not supported by available ICDs or enabled " 4961 "layers.", 4962 pCreateInfo->ppEnabledExtensionNames[i]); 4963 res = VK_ERROR_EXTENSION_NOT_PRESENT; 4964 goto out; 4965 } 4966 } 4967 4968 out: 4969 loader_destroy_layer_list(inst, NULL, &active_layers); 4970 loader_destroy_layer_list(inst, NULL, &expanded_layers); 4971 return res; 4972 } 4973 4974 VkResult loader_validate_device_extensions(struct loader_physical_device_tramp *phys_dev, 4975 const struct loader_layer_list *activated_device_layers, 4976 const struct loader_extension_list *icd_exts, const VkDeviceCreateInfo *pCreateInfo) { 4977 VkExtensionProperties *extension_prop; 4978 struct loader_layer_properties *layer_prop; 4979 4980 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) { 4981 VkStringErrorFlags result = vk_string_validate(MaxLoaderStringLength, pCreateInfo->ppEnabledExtensionNames[i]); 4982 if (result != VK_STRING_ERROR_NONE) { 4983 loader_log(phys_dev->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 4984 "loader_validate_device_extensions: Device ppEnabledExtensionNames contains " 4985 "string that is too long or is badly formed"); 4986 return VK_ERROR_EXTENSION_NOT_PRESENT; 4987 } 4988 4989 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i]; 4990 extension_prop = get_extension_property(extension_name, icd_exts); 4991 4992 if (extension_prop) { 4993 continue; 4994 } 4995 4996 // Not in global list, search activated layer extension lists 4997 for (uint32_t j = 0; j < activated_device_layers->count; j++) { 4998 layer_prop = &activated_device_layers->list[j]; 4999 5000 extension_prop = get_dev_extension_property(extension_name, &layer_prop->device_extension_list); 5001 if (extension_prop) { 5002 // Found the extension in one of the layers enabled by the app. 5003 break; 5004 } 5005 } 5006 5007 if (!extension_prop) { 5008 // Didn't find extension name in any of the device layers, error out 5009 loader_log(phys_dev->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 5010 "loader_validate_device_extensions: Device extension %s not supported by selected physical device " 5011 "or enabled layers.", 5012 pCreateInfo->ppEnabledExtensionNames[i]); 5013 return VK_ERROR_EXTENSION_NOT_PRESENT; 5014 } 5015 } 5016 return VK_SUCCESS; 5017 } 5018 5019 // Terminator functions for the Instance chain 5020 // All named terminator_<Vulakn API name> 5021 VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateInstance(const VkInstanceCreateInfo *pCreateInfo, 5022 const VkAllocationCallbacks *pAllocator, VkInstance *pInstance) { 5023 struct loader_icd_term *icd_term; 5024 VkExtensionProperties *prop; 5025 char **filtered_extension_names = NULL; 5026 VkInstanceCreateInfo icd_create_info; 5027 VkResult res = VK_SUCCESS; 5028 bool one_icd_successful = false; 5029 5030 struct loader_instance *ptr_instance = (struct loader_instance *)*pInstance; 5031 memcpy(&icd_create_info, pCreateInfo, sizeof(icd_create_info)); 5032 5033 icd_create_info.enabledLayerCount = 0; 5034 icd_create_info.ppEnabledLayerNames = NULL; 5035 5036 // NOTE: Need to filter the extensions to only those supported by the ICD. 5037 // No ICD will advertise support for layers. An ICD library could 5038 // support a layer, but it would be independent of the actual ICD, 5039 // just in the same library. 5040 filtered_extension_names = loader_stack_alloc(pCreateInfo->enabledExtensionCount * sizeof(char *)); 5041 if (!filtered_extension_names) { 5042 loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 5043 "terminator_CreateInstance: Failed create extension name array for %d extensions", 5044 pCreateInfo->enabledExtensionCount); 5045 res = VK_ERROR_OUT_OF_HOST_MEMORY; 5046 goto out; 5047 } 5048 icd_create_info.ppEnabledExtensionNames = (const char *const *)filtered_extension_names; 5049 5050 for (uint32_t i = 0; i < ptr_instance->icd_tramp_list.count; i++) { 5051 icd_term = loader_icd_add(ptr_instance, &ptr_instance->icd_tramp_list.scanned_list[i]); 5052 if (NULL == icd_term) { 5053 loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 5054 "terminator_CreateInstance: Failed to add ICD %d to ICD trampoline list.", i); 5055 res = VK_ERROR_OUT_OF_HOST_MEMORY; 5056 goto out; 5057 } 5058 5059 // If any error happens after here, we need to remove the ICD from the list, 5060 // because we've already added it, but haven't validated it 5061 5062 icd_create_info.enabledExtensionCount = 0; 5063 struct loader_extension_list icd_exts; 5064 5065 loader_log(ptr_instance, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Build ICD instance extension list"); 5066 // traverse scanned icd list adding non-duplicate extensions to the list 5067 res = loader_init_generic_list(ptr_instance, (struct loader_generic_list *)&icd_exts, sizeof(VkExtensionProperties)); 5068 if (VK_ERROR_OUT_OF_HOST_MEMORY == res) { 5069 // If out of memory, bail immediately. 5070 goto out; 5071 } else if (VK_SUCCESS != res) { 5072 // Something bad happened with this ICD, so free it and try the 5073 // next. 5074 ptr_instance->icd_terms = icd_term->next; 5075 icd_term->next = NULL; 5076 loader_icd_destroy(ptr_instance, icd_term, pAllocator); 5077 continue; 5078 } 5079 5080 res = loader_add_instance_extensions(ptr_instance, icd_term->scanned_icd->EnumerateInstanceExtensionProperties, 5081 icd_term->scanned_icd->lib_name, &icd_exts); 5082 if (VK_SUCCESS != res) { 5083 loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *)&icd_exts); 5084 if (VK_ERROR_OUT_OF_HOST_MEMORY == res) { 5085 // If out of memory, bail immediately. 5086 goto out; 5087 } else { 5088 // Something bad happened with this ICD, so free it and try the next. 5089 ptr_instance->icd_terms = icd_term->next; 5090 icd_term->next = NULL; 5091 loader_icd_destroy(ptr_instance, icd_term, pAllocator); 5092 continue; 5093 } 5094 } 5095 5096 for (uint32_t j = 0; j < pCreateInfo->enabledExtensionCount; j++) { 5097 prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[j], &icd_exts); 5098 if (prop) { 5099 filtered_extension_names[icd_create_info.enabledExtensionCount] = (char *)pCreateInfo->ppEnabledExtensionNames[j]; 5100 icd_create_info.enabledExtensionCount++; 5101 } 5102 } 5103 5104 loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *)&icd_exts); 5105 5106 VkResult icd_result = 5107 ptr_instance->icd_tramp_list.scanned_list[i].CreateInstance(&icd_create_info, pAllocator, &(icd_term->instance)); 5108 if (VK_ERROR_OUT_OF_HOST_MEMORY == icd_result) { 5109 // If out of memory, bail immediately. 5110 res = VK_ERROR_OUT_OF_HOST_MEMORY; 5111 goto out; 5112 } else if (VK_SUCCESS != icd_result) { 5113 loader_log(ptr_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 5114 "terminator_CreateInstance: Failed to CreateInstance in " 5115 "ICD %d. Skipping ICD.", 5116 i); 5117 ptr_instance->icd_terms = icd_term->next; 5118 icd_term->next = NULL; 5119 loader_icd_destroy(ptr_instance, icd_term, pAllocator); 5120 continue; 5121 } 5122 5123 if (!loader_icd_init_entries(icd_term, icd_term->instance, 5124 ptr_instance->icd_tramp_list.scanned_list[i].GetInstanceProcAddr)) { 5125 loader_log(ptr_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 5126 "terminator_CreateInstance: Failed to CreateInstance and find " 5127 "entrypoints with ICD. Skipping ICD."); 5128 ptr_instance->icd_terms = icd_term->next; 5129 icd_term->next = NULL; 5130 loader_icd_destroy(ptr_instance, icd_term, pAllocator); 5131 continue; 5132 } 5133 5134 // If we made it this far, at least one ICD was successful 5135 one_icd_successful = true; 5136 } 5137 5138 // If no ICDs were added to instance list and res is unchanged from it's initial value, the loader was unable to 5139 // find a suitable ICD. 5140 if (VK_SUCCESS == res && (ptr_instance->icd_terms == NULL || !one_icd_successful)) { 5141 res = VK_ERROR_INCOMPATIBLE_DRIVER; 5142 } 5143 5144 out: 5145 5146 if (VK_SUCCESS != res) { 5147 while (NULL != ptr_instance->icd_terms) { 5148 icd_term = ptr_instance->icd_terms; 5149 ptr_instance->icd_terms = icd_term->next; 5150 if (NULL != icd_term->instance) { 5151 icd_term->dispatch.DestroyInstance(icd_term->instance, pAllocator); 5152 } 5153 loader_icd_destroy(ptr_instance, icd_term, pAllocator); 5154 } 5155 } 5156 5157 return res; 5158 } 5159 5160 VKAPI_ATTR void VKAPI_CALL terminator_DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) { 5161 struct loader_instance *ptr_instance = loader_instance(instance); 5162 if (NULL == ptr_instance) { 5163 return; 5164 } 5165 struct loader_icd_term *icd_terms = ptr_instance->icd_terms; 5166 struct loader_icd_term *next_icd_term; 5167 5168 // Remove this instance from the list of instances: 5169 struct loader_instance *prev = NULL; 5170 struct loader_instance *next = loader.instances; 5171 while (next != NULL) { 5172 if (next == ptr_instance) { 5173 // Remove this instance from the list: 5174 if (prev) 5175 prev->next = next->next; 5176 else 5177 loader.instances = next->next; 5178 break; 5179 } 5180 prev = next; 5181 next = next->next; 5182 } 5183 5184 while (NULL != icd_terms) { 5185 if (icd_terms->instance) { 5186 icd_terms->dispatch.DestroyInstance(icd_terms->instance, pAllocator); 5187 } 5188 next_icd_term = icd_terms->next; 5189 icd_terms->instance = VK_NULL_HANDLE; 5190 loader_icd_destroy(ptr_instance, icd_terms, pAllocator); 5191 5192 icd_terms = next_icd_term; 5193 } 5194 5195 loader_delete_layer_properties(ptr_instance, &ptr_instance->instance_layer_list); 5196 loader_scanned_icd_clear(ptr_instance, &ptr_instance->icd_tramp_list); 5197 loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *)&ptr_instance->ext_list); 5198 if (NULL != ptr_instance->phys_devs_term) { 5199 for (uint32_t i = 0; i < ptr_instance->phys_dev_count_term; i++) { 5200 loader_instance_heap_free(ptr_instance, ptr_instance->phys_devs_term[i]); 5201 } 5202 loader_instance_heap_free(ptr_instance, ptr_instance->phys_devs_term); 5203 } 5204 if (NULL != ptr_instance->phys_dev_groups_term) { 5205 for (uint32_t i = 0; i < ptr_instance->phys_dev_group_count_term; i++) { 5206 loader_instance_heap_free(ptr_instance, ptr_instance->phys_dev_groups_term[i]); 5207 } 5208 loader_instance_heap_free(ptr_instance, ptr_instance->phys_dev_groups_term); 5209 } 5210 loader_free_dev_ext_table(ptr_instance); 5211 loader_free_phys_dev_ext_table(ptr_instance); 5212 } 5213 5214 VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo, 5215 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) { 5216 VkResult res = VK_SUCCESS; 5217 struct loader_physical_device_term *phys_dev_term; 5218 phys_dev_term = (struct loader_physical_device_term *)physicalDevice; 5219 struct loader_icd_term *icd_term = phys_dev_term->this_icd_term; 5220 5221 struct loader_device *dev = (struct loader_device *)*pDevice; 5222 PFN_vkCreateDevice fpCreateDevice = icd_term->dispatch.CreateDevice; 5223 struct loader_extension_list icd_exts; 5224 5225 struct VkStructureHeader *caller_dgci_container = NULL; 5226 VkDeviceGroupDeviceCreateInfoKHX *caller_dgci = NULL; 5227 5228 dev->phys_dev_term = phys_dev_term; 5229 5230 icd_exts.list = NULL; 5231 5232 if (fpCreateDevice == NULL) { 5233 loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 5234 "terminator_CreateDevice: No vkCreateDevice command exposed " 5235 "by ICD %s", 5236 icd_term->scanned_icd->lib_name); 5237 res = VK_ERROR_INITIALIZATION_FAILED; 5238 goto out; 5239 } 5240 5241 VkDeviceCreateInfo localCreateInfo; 5242 memcpy(&localCreateInfo, pCreateInfo, sizeof(localCreateInfo)); 5243 5244 // NOTE: Need to filter the extensions to only those supported by the ICD. 5245 // No ICD will advertise support for layers. An ICD library could support a layer, 5246 // but it would be independent of the actual ICD, just in the same library. 5247 char **filtered_extension_names = NULL; 5248 if (0 < pCreateInfo->enabledExtensionCount) { 5249 filtered_extension_names = loader_stack_alloc(pCreateInfo->enabledExtensionCount * sizeof(char *)); 5250 if (NULL == filtered_extension_names) { 5251 loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 5252 "terminator_CreateDevice: Failed to create extension name " 5253 "storage for %d extensions %d", 5254 pCreateInfo->enabledExtensionCount); 5255 return VK_ERROR_OUT_OF_HOST_MEMORY; 5256 } 5257 } 5258 5259 localCreateInfo.enabledLayerCount = 0; 5260 localCreateInfo.ppEnabledLayerNames = NULL; 5261 5262 localCreateInfo.enabledExtensionCount = 0; 5263 localCreateInfo.ppEnabledExtensionNames = (const char *const *)filtered_extension_names; 5264 5265 // Get the physical device (ICD) extensions 5266 res = loader_init_generic_list(icd_term->this_instance, (struct loader_generic_list *)&icd_exts, sizeof(VkExtensionProperties)); 5267 if (VK_SUCCESS != res) { 5268 goto out; 5269 } 5270 5271 res = loader_add_device_extensions(icd_term->this_instance, icd_term->dispatch.EnumerateDeviceExtensionProperties, 5272 phys_dev_term->phys_dev, icd_term->scanned_icd->lib_name, &icd_exts); 5273 if (res != VK_SUCCESS) { 5274 goto out; 5275 } 5276 5277 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) { 5278 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i]; 5279 VkExtensionProperties *prop = get_extension_property(extension_name, &icd_exts); 5280 if (prop) { 5281 filtered_extension_names[localCreateInfo.enabledExtensionCount] = (char *)extension_name; 5282 localCreateInfo.enabledExtensionCount++; 5283 } else { 5284 loader_log(icd_term->this_instance, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, 5285 "vkCreateDevice extension %s not available for " 5286 "devices associated with ICD %s", 5287 extension_name, icd_term->scanned_icd->lib_name); 5288 } 5289 } 5290 5291 // Before we continue, If KHX_device_group is the list of enabled and viable extensions, then we then need to look for the 5292 // corresponding VkDeviceGroupDeviceCreateInfoKHX struct in the device list and replace all the physical device values (which 5293 // are really loader physical device terminator values) with the ICD versions. 5294 if (icd_term->this_instance->enabled_known_extensions.khx_device_group_creation == 1) { 5295 struct VkStructureHeader *pNext = (struct VkStructureHeader *)localCreateInfo.pNext; 5296 struct VkStructureHeader *pPrev = (struct VkStructureHeader *)&localCreateInfo; 5297 while (NULL != pNext) { 5298 if (VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHX == pNext->sType) { 5299 VkDeviceGroupDeviceCreateInfoKHX *cur_struct = (VkDeviceGroupDeviceCreateInfoKHX *)pNext; 5300 if (0 < cur_struct->physicalDeviceCount && NULL != cur_struct->pPhysicalDevices) { 5301 VkDeviceGroupDeviceCreateInfoKHX *temp_struct = loader_stack_alloc(sizeof(VkDeviceGroupDeviceCreateInfoKHX)); 5302 VkPhysicalDevice *phys_dev_array = NULL; 5303 if (NULL == temp_struct) { 5304 return VK_ERROR_OUT_OF_HOST_MEMORY; 5305 } 5306 memcpy(temp_struct, cur_struct, sizeof(VkDeviceGroupDeviceCreateInfoKHX)); 5307 phys_dev_array = loader_stack_alloc(sizeof(VkPhysicalDevice) * cur_struct->physicalDeviceCount); 5308 if (NULL == phys_dev_array) { 5309 return VK_ERROR_OUT_OF_HOST_MEMORY; 5310 } 5311 5312 // Before calling down, replace the incoming physical device values (which are really loader terminator 5313 // physical devices) with the ICDs physical device values. 5314 struct loader_physical_device_term *cur_term; 5315 for (uint32_t phys_dev = 0; phys_dev < cur_struct->physicalDeviceCount; phys_dev++) { 5316 cur_term = (struct loader_physical_device_term *)cur_struct->pPhysicalDevices[phys_dev]; 5317 phys_dev_array[phys_dev] = cur_term->phys_dev; 5318 } 5319 temp_struct->pPhysicalDevices = phys_dev_array; 5320 5321 // Keep track of pointers to restore pNext chain before returning 5322 caller_dgci_container = pPrev; 5323 caller_dgci = cur_struct; 5324 5325 // Replace the old struct in the pNext chain with this one. 5326 pPrev->pNext = (const void *)temp_struct; 5327 pNext = (struct VkStructureHeader *)(temp_struct); 5328 } 5329 break; 5330 } 5331 5332 pPrev = pNext; 5333 pNext = (struct VkStructureHeader *)(pPrev->pNext); 5334 } 5335 } 5336 5337 // Handle loader emulation for structs that are not supported by the ICD: 5338 // Presently, the emulation leaves the pNext chain alone. This means that the ICD will receive items in the chain which 5339 // are not recognized by the ICD. If this causes the ICD to fail, then the items would have to be removed here. The current 5340 // implementation does not remove them because copying the pNext chain would be impossible if the loader does not recognize 5341 // the any of the struct types, as the loader would not know the size to allocate and copy. 5342 if (icd_term->dispatch.GetPhysicalDeviceFeatures2KHR == NULL) { 5343 const void *pNext = localCreateInfo.pNext; 5344 while (pNext != NULL) { 5345 switch (*(VkStructureType *)pNext) { 5346 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR: { 5347 loader_log(icd_term->this_instance, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, 5348 "vkCreateDevice: Emulating handling of VkPhysicalDeviceFeatures2KHR in pNext chain for ICD \"%s\"", 5349 icd_term->scanned_icd->lib_name); 5350 const VkPhysicalDeviceFeatures2KHR *features = pNext; 5351 5352 // Verify that VK_KHR_get_physical_device_properties2 is enabled 5353 if (icd_term->this_instance->enabled_known_extensions.khr_get_physical_device_properties2) { 5354 localCreateInfo.pEnabledFeatures = &features->features; 5355 } 5356 5357 // Leave this item in the pNext chain for now 5358 5359 pNext = features->pNext; 5360 break; 5361 } 5362 5363 case VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHX: { 5364 loader_log( 5365 icd_term->this_instance, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, 5366 "vkCreateDevice: Emulating handling of VkDeviceGroupDeviceCreateInfoKHX in pNext chain for ICD \"%s\"", 5367 icd_term->scanned_icd->lib_name); 5368 const VkDeviceGroupDeviceCreateInfoKHX *group_info = pNext; 5369 5370 // The group must contain only this one device, since physical device groups aren't actually supported 5371 if (group_info->physicalDeviceCount != 1 || group_info->pPhysicalDevices[0] != physicalDevice) { 5372 loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 5373 "vkCreateDevice: Emulation failed to create device from device group info"); 5374 res = VK_ERROR_INITIALIZATION_FAILED; 5375 goto out; 5376 } 5377 5378 // Nothing needs to be done here because we're leaving the item in the pNext chain and because the spec states 5379 // that the physicalDevice argument must be included in the device group, and we've already checked that it is 5380 5381 pNext = group_info->pNext; 5382 break; 5383 } 5384 5385 // Multiview properties are also allowed, but since VK_KHX_multiview is a device extension, we'll just let the ICD 5386 // handle that error when the user enables the extension here 5387 default: { 5388 const struct VkStructureHeader *header = pNext; 5389 pNext = header->pNext; 5390 break; 5391 } 5392 } 5393 } 5394 } 5395 5396 res = fpCreateDevice(phys_dev_term->phys_dev, &localCreateInfo, pAllocator, &dev->icd_device); 5397 if (res != VK_SUCCESS) { 5398 loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 5399 "terminator_CreateDevice: Failed in ICD %s vkCreateDevice" 5400 "call", 5401 icd_term->scanned_icd->lib_name); 5402 goto out; 5403 } 5404 5405 *pDevice = dev->icd_device; 5406 loader_add_logical_device(icd_term->this_instance, icd_term, dev); 5407 5408 // Init dispatch pointer in new device object 5409 loader_init_dispatch(*pDevice, &dev->loader_dispatch); 5410 5411 out: 5412 if (NULL != icd_exts.list) { 5413 loader_destroy_generic_list(icd_term->this_instance, (struct loader_generic_list *)&icd_exts); 5414 } 5415 5416 // Restore pNext pointer to old VkDeviceGroupDeviceCreateInfoKHX 5417 // in the chain to maintain consistency for the caller. 5418 if (caller_dgci_container != NULL) { 5419 caller_dgci_container->pNext = caller_dgci; 5420 } 5421 5422 return res; 5423 } 5424 5425 VkResult setupLoaderTrampPhysDevs(VkInstance instance) { 5426 VkResult res = VK_SUCCESS; 5427 VkPhysicalDevice *local_phys_devs = NULL; 5428 struct loader_instance *inst; 5429 uint32_t total_count = 0; 5430 struct loader_physical_device_tramp **new_phys_devs = NULL; 5431 5432 inst = loader_get_instance(instance); 5433 if (NULL == inst) { 5434 res = VK_ERROR_INITIALIZATION_FAILED; 5435 goto out; 5436 } 5437 5438 // Query how many GPUs there 5439 res = inst->disp->layer_inst_disp.EnumeratePhysicalDevices(instance, &total_count, NULL); 5440 if (res != VK_SUCCESS) { 5441 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 5442 "setupLoaderTrampPhysDevs: Failed during dispatch call " 5443 "of \'vkEnumeratePhysicalDevices\' to lower layers or " 5444 "loader to get count."); 5445 goto out; 5446 } 5447 5448 // Really use what the total GPU count is since Optimus and other layers may mess 5449 // the count up. 5450 total_count = inst->total_gpu_count; 5451 5452 // Create an array for the new physical devices, which will be stored 5453 // in the instance for the trampoline code. 5454 new_phys_devs = (struct loader_physical_device_tramp **)loader_instance_heap_alloc( 5455 inst, total_count * sizeof(struct loader_physical_device_tramp *), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 5456 if (NULL == new_phys_devs) { 5457 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 5458 "setupLoaderTrampPhysDevs: Failed to allocate new physical device" 5459 " array of size %d", 5460 total_count); 5461 res = VK_ERROR_OUT_OF_HOST_MEMORY; 5462 goto out; 5463 } 5464 memset(new_phys_devs, 0, total_count * sizeof(struct loader_physical_device_tramp *)); 5465 5466 // Create a temporary array (on the stack) to keep track of the 5467 // returned VkPhysicalDevice values. 5468 local_phys_devs = loader_stack_alloc(sizeof(VkPhysicalDevice) * total_count); 5469 if (NULL == local_phys_devs) { 5470 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 5471 "setupLoaderTrampPhysDevs: Failed to allocate local " 5472 "physical device array of size %d", 5473 total_count); 5474 res = VK_ERROR_OUT_OF_HOST_MEMORY; 5475 goto out; 5476 } 5477 memset(local_phys_devs, 0, sizeof(VkPhysicalDevice) * total_count); 5478 5479 res = inst->disp->layer_inst_disp.EnumeratePhysicalDevices(instance, &total_count, local_phys_devs); 5480 if (VK_SUCCESS != res) { 5481 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 5482 "setupLoaderTrampPhysDevs: Failed during dispatch call " 5483 "of \'vkEnumeratePhysicalDevices\' to lower layers or " 5484 "loader to get content."); 5485 goto out; 5486 } 5487 5488 // Copy or create everything to fill the new array of physical devices 5489 for (uint32_t new_idx = 0; new_idx < total_count; new_idx++) { 5490 // Check if this physical device is already in the old buffer 5491 for (uint32_t old_idx = 0; old_idx < inst->phys_dev_count_tramp; old_idx++) { 5492 if (local_phys_devs[new_idx] == inst->phys_devs_tramp[old_idx]->phys_dev) { 5493 new_phys_devs[new_idx] = inst->phys_devs_tramp[old_idx]; 5494 break; 5495 } 5496 } 5497 5498 // If this physical device isn't in the old buffer, create it 5499 if (NULL == new_phys_devs[new_idx]) { 5500 new_phys_devs[new_idx] = (struct loader_physical_device_tramp *)loader_instance_heap_alloc( 5501 inst, sizeof(struct loader_physical_device_tramp), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 5502 if (NULL == new_phys_devs[new_idx]) { 5503 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 5504 "setupLoaderTrampPhysDevs: Failed to allocate " 5505 "physical device trampoline object %d", 5506 new_idx); 5507 total_count = new_idx; 5508 res = VK_ERROR_OUT_OF_HOST_MEMORY; 5509 goto out; 5510 } 5511 5512 // Initialize the new physicalDevice object 5513 loader_set_dispatch((void *)new_phys_devs[new_idx], inst->disp); 5514 new_phys_devs[new_idx]->this_instance = inst; 5515 new_phys_devs[new_idx]->phys_dev = local_phys_devs[new_idx]; 5516 } 5517 } 5518 5519 out: 5520 5521 if (VK_SUCCESS != res) { 5522 if (NULL != new_phys_devs) { 5523 for (uint32_t i = 0; i < total_count; i++) { 5524 loader_instance_heap_free(inst, new_phys_devs[i]); 5525 } 5526 loader_instance_heap_free(inst, new_phys_devs); 5527 } 5528 total_count = 0; 5529 } else { 5530 // Free everything that didn't carry over to the new array of 5531 // physical devices 5532 if (NULL != inst->phys_devs_tramp) { 5533 for (uint32_t i = 0; i < inst->phys_dev_count_tramp; i++) { 5534 bool found = false; 5535 for (uint32_t j = 0; j < total_count; j++) { 5536 if (inst->phys_devs_tramp[i] == new_phys_devs[j]) { 5537 found = true; 5538 break; 5539 } 5540 } 5541 if (!found) { 5542 loader_instance_heap_free(inst, inst->phys_devs_tramp[i]); 5543 } 5544 } 5545 loader_instance_heap_free(inst, inst->phys_devs_tramp); 5546 } 5547 5548 // Swap in the new physical device list 5549 inst->phys_dev_count_tramp = total_count; 5550 inst->phys_devs_tramp = new_phys_devs; 5551 } 5552 5553 return res; 5554 } 5555 5556 VkResult setupLoaderTermPhysDevs(struct loader_instance *inst) { 5557 VkResult res = VK_SUCCESS; 5558 struct loader_icd_term *icd_term; 5559 struct loader_phys_dev_per_icd *icd_phys_dev_array = NULL; 5560 struct loader_physical_device_term **new_phys_devs = NULL; 5561 5562 inst->total_gpu_count = 0; 5563 5564 // Allocate something to store the physical device characteristics 5565 // that we read from each ICD. 5566 icd_phys_dev_array = 5567 (struct loader_phys_dev_per_icd *)loader_stack_alloc(sizeof(struct loader_phys_dev_per_icd) * inst->total_icd_count); 5568 if (NULL == icd_phys_dev_array) { 5569 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 5570 "setupLoaderTermPhysDevs: Failed to allocate temporary " 5571 "ICD Physical device info array of size %d", 5572 inst->total_gpu_count); 5573 res = VK_ERROR_OUT_OF_HOST_MEMORY; 5574 goto out; 5575 } 5576 memset(icd_phys_dev_array, 0, sizeof(struct loader_phys_dev_per_icd) * inst->total_icd_count); 5577 icd_term = inst->icd_terms; 5578 5579 // For each ICD, query the number of physical devices, and then get an 5580 // internal value for those physical devices. 5581 for (uint32_t icd_idx = 0; NULL != icd_term; icd_term = icd_term->next, icd_idx++) { 5582 res = icd_term->dispatch.EnumeratePhysicalDevices(icd_term->instance, &icd_phys_dev_array[icd_idx].count, NULL); 5583 if (VK_SUCCESS != res) { 5584 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 5585 "setupLoaderTermPhysDevs: Call to " 5586 "ICD %d's \'vkEnumeratePhysicalDevices\' failed with" 5587 " error 0x%08x", 5588 icd_idx, res); 5589 goto out; 5590 } 5591 5592 icd_phys_dev_array[icd_idx].phys_devs = 5593 (VkPhysicalDevice *)loader_stack_alloc(icd_phys_dev_array[icd_idx].count * sizeof(VkPhysicalDevice)); 5594 if (NULL == icd_phys_dev_array[icd_idx].phys_devs) { 5595 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 5596 "setupLoaderTermPhysDevs: Failed to allocate temporary " 5597 "ICD Physical device array for ICD %d of size %d", 5598 icd_idx, inst->total_gpu_count); 5599 res = VK_ERROR_OUT_OF_HOST_MEMORY; 5600 goto out; 5601 } 5602 5603 res = icd_term->dispatch.EnumeratePhysicalDevices(icd_term->instance, &(icd_phys_dev_array[icd_idx].count), 5604 icd_phys_dev_array[icd_idx].phys_devs); 5605 if (VK_SUCCESS != res) { 5606 goto out; 5607 } 5608 inst->total_gpu_count += icd_phys_dev_array[icd_idx].count; 5609 icd_phys_dev_array[icd_idx].this_icd_term = icd_term; 5610 } 5611 5612 if (0 == inst->total_gpu_count) { 5613 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 5614 "setupLoaderTermPhysDevs: Failed to detect any valid" 5615 " GPUs in the current config"); 5616 res = VK_ERROR_INITIALIZATION_FAILED; 5617 goto out; 5618 } 5619 5620 new_phys_devs = loader_instance_heap_alloc(inst, sizeof(struct loader_physical_device_term *) * inst->total_gpu_count, 5621 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 5622 if (NULL == new_phys_devs) { 5623 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 5624 "setupLoaderTermPhysDevs: Failed to allocate new physical" 5625 " device array of size %d", 5626 inst->total_gpu_count); 5627 res = VK_ERROR_OUT_OF_HOST_MEMORY; 5628 goto out; 5629 } 5630 memset(new_phys_devs, 0, sizeof(struct loader_physical_device_term *) * inst->total_gpu_count); 5631 5632 // Copy or create everything to fill the new array of physical devices 5633 uint32_t idx = 0; 5634 for (uint32_t icd_idx = 0; icd_idx < inst->total_icd_count; icd_idx++) { 5635 for (uint32_t pd_idx = 0; pd_idx < icd_phys_dev_array[icd_idx].count; pd_idx++) { 5636 // Check if this physical device is already in the old buffer 5637 if (NULL != inst->phys_devs_term) { 5638 for (uint32_t old_idx = 0; old_idx < inst->phys_dev_count_term; old_idx++) { 5639 if (icd_phys_dev_array[icd_idx].phys_devs[pd_idx] == inst->phys_devs_term[old_idx]->phys_dev) { 5640 new_phys_devs[idx] = inst->phys_devs_term[old_idx]; 5641 break; 5642 } 5643 } 5644 } 5645 // If this physical device isn't in the old buffer, then we 5646 // need to create it. 5647 if (NULL == new_phys_devs[idx]) { 5648 new_phys_devs[idx] = loader_instance_heap_alloc(inst, sizeof(struct loader_physical_device_term), 5649 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 5650 if (NULL == new_phys_devs[idx]) { 5651 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 5652 "setupLoaderTermPhysDevs: Failed to allocate " 5653 "physical device terminator object %d", 5654 idx); 5655 inst->total_gpu_count = idx; 5656 res = VK_ERROR_OUT_OF_HOST_MEMORY; 5657 goto out; 5658 } 5659 5660 loader_set_dispatch((void *)new_phys_devs[idx], inst->disp); 5661 new_phys_devs[idx]->this_icd_term = icd_phys_dev_array[icd_idx].this_icd_term; 5662 new_phys_devs[idx]->icd_index = (uint8_t)(icd_idx); 5663 new_phys_devs[idx]->phys_dev = icd_phys_dev_array[icd_idx].phys_devs[pd_idx]; 5664 } 5665 idx++; 5666 } 5667 } 5668 5669 out: 5670 5671 if (VK_SUCCESS != res) { 5672 if (NULL != new_phys_devs) { 5673 // We've encountered an error, so we should free the new buffers. 5674 for (uint32_t i = 0; i < inst->total_gpu_count; i++) { 5675 loader_instance_heap_free(inst, new_phys_devs[i]); 5676 } 5677 loader_instance_heap_free(inst, new_phys_devs); 5678 } 5679 inst->total_gpu_count = 0; 5680 } else { 5681 // Free everything that didn't carry over to the new array of 5682 // physical devices. Everything else will have been copied over 5683 // to the new array. 5684 if (NULL != inst->phys_devs_term) { 5685 for (uint32_t cur_pd = 0; cur_pd < inst->phys_dev_count_term; cur_pd++) { 5686 bool found = false; 5687 for (uint32_t new_pd_idx = 0; new_pd_idx < inst->total_gpu_count; new_pd_idx++) { 5688 if (inst->phys_devs_term[cur_pd] == new_phys_devs[new_pd_idx]) { 5689 found = true; 5690 break; 5691 } 5692 } 5693 if (!found) { 5694 loader_instance_heap_free(inst, inst->phys_devs_term[cur_pd]); 5695 } 5696 } 5697 loader_instance_heap_free(inst, inst->phys_devs_term); 5698 } 5699 5700 // Swap out old and new devices list 5701 inst->phys_dev_count_term = inst->total_gpu_count; 5702 inst->phys_devs_term = new_phys_devs; 5703 } 5704 5705 return res; 5706 } 5707 5708 VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount, 5709 VkPhysicalDevice *pPhysicalDevices) { 5710 struct loader_instance *inst = (struct loader_instance *)instance; 5711 VkResult res = VK_SUCCESS; 5712 5713 // Always call the setup loader terminator physical devices because they may 5714 // have changed at any point. 5715 res = setupLoaderTermPhysDevs(inst); 5716 if (VK_SUCCESS != res) { 5717 goto out; 5718 } 5719 5720 uint32_t copy_count = inst->total_gpu_count; 5721 if (NULL != pPhysicalDevices) { 5722 if (copy_count > *pPhysicalDeviceCount) { 5723 copy_count = *pPhysicalDeviceCount; 5724 res = VK_INCOMPLETE; 5725 } 5726 5727 for (uint32_t i = 0; i < copy_count; i++) { 5728 pPhysicalDevices[i] = (VkPhysicalDevice)inst->phys_devs_term[i]; 5729 } 5730 } 5731 5732 *pPhysicalDeviceCount = copy_count; 5733 5734 out: 5735 5736 return res; 5737 } 5738 5739 VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, 5740 VkPhysicalDeviceProperties *pProperties) { 5741 struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice; 5742 struct loader_icd_term *icd_term = phys_dev_term->this_icd_term; 5743 if (NULL != icd_term->dispatch.GetPhysicalDeviceProperties) { 5744 icd_term->dispatch.GetPhysicalDeviceProperties(phys_dev_term->phys_dev, pProperties); 5745 } 5746 } 5747 5748 VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice, 5749 uint32_t *pQueueFamilyPropertyCount, 5750 VkQueueFamilyProperties *pProperties) { 5751 struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice; 5752 struct loader_icd_term *icd_term = phys_dev_term->this_icd_term; 5753 if (NULL != icd_term->dispatch.GetPhysicalDeviceQueueFamilyProperties) { 5754 icd_term->dispatch.GetPhysicalDeviceQueueFamilyProperties(phys_dev_term->phys_dev, pQueueFamilyPropertyCount, pProperties); 5755 } 5756 } 5757 5758 VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice, 5759 VkPhysicalDeviceMemoryProperties *pProperties) { 5760 struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice; 5761 struct loader_icd_term *icd_term = phys_dev_term->this_icd_term; 5762 if (NULL != icd_term->dispatch.GetPhysicalDeviceMemoryProperties) { 5763 icd_term->dispatch.GetPhysicalDeviceMemoryProperties(phys_dev_term->phys_dev, pProperties); 5764 } 5765 } 5766 5767 VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice, 5768 VkPhysicalDeviceFeatures *pFeatures) { 5769 struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice; 5770 struct loader_icd_term *icd_term = phys_dev_term->this_icd_term; 5771 if (NULL != icd_term->dispatch.GetPhysicalDeviceFeatures) { 5772 icd_term->dispatch.GetPhysicalDeviceFeatures(phys_dev_term->phys_dev, pFeatures); 5773 } 5774 } 5775 5776 VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, 5777 VkFormatProperties *pFormatInfo) { 5778 struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice; 5779 struct loader_icd_term *icd_term = phys_dev_term->this_icd_term; 5780 if (NULL != icd_term->dispatch.GetPhysicalDeviceFormatProperties) { 5781 icd_term->dispatch.GetPhysicalDeviceFormatProperties(phys_dev_term->phys_dev, format, pFormatInfo); 5782 } 5783 } 5784 5785 VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, 5786 VkImageType type, VkImageTiling tiling, 5787 VkImageUsageFlags usage, VkImageCreateFlags flags, 5788 VkImageFormatProperties *pImageFormatProperties) { 5789 struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice; 5790 struct loader_icd_term *icd_term = phys_dev_term->this_icd_term; 5791 if (NULL == icd_term->dispatch.GetPhysicalDeviceImageFormatProperties) { 5792 loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 5793 "Encountered the vkEnumerateDeviceLayerProperties " 5794 "terminator. This means a layer improperly continued."); 5795 return VK_ERROR_INITIALIZATION_FAILED; 5796 } 5797 return icd_term->dispatch.GetPhysicalDeviceImageFormatProperties(phys_dev_term->phys_dev, format, type, tiling, usage, flags, 5798 pImageFormatProperties); 5799 } 5800 5801 VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, 5802 VkImageType type, VkSampleCountFlagBits samples, 5803 VkImageUsageFlags usage, VkImageTiling tiling, 5804 uint32_t *pNumProperties, 5805 VkSparseImageFormatProperties *pProperties) { 5806 struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice; 5807 struct loader_icd_term *icd_term = phys_dev_term->this_icd_term; 5808 if (NULL != icd_term->dispatch.GetPhysicalDeviceSparseImageFormatProperties) { 5809 icd_term->dispatch.GetPhysicalDeviceSparseImageFormatProperties(phys_dev_term->phys_dev, format, type, samples, usage, 5810 tiling, pNumProperties, pProperties); 5811 } 5812 } 5813 5814 VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, 5815 const char *pLayerName, uint32_t *pPropertyCount, 5816 VkExtensionProperties *pProperties) { 5817 struct loader_physical_device_term *phys_dev_term; 5818 5819 struct loader_layer_list implicit_layer_list = {0}; 5820 struct loader_extension_list all_exts = {0}; 5821 struct loader_extension_list icd_exts = {0}; 5822 5823 assert(pLayerName == NULL || strlen(pLayerName) == 0); 5824 5825 // Any layer or trampoline wrapping should be removed at this point in time can just cast to the expected 5826 // type for VkPhysicalDevice. 5827 phys_dev_term = (struct loader_physical_device_term *)physicalDevice; 5828 5829 // This case is during the call down the instance chain with pLayerName == NULL 5830 struct loader_icd_term *icd_term = phys_dev_term->this_icd_term; 5831 uint32_t icd_ext_count = *pPropertyCount; 5832 VkResult res; 5833 5834 // Get the available device extensions 5835 res = icd_term->dispatch.EnumerateDeviceExtensionProperties(phys_dev_term->phys_dev, NULL, &icd_ext_count, pProperties); 5836 if (res != VK_SUCCESS) { 5837 goto out; 5838 } 5839 5840 if (!loader_init_layer_list(icd_term->this_instance, &implicit_layer_list)) { 5841 res = VK_ERROR_OUT_OF_HOST_MEMORY; 5842 goto out; 5843 } 5844 5845 loader_add_implicit_layers(icd_term->this_instance, &implicit_layer_list, NULL, &icd_term->this_instance->instance_layer_list); 5846 // We need to determine which implicit layers are active, and then add their extensions. This can't be cached as 5847 // it depends on results of environment variables (which can change). 5848 if (pProperties != NULL) { 5849 // Initialize dev_extension list within the physicalDevice object 5850 res = loader_init_device_extensions(icd_term->this_instance, phys_dev_term, icd_ext_count, pProperties, &icd_exts); 5851 if (res != VK_SUCCESS) { 5852 goto out; 5853 } 5854 5855 // We need to determine which implicit layers are active, and then add their extensions. This can't be cached as 5856 // it depends on results of environment variables (which can change). 5857 res = loader_add_to_ext_list(icd_term->this_instance, &all_exts, icd_exts.count, icd_exts.list); 5858 if (res != VK_SUCCESS) { 5859 goto out; 5860 } 5861 5862 loader_add_implicit_layers(icd_term->this_instance, &implicit_layer_list, NULL, 5863 &icd_term->this_instance->instance_layer_list); 5864 5865 for (uint32_t i = 0; i < implicit_layer_list.count; i++) { 5866 for (uint32_t j = 0; j < implicit_layer_list.list[i].device_extension_list.count; j++) { 5867 res = loader_add_to_ext_list(icd_term->this_instance, &all_exts, 1, 5868 &implicit_layer_list.list[i].device_extension_list.list[j].props); 5869 if (res != VK_SUCCESS) { 5870 goto out; 5871 } 5872 } 5873 } 5874 uint32_t capacity = *pPropertyCount; 5875 VkExtensionProperties *props = pProperties; 5876 5877 for (uint32_t i = 0; i < all_exts.count && i < capacity; i++) { 5878 props[i] = all_exts.list[i]; 5879 } 5880 5881 // Wasn't enough space for the extensions, we did partial copy now return VK_INCOMPLETE 5882 if (capacity < all_exts.count) { 5883 res = VK_INCOMPLETE; 5884 } else { 5885 *pPropertyCount = all_exts.count; 5886 } 5887 } else { 5888 // Just return the count; need to add in the count of implicit layer extensions 5889 // don't worry about duplicates being added in the count 5890 *pPropertyCount = icd_ext_count; 5891 5892 for (uint32_t i = 0; i < implicit_layer_list.count; i++) { 5893 *pPropertyCount += implicit_layer_list.list[i].device_extension_list.count; 5894 } 5895 res = VK_SUCCESS; 5896 } 5897 5898 out: 5899 5900 if (NULL != implicit_layer_list.list) { 5901 loader_destroy_generic_list(icd_term->this_instance, (struct loader_generic_list *)&implicit_layer_list); 5902 } 5903 if (NULL != all_exts.list) { 5904 loader_destroy_generic_list(icd_term->this_instance, (struct loader_generic_list *)&all_exts); 5905 } 5906 if (NULL != icd_exts.list) { 5907 loader_destroy_generic_list(icd_term->this_instance, (struct loader_generic_list *)&icd_exts); 5908 } 5909 5910 return res; 5911 } 5912 5913 VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pPropertyCount, 5914 VkLayerProperties *pProperties) { 5915 struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice; 5916 struct loader_icd_term *icd_term = phys_dev_term->this_icd_term; 5917 loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 5918 "Encountered the vkEnumerateDeviceLayerProperties " 5919 "terminator. This means a layer improperly continued."); 5920 // Should never get here this call isn't dispatched down the chain 5921 return VK_ERROR_INITIALIZATION_FAILED; 5922 } 5923 5924 VkStringErrorFlags vk_string_validate(const int max_length, const char *utf8) { 5925 VkStringErrorFlags result = VK_STRING_ERROR_NONE; 5926 int num_char_bytes = 0; 5927 int i, j; 5928 5929 for (i = 0; i <= max_length; i++) { 5930 if (utf8[i] == 0) { 5931 break; 5932 } else if (i == max_length) { 5933 result |= VK_STRING_ERROR_LENGTH; 5934 break; 5935 } else if ((utf8[i] >= 0x20) && (utf8[i] < 0x7f)) { 5936 num_char_bytes = 0; 5937 } else if ((utf8[i] & UTF8_ONE_BYTE_MASK) == UTF8_ONE_BYTE_CODE) { 5938 num_char_bytes = 1; 5939 } else if ((utf8[i] & UTF8_TWO_BYTE_MASK) == UTF8_TWO_BYTE_CODE) { 5940 num_char_bytes = 2; 5941 } else if ((utf8[i] & UTF8_THREE_BYTE_MASK) == UTF8_THREE_BYTE_CODE) { 5942 num_char_bytes = 3; 5943 } else { 5944 result = VK_STRING_ERROR_BAD_DATA; 5945 } 5946 5947 // Validate the following num_char_bytes of data 5948 for (j = 0; (j < num_char_bytes) && (i < max_length); j++) { 5949 if (++i == max_length) { 5950 result |= VK_STRING_ERROR_LENGTH; 5951 break; 5952 } 5953 if ((utf8[i] & UTF8_DATA_BYTE_MASK) != UTF8_DATA_BYTE_CODE) { 5954 result |= VK_STRING_ERROR_BAD_DATA; 5955 } 5956 } 5957 } 5958 return result; 5959 } 5960 5961 VKAPI_ATTR VkResult VKAPI_CALL 5962 terminator_EnumerateInstanceExtensionProperties(const VkEnumerateInstanceExtensionPropertiesChain *chain, const char *pLayerName, 5963 uint32_t *pPropertyCount, VkExtensionProperties *pProperties) { 5964 struct loader_extension_list *global_ext_list = NULL; 5965 struct loader_layer_list instance_layers; 5966 struct loader_extension_list local_ext_list; 5967 struct loader_icd_tramp_list icd_tramp_list; 5968 uint32_t copy_size; 5969 VkResult res = VK_SUCCESS; 5970 5971 // tls_instance = NULL; 5972 memset(&local_ext_list, 0, sizeof(local_ext_list)); 5973 memset(&instance_layers, 0, sizeof(instance_layers)); 5974 5975 // Get layer libraries if needed 5976 if (pLayerName && strlen(pLayerName) != 0) { 5977 if (vk_string_validate(MaxLoaderStringLength, pLayerName) != VK_STRING_ERROR_NONE) { 5978 assert(VK_FALSE && 5979 "vkEnumerateInstanceExtensionProperties: " 5980 "pLayerName is too long or is badly formed"); 5981 res = VK_ERROR_EXTENSION_NOT_PRESENT; 5982 goto out; 5983 } 5984 5985 loader_layer_scan(NULL, &instance_layers); 5986 for (uint32_t i = 0; i < instance_layers.count; i++) { 5987 struct loader_layer_properties *props = &instance_layers.list[i]; 5988 if (strcmp(props->info.layerName, pLayerName) == 0) { 5989 global_ext_list = &props->instance_extension_list; 5990 break; 5991 } 5992 } 5993 } else { 5994 // Scan/discover all ICD libraries 5995 memset(&icd_tramp_list, 0, sizeof(icd_tramp_list)); 5996 res = loader_icd_scan(NULL, &icd_tramp_list); 5997 if (VK_SUCCESS != res) { 5998 goto out; 5999 } 6000 // Get extensions from all ICD's, merge so no duplicates 6001 res = loader_get_icd_loader_instance_extensions(NULL, &icd_tramp_list, &local_ext_list); 6002 if (VK_SUCCESS != res) { 6003 goto out; 6004 } 6005 loader_scanned_icd_clear(NULL, &icd_tramp_list); 6006 6007 // Append enabled implicit layers. 6008 loader_implicit_layer_scan(NULL, &instance_layers); 6009 for (uint32_t i = 0; i < instance_layers.count; i++) { 6010 if (!loader_is_implicit_layer_enabled(NULL, &instance_layers.list[i])) { 6011 continue; 6012 } 6013 struct loader_extension_list *ext_list = &instance_layers.list[i].instance_extension_list; 6014 loader_add_to_ext_list(NULL, &local_ext_list, ext_list->count, ext_list->list); 6015 } 6016 6017 global_ext_list = &local_ext_list; 6018 } 6019 6020 if (global_ext_list == NULL) { 6021 res = VK_ERROR_LAYER_NOT_PRESENT; 6022 goto out; 6023 } 6024 6025 if (pProperties == NULL) { 6026 *pPropertyCount = global_ext_list->count; 6027 goto out; 6028 } 6029 6030 copy_size = *pPropertyCount < global_ext_list->count ? *pPropertyCount : global_ext_list->count; 6031 for (uint32_t i = 0; i < copy_size; i++) { 6032 memcpy(&pProperties[i], &global_ext_list->list[i], sizeof(VkExtensionProperties)); 6033 } 6034 *pPropertyCount = copy_size; 6035 6036 if (copy_size < global_ext_list->count) { 6037 res = VK_INCOMPLETE; 6038 goto out; 6039 } 6040 6041 out: 6042 6043 loader_destroy_generic_list(NULL, (struct loader_generic_list *)&local_ext_list); 6044 loader_delete_layer_properties(NULL, &instance_layers); 6045 return res; 6046 } 6047 6048 VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateInstanceLayerProperties(const VkEnumerateInstanceLayerPropertiesChain *chain, 6049 uint32_t *pPropertyCount, 6050 VkLayerProperties *pProperties) { 6051 VkResult result = VK_SUCCESS; 6052 struct loader_layer_list instance_layer_list; 6053 tls_instance = NULL; 6054 6055 LOADER_PLATFORM_THREAD_ONCE(&once_init, loader_initialize); 6056 6057 uint32_t copy_size; 6058 6059 // Get layer libraries 6060 memset(&instance_layer_list, 0, sizeof(instance_layer_list)); 6061 loader_layer_scan(NULL, &instance_layer_list); 6062 6063 if (pProperties == NULL) { 6064 *pPropertyCount = instance_layer_list.count; 6065 goto out; 6066 } 6067 6068 copy_size = (*pPropertyCount < instance_layer_list.count) ? *pPropertyCount : instance_layer_list.count; 6069 for (uint32_t i = 0; i < copy_size; i++) { 6070 memcpy(&pProperties[i], &instance_layer_list.list[i].info, sizeof(VkLayerProperties)); 6071 } 6072 6073 *pPropertyCount = copy_size; 6074 6075 if (copy_size < instance_layer_list.count) { 6076 result = VK_INCOMPLETE; 6077 goto out; 6078 } 6079 6080 out: 6081 6082 loader_delete_layer_properties(NULL, &instance_layer_list); 6083 return result; 6084 } 6085 6086 #if defined(_WIN32) && defined(LOADER_DYNAMIC_LIB) 6087 BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, LPVOID reserved) { 6088 switch (reason) { 6089 case DLL_PROCESS_ATTACH: 6090 loader_initialize(); 6091 break; 6092 case DLL_PROCESS_DETACH: 6093 if (NULL == reserved) { 6094 loader_release(); 6095 } 6096 break; 6097 default: 6098 // Do nothing 6099 break; 6100 } 6101 return TRUE; 6102 } 6103 #elif !defined(_WIN32) 6104 __attribute__((constructor)) void loader_init_library() { loader_initialize(); } 6105 6106 __attribute__((destructor)) void loader_free_library() { loader_release(); } 6107 #endif 6108