loader.c revision a867ee49907c70fcc8135547e17c14f034eccb3d
1/* 2 * 3 * Copyright (c) 2014-2016 The Khronos Group Inc. 4 * Copyright (c) 2014-2016 Valve Corporation 5 * Copyright (c) 2014-2016 LunarG, Inc. 6 * Copyright (C) 2015 Google Inc. 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a copy 9 * of this software and/or associated documentation files (the "Materials"), to 10 * deal in the Materials without restriction, including without limitation the 11 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 12 * sell copies of the Materials, and to permit persons to whom the Materials are 13 * furnished to do so, subject to the following conditions: 14 * 15 * The above copyright notice(s) and this permission notice shall be included in 16 * all copies or substantial portions of the Materials. 17 * 18 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 * 22 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 23 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 24 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE 25 * USE OR OTHER DEALINGS IN THE MATERIALS. 26 * 27 * Author: Jon Ashburn <jon@lunarg.com> 28 * Author: Courtney Goeltzenleuchter <courtney@LunarG.com> 29 * 30 */ 31 32#define _GNU_SOURCE 33#include <stdio.h> 34#include <stdlib.h> 35#include <stdarg.h> 36#include <stdbool.h> 37#include <string.h> 38 39#include <sys/types.h> 40#if defined(_WIN32) 41#include "dirent_on_windows.h" 42#else // _WIN32 43#include <dirent.h> 44#endif // _WIN32 45#include "vk_loader_platform.h" 46#include "loader.h" 47#include "gpa_helper.h" 48#include "table_ops.h" 49#include "debug_report.h" 50#include "wsi.h" 51#include "vulkan/vk_icd.h" 52#include "cJSON.h" 53#include "murmurhash.h" 54 55static loader_platform_dl_handle 56loader_add_layer_lib(const struct loader_instance *inst, const char *chain_type, 57 struct loader_layer_properties *layer_prop); 58 59static void loader_remove_layer_lib(struct loader_instance *inst, 60 struct loader_layer_properties *layer_prop); 61 62struct loader_struct loader = {0}; 63// TLS for instance for alloc/free callbacks 64THREAD_LOCAL_DECL struct loader_instance *tls_instance; 65 66static bool loader_init_generic_list(const struct loader_instance *inst, 67 struct loader_generic_list *list_info, 68 size_t element_size); 69 70static size_t loader_platform_combine_path(char *dest, size_t len, ...); 71 72struct loader_phys_dev_per_icd { 73 uint32_t count; 74 VkPhysicalDevice *phys_devs; 75}; 76 77enum loader_debug { 78 LOADER_INFO_BIT = 0x01, 79 LOADER_WARN_BIT = 0x02, 80 LOADER_PERF_BIT = 0x04, 81 LOADER_ERROR_BIT = 0x08, 82 LOADER_DEBUG_BIT = 0x10, 83}; 84 85uint32_t g_loader_debug = 0; 86uint32_t g_loader_log_msgs = 0; 87 88// thread safety lock for accessing global data structures such as "loader" 89// all entrypoints on the instance chain need to be locked except GPA 90// additionally CreateDevice and DestroyDevice needs to be locked 91loader_platform_thread_mutex loader_lock; 92loader_platform_thread_mutex loader_json_lock; 93 94const char *std_validation_str = "VK_LAYER_LUNARG_standard_validation"; 95 96// This table contains the loader's instance dispatch table, which contains 97// default functions if no instance layers are activated. This contains 98// pointers to "terminator functions". 99const VkLayerInstanceDispatchTable instance_disp = { 100 .GetInstanceProcAddr = vkGetInstanceProcAddr, 101 .DestroyInstance = loader_DestroyInstance, 102 .EnumeratePhysicalDevices = loader_EnumeratePhysicalDevices, 103 .GetPhysicalDeviceFeatures = loader_GetPhysicalDeviceFeatures, 104 .GetPhysicalDeviceFormatProperties = 105 loader_GetPhysicalDeviceFormatProperties, 106 .GetPhysicalDeviceImageFormatProperties = 107 loader_GetPhysicalDeviceImageFormatProperties, 108 .GetPhysicalDeviceProperties = loader_GetPhysicalDeviceProperties, 109 .GetPhysicalDeviceQueueFamilyProperties = 110 loader_GetPhysicalDeviceQueueFamilyProperties, 111 .GetPhysicalDeviceMemoryProperties = 112 loader_GetPhysicalDeviceMemoryProperties, 113 .EnumerateDeviceExtensionProperties = 114 loader_EnumerateDeviceExtensionProperties, 115 .EnumerateDeviceLayerProperties = loader_EnumerateDeviceLayerProperties, 116 .GetPhysicalDeviceSparseImageFormatProperties = 117 loader_GetPhysicalDeviceSparseImageFormatProperties, 118 .DestroySurfaceKHR = loader_DestroySurfaceKHR, 119 .GetPhysicalDeviceSurfaceSupportKHR = 120 loader_GetPhysicalDeviceSurfaceSupportKHR, 121 .GetPhysicalDeviceSurfaceCapabilitiesKHR = 122 loader_GetPhysicalDeviceSurfaceCapabilitiesKHR, 123 .GetPhysicalDeviceSurfaceFormatsKHR = 124 loader_GetPhysicalDeviceSurfaceFormatsKHR, 125 .GetPhysicalDeviceSurfacePresentModesKHR = 126 loader_GetPhysicalDeviceSurfacePresentModesKHR, 127 .CreateDebugReportCallbackEXT = loader_CreateDebugReportCallback, 128 .DestroyDebugReportCallbackEXT = loader_DestroyDebugReportCallback, 129 .DebugReportMessageEXT = loader_DebugReportMessage, 130#ifdef VK_USE_PLATFORM_MIR_KHR 131 .CreateMirSurfaceKHR = loader_CreateMirSurfaceKHR, 132 .GetPhysicalDeviceMirPresentationSupportKHR = 133 loader_GetPhysicalDeviceMirPresentationSupportKHR, 134#endif 135#ifdef VK_USE_PLATFORM_WAYLAND_KHR 136 .CreateWaylandSurfaceKHR = loader_CreateWaylandSurfaceKHR, 137 .GetPhysicalDeviceWaylandPresentationSupportKHR = 138 loader_GetPhysicalDeviceWaylandPresentationSupportKHR, 139#endif 140#ifdef VK_USE_PLATFORM_WIN32_KHR 141 .CreateWin32SurfaceKHR = loader_CreateWin32SurfaceKHR, 142 .GetPhysicalDeviceWin32PresentationSupportKHR = 143 loader_GetPhysicalDeviceWin32PresentationSupportKHR, 144#endif 145#ifdef VK_USE_PLATFORM_XCB_KHR 146 .CreateXcbSurfaceKHR = loader_CreateXcbSurfaceKHR, 147 .GetPhysicalDeviceXcbPresentationSupportKHR = 148 loader_GetPhysicalDeviceXcbPresentationSupportKHR, 149#endif 150#ifdef VK_USE_PLATFORM_XLIB_KHR 151 .CreateXlibSurfaceKHR = loader_CreateXlibSurfaceKHR, 152 .GetPhysicalDeviceXlibPresentationSupportKHR = 153 loader_GetPhysicalDeviceXlibPresentationSupportKHR, 154#endif 155#ifdef VK_USE_PLATFORM_ANDROID_KHR 156 .CreateAndroidSurfaceKHR = loader_CreateAndroidSurfaceKHR, 157#endif 158}; 159 160LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_init); 161 162void *loader_heap_alloc(const struct loader_instance *instance, size_t size, 163 VkSystemAllocationScope alloc_scope) { 164 if (instance && instance->alloc_callbacks.pfnAllocation) { 165 /* TODO: What should default alignment be? 1, 4, 8, other? */ 166 return instance->alloc_callbacks.pfnAllocation( 167 instance->alloc_callbacks.pUserData, size, sizeof(int), 168 alloc_scope); 169 } 170 return malloc(size); 171} 172 173void loader_heap_free(const struct loader_instance *instance, void *pMemory) { 174 if (pMemory == NULL) 175 return; 176 if (instance && instance->alloc_callbacks.pfnFree) { 177 instance->alloc_callbacks.pfnFree(instance->alloc_callbacks.pUserData, 178 pMemory); 179 return; 180 } 181 free(pMemory); 182} 183 184void *loader_heap_realloc(const struct loader_instance *instance, void *pMemory, 185 size_t orig_size, size_t size, 186 VkSystemAllocationScope alloc_scope) { 187 if (pMemory == NULL || orig_size == 0) 188 return loader_heap_alloc(instance, size, alloc_scope); 189 if (size == 0) { 190 loader_heap_free(instance, pMemory); 191 return NULL; 192 } 193 // TODO use the callback realloc function 194 if (instance && instance->alloc_callbacks.pfnAllocation) { 195 if (size <= orig_size) { 196 memset(((uint8_t *)pMemory) + size, 0, orig_size - size); 197 return pMemory; 198 } 199 /* TODO: What should default alignment be? 1, 4, 8, other? */ 200 void *new_ptr = instance->alloc_callbacks.pfnAllocation( 201 instance->alloc_callbacks.pUserData, size, sizeof(int), 202 alloc_scope); 203 if (!new_ptr) 204 return NULL; 205 memcpy(new_ptr, pMemory, orig_size); 206 instance->alloc_callbacks.pfnFree(instance->alloc_callbacks.pUserData, 207 pMemory); 208 return new_ptr; 209 } 210 return realloc(pMemory, size); 211} 212 213void *loader_tls_heap_alloc(size_t size) { 214 return loader_heap_alloc(tls_instance, size, 215 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 216} 217 218void loader_tls_heap_free(void *pMemory) { 219 loader_heap_free(tls_instance, pMemory); 220} 221 222void loader_log(const struct loader_instance *inst, VkFlags msg_type, 223 int32_t msg_code, const char *format, ...) { 224 char msg[512]; 225 va_list ap; 226 int ret; 227 228 va_start(ap, format); 229 ret = vsnprintf(msg, sizeof(msg), format, ap); 230 if ((ret >= (int)sizeof(msg)) || ret < 0) { 231 msg[sizeof(msg) - 1] = '\0'; 232 } 233 va_end(ap); 234 235 if (inst) { 236 util_DebugReportMessage(inst, msg_type, 237 VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, 238 (uint64_t)inst, 0, msg_code, "loader", msg); 239 } 240 241 if (!(msg_type & g_loader_log_msgs)) { 242 return; 243 } 244 245#if defined(WIN32) 246 OutputDebugString(msg); 247 OutputDebugString("\n"); 248#endif 249 fputs(msg, stderr); 250 fputc('\n', stderr); 251} 252 253#if defined(WIN32) 254static char *loader_get_next_path(char *path); 255/** 256* Find the list of registry files (names within a key) in key "location". 257* 258* This function looks in the registry (hive = DEFAULT_VK_REGISTRY_HIVE) key as 259*given in "location" 260* for a list or name/values which are added to a returned list (function return 261*value). 262* The DWORD values within the key must be 0 or they are skipped. 263* Function return is a string with a ';' separated list of filenames. 264* Function return is NULL if no valid name/value pairs are found in the key, 265* or the key is not found. 266* 267* \returns 268* A string list of filenames as pointer. 269* When done using the returned string list, pointer should be freed. 270*/ 271static char *loader_get_registry_files(const struct loader_instance *inst, 272 char *location) { 273 LONG rtn_value; 274 HKEY hive, key; 275 DWORD access_flags; 276 char name[2048]; 277 char *out = NULL; 278 char *loc = location; 279 char *next; 280 DWORD idx = 0; 281 DWORD name_size = sizeof(name); 282 DWORD value; 283 DWORD total_size = 4096; 284 DWORD value_size = sizeof(value); 285 286 while (*loc) { 287 next = loader_get_next_path(loc); 288 hive = DEFAULT_VK_REGISTRY_HIVE; 289 access_flags = KEY_QUERY_VALUE; 290 rtn_value = RegOpenKeyEx(hive, loc, 0, access_flags, &key); 291 if (rtn_value != ERROR_SUCCESS) { 292 // We still couldn't find the key, so give up: 293 loc = next; 294 continue; 295 } 296 297 while ((rtn_value = RegEnumValue(key, idx++, name, &name_size, NULL, 298 NULL, (LPBYTE)&value, &value_size)) == 299 ERROR_SUCCESS) { 300 if (value_size == sizeof(value) && value == 0) { 301 if (out == NULL) { 302 out = loader_heap_alloc( 303 inst, total_size, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 304 out[0] = '\0'; 305 } else if (strlen(out) + name_size + 1 > total_size) { 306 out = loader_heap_realloc( 307 inst, out, total_size, total_size * 2, 308 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 309 total_size *= 2; 310 } 311 if (out == NULL) { 312 loader_log( 313 inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 314 "Out of memory, failed loader_get_registry_files"); 315 return NULL; 316 } 317 if (strlen(out) == 0) 318 snprintf(out, name_size + 1, "%s", name); 319 else 320 snprintf(out + strlen(out), name_size + 2, "%c%s", 321 PATH_SEPERATOR, name); 322 } 323 name_size = 2048; 324 } 325 loc = next; 326 } 327 328 return out; 329} 330 331#endif // WIN32 332 333/** 334 * Combine path elements, separating each element with the platform-specific 335 * directory separator, and save the combined string to a destination buffer, 336 * not exceeding the given length. Path elements are given as variadic args, 337 * with a NULL element terminating the list. 338 * 339 * \returns the total length of the combined string, not including an ASCII 340 * NUL termination character. This length may exceed the available storage: 341 * in this case, the written string will be truncated to avoid a buffer 342 * overrun, and the return value will greater than or equal to the storage 343 * size. A NULL argument may be provided as the destination buffer in order 344 * to determine the required string length without actually writing a string. 345 */ 346 347static size_t loader_platform_combine_path(char *dest, size_t len, ...) { 348 size_t required_len = 0; 349 va_list ap; 350 const char *component; 351 352 va_start(ap, len); 353 354 while ((component = va_arg(ap, const char *))) { 355 if (required_len > 0) { 356 // This path element is not the first non-empty element; prepend 357 // a directory separator if space allows 358 if (dest && required_len + 1 < len) { 359 snprintf(dest + required_len, len - required_len, "%c", 360 DIRECTORY_SYMBOL); 361 } 362 required_len++; 363 } 364 365 if (dest && required_len < len) { 366 strncpy(dest + required_len, component, len - required_len); 367 } 368 required_len += strlen(component); 369 } 370 371 va_end(ap); 372 373 // strncpy(3) won't add a NUL terminating byte in the event of truncation. 374 if (dest && required_len >= len) { 375 dest[len - 1] = '\0'; 376 } 377 378 return required_len; 379} 380 381/** 382 * Given string of three part form "maj.min.pat" convert to a vulkan version 383 * number. 384 */ 385static uint32_t loader_make_version(const char *vers_str) { 386 uint32_t vers = 0, major = 0, minor = 0, patch = 0; 387 char *minor_str = NULL; 388 char *patch_str = NULL; 389 char *cstr; 390 char *str; 391 392 if (!vers_str) 393 return vers; 394 cstr = loader_stack_alloc(strlen(vers_str) + 1); 395 strcpy(cstr, vers_str); 396 while ((str = strchr(cstr, '.')) != NULL) { 397 if (minor_str == NULL) { 398 minor_str = str + 1; 399 *str = '\0'; 400 major = atoi(cstr); 401 } else if (patch_str == NULL) { 402 patch_str = str + 1; 403 *str = '\0'; 404 minor = atoi(minor_str); 405 } else { 406 return vers; 407 } 408 cstr = str + 1; 409 } 410 patch = atoi(patch_str); 411 412 return VK_MAKE_VERSION(major, minor, patch); 413} 414 415bool compare_vk_extension_properties(const VkExtensionProperties *op1, 416 const VkExtensionProperties *op2) { 417 return strcmp(op1->extensionName, op2->extensionName) == 0 ? true : false; 418} 419 420/** 421 * Search the given ext_array for an extension 422 * matching the given vk_ext_prop 423 */ 424bool has_vk_extension_property_array(const VkExtensionProperties *vk_ext_prop, 425 const uint32_t count, 426 const VkExtensionProperties *ext_array) { 427 for (uint32_t i = 0; i < count; i++) { 428 if (compare_vk_extension_properties(vk_ext_prop, &ext_array[i])) 429 return true; 430 } 431 return false; 432} 433 434/** 435 * Search the given ext_list for an extension 436 * matching the given vk_ext_prop 437 */ 438bool has_vk_extension_property(const VkExtensionProperties *vk_ext_prop, 439 const struct loader_extension_list *ext_list) { 440 for (uint32_t i = 0; i < ext_list->count; i++) { 441 if (compare_vk_extension_properties(&ext_list->list[i], vk_ext_prop)) 442 return true; 443 } 444 return false; 445} 446 447static inline bool loader_is_layer_type_device(const enum layer_type type) { 448 if ((type & VK_LAYER_TYPE_DEVICE_EXPLICIT) || 449 (type & VK_LAYER_TYPE_DEVICE_IMPLICIT)) 450 return true; 451 return false; 452} 453 454/* 455 * Search the given layer list for a layer matching the given layer name 456 */ 457static struct loader_layer_properties * 458loader_get_layer_property(const char *name, 459 const struct loader_layer_list *layer_list) { 460 for (uint32_t i = 0; i < layer_list->count; i++) { 461 const VkLayerProperties *item = &layer_list->list[i].info; 462 if (strcmp(name, item->layerName) == 0) 463 return &layer_list->list[i]; 464 } 465 return NULL; 466} 467 468/** 469 * Get the next unused layer property in the list. Init the property to zero. 470 */ 471static struct loader_layer_properties * 472loader_get_next_layer_property(const struct loader_instance *inst, 473 struct loader_layer_list *layer_list) { 474 if (layer_list->capacity == 0) { 475 layer_list->list = 476 loader_heap_alloc(inst, sizeof(struct loader_layer_properties) * 64, 477 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 478 if (layer_list->list == NULL) { 479 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 480 "Out of memory can't add any layer properties to list"); 481 return NULL; 482 } 483 memset(layer_list->list, 0, 484 sizeof(struct loader_layer_properties) * 64); 485 layer_list->capacity = sizeof(struct loader_layer_properties) * 64; 486 } 487 488 // ensure enough room to add an entry 489 if ((layer_list->count + 1) * sizeof(struct loader_layer_properties) > 490 layer_list->capacity) { 491 layer_list->list = loader_heap_realloc( 492 inst, layer_list->list, layer_list->capacity, 493 layer_list->capacity * 2, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 494 if (layer_list->list == NULL) { 495 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 496 "realloc failed for layer list"); 497 } 498 layer_list->capacity *= 2; 499 } 500 501 layer_list->count++; 502 return &(layer_list->list[layer_list->count - 1]); 503} 504 505/** 506 * Remove all layer properties entrys from the list 507 */ 508void loader_delete_layer_properties(const struct loader_instance *inst, 509 struct loader_layer_list *layer_list) { 510 uint32_t i, j; 511 struct loader_device_extension_list *dev_ext_list; 512 if (!layer_list) 513 return; 514 515 for (i = 0; i < layer_list->count; i++) { 516 loader_destroy_generic_list( 517 inst, (struct loader_generic_list *)&layer_list->list[i] 518 .instance_extension_list); 519 dev_ext_list = &layer_list->list[i].device_extension_list; 520 if (dev_ext_list->capacity > 0 && 521 dev_ext_list->list->entrypoint_count > 0) { 522 for (j = 0; j < dev_ext_list->list->entrypoint_count; j++) { 523 loader_heap_free(inst, dev_ext_list->list->entrypoints[j]); 524 } 525 loader_heap_free(inst, dev_ext_list->list->entrypoints); 526 } 527 loader_destroy_generic_list(inst, 528 (struct loader_generic_list *)dev_ext_list); 529 } 530 layer_list->count = 0; 531 532 if (layer_list->capacity > 0) { 533 layer_list->capacity = 0; 534 loader_heap_free(inst, layer_list->list); 535 } 536} 537 538static void loader_add_instance_extensions( 539 const struct loader_instance *inst, 540 const PFN_vkEnumerateInstanceExtensionProperties fp_get_props, 541 const char *lib_name, struct loader_extension_list *ext_list) { 542 uint32_t i, count = 0; 543 VkExtensionProperties *ext_props; 544 VkResult res; 545 546 if (!fp_get_props) { 547 /* No EnumerateInstanceExtensionProperties defined */ 548 return; 549 } 550 551 res = fp_get_props(NULL, &count, NULL); 552 if (res != VK_SUCCESS) { 553 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 554 "Error getting Instance extension count from %s", lib_name); 555 return; 556 } 557 558 if (count == 0) { 559 /* No ExtensionProperties to report */ 560 return; 561 } 562 563 ext_props = loader_stack_alloc(count * sizeof(VkExtensionProperties)); 564 565 res = fp_get_props(NULL, &count, ext_props); 566 if (res != VK_SUCCESS) { 567 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 568 "Error getting Instance extensions from %s", lib_name); 569 return; 570 } 571 572 for (i = 0; i < count; i++) { 573 char spec_version[64]; 574 575 snprintf(spec_version, sizeof(spec_version), "%d.%d.%d", 576 VK_MAJOR(ext_props[i].specVersion), 577 VK_MINOR(ext_props[i].specVersion), 578 VK_PATCH(ext_props[i].specVersion)); 579 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, 580 "Instance Extension: %s (%s) version %s", 581 ext_props[i].extensionName, lib_name, spec_version); 582 loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]); 583 } 584 585 return; 586} 587 588/* 589 * Initialize ext_list with the physical device extensions. 590 * The extension properties are passed as inputs in count and ext_props. 591 */ 592static VkResult 593loader_init_device_extensions(const struct loader_instance *inst, 594 struct loader_physical_device *phys_dev, 595 uint32_t count, VkExtensionProperties *ext_props, 596 struct loader_extension_list *ext_list) { 597 VkResult res; 598 uint32_t i; 599 600 if (!loader_init_generic_list(inst, (struct loader_generic_list *)ext_list, 601 sizeof(VkExtensionProperties))) { 602 return VK_ERROR_OUT_OF_HOST_MEMORY; 603 } 604 605 for (i = 0; i < count; i++) { 606 char spec_version[64]; 607 608 snprintf(spec_version, sizeof(spec_version), "%d.%d.%d", 609 VK_MAJOR(ext_props[i].specVersion), 610 VK_MINOR(ext_props[i].specVersion), 611 VK_PATCH(ext_props[i].specVersion)); 612 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, 613 "Device Extension: %s (%s) version %s", 614 ext_props[i].extensionName, 615 phys_dev->this_icd->this_icd_lib->lib_name, spec_version); 616 res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]); 617 if (res != VK_SUCCESS) 618 return res; 619 } 620 621 return VK_SUCCESS; 622} 623 624static VkResult loader_add_device_extensions( 625 const struct loader_instance *inst, struct loader_icd *icd, 626 VkPhysicalDevice physical_device, const char *lib_name, 627 struct loader_extension_list *ext_list) { 628 uint32_t i, count; 629 VkResult res; 630 VkExtensionProperties *ext_props; 631 632 res = icd->EnumerateDeviceExtensionProperties(physical_device, NULL, &count, 633 NULL); 634 if (res == VK_SUCCESS && count > 0) { 635 ext_props = loader_stack_alloc(count * sizeof(VkExtensionProperties)); 636 if (!ext_props) 637 return VK_ERROR_OUT_OF_HOST_MEMORY; 638 res = icd->EnumerateDeviceExtensionProperties(physical_device, NULL, 639 &count, ext_props); 640 if (res != VK_SUCCESS) 641 return res; 642 for (i = 0; i < count; i++) { 643 char spec_version[64]; 644 645 snprintf(spec_version, sizeof(spec_version), "%d.%d.%d", 646 VK_MAJOR(ext_props[i].specVersion), 647 VK_MINOR(ext_props[i].specVersion), 648 VK_PATCH(ext_props[i].specVersion)); 649 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, 650 "Device Extension: %s (%s) version %s", 651 ext_props[i].extensionName, lib_name, spec_version); 652 res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]); 653 if (res != VK_SUCCESS) 654 return res; 655 } 656 } else { 657 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 658 "Error getting physical device extension info count from " 659 "library %s", 660 lib_name); 661 return res; 662 } 663 664 return VK_SUCCESS; 665} 666 667static bool loader_init_generic_list(const struct loader_instance *inst, 668 struct loader_generic_list *list_info, 669 size_t element_size) { 670 list_info->capacity = 32 * element_size; 671 list_info->list = loader_heap_alloc(inst, list_info->capacity, 672 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 673 if (list_info->list == NULL) { 674 return false; 675 } 676 memset(list_info->list, 0, list_info->capacity); 677 list_info->count = 0; 678 return true; 679} 680 681void loader_destroy_generic_list(const struct loader_instance *inst, 682 struct loader_generic_list *list) { 683 loader_heap_free(inst, list->list); 684 list->count = 0; 685 list->capacity = 0; 686} 687 688/* 689 * Append non-duplicate extension properties defined in props 690 * to the given ext_list. 691 * Return 692 * Vk_SUCCESS on success 693 */ 694VkResult loader_add_to_ext_list(const struct loader_instance *inst, 695 struct loader_extension_list *ext_list, 696 uint32_t prop_list_count, 697 const VkExtensionProperties *props) { 698 uint32_t i; 699 const VkExtensionProperties *cur_ext; 700 701 if (ext_list->list == NULL || ext_list->capacity == 0) { 702 loader_init_generic_list(inst, (struct loader_generic_list *)ext_list, 703 sizeof(VkExtensionProperties)); 704 } 705 706 if (ext_list->list == NULL) 707 return VK_ERROR_OUT_OF_HOST_MEMORY; 708 709 for (i = 0; i < prop_list_count; i++) { 710 cur_ext = &props[i]; 711 712 // look for duplicates 713 if (has_vk_extension_property(cur_ext, ext_list)) { 714 continue; 715 } 716 717 // add to list at end 718 // check for enough capacity 719 if (ext_list->count * sizeof(VkExtensionProperties) >= 720 ext_list->capacity) { 721 722 ext_list->list = loader_heap_realloc( 723 inst, ext_list->list, ext_list->capacity, 724 ext_list->capacity * 2, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 725 726 if (ext_list->list == NULL) 727 return VK_ERROR_OUT_OF_HOST_MEMORY; 728 729 // double capacity 730 ext_list->capacity *= 2; 731 } 732 733 memcpy(&ext_list->list[ext_list->count], cur_ext, 734 sizeof(VkExtensionProperties)); 735 ext_list->count++; 736 } 737 return VK_SUCCESS; 738} 739 740/* 741 * Append one extension property defined in props with entrypoints 742 * defined in entrys to the given ext_list. 743 * Return 744 * Vk_SUCCESS on success 745 */ 746VkResult 747loader_add_to_dev_ext_list(const struct loader_instance *inst, 748 struct loader_device_extension_list *ext_list, 749 const VkExtensionProperties *props, 750 uint32_t entry_count, char **entrys) { 751 uint32_t idx; 752 if (ext_list->list == NULL || ext_list->capacity == 0) { 753 loader_init_generic_list(inst, (struct loader_generic_list *)ext_list, 754 sizeof(struct loader_dev_ext_props)); 755 } 756 757 if (ext_list->list == NULL) 758 return VK_ERROR_OUT_OF_HOST_MEMORY; 759 760 idx = ext_list->count; 761 // add to list at end 762 // check for enough capacity 763 if (idx * sizeof(struct loader_dev_ext_props) >= ext_list->capacity) { 764 765 ext_list->list = loader_heap_realloc( 766 inst, ext_list->list, ext_list->capacity, ext_list->capacity * 2, 767 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 768 769 if (ext_list->list == NULL) 770 return VK_ERROR_OUT_OF_HOST_MEMORY; 771 772 // double capacity 773 ext_list->capacity *= 2; 774 } 775 776 memcpy(&ext_list->list[idx].props, props, 777 sizeof(struct loader_dev_ext_props)); 778 ext_list->list[idx].entrypoint_count = entry_count; 779 ext_list->list[idx].entrypoints = 780 loader_heap_alloc(inst, sizeof(char *) * entry_count, 781 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 782 if (ext_list->list[idx].entrypoints == NULL) 783 return VK_ERROR_OUT_OF_HOST_MEMORY; 784 for (uint32_t i = 0; i < entry_count; i++) { 785 ext_list->list[idx].entrypoints[i] = loader_heap_alloc( 786 inst, strlen(entrys[i]) + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 787 if (ext_list->list[idx].entrypoints[i] == NULL) 788 return VK_ERROR_OUT_OF_HOST_MEMORY; 789 strcpy(ext_list->list[idx].entrypoints[i], entrys[i]); 790 } 791 ext_list->count++; 792 793 return VK_SUCCESS; 794} 795 796/** 797 * Search the given search_list for any layers in the props list. 798 * Add these to the output layer_list. Don't add duplicates to the output 799 * layer_list. 800 */ 801static VkResult 802loader_add_layer_names_to_list(const struct loader_instance *inst, 803 struct loader_layer_list *output_list, 804 uint32_t name_count, const char *const *names, 805 const struct loader_layer_list *search_list) { 806 struct loader_layer_properties *layer_prop; 807 VkResult err = VK_SUCCESS; 808 809 for (uint32_t i = 0; i < name_count; i++) { 810 const char *search_target = names[i]; 811 layer_prop = loader_get_layer_property(search_target, search_list); 812 if (!layer_prop) { 813 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 814 "Unable to find layer %s", search_target); 815 err = VK_ERROR_LAYER_NOT_PRESENT; 816 continue; 817 } 818 819 loader_add_to_layer_list(inst, output_list, 1, layer_prop); 820 } 821 822 return err; 823} 824 825/* 826 * Manage lists of VkLayerProperties 827 */ 828static bool loader_init_layer_list(const struct loader_instance *inst, 829 struct loader_layer_list *list) { 830 list->capacity = 32 * sizeof(struct loader_layer_properties); 831 list->list = loader_heap_alloc(inst, list->capacity, 832 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 833 if (list->list == NULL) { 834 return false; 835 } 836 memset(list->list, 0, list->capacity); 837 list->count = 0; 838 return true; 839} 840 841void loader_destroy_layer_list(const struct loader_instance *inst, 842 struct loader_layer_list *layer_list) { 843 loader_heap_free(inst, layer_list->list); 844 layer_list->count = 0; 845 layer_list->capacity = 0; 846} 847 848/* 849 * Manage list of layer libraries (loader_lib_info) 850 */ 851static bool 852loader_init_layer_library_list(const struct loader_instance *inst, 853 struct loader_layer_library_list *list) { 854 list->capacity = 32 * sizeof(struct loader_lib_info); 855 list->list = loader_heap_alloc(inst, list->capacity, 856 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 857 if (list->list == NULL) { 858 return false; 859 } 860 memset(list->list, 0, list->capacity); 861 list->count = 0; 862 return true; 863} 864 865void loader_destroy_layer_library_list(const struct loader_instance *inst, 866 struct loader_layer_library_list *list) { 867 for (uint32_t i = 0; i < list->count; i++) { 868 loader_heap_free(inst, list->list[i].lib_name); 869 } 870 loader_heap_free(inst, list->list); 871 list->count = 0; 872 list->capacity = 0; 873} 874 875void loader_add_to_layer_library_list(const struct loader_instance *inst, 876 struct loader_layer_library_list *list, 877 uint32_t item_count, 878 const struct loader_lib_info *new_items) { 879 uint32_t i; 880 struct loader_lib_info *item; 881 882 if (list->list == NULL || list->capacity == 0) { 883 loader_init_layer_library_list(inst, list); 884 } 885 886 if (list->list == NULL) 887 return; 888 889 for (i = 0; i < item_count; i++) { 890 item = (struct loader_lib_info *)&new_items[i]; 891 892 // look for duplicates 893 for (uint32_t j = 0; j < list->count; j++) { 894 if (strcmp(list->list[i].lib_name, new_items->lib_name) == 0) { 895 continue; 896 } 897 } 898 899 // add to list at end 900 // check for enough capacity 901 if (list->count * sizeof(struct loader_lib_info) >= list->capacity) { 902 903 list->list = loader_heap_realloc( 904 inst, list->list, list->capacity, list->capacity * 2, 905 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 906 // double capacity 907 list->capacity *= 2; 908 } 909 910 memcpy(&list->list[list->count], item, sizeof(struct loader_lib_info)); 911 list->count++; 912 } 913} 914 915/* 916 * Search the given layer list for a list 917 * matching the given VkLayerProperties 918 */ 919bool has_vk_layer_property(const VkLayerProperties *vk_layer_prop, 920 const struct loader_layer_list *list) { 921 for (uint32_t i = 0; i < list->count; i++) { 922 if (strcmp(vk_layer_prop->layerName, list->list[i].info.layerName) == 0) 923 return true; 924 } 925 return false; 926} 927 928/* 929 * Search the given layer list for a layer 930 * matching the given name 931 */ 932bool has_layer_name(const char *name, const struct loader_layer_list *list) { 933 for (uint32_t i = 0; i < list->count; i++) { 934 if (strcmp(name, list->list[i].info.layerName) == 0) 935 return true; 936 } 937 return false; 938} 939 940/* 941 * Append non-duplicate layer properties defined in prop_list 942 * to the given layer_info list 943 */ 944void loader_add_to_layer_list(const struct loader_instance *inst, 945 struct loader_layer_list *list, 946 uint32_t prop_list_count, 947 const struct loader_layer_properties *props) { 948 uint32_t i; 949 struct loader_layer_properties *layer; 950 951 if (list->list == NULL || list->capacity == 0) { 952 loader_init_layer_list(inst, list); 953 } 954 955 if (list->list == NULL) 956 return; 957 958 for (i = 0; i < prop_list_count; i++) { 959 layer = (struct loader_layer_properties *)&props[i]; 960 961 // look for duplicates 962 if (has_vk_layer_property(&layer->info, list)) { 963 continue; 964 } 965 966 // add to list at end 967 // check for enough capacity 968 if (list->count * sizeof(struct loader_layer_properties) >= 969 list->capacity) { 970 971 list->list = loader_heap_realloc( 972 inst, list->list, list->capacity, list->capacity * 2, 973 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 974 // double capacity 975 list->capacity *= 2; 976 } 977 978 memcpy(&list->list[list->count], layer, 979 sizeof(struct loader_layer_properties)); 980 list->count++; 981 } 982} 983 984/** 985 * Search the search_list for any layer with a name 986 * that matches the given name and a type that matches the given type 987 * Add all matching layers to the found_list 988 * Do not add if found loader_layer_properties is already 989 * on the found_list. 990 */ 991static void 992loader_find_layer_name_add_list(const struct loader_instance *inst, 993 const char *name, const enum layer_type type, 994 const struct loader_layer_list *search_list, 995 struct loader_layer_list *found_list) { 996 bool found = false; 997 for (uint32_t i = 0; i < search_list->count; i++) { 998 struct loader_layer_properties *layer_prop = &search_list->list[i]; 999 if (0 == strcmp(layer_prop->info.layerName, name) && 1000 (layer_prop->type & type)) { 1001 /* Found a layer with the same name, add to found_list */ 1002 loader_add_to_layer_list(inst, found_list, 1, layer_prop); 1003 found = true; 1004 } 1005 } 1006 if (!found) { 1007 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 1008 "Warning, couldn't find layer name %s to activate", name); 1009 } 1010} 1011 1012static VkExtensionProperties * 1013get_extension_property(const char *name, 1014 const struct loader_extension_list *list) { 1015 for (uint32_t i = 0; i < list->count; i++) { 1016 if (strcmp(name, list->list[i].extensionName) == 0) 1017 return &list->list[i]; 1018 } 1019 return NULL; 1020} 1021 1022static VkExtensionProperties * 1023get_dev_extension_property(const char *name, 1024 const struct loader_device_extension_list *list) { 1025 for (uint32_t i = 0; i < list->count; i++) { 1026 if (strcmp(name, list->list[i].props.extensionName) == 0) 1027 return &list->list[i].props; 1028 } 1029 return NULL; 1030} 1031 1032/* 1033 * This function will return the pNext pointer of any 1034 * CreateInfo extensions that are not loader extensions. 1035 * This is used to skip past the loader extensions prepended 1036 * to the list during CreateInstance and CreateDevice. 1037 */ 1038void *loader_strip_create_extensions(const void *pNext) { 1039 VkLayerInstanceCreateInfo *create_info = (VkLayerInstanceCreateInfo *)pNext; 1040 1041 while ( 1042 create_info && 1043 (create_info->sType == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO || 1044 create_info->sType == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO)) { 1045 create_info = (VkLayerInstanceCreateInfo *)create_info->pNext; 1046 } 1047 1048 return create_info; 1049} 1050 1051/* 1052 * For Instance extensions implemented within the loader (i.e. DEBUG_REPORT 1053 * the extension must provide two entry points for the loader to use: 1054 * - "trampoline" entry point - this is the address returned by GetProcAddr 1055 * and will always do what's necessary to support a global call. 1056 * - "terminator" function - this function will be put at the end of the 1057 * instance chain and will contain the necessary logic to call / process 1058 * the extension for the appropriate ICDs that are available. 1059 * There is no generic mechanism for including these functions, the references 1060 * must be placed into the appropriate loader entry points. 1061 * GetInstanceProcAddr: call extension GetInstanceProcAddr to check for 1062 * GetProcAddr requests 1063 * loader_coalesce_extensions(void) - add extension records to the list of 1064 * global 1065 * extension available to the app. 1066 * instance_disp - add function pointer for terminator function to this array. 1067 * The extension itself should be in a separate file that will be 1068 * linked directly with the loader. 1069 */ 1070 1071void loader_get_icd_loader_instance_extensions( 1072 const struct loader_instance *inst, struct loader_icd_libs *icd_libs, 1073 struct loader_extension_list *inst_exts) { 1074 struct loader_extension_list icd_exts; 1075 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, 1076 "Build ICD instance extension list"); 1077 // traverse scanned icd list adding non-duplicate extensions to the list 1078 for (uint32_t i = 0; i < icd_libs->count; i++) { 1079 loader_init_generic_list(inst, (struct loader_generic_list *)&icd_exts, 1080 sizeof(VkExtensionProperties)); 1081 loader_add_instance_extensions( 1082 inst, icd_libs->list[i].EnumerateInstanceExtensionProperties, 1083 icd_libs->list[i].lib_name, &icd_exts); 1084 loader_add_to_ext_list(inst, inst_exts, icd_exts.count, icd_exts.list); 1085 loader_destroy_generic_list(inst, 1086 (struct loader_generic_list *)&icd_exts); 1087 }; 1088 1089 // Traverse loader's extensions, adding non-duplicate extensions to the list 1090 wsi_add_instance_extensions(inst, inst_exts); 1091 debug_report_add_instance_extensions(inst, inst_exts); 1092} 1093 1094struct loader_physical_device * 1095loader_get_physical_device(const VkPhysicalDevice physdev) { 1096 uint32_t i; 1097 for (struct loader_instance *inst = loader.instances; inst; 1098 inst = inst->next) { 1099 for (i = 0; i < inst->total_gpu_count; i++) { 1100 // TODO this aliases physDevices within instances, need for this 1101 // function to go away 1102 if (inst->phys_devs[i].disp == 1103 loader_get_instance_dispatch(physdev)) { 1104 return &inst->phys_devs[i]; 1105 } 1106 } 1107 } 1108 return NULL; 1109} 1110 1111struct loader_icd *loader_get_icd_and_device(const VkDevice device, 1112 struct loader_device **found_dev) { 1113 *found_dev = NULL; 1114 for (struct loader_instance *inst = loader.instances; inst; 1115 inst = inst->next) { 1116 for (struct loader_icd *icd = inst->icds; icd; icd = icd->next) { 1117 for (struct loader_device *dev = icd->logical_device_list; dev; 1118 dev = dev->next) 1119 /* Value comparison of device prevents object wrapping by layers 1120 */ 1121 if (loader_get_dispatch(dev->device) == 1122 loader_get_dispatch(device)) { 1123 *found_dev = dev; 1124 return icd; 1125 } 1126 } 1127 } 1128 return NULL; 1129} 1130 1131static void loader_destroy_logical_device(const struct loader_instance *inst, 1132 struct loader_device *dev) { 1133 loader_heap_free(inst, dev->app_extension_props); 1134 loader_destroy_layer_list(inst, &dev->activated_layer_list); 1135 loader_heap_free(inst, dev); 1136} 1137 1138static struct loader_device * 1139loader_add_logical_device(const struct loader_instance *inst, 1140 struct loader_device **device_list) { 1141 struct loader_device *new_dev; 1142 1143 new_dev = loader_heap_alloc(inst, sizeof(struct loader_device), 1144 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); 1145 if (!new_dev) { 1146 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 1147 "Failed to alloc struct loader-device"); 1148 return NULL; 1149 } 1150 1151 memset(new_dev, 0, sizeof(struct loader_device)); 1152 1153 new_dev->next = *device_list; 1154 *device_list = new_dev; 1155 return new_dev; 1156} 1157 1158void loader_remove_logical_device(const struct loader_instance *inst, 1159 struct loader_icd *icd, 1160 struct loader_device *found_dev) { 1161 struct loader_device *dev, *prev_dev; 1162 1163 if (!icd || !found_dev) 1164 return; 1165 1166 prev_dev = NULL; 1167 dev = icd->logical_device_list; 1168 while (dev && dev != found_dev) { 1169 prev_dev = dev; 1170 dev = dev->next; 1171 } 1172 1173 if (prev_dev) 1174 prev_dev->next = found_dev->next; 1175 else 1176 icd->logical_device_list = found_dev->next; 1177 loader_destroy_logical_device(inst, found_dev); 1178} 1179 1180static void loader_icd_destroy(struct loader_instance *ptr_inst, 1181 struct loader_icd *icd) { 1182 ptr_inst->total_icd_count--; 1183 for (struct loader_device *dev = icd->logical_device_list; dev;) { 1184 struct loader_device *next_dev = dev->next; 1185 loader_destroy_logical_device(ptr_inst, dev); 1186 dev = next_dev; 1187 } 1188 1189 loader_heap_free(ptr_inst, icd); 1190} 1191 1192static struct loader_icd * 1193loader_icd_create(const struct loader_instance *inst) { 1194 struct loader_icd *icd; 1195 1196 icd = loader_heap_alloc(inst, sizeof(*icd), 1197 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1198 if (!icd) 1199 return NULL; 1200 1201 memset(icd, 0, sizeof(*icd)); 1202 1203 return icd; 1204} 1205 1206static struct loader_icd * 1207loader_icd_add(struct loader_instance *ptr_inst, 1208 const struct loader_scanned_icds *icd_lib) { 1209 struct loader_icd *icd; 1210 1211 icd = loader_icd_create(ptr_inst); 1212 if (!icd) 1213 return NULL; 1214 1215 icd->this_icd_lib = icd_lib; 1216 icd->this_instance = ptr_inst; 1217 1218 /* prepend to the list */ 1219 icd->next = ptr_inst->icds; 1220 ptr_inst->icds = icd; 1221 ptr_inst->total_icd_count++; 1222 1223 return icd; 1224} 1225 1226void loader_scanned_icd_clear(const struct loader_instance *inst, 1227 struct loader_icd_libs *icd_libs) { 1228 if (icd_libs->capacity == 0) 1229 return; 1230 for (uint32_t i = 0; i < icd_libs->count; i++) { 1231 loader_platform_close_library(icd_libs->list[i].handle); 1232 loader_heap_free(inst, icd_libs->list[i].lib_name); 1233 } 1234 loader_heap_free(inst, icd_libs->list); 1235 icd_libs->capacity = 0; 1236 icd_libs->count = 0; 1237 icd_libs->list = NULL; 1238} 1239 1240static void loader_scanned_icd_init(const struct loader_instance *inst, 1241 struct loader_icd_libs *icd_libs) { 1242 loader_scanned_icd_clear(inst, icd_libs); 1243 icd_libs->capacity = 8 * sizeof(struct loader_scanned_icds); 1244 icd_libs->list = loader_heap_alloc(inst, icd_libs->capacity, 1245 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1246} 1247 1248static void loader_scanned_icd_add(const struct loader_instance *inst, 1249 struct loader_icd_libs *icd_libs, 1250 const char *filename, uint32_t api_version) { 1251 loader_platform_dl_handle handle; 1252 PFN_vkCreateInstance fp_create_inst; 1253 PFN_vkEnumerateInstanceExtensionProperties fp_get_inst_ext_props; 1254 PFN_vkGetInstanceProcAddr fp_get_proc_addr; 1255 struct loader_scanned_icds *new_node; 1256 1257 /* TODO implement ref counting of libraries, for now this function leaves 1258 libraries open and the scanned_icd_clear closes them */ 1259 // Used to call: dlopen(filename, RTLD_LAZY); 1260 handle = loader_platform_open_library(filename); 1261 if (!handle) { 1262 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 1263 loader_platform_open_library_error(filename)); 1264 return; 1265 } 1266 1267 fp_get_proc_addr = 1268 loader_platform_get_proc_address(handle, "vk_icdGetInstanceProcAddr"); 1269 if (!fp_get_proc_addr) { 1270 // Use deprecated interface 1271 fp_get_proc_addr = 1272 loader_platform_get_proc_address(handle, "vkGetInstanceProcAddr"); 1273 if (!fp_get_proc_addr) { 1274 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 1275 loader_platform_get_proc_address_error( 1276 "vk_icdGetInstanceProcAddr")); 1277 return; 1278 } else { 1279 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 1280 "Using deprecated ICD interface of " 1281 "vkGetInstanceProcAddr instead of " 1282 "vk_icdGetInstanceProcAddr"); 1283 } 1284 fp_create_inst = 1285 loader_platform_get_proc_address(handle, "vkCreateInstance"); 1286 if (!fp_create_inst) { 1287 loader_log( 1288 inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 1289 "Couldn't get vkCreateInstance via dlsym/loadlibrary from ICD"); 1290 return; 1291 } 1292 fp_get_inst_ext_props = loader_platform_get_proc_address( 1293 handle, "vkEnumerateInstanceExtensionProperties"); 1294 if (!fp_get_inst_ext_props) { 1295 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 1296 "Couldn't get vkEnumerateInstanceExtensionProperties " 1297 "via dlsym/loadlibrary from ICD"); 1298 return; 1299 } 1300 } else { 1301 // Use newer interface 1302 fp_create_inst = 1303 (PFN_vkCreateInstance)fp_get_proc_addr(NULL, "vkCreateInstance"); 1304 if (!fp_create_inst) { 1305 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 1306 "Couldn't get vkCreateInstance via " 1307 "vk_icdGetInstanceProcAddr from ICD"); 1308 return; 1309 } 1310 fp_get_inst_ext_props = 1311 (PFN_vkEnumerateInstanceExtensionProperties)fp_get_proc_addr( 1312 NULL, "vkEnumerateInstanceExtensionProperties"); 1313 if (!fp_get_inst_ext_props) { 1314 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 1315 "Couldn't get vkEnumerateInstanceExtensionProperties " 1316 "via vk_icdGetInstanceProcAddr from ICD"); 1317 return; 1318 } 1319 } 1320 1321 // check for enough capacity 1322 if ((icd_libs->count * sizeof(struct loader_scanned_icds)) >= 1323 icd_libs->capacity) { 1324 1325 icd_libs->list = loader_heap_realloc( 1326 inst, icd_libs->list, icd_libs->capacity, icd_libs->capacity * 2, 1327 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1328 // double capacity 1329 icd_libs->capacity *= 2; 1330 } 1331 new_node = &(icd_libs->list[icd_libs->count]); 1332 1333 new_node->handle = handle; 1334 new_node->api_version = api_version; 1335 new_node->GetInstanceProcAddr = fp_get_proc_addr; 1336 new_node->EnumerateInstanceExtensionProperties = fp_get_inst_ext_props; 1337 new_node->CreateInstance = fp_create_inst; 1338 1339 new_node->lib_name = (char *)loader_heap_alloc( 1340 inst, strlen(filename) + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1341 if (!new_node->lib_name) { 1342 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 1343 "Out of memory can't add icd"); 1344 return; 1345 } 1346 strcpy(new_node->lib_name, filename); 1347 icd_libs->count++; 1348} 1349 1350static bool loader_icd_init_entrys(struct loader_icd *icd, VkInstance inst, 1351 const PFN_vkGetInstanceProcAddr fp_gipa) { 1352/* initialize entrypoint function pointers */ 1353 1354#define LOOKUP_GIPA(func, required) \ 1355 do { \ 1356 icd->func = (PFN_vk##func)fp_gipa(inst, "vk" #func); \ 1357 if (!icd->func && required) { \ 1358 loader_log((struct loader_instance *)inst, \ 1359 VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, \ 1360 loader_platform_get_proc_address_error("vk" #func)); \ 1361 return false; \ 1362 } \ 1363 } while (0) 1364 1365 LOOKUP_GIPA(GetDeviceProcAddr, true); 1366 LOOKUP_GIPA(DestroyInstance, true); 1367 LOOKUP_GIPA(EnumeratePhysicalDevices, true); 1368 LOOKUP_GIPA(GetPhysicalDeviceFeatures, true); 1369 LOOKUP_GIPA(GetPhysicalDeviceFormatProperties, true); 1370 LOOKUP_GIPA(GetPhysicalDeviceImageFormatProperties, true); 1371 LOOKUP_GIPA(CreateDevice, true); 1372 LOOKUP_GIPA(GetPhysicalDeviceProperties, true); 1373 LOOKUP_GIPA(GetPhysicalDeviceMemoryProperties, true); 1374 LOOKUP_GIPA(GetPhysicalDeviceQueueFamilyProperties, true); 1375 LOOKUP_GIPA(EnumerateDeviceExtensionProperties, true); 1376 LOOKUP_GIPA(GetPhysicalDeviceSparseImageFormatProperties, true); 1377 LOOKUP_GIPA(CreateDebugReportCallbackEXT, false); 1378 LOOKUP_GIPA(DestroyDebugReportCallbackEXT, false); 1379 LOOKUP_GIPA(GetPhysicalDeviceSurfaceSupportKHR, false); 1380 LOOKUP_GIPA(GetPhysicalDeviceSurfaceCapabilitiesKHR, false); 1381 LOOKUP_GIPA(GetPhysicalDeviceSurfaceFormatsKHR, false); 1382 LOOKUP_GIPA(GetPhysicalDeviceSurfacePresentModesKHR, false); 1383#ifdef VK_USE_PLATFORM_WIN32_KHR 1384 LOOKUP_GIPA(GetPhysicalDeviceWin32PresentationSupportKHR, false); 1385#endif 1386#ifdef VK_USE_PLATFORM_XCB_KHR 1387 LOOKUP_GIPA(GetPhysicalDeviceXcbPresentationSupportKHR, false); 1388#endif 1389 1390#undef LOOKUP_GIPA 1391 1392 return true; 1393} 1394 1395static void loader_debug_init(void) { 1396 const char *env, *orig; 1397 1398 if (g_loader_debug > 0) 1399 return; 1400 1401 g_loader_debug = 0; 1402 1403 /* parse comma-separated debug options */ 1404 orig = env = loader_getenv("VK_LOADER_DEBUG"); 1405 while (env) { 1406 const char *p = strchr(env, ','); 1407 size_t len; 1408 1409 if (p) 1410 len = p - env; 1411 else 1412 len = strlen(env); 1413 1414 if (len > 0) { 1415 if (strncmp(env, "all", len) == 0) { 1416 g_loader_debug = ~0u; 1417 g_loader_log_msgs = ~0u; 1418 } else if (strncmp(env, "warn", len) == 0) { 1419 g_loader_debug |= LOADER_WARN_BIT; 1420 g_loader_log_msgs |= VK_DEBUG_REPORT_WARNING_BIT_EXT; 1421 } else if (strncmp(env, "info", len) == 0) { 1422 g_loader_debug |= LOADER_INFO_BIT; 1423 g_loader_log_msgs |= VK_DEBUG_REPORT_INFORMATION_BIT_EXT; 1424 } else if (strncmp(env, "perf", len) == 0) { 1425 g_loader_debug |= LOADER_PERF_BIT; 1426 g_loader_log_msgs |= VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT; 1427 } else if (strncmp(env, "error", len) == 0) { 1428 g_loader_debug |= LOADER_ERROR_BIT; 1429 g_loader_log_msgs |= VK_DEBUG_REPORT_ERROR_BIT_EXT; 1430 } else if (strncmp(env, "debug", len) == 0) { 1431 g_loader_debug |= LOADER_DEBUG_BIT; 1432 g_loader_log_msgs |= VK_DEBUG_REPORT_DEBUG_BIT_EXT; 1433 } 1434 } 1435 1436 if (!p) 1437 break; 1438 1439 env = p + 1; 1440 } 1441 1442 loader_free_getenv(orig); 1443} 1444 1445void loader_initialize(void) { 1446 // initialize mutexs 1447 loader_platform_thread_create_mutex(&loader_lock); 1448 loader_platform_thread_create_mutex(&loader_json_lock); 1449 1450 // initialize logging 1451 loader_debug_init(); 1452 1453 // initial cJSON to use alloc callbacks 1454 cJSON_Hooks alloc_fns = { 1455 .malloc_fn = loader_tls_heap_alloc, .free_fn = loader_tls_heap_free, 1456 }; 1457 cJSON_InitHooks(&alloc_fns); 1458} 1459 1460struct loader_manifest_files { 1461 uint32_t count; 1462 char **filename_list; 1463}; 1464 1465/** 1466 * Get next file or dirname given a string list or registry key path 1467 * 1468 * \returns 1469 * A pointer to first char in the next path. 1470 * The next path (or NULL) in the list is returned in next_path. 1471 * Note: input string is modified in some cases. PASS IN A COPY! 1472 */ 1473static char *loader_get_next_path(char *path) { 1474 uint32_t len; 1475 char *next; 1476 1477 if (path == NULL) 1478 return NULL; 1479 next = strchr(path, PATH_SEPERATOR); 1480 if (next == NULL) { 1481 len = (uint32_t)strlen(path); 1482 next = path + len; 1483 } else { 1484 *next = '\0'; 1485 next++; 1486 } 1487 1488 return next; 1489} 1490 1491/** 1492 * Given a path which is absolute or relative, expand the path if relative or 1493 * leave the path unmodified if absolute. The base path to prepend to relative 1494 * paths is given in rel_base. 1495 * 1496 * \returns 1497 * A string in out_fullpath of the full absolute path 1498 */ 1499static void loader_expand_path(const char *path, const char *rel_base, 1500 size_t out_size, char *out_fullpath) { 1501 if (loader_platform_is_path_absolute(path)) { 1502 // do not prepend a base to an absolute path 1503 rel_base = ""; 1504 } 1505 1506 loader_platform_combine_path(out_fullpath, out_size, rel_base, path, NULL); 1507} 1508 1509/** 1510 * Given a filename (file) and a list of paths (dir), try to find an existing 1511 * file in the paths. If filename already is a path then no 1512 * searching in the given paths. 1513 * 1514 * \returns 1515 * A string in out_fullpath of either the full path or file. 1516 */ 1517static void loader_get_fullpath(const char *file, const char *dirs, 1518 size_t out_size, char *out_fullpath) { 1519 if (!loader_platform_is_path(file) && *dirs) { 1520 char *dirs_copy, *dir, *next_dir; 1521 1522 dirs_copy = loader_stack_alloc(strlen(dirs) + 1); 1523 strcpy(dirs_copy, dirs); 1524 1525 // find if file exists after prepending paths in given list 1526 for (dir = dirs_copy; *dir && (next_dir = loader_get_next_path(dir)); 1527 dir = next_dir) { 1528 loader_platform_combine_path(out_fullpath, out_size, dir, file, 1529 NULL); 1530 if (loader_platform_file_exists(out_fullpath)) { 1531 return; 1532 } 1533 } 1534 } 1535 1536 snprintf(out_fullpath, out_size, "%s", file); 1537} 1538 1539/** 1540 * Read a JSON file into a buffer. 1541 * 1542 * \returns 1543 * A pointer to a cJSON object representing the JSON parse tree. 1544 * This returned buffer should be freed by caller. 1545 */ 1546static cJSON *loader_get_json(const struct loader_instance *inst, 1547 const char *filename) { 1548 FILE *file; 1549 char *json_buf; 1550 cJSON *json; 1551 size_t len; 1552 file = fopen(filename, "rb"); 1553 if (!file) { 1554 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 1555 "Couldn't open JSON file %s", filename); 1556 return NULL; 1557 } 1558 fseek(file, 0, SEEK_END); 1559 len = ftell(file); 1560 fseek(file, 0, SEEK_SET); 1561 json_buf = (char *)loader_stack_alloc(len + 1); 1562 if (json_buf == NULL) { 1563 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 1564 "Out of memory can't get JSON file"); 1565 fclose(file); 1566 return NULL; 1567 } 1568 if (fread(json_buf, sizeof(char), len, file) != len) { 1569 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 1570 "fread failed can't get JSON file"); 1571 fclose(file); 1572 return NULL; 1573 } 1574 fclose(file); 1575 json_buf[len] = '\0'; 1576 1577 // parse text from file 1578 json = cJSON_Parse(json_buf); 1579 if (json == NULL) 1580 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 1581 "Can't parse JSON file %s", filename); 1582 return json; 1583} 1584 1585/** 1586 * Do a deep copy of the loader_layer_properties structure. 1587 */ 1588static void loader_copy_layer_properties(const struct loader_instance *inst, 1589 struct loader_layer_properties *dst, 1590 struct loader_layer_properties *src) { 1591 uint32_t cnt, i; 1592 memcpy(dst, src, sizeof(*src)); 1593 dst->instance_extension_list.list = 1594 loader_heap_alloc(inst, sizeof(VkExtensionProperties) * 1595 src->instance_extension_list.count, 1596 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1597 dst->instance_extension_list.capacity = 1598 sizeof(VkExtensionProperties) * src->instance_extension_list.count; 1599 memcpy(dst->instance_extension_list.list, src->instance_extension_list.list, 1600 dst->instance_extension_list.capacity); 1601 dst->device_extension_list.list = 1602 loader_heap_alloc(inst, sizeof(struct loader_dev_ext_props) * 1603 src->device_extension_list.count, 1604 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1605 1606 dst->device_extension_list.capacity = 1607 sizeof(struct loader_dev_ext_props) * src->device_extension_list.count; 1608 memcpy(dst->device_extension_list.list, src->device_extension_list.list, 1609 dst->device_extension_list.capacity); 1610 if (src->device_extension_list.count > 0 && 1611 src->device_extension_list.list->entrypoint_count > 0) { 1612 cnt = src->device_extension_list.list->entrypoint_count; 1613 dst->device_extension_list.list->entrypoints = loader_heap_alloc( 1614 inst, sizeof(char *) * cnt, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1615 for (i = 0; i < cnt; i++) { 1616 dst->device_extension_list.list->entrypoints[i] = loader_heap_alloc( 1617 inst, 1618 strlen(src->device_extension_list.list->entrypoints[i]) + 1, 1619 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1620 strcpy(dst->device_extension_list.list->entrypoints[i], 1621 src->device_extension_list.list->entrypoints[i]); 1622 } 1623 } 1624} 1625 1626static bool 1627loader_find_layer_name_list(const char *name, 1628 const struct loader_layer_list *layer_list) { 1629 if (!layer_list) 1630 return false; 1631 for (uint32_t j = 0; j < layer_list->count; j++) 1632 if (!strcmp(name, layer_list->list[j].info.layerName)) 1633 return true; 1634 return false; 1635} 1636 1637static bool loader_find_layer_name(const char *name, uint32_t layer_count, 1638 const char **layer_list) { 1639 if (!layer_list) 1640 return false; 1641 for (uint32_t j = 0; j < layer_count; j++) 1642 if (!strcmp(name, layer_list[j])) 1643 return true; 1644 return false; 1645} 1646 1647static bool loader_find_layer_name_array( 1648 const char *name, uint32_t layer_count, 1649 const char layer_list[][VK_MAX_EXTENSION_NAME_SIZE]) { 1650 if (!layer_list) 1651 return false; 1652 for (uint32_t j = 0; j < layer_count; j++) 1653 if (!strcmp(name, layer_list[j])) 1654 return true; 1655 return false; 1656} 1657 1658/** 1659 * Searches through an array of layer names (ppp_layer_names) looking for a 1660 * layer key_name. 1661 * If not found then simply returns updating nothing. 1662 * Otherwise, it uses expand_count, expand_names adding them to layer names. 1663 * Any duplicate (pre-existing) exapand_names in layer names are removed. 1664 * Expand names are added to the back/end of the list of layer names. 1665 * @param inst 1666 * @param layer_count 1667 * @param ppp_layer_names 1668 */ 1669void loader_expand_layer_names( 1670 const struct loader_instance *inst, const char *key_name, 1671 uint32_t expand_count, 1672 const char expand_names[][VK_MAX_EXTENSION_NAME_SIZE], 1673 uint32_t *layer_count, char ***ppp_layer_names) { 1674 char **pp_layer_names, **pp_src_layers = *ppp_layer_names; 1675 1676 if (!loader_find_layer_name(key_name, *layer_count, 1677 (const char **)pp_src_layers)) 1678 return; // didn't find the key_name in the list 1679 1680 // since the total number of layers may expand, allocate new memory for the 1681 // array of pointers 1682 pp_layer_names = 1683 loader_heap_alloc(inst, (expand_count + *layer_count) * sizeof(char *), 1684 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 1685 1686 loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, 1687 "Found meta layer %s, replacing with actual layer group", 1688 key_name); 1689 // In place removal of any expand_names found in layer_name (remove 1690 // duplicates) 1691 // Also remove the key_name 1692 uint32_t src_idx, dst_idx, cnt = *layer_count; 1693 for (src_idx = 0; src_idx < *layer_count; src_idx++) { 1694 if (loader_find_layer_name_array(pp_src_layers[src_idx], expand_count, 1695 expand_names)) { 1696 pp_src_layers[src_idx] = NULL; 1697 cnt--; 1698 } else if (!strcmp(pp_src_layers[src_idx], key_name)) { 1699 pp_src_layers[src_idx] = NULL; 1700 cnt--; 1701 } 1702 pp_layer_names[src_idx] = pp_src_layers[src_idx]; 1703 } 1704 for (dst_idx = 0; dst_idx < cnt; dst_idx++) { 1705 if (pp_layer_names[dst_idx] == NULL) { 1706 src_idx = dst_idx + 1; 1707 while (src_idx < *layer_count && pp_src_layers[src_idx] == NULL) 1708 src_idx++; 1709 if (src_idx < *layer_count && pp_src_layers[src_idx] != NULL) 1710 pp_layer_names[dst_idx] = pp_src_layers[src_idx]; 1711 } 1712 } 1713 1714 // Add the expand_names to layer_names 1715 src_idx = 0; 1716 for (dst_idx = cnt; dst_idx < cnt + expand_count; dst_idx++) { 1717 pp_layer_names[dst_idx] = (char *)&expand_names[src_idx++][0]; 1718 } 1719 *layer_count = expand_count + cnt; 1720 *ppp_layer_names = pp_layer_names; 1721 return; 1722} 1723 1724/** 1725 * Restores the layer name list and count into the pCreatInfo structure. 1726 * If is_device == tru then pCreateInfo is a device structure else an instance 1727 * structure. 1728 * @param layer_count 1729 * @param layer_names 1730 * @param pCreateInfo 1731 */ 1732void loader_unexpand_dev_layer_names(const struct loader_instance *inst, 1733 uint32_t layer_count, char **layer_names, 1734 char **layer_ptr, 1735 const VkDeviceCreateInfo *pCreateInfo) { 1736 uint32_t *p_cnt = (uint32_t *)&pCreateInfo->enabledLayerCount; 1737 *p_cnt = layer_count; 1738 1739 char ***p_ptr = (char ***)&pCreateInfo->ppEnabledLayerNames; 1740 if ((char **)pCreateInfo->ppEnabledLayerNames != layer_ptr) 1741 loader_heap_free(inst, (void *)pCreateInfo->ppEnabledLayerNames); 1742 *p_ptr = layer_ptr; 1743 for (uint32_t i = 0; i < layer_count; i++) { 1744 char **pp_str = (char **)&pCreateInfo->ppEnabledLayerNames[i]; 1745 *pp_str = layer_names[i]; 1746 } 1747} 1748 1749void loader_unexpand_inst_layer_names(const struct loader_instance *inst, 1750 uint32_t layer_count, char **layer_names, 1751 char **layer_ptr, 1752 const VkInstanceCreateInfo *pCreateInfo) { 1753 uint32_t *p_cnt = (uint32_t *)&pCreateInfo->enabledLayerCount; 1754 *p_cnt = layer_count; 1755 1756 char ***p_ptr = (char ***)&pCreateInfo->ppEnabledLayerNames; 1757 if ((char **)pCreateInfo->ppEnabledLayerNames != layer_ptr) 1758 loader_heap_free(inst, (void *)pCreateInfo->ppEnabledLayerNames); 1759 *p_ptr = layer_ptr; 1760 for (uint32_t i = 0; i < layer_count; i++) { 1761 char **pp_str = (char **)&pCreateInfo->ppEnabledLayerNames[i]; 1762 *pp_str = layer_names[i]; 1763 } 1764} 1765 1766/** 1767 * Searches through the existing instance and device layer lists looking for 1768 * the set of required layer names. If found then it adds a meta property to the 1769 * layer list. 1770 * Assumes the required layers are the same for both instance and device lists. 1771 * @param inst 1772 * @param layer_count number of layers in layer_names 1773 * @param layer_names array of required layer names 1774 * @param layer_instance_list 1775 * @param layer_device_list 1776 */ 1777static void loader_add_layer_property_meta( 1778 const struct loader_instance *inst, uint32_t layer_count, 1779 const char layer_names[][VK_MAX_EXTENSION_NAME_SIZE], 1780 struct loader_layer_list *layer_instance_list, 1781 struct loader_layer_list *layer_device_list) { 1782 uint32_t i, j; 1783 bool found; 1784 struct loader_layer_list *layer_list; 1785 1786 if (0 == layer_count || 1787 NULL == layer_instance_list || 1788 NULL == layer_device_list || 1789 (layer_count > layer_instance_list->count && 1790 layer_count > layer_device_list->count)) 1791 return; 1792 1793 for (j = 0; j < 2; j++) { 1794 if (j == 0) 1795 layer_list = layer_instance_list; 1796 else 1797 layer_list = layer_device_list; 1798 found = true; 1799 for (i = 0; i < layer_count; i++) { 1800 if (loader_find_layer_name_list(layer_names[i], layer_list)) 1801 continue; 1802 found = false; 1803 break; 1804 } 1805 1806 struct loader_layer_properties *props; 1807 if (found) { 1808 props = loader_get_next_layer_property(inst, layer_list); 1809 props->type = VK_LAYER_TYPE_META_EXPLICT; 1810 strncpy(props->info.description, "LunarG Standard Validation Layer", 1811 sizeof(props->info.description)); 1812 props->info.implementationVersion = 1; 1813 strncpy(props->info.layerName, std_validation_str, 1814 sizeof(props->info.layerName)); 1815 // TODO what about specVersion? for now insert loader's built 1816 // version 1817 props->info.specVersion = VK_API_VERSION; 1818 } 1819 } 1820} 1821 1822/** 1823 * Given a cJSON struct (json) of the top level JSON object from layer manifest 1824 * file, add entry to the layer_list. 1825 * Fill out the layer_properties in this list entry from the input cJSON object. 1826 * 1827 * \returns 1828 * void 1829 * layer_list has a new entry and initialized accordingly. 1830 * If the json input object does not have all the required fields no entry 1831 * is added to the list. 1832 */ 1833static void 1834loader_add_layer_properties(const struct loader_instance *inst, 1835 struct loader_layer_list *layer_instance_list, 1836 struct loader_layer_list *layer_device_list, 1837 cJSON *json, bool is_implicit, char *filename) { 1838 /* Fields in layer manifest file that are required: 1839 * (required) “file_format_version” 1840 * following are required in the "layer" object: 1841 * (required) "name" 1842 * (required) "type" 1843 * (required) “library_path” 1844 * (required) “api_version” 1845 * (required) “implementation_version” 1846 * (required) “description” 1847 * (required for implicit layers) “disable_environment” 1848 * 1849 * First get all required items and if any missing abort 1850 */ 1851 1852 cJSON *item, *layer_node, *ext_item; 1853 char *temp; 1854 char *name, *type, *library_path, *api_version; 1855 char *implementation_version, *description; 1856 cJSON *disable_environment; 1857 int i, j; 1858 VkExtensionProperties ext_prop; 1859 item = cJSON_GetObjectItem(json, "file_format_version"); 1860 if (item == NULL) { 1861 return; 1862 } 1863 char *file_vers = cJSON_PrintUnformatted(item); 1864 loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, 1865 "Found manifest file %s, version %s", filename, file_vers); 1866 if (strcmp(file_vers, "\"1.0.0\"") != 0) 1867 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 1868 "Unexpected manifest file version (expected 1.0.0), may " 1869 "cause errors"); 1870 loader_tls_heap_free(file_vers); 1871 1872 layer_node = cJSON_GetObjectItem(json, "layer"); 1873 if (layer_node == NULL) { 1874 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 1875 "Can't find \"layer\" object in manifest JSON file, " 1876 "skipping this file"); 1877 return; 1878 } 1879 1880 // loop through all "layer" objects in the file 1881 do { 1882#define GET_JSON_OBJECT(node, var) \ 1883 { \ 1884 var = cJSON_GetObjectItem(node, #var); \ 1885 if (var == NULL) { \ 1886 layer_node = layer_node->next; \ 1887 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, \ 1888 "Didn't find required layer object %s in manifest " \ 1889 "JSON file, skipping this layer", \ 1890 #var); \ 1891 continue; \ 1892 } \ 1893 } 1894#define GET_JSON_ITEM(node, var) \ 1895 { \ 1896 item = cJSON_GetObjectItem(node, #var); \ 1897 if (item == NULL) { \ 1898 layer_node = layer_node->next; \ 1899 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, \ 1900 "Didn't find required layer value %s in manifest JSON " \ 1901 "file, skipping this layer", \ 1902 #var); \ 1903 continue; \ 1904 } \ 1905 temp = cJSON_Print(item); \ 1906 temp[strlen(temp) - 1] = '\0'; \ 1907 var = loader_stack_alloc(strlen(temp) + 1); \ 1908 strcpy(var, &temp[1]); \ 1909 loader_tls_heap_free(temp); \ 1910 } 1911 GET_JSON_ITEM(layer_node, name) 1912 GET_JSON_ITEM(layer_node, type) 1913 GET_JSON_ITEM(layer_node, library_path) 1914 GET_JSON_ITEM(layer_node, api_version) 1915 GET_JSON_ITEM(layer_node, implementation_version) 1916 GET_JSON_ITEM(layer_node, description) 1917 if (is_implicit) { 1918 GET_JSON_OBJECT(layer_node, disable_environment) 1919 } 1920#undef GET_JSON_ITEM 1921#undef GET_JSON_OBJECT 1922 1923 // add list entry 1924 struct loader_layer_properties *props = NULL; 1925 if (!strcmp(type, "DEVICE")) { 1926 if (layer_device_list == NULL) { 1927 layer_node = layer_node->next; 1928 continue; 1929 } 1930 props = loader_get_next_layer_property(inst, layer_device_list); 1931 props->type = (is_implicit) ? VK_LAYER_TYPE_DEVICE_IMPLICIT 1932 : VK_LAYER_TYPE_DEVICE_EXPLICIT; 1933 } 1934 if (!strcmp(type, "INSTANCE")) { 1935 if (layer_instance_list == NULL) { 1936 layer_node = layer_node->next; 1937 continue; 1938 } 1939 props = loader_get_next_layer_property(inst, layer_instance_list); 1940 props->type = (is_implicit) ? VK_LAYER_TYPE_INSTANCE_IMPLICIT 1941 : VK_LAYER_TYPE_INSTANCE_EXPLICIT; 1942 } 1943 if (!strcmp(type, "GLOBAL")) { 1944 if (layer_instance_list != NULL) 1945 props = 1946 loader_get_next_layer_property(inst, layer_instance_list); 1947 else if (layer_device_list != NULL) 1948 props = loader_get_next_layer_property(inst, layer_device_list); 1949 else { 1950 layer_node = layer_node->next; 1951 continue; 1952 } 1953 props->type = (is_implicit) ? VK_LAYER_TYPE_GLOBAL_IMPLICIT 1954 : VK_LAYER_TYPE_GLOBAL_EXPLICIT; 1955 } 1956 1957 if (props == NULL) { 1958 layer_node = layer_node->next; 1959 continue; 1960 } 1961 1962 strncpy(props->info.layerName, name, sizeof(props->info.layerName)); 1963 props->info.layerName[sizeof(props->info.layerName) - 1] = '\0'; 1964 1965 char *fullpath = props->lib_name; 1966 char *rel_base; 1967 if (loader_platform_is_path(library_path)) { 1968 // a relative or absolute path 1969 char *name_copy = loader_stack_alloc(strlen(filename) + 1); 1970 strcpy(name_copy, filename); 1971 rel_base = loader_platform_dirname(name_copy); 1972 loader_expand_path(library_path, rel_base, MAX_STRING_SIZE, 1973 fullpath); 1974 } else { 1975 // a filename which is assumed in a system directory 1976 loader_get_fullpath(library_path, DEFAULT_VK_LAYERS_PATH, 1977 MAX_STRING_SIZE, fullpath); 1978 } 1979 props->info.specVersion = loader_make_version(api_version); 1980 props->info.implementationVersion = atoi(implementation_version); 1981 strncpy((char *)props->info.description, description, 1982 sizeof(props->info.description)); 1983 props->info.description[sizeof(props->info.description) - 1] = '\0'; 1984 if (is_implicit) { 1985 if (!disable_environment || !disable_environment->child) { 1986 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 1987 "Didn't find required layer child value disable_environment" 1988 "in manifest JSON file, skipping this layer"); 1989 layer_node = layer_node->next; 1990 continue; 1991 } 1992 strncpy(props->disable_env_var.name, 1993 disable_environment->child->string, 1994 sizeof(props->disable_env_var.name)); 1995 props->disable_env_var 1996 .name[sizeof(props->disable_env_var.name) - 1] = '\0'; 1997 strncpy(props->disable_env_var.value, 1998 disable_environment->child->valuestring, 1999 sizeof(props->disable_env_var.value)); 2000 props->disable_env_var 2001 .value[sizeof(props->disable_env_var.value) - 1] = '\0'; 2002 } 2003 2004/** 2005 * Now get all optional items and objects and put in list: 2006 * functions 2007 * instance_extensions 2008 * device_extensions 2009 * enable_environment (implicit layers only) 2010 */ 2011#define GET_JSON_OBJECT(node, var) \ 2012 { var = cJSON_GetObjectItem(node, #var); } 2013#define GET_JSON_ITEM(node, var) \ 2014 { \ 2015 item = cJSON_GetObjectItem(node, #var); \ 2016 if (item != NULL) { \ 2017 temp = cJSON_Print(item); \ 2018 temp[strlen(temp) - 1] = '\0'; \ 2019 var = loader_stack_alloc(strlen(temp) + 1); \ 2020 strcpy(var, &temp[1]); \ 2021 loader_tls_heap_free(temp); \ 2022 } \ 2023 } 2024 2025 cJSON *instance_extensions, *device_extensions, *functions, 2026 *enable_environment; 2027 cJSON *entrypoints; 2028 char *vkGetInstanceProcAddr, *vkGetDeviceProcAddr, *spec_version; 2029 char **entry_array; 2030 vkGetInstanceProcAddr = NULL; 2031 vkGetDeviceProcAddr = NULL; 2032 spec_version = NULL; 2033 entrypoints = NULL; 2034 entry_array = NULL; 2035 /** 2036 * functions 2037 * vkGetInstanceProcAddr 2038 * vkGetDeviceProcAddr 2039 */ 2040 GET_JSON_OBJECT(layer_node, functions) 2041 if (functions != NULL) { 2042 GET_JSON_ITEM(functions, vkGetInstanceProcAddr) 2043 GET_JSON_ITEM(functions, vkGetDeviceProcAddr) 2044 if (vkGetInstanceProcAddr != NULL) 2045 strncpy(props->functions.str_gipa, vkGetInstanceProcAddr, 2046 sizeof(props->functions.str_gipa)); 2047 props->functions.str_gipa[sizeof(props->functions.str_gipa) - 1] = 2048 '\0'; 2049 if (vkGetDeviceProcAddr != NULL) 2050 strncpy(props->functions.str_gdpa, vkGetDeviceProcAddr, 2051 sizeof(props->functions.str_gdpa)); 2052 props->functions.str_gdpa[sizeof(props->functions.str_gdpa) - 1] = 2053 '\0'; 2054 } 2055 /** 2056 * instance_extensions 2057 * array of 2058 * name 2059 * spec_version 2060 */ 2061 GET_JSON_OBJECT(layer_node, instance_extensions) 2062 if (instance_extensions != NULL) { 2063 int count = cJSON_GetArraySize(instance_extensions); 2064 for (i = 0; i < count; i++) { 2065 ext_item = cJSON_GetArrayItem(instance_extensions, i); 2066 GET_JSON_ITEM(ext_item, name) 2067 GET_JSON_ITEM(ext_item, spec_version) 2068 if (name != NULL) { 2069 strncpy(ext_prop.extensionName, name, 2070 sizeof(ext_prop.extensionName)); 2071 ext_prop.extensionName[sizeof(ext_prop.extensionName) - 1] = 2072 '\0'; 2073 } 2074 ext_prop.specVersion = atoi(spec_version); 2075 loader_add_to_ext_list(inst, &props->instance_extension_list, 1, 2076 &ext_prop); 2077 } 2078 } 2079 /** 2080 * device_extensions 2081 * array of 2082 * name 2083 * spec_version 2084 * entrypoints 2085 */ 2086 GET_JSON_OBJECT(layer_node, device_extensions) 2087 if (device_extensions != NULL) { 2088 int count = cJSON_GetArraySize(device_extensions); 2089 for (i = 0; i < count; i++) { 2090 ext_item = cJSON_GetArrayItem(device_extensions, i); 2091 GET_JSON_ITEM(ext_item, name) 2092 GET_JSON_ITEM(ext_item, spec_version) 2093 if (name != NULL) { 2094 strncpy(ext_prop.extensionName, name, 2095 sizeof(ext_prop.extensionName)); 2096 ext_prop.extensionName[sizeof(ext_prop.extensionName) - 1] = 2097 '\0'; 2098 } 2099 ext_prop.specVersion = atoi(spec_version); 2100 // entrypoints = cJSON_GetObjectItem(ext_item, "entrypoints"); 2101 GET_JSON_OBJECT(ext_item, entrypoints) 2102 int entry_count; 2103 if (entrypoints == NULL) { 2104 loader_add_to_dev_ext_list(inst, 2105 &props->device_extension_list, 2106 &ext_prop, 0, NULL); 2107 continue; 2108 } 2109 entry_count = cJSON_GetArraySize(entrypoints); 2110 if (entry_count) 2111 entry_array = (char **)loader_stack_alloc(sizeof(char *) * 2112 entry_count); 2113 for (j = 0; j < entry_count; j++) { 2114 ext_item = cJSON_GetArrayItem(entrypoints, j); 2115 if (ext_item != NULL) { 2116 temp = cJSON_Print(ext_item); 2117 temp[strlen(temp) - 1] = '\0'; 2118 entry_array[j] = loader_stack_alloc(strlen(temp) + 1); 2119 strcpy(entry_array[j], &temp[1]); 2120 loader_tls_heap_free(temp); 2121 } 2122 } 2123 loader_add_to_dev_ext_list(inst, &props->device_extension_list, 2124 &ext_prop, entry_count, entry_array); 2125 } 2126 } 2127 if (is_implicit) { 2128 GET_JSON_OBJECT(layer_node, enable_environment) 2129 2130 // enable_environment is optional 2131 if (enable_environment) { 2132 strncpy(props->enable_env_var.name, 2133 enable_environment->child->string, 2134 sizeof(props->enable_env_var.name)); 2135 props->enable_env_var 2136 .name[sizeof(props->enable_env_var.name) - 1] = '\0'; 2137 strncpy(props->enable_env_var.value, 2138 enable_environment->child->valuestring, 2139 sizeof(props->enable_env_var.value)); 2140 props->enable_env_var 2141 .value[sizeof(props->enable_env_var.value) - 1] = '\0'; 2142 } 2143 } 2144#undef GET_JSON_ITEM 2145#undef GET_JSON_OBJECT 2146 // for global layers need to add them to both device and instance list 2147 if (!strcmp(type, "GLOBAL")) { 2148 struct loader_layer_properties *dev_props; 2149 if (layer_instance_list == NULL || layer_device_list == NULL) { 2150 layer_node = layer_node->next; 2151 continue; 2152 } 2153 dev_props = loader_get_next_layer_property(inst, layer_device_list); 2154 // copy into device layer list 2155 loader_copy_layer_properties(inst, dev_props, props); 2156 } 2157 layer_node = layer_node->next; 2158 } while (layer_node != NULL); 2159 return; 2160} 2161 2162/** 2163 * Find the Vulkan library manifest files. 2164 * 2165 * This function scans the "location" or "env_override" directories/files 2166 * for a list of JSON manifest files. If env_override is non-NULL 2167 * and has a valid value. Then the location is ignored. Otherwise 2168 * location is used to look for manifest files. The location 2169 * is interpreted as Registry path on Windows and a directory path(s) 2170 * on Linux. "home_location" is an additional directory in the users home 2171 * directory to look at. It is exapanded into the dir path $HOME/home_location. 2172 * This "home_location" is only used on Linux. 2173 * 2174 * \returns 2175 * A string list of manifest files to be opened in out_files param. 2176 * List has a pointer to string for each manifest filename. 2177 * When done using the list in out_files, pointers should be freed. 2178 * Location or override string lists can be either files or directories as 2179 *follows: 2180 * | location | override 2181 * -------------------------------- 2182 * Win ICD | files | files 2183 * Win Layer | files | dirs 2184 * Linux ICD | dirs | files 2185 * Linux Layer| dirs | dirs 2186 */ 2187static void loader_get_manifest_files(const struct loader_instance *inst, 2188 const char *env_override, bool is_layer, 2189 const char *location, 2190 const char *home_location, 2191 struct loader_manifest_files *out_files) { 2192 char *override = NULL; 2193 char *loc; 2194 char *file, *next_file, *name; 2195 size_t alloced_count = 64; 2196 char full_path[2048]; 2197 DIR *sysdir = NULL; 2198 bool list_is_dirs = false; 2199 struct dirent *dent; 2200 2201 out_files->count = 0; 2202 out_files->filename_list = NULL; 2203 2204 if (env_override != NULL && (override = loader_getenv(env_override))) { 2205#if !defined(_WIN32) 2206 if (geteuid() != getuid()) { 2207 /* Don't allow setuid apps to use the env var: */ 2208 loader_free_getenv(override); 2209 override = NULL; 2210 } 2211#endif 2212 } 2213 2214#if !defined(_WIN32) 2215 if (location == NULL && home_location == NULL) { 2216#else 2217 home_location = NULL; 2218 if (location == NULL) { 2219#endif 2220 loader_log( 2221 inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2222 "Can't get manifest files with NULL location, env_override=%s", 2223 env_override); 2224 return; 2225 } 2226 2227#if defined(_WIN32) 2228 list_is_dirs = (is_layer && override != NULL) ? true : false; 2229#else 2230 list_is_dirs = (override == NULL || is_layer) ? true : false; 2231#endif 2232 // Make a copy of the input we are using so it is not modified 2233 // Also handle getting the location(s) from registry on Windows 2234 if (override == NULL) { 2235 loc = loader_stack_alloc(strlen(location) + 1); 2236 if (loc == NULL) { 2237 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2238 "Out of memory can't get manifest files"); 2239 return; 2240 } 2241 strcpy(loc, location); 2242#if defined(_WIN32) 2243 loc = loader_get_registry_files(inst, loc); 2244 if (loc == NULL) { 2245 if (!is_layer) { 2246 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2247 "Registry lookup failed can't get ICD manifest " 2248 "files, do you have a Vulkan driver installed"); 2249 } else { 2250 // warning only for layers 2251 loader_log( 2252 inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 2253 "Registry lookup failed can't get layer manifest files"); 2254 } 2255 return; 2256 } 2257#endif 2258 } else { 2259 loc = loader_stack_alloc(strlen(override) + 1); 2260 if (loc == NULL) { 2261 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2262 "Out of memory can't get manifest files"); 2263 return; 2264 } 2265 strcpy(loc, override); 2266 loader_free_getenv(override); 2267 } 2268 2269 // Print out the paths being searched if debugging is enabled 2270 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, 2271 "Searching the following paths for manifest files: %s\n", loc); 2272 2273 file = loc; 2274 while (*file) { 2275 next_file = loader_get_next_path(file); 2276#if !defined(_WIN32) 2277 if (home_location != NULL && (next_file == NULL || *next_file == '\0')) { 2278 char *home = secure_getenv("HOME"); 2279 if (home != NULL) { 2280 size_t len; 2281 char *home_loc = loader_stack_alloc(strlen(home) + 2 + 2282 strlen(home_location)); 2283 if (home_loc == NULL) { 2284 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2285 "Out of memory can't get manifest files"); 2286 return; 2287 } 2288 strcpy(home_loc, home); 2289 // Add directory separator if needed 2290 if (home_location[0] != DIRECTORY_SYMBOL) { 2291 len = strlen(home_loc); 2292 home_loc[len] = DIRECTORY_SYMBOL; 2293 home_loc[len+1] = '\0'; 2294 } 2295 strcat(home_loc, home_location); 2296 file = home_loc; 2297 next_file = loader_get_next_path(file); 2298 home_location = NULL; 2299 2300 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, 2301 "Searching the following paths for manifest files: %s\n", 2302 home_loc); 2303 list_is_dirs = true; 2304 } 2305 } 2306#endif 2307 if (list_is_dirs) { 2308 sysdir = opendir(file); 2309 name = NULL; 2310 if (sysdir) { 2311 dent = readdir(sysdir); 2312 if (dent == NULL) 2313 break; 2314 name = &(dent->d_name[0]); 2315 loader_get_fullpath(name, file, sizeof(full_path), full_path); 2316 name = full_path; 2317 } 2318 } else { 2319#if defined(_WIN32) 2320 name = file; 2321#else 2322 // only Linux has relative paths 2323 char *dir; 2324 // make a copy of location so it isn't modified 2325 dir = loader_stack_alloc(strlen(loc) + 1); 2326 if (dir == NULL) { 2327 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2328 "Out of memory can't get manifest files"); 2329 return; 2330 } 2331 strcpy(dir, loc); 2332 2333 loader_get_fullpath(file, dir, sizeof(full_path), full_path); 2334 2335 name = full_path; 2336#endif 2337 } 2338 while (name) { 2339 /* Look for files ending with ".json" suffix */ 2340 uint32_t nlen = (uint32_t)strlen(name); 2341 const char *suf = name + nlen - 5; 2342 if ((nlen > 5) && !strncmp(suf, ".json", 5)) { 2343 if (out_files->count == 0) { 2344 out_files->filename_list = 2345 loader_heap_alloc(inst, alloced_count * sizeof(char *), 2346 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 2347 } else if (out_files->count == alloced_count) { 2348 out_files->filename_list = 2349 loader_heap_realloc(inst, out_files->filename_list, 2350 alloced_count * sizeof(char *), 2351 alloced_count * sizeof(char *) * 2, 2352 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 2353 alloced_count *= 2; 2354 } 2355 if (out_files->filename_list == NULL) { 2356 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2357 "Out of memory can't alloc manifest file list"); 2358 return; 2359 } 2360 out_files->filename_list[out_files->count] = loader_heap_alloc( 2361 inst, strlen(name) + 1, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 2362 if (out_files->filename_list[out_files->count] == NULL) { 2363 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2364 "Out of memory can't get manifest files"); 2365 return; 2366 } 2367 strcpy(out_files->filename_list[out_files->count], name); 2368 out_files->count++; 2369 } else if (!list_is_dirs) { 2370 loader_log( 2371 inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 2372 "Skipping manifest file %s, file name must end in .json", 2373 name); 2374 } 2375 if (list_is_dirs) { 2376 dent = readdir(sysdir); 2377 if (dent == NULL) 2378 break; 2379 name = &(dent->d_name[0]); 2380 loader_get_fullpath(name, file, sizeof(full_path), full_path); 2381 name = full_path; 2382 } else { 2383 break; 2384 } 2385 } 2386 if (sysdir) 2387 closedir(sysdir); 2388 file = next_file; 2389 } 2390 return; 2391} 2392 2393void loader_init_icd_lib_list() {} 2394 2395void loader_destroy_icd_lib_list() {} 2396/** 2397 * Try to find the Vulkan ICD driver(s). 2398 * 2399 * This function scans the default system loader path(s) or path 2400 * specified by the \c VK_ICD_FILENAMES environment variable in 2401 * order to find loadable VK ICDs manifest files. From these 2402 * manifest files it finds the ICD libraries. 2403 * 2404 * \returns 2405 * a list of icds that were discovered 2406 */ 2407void loader_icd_scan(const struct loader_instance *inst, 2408 struct loader_icd_libs *icds) { 2409 char *file_str; 2410 struct loader_manifest_files manifest_files; 2411 2412 loader_scanned_icd_init(inst, icds); 2413 // Get a list of manifest files for ICDs 2414 loader_get_manifest_files(inst, "VK_ICD_FILENAMES", false, 2415 DEFAULT_VK_DRIVERS_INFO, HOME_VK_DRIVERS_INFO, 2416 &manifest_files); 2417 if (manifest_files.count == 0) 2418 return; 2419 loader_platform_thread_lock_mutex(&loader_json_lock); 2420 for (uint32_t i = 0; i < manifest_files.count; i++) { 2421 file_str = manifest_files.filename_list[i]; 2422 if (file_str == NULL) 2423 continue; 2424 2425 cJSON *json; 2426 json = loader_get_json(inst, file_str); 2427 if (!json) 2428 continue; 2429 cJSON *item, *itemICD; 2430 item = cJSON_GetObjectItem(json, "file_format_version"); 2431 if (item == NULL) { 2432 loader_platform_thread_unlock_mutex(&loader_json_lock); 2433 return; 2434 } 2435 char *file_vers = cJSON_Print(item); 2436 loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, 2437 "Found manifest file %s, version %s", file_str, file_vers); 2438 if (strcmp(file_vers, "\"1.0.0\"") != 0) 2439 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 2440 "Unexpected manifest file version (expected 1.0.0), may " 2441 "cause errors"); 2442 loader_tls_heap_free(file_vers); 2443 itemICD = cJSON_GetObjectItem(json, "ICD"); 2444 if (itemICD != NULL) { 2445 item = cJSON_GetObjectItem(itemICD, "library_path"); 2446 if (item != NULL) { 2447 char *temp = cJSON_Print(item); 2448 if (!temp || strlen(temp) == 0) { 2449 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 2450 "Can't find \"library_path\" in ICD JSON file " 2451 "%s, skipping", 2452 file_str); 2453 loader_tls_heap_free(temp); 2454 loader_heap_free(inst, file_str); 2455 cJSON_Delete(json); 2456 continue; 2457 } 2458 // strip out extra quotes 2459 temp[strlen(temp) - 1] = '\0'; 2460 char *library_path = loader_stack_alloc(strlen(temp) + 1); 2461 strcpy(library_path, &temp[1]); 2462 loader_tls_heap_free(temp); 2463 if (!library_path || strlen(library_path) == 0) { 2464 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 2465 "Can't find \"library_path\" in ICD JSON file " 2466 "%s, skipping", 2467 file_str); 2468 loader_heap_free(inst, file_str); 2469 cJSON_Delete(json); 2470 continue; 2471 } 2472 char fullpath[MAX_STRING_SIZE]; 2473 // Print out the paths being searched if debugging is enabled 2474 loader_log( 2475 inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, 2476 "Searching for ICD drivers named %s default dir %s\n", 2477 library_path, DEFAULT_VK_DRIVERS_PATH); 2478 if (loader_platform_is_path(library_path)) { 2479 // a relative or absolute path 2480 char *name_copy = loader_stack_alloc(strlen(file_str) + 1); 2481 char *rel_base; 2482 strcpy(name_copy, file_str); 2483 rel_base = loader_platform_dirname(name_copy); 2484 loader_expand_path(library_path, rel_base, sizeof(fullpath), 2485 fullpath); 2486 } else { 2487 // a filename which is assumed in a system directory 2488 loader_get_fullpath(library_path, DEFAULT_VK_DRIVERS_PATH, 2489 sizeof(fullpath), fullpath); 2490 } 2491 2492 uint32_t vers = 0; 2493 item = cJSON_GetObjectItem(itemICD, "api_version"); 2494 if (item != NULL) { 2495 temp = cJSON_Print(item); 2496 vers = loader_make_version(temp); 2497 loader_tls_heap_free(temp); 2498 } 2499 loader_scanned_icd_add(inst, icds, fullpath, vers); 2500 } else 2501 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 2502 "Can't find \"library_path\" object in ICD JSON " 2503 "file %s, skipping", 2504 file_str); 2505 } else 2506 loader_log( 2507 inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 2508 "Can't find \"ICD\" object in ICD JSON file %s, skipping", 2509 file_str); 2510 2511 loader_heap_free(inst, file_str); 2512 cJSON_Delete(json); 2513 } 2514 loader_heap_free(inst, manifest_files.filename_list); 2515 loader_platform_thread_unlock_mutex(&loader_json_lock); 2516} 2517 2518void loader_layer_scan(const struct loader_instance *inst, 2519 struct loader_layer_list *instance_layers, 2520 struct loader_layer_list *device_layers) { 2521 char *file_str; 2522 struct loader_manifest_files 2523 manifest_files[2]; // [0] = explicit, [1] = implicit 2524 cJSON *json; 2525 uint32_t i; 2526 uint32_t implicit; 2527 2528 // Get a list of manifest files for explicit layers 2529 loader_get_manifest_files(inst, LAYERS_PATH_ENV, true, 2530 DEFAULT_VK_ELAYERS_INFO, HOME_VK_ELAYERS_INFO, 2531 &manifest_files[0]); 2532 // Pass NULL for environment variable override - implicit layers are not 2533 // overridden by LAYERS_PATH_ENV 2534 loader_get_manifest_files(inst, NULL, true, DEFAULT_VK_ILAYERS_INFO, 2535 HOME_VK_ILAYERS_INFO, &manifest_files[1]); 2536 if (manifest_files[0].count == 0 && manifest_files[1].count == 0) 2537 return; 2538 2539#if 0 // TODO 2540 /** 2541 * We need a list of the layer libraries, not just a list of 2542 * the layer properties (a layer library could expose more than 2543 * one layer property). This list of scanned layers would be 2544 * used to check for global and physicaldevice layer properties. 2545 */ 2546 if (!loader_init_layer_library_list(&loader.scanned_layer_libraries)) { 2547 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2548 "Alloc for layer list failed: %s line: %d", __FILE__, __LINE__); 2549 return; 2550 } 2551#endif 2552 2553 /* cleanup any previously scanned libraries */ 2554 loader_delete_layer_properties(inst, instance_layers); 2555 loader_delete_layer_properties(inst, device_layers); 2556 2557 loader_platform_thread_lock_mutex(&loader_json_lock); 2558 for (implicit = 0; implicit < 2; implicit++) { 2559 for (i = 0; i < manifest_files[implicit].count; i++) { 2560 file_str = manifest_files[implicit].filename_list[i]; 2561 if (file_str == NULL) 2562 continue; 2563 2564 // parse file into JSON struct 2565 json = loader_get_json(inst, file_str); 2566 if (!json) { 2567 continue; 2568 } 2569 2570 // TODO error if device layers expose instance_extensions 2571 // TODO error if instance layers expose device extensions 2572 loader_add_layer_properties(inst, instance_layers, device_layers, 2573 json, (implicit == 1), file_str); 2574 2575 loader_heap_free(inst, file_str); 2576 cJSON_Delete(json); 2577 } 2578 } 2579 if (manifest_files[0].count != 0) 2580 loader_heap_free(inst, manifest_files[0].filename_list); 2581 2582 if (manifest_files[1].count != 0) 2583 loader_heap_free(inst, manifest_files[1].filename_list); 2584 2585 // add a meta layer for validation if the validation layers are all present 2586 loader_add_layer_property_meta( 2587 inst, sizeof(std_validation_names) / sizeof(std_validation_names[0]), 2588 std_validation_names, instance_layers, device_layers); 2589 2590 loader_platform_thread_unlock_mutex(&loader_json_lock); 2591} 2592 2593static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL 2594loader_gpa_instance_internal(VkInstance inst, const char *pName) { 2595 if (!strcmp(pName, "vkGetInstanceProcAddr")) 2596 return (void *)loader_gpa_instance_internal; 2597 if (!strcmp(pName, "vkCreateInstance")) 2598 return (void *)loader_CreateInstance; 2599 if (!strcmp(pName, "vkCreateDevice")) 2600 return (void *)loader_create_device_terminator; 2601 2602 // inst is not wrapped 2603 if (inst == VK_NULL_HANDLE) { 2604 return NULL; 2605 } 2606 VkLayerInstanceDispatchTable *disp_table = 2607 *(VkLayerInstanceDispatchTable **)inst; 2608 void *addr; 2609 2610 if (disp_table == NULL) 2611 return NULL; 2612 2613 addr = loader_lookup_instance_dispatch_table(disp_table, pName); 2614 if (addr) { 2615 return addr; 2616 } 2617 2618 if (disp_table->GetInstanceProcAddr == NULL) { 2619 return NULL; 2620 } 2621 return disp_table->GetInstanceProcAddr(inst, pName); 2622} 2623 2624/** 2625 * Initialize device_ext dispatch table entry as follows: 2626 * If dev == NULL find all logical devices created within this instance and 2627 * init the entry (given by idx) in the ext dispatch table. 2628 * If dev != NULL only initialize the entry in the given dev's dispatch table. 2629 * The initialization value is gotten by calling down the device chain with 2630 * GDPA. 2631 * If GDPA returns NULL then don't initialize the dispatch table entry. 2632 */ 2633static void loader_init_dispatch_dev_ext_entry(struct loader_instance *inst, 2634 struct loader_device *dev, 2635 uint32_t idx, 2636 const char *funcName) 2637 2638{ 2639 void *gdpa_value; 2640 if (dev != NULL) { 2641 gdpa_value = dev->loader_dispatch.core_dispatch.GetDeviceProcAddr( 2642 dev->device, funcName); 2643 if (gdpa_value != NULL) 2644 dev->loader_dispatch.ext_dispatch.DevExt[idx] = 2645 (PFN_vkDevExt)gdpa_value; 2646 } else { 2647 for (uint32_t i = 0; i < inst->total_icd_count; i++) { 2648 struct loader_icd *icd = &inst->icds[i]; 2649 struct loader_device *dev = icd->logical_device_list; 2650 while (dev) { 2651 gdpa_value = 2652 dev->loader_dispatch.core_dispatch.GetDeviceProcAddr( 2653 dev->device, funcName); 2654 if (gdpa_value != NULL) 2655 dev->loader_dispatch.ext_dispatch.DevExt[idx] = 2656 (PFN_vkDevExt)gdpa_value; 2657 dev = dev->next; 2658 } 2659 } 2660 } 2661} 2662 2663/** 2664 * Find all dev extension in the hash table and initialize the dispatch table 2665 * for dev for each of those extension entrypoints found in hash table. 2666 2667 */ 2668static void loader_init_dispatch_dev_ext(struct loader_instance *inst, 2669 struct loader_device *dev) { 2670 for (uint32_t i = 0; i < MAX_NUM_DEV_EXTS; i++) { 2671 if (inst->disp_hash[i].func_name != NULL) 2672 loader_init_dispatch_dev_ext_entry(inst, dev, i, 2673 inst->disp_hash[i].func_name); 2674 } 2675} 2676 2677static bool loader_check_icds_for_address(struct loader_instance *inst, 2678 const char *funcName) { 2679 struct loader_icd *icd; 2680 icd = inst->icds; 2681 while (icd) { 2682 if (icd->this_icd_lib->GetInstanceProcAddr(icd->instance, funcName)) 2683 // this icd supports funcName 2684 return true; 2685 icd = icd->next; 2686 } 2687 2688 return false; 2689} 2690 2691static void loader_free_dev_ext_table(struct loader_instance *inst) { 2692 for (uint32_t i = 0; i < MAX_NUM_DEV_EXTS; i++) { 2693 loader_heap_free(inst, inst->disp_hash[i].func_name); 2694 loader_heap_free(inst, inst->disp_hash[i].list.index); 2695 } 2696 memset(inst->disp_hash, 0, sizeof(inst->disp_hash)); 2697} 2698 2699static bool loader_add_dev_ext_table(struct loader_instance *inst, 2700 uint32_t *ptr_idx, const char *funcName) { 2701 uint32_t i; 2702 uint32_t idx = *ptr_idx; 2703 struct loader_dispatch_hash_list *list = &inst->disp_hash[idx].list; 2704 2705 if (!inst->disp_hash[idx].func_name) { 2706 // no entry here at this idx, so use it 2707 assert(list->capacity == 0); 2708 inst->disp_hash[idx].func_name = (char *)loader_heap_alloc( 2709 inst, strlen(funcName) + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 2710 if (inst->disp_hash[idx].func_name == NULL) { 2711 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2712 "loader_add_dev_ext_table() can't allocate memory for " 2713 "func_name"); 2714 return false; 2715 } 2716 strncpy(inst->disp_hash[idx].func_name, funcName, strlen(funcName) + 1); 2717 return true; 2718 } 2719 2720 // check for enough capacity 2721 if (list->capacity == 0) { 2722 list->index = loader_heap_alloc(inst, 8 * sizeof(*(list->index)), 2723 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 2724 if (list->index == NULL) { 2725 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2726 "loader_add_dev_ext_table() can't allocate list memory"); 2727 return false; 2728 } 2729 list->capacity = 8 * sizeof(*(list->index)); 2730 } else if (list->capacity < (list->count + 1) * sizeof(*(list->index))) { 2731 list->index = loader_heap_realloc(inst, list->index, list->capacity, 2732 list->capacity * 2, 2733 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 2734 if (list->index == NULL) { 2735 loader_log( 2736 inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2737 "loader_add_dev_ext_table() can't reallocate list memory"); 2738 return false; 2739 } 2740 list->capacity *= 2; 2741 } 2742 2743 // find an unused index in the hash table and use it 2744 i = (idx + 1) % MAX_NUM_DEV_EXTS; 2745 do { 2746 if (!inst->disp_hash[i].func_name) { 2747 assert(inst->disp_hash[i].list.capacity == 0); 2748 inst->disp_hash[i].func_name = 2749 (char *)loader_heap_alloc(inst, strlen(funcName) + 1, 2750 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 2751 if (inst->disp_hash[i].func_name == NULL) { 2752 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2753 "loader_add_dev_ext_table() can't rallocate " 2754 "func_name memory"); 2755 return false; 2756 } 2757 strncpy(inst->disp_hash[i].func_name, funcName, 2758 strlen(funcName) + 1); 2759 list->index[list->count] = i; 2760 list->count++; 2761 *ptr_idx = i; 2762 return true; 2763 } 2764 i = (i + 1) % MAX_NUM_DEV_EXTS; 2765 } while (i != idx); 2766 2767 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2768 "loader_add_dev_ext_table() couldn't insert into hash table; is " 2769 "it full?"); 2770 return false; 2771} 2772 2773static bool loader_name_in_dev_ext_table(struct loader_instance *inst, 2774 uint32_t *idx, const char *funcName) { 2775 uint32_t alt_idx; 2776 if (inst->disp_hash[*idx].func_name && 2777 !strcmp(inst->disp_hash[*idx].func_name, funcName)) 2778 return true; 2779 2780 // funcName wasn't at the primary spot in the hash table 2781 // search the list of secondary locations (shallow search, not deep search) 2782 for (uint32_t i = 0; i < inst->disp_hash[*idx].list.count; i++) { 2783 alt_idx = inst->disp_hash[*idx].list.index[i]; 2784 if (!strcmp(inst->disp_hash[*idx].func_name, funcName)) { 2785 *idx = alt_idx; 2786 return true; 2787 } 2788 } 2789 2790 return false; 2791} 2792 2793/** 2794 * This function returns generic trampoline code address for unknown entry 2795 * points. 2796 * Presumably, these unknown entry points (as given by funcName) are device 2797 * extension entrypoints. A hash table is used to keep a list of unknown entry 2798 * points and their mapping to the device extension dispatch table 2799 * (struct loader_dev_ext_dispatch_table). 2800 * \returns 2801 * For a given entry point string (funcName), if an existing mapping is found 2802 * the 2803 * trampoline address for that mapping is returned. Otherwise, this unknown 2804 * entry point 2805 * has not been seen yet. Next check if a layer or ICD supports it. If so then 2806 * a 2807 * new entry in the hash table is initialized and that trampoline address for 2808 * the new entry is returned. Null is returned if the hash table is full or 2809 * if no discovered layer or ICD returns a non-NULL GetProcAddr for it. 2810 */ 2811void *loader_dev_ext_gpa(struct loader_instance *inst, const char *funcName) { 2812 uint32_t idx; 2813 uint32_t seed = 0; 2814 2815 idx = murmurhash(funcName, strlen(funcName), seed) % MAX_NUM_DEV_EXTS; 2816 2817 if (loader_name_in_dev_ext_table(inst, &idx, funcName)) 2818 // found funcName already in hash 2819 return loader_get_dev_ext_trampoline(idx); 2820 2821 // Check if funcName is supported in either ICDs or a layer library 2822 if (!loader_check_icds_for_address(inst, funcName)) { 2823 // TODO Add check in layer libraries for support of address 2824 // if support found in layers continue on 2825 return NULL; 2826 } 2827 2828 if (loader_add_dev_ext_table(inst, &idx, funcName)) { 2829 // successfully added new table entry 2830 // init any dev dispatch table entrys as needed 2831 loader_init_dispatch_dev_ext_entry(inst, NULL, idx, funcName); 2832 return loader_get_dev_ext_trampoline(idx); 2833 } 2834 2835 return NULL; 2836} 2837 2838struct loader_instance *loader_get_instance(const VkInstance instance) { 2839 /* look up the loader_instance in our list by comparing dispatch tables, as 2840 * there is no guarantee the instance is still a loader_instance* after any 2841 * layers which wrap the instance object. 2842 */ 2843 const VkLayerInstanceDispatchTable *disp; 2844 struct loader_instance *ptr_instance = NULL; 2845 disp = loader_get_instance_dispatch(instance); 2846 for (struct loader_instance *inst = loader.instances; inst; 2847 inst = inst->next) { 2848 if (inst->disp == disp) { 2849 ptr_instance = inst; 2850 break; 2851 } 2852 } 2853 return ptr_instance; 2854} 2855 2856static loader_platform_dl_handle 2857loader_add_layer_lib(const struct loader_instance *inst, const char *chain_type, 2858 struct loader_layer_properties *layer_prop) { 2859 struct loader_lib_info *new_layer_lib_list, *my_lib; 2860 size_t new_alloc_size; 2861 /* 2862 * TODO: We can now track this information in the 2863 * scanned_layer_libraries list. 2864 */ 2865 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) { 2866 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, 2867 layer_prop->lib_name) == 0) { 2868 /* Have already loaded this library, just increment ref count */ 2869 loader.loaded_layer_lib_list[i].ref_count++; 2870 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, 2871 "%s Chain: Increment layer reference count for layer " 2872 "library %s", 2873 chain_type, layer_prop->lib_name); 2874 return loader.loaded_layer_lib_list[i].lib_handle; 2875 } 2876 } 2877 2878 /* Haven't seen this library so load it */ 2879 new_alloc_size = 0; 2880 if (loader.loaded_layer_lib_capacity == 0) 2881 new_alloc_size = 8 * sizeof(struct loader_lib_info); 2882 else if (loader.loaded_layer_lib_capacity <= 2883 loader.loaded_layer_lib_count * sizeof(struct loader_lib_info)) 2884 new_alloc_size = loader.loaded_layer_lib_capacity * 2; 2885 2886 if (new_alloc_size) { 2887 new_layer_lib_list = loader_heap_realloc( 2888 inst, loader.loaded_layer_lib_list, 2889 loader.loaded_layer_lib_capacity, new_alloc_size, 2890 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 2891 if (!new_layer_lib_list) { 2892 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2893 "loader: realloc failed in loader_add_layer_lib"); 2894 return NULL; 2895 } 2896 loader.loaded_layer_lib_capacity = new_alloc_size; 2897 loader.loaded_layer_lib_list = new_layer_lib_list; 2898 } else 2899 new_layer_lib_list = loader.loaded_layer_lib_list; 2900 my_lib = &new_layer_lib_list[loader.loaded_layer_lib_count]; 2901 2902 strncpy(my_lib->lib_name, layer_prop->lib_name, sizeof(my_lib->lib_name)); 2903 my_lib->lib_name[sizeof(my_lib->lib_name) - 1] = '\0'; 2904 my_lib->ref_count = 0; 2905 my_lib->lib_handle = NULL; 2906 2907 if ((my_lib->lib_handle = loader_platform_open_library(my_lib->lib_name)) == 2908 NULL) { 2909 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2910 loader_platform_open_library_error(my_lib->lib_name)); 2911 return NULL; 2912 } else { 2913 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, 2914 "Chain: %s: Loading layer library %s", chain_type, 2915 layer_prop->lib_name); 2916 } 2917 loader.loaded_layer_lib_count++; 2918 my_lib->ref_count++; 2919 2920 return my_lib->lib_handle; 2921} 2922 2923static void 2924loader_remove_layer_lib(struct loader_instance *inst, 2925 struct loader_layer_properties *layer_prop) { 2926 uint32_t idx = loader.loaded_layer_lib_count; 2927 struct loader_lib_info *new_layer_lib_list, *my_lib = NULL; 2928 2929 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) { 2930 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, 2931 layer_prop->lib_name) == 0) { 2932 /* found matching library */ 2933 idx = i; 2934 my_lib = &loader.loaded_layer_lib_list[i]; 2935 break; 2936 } 2937 } 2938 2939 if (idx == loader.loaded_layer_lib_count) { 2940 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2941 "Unable to unref library %s", layer_prop->lib_name); 2942 return; 2943 } 2944 2945 if (my_lib) { 2946 my_lib->ref_count--; 2947 if (my_lib->ref_count > 0) { 2948 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, 2949 "Decrement reference count for layer library %s", 2950 layer_prop->lib_name); 2951 return; 2952 } 2953 } 2954 loader_platform_close_library(my_lib->lib_handle); 2955 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, 2956 "Unloading layer library %s", layer_prop->lib_name); 2957 2958 /* Need to remove unused library from list */ 2959 new_layer_lib_list = 2960 loader_heap_alloc(inst, loader.loaded_layer_lib_capacity, 2961 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 2962 if (!new_layer_lib_list) { 2963 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2964 "loader: heap alloc failed loader_remove_layer_library"); 2965 return; 2966 } 2967 2968 if (idx > 0) { 2969 /* Copy records before idx */ 2970 memcpy(new_layer_lib_list, &loader.loaded_layer_lib_list[0], 2971 sizeof(struct loader_lib_info) * idx); 2972 } 2973 if (idx < (loader.loaded_layer_lib_count - 1)) { 2974 /* Copy records after idx */ 2975 memcpy(&new_layer_lib_list[idx], &loader.loaded_layer_lib_list[idx + 1], 2976 sizeof(struct loader_lib_info) * 2977 (loader.loaded_layer_lib_count - idx - 1)); 2978 } 2979 2980 loader_heap_free(inst, loader.loaded_layer_lib_list); 2981 loader.loaded_layer_lib_count--; 2982 loader.loaded_layer_lib_list = new_layer_lib_list; 2983} 2984 2985/** 2986 * Go through the search_list and find any layers which match type. If layer 2987 * type match is found in then add it to ext_list. 2988 */ 2989static void 2990loader_add_layer_implicit(const struct loader_instance *inst, 2991 const enum layer_type type, 2992 struct loader_layer_list *list, 2993 const struct loader_layer_list *search_list) { 2994 bool enable; 2995 char *env_value; 2996 uint32_t i; 2997 for (i = 0; i < search_list->count; i++) { 2998 const struct loader_layer_properties *prop = &search_list->list[i]; 2999 if (prop->type & type) { 3000 /* Found an implicit layer, see if it should be enabled */ 3001 enable = false; 3002 3003 // if no enable_environment variable is specified, this implicit 3004 // layer 3005 // should always be enabled. Otherwise check if the variable is set 3006 if (prop->enable_env_var.name[0] == 0) { 3007 enable = true; 3008 } else { 3009 env_value = loader_getenv(prop->enable_env_var.name); 3010 if (env_value && !strcmp(prop->enable_env_var.value, env_value)) 3011 enable = true; 3012 loader_free_getenv(env_value); 3013 } 3014 3015 // disable_environment has priority, i.e. if both enable and disable 3016 // environment variables are set, the layer is disabled. Implicit 3017 // layers 3018 // are required to have a disable_environment variables 3019 env_value = loader_getenv(prop->disable_env_var.name); 3020 if (env_value) 3021 enable = false; 3022 loader_free_getenv(env_value); 3023 3024 if (enable) 3025 loader_add_to_layer_list(inst, list, 1, prop); 3026 } 3027 } 3028} 3029 3030/** 3031 * Get the layer name(s) from the env_name environment variable. If layer 3032 * is found in search_list then add it to layer_list. But only add it to 3033 * layer_list if type matches. 3034 */ 3035static void loader_add_layer_env(const struct loader_instance *inst, 3036 const enum layer_type type, 3037 const char *env_name, 3038 struct loader_layer_list *layer_list, 3039 const struct loader_layer_list *search_list) { 3040 char *layerEnv; 3041 char *next, *name; 3042 3043 layerEnv = loader_getenv(env_name); 3044 if (layerEnv == NULL) { 3045 return; 3046 } 3047 name = loader_stack_alloc(strlen(layerEnv) + 1); 3048 if (name == NULL) { 3049 return; 3050 } 3051 strcpy(name, layerEnv); 3052 3053 loader_free_getenv(layerEnv); 3054 3055 while (name && *name) { 3056 next = loader_get_next_path(name); 3057 if (!strcmp(std_validation_str, name)) { 3058 /* add meta list of layers 3059 don't attempt to remove duplicate layers already added by app or 3060 env var 3061 */ 3062 loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, 3063 "Expanding meta layer %s found in environment variable", 3064 std_validation_str); 3065 for (uint32_t i = 0; i < sizeof(std_validation_names) / 3066 sizeof(std_validation_names[0]); 3067 i++) { 3068 loader_find_layer_name_add_list(inst, std_validation_names[i], 3069 type, search_list, layer_list); 3070 } 3071 } else { 3072 loader_find_layer_name_add_list(inst, name, type, search_list, 3073 layer_list); 3074 } 3075 name = next; 3076 } 3077 3078 return; 3079} 3080 3081void loader_deactivate_instance_layers(struct loader_instance *instance) { 3082 /* Create instance chain of enabled layers */ 3083 for (uint32_t i = 0; i < instance->activated_layer_list.count; i++) { 3084 struct loader_layer_properties *layer_prop = 3085 &instance->activated_layer_list.list[i]; 3086 3087 loader_remove_layer_lib(instance, layer_prop); 3088 } 3089 loader_destroy_layer_list(instance, &instance->activated_layer_list); 3090} 3091 3092VkResult 3093loader_enable_instance_layers(struct loader_instance *inst, 3094 const VkInstanceCreateInfo *pCreateInfo, 3095 const struct loader_layer_list *instance_layers) { 3096 VkResult err; 3097 3098 assert(inst && "Cannot have null instance"); 3099 3100 if (!loader_init_layer_list(inst, &inst->activated_layer_list)) { 3101 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 3102 "Failed to alloc Instance activated layer list"); 3103 return VK_ERROR_OUT_OF_HOST_MEMORY; 3104 } 3105 3106 /* Add any implicit layers first */ 3107 loader_add_layer_implicit(inst, VK_LAYER_TYPE_INSTANCE_IMPLICIT, 3108 &inst->activated_layer_list, instance_layers); 3109 3110 /* Add any layers specified via environment variable next */ 3111 loader_add_layer_env(inst, VK_LAYER_TYPE_INSTANCE_EXPLICIT, 3112 "VK_INSTANCE_LAYERS", &inst->activated_layer_list, 3113 instance_layers); 3114 3115 /* Add layers specified by the application */ 3116 err = loader_add_layer_names_to_list( 3117 inst, &inst->activated_layer_list, pCreateInfo->enabledLayerCount, 3118 pCreateInfo->ppEnabledLayerNames, instance_layers); 3119 3120 return err; 3121} 3122 3123/* 3124 * Given the list of layers to activate in the loader_instance 3125 * structure. This function will add a VkLayerInstanceCreateInfo 3126 * structure to the VkInstanceCreateInfo.pNext pointer. 3127 * Each activated layer will have it's own VkLayerInstanceLink 3128 * structure that tells the layer what Get*ProcAddr to call to 3129 * get function pointers to the next layer down. 3130 * Once the chain info has been created this function will 3131 * execute the CreateInstance call chain. Each layer will 3132 * then have an opportunity in it's CreateInstance function 3133 * to setup it's dispatch table when the lower layer returns 3134 * successfully. 3135 * Each layer can wrap or not-wrap the returned VkInstance object 3136 * as it sees fit. 3137 * The instance chain is terminated by a loader function 3138 * that will call CreateInstance on all available ICD's and 3139 * cache those VkInstance objects for future use. 3140 */ 3141VkResult loader_create_instance_chain(const VkInstanceCreateInfo *pCreateInfo, 3142 const VkAllocationCallbacks *pAllocator, 3143 struct loader_instance *inst, 3144 VkInstance *created_instance) { 3145 uint32_t activated_layers = 0; 3146 VkLayerInstanceCreateInfo chain_info; 3147 VkLayerInstanceLink *layer_instance_link_info = NULL; 3148 VkInstanceCreateInfo loader_create_info; 3149 VkResult res; 3150 3151 PFN_vkGetInstanceProcAddr nextGIPA = loader_gpa_instance_internal; 3152 PFN_vkGetInstanceProcAddr fpGIPA = loader_gpa_instance_internal; 3153 3154 memcpy(&loader_create_info, pCreateInfo, sizeof(VkInstanceCreateInfo)); 3155 3156 if (inst->activated_layer_list.count > 0) { 3157 3158 chain_info.u.pLayerInfo = NULL; 3159 chain_info.pNext = pCreateInfo->pNext; 3160 chain_info.sType = VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO; 3161 chain_info.function = VK_LAYER_LINK_INFO; 3162 loader_create_info.pNext = &chain_info; 3163 3164 layer_instance_link_info = loader_stack_alloc( 3165 sizeof(VkLayerInstanceLink) * inst->activated_layer_list.count); 3166 if (!layer_instance_link_info) { 3167 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 3168 "Failed to alloc Instance objects for layer"); 3169 return VK_ERROR_OUT_OF_HOST_MEMORY; 3170 } 3171 3172 /* Create instance chain of enabled layers */ 3173 for (int32_t i = inst->activated_layer_list.count - 1; i >= 0; i--) { 3174 struct loader_layer_properties *layer_prop = 3175 &inst->activated_layer_list.list[i]; 3176 loader_platform_dl_handle lib_handle; 3177 3178 lib_handle = loader_add_layer_lib(inst, "instance", layer_prop); 3179 if (!lib_handle) 3180 continue; 3181 if ((fpGIPA = layer_prop->functions.get_instance_proc_addr) == 3182 NULL) { 3183 if (layer_prop->functions.str_gipa == NULL || 3184 strlen(layer_prop->functions.str_gipa) == 0) { 3185 fpGIPA = (PFN_vkGetInstanceProcAddr) 3186 loader_platform_get_proc_address( 3187 lib_handle, "vkGetInstanceProcAddr"); 3188 layer_prop->functions.get_instance_proc_addr = fpGIPA; 3189 } else 3190 fpGIPA = (PFN_vkGetInstanceProcAddr) 3191 loader_platform_get_proc_address( 3192 lib_handle, layer_prop->functions.str_gipa); 3193 if (!fpGIPA) { 3194 loader_log( 3195 inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 3196 "Failed to find vkGetInstanceProcAddr in layer %s", 3197 layer_prop->lib_name); 3198 continue; 3199 } 3200 } 3201 3202 layer_instance_link_info[activated_layers].pNext = 3203 chain_info.u.pLayerInfo; 3204 layer_instance_link_info[activated_layers] 3205 .pfnNextGetInstanceProcAddr = nextGIPA; 3206 chain_info.u.pLayerInfo = 3207 &layer_instance_link_info[activated_layers]; 3208 nextGIPA = fpGIPA; 3209 3210 loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, 3211 "Insert instance layer %s (%s)", 3212 layer_prop->info.layerName, layer_prop->lib_name); 3213 3214 activated_layers++; 3215 } 3216 } 3217 3218 PFN_vkCreateInstance fpCreateInstance = 3219 (PFN_vkCreateInstance)nextGIPA(*created_instance, "vkCreateInstance"); 3220 if (fpCreateInstance) { 3221 VkLayerInstanceCreateInfo instance_create_info; 3222 3223 instance_create_info.sType = 3224 VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO; 3225 instance_create_info.function = VK_LAYER_INSTANCE_INFO; 3226 3227 instance_create_info.u.instanceInfo.instance_info = inst; 3228 instance_create_info.u.instanceInfo.pfnNextGetInstanceProcAddr = 3229 nextGIPA; 3230 3231 instance_create_info.pNext = loader_create_info.pNext; 3232 loader_create_info.pNext = &instance_create_info; 3233 3234 res = 3235 fpCreateInstance(&loader_create_info, pAllocator, created_instance); 3236 } else { 3237 // Couldn't find CreateInstance function! 3238 res = VK_ERROR_INITIALIZATION_FAILED; 3239 } 3240 3241 if (res != VK_SUCCESS) { 3242 // TODO: Need to clean up here 3243 } else { 3244 loader_init_instance_core_dispatch_table(inst->disp, nextGIPA, 3245 *created_instance); 3246 } 3247 3248 return res; 3249} 3250 3251void loader_activate_instance_layer_extensions(struct loader_instance *inst, 3252 VkInstance created_inst) { 3253 3254 loader_init_instance_extension_dispatch_table( 3255 inst->disp, inst->disp->GetInstanceProcAddr, created_inst); 3256} 3257 3258static VkResult 3259loader_enable_device_layers(const struct loader_instance *inst, 3260 struct loader_icd *icd, 3261 struct loader_layer_list *activated_layer_list, 3262 const VkDeviceCreateInfo *pCreateInfo, 3263 const struct loader_layer_list *device_layers) 3264 3265{ 3266 VkResult err; 3267 3268 assert(activated_layer_list && "Cannot have null output layer list"); 3269 3270 if (activated_layer_list->list == NULL || 3271 activated_layer_list->capacity == 0) { 3272 loader_init_layer_list(inst, activated_layer_list); 3273 } 3274 3275 if (activated_layer_list->list == NULL) { 3276 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 3277 "Failed to alloc device activated layer list"); 3278 return VK_ERROR_OUT_OF_HOST_MEMORY; 3279 } 3280 3281 /* Add any implicit layers first */ 3282 loader_add_layer_implicit(inst, VK_LAYER_TYPE_DEVICE_IMPLICIT, 3283 activated_layer_list, device_layers); 3284 3285 /* Add any layers specified via environment variable next */ 3286 loader_add_layer_env(inst, VK_LAYER_TYPE_DEVICE_EXPLICIT, 3287 "VK_DEVICE_LAYERS", activated_layer_list, 3288 device_layers); 3289 3290 /* Add layers specified by the application */ 3291 err = loader_add_layer_names_to_list( 3292 inst, activated_layer_list, pCreateInfo->enabledLayerCount, 3293 pCreateInfo->ppEnabledLayerNames, device_layers); 3294 3295 return err; 3296} 3297 3298VKAPI_ATTR VkResult VKAPI_CALL 3299loader_create_device_terminator(VkPhysicalDevice physicalDevice, 3300 const VkDeviceCreateInfo *pCreateInfo, 3301 const VkAllocationCallbacks *pAllocator, 3302 VkDevice *pDevice) { 3303 struct loader_physical_device *phys_dev; 3304 phys_dev = loader_get_physical_device(physicalDevice); 3305 3306 VkLayerDeviceCreateInfo *chain_info = 3307 (VkLayerDeviceCreateInfo *)pCreateInfo->pNext; 3308 while (chain_info && 3309 !(chain_info->sType == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO && 3310 chain_info->function == VK_LAYER_DEVICE_INFO)) { 3311 chain_info = (VkLayerDeviceCreateInfo *)chain_info->pNext; 3312 } 3313 assert(chain_info != NULL); 3314 3315 struct loader_device *dev = 3316 (struct loader_device *)chain_info->u.deviceInfo.device_info; 3317 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = 3318 chain_info->u.deviceInfo.pfnNextGetInstanceProcAddr; 3319 PFN_vkCreateDevice fpCreateDevice = 3320 (PFN_vkCreateDevice)fpGetInstanceProcAddr(phys_dev->this_icd->instance, 3321 "vkCreateDevice"); 3322 if (fpCreateDevice == NULL) { 3323 return VK_ERROR_INITIALIZATION_FAILED; 3324 } 3325 3326 VkDeviceCreateInfo localCreateInfo; 3327 memcpy(&localCreateInfo, pCreateInfo, sizeof(localCreateInfo)); 3328 localCreateInfo.pNext = loader_strip_create_extensions(pCreateInfo->pNext); 3329 3330 /* 3331 * NOTE: Need to filter the extensions to only those 3332 * supported by the ICD. 3333 * No ICD will advertise support for layers. An ICD 3334 * library could support a layer, but it would be 3335 * independent of the actual ICD, just in the same library. 3336 */ 3337 char **filtered_extension_names = NULL; 3338 filtered_extension_names = 3339 loader_stack_alloc(pCreateInfo->enabledExtensionCount * sizeof(char *)); 3340 if (!filtered_extension_names) { 3341 return VK_ERROR_OUT_OF_HOST_MEMORY; 3342 } 3343 3344 localCreateInfo.enabledLayerCount = 0; 3345 localCreateInfo.ppEnabledLayerNames = NULL; 3346 3347 localCreateInfo.enabledExtensionCount = 0; 3348 localCreateInfo.ppEnabledExtensionNames = 3349 (const char *const *)filtered_extension_names; 3350 3351 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) { 3352 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i]; 3353 VkExtensionProperties *prop = get_extension_property( 3354 extension_name, &phys_dev->device_extension_cache); 3355 if (prop) { 3356 filtered_extension_names[localCreateInfo.enabledExtensionCount] = 3357 (char *)extension_name; 3358 localCreateInfo.enabledExtensionCount++; 3359 } 3360 } 3361 3362 VkDevice localDevice; 3363 // TODO: Why does fpCreateDevice behave differently than 3364 // this_icd->CreateDevice? 3365 // VkResult res = fpCreateDevice(phys_dev->phys_dev, &localCreateInfo, 3366 // pAllocator, &localDevice); 3367 VkResult res = phys_dev->this_icd->CreateDevice( 3368 phys_dev->phys_dev, &localCreateInfo, pAllocator, &localDevice); 3369 3370 if (res != VK_SUCCESS) { 3371 return res; 3372 } 3373 3374 *pDevice = localDevice; 3375 3376 /* Init dispatch pointer in new device object */ 3377 loader_init_dispatch(*pDevice, &dev->loader_dispatch); 3378 3379 return res; 3380} 3381 3382VkResult loader_create_device_chain(VkPhysicalDevice physicalDevice, 3383 const VkDeviceCreateInfo *pCreateInfo, 3384 const VkAllocationCallbacks *pAllocator, 3385 struct loader_instance *inst, 3386 struct loader_icd *icd, 3387 struct loader_device *dev) { 3388 uint32_t activated_layers = 0; 3389 VkLayerDeviceLink *layer_device_link_info; 3390 VkLayerDeviceCreateInfo chain_info; 3391 VkLayerDeviceCreateInfo device_info; 3392 VkDeviceCreateInfo loader_create_info; 3393 VkResult res; 3394 3395 PFN_vkGetDeviceProcAddr fpGDPA, nextGDPA = icd->GetDeviceProcAddr; 3396 PFN_vkGetInstanceProcAddr fpGIPA, nextGIPA = loader_gpa_instance_internal; 3397 3398 memcpy(&loader_create_info, pCreateInfo, sizeof(VkDeviceCreateInfo)); 3399 3400 chain_info.sType = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO; 3401 chain_info.function = VK_LAYER_LINK_INFO; 3402 chain_info.u.pLayerInfo = NULL; 3403 chain_info.pNext = pCreateInfo->pNext; 3404 3405 layer_device_link_info = loader_stack_alloc( 3406 sizeof(VkLayerDeviceLink) * dev->activated_layer_list.count); 3407 if (!layer_device_link_info) { 3408 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 3409 "Failed to alloc Device objects for layer"); 3410 return VK_ERROR_OUT_OF_HOST_MEMORY; 3411 } 3412 3413 /* 3414 * This structure is used by loader_create_device_terminator 3415 * so that it can intialize the device dispatch table pointer 3416 * in the device object returned by the ICD. Without this 3417 * structure the code wouldn't know where the loader's device_info 3418 * structure is located. 3419 */ 3420 device_info.sType = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO; 3421 device_info.function = VK_LAYER_DEVICE_INFO; 3422 device_info.pNext = &chain_info; 3423 device_info.u.deviceInfo.device_info = dev; 3424 device_info.u.deviceInfo.pfnNextGetInstanceProcAddr = 3425 icd->this_icd_lib->GetInstanceProcAddr; 3426 3427 loader_create_info.pNext = &device_info; 3428 3429 if (dev->activated_layer_list.count > 0) { 3430 /* Create instance chain of enabled layers */ 3431 for (int32_t i = dev->activated_layer_list.count - 1; i >= 0; i--) { 3432 struct loader_layer_properties *layer_prop = 3433 &dev->activated_layer_list.list[i]; 3434 loader_platform_dl_handle lib_handle; 3435 3436 lib_handle = loader_add_layer_lib(inst, "device", layer_prop); 3437 if (!lib_handle) 3438 continue; 3439 if ((fpGIPA = layer_prop->functions.get_instance_proc_addr) == 3440 NULL) { 3441 if (layer_prop->functions.str_gipa == NULL || 3442 strlen(layer_prop->functions.str_gipa) == 0) { 3443 fpGIPA = (PFN_vkGetInstanceProcAddr) 3444 loader_platform_get_proc_address( 3445 lib_handle, "vkGetInstanceProcAddr"); 3446 layer_prop->functions.get_instance_proc_addr = fpGIPA; 3447 } else 3448 fpGIPA = (PFN_vkGetInstanceProcAddr) 3449 loader_platform_get_proc_address( 3450 lib_handle, layer_prop->functions.str_gipa); 3451 if (!fpGIPA) { 3452 loader_log( 3453 inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 3454 "Failed to find vkGetInstanceProcAddr in layer %s", 3455 layer_prop->lib_name); 3456 continue; 3457 } 3458 } 3459 if ((fpGDPA = layer_prop->functions.get_device_proc_addr) == NULL) { 3460 if (layer_prop->functions.str_gdpa == NULL || 3461 strlen(layer_prop->functions.str_gdpa) == 0) { 3462 fpGDPA = (PFN_vkGetDeviceProcAddr) 3463 loader_platform_get_proc_address(lib_handle, 3464 "vkGetDeviceProcAddr"); 3465 layer_prop->functions.get_device_proc_addr = fpGDPA; 3466 } else 3467 fpGDPA = (PFN_vkGetDeviceProcAddr) 3468 loader_platform_get_proc_address( 3469 lib_handle, layer_prop->functions.str_gdpa); 3470 if (!fpGDPA) { 3471 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 3472 "Failed to find vkGetDeviceProcAddr in layer %s", 3473 layer_prop->lib_name); 3474 continue; 3475 } 3476 } 3477 3478 layer_device_link_info[activated_layers].pNext = 3479 chain_info.u.pLayerInfo; 3480 layer_device_link_info[activated_layers] 3481 .pfnNextGetInstanceProcAddr = nextGIPA; 3482 layer_device_link_info[activated_layers].pfnNextGetDeviceProcAddr = 3483 nextGDPA; 3484 chain_info.u.pLayerInfo = &layer_device_link_info[activated_layers]; 3485 nextGIPA = fpGIPA; 3486 nextGDPA = fpGDPA; 3487 3488 loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, 3489 "Insert device layer %s (%s)", 3490 layer_prop->info.layerName, layer_prop->lib_name); 3491 3492 activated_layers++; 3493 } 3494 } 3495 3496 PFN_vkCreateDevice fpCreateDevice = 3497 (PFN_vkCreateDevice)nextGIPA((VkInstance)inst, "vkCreateDevice"); 3498 if (fpCreateDevice) { 3499 res = fpCreateDevice(physicalDevice, &loader_create_info, pAllocator, 3500 &dev->device); 3501 } else { 3502 // Couldn't find CreateDevice function! 3503 return VK_ERROR_INITIALIZATION_FAILED; 3504 } 3505 3506 /* Initialize device dispatch table */ 3507 loader_init_device_dispatch_table(&dev->loader_dispatch, nextGDPA, 3508 dev->device); 3509 3510 return res; 3511} 3512 3513VkResult loader_validate_layers(const struct loader_instance *inst, 3514 const uint32_t layer_count, 3515 const char *const *ppEnabledLayerNames, 3516 const struct loader_layer_list *list) { 3517 struct loader_layer_properties *prop; 3518 3519 for (uint32_t i = 0; i < layer_count; i++) { 3520 VkStringErrorFlags result = 3521 vk_string_validate(MaxLoaderStringLength, ppEnabledLayerNames[i]); 3522 if (result != VK_STRING_ERROR_NONE) { 3523 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 3524 "Loader: Device ppEnabledLayerNames contains string " 3525 "that is too long or is badly formed"); 3526 return VK_ERROR_LAYER_NOT_PRESENT; 3527 } 3528 3529 prop = loader_get_layer_property(ppEnabledLayerNames[i], list); 3530 if (!prop) { 3531 return VK_ERROR_LAYER_NOT_PRESENT; 3532 } 3533 } 3534 return VK_SUCCESS; 3535} 3536 3537VkResult loader_validate_instance_extensions( 3538 const struct loader_instance *inst, 3539 const struct loader_extension_list *icd_exts, 3540 const struct loader_layer_list *instance_layer, 3541 const VkInstanceCreateInfo *pCreateInfo) { 3542 3543 VkExtensionProperties *extension_prop; 3544 struct loader_layer_properties *layer_prop; 3545 3546 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) { 3547 VkStringErrorFlags result = vk_string_validate( 3548 MaxLoaderStringLength, pCreateInfo->ppEnabledExtensionNames[i]); 3549 if (result != VK_STRING_ERROR_NONE) { 3550 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 3551 "Loader: Instance ppEnabledExtensionNames contains " 3552 "string that is too long or is badly formed"); 3553 return VK_ERROR_EXTENSION_NOT_PRESENT; 3554 } 3555 3556 extension_prop = get_extension_property( 3557 pCreateInfo->ppEnabledExtensionNames[i], icd_exts); 3558 3559 if (extension_prop) { 3560 continue; 3561 } 3562 3563 extension_prop = NULL; 3564 3565 /* Not in global list, search layer extension lists */ 3566 for (uint32_t j = 0; j < pCreateInfo->enabledLayerCount; j++) { 3567 layer_prop = loader_get_layer_property( 3568 pCreateInfo->ppEnabledLayerNames[i], instance_layer); 3569 if (!layer_prop) { 3570 /* Should NOT get here, loader_validate_layers 3571 * should have already filtered this case out. 3572 */ 3573 continue; 3574 } 3575 3576 extension_prop = 3577 get_extension_property(pCreateInfo->ppEnabledExtensionNames[i], 3578 &layer_prop->instance_extension_list); 3579 if (extension_prop) { 3580 /* Found the extension in one of the layers enabled by the app. 3581 */ 3582 break; 3583 } 3584 } 3585 3586 if (!extension_prop) { 3587 /* Didn't find extension name in any of the global layers, error out 3588 */ 3589 return VK_ERROR_EXTENSION_NOT_PRESENT; 3590 } 3591 } 3592 return VK_SUCCESS; 3593} 3594 3595VkResult loader_validate_device_extensions( 3596 struct loader_physical_device *phys_dev, 3597 const struct loader_layer_list *activated_device_layers, 3598 const VkDeviceCreateInfo *pCreateInfo) { 3599 VkExtensionProperties *extension_prop; 3600 struct loader_layer_properties *layer_prop; 3601 3602 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) { 3603 3604 VkStringErrorFlags result = vk_string_validate( 3605 MaxLoaderStringLength, pCreateInfo->ppEnabledExtensionNames[i]); 3606 if (result != VK_STRING_ERROR_NONE) { 3607 loader_log(phys_dev->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 3608 0, "Loader: Device ppEnabledExtensionNames contains " 3609 "string that is too long or is badly formed"); 3610 return VK_ERROR_EXTENSION_NOT_PRESENT; 3611 } 3612 3613 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i]; 3614 extension_prop = get_extension_property( 3615 extension_name, &phys_dev->device_extension_cache); 3616 3617 if (extension_prop) { 3618 continue; 3619 } 3620 3621 /* Not in global list, search activated layer extension lists */ 3622 for (uint32_t j = 0; j < activated_device_layers->count; j++) { 3623 layer_prop = &activated_device_layers->list[j]; 3624 3625 extension_prop = get_dev_extension_property( 3626 extension_name, &layer_prop->device_extension_list); 3627 if (extension_prop) { 3628 /* Found the extension in one of the layers enabled by the app. 3629 */ 3630 break; 3631 } 3632 } 3633 3634 if (!extension_prop) { 3635 /* Didn't find extension name in any of the device layers, error out 3636 */ 3637 return VK_ERROR_EXTENSION_NOT_PRESENT; 3638 } 3639 } 3640 return VK_SUCCESS; 3641} 3642 3643VKAPI_ATTR VkResult VKAPI_CALL 3644loader_CreateInstance(const VkInstanceCreateInfo *pCreateInfo, 3645 const VkAllocationCallbacks *pAllocator, 3646 VkInstance *pInstance) { 3647 struct loader_icd *icd; 3648 VkExtensionProperties *prop; 3649 char **filtered_extension_names = NULL; 3650 VkInstanceCreateInfo icd_create_info; 3651 VkResult res = VK_SUCCESS; 3652 bool success = false; 3653 3654 VkLayerInstanceCreateInfo *chain_info = 3655 (VkLayerInstanceCreateInfo *)pCreateInfo->pNext; 3656 while ( 3657 chain_info && 3658 !(chain_info->sType == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO && 3659 chain_info->function == VK_LAYER_INSTANCE_INFO)) { 3660 chain_info = (VkLayerInstanceCreateInfo *)chain_info->pNext; 3661 } 3662 assert(chain_info != NULL); 3663 3664 struct loader_instance *ptr_instance = 3665 (struct loader_instance *)chain_info->u.instanceInfo.instance_info; 3666 memcpy(&icd_create_info, pCreateInfo, sizeof(icd_create_info)); 3667 3668 icd_create_info.enabledLayerCount = 0; 3669 icd_create_info.ppEnabledLayerNames = NULL; 3670 3671 // strip off the VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO entries 3672 icd_create_info.pNext = loader_strip_create_extensions(pCreateInfo->pNext); 3673 3674 /* 3675 * NOTE: Need to filter the extensions to only those 3676 * supported by the ICD. 3677 * No ICD will advertise support for layers. An ICD 3678 * library could support a layer, but it would be 3679 * independent of the actual ICD, just in the same library. 3680 */ 3681 filtered_extension_names = 3682 loader_stack_alloc(pCreateInfo->enabledExtensionCount * sizeof(char *)); 3683 if (!filtered_extension_names) { 3684 return VK_ERROR_OUT_OF_HOST_MEMORY; 3685 } 3686 icd_create_info.ppEnabledExtensionNames = 3687 (const char *const *)filtered_extension_names; 3688 3689 for (uint32_t i = 0; i < ptr_instance->icd_libs.count; i++) { 3690 icd = loader_icd_add(ptr_instance, &ptr_instance->icd_libs.list[i]); 3691 if (icd) { 3692 icd_create_info.enabledExtensionCount = 0; 3693 struct loader_extension_list icd_exts; 3694 3695 loader_log(ptr_instance, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, 3696 "Build ICD instance extension list"); 3697 // traverse scanned icd list adding non-duplicate extensions to the 3698 // list 3699 loader_init_generic_list(ptr_instance, 3700 (struct loader_generic_list *)&icd_exts, 3701 sizeof(VkExtensionProperties)); 3702 loader_add_instance_extensions( 3703 ptr_instance, 3704 icd->this_icd_lib->EnumerateInstanceExtensionProperties, 3705 icd->this_icd_lib->lib_name, &icd_exts); 3706 3707 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) { 3708 prop = get_extension_property( 3709 pCreateInfo->ppEnabledExtensionNames[i], &icd_exts); 3710 if (prop) { 3711 filtered_extension_names[icd_create_info 3712 .enabledExtensionCount] = 3713 (char *)pCreateInfo->ppEnabledExtensionNames[i]; 3714 icd_create_info.enabledExtensionCount++; 3715 } 3716 } 3717 3718 loader_destroy_generic_list( 3719 ptr_instance, (struct loader_generic_list *)&icd_exts); 3720 3721 res = ptr_instance->icd_libs.list[i].CreateInstance( 3722 &icd_create_info, pAllocator, &(icd->instance)); 3723 if (res == VK_SUCCESS) 3724 success = loader_icd_init_entrys( 3725 icd, icd->instance, 3726 ptr_instance->icd_libs.list[i].GetInstanceProcAddr); 3727 3728 if (res != VK_SUCCESS || !success) { 3729 ptr_instance->icds = ptr_instance->icds->next; 3730 loader_icd_destroy(ptr_instance, icd); 3731 loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 3732 "ICD ignored: failed to CreateInstance and find " 3733 "entrypoints with ICD"); 3734 } 3735 } 3736 } 3737 3738 /* 3739 * If no ICDs were added to instance list and res is unchanged 3740 * from it's initial value, the loader was unable to find 3741 * a suitable ICD. 3742 */ 3743 if (ptr_instance->icds == NULL) { 3744 if (res == VK_SUCCESS) { 3745 return VK_ERROR_INCOMPATIBLE_DRIVER; 3746 } else { 3747 return res; 3748 } 3749 } 3750 3751 return VK_SUCCESS; 3752} 3753 3754VKAPI_ATTR void VKAPI_CALL 3755loader_DestroyInstance(VkInstance instance, 3756 const VkAllocationCallbacks *pAllocator) { 3757 struct loader_instance *ptr_instance = loader_instance(instance); 3758 struct loader_icd *icds = ptr_instance->icds; 3759 struct loader_icd *next_icd; 3760 3761 // Remove this instance from the list of instances: 3762 struct loader_instance *prev = NULL; 3763 struct loader_instance *next = loader.instances; 3764 while (next != NULL) { 3765 if (next == ptr_instance) { 3766 // Remove this instance from the list: 3767 if (prev) 3768 prev->next = next->next; 3769 else 3770 loader.instances = next->next; 3771 break; 3772 } 3773 prev = next; 3774 next = next->next; 3775 } 3776 3777 while (icds) { 3778 if (icds->instance) { 3779 icds->DestroyInstance(icds->instance, pAllocator); 3780 } 3781 next_icd = icds->next; 3782 icds->instance = VK_NULL_HANDLE; 3783 loader_icd_destroy(ptr_instance, icds); 3784 3785 icds = next_icd; 3786 } 3787 loader_delete_layer_properties(ptr_instance, 3788 &ptr_instance->device_layer_list); 3789 loader_delete_layer_properties(ptr_instance, 3790 &ptr_instance->instance_layer_list); 3791 loader_scanned_icd_clear(ptr_instance, &ptr_instance->icd_libs); 3792 loader_destroy_generic_list( 3793 ptr_instance, (struct loader_generic_list *)&ptr_instance->ext_list); 3794 for (uint32_t i = 0; i < ptr_instance->total_gpu_count; i++) 3795 loader_destroy_generic_list( 3796 ptr_instance, 3797 (struct loader_generic_list *)&ptr_instance->phys_devs[i] 3798 .device_extension_cache); 3799 loader_heap_free(ptr_instance, ptr_instance->phys_devs); 3800 loader_free_dev_ext_table(ptr_instance); 3801} 3802 3803VkResult 3804loader_init_physical_device_info(struct loader_instance *ptr_instance) { 3805 struct loader_icd *icd; 3806 uint32_t i, j, idx, count = 0; 3807 VkResult res; 3808 struct loader_phys_dev_per_icd *phys_devs; 3809 3810 ptr_instance->total_gpu_count = 0; 3811 phys_devs = (struct loader_phys_dev_per_icd *)loader_stack_alloc( 3812 sizeof(struct loader_phys_dev_per_icd) * ptr_instance->total_icd_count); 3813 if (!phys_devs) 3814 return VK_ERROR_OUT_OF_HOST_MEMORY; 3815 3816 icd = ptr_instance->icds; 3817 for (i = 0; i < ptr_instance->total_icd_count; i++) { 3818 assert(icd); 3819 res = icd->EnumeratePhysicalDevices(icd->instance, &phys_devs[i].count, 3820 NULL); 3821 if (res != VK_SUCCESS) 3822 return res; 3823 count += phys_devs[i].count; 3824 icd = icd->next; 3825 } 3826 3827 ptr_instance->phys_devs = 3828 (struct loader_physical_device *)loader_heap_alloc( 3829 ptr_instance, count * sizeof(struct loader_physical_device), 3830 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 3831 if (!ptr_instance->phys_devs) 3832 return VK_ERROR_OUT_OF_HOST_MEMORY; 3833 3834 icd = ptr_instance->icds; 3835 3836 struct loader_physical_device *inst_phys_devs = ptr_instance->phys_devs; 3837 idx = 0; 3838 for (i = 0; i < ptr_instance->total_icd_count; i++) { 3839 assert(icd); 3840 3841 phys_devs[i].phys_devs = (VkPhysicalDevice *)loader_stack_alloc( 3842 phys_devs[i].count * sizeof(VkPhysicalDevice)); 3843 if (!phys_devs[i].phys_devs) { 3844 loader_heap_free(ptr_instance, ptr_instance->phys_devs); 3845 ptr_instance->phys_devs = NULL; 3846 return VK_ERROR_OUT_OF_HOST_MEMORY; 3847 } 3848 res = icd->EnumeratePhysicalDevices( 3849 icd->instance, &(phys_devs[i].count), phys_devs[i].phys_devs); 3850 if ((res == VK_SUCCESS)) { 3851 ptr_instance->total_gpu_count += phys_devs[i].count; 3852 for (j = 0; j < phys_devs[i].count; j++) { 3853 3854 // initialize the loader's physicalDevice object 3855 loader_set_dispatch((void *)&inst_phys_devs[idx], 3856 ptr_instance->disp); 3857 inst_phys_devs[idx].this_instance = ptr_instance; 3858 inst_phys_devs[idx].this_icd = icd; 3859 inst_phys_devs[idx].phys_dev = phys_devs[i].phys_devs[j]; 3860 memset(&inst_phys_devs[idx].device_extension_cache, 0, 3861 sizeof(struct loader_extension_list)); 3862 3863 idx++; 3864 } 3865 } else { 3866 loader_heap_free(ptr_instance, ptr_instance->phys_devs); 3867 ptr_instance->phys_devs = NULL; 3868 return res; 3869 } 3870 3871 icd = icd->next; 3872 } 3873 3874 return VK_SUCCESS; 3875} 3876 3877VKAPI_ATTR VkResult VKAPI_CALL 3878loader_EnumeratePhysicalDevices(VkInstance instance, 3879 uint32_t *pPhysicalDeviceCount, 3880 VkPhysicalDevice *pPhysicalDevices) { 3881 uint32_t i; 3882 uint32_t copy_count = 0; 3883 struct loader_instance *ptr_instance = (struct loader_instance *)instance; 3884 VkResult res = VK_SUCCESS; 3885 3886 if (ptr_instance->total_gpu_count == 0) { 3887 res = loader_init_physical_device_info(ptr_instance); 3888 } 3889 3890 *pPhysicalDeviceCount = ptr_instance->total_gpu_count; 3891 if (!pPhysicalDevices) { 3892 return res; 3893 } 3894 3895 copy_count = (ptr_instance->total_gpu_count < *pPhysicalDeviceCount) 3896 ? ptr_instance->total_gpu_count 3897 : *pPhysicalDeviceCount; 3898 for (i = 0; i < copy_count; i++) { 3899 pPhysicalDevices[i] = (VkPhysicalDevice)&ptr_instance->phys_devs[i]; 3900 } 3901 *pPhysicalDeviceCount = copy_count; 3902 3903 if (copy_count < ptr_instance->total_gpu_count) { 3904 return VK_INCOMPLETE; 3905 } 3906 3907 return res; 3908} 3909 3910VKAPI_ATTR void VKAPI_CALL 3911loader_GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, 3912 VkPhysicalDeviceProperties *pProperties) { 3913 struct loader_physical_device *phys_dev = 3914 (struct loader_physical_device *)physicalDevice; 3915 struct loader_icd *icd = phys_dev->this_icd; 3916 3917 if (icd->GetPhysicalDeviceProperties) 3918 icd->GetPhysicalDeviceProperties(phys_dev->phys_dev, pProperties); 3919} 3920 3921VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceQueueFamilyProperties( 3922 VkPhysicalDevice physicalDevice, uint32_t *pQueueFamilyPropertyCount, 3923 VkQueueFamilyProperties *pProperties) { 3924 struct loader_physical_device *phys_dev = 3925 (struct loader_physical_device *)physicalDevice; 3926 struct loader_icd *icd = phys_dev->this_icd; 3927 3928 if (icd->GetPhysicalDeviceQueueFamilyProperties) 3929 icd->GetPhysicalDeviceQueueFamilyProperties( 3930 phys_dev->phys_dev, pQueueFamilyPropertyCount, pProperties); 3931} 3932 3933VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceMemoryProperties( 3934 VkPhysicalDevice physicalDevice, 3935 VkPhysicalDeviceMemoryProperties *pProperties) { 3936 struct loader_physical_device *phys_dev = 3937 (struct loader_physical_device *)physicalDevice; 3938 struct loader_icd *icd = phys_dev->this_icd; 3939 3940 if (icd->GetPhysicalDeviceMemoryProperties) 3941 icd->GetPhysicalDeviceMemoryProperties(phys_dev->phys_dev, pProperties); 3942} 3943 3944VKAPI_ATTR void VKAPI_CALL 3945loader_GetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice, 3946 VkPhysicalDeviceFeatures *pFeatures) { 3947 struct loader_physical_device *phys_dev = 3948 (struct loader_physical_device *)physicalDevice; 3949 struct loader_icd *icd = phys_dev->this_icd; 3950 3951 if (icd->GetPhysicalDeviceFeatures) 3952 icd->GetPhysicalDeviceFeatures(phys_dev->phys_dev, pFeatures); 3953} 3954 3955VKAPI_ATTR void VKAPI_CALL 3956loader_GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, 3957 VkFormat format, 3958 VkFormatProperties *pFormatInfo) { 3959 struct loader_physical_device *phys_dev = 3960 (struct loader_physical_device *)physicalDevice; 3961 struct loader_icd *icd = phys_dev->this_icd; 3962 3963 if (icd->GetPhysicalDeviceFormatProperties) 3964 icd->GetPhysicalDeviceFormatProperties(phys_dev->phys_dev, format, 3965 pFormatInfo); 3966} 3967 3968VKAPI_ATTR VkResult VKAPI_CALL loader_GetPhysicalDeviceImageFormatProperties( 3969 VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, 3970 VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, 3971 VkImageFormatProperties *pImageFormatProperties) { 3972 struct loader_physical_device *phys_dev = 3973 (struct loader_physical_device *)physicalDevice; 3974 struct loader_icd *icd = phys_dev->this_icd; 3975 3976 if (!icd->GetPhysicalDeviceImageFormatProperties) 3977 return VK_ERROR_INITIALIZATION_FAILED; 3978 3979 return icd->GetPhysicalDeviceImageFormatProperties( 3980 phys_dev->phys_dev, format, type, tiling, usage, flags, 3981 pImageFormatProperties); 3982} 3983 3984VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceSparseImageFormatProperties( 3985 VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, 3986 VkSampleCountFlagBits samples, VkImageUsageFlags usage, 3987 VkImageTiling tiling, uint32_t *pNumProperties, 3988 VkSparseImageFormatProperties *pProperties) { 3989 struct loader_physical_device *phys_dev = 3990 (struct loader_physical_device *)physicalDevice; 3991 struct loader_icd *icd = phys_dev->this_icd; 3992 3993 if (icd->GetPhysicalDeviceSparseImageFormatProperties) 3994 icd->GetPhysicalDeviceSparseImageFormatProperties( 3995 phys_dev->phys_dev, format, type, samples, usage, tiling, 3996 pNumProperties, pProperties); 3997} 3998 3999VKAPI_ATTR VkResult VKAPI_CALL 4000loader_CreateDevice(VkPhysicalDevice physicalDevice, 4001 const VkDeviceCreateInfo *pCreateInfo, 4002 const VkAllocationCallbacks *pAllocator, 4003 VkDevice *pDevice) { 4004 struct loader_physical_device *phys_dev; 4005 struct loader_icd *icd; 4006 struct loader_device *dev; 4007 struct loader_instance *inst; 4008 struct loader_layer_list activated_layer_list = {0}; 4009 VkResult res; 4010 4011 assert(pCreateInfo->queueCreateInfoCount >= 1); 4012 4013 // TODO this only works for one physical device per instance 4014 // once CreateDevice layer bootstrapping is done via DeviceCreateInfo 4015 // hopefully don't need this anymore in trampoline code 4016 phys_dev = loader_get_physical_device(physicalDevice); 4017 icd = phys_dev->this_icd; 4018 if (!icd) 4019 return VK_ERROR_INITIALIZATION_FAILED; 4020 4021 inst = phys_dev->this_instance; 4022 4023 if (!icd->CreateDevice) { 4024 return VK_ERROR_INITIALIZATION_FAILED; 4025 } 4026 4027 /* validate any app enabled layers are available */ 4028 if (pCreateInfo->enabledLayerCount > 0) { 4029 res = loader_validate_layers(inst, pCreateInfo->enabledLayerCount, 4030 pCreateInfo->ppEnabledLayerNames, 4031 &inst->device_layer_list); 4032 if (res != VK_SUCCESS) { 4033 return res; 4034 } 4035 } 4036 4037 /* Get the physical device extensions if they haven't been retrieved yet */ 4038 if (phys_dev->device_extension_cache.capacity == 0) { 4039 if (!loader_init_generic_list( 4040 inst, 4041 (struct loader_generic_list *)&phys_dev->device_extension_cache, 4042 sizeof(VkExtensionProperties))) { 4043 return VK_ERROR_OUT_OF_HOST_MEMORY; 4044 } 4045 4046 res = loader_add_device_extensions( 4047 inst, icd, phys_dev->phys_dev, 4048 phys_dev->this_icd->this_icd_lib->lib_name, 4049 &phys_dev->device_extension_cache); 4050 if (res != VK_SUCCESS) { 4051 return res; 4052 } 4053 } 4054 4055 /* convert any meta layers to the actual layers makes a copy of layer name*/ 4056 uint32_t saved_layer_count = pCreateInfo->enabledLayerCount; 4057 char **saved_layer_names; 4058 char **saved_layer_ptr; 4059 saved_layer_names = 4060 loader_stack_alloc(sizeof(char *) * pCreateInfo->enabledLayerCount); 4061 for (uint32_t i = 0; i < saved_layer_count; i++) { 4062 saved_layer_names[i] = (char *)pCreateInfo->ppEnabledLayerNames[i]; 4063 } 4064 saved_layer_ptr = (char **)pCreateInfo->ppEnabledLayerNames; 4065 4066 loader_expand_layer_names( 4067 inst, std_validation_str, 4068 sizeof(std_validation_names) / sizeof(std_validation_names[0]), 4069 std_validation_names, (uint32_t *)&pCreateInfo->enabledLayerCount, 4070 (char ***)&pCreateInfo->ppEnabledLayerNames); 4071 4072 /* fetch a list of all layers activated, explicit and implicit */ 4073 res = loader_enable_device_layers(inst, icd, &activated_layer_list, 4074 pCreateInfo, &inst->device_layer_list); 4075 if (res != VK_SUCCESS) { 4076 loader_unexpand_dev_layer_names(inst, saved_layer_count, 4077 saved_layer_names, saved_layer_ptr, 4078 pCreateInfo); 4079 return res; 4080 } 4081 4082 /* make sure requested extensions to be enabled are supported */ 4083 res = loader_validate_device_extensions(phys_dev, &activated_layer_list, 4084 pCreateInfo); 4085 if (res != VK_SUCCESS) { 4086 loader_unexpand_dev_layer_names(inst, saved_layer_count, 4087 saved_layer_names, saved_layer_ptr, 4088 pCreateInfo); 4089 loader_destroy_generic_list( 4090 inst, (struct loader_generic_list *)&activated_layer_list); 4091 return res; 4092 } 4093 4094 dev = loader_add_logical_device(inst, &icd->logical_device_list); 4095 if (dev == NULL) { 4096 loader_unexpand_dev_layer_names(inst, saved_layer_count, 4097 saved_layer_names, saved_layer_ptr, 4098 pCreateInfo); 4099 loader_destroy_generic_list( 4100 inst, (struct loader_generic_list *)&activated_layer_list); 4101 return VK_ERROR_OUT_OF_HOST_MEMORY; 4102 } 4103 4104 /* move the locally filled layer list into the device, and pass ownership of 4105 * the memory */ 4106 dev->activated_layer_list.capacity = activated_layer_list.capacity; 4107 dev->activated_layer_list.count = activated_layer_list.count; 4108 dev->activated_layer_list.list = activated_layer_list.list; 4109 memset(&activated_layer_list, 0, sizeof(activated_layer_list)); 4110 4111 /* activate any layers on device chain which terminates with device*/ 4112 res = loader_enable_device_layers(inst, icd, &dev->activated_layer_list, 4113 pCreateInfo, &inst->device_layer_list); 4114 if (res != VK_SUCCESS) { 4115 loader_unexpand_dev_layer_names(inst, saved_layer_count, 4116 saved_layer_names, saved_layer_ptr, 4117 pCreateInfo); 4118 loader_remove_logical_device(inst, icd, dev); 4119 return res; 4120 } 4121 4122 res = loader_create_device_chain(physicalDevice, pCreateInfo, pAllocator, 4123 inst, icd, dev); 4124 if (res != VK_SUCCESS) { 4125 loader_unexpand_dev_layer_names(inst, saved_layer_count, 4126 saved_layer_names, saved_layer_ptr, 4127 pCreateInfo); 4128 loader_remove_logical_device(inst, icd, dev); 4129 return res; 4130 } 4131 4132 *pDevice = dev->device; 4133 4134 /* initialize any device extension dispatch entry's from the instance list*/ 4135 loader_init_dispatch_dev_ext(inst, dev); 4136 4137 /* initialize WSI device extensions as part of core dispatch since loader 4138 * has 4139 * dedicated trampoline code for these*/ 4140 loader_init_device_extension_dispatch_table( 4141 &dev->loader_dispatch, 4142 dev->loader_dispatch.core_dispatch.GetDeviceProcAddr, *pDevice); 4143 4144 loader_unexpand_dev_layer_names(inst, saved_layer_count, saved_layer_names, 4145 saved_layer_ptr, pCreateInfo); 4146 return res; 4147} 4148 4149/** 4150 * Get an instance level or global level entry point address. 4151 * @param instance 4152 * @param pName 4153 * @return 4154 * If instance == NULL returns a global level functions only 4155 * If instance is valid returns a trampoline entry point for all dispatchable 4156 * Vulkan 4157 * functions both core and extensions. 4158 */ 4159LOADER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL 4160vkGetInstanceProcAddr(VkInstance instance, const char *pName) { 4161 4162 void *addr; 4163 4164 addr = globalGetProcAddr(pName); 4165 if (instance == VK_NULL_HANDLE) { 4166 // get entrypoint addresses that are global (no dispatchable object) 4167 4168 return addr; 4169 } else { 4170 // if a global entrypoint return NULL 4171 if (addr) 4172 return NULL; 4173 } 4174 4175 struct loader_instance *ptr_instance = loader_get_instance(instance); 4176 if (ptr_instance == NULL) 4177 return NULL; 4178 // Return trampoline code for non-global entrypoints including any 4179 // extensions. 4180 // Device extensions are returned if a layer or ICD supports the extension. 4181 // Instance extensions are returned if the extension is enabled and the 4182 // loader 4183 // or someone else supports the extension 4184 return trampolineGetProcAddr(ptr_instance, pName); 4185} 4186 4187/** 4188 * Get a device level or global level entry point address. 4189 * @param device 4190 * @param pName 4191 * @return 4192 * If device is valid, returns a device relative entry point for device level 4193 * entry points both core and extensions. 4194 * Device relative means call down the device chain. 4195 */ 4196LOADER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL 4197vkGetDeviceProcAddr(VkDevice device, const char *pName) { 4198 void *addr; 4199 4200 /* for entrypoints that loader must handle (ie non-dispatchable or create 4201 object) 4202 make sure the loader entrypoint is returned */ 4203 addr = loader_non_passthrough_gdpa(pName); 4204 if (addr) { 4205 return addr; 4206 } 4207 4208 /* Although CreateDevice is on device chain it's dispatchable object isn't 4209 * a VkDevice or child of VkDevice so return NULL. 4210 */ 4211 if (!strcmp(pName, "CreateDevice")) 4212 return NULL; 4213 4214 /* return the dispatch table entrypoint for the fastest case */ 4215 const VkLayerDispatchTable *disp_table = *(VkLayerDispatchTable **)device; 4216 if (disp_table == NULL) 4217 return NULL; 4218 4219 addr = loader_lookup_device_dispatch_table(disp_table, pName); 4220 if (addr) 4221 return addr; 4222 4223 if (disp_table->GetDeviceProcAddr == NULL) 4224 return NULL; 4225 return disp_table->GetDeviceProcAddr(device, pName); 4226} 4227 4228LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL 4229vkEnumerateInstanceExtensionProperties(const char *pLayerName, 4230 uint32_t *pPropertyCount, 4231 VkExtensionProperties *pProperties) { 4232 struct loader_extension_list *global_ext_list = NULL; 4233 struct loader_layer_list instance_layers; 4234 struct loader_extension_list icd_extensions; 4235 struct loader_icd_libs icd_libs; 4236 uint32_t copy_size; 4237 4238 tls_instance = NULL; 4239 memset(&icd_extensions, 0, sizeof(icd_extensions)); 4240 memset(&instance_layers, 0, sizeof(instance_layers)); 4241 loader_platform_thread_once(&once_init, loader_initialize); 4242 4243 /* get layer libraries if needed */ 4244 if (pLayerName && strlen(pLayerName) != 0) { 4245 if (vk_string_validate(MaxLoaderStringLength, pLayerName) == 4246 VK_STRING_ERROR_NONE) { 4247 loader_layer_scan(NULL, &instance_layers, NULL); 4248 for (uint32_t i = 0; i < instance_layers.count; i++) { 4249 struct loader_layer_properties *props = 4250 &instance_layers.list[i]; 4251 if (strcmp(props->info.layerName, pLayerName) == 0) { 4252 global_ext_list = &props->instance_extension_list; 4253 } 4254 } 4255 } else { 4256 assert(VK_FALSE && "vkEnumerateInstanceExtensionProperties: " 4257 "pLayerName is too long or is badly formed"); 4258 return VK_ERROR_EXTENSION_NOT_PRESENT; 4259 } 4260 } else { 4261 /* Scan/discover all ICD libraries */ 4262 memset(&icd_libs, 0, sizeof(struct loader_icd_libs)); 4263 loader_icd_scan(NULL, &icd_libs); 4264 /* get extensions from all ICD's, merge so no duplicates */ 4265 loader_get_icd_loader_instance_extensions(NULL, &icd_libs, 4266 &icd_extensions); 4267 loader_scanned_icd_clear(NULL, &icd_libs); 4268 global_ext_list = &icd_extensions; 4269 } 4270 4271 if (global_ext_list == NULL) { 4272 loader_destroy_layer_list(NULL, &instance_layers); 4273 return VK_ERROR_LAYER_NOT_PRESENT; 4274 } 4275 4276 if (pProperties == NULL) { 4277 *pPropertyCount = global_ext_list->count; 4278 loader_destroy_layer_list(NULL, &instance_layers); 4279 loader_destroy_generic_list( 4280 NULL, (struct loader_generic_list *)&icd_extensions); 4281 return VK_SUCCESS; 4282 } 4283 4284 copy_size = *pPropertyCount < global_ext_list->count 4285 ? *pPropertyCount 4286 : global_ext_list->count; 4287 for (uint32_t i = 0; i < copy_size; i++) { 4288 memcpy(&pProperties[i], &global_ext_list->list[i], 4289 sizeof(VkExtensionProperties)); 4290 } 4291 *pPropertyCount = copy_size; 4292 loader_destroy_generic_list(NULL, 4293 (struct loader_generic_list *)&icd_extensions); 4294 4295 if (copy_size < global_ext_list->count) { 4296 loader_destroy_layer_list(NULL, &instance_layers); 4297 return VK_INCOMPLETE; 4298 } 4299 4300 loader_destroy_layer_list(NULL, &instance_layers); 4301 return VK_SUCCESS; 4302} 4303 4304LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL 4305vkEnumerateInstanceLayerProperties(uint32_t *pPropertyCount, 4306 VkLayerProperties *pProperties) { 4307 4308 struct loader_layer_list instance_layer_list; 4309 tls_instance = NULL; 4310 4311 loader_platform_thread_once(&once_init, loader_initialize); 4312 4313 uint32_t copy_size; 4314 4315 /* get layer libraries */ 4316 memset(&instance_layer_list, 0, sizeof(instance_layer_list)); 4317 loader_layer_scan(NULL, &instance_layer_list, NULL); 4318 4319 if (pProperties == NULL) { 4320 *pPropertyCount = instance_layer_list.count; 4321 loader_destroy_layer_list(NULL, &instance_layer_list); 4322 return VK_SUCCESS; 4323 } 4324 4325 copy_size = (*pPropertyCount < instance_layer_list.count) 4326 ? *pPropertyCount 4327 : instance_layer_list.count; 4328 for (uint32_t i = 0; i < copy_size; i++) { 4329 memcpy(&pProperties[i], &instance_layer_list.list[i].info, 4330 sizeof(VkLayerProperties)); 4331 } 4332 4333 *pPropertyCount = copy_size; 4334 loader_destroy_layer_list(NULL, &instance_layer_list); 4335 4336 if (copy_size < instance_layer_list.count) { 4337 return VK_INCOMPLETE; 4338 } 4339 4340 return VK_SUCCESS; 4341} 4342 4343VKAPI_ATTR VkResult VKAPI_CALL 4344loader_EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, 4345 const char *pLayerName, 4346 uint32_t *pPropertyCount, 4347 VkExtensionProperties *pProperties) { 4348 struct loader_physical_device *phys_dev; 4349 uint32_t copy_size; 4350 4351 uint32_t count; 4352 struct loader_device_extension_list *dev_ext_list = NULL; 4353 struct loader_layer_list implicit_layer_list; 4354 4355 // TODO fix this aliases physical devices 4356 phys_dev = loader_get_physical_device(physicalDevice); 4357 4358 /* get layer libraries if needed */ 4359 if (pLayerName && strlen(pLayerName) != 0) { 4360 if (vk_string_validate(MaxLoaderStringLength, pLayerName) == 4361 VK_STRING_ERROR_NONE) { 4362 for (uint32_t i = 0; 4363 i < phys_dev->this_instance->device_layer_list.count; i++) { 4364 struct loader_layer_properties *props = 4365 &phys_dev->this_instance->device_layer_list.list[i]; 4366 if (strcmp(props->info.layerName, pLayerName) == 0) { 4367 dev_ext_list = &props->device_extension_list; 4368 } 4369 } 4370 count = (dev_ext_list == NULL) ? 0 : dev_ext_list->count; 4371 if (pProperties == NULL) { 4372 *pPropertyCount = count; 4373 return VK_SUCCESS; 4374 } 4375 4376 copy_size = *pPropertyCount < count ? *pPropertyCount : count; 4377 for (uint32_t i = 0; i < copy_size; i++) { 4378 memcpy(&pProperties[i], &dev_ext_list->list[i].props, 4379 sizeof(VkExtensionProperties)); 4380 } 4381 *pPropertyCount = copy_size; 4382 4383 if (copy_size < count) { 4384 return VK_INCOMPLETE; 4385 } 4386 } else { 4387 loader_log(phys_dev->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 4388 0, "vkEnumerateDeviceExtensionProperties: pLayerName " 4389 "is too long or is badly formed"); 4390 return VK_ERROR_EXTENSION_NOT_PRESENT; 4391 } 4392 return VK_SUCCESS; 4393 } else { 4394 /* this case is during the call down the instance chain with pLayerName 4395 * == NULL*/ 4396 struct loader_icd *icd = phys_dev->this_icd; 4397 uint32_t icd_ext_count = *pPropertyCount; 4398 VkResult res; 4399 4400 /* get device extensions */ 4401 res = icd->EnumerateDeviceExtensionProperties( 4402 phys_dev->phys_dev, NULL, &icd_ext_count, pProperties); 4403 if (res != VK_SUCCESS) 4404 return res; 4405 4406 loader_init_layer_list(phys_dev->this_instance, &implicit_layer_list); 4407 4408 loader_add_layer_implicit( 4409 phys_dev->this_instance, VK_LAYER_TYPE_INSTANCE_IMPLICIT, 4410 &implicit_layer_list, 4411 &phys_dev->this_instance->instance_layer_list); 4412 /* we need to determine which implicit layers are active, 4413 * and then add their extensions. This can't be cached as 4414 * it depends on results of environment variables (which can change). 4415 */ 4416 if (pProperties != NULL) { 4417 /* initialize dev_extension list within the physicalDevice object */ 4418 res = loader_init_device_extensions( 4419 phys_dev->this_instance, phys_dev, icd_ext_count, pProperties, 4420 &phys_dev->device_extension_cache); 4421 if (res != VK_SUCCESS) 4422 return res; 4423 4424 /* we need to determine which implicit layers are active, 4425 * and then add their extensions. This can't be cached as 4426 * it depends on results of environment variables (which can 4427 * change). 4428 */ 4429 struct loader_extension_list all_exts = {0}; 4430 loader_add_to_ext_list(phys_dev->this_instance, &all_exts, 4431 phys_dev->device_extension_cache.count, 4432 phys_dev->device_extension_cache.list); 4433 4434 loader_init_layer_list(phys_dev->this_instance, 4435 &implicit_layer_list); 4436 4437 loader_add_layer_implicit( 4438 phys_dev->this_instance, VK_LAYER_TYPE_INSTANCE_IMPLICIT, 4439 &implicit_layer_list, 4440 &phys_dev->this_instance->instance_layer_list); 4441 4442 for (uint32_t i = 0; i < implicit_layer_list.count; i++) { 4443 for ( 4444 uint32_t j = 0; 4445 j < implicit_layer_list.list[i].device_extension_list.count; 4446 j++) { 4447 loader_add_to_ext_list(phys_dev->this_instance, &all_exts, 4448 1, 4449 &implicit_layer_list.list[i] 4450 .device_extension_list.list[j] 4451 .props); 4452 } 4453 } 4454 uint32_t capacity = *pPropertyCount; 4455 VkExtensionProperties *props = pProperties; 4456 4457 for (uint32_t i = 0; i < all_exts.count && i < capacity; i++) { 4458 props[i] = all_exts.list[i]; 4459 } 4460 /* wasn't enough space for the extensions, we did partial copy now 4461 * return VK_INCOMPLETE */ 4462 if (capacity < all_exts.count) { 4463 res = VK_INCOMPLETE; 4464 } else { 4465 *pPropertyCount = all_exts.count; 4466 } 4467 loader_destroy_generic_list( 4468 phys_dev->this_instance, 4469 (struct loader_generic_list *)&all_exts); 4470 } else { 4471 /* just return the count; need to add in the count of implicit layer 4472 * extensions 4473 * don't worry about duplicates being added in the count */ 4474 *pPropertyCount = icd_ext_count; 4475 4476 for (uint32_t i = 0; i < implicit_layer_list.count; i++) { 4477 *pPropertyCount += 4478 implicit_layer_list.list[i].device_extension_list.count; 4479 } 4480 res = VK_SUCCESS; 4481 } 4482 4483 loader_destroy_generic_list( 4484 phys_dev->this_instance, 4485 (struct loader_generic_list *)&implicit_layer_list); 4486 return res; 4487 } 4488} 4489 4490VKAPI_ATTR VkResult VKAPI_CALL 4491loader_EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, 4492 uint32_t *pPropertyCount, 4493 VkLayerProperties *pProperties) { 4494 uint32_t copy_size; 4495 struct loader_physical_device *phys_dev; 4496 // TODO fix this, aliases physical devices 4497 phys_dev = loader_get_physical_device(physicalDevice); 4498 uint32_t count = phys_dev->this_instance->device_layer_list.count; 4499 4500 if (pProperties == NULL) { 4501 *pPropertyCount = count; 4502 return VK_SUCCESS; 4503 } 4504 4505 copy_size = (*pPropertyCount < count) ? *pPropertyCount : count; 4506 for (uint32_t i = 0; i < copy_size; i++) { 4507 memcpy(&pProperties[i], 4508 &(phys_dev->this_instance->device_layer_list.list[i].info), 4509 sizeof(VkLayerProperties)); 4510 } 4511 *pPropertyCount = copy_size; 4512 4513 if (copy_size < count) { 4514 return VK_INCOMPLETE; 4515 } 4516 4517 return VK_SUCCESS; 4518} 4519 4520VkStringErrorFlags vk_string_validate(const int max_length, const char *utf8) { 4521 VkStringErrorFlags result = VK_STRING_ERROR_NONE; 4522 int num_char_bytes; 4523 int i, j; 4524 4525 for (i = 0; i < max_length; i++) { 4526 if (utf8[i] == 0) { 4527 break; 4528 } else if ((utf8[i] >= 0x20) && (utf8[i] < 0x7f)) { 4529 num_char_bytes = 0; 4530 } else if ((utf8[i] & UTF8_ONE_BYTE_MASK) == UTF8_ONE_BYTE_CODE) { 4531 num_char_bytes = 1; 4532 } else if ((utf8[i] & UTF8_TWO_BYTE_MASK) == UTF8_TWO_BYTE_CODE) { 4533 num_char_bytes = 2; 4534 } else if ((utf8[i] & UTF8_THREE_BYTE_MASK) == UTF8_THREE_BYTE_CODE) { 4535 num_char_bytes = 3; 4536 } else { 4537 result = VK_STRING_ERROR_BAD_DATA; 4538 } 4539 4540 // Validate the following num_char_bytes of data 4541 for (j = 0; (j < num_char_bytes) && (i < max_length); j++) { 4542 if (++i == max_length) { 4543 result |= VK_STRING_ERROR_LENGTH; 4544 break; 4545 } 4546 if ((utf8[i] & UTF8_DATA_BYTE_MASK) != UTF8_DATA_BYTE_CODE) { 4547 result |= VK_STRING_ERROR_BAD_DATA; 4548 } 4549 } 4550 } 4551 return result; 4552} 4553