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