loader.c revision 50c57efd215d2bc06616b7707d460c7a1b8b7774
1/* 2 * 3 * Copyright (C) 2014 LunarG, Inc. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included 13 * in all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 * 23 * Authors: 24 * Chia-I Wu <olv@lunarg.com> 25 * Jon Ashburn <jon@lunarg.com> 26 * Courtney Goeltzenleuchter <courtney@lunarg.com> 27 * Ian Elliott <ian@lunarg.com> 28 */ 29#define _GNU_SOURCE 30#include <stdio.h> 31#include <stdlib.h> 32#include <stdarg.h> 33#include <stdbool.h> 34#include <string.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 "table_ops.h" 46#include "debug_report.h" 47#include "vk_icd.h" 48#include "cJSON.h" 49 50static loader_platform_dl_handle loader_add_layer_lib( 51 const struct loader_instance *inst, 52 const char *chain_type, 53 struct loader_layer_properties *layer_prop); 54 55static void loader_remove_layer_lib( 56 struct loader_instance *inst, 57 struct loader_layer_properties *layer_prop); 58 59struct loader_struct loader = {0}; 60// TLS for instance for alloc/free callbacks 61THREAD_LOCAL_DECL struct loader_instance *tls_instance; 62 63static bool loader_init_ext_list( 64 const struct loader_instance *inst, 65 struct loader_extension_list *ext_info); 66 67static int loader_platform_combine_path(char *dest, int len, ...); 68 69struct loader_phys_dev_per_icd { 70 uint32_t count; 71 VkPhysicalDevice *phys_devs; 72}; 73 74enum loader_debug { 75 LOADER_INFO_BIT = 0x01, 76 LOADER_WARN_BIT = 0x02, 77 LOADER_PERF_BIT = 0x04, 78 LOADER_ERROR_BIT = 0x08, 79 LOADER_DEBUG_BIT = 0x10, 80}; 81 82uint32_t g_loader_debug = 0; 83uint32_t g_loader_log_msgs = 0; 84 85//thread safety lock for accessing global data structures such as "loader" 86// all entrypoints on the instance chain need to be locked except GPA 87// additionally CreateDevice and DestroyDevice needs to be locked 88loader_platform_thread_mutex loader_lock; 89loader_platform_thread_mutex loader_json_lock; 90 91// This table contains the loader's instance dispatch table, which contains 92// default functions if no instance layers are activated. This contains 93// pointers to "terminator functions". 94const VkLayerInstanceDispatchTable instance_disp = { 95 .GetInstanceProcAddr = vkGetInstanceProcAddr, 96 .CreateInstance = loader_CreateInstance, 97 .DestroyInstance = loader_DestroyInstance, 98 .EnumeratePhysicalDevices = loader_EnumeratePhysicalDevices, 99 .GetPhysicalDeviceFeatures = loader_GetPhysicalDeviceFeatures, 100 .GetPhysicalDeviceFormatProperties = loader_GetPhysicalDeviceFormatProperties, 101 .GetPhysicalDeviceImageFormatProperties = loader_GetPhysicalDeviceImageFormatProperties, 102 .GetPhysicalDeviceProperties = loader_GetPhysicalDeviceProperties, 103 .GetPhysicalDeviceQueueFamilyProperties = loader_GetPhysicalDeviceQueueFamilyProperties, 104 .GetPhysicalDeviceMemoryProperties = loader_GetPhysicalDeviceMemoryProperties, 105 .EnumerateDeviceExtensionProperties = loader_EnumerateDeviceExtensionProperties, 106 .EnumerateDeviceLayerProperties = loader_EnumerateDeviceLayerProperties, 107 .GetPhysicalDeviceSparseImageFormatProperties = loader_GetPhysicalDeviceSparseImageFormatProperties, 108 .GetPhysicalDeviceSurfaceSupportKHR = loader_GetPhysicalDeviceSurfaceSupportKHR, 109 .DbgCreateMsgCallback = loader_DbgCreateMsgCallback, 110 .DbgDestroyMsgCallback = loader_DbgDestroyMsgCallback, 111}; 112 113LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_init); 114 115void* loader_heap_alloc( 116 const struct loader_instance *instance, 117 size_t size, 118 VkSystemAllocationScope alloc_scope) 119{ 120 if (instance && instance->alloc_callbacks.pfnAllocation) { 121 /* TODO: What should default alignment be? 1, 4, 8, other? */ 122 return instance->alloc_callbacks.pfnAllocation(instance->alloc_callbacks.pUserData, size, 4, alloc_scope); 123 } 124 return malloc(size); 125} 126 127void loader_heap_free( 128 const struct loader_instance *instance, 129 void *pMemory) 130{ 131 if (pMemory == NULL) return; 132 if (instance && instance->alloc_callbacks.pfnFree) { 133 instance->alloc_callbacks.pfnFree(instance->alloc_callbacks.pUserData, pMemory); 134 return; 135 } 136 free(pMemory); 137} 138 139void* loader_heap_realloc( 140 const struct loader_instance *instance, 141 void *pMemory, 142 size_t orig_size, 143 size_t size, 144 VkSystemAllocationScope alloc_scope) 145{ 146 if (pMemory == NULL || orig_size == 0) 147 return loader_heap_alloc(instance, size, alloc_scope); 148 if (size == 0) { 149 loader_heap_free(instance, pMemory); 150 return NULL; 151 } 152 if (instance && instance->alloc_callbacks.pfnAllocation) { 153 if (size <= orig_size) { 154 memset(((uint8_t *)pMemory) + size, 0, orig_size - size); 155 return pMemory; 156 } 157 void *new_ptr = instance->alloc_callbacks.pfnAllocation(instance->alloc_callbacks.pUserData, size, 4, alloc_scope); 158 if (!new_ptr) 159 return NULL; 160 memcpy(new_ptr, pMemory, orig_size); 161 instance->alloc_callbacks.pfnFree(instance->alloc_callbacks.pUserData, pMemory); 162 return new_ptr; 163 } 164 return realloc(pMemory, size); 165} 166 167void *loader_tls_heap_alloc(size_t size) 168{ 169 return loader_heap_alloc(tls_instance, size, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 170} 171 172void loader_tls_heap_free(void *pMemory) 173{ 174 loader_heap_free(tls_instance, pMemory); 175} 176 177static void loader_log(VkFlags msg_type, int32_t msg_code, 178 const char *format, ...) 179{ 180 char msg[512]; 181 va_list ap; 182 int ret; 183 184 if (!(msg_type & g_loader_log_msgs)) { 185 return; 186 } 187 188 va_start(ap, format); 189 ret = vsnprintf(msg, sizeof(msg), format, ap); 190 if ((ret >= (int) sizeof(msg)) || ret < 0) { 191 msg[sizeof(msg)-1] = '\0'; 192 } 193 va_end(ap); 194 195#if defined(WIN32) 196 OutputDebugString(msg); 197 OutputDebugString("\n"); 198#endif 199 fputs(msg, stderr); 200 fputc('\n', stderr); 201} 202 203#if defined(WIN32) 204static char *loader_get_next_path(char *path); 205/** 206* Find the list of registry files (names within a key) in key "location". 207* 208* This function looks in the registry (hive = DEFAULT_VK_REGISTRY_HIVE) key as given in "location" 209* for a list or name/values which are added to a returned list (function return value). 210* The DWORD values within the key must be 0 or they are skipped. 211* Function return is a string with a ';' separated list of filenames. 212* Function return is NULL if no valid name/value pairs are found in the key, 213* or the key is not found. 214* 215* \returns 216* A string list of filenames as pointer. 217* When done using the returned string list, pointer should be freed. 218*/ 219static char *loader_get_registry_files(const struct loader_instance *inst, char *location) 220{ 221 LONG rtn_value; 222 HKEY hive, key; 223 DWORD access_flags = KEY_QUERY_VALUE; 224 char name[2048]; 225 char *out = NULL; 226 char *loc = location; 227 char *next; 228 DWORD idx = 0; 229 DWORD name_size = sizeof(name); 230 DWORD value; 231 DWORD total_size = 4096; 232 DWORD value_size = sizeof(value); 233 234 while(*loc) 235 { 236 next = loader_get_next_path(loc); 237 hive = DEFAULT_VK_REGISTRY_HIVE; 238 rtn_value = RegOpenKeyEx(hive, loc, 0, access_flags, &key); 239 if (rtn_value != ERROR_SUCCESS) { 240 // We didn't find the key. Try the 32-bit hive (where we've seen the 241 // key end up on some people's systems): 242 access_flags |= KEY_WOW64_32KEY; 243 rtn_value = RegOpenKeyEx(hive, loc, 0, access_flags, &key); 244 if (rtn_value != ERROR_SUCCESS) { 245 // We still couldn't find the key, so give up: 246 loc = next; 247 continue; 248 } 249 } 250 251 while ((rtn_value = RegEnumValue(key, idx++, name, &name_size, NULL, NULL, (LPBYTE) &value, &value_size)) == ERROR_SUCCESS) { 252 if (value_size == sizeof(value) && value == 0) { 253 if (out == NULL) { 254 out = loader_heap_alloc(inst, total_size, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 255 out[0] = '\0'; 256 } 257 else if (strlen(out) + name_size + 1 > total_size) { 258 out = loader_heap_realloc(inst, out, total_size, total_size * 2, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 259 total_size *= 2; 260 } 261 if (out == NULL) { 262 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory, failed loader_get_registry_files"); 263 return NULL; 264 } 265 if (strlen(out) == 0) 266 snprintf(out, name_size + 1, "%s", name); 267 else 268 snprintf(out + strlen(out), name_size + 2, "%c%s", PATH_SEPERATOR, name); 269 } 270 name_size = 2048; 271 } 272 loc = next; 273 } 274 275 return out; 276} 277 278#endif // WIN32 279 280/** 281 * Combine path elements, separating each element with the platform-specific 282 * directory separator, and save the combined string to a destination buffer, 283 * not exceeding the given length. Path elements are given as variadic args, 284 * with a NULL element terminating the list. 285 * 286 * \returns the total length of the combined string, not including an ASCII 287 * NUL termination character. This length may exceed the available storage: 288 * in this case, the written string will be truncated to avoid a buffer 289 * overrun, and the return value will greater than or equal to the storage 290 * size. A NULL argument may be provided as the destination buffer in order 291 * to determine the required string length without actually writing a string. 292 */ 293 294static int loader_platform_combine_path(char *dest, int len, ...) 295{ 296 int required_len = 0; 297 va_list ap; 298 const char *component; 299 300 va_start(ap, len); 301 302 while((component = va_arg(ap, const char *))) { 303 if (required_len > 0) { 304 // This path element is not the first non-empty element; prepend 305 // a directory separator if space allows 306 if (dest && required_len + 1 < len) { 307 snprintf(dest + required_len, len - required_len, "%c", 308 DIRECTORY_SYMBOL); 309 } 310 required_len++; 311 } 312 313 if (dest && required_len < len) { 314 strncpy(dest + required_len, component, len - required_len); 315 } 316 required_len += strlen(component); 317 } 318 319 va_end(ap); 320 321 // strncpy(3) won't add a NUL terminating byte in the event of truncation. 322 if (dest && required_len >= len) { 323 dest[len - 1] = '\0'; 324 } 325 326 return required_len; 327} 328 329 330/** 331 * Given string of three part form "maj.min.pat" convert to a vulkan version 332 * number. 333 */ 334static uint32_t loader_make_version(const char *vers_str) 335{ 336 uint32_t vers = 0, major=0, minor=0, patch=0; 337 char *minor_str= NULL; 338 char *patch_str = NULL; 339 char *cstr; 340 char *str; 341 342 if (!vers_str) 343 return vers; 344 cstr = loader_stack_alloc(strlen(vers_str) + 1); 345 strcpy(cstr, vers_str); 346 while ((str = strchr(cstr, '.')) != NULL) { 347 if (minor_str == NULL) { 348 minor_str = str + 1; 349 *str = '\0'; 350 major = atoi(cstr); 351 } 352 else if (patch_str == NULL) { 353 patch_str = str + 1; 354 *str = '\0'; 355 minor = atoi(minor_str); 356 } 357 else { 358 return vers; 359 } 360 cstr = str + 1; 361 } 362 patch = atoi(patch_str); 363 364 return VK_MAKE_VERSION(major, minor, patch); 365 366} 367 368bool compare_vk_extension_properties(const VkExtensionProperties *op1, const VkExtensionProperties *op2) 369{ 370 return strcmp(op1->extensionName, op2->extensionName) == 0 ? true : false; 371} 372 373/** 374 * Search the given ext_array for an extension 375 * matching the given vk_ext_prop 376 */ 377bool has_vk_extension_property_array( 378 const VkExtensionProperties *vk_ext_prop, 379 const uint32_t count, 380 const VkExtensionProperties *ext_array) 381{ 382 for (uint32_t i = 0; i < count; i++) { 383 if (compare_vk_extension_properties(vk_ext_prop, &ext_array[i])) 384 return true; 385 } 386 return false; 387} 388 389/** 390 * Search the given ext_list for an extension 391 * matching the given vk_ext_prop 392 */ 393bool has_vk_extension_property( 394 const VkExtensionProperties *vk_ext_prop, 395 const struct loader_extension_list *ext_list) 396{ 397 for (uint32_t i = 0; i < ext_list->count; i++) { 398 if (compare_vk_extension_properties(&ext_list->list[i], vk_ext_prop)) 399 return true; 400 } 401 return false; 402} 403 404static inline bool loader_is_layer_type_device(const enum layer_type type) { 405 if ((type & VK_LAYER_TYPE_DEVICE_EXPLICIT) || 406 (type & VK_LAYER_TYPE_DEVICE_IMPLICIT)) 407 return true; 408 return false; 409} 410 411/* 412 * Search the given layer list for a layer matching the given layer name 413 */ 414static struct loader_layer_properties *loader_get_layer_property( 415 const char *name, 416 const struct loader_layer_list *layer_list) 417{ 418 for (uint32_t i = 0; i < layer_list->count; i++) { 419 const VkLayerProperties *item = &layer_list->list[i].info; 420 if (strcmp(name, item->layerName) == 0) 421 return &layer_list->list[i]; 422 } 423 return NULL; 424} 425 426/** 427 * Get the next unused layer property in the list. Init the property to zero. 428 */ 429static struct loader_layer_properties *loader_get_next_layer_property( 430 const struct loader_instance *inst, 431 struct loader_layer_list *layer_list) 432{ 433 if (layer_list->capacity == 0) { 434 layer_list->list = loader_heap_alloc(inst, 435 sizeof(struct loader_layer_properties) * 64, 436 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 437 if (layer_list->list == NULL) { 438 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't add any layer properties to list"); 439 return NULL; 440 } 441 memset(layer_list->list, 0, sizeof(struct loader_layer_properties) * 64); 442 layer_list->capacity = sizeof(struct loader_layer_properties) * 64; 443 } 444 445 // ensure enough room to add an entry 446 if ((layer_list->count + 1) * sizeof (struct loader_layer_properties) 447 > layer_list->capacity) { 448 layer_list->list = loader_heap_realloc(inst, layer_list->list, 449 layer_list->capacity, 450 layer_list->capacity * 2, 451 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 452 if (layer_list->list == NULL) { 453 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, 454 "realloc failed for layer list"); 455 } 456 layer_list->capacity *= 2; 457 } 458 459 layer_list->count++; 460 return &(layer_list->list[layer_list->count - 1]); 461} 462 463/** 464 * Remove all layer properties entrys from the list 465 */ 466void loader_delete_layer_properties( 467 const struct loader_instance *inst, 468 struct loader_layer_list *layer_list) 469{ 470 uint32_t i; 471 472 if (!layer_list) 473 return; 474 475 for (i = 0; i < layer_list->count; i++) { 476 loader_destroy_ext_list(inst, &layer_list->list[i].instance_extension_list); 477 loader_destroy_ext_list(inst, &layer_list->list[i].device_extension_list); 478 } 479 layer_list->count = 0; 480 481 if (layer_list->capacity > 0) { 482 layer_list->capacity = 0; 483 loader_heap_free(inst, layer_list->list); 484 } 485 486} 487 488static void loader_add_global_extensions( 489 const struct loader_instance *inst, 490 const PFN_vkEnumerateInstanceExtensionProperties fp_get_props, 491 const char *lib_name, 492 struct loader_extension_list *ext_list) 493{ 494 uint32_t i, count; 495 VkExtensionProperties *ext_props; 496 VkResult res; 497 498 if (!fp_get_props) { 499 /* No EnumerateInstanceExtensionProperties defined */ 500 return; 501 } 502 503 res = fp_get_props(NULL, &count, NULL); 504 if (res != VK_SUCCESS) { 505 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Error getting global extension count from %s", lib_name); 506 return; 507 } 508 509 if (count == 0) { 510 /* No ExtensionProperties to report */ 511 return; 512 } 513 514 ext_props = loader_stack_alloc(count * sizeof(VkExtensionProperties)); 515 516 res = fp_get_props(NULL, &count, ext_props); 517 if (res != VK_SUCCESS) { 518 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Error getting global extensions from %s", lib_name); 519 return; 520 } 521 522 for (i = 0; i < count; i++) { 523 char spec_version[64]; 524 525 snprintf(spec_version, sizeof(spec_version), "%d.%d.%d", 526 VK_MAJOR(ext_props[i].specVersion), 527 VK_MINOR(ext_props[i].specVersion), 528 VK_PATCH(ext_props[i].specVersion)); 529 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, 530 "Global Extension: %s (%s) version %s", 531 ext_props[i].extensionName, lib_name, spec_version); 532 loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]); 533 } 534 535 return; 536} 537 538/* 539 * Initialize ext_list with the physical device extensions. 540 * The extension properties are passed as inputs in count and ext_props. 541 */ 542static VkResult loader_init_physical_device_extensions( 543 const struct loader_instance *inst, 544 struct loader_physical_device *phys_dev, 545 uint32_t count, 546 VkExtensionProperties *ext_props, 547 struct loader_extension_list *ext_list) 548{ 549 VkResult res; 550 uint32_t i; 551 552 if (!loader_init_ext_list(inst, ext_list)) { 553 return VK_ERROR_OUT_OF_HOST_MEMORY; 554 } 555 556 for (i = 0; i < count; i++) { 557 char spec_version[64]; 558 559 snprintf(spec_version, sizeof (spec_version), "%d.%d.%d", 560 VK_MAJOR(ext_props[i].specVersion), 561 VK_MINOR(ext_props[i].specVersion), 562 VK_PATCH(ext_props[i].specVersion)); 563 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, 564 "PhysicalDevice Extension: %s (%s) version %s", 565 ext_props[i].extensionName, phys_dev->this_icd->this_icd_lib->lib_name, spec_version); 566 res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]); 567 if (res != VK_SUCCESS) 568 return res; 569 } 570 571 return VK_SUCCESS; 572} 573 574static VkResult loader_add_physical_device_extensions( 575 const struct loader_instance *inst, 576 VkPhysicalDevice physical_device, 577 const char *lib_name, 578 struct loader_extension_list *ext_list) 579{ 580 uint32_t i, count; 581 VkResult res; 582 VkExtensionProperties *ext_props; 583 584 res = loader_EnumerateDeviceExtensionProperties(physical_device, NULL, &count, NULL); 585 if (res == VK_SUCCESS && count > 0) { 586 ext_props = loader_stack_alloc(count * sizeof (VkExtensionProperties)); 587 if (!ext_props) 588 return VK_ERROR_OUT_OF_HOST_MEMORY; 589 res = loader_EnumerateDeviceExtensionProperties(physical_device, NULL, &count, ext_props); 590 if (res != VK_SUCCESS) 591 return res; 592 for (i = 0; i < count; i++) { 593 char spec_version[64]; 594 595 snprintf(spec_version, sizeof (spec_version), "%d.%d.%d", 596 VK_MAJOR(ext_props[i].specVersion), 597 VK_MINOR(ext_props[i].specVersion), 598 VK_PATCH(ext_props[i].specVersion)); 599 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, 600 "PhysicalDevice Extension: %s (%s) version %s", 601 ext_props[i].extensionName, lib_name, spec_version); 602 res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]); 603 if (res != VK_SUCCESS) 604 return res; 605 } 606 } else { 607 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Error getting physical device extension info count from library %s", lib_name); 608 return res; 609 } 610 611 return VK_SUCCESS; 612} 613 614static bool loader_init_ext_list(const struct loader_instance *inst, 615 struct loader_extension_list *ext_info) 616{ 617 ext_info->capacity = 32 * sizeof(VkExtensionProperties); 618 ext_info->list = loader_heap_alloc(inst, ext_info->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 619 if (ext_info->list == NULL) { 620 return false; 621 } 622 memset(ext_info->list, 0, ext_info->capacity); 623 ext_info->count = 0; 624 return true; 625} 626 627void loader_destroy_ext_list(const struct loader_instance *inst, 628 struct loader_extension_list *ext_info) 629{ 630 loader_heap_free(inst, ext_info->list); 631 ext_info->count = 0; 632 ext_info->capacity = 0; 633} 634 635/* 636 * Append non-duplicate extension properties defined in props 637 * to the given ext_list. 638 * Return 639 * Vk_SUCCESS on success 640 */ 641VkResult loader_add_to_ext_list( 642 const struct loader_instance *inst, 643 struct loader_extension_list *ext_list, 644 uint32_t prop_list_count, 645 const VkExtensionProperties *props) 646{ 647 uint32_t i; 648 const VkExtensionProperties *cur_ext; 649 650 if (ext_list->list == NULL || ext_list->capacity == 0) { 651 loader_init_ext_list(inst, ext_list); 652 } 653 654 if (ext_list->list == NULL) 655 return VK_ERROR_OUT_OF_HOST_MEMORY; 656 657 for (i = 0; i < prop_list_count; i++) { 658 cur_ext = &props[i]; 659 660 // look for duplicates 661 if (has_vk_extension_property(cur_ext, ext_list)) { 662 continue; 663 } 664 665 // add to list at end 666 // check for enough capacity 667 if (ext_list->count * sizeof(VkExtensionProperties) 668 >= ext_list->capacity) { 669 670 ext_list->list = loader_heap_realloc(inst, 671 ext_list->list, 672 ext_list->capacity, 673 ext_list->capacity * 2, 674 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 675 676 if (ext_list->list == NULL) 677 return VK_ERROR_OUT_OF_HOST_MEMORY; 678 679 // double capacity 680 ext_list->capacity *= 2; 681 } 682 683 memcpy(&ext_list->list[ext_list->count], cur_ext, sizeof(VkExtensionProperties)); 684 ext_list->count++; 685 } 686 return VK_SUCCESS; 687} 688 689/** 690 * Search the given search_list for any layers in the props list. 691 * Add these to the output layer_list. Don't add duplicates to the output layer_list. 692 */ 693static VkResult loader_add_layer_names_to_list( 694 const struct loader_instance *inst, 695 struct loader_layer_list *output_list, 696 uint32_t name_count, 697 const char * const *names, 698 const struct loader_layer_list *search_list) 699{ 700 struct loader_layer_properties *layer_prop; 701 VkResult err = VK_SUCCESS; 702 703 for (uint32_t i = 0; i < name_count; i++) { 704 const char *search_target = names[i]; 705 layer_prop = loader_get_layer_property(search_target, search_list); 706 if (!layer_prop) { 707 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Unable to find layer %s", search_target); 708 err = VK_ERROR_LAYER_NOT_PRESENT; 709 continue; 710 } 711 712 loader_add_to_layer_list(inst, output_list, 1, layer_prop); 713 } 714 715 return err; 716} 717 718 719/* 720 * Manage lists of VkLayerProperties 721 */ 722static bool loader_init_layer_list(const struct loader_instance *inst, 723 struct loader_layer_list *list) 724{ 725 list->capacity = 32 * sizeof(struct loader_layer_properties); 726 list->list = loader_heap_alloc(inst, list->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 727 if (list->list == NULL) { 728 return false; 729 } 730 memset(list->list, 0, list->capacity); 731 list->count = 0; 732 return true; 733} 734 735void loader_destroy_layer_list(const struct loader_instance *inst, 736 struct loader_layer_list *layer_list) 737{ 738 loader_heap_free(inst, layer_list->list); 739 layer_list->count = 0; 740 layer_list->capacity = 0; 741} 742 743/* 744 * Manage list of layer libraries (loader_lib_info) 745 */ 746static bool loader_init_layer_library_list(const struct loader_instance *inst, 747 struct loader_layer_library_list *list) 748{ 749 list->capacity = 32 * sizeof(struct loader_lib_info); 750 list->list = loader_heap_alloc(inst, list->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 751 if (list->list == NULL) { 752 return false; 753 } 754 memset(list->list, 0, list->capacity); 755 list->count = 0; 756 return true; 757} 758 759void loader_destroy_layer_library_list(const struct loader_instance *inst, 760 struct loader_layer_library_list *list) 761{ 762 for (uint32_t i = 0; i < list->count; i++) { 763 loader_heap_free(inst, list->list[i].lib_name); 764 } 765 loader_heap_free(inst, list->list); 766 list->count = 0; 767 list->capacity = 0; 768} 769 770void loader_add_to_layer_library_list( 771 const struct loader_instance *inst, 772 struct loader_layer_library_list *list, 773 uint32_t item_count, 774 const struct loader_lib_info *new_items) 775{ 776 uint32_t i; 777 struct loader_lib_info *item; 778 779 if (list->list == NULL || list->capacity == 0) { 780 loader_init_layer_library_list(inst, list); 781 } 782 783 if (list->list == NULL) 784 return; 785 786 for (i = 0; i < item_count; i++) { 787 item = (struct loader_lib_info *) &new_items[i]; 788 789 // look for duplicates 790 for (uint32_t j = 0; j < list->count; j++) { 791 if (strcmp(list->list[i].lib_name, new_items->lib_name) == 0) { 792 continue; 793 } 794 } 795 796 // add to list at end 797 // check for enough capacity 798 if (list->count * sizeof(struct loader_lib_info) 799 >= list->capacity) { 800 801 list->list = loader_heap_realloc(inst, 802 list->list, 803 list->capacity, 804 list->capacity * 2, 805 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 806 // double capacity 807 list->capacity *= 2; 808 } 809 810 memcpy(&list->list[list->count], item, sizeof(struct loader_lib_info)); 811 list->count++; 812 } 813} 814 815 816/* 817 * Search the given layer list for a list 818 * matching the given VkLayerProperties 819 */ 820bool has_vk_layer_property( 821 const VkLayerProperties *vk_layer_prop, 822 const struct loader_layer_list *list) 823{ 824 for (uint32_t i = 0; i < list->count; i++) { 825 if (strcmp(vk_layer_prop->layerName, list->list[i].info.layerName) == 0) 826 return true; 827 } 828 return false; 829} 830 831/* 832 * Search the given layer list for a layer 833 * matching the given name 834 */ 835bool has_layer_name( 836 const char *name, 837 const struct loader_layer_list *list) 838{ 839 for (uint32_t i = 0; i < list->count; i++) { 840 if (strcmp(name, list->list[i].info.layerName) == 0) 841 return true; 842 } 843 return false; 844} 845 846/* 847 * Append non-duplicate layer properties defined in prop_list 848 * to the given layer_info list 849 */ 850void loader_add_to_layer_list( 851 const struct loader_instance *inst, 852 struct loader_layer_list *list, 853 uint32_t prop_list_count, 854 const struct loader_layer_properties *props) 855{ 856 uint32_t i; 857 struct loader_layer_properties *layer; 858 859 if (list->list == NULL || list->capacity == 0) { 860 loader_init_layer_list(inst, list); 861 } 862 863 if (list->list == NULL) 864 return; 865 866 for (i = 0; i < prop_list_count; i++) { 867 layer = (struct loader_layer_properties *) &props[i]; 868 869 // look for duplicates 870 if (has_vk_layer_property(&layer->info, list)) { 871 continue; 872 } 873 874 // add to list at end 875 // check for enough capacity 876 if (list->count * sizeof(struct loader_layer_properties) 877 >= list->capacity) { 878 879 list->list = loader_heap_realloc(inst, 880 list->list, 881 list->capacity, 882 list->capacity * 2, 883 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 884 // double capacity 885 list->capacity *= 2; 886 } 887 888 memcpy(&list->list[list->count], layer, sizeof(struct loader_layer_properties)); 889 list->count++; 890 } 891} 892 893/** 894 * Search the search_list for any layer with a name 895 * that matches the given name and a type that matches the given type 896 * Add all matching layers to the found_list 897 * Do not add if found loader_layer_properties is already 898 * on the found_list. 899 */ 900static void loader_find_layer_name_add_list( 901 const struct loader_instance *inst, 902 const char *name, 903 const enum layer_type type, 904 const struct loader_layer_list *search_list, 905 struct loader_layer_list *found_list) 906{ 907 bool found = false; 908 for (uint32_t i = 0; i < search_list->count; i++) { 909 struct loader_layer_properties *layer_prop = &search_list->list[i]; 910 if (0 == strcmp(layer_prop->info.layerName, name) && 911 (layer_prop->type & type)) { 912 /* Found a layer with the same name, add to found_list */ 913 loader_add_to_layer_list(inst, found_list, 1, layer_prop); 914 found = true; 915 } 916 } 917 if (!found) { 918 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Warning, couldn't find layer name %s to activate", name); 919 } 920} 921 922static VkExtensionProperties *get_extension_property( 923 const char *name, 924 const struct loader_extension_list *list) 925{ 926 for (uint32_t i = 0; i < list->count; i++) { 927 if (strcmp(name, list->list[i].extensionName) == 0) 928 return &list->list[i]; 929 } 930 return NULL; 931} 932 933/* 934 * For global exenstions implemented within the loader (i.e. DEBUG_REPORT 935 * the extension must provide two entry points for the loader to use: 936 * - "trampoline" entry point - this is the address returned by GetProcAddr 937 * and will always do what's necessary to support a global call. 938 * - "terminator" function - this function will be put at the end of the 939 * instance chain and will contain the necessary logica to call / process 940 * the extension for the appropriate ICDs that are available. 941 * There is no generic mechanism for including these functions, the references 942 * must be placed into the appropriate loader entry points. 943 * GetInstanceProcAddr: call extension GetInstanceProcAddr to check for GetProcAddr requests 944 * loader_coalesce_extensions(void) - add extension records to the list of global 945 * extension available to the app. 946 * instance_disp - add function pointer for terminator function to this array. 947 * The extension itself should be in a separate file that will be 948 * linked directly with the loader. 949 */ 950 951void loader_get_icd_loader_instance_extensions( 952 const struct loader_instance *inst, 953 struct loader_icd_libs *icd_libs, 954 struct loader_extension_list *inst_exts) 955{ 956 struct loader_extension_list icd_exts; 957 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, "Build ICD instance extension list"); 958 // traverse scanned icd list adding non-duplicate extensions to the list 959 for (uint32_t i = 0; i < icd_libs->count; i++) { 960 loader_init_ext_list(inst, &icd_exts); 961 loader_add_global_extensions(inst, icd_libs->list[i].EnumerateInstanceExtensionProperties, 962 icd_libs->list[i].lib_name, 963 &icd_exts); 964 loader_add_to_ext_list(inst, inst_exts, 965 icd_exts.count, 966 icd_exts.list); 967 loader_destroy_ext_list(inst, &icd_exts); 968 }; 969 970 // Traverse loader's extensions, adding non-duplicate extensions to the list 971 wsi_swapchain_add_instance_extensions(inst, inst_exts); 972 debug_report_add_instance_extensions(inst, inst_exts); 973} 974 975struct loader_icd *loader_get_icd_and_device(const VkDevice device, 976 struct loader_device **found_dev) 977{ 978 *found_dev = NULL; 979 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) { 980 for (struct loader_icd *icd = inst->icds; icd; icd = icd->next) { 981 for (struct loader_device *dev = icd->logical_device_list; dev; dev = dev->next) 982 /* Value comparison of device prevents object wrapping by layers */ 983 if (loader_get_dispatch(dev->device) == loader_get_dispatch(device)) { 984 *found_dev = dev; 985 return icd; 986 } 987 } 988 } 989 return NULL; 990} 991 992static void loader_destroy_logical_device(const struct loader_instance *inst, 993 struct loader_device *dev) 994{ 995 loader_heap_free(inst, dev->app_extension_props); 996 if (dev->activated_layer_list.count) 997 loader_destroy_layer_list(inst, &dev->activated_layer_list); 998 loader_heap_free(inst, dev); 999} 1000 1001static struct loader_device *loader_add_logical_device( 1002 const struct loader_instance *inst, 1003 const VkDevice dev, 1004 struct loader_device **device_list) 1005{ 1006 struct loader_device *new_dev; 1007 1008 new_dev = loader_heap_alloc(inst, sizeof(struct loader_device), VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); 1009 if (!new_dev) { 1010 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc struct laoder-device"); 1011 return NULL; 1012 } 1013 1014 memset(new_dev, 0, sizeof(struct loader_device)); 1015 1016 new_dev->next = *device_list; 1017 new_dev->device = dev; 1018 *device_list = new_dev; 1019 return new_dev; 1020} 1021 1022void loader_remove_logical_device( 1023 const struct loader_instance *inst, 1024 VkDevice device) 1025{ 1026 struct loader_device *found_dev, *dev, *prev_dev; 1027 struct loader_icd *icd; 1028 icd = loader_get_icd_and_device(device, &found_dev); 1029 1030 if (!icd || !found_dev) 1031 return; 1032 1033 prev_dev = NULL; 1034 dev = icd->logical_device_list; 1035 while (dev && dev != found_dev) { 1036 prev_dev = dev; 1037 dev = dev->next; 1038 } 1039 1040 if (prev_dev) 1041 prev_dev->next = found_dev->next; 1042 else 1043 icd->logical_device_list = found_dev->next; 1044 loader_destroy_logical_device(inst, found_dev); 1045} 1046 1047 1048static void loader_icd_destroy( 1049 struct loader_instance *ptr_inst, 1050 struct loader_icd *icd) 1051{ 1052 ptr_inst->total_icd_count--; 1053 for (struct loader_device *dev = icd->logical_device_list; dev; ) { 1054 struct loader_device *next_dev = dev->next; 1055 loader_destroy_logical_device(ptr_inst, dev); 1056 dev = next_dev; 1057 } 1058 1059 loader_heap_free(ptr_inst, icd); 1060} 1061 1062static struct loader_icd * loader_icd_create(const struct loader_instance *inst) 1063{ 1064 struct loader_icd *icd; 1065 1066 icd = loader_heap_alloc(inst, sizeof(*icd), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1067 if (!icd) 1068 return NULL; 1069 1070 memset(icd, 0, sizeof(*icd)); 1071 1072 return icd; 1073} 1074 1075static struct loader_icd *loader_icd_add( 1076 struct loader_instance *ptr_inst, 1077 const struct loader_scanned_icds *icd_lib) 1078{ 1079 struct loader_icd *icd; 1080 1081 icd = loader_icd_create(ptr_inst); 1082 if (!icd) 1083 return NULL; 1084 1085 icd->this_icd_lib = icd_lib; 1086 icd->this_instance = ptr_inst; 1087 1088 /* prepend to the list */ 1089 icd->next = ptr_inst->icds; 1090 ptr_inst->icds = icd; 1091 ptr_inst->total_icd_count++; 1092 1093 return icd; 1094} 1095 1096void loader_scanned_icd_clear( 1097 const struct loader_instance *inst, 1098 struct loader_icd_libs *icd_libs) 1099{ 1100 if (icd_libs->capacity == 0) 1101 return; 1102 for (uint32_t i = 0; i < icd_libs->count; i++) { 1103 loader_platform_close_library(icd_libs->list[i].handle); 1104 loader_heap_free(inst, icd_libs->list[i].lib_name); 1105 } 1106 loader_heap_free(inst, icd_libs->list); 1107 icd_libs->capacity = 0; 1108 icd_libs->count = 0; 1109 icd_libs->list = NULL; 1110} 1111 1112static void loader_scanned_icd_init(const struct loader_instance *inst, 1113 struct loader_icd_libs *icd_libs) 1114{ 1115 loader_scanned_icd_clear(inst, icd_libs); 1116 icd_libs->capacity = 8 * sizeof(struct loader_scanned_icds); 1117 icd_libs->list = loader_heap_alloc(inst, icd_libs->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1118 1119} 1120 1121static void loader_scanned_icd_add( 1122 const struct loader_instance *inst, 1123 struct loader_icd_libs *icd_libs, 1124 const char *filename) 1125{ 1126 loader_platform_dl_handle handle; 1127 PFN_vkCreateInstance fp_create_inst; 1128 PFN_vkEnumerateInstanceExtensionProperties fp_get_global_ext_props; 1129 PFN_vkGetInstanceProcAddr fp_get_proc_addr; 1130 struct loader_scanned_icds *new_node; 1131 1132 /* TODO implement ref counting of libraries, for now this function leaves 1133 libraries open and the scanned_icd_clear closes them */ 1134 // Used to call: dlopen(filename, RTLD_LAZY); 1135 handle = loader_platform_open_library(filename); 1136 if (!handle) { 1137 loader_log(VK_DBG_REPORT_WARN_BIT, 0, loader_platform_open_library_error(filename)); 1138 return; 1139 } 1140 1141#define LOOKUP_LD(func_ptr, func) do { \ 1142 func_ptr = (PFN_vk ##func) loader_platform_get_proc_address(handle, "vk" #func); \ 1143 if (!func_ptr) { \ 1144 loader_log(VK_DBG_REPORT_WARN_BIT, 0, loader_platform_get_proc_address_error("vk" #func)); \ 1145 return; \ 1146 } \ 1147} while (0) 1148 1149 LOOKUP_LD(fp_get_proc_addr, GetInstanceProcAddr); 1150 LOOKUP_LD(fp_create_inst, CreateInstance); 1151 LOOKUP_LD(fp_get_global_ext_props, EnumerateInstanceExtensionProperties); 1152 1153#undef LOOKUP_LD 1154 1155 // check for enough capacity 1156 if ((icd_libs->count * sizeof(struct loader_scanned_icds)) >= icd_libs->capacity) { 1157 1158 icd_libs->list = loader_heap_realloc(inst, 1159 icd_libs->list, 1160 icd_libs->capacity, 1161 icd_libs->capacity * 2, 1162 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1163 // double capacity 1164 icd_libs->capacity *= 2; 1165 } 1166 new_node = &(icd_libs->list[icd_libs->count]); 1167 1168 new_node->handle = handle; 1169 new_node->GetInstanceProcAddr = fp_get_proc_addr; 1170 new_node->CreateInstance = fp_create_inst; 1171 new_node->EnumerateInstanceExtensionProperties = fp_get_global_ext_props; 1172 1173 new_node->lib_name = (char *) loader_heap_alloc(inst, 1174 strlen(filename) + 1, 1175 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1176 if (!new_node->lib_name) { 1177 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Out of memory can't add icd"); 1178 return; 1179 } 1180 strcpy(new_node->lib_name, filename); 1181 icd_libs->count++; 1182} 1183 1184static bool loader_icd_init_entrys(struct loader_icd *icd, 1185 VkInstance inst, 1186 const PFN_vkGetInstanceProcAddr fp_gipa) 1187{ 1188 /* initialize entrypoint function pointers */ 1189 1190 #define LOOKUP_GIPA(func, required) do { \ 1191 icd->func = (PFN_vk ##func) fp_gipa(inst, "vk" #func); \ 1192 if (!icd->func && required) { \ 1193 loader_log(VK_DBG_REPORT_WARN_BIT, 0, \ 1194 loader_platform_get_proc_address_error("vk" #func)); \ 1195 return false; \ 1196 } \ 1197 } while (0) 1198 1199 LOOKUP_GIPA(GetDeviceProcAddr, true); 1200 LOOKUP_GIPA(DestroyInstance, true); 1201 LOOKUP_GIPA(EnumeratePhysicalDevices, true); 1202 LOOKUP_GIPA(GetPhysicalDeviceFeatures, true); 1203 LOOKUP_GIPA(GetPhysicalDeviceFormatProperties, true); 1204 LOOKUP_GIPA(GetPhysicalDeviceImageFormatProperties, true); 1205 LOOKUP_GIPA(CreateDevice, true); 1206 LOOKUP_GIPA(GetPhysicalDeviceProperties, true); 1207 LOOKUP_GIPA(GetPhysicalDeviceMemoryProperties, true); 1208 LOOKUP_GIPA(GetPhysicalDeviceQueueFamilyProperties, true); 1209 LOOKUP_GIPA(EnumerateDeviceExtensionProperties, true); 1210 LOOKUP_GIPA(GetPhysicalDeviceSparseImageFormatProperties, true); 1211 LOOKUP_GIPA(DbgCreateMsgCallback, false); 1212 LOOKUP_GIPA(DbgDestroyMsgCallback, false); 1213 LOOKUP_GIPA(GetPhysicalDeviceSurfaceSupportKHR, false); 1214 1215#undef LOOKUP_GIPA 1216 1217 return true; 1218} 1219 1220static void loader_debug_init(void) 1221{ 1222 const char *env; 1223 1224 if (g_loader_debug > 0) 1225 return; 1226 1227 g_loader_debug = 0; 1228 1229 /* parse comma-separated debug options */ 1230 env = getenv("VK_LOADER_DEBUG"); 1231 while (env) { 1232 const char *p = strchr(env, ','); 1233 size_t len; 1234 1235 if (p) 1236 len = p - env; 1237 else 1238 len = strlen(env); 1239 1240 if (len > 0) { 1241 if (strncmp(env, "warn", len) == 0) { 1242 g_loader_debug |= LOADER_WARN_BIT; 1243 g_loader_log_msgs |= VK_DBG_REPORT_WARN_BIT; 1244 } else if (strncmp(env, "info", len) == 0) { 1245 g_loader_debug |= LOADER_INFO_BIT; 1246 g_loader_log_msgs |= VK_DBG_REPORT_INFO_BIT; 1247 } else if (strncmp(env, "perf", len) == 0) { 1248 g_loader_debug |= LOADER_PERF_BIT; 1249 g_loader_log_msgs |= VK_DBG_REPORT_PERF_WARN_BIT; 1250 } else if (strncmp(env, "error", len) == 0) { 1251 g_loader_debug |= LOADER_ERROR_BIT; 1252 g_loader_log_msgs |= VK_DBG_REPORT_ERROR_BIT; 1253 } else if (strncmp(env, "debug", len) == 0) { 1254 g_loader_debug |= LOADER_DEBUG_BIT; 1255 g_loader_log_msgs |= VK_DBG_REPORT_DEBUG_BIT; 1256 } 1257 } 1258 1259 if (!p) 1260 break; 1261 1262 env = p + 1; 1263 } 1264} 1265 1266void loader_initialize(void) 1267{ 1268 // initialize mutexs 1269 loader_platform_thread_create_mutex(&loader_lock); 1270 loader_platform_thread_create_mutex(&loader_json_lock); 1271 1272 // initialize logging 1273 loader_debug_init(); 1274 1275 // initial cJSON to use alloc callbacks 1276 cJSON_Hooks alloc_fns = { 1277 .malloc_fn = loader_tls_heap_alloc, 1278 .free_fn = loader_tls_heap_free, 1279 }; 1280 cJSON_InitHooks(&alloc_fns); 1281} 1282 1283struct loader_manifest_files { 1284 uint32_t count; 1285 char **filename_list; 1286}; 1287 1288/** 1289 * Get next file or dirname given a string list or registry key path 1290 * 1291 * \returns 1292 * A pointer to first char in the next path. 1293 * The next path (or NULL) in the list is returned in next_path. 1294 * Note: input string is modified in some cases. PASS IN A COPY! 1295 */ 1296static char *loader_get_next_path(char *path) 1297{ 1298 uint32_t len; 1299 char *next; 1300 1301 if (path == NULL) 1302 return NULL; 1303 next = strchr(path, PATH_SEPERATOR); 1304 if (next == NULL) { 1305 len = (uint32_t) strlen(path); 1306 next = path + len; 1307 } 1308 else { 1309 *next = '\0'; 1310 next++; 1311 } 1312 1313 return next; 1314} 1315 1316/** 1317 * Given a path which is absolute or relative, expand the path if relative or 1318 * leave the path unmodified if absolute. The base path to prepend to relative 1319 * paths is given in rel_base. 1320 * 1321 * \returns 1322 * A string in out_fullpath of the full absolute path 1323 */ 1324static void loader_expand_path(const char *path, 1325 const char *rel_base, 1326 size_t out_size, 1327 char *out_fullpath) 1328{ 1329 if (loader_platform_is_path_absolute(path)) { 1330 // do not prepend a base to an absolute path 1331 rel_base = ""; 1332 } 1333 1334 loader_platform_combine_path(out_fullpath, out_size, rel_base, path, NULL); 1335} 1336 1337/** 1338 * Given a filename (file) and a list of paths (dir), try to find an existing 1339 * file in the paths. If filename already is a path then no 1340 * searching in the given paths. 1341 * 1342 * \returns 1343 * A string in out_fullpath of either the full path or file. 1344 */ 1345static void loader_get_fullpath(const char *file, 1346 const char *dirs, 1347 size_t out_size, 1348 char *out_fullpath) 1349{ 1350 if (!loader_platform_is_path(file) && *dirs) { 1351 char *dirs_copy, *dir, *next_dir; 1352 1353 dirs_copy = loader_stack_alloc(strlen(dirs) + 1); 1354 strcpy(dirs_copy, dirs); 1355 1356 //find if file exists after prepending paths in given list 1357 for (dir = dirs_copy; 1358 *dir && (next_dir = loader_get_next_path(dir)); 1359 dir = next_dir) { 1360 loader_platform_combine_path(out_fullpath, out_size, dir, file, NULL); 1361 if (loader_platform_file_exists(out_fullpath)) { 1362 return; 1363 } 1364 } 1365 } 1366 1367 snprintf(out_fullpath, out_size, "%s", file); 1368} 1369 1370/** 1371 * Read a JSON file into a buffer. 1372 * 1373 * \returns 1374 * A pointer to a cJSON object representing the JSON parse tree. 1375 * This returned buffer should be freed by caller. 1376 */ 1377static cJSON *loader_get_json(const char *filename) 1378{ 1379 FILE *file; 1380 char *json_buf; 1381 cJSON *json; 1382 uint64_t len; 1383 file = fopen(filename,"rb"); 1384 if (!file) { 1385 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Couldn't open JSON file %s", filename); 1386 return NULL; 1387 } 1388 fseek(file, 0, SEEK_END); 1389 len = ftell(file); 1390 fseek(file, 0, SEEK_SET); 1391 json_buf = (char*) loader_stack_alloc(len+1); 1392 if (json_buf == NULL) { 1393 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get JSON file"); 1394 fclose(file); 1395 return NULL; 1396 } 1397 if (fread(json_buf, sizeof(char), len, file) != len) { 1398 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "fread failed can't get JSON file"); 1399 fclose(file); 1400 return NULL; 1401 } 1402 fclose(file); 1403 json_buf[len] = '\0'; 1404 1405 //parse text from file 1406 json = cJSON_Parse(json_buf); 1407 if (json == NULL) 1408 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Can't parse JSON file %s", filename); 1409 return json; 1410} 1411 1412/** 1413 * Do a deep copy of the loader_layer_properties structure. 1414 */ 1415static void loader_copy_layer_properties( 1416 const struct loader_instance *inst, 1417 struct loader_layer_properties *dst, 1418 struct loader_layer_properties *src) 1419{ 1420 memcpy(dst, src, sizeof (*src)); 1421 dst->instance_extension_list.list = loader_heap_alloc( 1422 inst, 1423 sizeof(VkExtensionProperties) * 1424 src->instance_extension_list.count, 1425 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1426 dst->instance_extension_list.capacity = sizeof(VkExtensionProperties) * 1427 src->instance_extension_list.count; 1428 memcpy(dst->instance_extension_list.list, src->instance_extension_list.list, 1429 dst->instance_extension_list.capacity); 1430 dst->device_extension_list.list = loader_heap_alloc( 1431 inst, 1432 sizeof(VkExtensionProperties) * 1433 src->device_extension_list.count, 1434 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1435 dst->device_extension_list.capacity = sizeof(VkExtensionProperties) * 1436 src->device_extension_list.count; 1437 memcpy(dst->device_extension_list.list, src->device_extension_list.list, 1438 dst->device_extension_list.capacity); 1439} 1440 1441/** 1442 * Given a cJSON struct (json) of the top level JSON object from layer manifest 1443 * file, add entry to the layer_list. 1444 * Fill out the layer_properties in this list entry from the input cJSON object. 1445 * 1446 * \returns 1447 * void 1448 * layer_list has a new entry and initialized accordingly. 1449 * If the json input object does not have all the required fields no entry 1450 * is added to the list. 1451 */ 1452static void loader_add_layer_properties(const struct loader_instance *inst, 1453 struct loader_layer_list *layer_instance_list, 1454 struct loader_layer_list *layer_device_list, 1455 cJSON *json, 1456 bool is_implicit, 1457 char *filename) 1458{ 1459 /* Fields in layer manifest file that are required: 1460 * (required) “file_format_version” 1461 * following are required in the "layer" object: 1462 * (required) "name" 1463 * (required) "type" 1464 * (required) “library_path” 1465 * (required) “abi_versions” 1466 * (required) “implementation_version” 1467 * (required) “description” 1468 * (required for implicit layers) “disable_environment” 1469 * 1470 * First get all required items and if any missing abort 1471 */ 1472 1473 cJSON *item, *layer_node, *ext_item; 1474 char *temp; 1475 char *name, *type, *library_path, *abi_versions; 1476 char *implementation_version, *description; 1477 cJSON *disable_environment; 1478 int i; 1479 VkExtensionProperties ext_prop; 1480 item = cJSON_GetObjectItem(json, "file_format_version"); 1481 if (item == NULL) { 1482 return; 1483 } 1484 char *file_vers = cJSON_PrintUnformatted(item); 1485 loader_log(VK_DBG_REPORT_INFO_BIT, 0, "Found manifest file %s, version %s", 1486 filename, file_vers); 1487 if (strcmp(file_vers, "\"0.9.0\"") != 0) 1488 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Unexpected manifest file version (expected 0.9.0), may cause errors"); 1489 loader_tls_heap_free(file_vers); 1490 1491 layer_node = cJSON_GetObjectItem(json, "layer"); 1492 if (layer_node == NULL) { 1493 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"layer\" object in manifest JSON file, skipping"); 1494 return; 1495 } 1496 1497 // loop through all "layer" objects in the file 1498 do { 1499#define GET_JSON_OBJECT(node, var) { \ 1500 var = cJSON_GetObjectItem(node, #var); \ 1501 if (var == NULL) { \ 1502 layer_node = layer_node->next; \ 1503 continue; \ 1504 } \ 1505 } 1506#define GET_JSON_ITEM(node, var) { \ 1507 item = cJSON_GetObjectItem(node, #var); \ 1508 if (item == NULL) { \ 1509 layer_node = layer_node->next; \ 1510 continue; \ 1511 } \ 1512 temp = cJSON_Print(item); \ 1513 temp[strlen(temp) - 1] = '\0'; \ 1514 var = loader_stack_alloc(strlen(temp) + 1); \ 1515 strcpy(var, &temp[1]); \ 1516 loader_tls_heap_free(temp); \ 1517 } 1518 GET_JSON_ITEM(layer_node, name) 1519 GET_JSON_ITEM(layer_node, type) 1520 GET_JSON_ITEM(layer_node, library_path) 1521 GET_JSON_ITEM(layer_node, abi_versions) 1522 GET_JSON_ITEM(layer_node, implementation_version) 1523 GET_JSON_ITEM(layer_node, description) 1524 if (is_implicit) { 1525 GET_JSON_OBJECT(layer_node, disable_environment) 1526 } 1527#undef GET_JSON_ITEM 1528#undef GET_JSON_OBJECT 1529 1530 // add list entry 1531 struct loader_layer_properties *props=NULL; 1532 if (!strcmp(type, "DEVICE")) { 1533 if (layer_device_list == NULL) { 1534 layer_node = layer_node->next; 1535 continue; 1536 } 1537 props = loader_get_next_layer_property(inst, layer_device_list); 1538 props->type = (is_implicit) ? VK_LAYER_TYPE_DEVICE_IMPLICIT : VK_LAYER_TYPE_DEVICE_EXPLICIT; 1539 } 1540 if (!strcmp(type, "INSTANCE")) { 1541 if (layer_instance_list == NULL) { 1542 layer_node = layer_node->next; 1543 continue; 1544 } 1545 props = loader_get_next_layer_property(inst, layer_instance_list); 1546 props->type = (is_implicit) ? VK_LAYER_TYPE_INSTANCE_IMPLICIT : VK_LAYER_TYPE_INSTANCE_EXPLICIT; 1547 } 1548 if (!strcmp(type, "GLOBAL")) { 1549 if (layer_instance_list != NULL) 1550 props = loader_get_next_layer_property(inst, layer_instance_list); 1551 else if (layer_device_list != NULL) 1552 props = loader_get_next_layer_property(inst, layer_device_list); 1553 else { 1554 layer_node = layer_node->next; 1555 continue; 1556 } 1557 props->type = (is_implicit) ? VK_LAYER_TYPE_GLOBAL_IMPLICIT : VK_LAYER_TYPE_GLOBAL_EXPLICIT; 1558 } 1559 1560 if (props == NULL) { 1561 layer_node = layer_node->next; 1562 continue; 1563 } 1564 1565 strncpy(props->info.layerName, name, sizeof (props->info.layerName)); 1566 props->info.layerName[sizeof (props->info.layerName) - 1] = '\0'; 1567 1568 char *fullpath = props->lib_name; 1569 char *rel_base; 1570 if (loader_platform_is_path(filename)) { 1571 // a relative or absolute path 1572 char *name_copy = loader_stack_alloc(strlen(filename) + 1); 1573 strcpy(name_copy, filename); 1574 rel_base = loader_platform_dirname(name_copy); 1575 loader_expand_path(library_path, rel_base, MAX_STRING_SIZE, fullpath); 1576 } else { 1577 // a filename which is assumed in a system directory 1578 loader_get_fullpath(library_path, DEFAULT_VK_LAYERS_PATH, MAX_STRING_SIZE, fullpath); 1579 } 1580 props->info.specVersion = loader_make_version(abi_versions); 1581 props->info.implementationVersion = loader_make_version(implementation_version); 1582 strncpy((char *) props->info.description, description, sizeof (props->info.description)); 1583 props->info.description[sizeof (props->info.description) - 1] = '\0'; 1584 if (is_implicit) { 1585 strncpy(props->disable_env_var.name, disable_environment->child->string, sizeof (props->disable_env_var.name)); 1586 props->disable_env_var.name[sizeof (props->disable_env_var.name) - 1] = '\0'; 1587 strncpy(props->disable_env_var.value, disable_environment->child->valuestring, sizeof (props->disable_env_var.value)); 1588 props->disable_env_var.value[sizeof (props->disable_env_var.value) - 1] = '\0'; 1589 } 1590 1591 /** 1592 * Now get all optional items and objects and put in list: 1593 * functions 1594 * instance_extensions 1595 * device_extensions 1596 * enable_environment (implicit layers only) 1597 */ 1598#define GET_JSON_OBJECT(node, var) { \ 1599 var = cJSON_GetObjectItem(node, #var); \ 1600 } 1601#define GET_JSON_ITEM(node, var) { \ 1602 item = cJSON_GetObjectItem(node, #var); \ 1603 if (item != NULL) { \ 1604 temp = cJSON_Print(item); \ 1605 temp[strlen(temp) - 1] = '\0'; \ 1606 var = loader_stack_alloc(strlen(temp) + 1);\ 1607 strcpy(var, &temp[1]); \ 1608 loader_tls_heap_free(temp); \ 1609 } \ 1610 } 1611 1612 cJSON *instance_extensions, *device_extensions, *functions, *enable_environment; 1613 char *vkGetInstanceProcAddr = NULL, *vkGetDeviceProcAddr = NULL, *version=NULL; 1614 GET_JSON_OBJECT(layer_node, functions) 1615 if (functions != NULL) { 1616 GET_JSON_ITEM(functions, vkGetInstanceProcAddr) 1617 GET_JSON_ITEM(functions, vkGetDeviceProcAddr) 1618 if (vkGetInstanceProcAddr != NULL) 1619 strncpy(props->functions.str_gipa, vkGetInstanceProcAddr, sizeof (props->functions.str_gipa)); 1620 props->functions.str_gipa[sizeof (props->functions.str_gipa) - 1] = '\0'; 1621 if (vkGetDeviceProcAddr != NULL) 1622 strncpy(props->functions.str_gdpa, vkGetDeviceProcAddr, sizeof (props->functions.str_gdpa)); 1623 props->functions.str_gdpa[sizeof (props->functions.str_gdpa) - 1] = '\0'; 1624 } 1625 GET_JSON_OBJECT(layer_node, instance_extensions) 1626 if (instance_extensions != NULL) { 1627 int count = cJSON_GetArraySize(instance_extensions); 1628 for (i = 0; i < count; i++) { 1629 ext_item = cJSON_GetArrayItem(instance_extensions, i); 1630 GET_JSON_ITEM(ext_item, name) 1631 GET_JSON_ITEM(ext_item, version) 1632 strncpy(ext_prop.extensionName, name, sizeof (ext_prop.extensionName)); 1633 ext_prop.extensionName[sizeof (ext_prop.extensionName) - 1] = '\0'; 1634 ext_prop.specVersion = loader_make_version(version); 1635 loader_add_to_ext_list(inst, &props->instance_extension_list, 1, &ext_prop); 1636 } 1637 } 1638 GET_JSON_OBJECT(layer_node, device_extensions) 1639 if (device_extensions != NULL) { 1640 int count = cJSON_GetArraySize(device_extensions); 1641 for (i = 0; i < count; i++) { 1642 ext_item = cJSON_GetArrayItem(device_extensions, i); 1643 GET_JSON_ITEM(ext_item, name); 1644 GET_JSON_ITEM(ext_item, version); 1645 strncpy(ext_prop.extensionName, name, sizeof (ext_prop.extensionName)); 1646 ext_prop.extensionName[sizeof (ext_prop.extensionName) - 1] = '\0'; 1647 ext_prop.specVersion = loader_make_version(version); 1648 loader_add_to_ext_list(inst, &props->device_extension_list, 1, &ext_prop); 1649 } 1650 } 1651 if (is_implicit) { 1652 GET_JSON_OBJECT(layer_node, enable_environment) 1653 strncpy(props->enable_env_var.name, enable_environment->child->string, sizeof (props->enable_env_var.name)); 1654 props->enable_env_var.name[sizeof (props->enable_env_var.name) - 1] = '\0'; 1655 strncpy(props->enable_env_var.value, enable_environment->child->valuestring, sizeof (props->enable_env_var.value)); 1656 props->enable_env_var.value[sizeof (props->enable_env_var.value) - 1] = '\0'; 1657 } 1658#undef GET_JSON_ITEM 1659#undef GET_JSON_OBJECT 1660 // for global layers need to add them to both device and instance list 1661 if (!strcmp(type, "GLOBAL")) { 1662 struct loader_layer_properties *dev_props; 1663 if (layer_instance_list == NULL || layer_device_list == NULL) { 1664 layer_node = layer_node->next; 1665 continue; 1666 } 1667 dev_props = loader_get_next_layer_property(inst, layer_device_list); 1668 //copy into device layer list 1669 loader_copy_layer_properties(inst, dev_props, props); 1670 } 1671 layer_node = layer_node->next; 1672 } while (layer_node != NULL); 1673 return; 1674} 1675 1676/** 1677 * Find the Vulkan library manifest files. 1678 * 1679 * This function scans the location or env_override directories/files 1680 * for a list of JSON manifest files. If env_override is non-NULL 1681 * and has a valid value. Then the location is ignored. Otherwise 1682 * location is used to look for manifest files. The location 1683 * is interpreted as Registry path on Windows and a directory path(s) 1684 * on Linux. 1685 * 1686 * \returns 1687 * A string list of manifest files to be opened in out_files param. 1688 * List has a pointer to string for each manifest filename. 1689 * When done using the list in out_files, pointers should be freed. 1690 * Location or override string lists can be either files or directories as follows: 1691 * | location | override 1692 * -------------------------------- 1693 * Win ICD | files | files 1694 * Win Layer | files | dirs 1695 * Linux ICD | dirs | files 1696 * Linux Layer| dirs | dirs 1697 */ 1698static void loader_get_manifest_files(const struct loader_instance *inst, 1699 const char *env_override, 1700 bool is_layer, 1701 const char *location, 1702 struct loader_manifest_files *out_files) 1703{ 1704 char *override = NULL; 1705 char *loc; 1706 char *file, *next_file, *name; 1707 size_t alloced_count = 64; 1708 char full_path[2048]; 1709 DIR *sysdir = NULL; 1710 bool list_is_dirs = false; 1711 struct dirent *dent; 1712 1713 out_files->count = 0; 1714 out_files->filename_list = NULL; 1715 1716 if (env_override != NULL && (override = getenv(env_override))) { 1717#if !defined(_WIN32) 1718 if (geteuid() != getuid()) { 1719 /* Don't allow setuid apps to use the env var: */ 1720 override = NULL; 1721 } 1722#endif 1723 } 1724 1725 if (location == NULL) { 1726 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, 1727 "Can't get manifest files with NULL location, env_override=%s", 1728 env_override); 1729 return; 1730 } 1731 1732#if defined(_WIN32) 1733 list_is_dirs = (is_layer && override != NULL) ? true : false; 1734#else 1735 list_is_dirs = (override == NULL || is_layer) ? true : false; 1736#endif 1737 // Make a copy of the input we are using so it is not modified 1738 // Also handle getting the location(s) from registry on Windows 1739 if (override == NULL) { 1740 loc = loader_stack_alloc(strlen(location) + 1); 1741 if (loc == NULL) { 1742 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files"); 1743 return; 1744 } 1745 strcpy(loc, location); 1746#if defined(_WIN32) 1747 loc = loader_get_registry_files(inst, loc); 1748 if (loc == NULL) { 1749 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Registry lookup failed can't get manifest files"); 1750 return; 1751 } 1752#endif 1753 } 1754 else { 1755 loc = loader_stack_alloc(strlen(override) + 1); 1756 if (loc == NULL) { 1757 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files"); 1758 return; 1759 } 1760 strcpy(loc, override); 1761 } 1762 1763 // Print out the paths being searched if debugging is enabled 1764 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, "Searching the following paths for manifest files: %s\n", loc); 1765 1766 file = loc; 1767 while (*file) { 1768 next_file = loader_get_next_path(file); 1769 if (list_is_dirs) { 1770 sysdir = opendir(file); 1771 name = NULL; 1772 if (sysdir) { 1773 dent = readdir(sysdir); 1774 if (dent == NULL) 1775 break; 1776 name = &(dent->d_name[0]); 1777 loader_get_fullpath(name, file, sizeof(full_path), full_path); 1778 name = full_path; 1779 } 1780 } 1781 else { 1782#if defined(_WIN32) 1783 name = file; 1784#else 1785 // only Linux has relative paths 1786 char *dir; 1787 // make a copy of location so it isn't modified 1788 dir = loader_stack_alloc(strlen(loc) + 1); 1789 if (dir == NULL) { 1790 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files"); 1791 return; 1792 } 1793 strcpy(dir, loc); 1794 1795 loader_get_fullpath(file, dir, sizeof(full_path), full_path); 1796 1797 name = full_path; 1798#endif 1799 } 1800 while (name) { 1801 /* Look for files ending with ".json" suffix */ 1802 uint32_t nlen = (uint32_t) strlen(name); 1803 const char *suf = name + nlen - 5; 1804 if ((nlen > 5) && !strncmp(suf, ".json", 5)) { 1805 if (out_files->count == 0) { 1806 out_files->filename_list = loader_heap_alloc(inst, 1807 alloced_count * sizeof(char *), 1808 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 1809 } 1810 else if (out_files->count == alloced_count) { 1811 out_files->filename_list = loader_heap_realloc(inst, 1812 out_files->filename_list, 1813 alloced_count * sizeof(char *), 1814 alloced_count * sizeof(char *) * 2, 1815 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 1816 alloced_count *= 2; 1817 } 1818 if (out_files->filename_list == NULL) { 1819 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't alloc manifest file list"); 1820 return; 1821 } 1822 out_files->filename_list[out_files->count] = loader_heap_alloc( 1823 inst, 1824 strlen(name) + 1, 1825 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 1826 if (out_files->filename_list[out_files->count] == NULL) { 1827 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files"); 1828 return; 1829 } 1830 strcpy(out_files->filename_list[out_files->count], name); 1831 out_files->count++; 1832 } else if (!list_is_dirs) { 1833 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Skipping manifest file %s, file name must end in .json", name); 1834 } 1835 if (list_is_dirs) { 1836 dent = readdir(sysdir); 1837 if (dent == NULL) 1838 break; 1839 name = &(dent->d_name[0]); 1840 loader_get_fullpath(name, file, sizeof(full_path), full_path); 1841 name = full_path; 1842 } 1843 else { 1844 break; 1845 } 1846 } 1847 if (sysdir) 1848 closedir(sysdir); 1849 file = next_file; 1850 } 1851 return; 1852} 1853 1854void loader_init_icd_lib_list() 1855{ 1856 1857} 1858 1859void loader_destroy_icd_lib_list() 1860{ 1861 1862} 1863/** 1864 * Try to find the Vulkan ICD driver(s). 1865 * 1866 * This function scans the default system loader path(s) or path 1867 * specified by the \c VK_ICD_FILENAMES environment variable in 1868 * order to find loadable VK ICDs manifest files. From these 1869 * manifest files it finds the ICD libraries. 1870 * 1871 * \returns 1872 * a list of icds that were discovered 1873 */ 1874void loader_icd_scan( 1875 const struct loader_instance *inst, 1876 struct loader_icd_libs *icds) 1877{ 1878 char *file_str; 1879 struct loader_manifest_files manifest_files; 1880 1881 loader_scanned_icd_init(inst, icds); 1882 // Get a list of manifest files for ICDs 1883 loader_get_manifest_files(inst, "VK_ICD_FILENAMES", false, 1884 DEFAULT_VK_DRIVERS_INFO, &manifest_files); 1885 if (manifest_files.count == 0) 1886 return; 1887 loader_platform_thread_lock_mutex(&loader_json_lock); 1888 for (uint32_t i = 0; i < manifest_files.count; i++) { 1889 file_str = manifest_files.filename_list[i]; 1890 if (file_str == NULL) 1891 continue; 1892 1893 cJSON *json; 1894 json = loader_get_json(file_str); 1895 if (!json) 1896 continue; 1897 cJSON *item; 1898 item = cJSON_GetObjectItem(json, "file_format_version"); 1899 if (item == NULL) { 1900 loader_platform_thread_unlock_mutex(&loader_json_lock); 1901 return; 1902 } 1903 char *file_vers = cJSON_Print(item); 1904 loader_log(VK_DBG_REPORT_INFO_BIT, 0, "Found manifest file %s, version %s", 1905 file_str, file_vers); 1906 if (strcmp(file_vers, "\"1.0.0\"") != 0) 1907 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Unexpected manifest file version (expected 1.0.0), may cause errors"); 1908 loader_tls_heap_free(file_vers); 1909 item = cJSON_GetObjectItem(json, "ICD"); 1910 if (item != NULL) { 1911 item = cJSON_GetObjectItem(item, "library_path"); 1912 if (item != NULL) { 1913 char *temp= cJSON_Print(item); 1914 if (!temp || strlen(temp) == 0) { 1915 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"library_path\" in ICD JSON file %s, skipping", file_str); 1916 loader_tls_heap_free(temp); 1917 loader_heap_free(inst, file_str); 1918 cJSON_Delete(json); 1919 continue; 1920 } 1921 //strip out extra quotes 1922 temp[strlen(temp) - 1] = '\0'; 1923 char *library_path = loader_stack_alloc(strlen(temp) + 1); 1924 strcpy(library_path, &temp[1]); 1925 loader_tls_heap_free(temp); 1926 if (!library_path || strlen(library_path) == 0) { 1927 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"library_path\" in ICD JSON file %s, skipping", file_str); 1928 loader_heap_free(inst, file_str); 1929 cJSON_Delete(json); 1930 continue; 1931 } 1932 char fullpath[MAX_STRING_SIZE]; 1933 // Print out the paths being searched if debugging is enabled 1934 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, "Searching for ICD drivers named %s default dir %s\n", library_path, DEFAULT_VK_DRIVERS_PATH); 1935 if (loader_platform_is_path(library_path)) { 1936 // a relative or absolute path 1937 char *name_copy = loader_stack_alloc(strlen(file_str) + 1); 1938 char *rel_base; 1939 strcpy(name_copy, file_str); 1940 rel_base = loader_platform_dirname(name_copy); 1941 loader_expand_path(library_path, rel_base, sizeof(fullpath), fullpath); 1942 } else { 1943 // a filename which is assumed in a system directory 1944 loader_get_fullpath(library_path, DEFAULT_VK_DRIVERS_PATH, sizeof(fullpath), fullpath); 1945 } 1946 loader_scanned_icd_add(inst, icds, fullpath); 1947 } 1948 } 1949 else 1950 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"ICD\" object in ICD JSON file %s, skipping", file_str); 1951 1952 loader_heap_free(inst, file_str); 1953 cJSON_Delete(json); 1954 } 1955 loader_heap_free(inst, manifest_files.filename_list); 1956 loader_platform_thread_unlock_mutex(&loader_json_lock); 1957} 1958 1959 1960void loader_layer_scan( 1961 const struct loader_instance *inst, 1962 struct loader_layer_list *instance_layers, 1963 struct loader_layer_list *device_layers) 1964{ 1965 char *file_str; 1966 struct loader_manifest_files manifest_files; 1967 cJSON *json; 1968 uint32_t i; 1969 1970 // Get a list of manifest files for layers 1971 loader_get_manifest_files(inst, LAYERS_PATH_ENV, true, DEFAULT_VK_LAYERS_INFO, 1972 &manifest_files); 1973 if (manifest_files.count == 0) 1974 return; 1975 1976#if 0 //TODO 1977 /** 1978 * We need a list of the layer libraries, not just a list of 1979 * the layer properties (a layer library could expose more than 1980 * one layer property). This list of scanned layers would be 1981 * used to check for global and physicaldevice layer properties. 1982 */ 1983 if (!loader_init_layer_library_list(&loader.scanned_layer_libraries)) { 1984 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, 1985 "Alloc for layer list failed: %s line: %d", __FILE__, __LINE__); 1986 return; 1987 } 1988#endif 1989 1990 /* cleanup any previously scanned libraries */ 1991 loader_delete_layer_properties(inst, instance_layers); 1992 loader_delete_layer_properties(inst, device_layers); 1993 1994 loader_platform_thread_lock_mutex(&loader_json_lock); 1995 for (i = 0; i < manifest_files.count; i++) { 1996 file_str = manifest_files.filename_list[i]; 1997 if (file_str == NULL) 1998 continue; 1999 2000 // parse file into JSON struct 2001 json = loader_get_json(file_str); 2002 if (!json) { 2003 continue; 2004 } 2005 2006 //TODO pass in implicit versus explicit bool 2007 //TODO error if device layers expose instance_extensions 2008 //TODO error if instance layers expose device extensions 2009 loader_add_layer_properties(inst, 2010 instance_layers, 2011 device_layers, 2012 json, 2013 false, 2014 file_str); 2015 2016 loader_heap_free(inst, file_str); 2017 cJSON_Delete(json); 2018 } 2019 loader_heap_free(inst, manifest_files.filename_list); 2020 loader_platform_thread_unlock_mutex(&loader_json_lock); 2021} 2022 2023static PFN_vkVoidFunction VKAPI loader_gpa_instance_internal(VkInstance inst, const char * pName) 2024{ 2025 // inst is not wrapped 2026 if (inst == VK_NULL_HANDLE) { 2027 return NULL; 2028 } 2029 VkLayerInstanceDispatchTable* disp_table = * (VkLayerInstanceDispatchTable **) inst; 2030 void *addr; 2031 2032 if (!strcmp(pName, "vkGetInstanceProcAddr")) 2033 return (void *) loader_gpa_instance_internal; 2034 2035 if (disp_table == NULL) 2036 return NULL; 2037 2038 addr = loader_lookup_instance_dispatch_table(disp_table, pName); 2039 if (addr) { 2040 return addr; 2041 } 2042 2043 if (disp_table->GetInstanceProcAddr == NULL) { 2044 return NULL; 2045 } 2046 return disp_table->GetInstanceProcAddr(inst, pName); 2047} 2048 2049struct loader_instance *loader_get_instance(const VkInstance instance) 2050{ 2051 /* look up the loader_instance in our list by comparing dispatch tables, as 2052 * there is no guarantee the instance is still a loader_instance* after any 2053 * layers which wrap the instance object. 2054 */ 2055 const VkLayerInstanceDispatchTable *disp; 2056 struct loader_instance *ptr_instance = NULL; 2057 disp = loader_get_instance_dispatch(instance); 2058 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) { 2059 if (inst->disp == disp) { 2060 ptr_instance = inst; 2061 break; 2062 } 2063 } 2064 return ptr_instance; 2065} 2066 2067static loader_platform_dl_handle loader_add_layer_lib( 2068 const struct loader_instance *inst, 2069 const char *chain_type, 2070 struct loader_layer_properties *layer_prop) 2071{ 2072 struct loader_lib_info *new_layer_lib_list, *my_lib; 2073 size_t new_alloc_size; 2074 /* 2075 * TODO: We can now track this information in the 2076 * scanned_layer_libraries list. 2077 */ 2078 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) { 2079 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, layer_prop->lib_name) == 0) { 2080 /* Have already loaded this library, just increment ref count */ 2081 loader.loaded_layer_lib_list[i].ref_count++; 2082 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, 2083 "%s Chain: Increment layer reference count for layer library %s", 2084 chain_type, layer_prop->lib_name); 2085 return loader.loaded_layer_lib_list[i].lib_handle; 2086 } 2087 } 2088 2089 /* Haven't seen this library so load it */ 2090 new_alloc_size = 0; 2091 if (loader.loaded_layer_lib_capacity == 0) 2092 new_alloc_size = 8 * sizeof(struct loader_lib_info); 2093 else if (loader.loaded_layer_lib_capacity <= loader.loaded_layer_lib_count * 2094 sizeof(struct loader_lib_info)) 2095 new_alloc_size = loader.loaded_layer_lib_capacity * 2; 2096 2097 if (new_alloc_size) { 2098 new_layer_lib_list = loader_heap_realloc( 2099 inst, loader.loaded_layer_lib_list, 2100 loader.loaded_layer_lib_capacity, 2101 new_alloc_size, 2102 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 2103 if (!new_layer_lib_list) { 2104 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "loader: realloc failed in loader_add_layer_lib"); 2105 return NULL; 2106 } 2107 loader.loaded_layer_lib_capacity = new_alloc_size; 2108 } else 2109 new_layer_lib_list = loader.loaded_layer_lib_list; 2110 my_lib = &new_layer_lib_list[loader.loaded_layer_lib_count]; 2111 2112 strncpy(my_lib->lib_name, layer_prop->lib_name, sizeof(my_lib->lib_name)); 2113 my_lib->lib_name[sizeof(my_lib->lib_name) - 1] = '\0'; 2114 my_lib->ref_count = 0; 2115 my_lib->lib_handle = NULL; 2116 2117 if ((my_lib->lib_handle = loader_platform_open_library(my_lib->lib_name)) == NULL) { 2118 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, 2119 loader_platform_open_library_error(my_lib->lib_name)); 2120 return NULL; 2121 } else { 2122 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, 2123 "Chain: %s: Loading layer library %s", 2124 chain_type, layer_prop->lib_name); 2125 } 2126 loader.loaded_layer_lib_count++; 2127 loader.loaded_layer_lib_list = new_layer_lib_list; 2128 my_lib->ref_count++; 2129 2130 return my_lib->lib_handle; 2131} 2132 2133static void loader_remove_layer_lib( 2134 struct loader_instance *inst, 2135 struct loader_layer_properties *layer_prop) 2136{ 2137 uint32_t idx; 2138 struct loader_lib_info *new_layer_lib_list, *my_lib = NULL; 2139 2140 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) { 2141 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, layer_prop->lib_name) == 0) { 2142 /* found matching library */ 2143 idx = i; 2144 my_lib = &loader.loaded_layer_lib_list[i]; 2145 break; 2146 } 2147 } 2148 2149 if (my_lib) { 2150 my_lib->ref_count--; 2151 if (my_lib->ref_count > 0) { 2152 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, 2153 "Decrement reference count for layer library %s", layer_prop->lib_name); 2154 return; 2155 } 2156 } 2157 loader_platform_close_library(my_lib->lib_handle); 2158 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, 2159 "Unloading layer library %s", layer_prop->lib_name); 2160 2161 /* Need to remove unused library from list */ 2162 new_layer_lib_list = loader_heap_alloc(inst, 2163 loader.loaded_layer_lib_capacity, 2164 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 2165 if (!new_layer_lib_list) { 2166 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "loader: heap alloc failed loader_remove_layer_library"); 2167 return; 2168 } 2169 2170 if (idx > 0) { 2171 /* Copy records before idx */ 2172 memcpy(new_layer_lib_list, &loader.loaded_layer_lib_list[0], 2173 sizeof(struct loader_lib_info) * idx); 2174 } 2175 if (idx < (loader.loaded_layer_lib_count - 1)) { 2176 /* Copy records after idx */ 2177 memcpy(&new_layer_lib_list[idx], &loader.loaded_layer_lib_list[idx+1], 2178 sizeof(struct loader_lib_info) * (loader.loaded_layer_lib_count - idx - 1)); 2179 } 2180 2181 loader_heap_free(inst, loader.loaded_layer_lib_list); 2182 loader.loaded_layer_lib_count--; 2183 loader.loaded_layer_lib_list = new_layer_lib_list; 2184} 2185 2186 2187/** 2188 * Go through the search_list and find any layers which match type. If layer 2189 * type match is found in then add it to ext_list. 2190 */ 2191//TODO need to handle implict layer enable env var and disable env var 2192static void loader_add_layer_implicit( 2193 const struct loader_instance *inst, 2194 const enum layer_type type, 2195 struct loader_layer_list *list, 2196 const struct loader_layer_list *search_list) 2197{ 2198 uint32_t i; 2199 for (i = 0; i < search_list->count; i++) { 2200 const struct loader_layer_properties *prop = &search_list->list[i]; 2201 if (prop->type & type) { 2202 /* Found an layer with the same type, add to layer_list */ 2203 loader_add_to_layer_list(inst, list, 1, prop); 2204 } 2205 } 2206 2207} 2208 2209/** 2210 * Get the layer name(s) from the env_name environment variable. If layer 2211 * is found in search_list then add it to layer_list. But only add it to 2212 * layer_list if type matches. 2213 */ 2214static void loader_add_layer_env( 2215 const struct loader_instance *inst, 2216 const enum layer_type type, 2217 const char *env_name, 2218 struct loader_layer_list *layer_list, 2219 const struct loader_layer_list *search_list) 2220{ 2221 char *layerEnv; 2222 char *next, *name; 2223 2224 layerEnv = getenv(env_name); 2225 if (layerEnv == NULL) { 2226 return; 2227 } 2228 name = loader_stack_alloc(strlen(layerEnv) + 1); 2229 if (name == NULL) { 2230 return; 2231 } 2232 strcpy(name, layerEnv); 2233 2234 while (name && *name ) { 2235 next = loader_get_next_path(name); 2236 loader_find_layer_name_add_list(inst, name, type, search_list, layer_list); 2237 name = next; 2238 } 2239 2240 return; 2241} 2242 2243void loader_deactivate_instance_layers(struct loader_instance *instance) 2244{ 2245 if (!instance->activated_layer_list.count) { 2246 return; 2247 } 2248 2249 /* Create instance chain of enabled layers */ 2250 for (uint32_t i = 0; i < instance->activated_layer_list.count; i++) { 2251 struct loader_layer_properties *layer_prop = &instance->activated_layer_list.list[i]; 2252 2253 loader_remove_layer_lib(instance, layer_prop); 2254 } 2255 loader_destroy_layer_list(instance, &instance->activated_layer_list); 2256} 2257 2258VkResult loader_enable_instance_layers( 2259 struct loader_instance *inst, 2260 const VkInstanceCreateInfo *pCreateInfo, 2261 const struct loader_layer_list *instance_layers) 2262{ 2263 VkResult err; 2264 2265 assert(inst && "Cannot have null instance"); 2266 2267 if (!loader_init_layer_list(inst, &inst->activated_layer_list)) { 2268 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc Instance activated layer list"); 2269 return VK_ERROR_OUT_OF_HOST_MEMORY; 2270 } 2271 2272 /* Add any implicit layers first */ 2273 loader_add_layer_implicit( 2274 inst, 2275 VK_LAYER_TYPE_INSTANCE_IMPLICIT, 2276 &inst->activated_layer_list, 2277 instance_layers); 2278 2279 /* Add any layers specified via environment variable next */ 2280 loader_add_layer_env( 2281 inst, 2282 VK_LAYER_TYPE_INSTANCE_EXPLICIT, 2283 "VK_INSTANCE_LAYERS", 2284 &inst->activated_layer_list, 2285 instance_layers); 2286 2287 /* Add layers specified by the application */ 2288 err = loader_add_layer_names_to_list( 2289 inst, 2290 &inst->activated_layer_list, 2291 pCreateInfo->enabledLayerNameCount, 2292 pCreateInfo->ppEnabledLayerNames, 2293 instance_layers); 2294 2295 return err; 2296} 2297 2298uint32_t loader_activate_instance_layers(struct loader_instance *inst) 2299{ 2300 uint32_t layer_idx; 2301 VkBaseLayerObject *wrappedInstance; 2302 2303 if (inst == NULL) { 2304 return 0; 2305 } 2306 2307 // NOTE inst is unwrapped at this point in time 2308 void* baseObj = (void*) inst; 2309 void* nextObj = (void*) inst; 2310 VkBaseLayerObject *nextInstObj; 2311 PFN_vkGetInstanceProcAddr nextGPA = loader_gpa_instance_internal; 2312 2313 if (!inst->activated_layer_list.count) { 2314 loader_init_instance_core_dispatch_table(inst->disp, nextGPA, (VkInstance) nextObj, (VkInstance) baseObj); 2315 return 0; 2316 } 2317 2318 wrappedInstance = loader_stack_alloc(sizeof(VkBaseLayerObject) 2319 * inst->activated_layer_list.count); 2320 if (!wrappedInstance) { 2321 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc Instance objects for layer"); 2322 return 0; 2323 } 2324 2325 /* Create instance chain of enabled layers */ 2326 layer_idx = inst->activated_layer_list.count - 1; 2327 for (int32_t i = inst->activated_layer_list.count - 1; i >= 0; i--) { 2328 struct loader_layer_properties *layer_prop = &inst->activated_layer_list.list[i]; 2329 loader_platform_dl_handle lib_handle; 2330 2331 /* 2332 * Note: An extension's Get*ProcAddr should not return a function pointer for 2333 * any extension entry points until the extension has been enabled. 2334 * To do this requires a different behavior from Get*ProcAddr functions implemented 2335 * in layers. 2336 * The very first call to a layer will be it's Get*ProcAddr function requesting 2337 * the layer's vkGet*ProcAddr. The layer should initialize its internal dispatch table 2338 * with the wrapped object given (either Instance or Device) and return the layer's 2339 * Get*ProcAddr function. The layer should also use this opportunity to record the 2340 * baseObject so that it can find the correct local dispatch table on future calls. 2341 * Subsequent calls to Get*ProcAddr, CreateInstance, CreateDevice 2342 * will not use a wrapped object and must look up their local dispatch table from 2343 * the given baseObject. 2344 */ 2345 nextInstObj = (wrappedInstance + layer_idx); 2346 nextInstObj->pGPA = (PFN_vkGPA) nextGPA; 2347 nextInstObj->baseObject = baseObj; 2348 nextInstObj->nextObject = nextObj; 2349 nextObj = (void*) nextInstObj; 2350 2351 lib_handle = loader_add_layer_lib(inst, "instance", layer_prop); 2352 if ((nextGPA = layer_prop->functions.get_instance_proc_addr) == NULL) { 2353 if (layer_prop->functions.str_gipa == NULL || strlen(layer_prop->functions.str_gipa) == 0) { 2354 nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetInstanceProcAddr"); 2355 layer_prop->functions.get_instance_proc_addr = nextGPA; 2356 } else 2357 nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gipa); 2358 if (!nextGPA) { 2359 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to find vkGetInstanceProcAddr in layer %s", layer_prop->lib_name); 2360 2361 /* TODO: Should we return nextObj, nextGPA to previous? or decrement layer_list count*/ 2362 continue; 2363 } 2364 } 2365 2366 loader_log(VK_DBG_REPORT_INFO_BIT, 0, 2367 "Insert instance layer %s (%s)", 2368 layer_prop->info.layerName, 2369 layer_prop->lib_name); 2370 2371 layer_idx--; 2372 } 2373 2374 loader_init_instance_core_dispatch_table(inst->disp, nextGPA, (VkInstance) nextObj, (VkInstance) baseObj); 2375 2376 return inst->activated_layer_list.count; 2377} 2378 2379void loader_activate_instance_layer_extensions(struct loader_instance *inst) 2380{ 2381 2382 loader_init_instance_extension_dispatch_table(inst->disp, 2383 inst->disp->GetInstanceProcAddr, 2384 (VkInstance) inst); 2385} 2386 2387static VkResult loader_enable_device_layers( 2388 const struct loader_instance *inst, 2389 struct loader_icd *icd, 2390 struct loader_device *dev, 2391 const VkDeviceCreateInfo *pCreateInfo, 2392 const struct loader_layer_list *device_layers) 2393 2394{ 2395 VkResult err; 2396 2397 assert(dev && "Cannot have null device"); 2398 2399 if (dev->activated_layer_list.list == NULL || dev->activated_layer_list.capacity == 0) { 2400 loader_init_layer_list(inst, &dev->activated_layer_list); 2401 } 2402 2403 if (dev->activated_layer_list.list == NULL) { 2404 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc device activated layer list"); 2405 return VK_ERROR_OUT_OF_HOST_MEMORY; 2406 } 2407 2408 /* Add any implicit layers first */ 2409 loader_add_layer_implicit( 2410 inst, 2411 VK_LAYER_TYPE_DEVICE_IMPLICIT, 2412 &dev->activated_layer_list, 2413 device_layers); 2414 2415 /* Add any layers specified via environment variable next */ 2416 loader_add_layer_env( 2417 inst, 2418 VK_LAYER_TYPE_DEVICE_EXPLICIT, 2419 "VK_DEVICE_LAYERS", 2420 &dev->activated_layer_list, 2421 device_layers); 2422 2423 /* Add layers specified by the application */ 2424 err = loader_add_layer_names_to_list( 2425 inst, 2426 &dev->activated_layer_list, 2427 pCreateInfo->enabledLayerNameCount, 2428 pCreateInfo->ppEnabledLayerNames, 2429 device_layers); 2430 2431 return err; 2432} 2433 2434/* 2435 * This function terminates the device chain for CreateDevice. 2436 * CreateDevice is a special case and so the loader call's 2437 * the ICD's CreateDevice before creating the chain. Since 2438 * we can't call CreateDevice twice we must terminate the 2439 * device chain with something else. 2440 */ 2441static VkResult VKAPI scratch_vkCreateDevice( 2442 VkPhysicalDevice physicalDevice, 2443 const VkDeviceCreateInfo *pCreateInfo, 2444 const VkAllocationCallbacks* pAllocator, 2445 VkDevice *pDevice) 2446{ 2447 return VK_SUCCESS; 2448} 2449 2450static PFN_vkVoidFunction VKAPI loader_GetDeviceChainProcAddr(VkDevice device, const char * name) 2451{ 2452 if (!strcmp(name, "vkGetDeviceProcAddr")) 2453 return (PFN_vkVoidFunction) loader_GetDeviceChainProcAddr; 2454 if (!strcmp(name, "vkCreateDevice")) 2455 return (PFN_vkVoidFunction) scratch_vkCreateDevice; 2456 2457 struct loader_device *found_dev; 2458 struct loader_icd *icd = loader_get_icd_and_device(device, &found_dev); 2459 return icd->GetDeviceProcAddr(device, name); 2460} 2461 2462static uint32_t loader_activate_device_layers( 2463 const struct loader_instance *inst, 2464 struct loader_device *dev, 2465 VkDevice device) 2466{ 2467 if (!dev) { 2468 return 0; 2469 } 2470 2471 /* activate any layer libraries */ 2472 void* nextObj = (void*) device; 2473 void* baseObj = nextObj; 2474 VkBaseLayerObject *nextGpuObj; 2475 PFN_vkGetDeviceProcAddr nextGPA = loader_GetDeviceChainProcAddr; 2476 VkBaseLayerObject *wrappedGpus; 2477 2478 if (!dev->activated_layer_list.count) { 2479 loader_init_device_dispatch_table(&dev->loader_dispatch, nextGPA, 2480 (VkDevice) nextObj, (VkDevice) baseObj); 2481 return 0; 2482 } 2483 2484 wrappedGpus = loader_heap_alloc(inst, 2485 sizeof (VkBaseLayerObject) * dev->activated_layer_list.count, 2486 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 2487 if (!wrappedGpus) { 2488 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc Gpu objects for layer"); 2489 return 0; 2490 } 2491 2492 for (int32_t i = dev->activated_layer_list.count - 1; i >= 0; i--) { 2493 2494 struct loader_layer_properties *layer_prop = &dev->activated_layer_list.list[i]; 2495 loader_platform_dl_handle lib_handle; 2496 2497 nextGpuObj = (wrappedGpus + i); 2498 nextGpuObj->pGPA = (PFN_vkGPA)nextGPA; 2499 nextGpuObj->baseObject = baseObj; 2500 nextGpuObj->nextObject = nextObj; 2501 nextObj = (void*) nextGpuObj; 2502 2503 lib_handle = loader_add_layer_lib(inst, "device", layer_prop); 2504 if ((nextGPA = layer_prop->functions.get_device_proc_addr) == NULL) { 2505 if (layer_prop->functions.str_gdpa == NULL || strlen(layer_prop->functions.str_gdpa) == 0) { 2506 nextGPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetDeviceProcAddr"); 2507 layer_prop->functions.get_device_proc_addr = nextGPA; 2508 } else 2509 nextGPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gdpa); 2510 if (!nextGPA) { 2511 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to find vkGetDeviceProcAddr in layer %s", layer_prop->lib_name); 2512 continue; 2513 } 2514 } 2515 2516 loader_log(VK_DBG_REPORT_INFO_BIT, 0, 2517 "Insert device layer library %s (%s)", 2518 layer_prop->info.layerName, 2519 layer_prop->lib_name); 2520 2521 } 2522 2523 loader_init_device_dispatch_table(&dev->loader_dispatch, nextGPA, 2524 (VkDevice) nextObj, (VkDevice) baseObj); 2525 loader_heap_free(inst, wrappedGpus); 2526 2527 return dev->activated_layer_list.count; 2528} 2529 2530VkResult loader_validate_layers( 2531 const uint32_t layer_count, 2532 const char * const *ppEnabledLayerNames, 2533 const struct loader_layer_list *list) 2534{ 2535 struct loader_layer_properties *prop; 2536 2537 for (uint32_t i = 0; i < layer_count; i++) { 2538 prop = loader_get_layer_property(ppEnabledLayerNames[i], 2539 list); 2540 if (!prop) { 2541 return VK_ERROR_LAYER_NOT_PRESENT; 2542 } 2543 } 2544 2545 return VK_SUCCESS; 2546} 2547 2548VkResult loader_validate_instance_extensions( 2549 const struct loader_extension_list *icd_exts, 2550 const struct loader_layer_list *instance_layer, 2551 const VkInstanceCreateInfo *pCreateInfo) 2552{ 2553 VkExtensionProperties *extension_prop; 2554 struct loader_layer_properties *layer_prop; 2555 2556 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) { 2557 extension_prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i], 2558 icd_exts); 2559 2560 if (extension_prop) { 2561 continue; 2562 } 2563 2564 extension_prop = NULL; 2565 2566 /* Not in global list, search layer extension lists */ 2567 for (uint32_t j = 0; j < pCreateInfo->enabledLayerNameCount; j++) { 2568 layer_prop = loader_get_layer_property(pCreateInfo->ppEnabledLayerNames[i], 2569 instance_layer); 2570 if (!layer_prop) { 2571 /* Should NOT get here, loader_validate_layers 2572 * should have already filtered this case out. 2573 */ 2574 continue; 2575 } 2576 2577 extension_prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i], 2578 &layer_prop->instance_extension_list); 2579 if (extension_prop) { 2580 /* Found the extension in one of the layers enabled by the app. */ 2581 break; 2582 } 2583 } 2584 2585 if (!extension_prop) { 2586 /* Didn't find extension name in any of the global layers, error out */ 2587 return VK_ERROR_EXTENSION_NOT_PRESENT; 2588 } 2589 } 2590 return VK_SUCCESS; 2591} 2592 2593VkResult loader_validate_device_extensions( 2594 struct loader_physical_device *phys_dev, 2595 const struct loader_layer_list *device_layer, 2596 const VkDeviceCreateInfo *pCreateInfo) 2597{ 2598 VkExtensionProperties *extension_prop; 2599 struct loader_layer_properties *layer_prop; 2600 2601 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) { 2602 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i]; 2603 extension_prop = get_extension_property(extension_name, 2604 &phys_dev->device_extension_cache); 2605 2606 if (extension_prop) { 2607 continue; 2608 } 2609 2610 /* Not in global list, search layer extension lists */ 2611 for (uint32_t j = 0; j < pCreateInfo->enabledLayerNameCount; j++) { 2612 const char *layer_name = pCreateInfo->ppEnabledLayerNames[j]; 2613 layer_prop = loader_get_layer_property(layer_name, 2614 device_layer); 2615 2616 if (!layer_prop) { 2617 /* Should NOT get here, loader_validate_instance_layers 2618 * should have already filtered this case out. 2619 */ 2620 continue; 2621 } 2622 2623 extension_prop = get_extension_property(extension_name, 2624 &layer_prop->device_extension_list); 2625 if (extension_prop) { 2626 /* Found the extension in one of the layers enabled by the app. */ 2627 break; 2628 } 2629 } 2630 2631 if (!extension_prop) { 2632 /* Didn't find extension name in any of the device layers, error out */ 2633 return VK_ERROR_EXTENSION_NOT_PRESENT; 2634 } 2635 } 2636 return VK_SUCCESS; 2637} 2638 2639VkResult VKAPI loader_CreateInstance( 2640 const VkInstanceCreateInfo* pCreateInfo, 2641 const VkAllocationCallbacks* pAllocator, 2642 VkInstance* pInstance) 2643{ 2644 struct loader_instance *ptr_instance = *(struct loader_instance **) pInstance; 2645 struct loader_icd *icd; 2646 VkExtensionProperties *prop; 2647 char **filtered_extension_names = NULL; 2648 VkInstanceCreateInfo icd_create_info; 2649 VkResult res = VK_SUCCESS; 2650 bool success; 2651 2652 icd_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; 2653 icd_create_info.enabledLayerNameCount = 0; 2654 icd_create_info.ppEnabledLayerNames = NULL; 2655 icd_create_info.pApplicationInfo = pCreateInfo->pApplicationInfo; 2656 icd_create_info.pNext = pCreateInfo->pNext; 2657 2658 /* 2659 * NOTE: Need to filter the extensions to only those 2660 * supported by the ICD. 2661 * No ICD will advertise support for layers. An ICD 2662 * library could support a layer, but it would be 2663 * independent of the actual ICD, just in the same library. 2664 */ 2665 filtered_extension_names = loader_stack_alloc(pCreateInfo->enabledExtensionNameCount * sizeof(char *)); 2666 if (!filtered_extension_names) { 2667 return VK_ERROR_OUT_OF_HOST_MEMORY; 2668 } 2669 icd_create_info.ppEnabledExtensionNames = (const char * const *) filtered_extension_names; 2670 2671 for (uint32_t i = 0; i < ptr_instance->icd_libs.count; i++) { 2672 icd = loader_icd_add(ptr_instance, &ptr_instance->icd_libs.list[i]); 2673 if (icd) { 2674 icd_create_info.enabledExtensionNameCount = 0; 2675 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) { 2676 prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i], 2677 &ptr_instance->ext_list); 2678 if (prop) { 2679 filtered_extension_names[icd_create_info.enabledExtensionNameCount] = (char *) pCreateInfo->ppEnabledExtensionNames[i]; 2680 icd_create_info.enabledExtensionNameCount++; 2681 } 2682 } 2683 2684 res = ptr_instance->icd_libs.list[i].CreateInstance(&icd_create_info, 2685 pAllocator, 2686 &(icd->instance)); 2687 success = loader_icd_init_entrys( 2688 icd, 2689 icd->instance, 2690 ptr_instance->icd_libs.list[i].GetInstanceProcAddr); 2691 2692 if (res != VK_SUCCESS || !success) 2693 { 2694 ptr_instance->icds = ptr_instance->icds->next; 2695 loader_icd_destroy(ptr_instance, icd); 2696 icd->instance = VK_NULL_HANDLE; 2697 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, 2698 "ICD ignored: failed to CreateInstance and find entrypoints with ICD"); 2699 } 2700 } 2701 } 2702 2703 /* 2704 * If no ICDs were added to instance list and res is unchanged 2705 * from it's initial value, the loader was unable to find 2706 * a suitable ICD. 2707 */ 2708 if (ptr_instance->icds == NULL) { 2709 if (res == VK_SUCCESS) { 2710 return VK_ERROR_INCOMPATIBLE_DRIVER; 2711 } else { 2712 return res; 2713 } 2714 } 2715 2716 return VK_SUCCESS; 2717} 2718 2719void VKAPI loader_DestroyInstance( 2720 VkInstance instance, 2721 const VkAllocationCallbacks* pAllocator) 2722{ 2723 struct loader_instance *ptr_instance = loader_instance(instance); 2724 struct loader_icd *icds = ptr_instance->icds; 2725 struct loader_icd *next_icd; 2726 2727 // Remove this instance from the list of instances: 2728 struct loader_instance *prev = NULL; 2729 struct loader_instance *next = loader.instances; 2730 while (next != NULL) { 2731 if (next == ptr_instance) { 2732 // Remove this instance from the list: 2733 if (prev) 2734 prev->next = next->next; 2735 else 2736 loader.instances = next->next; 2737 break; 2738 } 2739 prev = next; 2740 next = next->next; 2741 } 2742 2743 while (icds) { 2744 if (icds->instance) { 2745 icds->DestroyInstance(icds->instance, pAllocator); 2746 } 2747 next_icd = icds->next; 2748 icds->instance = VK_NULL_HANDLE; 2749 loader_icd_destroy(ptr_instance, icds); 2750 2751 icds = next_icd; 2752 } 2753 loader_delete_layer_properties(ptr_instance, &ptr_instance->device_layer_list); 2754 loader_delete_layer_properties(ptr_instance, &ptr_instance->instance_layer_list); 2755 loader_scanned_icd_clear(ptr_instance, &ptr_instance->icd_libs); 2756 loader_destroy_ext_list(ptr_instance, &ptr_instance->ext_list); 2757 for (uint32_t i = 0; i < ptr_instance->total_gpu_count; i++) 2758 loader_destroy_ext_list(ptr_instance, &ptr_instance->phys_devs[i].device_extension_cache); 2759 loader_heap_free(ptr_instance, ptr_instance->phys_devs); 2760} 2761 2762VkResult loader_init_physical_device_info(struct loader_instance *ptr_instance) 2763{ 2764 struct loader_icd *icd; 2765 uint32_t i, j, idx, count = 0; 2766 VkResult res; 2767 struct loader_phys_dev_per_icd *phys_devs; 2768 2769 ptr_instance->total_gpu_count = 0; 2770 phys_devs = (struct loader_phys_dev_per_icd *) loader_stack_alloc( 2771 sizeof(struct loader_phys_dev_per_icd) * 2772 ptr_instance->total_icd_count); 2773 if (!phys_devs) 2774 return VK_ERROR_OUT_OF_HOST_MEMORY; 2775 2776 icd = ptr_instance->icds; 2777 for (i = 0; i < ptr_instance->total_icd_count; i++) { 2778 assert(icd); 2779 res = icd->EnumeratePhysicalDevices(icd->instance, &phys_devs[i].count, NULL); 2780 if (res != VK_SUCCESS) 2781 return res; 2782 count += phys_devs[i].count; 2783 icd = icd->next; 2784 } 2785 2786 ptr_instance->phys_devs = (struct loader_physical_device *) loader_heap_alloc( 2787 ptr_instance, 2788 count * sizeof(struct loader_physical_device), 2789 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 2790 if (!ptr_instance->phys_devs) 2791 return VK_ERROR_OUT_OF_HOST_MEMORY; 2792 2793 icd = ptr_instance->icds; 2794 2795 struct loader_physical_device *inst_phys_devs = ptr_instance->phys_devs; 2796 idx = 0; 2797 for (i = 0; i < ptr_instance->total_icd_count; i++) { 2798 assert(icd); 2799 2800 phys_devs[i].phys_devs = (VkPhysicalDevice *) loader_stack_alloc( 2801 phys_devs[i].count * sizeof(VkPhysicalDevice)); 2802 if (!phys_devs[i].phys_devs) { 2803 loader_heap_free(ptr_instance, ptr_instance->phys_devs); 2804 ptr_instance->phys_devs = NULL; 2805 return VK_ERROR_OUT_OF_HOST_MEMORY; 2806 } 2807 res = icd->EnumeratePhysicalDevices( 2808 icd->instance, 2809 &(phys_devs[i].count), 2810 phys_devs[i].phys_devs); 2811 if ((res == VK_SUCCESS)) { 2812 ptr_instance->total_gpu_count += phys_devs[i].count; 2813 for (j = 0; j < phys_devs[i].count; j++) { 2814 2815 // initialize the loader's physicalDevice object 2816 loader_set_dispatch((void *) &inst_phys_devs[idx], ptr_instance->disp); 2817 inst_phys_devs[idx].this_instance = ptr_instance; 2818 inst_phys_devs[idx].this_icd = icd; 2819 inst_phys_devs[idx].phys_dev = phys_devs[i].phys_devs[j]; 2820 memset(&inst_phys_devs[idx].device_extension_cache, 0, sizeof(struct loader_extension_list)); 2821 2822 idx++; 2823 } 2824 } else { 2825 loader_heap_free(ptr_instance, ptr_instance->phys_devs); 2826 ptr_instance->phys_devs = NULL; 2827 return res; 2828 } 2829 2830 icd = icd->next; 2831 } 2832 2833 return VK_SUCCESS; 2834} 2835 2836VkResult VKAPI loader_EnumeratePhysicalDevices( 2837 VkInstance instance, 2838 uint32_t* pPhysicalDeviceCount, 2839 VkPhysicalDevice* pPhysicalDevices) 2840{ 2841 uint32_t i; 2842 struct loader_instance *ptr_instance = (struct loader_instance *) instance; 2843 VkResult res = VK_SUCCESS; 2844 2845 if (ptr_instance->total_gpu_count == 0) { 2846 res = loader_init_physical_device_info(ptr_instance); 2847 } 2848 2849 *pPhysicalDeviceCount = ptr_instance->total_gpu_count; 2850 if (!pPhysicalDevices) { 2851 return res; 2852 } 2853 2854 for (i = 0; i < ptr_instance->total_gpu_count; i++) { 2855 pPhysicalDevices[i] = (VkPhysicalDevice) &ptr_instance->phys_devs[i]; 2856 } 2857 2858 return res; 2859} 2860 2861void VKAPI loader_GetPhysicalDeviceProperties( 2862 VkPhysicalDevice physicalDevice, 2863 VkPhysicalDeviceProperties* pProperties) 2864{ 2865 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice; 2866 struct loader_icd *icd = phys_dev->this_icd; 2867 2868 if (icd->GetPhysicalDeviceProperties) 2869 icd->GetPhysicalDeviceProperties(phys_dev->phys_dev, pProperties); 2870} 2871 2872void VKAPI loader_GetPhysicalDeviceQueueFamilyProperties ( 2873 VkPhysicalDevice physicalDevice, 2874 uint32_t* pQueueFamilyPropertyCount, 2875 VkQueueFamilyProperties* pProperties) 2876{ 2877 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice; 2878 struct loader_icd *icd = phys_dev->this_icd; 2879 2880 if (icd->GetPhysicalDeviceQueueFamilyProperties) 2881 icd->GetPhysicalDeviceQueueFamilyProperties(phys_dev->phys_dev, pQueueFamilyPropertyCount, pProperties); 2882} 2883 2884void VKAPI loader_GetPhysicalDeviceMemoryProperties ( 2885 VkPhysicalDevice physicalDevice, 2886 VkPhysicalDeviceMemoryProperties* pProperties) 2887{ 2888 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice; 2889 struct loader_icd *icd = phys_dev->this_icd; 2890 2891 if (icd->GetPhysicalDeviceMemoryProperties) 2892 icd->GetPhysicalDeviceMemoryProperties(phys_dev->phys_dev, pProperties); 2893} 2894 2895void VKAPI loader_GetPhysicalDeviceFeatures( 2896 VkPhysicalDevice physicalDevice, 2897 VkPhysicalDeviceFeatures* pFeatures) 2898{ 2899 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice; 2900 struct loader_icd *icd = phys_dev->this_icd; 2901 2902 if (icd->GetPhysicalDeviceFeatures) 2903 icd->GetPhysicalDeviceFeatures(phys_dev->phys_dev, pFeatures); 2904} 2905 2906void VKAPI loader_GetPhysicalDeviceFormatProperties( 2907 VkPhysicalDevice physicalDevice, 2908 VkFormat format, 2909 VkFormatProperties* pFormatInfo) 2910{ 2911 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice; 2912 struct loader_icd *icd = phys_dev->this_icd; 2913 2914 if (icd->GetPhysicalDeviceFormatProperties) 2915 icd->GetPhysicalDeviceFormatProperties(phys_dev->phys_dev, format, pFormatInfo); 2916} 2917 2918VkResult VKAPI loader_GetPhysicalDeviceImageFormatProperties( 2919 VkPhysicalDevice physicalDevice, 2920 VkFormat format, 2921 VkImageType type, 2922 VkImageTiling tiling, 2923 VkImageUsageFlags usage, 2924 VkImageCreateFlags flags, 2925 VkImageFormatProperties* pImageFormatProperties) 2926{ 2927 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice; 2928 struct loader_icd *icd = phys_dev->this_icd; 2929 2930 if (!icd->GetPhysicalDeviceImageFormatProperties) 2931 return VK_ERROR_INITIALIZATION_FAILED; 2932 2933 return icd->GetPhysicalDeviceImageFormatProperties(phys_dev->phys_dev, format, 2934 type, tiling, usage, flags, pImageFormatProperties); 2935} 2936 2937void VKAPI loader_GetPhysicalDeviceSparseImageFormatProperties( 2938 VkPhysicalDevice physicalDevice, 2939 VkFormat format, 2940 VkImageType type, 2941 VkSampleCountFlagBits samples, 2942 VkImageUsageFlags usage, 2943 VkImageTiling tiling, 2944 uint32_t* pNumProperties, 2945 VkSparseImageFormatProperties* pProperties) 2946{ 2947 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice; 2948 struct loader_icd *icd = phys_dev->this_icd; 2949 2950 if (icd->GetPhysicalDeviceSparseImageFormatProperties) 2951 icd->GetPhysicalDeviceSparseImageFormatProperties(phys_dev->phys_dev, format, type, samples, usage, tiling, pNumProperties, pProperties); 2952} 2953 2954VkResult VKAPI loader_CreateDevice( 2955 VkPhysicalDevice physicalDevice, 2956 const VkDeviceCreateInfo* pCreateInfo, 2957 const VkAllocationCallbacks* pAllocator, 2958 VkDevice* pDevice) 2959{ 2960 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice; 2961 struct loader_icd *icd = phys_dev->this_icd; 2962 struct loader_device *dev; 2963 const struct loader_instance *inst; 2964 VkDeviceCreateInfo device_create_info; 2965 char **filtered_extension_names = NULL; 2966 VkResult res; 2967 2968 assert(pCreateInfo->requestedQueueCount >= 1); 2969 2970 if (!icd) 2971 return VK_ERROR_INITIALIZATION_FAILED; 2972 2973 inst = phys_dev->this_instance; 2974 2975 if (!icd->CreateDevice) { 2976 return VK_ERROR_INITIALIZATION_FAILED; 2977 } 2978 2979 /* validate any app enabled layers are available */ 2980 if (pCreateInfo->enabledLayerNameCount > 0) { 2981 res = loader_validate_layers(pCreateInfo->enabledLayerNameCount, 2982 pCreateInfo->ppEnabledLayerNames, 2983 &inst->device_layer_list); 2984 if (res != VK_SUCCESS) { 2985 return res; 2986 } 2987 } 2988 2989 /* Get the physical device extensions if they haven't been retrieved yet */ 2990 if (phys_dev->device_extension_cache.capacity == 0) { 2991 if (!loader_init_ext_list(inst, &phys_dev->device_extension_cache)) { 2992 return VK_ERROR_OUT_OF_HOST_MEMORY; 2993 } 2994 res = loader_add_physical_device_extensions( 2995 inst, physicalDevice, 2996 phys_dev->this_icd->this_icd_lib->lib_name, 2997 &phys_dev->device_extension_cache); 2998 if (res != VK_SUCCESS) { 2999 return res; 3000 } 3001 } 3002 /* make sure requested extensions to be enabled are supported */ 3003 res = loader_validate_device_extensions(phys_dev, &inst->device_layer_list, pCreateInfo); 3004 if (res != VK_SUCCESS) { 3005 return res; 3006 } 3007 3008 /* 3009 * NOTE: Need to filter the extensions to only those 3010 * supported by the ICD. 3011 * No ICD will advertise support for layers. An ICD 3012 * library could support a layer, but it would be 3013 * independent of the actual ICD, just in the same library. 3014 */ 3015 filtered_extension_names = loader_stack_alloc(pCreateInfo->enabledExtensionNameCount * sizeof(char *)); 3016 if (!filtered_extension_names) { 3017 return VK_ERROR_OUT_OF_HOST_MEMORY; 3018 } 3019 3020 /* Copy user's data */ 3021 memcpy(&device_create_info, pCreateInfo, sizeof(VkDeviceCreateInfo)); 3022 3023 /* ICD's do not use layers */ 3024 device_create_info.enabledLayerNameCount = 0; 3025 device_create_info.ppEnabledLayerNames = NULL; 3026 3027 device_create_info.enabledExtensionNameCount = 0; 3028 device_create_info.ppEnabledExtensionNames = (const char * const *) filtered_extension_names; 3029 3030 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) { 3031 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i]; 3032 VkExtensionProperties *prop = get_extension_property(extension_name, 3033 &phys_dev->device_extension_cache); 3034 if (prop) { 3035 filtered_extension_names[device_create_info.enabledExtensionNameCount] = (char *) extension_name; 3036 device_create_info.enabledExtensionNameCount++; 3037 } 3038 } 3039 3040 // since physicalDevice object maybe wrapped by a layer need to get unwrapped version 3041 // we haven't yet called down the chain for the layer to unwrap the object 3042 res = icd->CreateDevice(phys_dev->phys_dev, pCreateInfo, pAllocator, pDevice); 3043 if (res != VK_SUCCESS) { 3044 return res; 3045 } 3046 3047 dev = loader_add_logical_device(inst, *pDevice, &icd->logical_device_list); 3048 if (dev == NULL) { 3049 return VK_ERROR_OUT_OF_HOST_MEMORY; 3050 } 3051 PFN_vkGetDeviceProcAddr get_proc_addr = icd->GetDeviceProcAddr; 3052 loader_init_device_dispatch_table(&dev->loader_dispatch, get_proc_addr, 3053 *pDevice, *pDevice); 3054 3055 dev->loader_dispatch.CreateDevice = scratch_vkCreateDevice; 3056 loader_init_dispatch(*pDevice, &dev->loader_dispatch); 3057 3058 /* activate any layers on device chain which terminates with device*/ 3059 res = loader_enable_device_layers(inst, icd, dev, pCreateInfo, &inst->device_layer_list); 3060 if (res != VK_SUCCESS) { 3061 loader_destroy_logical_device(inst, dev); 3062 return res; 3063 } 3064 loader_activate_device_layers(inst, dev, *pDevice); 3065 3066 res = dev->loader_dispatch.CreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice); 3067 3068 dev->loader_dispatch.CreateDevice = icd->CreateDevice; 3069 3070 return res; 3071} 3072 3073/** 3074 * Get an instance level or global level entry point address. 3075 * @param instance 3076 * @param pName 3077 * @return 3078 * If instance == NULL returns a global level entrypoint for all core entry points 3079 * If instance is valid returns a instance relative entry point for instance level 3080 * entry points both core and extensions. 3081 * Instance relative means call down the instance chain. Global means trampoline entry points. 3082 */ 3083LOADER_EXPORT PFN_vkVoidFunction VKAPI vkGetInstanceProcAddr(VkInstance instance, const char * pName) 3084{ 3085 3086 void *addr; 3087 3088 if (instance == VK_NULL_HANDLE) { 3089 /* get entrypoint addresses that are global (in the loader), 3090 doesn't include any instance extensions since they may not be enabled yet*/ 3091 3092 addr = globalGetProcAddr(pName); 3093 3094 return addr; 3095 } 3096 3097 3098 /* return any instance entrypoints that must resolve to loader code */ 3099 addr = loader_non_passthrough_gipa(pName); 3100 if (addr) { 3101 return addr; 3102 } 3103 3104 /* debug_report is a special case; need to return loader trampoline entrypoints 3105 * unless the extension is not enabled; also need to handle debug_report 3106 * utility functions */ 3107 struct loader_instance *ptr_instance = loader_get_instance(instance); 3108 if (debug_report_instance_gpa(ptr_instance, pName, &addr)) { 3109 return addr; 3110 } 3111 3112 /* return the instance dispatch table entrypoint for core and extensions */ 3113 const VkLayerInstanceDispatchTable *disp_table = * (VkLayerInstanceDispatchTable **) instance; 3114 if (disp_table == NULL) 3115 return NULL; 3116 3117 addr = loader_lookup_instance_dispatch_table(disp_table, pName); 3118 if (addr) 3119 return addr; 3120 3121 // NOTE: any instance extensions must be known to loader and resolved 3122 // in the above call to loader_lookup_instance_dispatch_table()) 3123 return NULL; 3124} 3125 3126/** 3127 * Get a device level or global level entry point address. 3128 * @param device 3129 * @param pName 3130 * @return 3131 * If device == NULL, returns a global level entrypoint for all core entry points 3132 * If device is valid, returns a device relative entry point for device level 3133 * entry points both core and extensions. 3134 * Device relative means call down the device chain. Global means trampoline entry points. 3135 */ 3136LOADER_EXPORT PFN_vkVoidFunction VKAPI vkGetDeviceProcAddr(VkDevice device, const char * pName) 3137{ 3138 void *addr; 3139 3140 if (device == VK_NULL_HANDLE) { 3141 /* get entrypoint addresses that are global (in the loader)*/ 3142 addr = globalGetProcAddr(pName); 3143 return addr; 3144 } 3145 3146 3147 /* for entrypoints that loader must handle (ie non-dispatchable or create object) 3148 make sure the loader entrypoint is returned */ 3149 addr = loader_non_passthrough_gdpa(pName); 3150 if (addr) { 3151 return addr; 3152 } 3153 3154 /* return the dispatch table entrypoint for the fastest case */ 3155 const VkLayerDispatchTable *disp_table = * (VkLayerDispatchTable **) device; 3156 if (disp_table == NULL) 3157 return NULL; 3158 3159 addr = loader_lookup_device_dispatch_table(disp_table, pName); 3160 if (addr) 3161 return addr; 3162 else { 3163 if (disp_table->GetDeviceProcAddr == NULL) 3164 return NULL; 3165 return disp_table->GetDeviceProcAddr(device, pName); 3166 } 3167} 3168 3169LOADER_EXPORT VkResult VKAPI vkEnumerateInstanceExtensionProperties( 3170 const char* pLayerName, 3171 uint32_t* pPropertyCount, 3172 VkExtensionProperties* pProperties) 3173{ 3174 struct loader_extension_list *global_ext_list=NULL; 3175 struct loader_layer_list instance_layers; 3176 struct loader_extension_list icd_extensions; 3177 struct loader_icd_libs icd_libs; 3178 uint32_t copy_size; 3179 3180 tls_instance = NULL; 3181 memset(&icd_extensions, 0, sizeof(icd_extensions)); 3182 memset(&instance_layers, 0, sizeof(instance_layers)); 3183 loader_platform_thread_once(&once_init, loader_initialize); 3184 3185 /* get layer libraries if needed */ 3186 if (pLayerName && strlen(pLayerName) != 0) { 3187 loader_layer_scan(NULL, &instance_layers, NULL); 3188 for (uint32_t i = 0; i < instance_layers.count; i++) { 3189 struct loader_layer_properties *props = &instance_layers.list[i]; 3190 if (strcmp(props->info.layerName, pLayerName) == 0) { 3191 global_ext_list = &props->instance_extension_list; 3192 } 3193 } 3194 } 3195 else { 3196 /* Scan/discover all ICD libraries */ 3197 memset(&icd_libs, 0 , sizeof(struct loader_icd_libs)); 3198 loader_icd_scan(NULL, &icd_libs); 3199 /* get extensions from all ICD's, merge so no duplicates */ 3200 loader_get_icd_loader_instance_extensions(NULL, &icd_libs, &icd_extensions); 3201 loader_scanned_icd_clear(NULL, &icd_libs); 3202 global_ext_list = &icd_extensions; 3203 } 3204 3205 if (global_ext_list == NULL) { 3206 loader_destroy_layer_list(NULL, &instance_layers); 3207 return VK_ERROR_LAYER_NOT_PRESENT; 3208 } 3209 3210 if (pProperties == NULL) { 3211 *pPropertyCount = global_ext_list->count; 3212 loader_destroy_layer_list(NULL, &instance_layers); 3213 loader_destroy_ext_list(NULL, &icd_extensions); 3214 return VK_SUCCESS; 3215 } 3216 3217 copy_size = *pPropertyCount < global_ext_list->count ? *pPropertyCount : global_ext_list->count; 3218 for (uint32_t i = 0; i < copy_size; i++) { 3219 memcpy(&pProperties[i], 3220 &global_ext_list->list[i], 3221 sizeof(VkExtensionProperties)); 3222 } 3223 *pPropertyCount = copy_size; 3224 loader_destroy_ext_list(NULL, &icd_extensions); 3225 3226 if (copy_size < global_ext_list->count) { 3227 loader_destroy_layer_list(NULL, &instance_layers); 3228 return VK_INCOMPLETE; 3229 } 3230 3231 loader_destroy_layer_list(NULL, &instance_layers); 3232 return VK_SUCCESS; 3233} 3234 3235LOADER_EXPORT VkResult VKAPI vkEnumerateInstanceLayerProperties( 3236 uint32_t* pPropertyCount, 3237 VkLayerProperties* pProperties) 3238{ 3239 3240 struct loader_layer_list instance_layer_list; 3241 tls_instance = NULL; 3242 3243 loader_platform_thread_once(&once_init, loader_initialize); 3244 3245 uint32_t copy_size; 3246 3247 /* get layer libraries */ 3248 memset(&instance_layer_list, 0, sizeof(instance_layer_list)); 3249 loader_layer_scan(NULL, &instance_layer_list, NULL); 3250 3251 if (pProperties == NULL) { 3252 *pPropertyCount = instance_layer_list.count; 3253 loader_destroy_layer_list(NULL, &instance_layer_list); 3254 return VK_SUCCESS; 3255 } 3256 3257 copy_size = (*pPropertyCount < instance_layer_list.count) ? *pPropertyCount : instance_layer_list.count; 3258 for (uint32_t i = 0; i < copy_size; i++) { 3259 memcpy(&pProperties[i], &instance_layer_list.list[i].info, sizeof(VkLayerProperties)); 3260 } 3261 *pPropertyCount = copy_size; 3262 loader_destroy_layer_list(NULL, &instance_layer_list); 3263 3264 if (copy_size < instance_layer_list.count) { 3265 return VK_INCOMPLETE; 3266 } 3267 3268 return VK_SUCCESS; 3269} 3270 3271VkResult VKAPI loader_EnumerateDeviceExtensionProperties( 3272 VkPhysicalDevice physicalDevice, 3273 const char* pLayerName, 3274 uint32_t* pPropertyCount, 3275 VkExtensionProperties* pProperties) 3276{ 3277 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice; 3278 uint32_t copy_size; 3279 3280 uint32_t count; 3281 struct loader_extension_list *dev_ext_list=NULL; 3282 3283 /* get layer libraries if needed */ 3284 if (pLayerName && strlen(pLayerName) != 0) { 3285 for (uint32_t i = 0; i < phys_dev->this_instance->device_layer_list.count; i++) { 3286 struct loader_layer_properties *props = &phys_dev->this_instance->device_layer_list.list[i]; 3287 if (strcmp(props->info.layerName, pLayerName) == 0) { 3288 dev_ext_list = &props->device_extension_list; 3289 } 3290 } 3291 } 3292 else { 3293 /* this case is during the call down the instance chain */ 3294 struct loader_icd *icd = phys_dev->this_icd; 3295 VkResult res; 3296 res = icd->EnumerateDeviceExtensionProperties(phys_dev->phys_dev, NULL, pPropertyCount, pProperties); 3297 if (pProperties != NULL && res == VK_SUCCESS) { 3298 /* initialize dev_extension list within the physicalDevice object */ 3299 res = loader_init_physical_device_extensions(phys_dev->this_instance, 3300 phys_dev, *pPropertyCount, pProperties, 3301 &phys_dev->device_extension_cache); 3302 } 3303 return res; 3304 } 3305 3306 count = (dev_ext_list == NULL) ? 0: dev_ext_list->count; 3307 if (pProperties == NULL) { 3308 *pPropertyCount = count; 3309 return VK_SUCCESS; 3310 } 3311 3312 copy_size = *pPropertyCount < count ? *pPropertyCount : count; 3313 for (uint32_t i = 0; i < copy_size; i++) { 3314 memcpy(&pProperties[i], 3315 &dev_ext_list->list[i], 3316 sizeof(VkExtensionProperties)); 3317 } 3318 *pPropertyCount = copy_size; 3319 3320 if (copy_size < count) { 3321 return VK_INCOMPLETE; 3322 } 3323 3324 return VK_SUCCESS; 3325} 3326 3327VkResult VKAPI loader_EnumerateDeviceLayerProperties( 3328 VkPhysicalDevice physicalDevice, 3329 uint32_t* pPropertyCount, 3330 VkLayerProperties* pProperties) 3331{ 3332 uint32_t copy_size; 3333 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice; 3334 3335 uint32_t count = phys_dev->this_instance->device_layer_list.count; 3336 3337 if (pProperties == NULL) { 3338 *pPropertyCount = count; 3339 return VK_SUCCESS; 3340 } 3341 3342 copy_size = (*pPropertyCount < count) ? *pPropertyCount : count; 3343 for (uint32_t i = 0; i < copy_size; i++) { 3344 memcpy(&pProperties[i], &(phys_dev->this_instance->device_layer_list.list[i].info), sizeof(VkLayerProperties)); 3345 } 3346 *pPropertyCount = copy_size; 3347 3348 if (copy_size < count) { 3349 return VK_INCOMPLETE; 3350 } 3351 3352 return VK_SUCCESS; 3353} 3354