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