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