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