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