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