1/* 2 * 3 * Copyright (c) 2014-2023 The Khronos Group Inc. 4 * Copyright (c) 2014-2023 Valve Corporation 5 * Copyright (c) 2014-2023 LunarG, Inc. 6 * Copyright (C) 2015 Google Inc. 7 * Copyright (c) 2021-2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 8 * Copyright (c) 2023-2023 RasterGrid Kft. 9 * 10 * Licensed under the Apache License, Version 2.0 (the "License"); 11 * you may not use this file except in compliance with the License. 12 * You may obtain a copy of the License at 13 * 14 * http://www.apache.org/licenses/LICENSE-2.0 15 * 16 * Unless required by applicable law or agreed to in writing, software 17 * distributed under the License is distributed on an "AS IS" BASIS, 18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 * See the License for the specific language governing permissions and 20 * limitations under the License. 21 22 * 23 * Author: Jon Ashburn <jon@lunarg.com> 24 * Author: Courtney Goeltzenleuchter <courtney@LunarG.com> 25 * Author: Mark Young <marky@lunarg.com> 26 * Author: Lenny Komow <lenny@lunarg.com> 27 * Author: Charles Giessen <charles@lunarg.com> 28 * 29 */ 30 31#include "loader.h" 32 33#include <ctype.h> 34#include <inttypes.h> 35#include <stdio.h> 36#include <stdlib.h> 37#include <stdarg.h> 38#include <stdbool.h> 39#include <string.h> 40#include <stddef.h> 41 42#if defined(__APPLE__) 43#include <CoreFoundation/CoreFoundation.h> 44#include <sys/param.h> 45#endif 46 47#include <sys/types.h> 48#if defined(_WIN32) 49#include "dirent_on_windows.h" 50#elif COMMON_UNIX_PLATFORMS 51#include <dirent.h> 52#else 53#warning dirent.h not available on this platform 54#endif // _WIN32 55 56#include "allocation.h" 57#include "cJSON.h" 58#include "debug_utils.h" 59#include "loader_environment.h" 60#include "gpa_helper.h" 61#include "log.h" 62#include "unknown_function_handling.h" 63#include "vk_loader_platform.h" 64#include "wsi.h" 65 66#if defined(WIN32) 67#include "loader_windows.h" 68#endif 69#if defined(LOADER_ENABLE_LINUX_SORT) 70// This header is currently only used when sorting Linux devices, so don't include it otherwise. 71#include "loader_linux.h" 72#endif // LOADER_ENABLE_LINUX_SORT 73 74// Generated file containing all the extension data 75#include "vk_loader_extensions.c" 76 77struct loader_struct loader = {0}; 78 79struct activated_layer_info { 80 char *name; 81 char *manifest; 82 char *library; 83 bool is_implicit; 84 char *disable_env; 85}; 86 87// thread safety lock for accessing global data structures such as "loader" 88// all entrypoints on the instance chain need to be locked except GPA 89// additionally CreateDevice and DestroyDevice needs to be locked 90loader_platform_thread_mutex loader_lock; 91loader_platform_thread_mutex loader_preload_icd_lock; 92loader_platform_thread_mutex loader_global_instance_list_lock; 93 94// A list of ICDs that gets initialized when the loader does its global initialization. This list should never be used by anything 95// other than EnumerateInstanceExtensionProperties(), vkDestroyInstance, and loader_release(). This list does not change 96// functionality, but the fact that the libraries already been loaded causes any call that needs to load ICD libraries to speed up 97// significantly. This can have a huge impact when making repeated calls to vkEnumerateInstanceExtensionProperties and 98// vkCreateInstance. 99struct loader_icd_tramp_list scanned_icds; 100 101// controls whether loader_platform_close_library() closes the libraries or not - controlled by an environment 102// variables - this is just the definition of the variable, usage is in vk_loader_platform.h 103bool loader_disable_dynamic_library_unloading; 104 105LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_init); 106 107// Creates loader_api_version struct that contains the major and minor fields, setting patch to 0 108loader_api_version loader_make_version(uint32_t version) { 109 loader_api_version out_version; 110 out_version.major = VK_API_VERSION_MAJOR(version); 111 out_version.minor = VK_API_VERSION_MINOR(version); 112 out_version.patch = 0; 113 return out_version; 114} 115 116// Creates loader_api_version struct containing the major, minor, and patch fields 117loader_api_version loader_make_full_version(uint32_t version) { 118 loader_api_version out_version; 119 out_version.major = VK_API_VERSION_MAJOR(version); 120 out_version.minor = VK_API_VERSION_MINOR(version); 121 out_version.patch = VK_API_VERSION_PATCH(version); 122 return out_version; 123} 124 125loader_api_version loader_combine_version(uint32_t major, uint32_t minor, uint32_t patch) { 126 loader_api_version out_version; 127 out_version.major = (uint16_t)major; 128 out_version.minor = (uint16_t)minor; 129 out_version.patch = (uint16_t)patch; 130 return out_version; 131} 132 133// Helper macros for determining if a version is valid or not 134bool loader_check_version_meets_required(loader_api_version required, loader_api_version version) { 135 // major version is satisfied 136 return (version.major > required.major) || 137 // major version is equal, minor version is patch version is greater to minimum minor 138 (version.major == required.major && version.minor > required.minor) || 139 // major and minor version are equal, patch version is greater or equal to minimum patch 140 (version.major == required.major && version.minor == required.minor && version.patch >= required.patch); 141} 142 143// Wrapper around opendir so that the dirent_on_windows gets the instance it needs 144// while linux opendir & readdir does not 145DIR *loader_opendir(const struct loader_instance *instance, const char *name) { 146#if defined(_WIN32) 147 return opendir(instance ? &instance->alloc_callbacks : NULL, name); 148#elif COMMON_UNIX_PLATFORMS 149 (void)instance; 150 return opendir(name); 151#else 152#warning dirent.h - opendir not available on this platform 153#endif // _WIN32 154} 155int loader_closedir(const struct loader_instance *instance, DIR *dir) { 156#if defined(_WIN32) 157 return closedir(instance ? &instance->alloc_callbacks : NULL, dir); 158#elif COMMON_UNIX_PLATFORMS 159 (void)instance; 160 return closedir(dir); 161#else 162#warning dirent.h - closedir not available on this platform 163#endif // _WIN32 164} 165 166bool is_json(const char *path, size_t len) { 167 if (len < 5) { 168 return false; 169 } 170 return !strncmp(path, ".json", 5); 171} 172 173// Handle error from to library loading 174void loader_handle_load_library_error(const struct loader_instance *inst, const char *filename, 175 enum loader_layer_library_status *lib_status) { 176 const char *error_message = loader_platform_open_library_error(filename); 177 // If the error is due to incompatible architecture (eg 32 bit vs 64 bit), report it with INFO level 178 // Discussed in Github issue 262 & 644 179 // "wrong ELF class" is a linux error, " with error 193" is a windows error 180 VkFlags err_flag = VULKAN_LOADER_ERROR_BIT; 181 if (strstr(error_message, "wrong ELF class:") != NULL || strstr(error_message, " with error 193") != NULL) { 182 err_flag = VULKAN_LOADER_INFO_BIT; 183 if (NULL != lib_status) { 184 *lib_status = LOADER_LAYER_LIB_ERROR_WRONG_BIT_TYPE; 185 } 186 } 187 // Check if the error is due to lack of memory 188 // "with error 8" is the windows error code for OOM cases, aka ERROR_NOT_ENOUGH_MEMORY 189 // Linux doesn't have such a nice error message - only if there are reported issues should this be called 190 else if (strstr(error_message, " with error 8") != NULL) { 191 if (NULL != lib_status) { 192 *lib_status = LOADER_LAYER_LIB_ERROR_OUT_OF_MEMORY; 193 } 194 } else if (NULL != lib_status) { 195 *lib_status = LOADER_LAYER_LIB_ERROR_FAILED_TO_LOAD; 196 } 197 loader_log(inst, err_flag, 0, error_message); 198} 199 200VKAPI_ATTR VkResult VKAPI_CALL vkSetInstanceDispatch(VkInstance instance, void *object) { 201 struct loader_instance *inst = loader_get_instance(instance); 202 if (!inst) { 203 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "vkSetInstanceDispatch: Can not retrieve Instance dispatch table."); 204 return VK_ERROR_INITIALIZATION_FAILED; 205 } 206 loader_set_dispatch(object, inst->disp); 207 return VK_SUCCESS; 208} 209 210VKAPI_ATTR VkResult VKAPI_CALL vkSetDeviceDispatch(VkDevice device, void *object) { 211 struct loader_device *dev; 212 struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev, NULL); 213 214 if (NULL == icd_term || NULL == dev) { 215 return VK_ERROR_INITIALIZATION_FAILED; 216 } 217 loader_set_dispatch(object, &dev->loader_dispatch); 218 return VK_SUCCESS; 219} 220 221void loader_free_layer_properties(const struct loader_instance *inst, struct loader_layer_properties *layer_properties) { 222 loader_instance_heap_free(inst, layer_properties->manifest_file_name); 223 loader_instance_heap_free(inst, layer_properties->lib_name); 224 loader_instance_heap_free(inst, layer_properties->functions.str_gipa); 225 loader_instance_heap_free(inst, layer_properties->functions.str_gdpa); 226 loader_instance_heap_free(inst, layer_properties->functions.str_negotiate_interface); 227 loader_destroy_generic_list(inst, (struct loader_generic_list *)&layer_properties->instance_extension_list); 228 if (layer_properties->device_extension_list.capacity > 0 && NULL != layer_properties->device_extension_list.list) { 229 for (uint32_t i = 0; i < layer_properties->device_extension_list.count; i++) { 230 free_string_list(inst, &layer_properties->device_extension_list.list[i].entrypoints); 231 } 232 } 233 loader_destroy_generic_list(inst, (struct loader_generic_list *)&layer_properties->device_extension_list); 234 loader_instance_heap_free(inst, layer_properties->disable_env_var.name); 235 loader_instance_heap_free(inst, layer_properties->disable_env_var.value); 236 loader_instance_heap_free(inst, layer_properties->enable_env_var.name); 237 loader_instance_heap_free(inst, layer_properties->enable_env_var.value); 238 free_string_list(inst, &layer_properties->component_layer_names); 239 loader_instance_heap_free(inst, layer_properties->pre_instance_functions.enumerate_instance_extension_properties); 240 loader_instance_heap_free(inst, layer_properties->pre_instance_functions.enumerate_instance_layer_properties); 241 loader_instance_heap_free(inst, layer_properties->pre_instance_functions.enumerate_instance_version); 242 free_string_list(inst, &layer_properties->override_paths); 243 free_string_list(inst, &layer_properties->blacklist_layer_names); 244 free_string_list(inst, &layer_properties->app_key_paths); 245 246 // Make sure to clear out the removed layer, in case new layers are added in the previous location 247 memset(layer_properties, 0, sizeof(struct loader_layer_properties)); 248} 249 250VkResult loader_init_library_list(struct loader_layer_list *instance_layers, loader_platform_dl_handle **libs) { 251 if (instance_layers->count > 0) { 252 *libs = loader_calloc(NULL, sizeof(loader_platform_dl_handle) * instance_layers->count, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 253 if (*libs == NULL) { 254 return VK_ERROR_OUT_OF_HOST_MEMORY; 255 } 256 } 257 return VK_SUCCESS; 258} 259 260VkResult loader_copy_to_new_str(const struct loader_instance *inst, const char *source_str, char **dest_str) { 261 assert(source_str && dest_str); 262 size_t str_len = strlen(source_str) + 1; 263 *dest_str = loader_instance_heap_calloc(inst, str_len, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 264 if (NULL == *dest_str) return VK_ERROR_OUT_OF_HOST_MEMORY; 265 loader_strncpy(*dest_str, str_len, source_str, str_len); 266 (*dest_str)[str_len - 1] = 0; 267 return VK_SUCCESS; 268} 269 270VkResult create_string_list(const struct loader_instance *inst, uint32_t allocated_count, struct loader_string_list *string_list) { 271 assert(string_list); 272 string_list->list = loader_instance_heap_calloc(inst, sizeof(char *) * allocated_count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 273 if (NULL == string_list->list) { 274 return VK_ERROR_OUT_OF_HOST_MEMORY; 275 } 276 string_list->allocated_count = allocated_count; 277 string_list->count = 0; 278 return VK_SUCCESS; 279} 280 281VkResult append_str_to_string_list(const struct loader_instance *inst, struct loader_string_list *string_list, char *str) { 282 assert(string_list && str); 283 if (string_list->allocated_count == 0) { 284 string_list->allocated_count = 32; 285 string_list->list = 286 loader_instance_heap_calloc(inst, sizeof(char *) * string_list->allocated_count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 287 if (NULL == string_list->list) { 288 return VK_ERROR_OUT_OF_HOST_MEMORY; 289 } 290 } else if (string_list->count + 1 > string_list->allocated_count) { 291 uint32_t new_allocated_count = string_list->allocated_count * 2; 292 string_list->list = loader_instance_heap_realloc(inst, string_list->list, sizeof(char *) * string_list->allocated_count, 293 sizeof(char *) * new_allocated_count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 294 if (NULL == string_list->list) { 295 return VK_ERROR_OUT_OF_HOST_MEMORY; 296 } 297 // Null out the new space 298 memset(string_list->list + string_list->allocated_count, 0, string_list->allocated_count); 299 string_list->allocated_count *= 2; 300 } 301 string_list->list[string_list->count++] = str; 302 return VK_SUCCESS; 303} 304 305VkResult copy_str_to_string_list(const struct loader_instance *inst, struct loader_string_list *string_list, const char *str, 306 size_t str_len) { 307 assert(string_list && str); 308 char *new_str = loader_instance_heap_calloc(inst, sizeof(char *) * str_len + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 309 if (NULL == new_str) { 310 return VK_ERROR_OUT_OF_HOST_MEMORY; 311 } 312 loader_strncpy(new_str, sizeof(char *) * str_len + 1, str, str_len); 313 new_str[str_len] = '\0'; 314 VkResult res = append_str_to_string_list(inst, string_list, new_str); 315 if (res != VK_SUCCESS) { 316 // Cleanup new_str if the append failed - as append_str_to_string_list takes ownership but not if the function fails 317 loader_instance_heap_free(inst, new_str); 318 } 319 return res; 320} 321 322void free_string_list(const struct loader_instance *inst, struct loader_string_list *string_list) { 323 assert(string_list); 324 if (string_list->list) { 325 for (uint32_t i = 0; i < string_list->count; i++) { 326 loader_instance_heap_free(inst, string_list->list[i]); 327 string_list->list[i] = NULL; 328 } 329 loader_instance_heap_free(inst, string_list->list); 330 } 331 memset(string_list, 0, sizeof(struct loader_string_list)); 332} 333 334// Given string of three part form "maj.min.pat" convert to a vulkan version number. 335// Also can understand four part form "variant.major.minor.patch" if provided. 336uint32_t loader_parse_version_string(char *vers_str) { 337 uint32_t variant = 0, major = 0, minor = 0, patch = 0; 338 char *vers_tok; 339 char *context = NULL; 340 if (!vers_str) { 341 return 0; 342 } 343 344 vers_tok = thread_safe_strtok(vers_str, ".\"\n\r", &context); 345 if (NULL != vers_tok) { 346 major = (uint16_t)atoi(vers_tok); 347 vers_tok = thread_safe_strtok(NULL, ".\"\n\r", &context); 348 if (NULL != vers_tok) { 349 minor = (uint16_t)atoi(vers_tok); 350 vers_tok = thread_safe_strtok(NULL, ".\"\n\r", &context); 351 if (NULL != vers_tok) { 352 patch = (uint16_t)atoi(vers_tok); 353 vers_tok = thread_safe_strtok(NULL, ".\"\n\r", &context); 354 // check that we are using a 4 part version string 355 if (NULL != vers_tok) { 356 // if we are, move the values over into the correct place 357 variant = major; 358 major = minor; 359 minor = patch; 360 patch = (uint16_t)atoi(vers_tok); 361 } 362 } 363 } 364 } 365 366 return VK_MAKE_API_VERSION(variant, major, minor, patch); 367} 368 369bool compare_vk_extension_properties(const VkExtensionProperties *op1, const VkExtensionProperties *op2) { 370 return strcmp(op1->extensionName, op2->extensionName) == 0 ? true : false; 371} 372 373// Search the given ext_array for an extension matching the given vk_ext_prop 374bool has_vk_extension_property_array(const VkExtensionProperties *vk_ext_prop, const uint32_t count, 375 const VkExtensionProperties *ext_array) { 376 for (uint32_t i = 0; i < count; i++) { 377 if (compare_vk_extension_properties(vk_ext_prop, &ext_array[i])) return true; 378 } 379 return false; 380} 381 382// Search the given ext_list for an extension matching the given vk_ext_prop 383bool has_vk_extension_property(const VkExtensionProperties *vk_ext_prop, const struct loader_extension_list *ext_list) { 384 for (uint32_t i = 0; i < ext_list->count; i++) { 385 if (compare_vk_extension_properties(&ext_list->list[i], vk_ext_prop)) return true; 386 } 387 return false; 388} 389 390// Search the given ext_list for a device extension matching the given ext_prop 391bool has_vk_dev_ext_property(const VkExtensionProperties *ext_prop, const struct loader_device_extension_list *ext_list) { 392 for (uint32_t i = 0; i < ext_list->count; i++) { 393 if (compare_vk_extension_properties(&ext_list->list[i].props, ext_prop)) return true; 394 } 395 return false; 396} 397 398VkResult loader_append_layer_property(const struct loader_instance *inst, struct loader_layer_list *layer_list, 399 struct loader_layer_properties *layer_property) { 400 VkResult res = VK_SUCCESS; 401 if (layer_list->capacity == 0) { 402 res = loader_init_generic_list(inst, (struct loader_generic_list *)layer_list, sizeof(struct loader_layer_properties)); 403 if (VK_SUCCESS != res) { 404 goto out; 405 } 406 } 407 408 // Ensure enough room to add an entry 409 if ((layer_list->count + 1) * sizeof(struct loader_layer_properties) > layer_list->capacity) { 410 void *new_ptr = loader_instance_heap_realloc(inst, layer_list->list, layer_list->capacity, layer_list->capacity * 2, 411 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 412 if (NULL == new_ptr) { 413 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_append_layer_property: realloc failed for layer list"); 414 res = VK_ERROR_OUT_OF_HOST_MEMORY; 415 goto out; 416 } 417 layer_list->list = new_ptr; 418 memset((uint8_t *)layer_list->list + layer_list->capacity, 0, layer_list->capacity); 419 layer_list->capacity *= 2; 420 } 421 memcpy(&layer_list->list[layer_list->count], layer_property, sizeof(struct loader_layer_properties)); 422 layer_list->count++; 423 memset(layer_property, 0, sizeof(struct loader_layer_properties)); 424out: 425 if (res != VK_SUCCESS) { 426 loader_free_layer_properties(inst, layer_property); 427 } 428 return res; 429} 430 431// Search the given layer list for a layer property matching the given layer name 432struct loader_layer_properties *loader_find_layer_property(const char *name, const struct loader_layer_list *layer_list) { 433 for (uint32_t i = 0; i < layer_list->count; i++) { 434 const VkLayerProperties *item = &layer_list->list[i].info; 435 if (strcmp(name, item->layerName) == 0) return &layer_list->list[i]; 436 } 437 return NULL; 438} 439 440struct loader_layer_properties *loader_find_pointer_layer_property(const char *name, 441 const struct loader_pointer_layer_list *layer_list) { 442 for (uint32_t i = 0; i < layer_list->count; i++) { 443 const VkLayerProperties *item = &layer_list->list[i]->info; 444 if (strcmp(name, item->layerName) == 0) return layer_list->list[i]; 445 } 446 return NULL; 447} 448 449// Search the given layer list for a layer matching the given layer name 450bool loader_find_layer_name_in_list(const char *name, const struct loader_pointer_layer_list *layer_list) { 451 if (NULL == layer_list) { 452 return false; 453 } 454 if (NULL != loader_find_pointer_layer_property(name, layer_list)) { 455 return true; 456 } 457 return false; 458} 459 460// Search the given meta-layer's component list for a layer matching the given layer name 461bool loader_find_layer_name_in_meta_layer(const struct loader_instance *inst, const char *layer_name, 462 struct loader_layer_list *layer_list, struct loader_layer_properties *meta_layer_props) { 463 for (uint32_t comp_layer = 0; comp_layer < meta_layer_props->component_layer_names.count; comp_layer++) { 464 if (!strcmp(meta_layer_props->component_layer_names.list[comp_layer], layer_name)) { 465 return true; 466 } 467 struct loader_layer_properties *comp_layer_props = 468 loader_find_layer_property(meta_layer_props->component_layer_names.list[comp_layer], layer_list); 469 if (comp_layer_props->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER) { 470 return loader_find_layer_name_in_meta_layer(inst, layer_name, layer_list, comp_layer_props); 471 } 472 } 473 return false; 474} 475 476// Search the override layer's blacklist for a layer matching the given layer name 477bool loader_find_layer_name_in_blacklist(const char *layer_name, struct loader_layer_properties *meta_layer_props) { 478 for (uint32_t black_layer = 0; black_layer < meta_layer_props->blacklist_layer_names.count; ++black_layer) { 479 if (!strcmp(meta_layer_props->blacklist_layer_names.list[black_layer], layer_name)) { 480 return true; 481 } 482 } 483 return false; 484} 485 486// Remove all layer properties entries from the list 487void loader_delete_layer_list_and_properties(const struct loader_instance *inst, struct loader_layer_list *layer_list) { 488 uint32_t i; 489 if (!layer_list) return; 490 491 for (i = 0; i < layer_list->count; i++) { 492 if (layer_list->list[i].lib_handle) { 493 loader_platform_close_library(layer_list->list[i].lib_handle); 494 loader_log(inst, VULKAN_LOADER_DEBUG_BIT | VULKAN_LOADER_LAYER_BIT, 0, "Unloading layer library %s", 495 layer_list->list[i].lib_name); 496 layer_list->list[i].lib_handle = NULL; 497 } 498 loader_free_layer_properties(inst, &(layer_list->list[i])); 499 } 500 layer_list->count = 0; 501 502 if (layer_list->capacity > 0) { 503 layer_list->capacity = 0; 504 loader_instance_heap_free(inst, layer_list->list); 505 } 506 memset(layer_list, 0, sizeof(struct loader_layer_list)); 507} 508 509void loader_remove_layer_in_list(const struct loader_instance *inst, struct loader_layer_list *layer_list, 510 uint32_t layer_to_remove) { 511 if (layer_list == NULL || layer_to_remove >= layer_list->count) { 512 return; 513 } 514 loader_free_layer_properties(inst, &(layer_list->list[layer_to_remove])); 515 516 // Remove the current invalid meta-layer from the layer list. Use memmove since we are 517 // overlapping the source and destination addresses. 518 memmove(&layer_list->list[layer_to_remove], &layer_list->list[layer_to_remove + 1], 519 sizeof(struct loader_layer_properties) * (layer_list->count - 1 - layer_to_remove)); 520 521 // Decrement the count (because we now have one less) and decrement the loop index since we need to 522 // re-check this index. 523 layer_list->count--; 524} 525 526// Remove all layers in the layer list that are blacklisted by the override layer. 527// NOTE: This should only be called if an override layer is found and not expired. 528void loader_remove_layers_in_blacklist(const struct loader_instance *inst, struct loader_layer_list *layer_list) { 529 struct loader_layer_properties *override_prop = loader_find_layer_property(VK_OVERRIDE_LAYER_NAME, layer_list); 530 if (NULL == override_prop) { 531 return; 532 } 533 534 for (int32_t j = 0; j < (int32_t)(layer_list->count); j++) { 535 struct loader_layer_properties cur_layer_prop = layer_list->list[j]; 536 const char *cur_layer_name = &cur_layer_prop.info.layerName[0]; 537 538 // Skip the override layer itself. 539 if (!strcmp(VK_OVERRIDE_LAYER_NAME, cur_layer_name)) { 540 continue; 541 } 542 543 // If found in the override layer's blacklist, remove it 544 if (loader_find_layer_name_in_blacklist(cur_layer_name, override_prop)) { 545 loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, 546 "loader_remove_layers_in_blacklist: Override layer is active and layer %s is in the blacklist inside of it. " 547 "Removing that layer from current layer list.", 548 cur_layer_name); 549 loader_remove_layer_in_list(inst, layer_list, j); 550 j--; 551 552 // Re-do the query for the override layer 553 override_prop = loader_find_layer_property(VK_OVERRIDE_LAYER_NAME, layer_list); 554 } 555 } 556} 557 558// Remove all layers in the layer list that are not found inside any implicit meta-layers. 559void loader_remove_layers_not_in_implicit_meta_layers(const struct loader_instance *inst, struct loader_layer_list *layer_list) { 560 int32_t i; 561 int32_t j; 562 int32_t layer_count = (int32_t)(layer_list->count); 563 564 for (i = 0; i < layer_count; i++) { 565 layer_list->list[i].keep = false; 566 } 567 568 for (i = 0; i < layer_count; i++) { 569 struct loader_layer_properties *cur_layer_prop = &layer_list->list[i]; 570 571 if (0 == (cur_layer_prop->type_flags & VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER)) { 572 cur_layer_prop->keep = true; 573 continue; 574 } 575 for (j = 0; j < layer_count; j++) { 576 struct loader_layer_properties *layer_to_check = &layer_list->list[j]; 577 578 if (i == j) { 579 continue; 580 } 581 582 if (layer_to_check->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER) { 583 // For all layers found in this meta layer, we want to keep them as well. 584 if (loader_find_layer_name_in_meta_layer(inst, cur_layer_prop->info.layerName, layer_list, layer_to_check)) { 585 cur_layer_prop->keep = true; 586 } 587 } 588 } 589 } 590 591 // Remove any layers we don't want to keep (Don't use layer_count here as we need it to be 592 // dynamically updated if we delete a layer property in the list). 593 for (i = 0; i < (int32_t)(layer_list->count); i++) { 594 struct loader_layer_properties *cur_layer_prop = &layer_list->list[i]; 595 if (!cur_layer_prop->keep) { 596 loader_log( 597 inst, VULKAN_LOADER_DEBUG_BIT, 0, 598 "loader_remove_layers_not_in_implicit_meta_layers : Implicit meta-layers are active, and layer %s is not list " 599 "inside of any. So removing layer from current layer list.", 600 cur_layer_prop->info.layerName); 601 loader_remove_layer_in_list(inst, layer_list, i); 602 i--; 603 } 604 } 605} 606 607VkResult loader_add_instance_extensions(const struct loader_instance *inst, 608 const PFN_vkEnumerateInstanceExtensionProperties fp_get_props, const char *lib_name, 609 struct loader_extension_list *ext_list) { 610 uint32_t i, count = 0; 611 VkExtensionProperties *ext_props; 612 VkResult res = VK_SUCCESS; 613 614 if (!fp_get_props) { 615 // No EnumerateInstanceExtensionProperties defined 616 goto out; 617 } 618 619 // Make sure we never call ourself by accident, this should never happen outside of error paths 620 if (fp_get_props == vkEnumerateInstanceExtensionProperties) { 621 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 622 "loader_add_instance_extensions: %s's vkEnumerateInstanceExtensionProperties points to the loader, this would " 623 "lead to infinite recursion.", 624 lib_name); 625 goto out; 626 } 627 628 res = fp_get_props(NULL, &count, NULL); 629 if (res != VK_SUCCESS) { 630 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 631 "loader_add_instance_extensions: Error getting Instance extension count from %s", lib_name); 632 goto out; 633 } 634 635 if (count == 0) { 636 // No ExtensionProperties to report 637 goto out; 638 } 639 640 ext_props = loader_stack_alloc(count * sizeof(VkExtensionProperties)); 641 if (NULL == ext_props) { 642 res = VK_ERROR_OUT_OF_HOST_MEMORY; 643 goto out; 644 } 645 646 res = fp_get_props(NULL, &count, ext_props); 647 if (res != VK_SUCCESS) { 648 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_add_instance_extensions: Error getting Instance extensions from %s", 649 lib_name); 650 goto out; 651 } 652 653 for (i = 0; i < count; i++) { 654 bool ext_unsupported = wsi_unsupported_instance_extension(&ext_props[i]); 655 if (!ext_unsupported) { 656 res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]); 657 if (res != VK_SUCCESS) { 658 goto out; 659 } 660 } 661 } 662 663out: 664 return res; 665} 666 667VkResult loader_add_device_extensions(const struct loader_instance *inst, 668 PFN_vkEnumerateDeviceExtensionProperties fpEnumerateDeviceExtensionProperties, 669 VkPhysicalDevice physical_device, const char *lib_name, 670 struct loader_extension_list *ext_list) { 671 uint32_t i = 0, count = 0; 672 VkResult res = VK_SUCCESS; 673 VkExtensionProperties *ext_props = NULL; 674 675 res = fpEnumerateDeviceExtensionProperties(physical_device, NULL, &count, NULL); 676 if (res != VK_SUCCESS) { 677 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 678 "loader_add_device_extensions: Error getting physical device extension info count from library %s", lib_name); 679 return res; 680 } 681 if (count > 0) { 682 ext_props = loader_stack_alloc(count * sizeof(VkExtensionProperties)); 683 if (!ext_props) { 684 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 685 "loader_add_device_extensions: Failed to allocate space for device extension properties from library %s.", 686 lib_name); 687 return VK_ERROR_OUT_OF_HOST_MEMORY; 688 } 689 res = fpEnumerateDeviceExtensionProperties(physical_device, NULL, &count, ext_props); 690 if (res != VK_SUCCESS) { 691 return res; 692 } 693 for (i = 0; i < count; i++) { 694 res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]); 695 if (res != VK_SUCCESS) { 696 return res; 697 } 698 } 699 } 700 701 return VK_SUCCESS; 702} 703 704VkResult loader_init_generic_list(const struct loader_instance *inst, struct loader_generic_list *list_info, size_t element_size) { 705 size_t capacity = 32 * element_size; 706 list_info->count = 0; 707 list_info->capacity = 0; 708 list_info->list = loader_instance_heap_calloc(inst, capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 709 if (list_info->list == NULL) { 710 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_init_generic_list: Failed to allocate space for generic list"); 711 return VK_ERROR_OUT_OF_HOST_MEMORY; 712 } 713 list_info->capacity = capacity; 714 return VK_SUCCESS; 715} 716 717void loader_destroy_generic_list(const struct loader_instance *inst, struct loader_generic_list *list) { 718 loader_instance_heap_free(inst, list->list); 719 memset(list, 0, sizeof(struct loader_generic_list)); 720} 721 722// Append non-duplicate extension properties defined in props to the given ext_list. 723// Return - Vk_SUCCESS on success 724VkResult loader_add_to_ext_list(const struct loader_instance *inst, struct loader_extension_list *ext_list, 725 uint32_t prop_list_count, const VkExtensionProperties *props) { 726 if (ext_list->list == NULL || ext_list->capacity == 0) { 727 VkResult res = loader_init_generic_list(inst, (struct loader_generic_list *)ext_list, sizeof(VkExtensionProperties)); 728 if (VK_SUCCESS != res) { 729 return res; 730 } 731 } 732 733 for (uint32_t i = 0; i < prop_list_count; i++) { 734 const VkExtensionProperties *cur_ext = &props[i]; 735 736 // look for duplicates 737 if (has_vk_extension_property(cur_ext, ext_list)) { 738 continue; 739 } 740 741 // add to list at end 742 // check for enough capacity 743 if (ext_list->count * sizeof(VkExtensionProperties) >= ext_list->capacity) { 744 void *new_ptr = loader_instance_heap_realloc(inst, ext_list->list, ext_list->capacity, ext_list->capacity * 2, 745 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 746 if (new_ptr == NULL) { 747 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 748 "loader_add_to_ext_list: Failed to reallocate space for extension list"); 749 return VK_ERROR_OUT_OF_HOST_MEMORY; 750 } 751 ext_list->list = new_ptr; 752 753 // double capacity 754 ext_list->capacity *= 2; 755 } 756 757 memcpy(&ext_list->list[ext_list->count], cur_ext, sizeof(VkExtensionProperties)); 758 ext_list->count++; 759 } 760 return VK_SUCCESS; 761} 762 763// Append one extension property defined in props with entrypoints defined in entries to the given 764// ext_list. Do not append if a duplicate. 765// If this is a duplicate, this function free's the passed in entries - as in it takes ownership over that list (if it is not 766// NULL) Return - Vk_SUCCESS on success 767VkResult loader_add_to_dev_ext_list(const struct loader_instance *inst, struct loader_device_extension_list *ext_list, 768 const VkExtensionProperties *props, struct loader_string_list *entrys) { 769 VkResult res = VK_SUCCESS; 770 bool should_free_entrys = true; 771 if (ext_list->list == NULL || ext_list->capacity == 0) { 772 res = loader_init_generic_list(inst, (struct loader_generic_list *)ext_list, sizeof(struct loader_dev_ext_props)); 773 if (VK_SUCCESS != res) { 774 goto out; 775 } 776 } 777 778 // look for duplicates 779 if (has_vk_dev_ext_property(props, ext_list)) { 780 goto out; 781 } 782 783 uint32_t idx = ext_list->count; 784 // add to list at end 785 // check for enough capacity 786 if (idx * sizeof(struct loader_dev_ext_props) >= ext_list->capacity) { 787 void *new_ptr = loader_instance_heap_realloc(inst, ext_list->list, ext_list->capacity, ext_list->capacity * 2, 788 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 789 790 if (NULL == new_ptr) { 791 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 792 "loader_add_to_dev_ext_list: Failed to reallocate space for device extension list"); 793 res = VK_ERROR_OUT_OF_HOST_MEMORY; 794 goto out; 795 } 796 ext_list->list = new_ptr; 797 798 // double capacity 799 ext_list->capacity *= 2; 800 } 801 802 memcpy(&ext_list->list[idx].props, props, sizeof(*props)); 803 if (entrys) { 804 ext_list->list[idx].entrypoints = *entrys; 805 should_free_entrys = false; 806 } 807 ext_list->count++; 808out: 809 if (NULL != entrys && should_free_entrys) { 810 free_string_list(inst, entrys); 811 } 812 return res; 813} 814 815// Create storage for pointers to loader_layer_properties 816bool loader_init_pointer_layer_list(const struct loader_instance *inst, struct loader_pointer_layer_list *list) { 817 list->capacity = 32 * sizeof(void *); 818 list->list = loader_instance_heap_calloc(inst, list->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 819 if (list->list == NULL) { 820 return false; 821 } 822 list->count = 0; 823 return true; 824} 825 826// Search the given array of layer names for an entry matching the given VkLayerProperties 827bool loader_names_array_has_layer_property(const VkLayerProperties *vk_layer_prop, uint32_t layer_info_count, 828 struct activated_layer_info *layer_info) { 829 for (uint32_t i = 0; i < layer_info_count; i++) { 830 if (strcmp(vk_layer_prop->layerName, layer_info[i].name) == 0) { 831 return true; 832 } 833 } 834 return false; 835} 836 837void loader_destroy_pointer_layer_list(const struct loader_instance *inst, struct loader_pointer_layer_list *layer_list) { 838 loader_instance_heap_free(inst, layer_list->list); 839 memset(layer_list, 0, sizeof(struct loader_pointer_layer_list)); 840} 841 842// Append layer properties defined in prop_list to the given layer_info list 843VkResult loader_add_layer_properties_to_list(const struct loader_instance *inst, struct loader_pointer_layer_list *list, 844 struct loader_layer_properties *props) { 845 if (list->list == NULL || list->capacity == 0) { 846 if (!loader_init_pointer_layer_list(inst, list)) { 847 return VK_ERROR_OUT_OF_HOST_MEMORY; 848 } 849 } 850 851 // Check for enough capacity 852 if (((list->count + 1) * sizeof(struct loader_layer_properties)) >= list->capacity) { 853 size_t new_capacity = list->capacity * 2; 854 void *new_ptr = 855 loader_instance_heap_realloc(inst, list->list, list->capacity, new_capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 856 if (NULL == new_ptr) { 857 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 858 "loader_add_layer_properties_to_list: Realloc failed for when attempting to add new layer"); 859 return VK_ERROR_OUT_OF_HOST_MEMORY; 860 } 861 list->list = new_ptr; 862 list->capacity = new_capacity; 863 } 864 list->list[list->count++] = props; 865 866 return VK_SUCCESS; 867} 868 869// Determine if the provided explicit layer should be available by querying the appropriate environmental variables. 870bool loader_layer_is_available(const struct loader_instance *inst, const struct loader_envvar_all_filters *filters, 871 const struct loader_layer_properties *prop) { 872 bool available = true; 873 bool is_implicit = (0 == (prop->type_flags & VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER)); 874 bool disabled_by_type = 875 (is_implicit) ? (filters->disable_filter.disable_all_implicit) : (filters->disable_filter.disable_all_explicit); 876 if ((filters->disable_filter.disable_all || disabled_by_type || 877 check_name_matches_filter_environment_var(prop->info.layerName, &filters->disable_filter.additional_filters)) && 878 !check_name_matches_filter_environment_var(prop->info.layerName, &filters->allow_filter)) { 879 available = false; 880 } 881 if (check_name_matches_filter_environment_var(prop->info.layerName, &filters->enable_filter)) { 882 available = true; 883 } else if (!available) { 884 loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0, 885 "Layer \"%s\" forced disabled because name matches filter of env var \'%s\'.", prop->info.layerName, 886 VK_LAYERS_DISABLE_ENV_VAR); 887 } 888 889 return available; 890} 891 892// Search the given search_list for any layers in the props list. Add these to the 893// output layer_list. 894VkResult loader_add_layer_names_to_list(const struct loader_instance *inst, const struct loader_envvar_all_filters *filters, 895 struct loader_pointer_layer_list *output_list, 896 struct loader_pointer_layer_list *expanded_output_list, uint32_t name_count, 897 const char *const *names, const struct loader_layer_list *source_list) { 898 VkResult err = VK_SUCCESS; 899 900 for (uint32_t i = 0; i < name_count; i++) { 901 const char *source_name = names[i]; 902 903 struct loader_layer_properties *layer_prop = loader_find_layer_property(source_name, source_list); 904 if (NULL == layer_prop) { 905 loader_log(inst, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_LAYER_BIT, 0, 906 "loader_add_layer_names_to_list: Unable to find layer \"%s\"", source_name); 907 err = VK_ERROR_LAYER_NOT_PRESENT; 908 continue; 909 } 910 911 // Make sure the layer isn't already in the output_list, skip adding it if it is. 912 if (loader_find_layer_name_in_list(source_name, output_list)) { 913 continue; 914 } 915 916 if (!loader_layer_is_available(inst, filters, layer_prop)) { 917 continue; 918 } 919 920 // If not a meta-layer, simply add it. 921 if (0 == (layer_prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER)) { 922 err = loader_add_layer_properties_to_list(inst, output_list, layer_prop); 923 if (err == VK_ERROR_OUT_OF_HOST_MEMORY) return err; 924 err = loader_add_layer_properties_to_list(inst, expanded_output_list, layer_prop); 925 if (err == VK_ERROR_OUT_OF_HOST_MEMORY) return err; 926 } else { 927 err = loader_add_meta_layer(inst, filters, layer_prop, output_list, expanded_output_list, source_list, NULL); 928 if (err == VK_ERROR_OUT_OF_HOST_MEMORY) return err; 929 } 930 } 931 932 return err; 933} 934 935// Determine if the provided implicit layer should be enabled by querying the appropriate environmental variables. 936// For an implicit layer, at least a disable environment variable is required. 937bool loader_implicit_layer_is_enabled(const struct loader_instance *inst, const struct loader_envvar_all_filters *filters, 938 const struct loader_layer_properties *prop) { 939 bool enable = false; 940 bool forced_disabled = false; 941 bool forced_enabled = false; 942 943 if ((filters->disable_filter.disable_all || filters->disable_filter.disable_all_implicit || 944 check_name_matches_filter_environment_var(prop->info.layerName, &filters->disable_filter.additional_filters)) && 945 !check_name_matches_filter_environment_var(prop->info.layerName, &filters->allow_filter)) { 946 forced_disabled = true; 947 } 948 if (check_name_matches_filter_environment_var(prop->info.layerName, &filters->enable_filter)) { 949 forced_enabled = true; 950 } 951 952 // If no enable_environment variable is specified, this implicit layer is always be enabled by default. 953 if (NULL == prop->enable_env_var.name) { 954 enable = true; 955 } else { 956 char *env_value = loader_getenv(prop->enable_env_var.name, inst); 957 if (env_value && !strcmp(prop->enable_env_var.value, env_value)) { 958 enable = true; 959 } 960 961 // Otherwise, only enable this layer if the enable environment variable is defined 962 loader_free_getenv(env_value, inst); 963 } 964 965 if (forced_enabled) { 966 // Only report a message that we've forced on a layer if it wouldn't have been enabled 967 // normally. 968 if (!enable) { 969 enable = true; 970 loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0, 971 "Implicit layer \"%s\" forced enabled due to env var \'%s\'.", prop->info.layerName, 972 VK_LAYERS_ENABLE_ENV_VAR); 973 } 974 } else if (enable && forced_disabled) { 975 enable = false; 976 // Report a message that we've forced off a layer if it would have been enabled normally. 977 loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0, 978 "Implicit layer \"%s\" forced disabled because name matches filter of env var \'%s\'.", prop->info.layerName, 979 VK_LAYERS_DISABLE_ENV_VAR); 980 return enable; 981 } 982 983 // The disable_environment has priority over everything else. If it is defined, the layer is always 984 // disabled. 985 if (NULL != prop->disable_env_var.name) { 986 char *env_value = loader_getenv(prop->disable_env_var.name, inst); 987 if (NULL != env_value) { 988 enable = false; 989 } 990 loader_free_getenv(env_value, inst); 991 } else if ((prop->type_flags & VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER) == 0) { 992 loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0, 993 "Implicit layer \"%s\" missing disabled environment variable!", prop->info.layerName, VK_LAYERS_DISABLE_ENV_VAR); 994 } 995 996 // Enable this layer if it is included in the override layer 997 if (inst != NULL && inst->override_layer_present) { 998 struct loader_layer_properties *override = NULL; 999 for (uint32_t i = 0; i < inst->instance_layer_list.count; ++i) { 1000 if (strcmp(inst->instance_layer_list.list[i].info.layerName, VK_OVERRIDE_LAYER_NAME) == 0) { 1001 override = &inst->instance_layer_list.list[i]; 1002 break; 1003 } 1004 } 1005 if (override != NULL) { 1006 for (uint32_t i = 0; i < override->component_layer_names.count; ++i) { 1007 if (strcmp(override->component_layer_names.list[i], prop->info.layerName) == 0) { 1008 enable = true; 1009 break; 1010 } 1011 } 1012 } 1013 } 1014 1015 return enable; 1016} 1017 1018// Check the individual implicit layer for the enable/disable environment variable settings. Only add it after 1019// every check has passed indicating it should be used, including making sure a layer of the same name hasn't already been 1020// added. 1021VkResult loader_add_implicit_layer(const struct loader_instance *inst, struct loader_layer_properties *prop, 1022 const struct loader_envvar_all_filters *filters, struct loader_pointer_layer_list *target_list, 1023 struct loader_pointer_layer_list *expanded_target_list, 1024 const struct loader_layer_list *source_list) { 1025 VkResult result = VK_SUCCESS; 1026 if (loader_implicit_layer_is_enabled(inst, filters, prop)) { 1027 if (0 == (prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER)) { 1028 // Make sure the layer isn't already in the output_list, skip adding it if it is. 1029 if (loader_find_layer_name_in_list(&prop->info.layerName[0], target_list)) { 1030 return result; 1031 } 1032 1033 result = loader_add_layer_properties_to_list(inst, target_list, prop); 1034 if (result == VK_ERROR_OUT_OF_HOST_MEMORY) return result; 1035 if (NULL != expanded_target_list) { 1036 result = loader_add_layer_properties_to_list(inst, expanded_target_list, prop); 1037 } 1038 } else { 1039 result = loader_add_meta_layer(inst, filters, prop, target_list, expanded_target_list, source_list, NULL); 1040 } 1041 } 1042 return result; 1043} 1044 1045// Add the component layers of a meta-layer to the active list of layers 1046VkResult loader_add_meta_layer(const struct loader_instance *inst, const struct loader_envvar_all_filters *filters, 1047 struct loader_layer_properties *prop, struct loader_pointer_layer_list *target_list, 1048 struct loader_pointer_layer_list *expanded_target_list, const struct loader_layer_list *source_list, 1049 bool *out_found_all_component_layers) { 1050 VkResult result = VK_SUCCESS; 1051 bool found_all_component_layers = true; 1052 1053 // We need to add all the individual component layers 1054 loader_api_version meta_layer_api_version = loader_make_version(prop->info.specVersion); 1055 for (uint32_t comp_layer = 0; comp_layer < prop->component_layer_names.count; comp_layer++) { 1056 struct loader_layer_properties *search_prop = 1057 loader_find_layer_property(prop->component_layer_names.list[comp_layer], source_list); 1058 if (search_prop != NULL) { 1059 loader_api_version search_prop_version = loader_make_version(prop->info.specVersion); 1060 if (!loader_check_version_meets_required(meta_layer_api_version, search_prop_version)) { 1061 loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0, 1062 "Meta-layer \"%s\" API version %u.%u, component layer \"%s\" version %u.%u, may have " 1063 "incompatibilities (Policy #LLP_LAYER_8)!", 1064 prop->info.layerName, meta_layer_api_version.major, meta_layer_api_version.minor, 1065 search_prop->info.layerName, search_prop_version.major, search_prop_version.minor); 1066 } 1067 1068 if (!loader_layer_is_available(inst, filters, search_prop)) { 1069 loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0, 1070 "Meta Layer \"%s\" component layer \"%s\" disabled.", prop->info.layerName, search_prop->info.layerName); 1071 continue; 1072 } 1073 1074 // If the component layer is itself an implicit layer, we need to do the implicit layer enable 1075 // checks 1076 if (0 == (search_prop->type_flags & VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER)) { 1077 result = loader_add_implicit_layer(inst, search_prop, filters, target_list, expanded_target_list, source_list); 1078 if (result == VK_ERROR_OUT_OF_HOST_MEMORY) return result; 1079 } else { 1080 if (0 != (search_prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER)) { 1081 bool found_layers_in_component_meta_layer = true; 1082 result = loader_add_meta_layer(inst, filters, search_prop, target_list, expanded_target_list, source_list, 1083 &found_layers_in_component_meta_layer); 1084 if (result == VK_ERROR_OUT_OF_HOST_MEMORY) return result; 1085 if (!found_layers_in_component_meta_layer) found_all_component_layers = false; 1086 } else if (!loader_find_layer_name_in_list(&search_prop->info.layerName[0], target_list)) { 1087 // Make sure the layer isn't already in the output_list, skip adding it if it is. 1088 result = loader_add_layer_properties_to_list(inst, target_list, search_prop); 1089 if (result == VK_ERROR_OUT_OF_HOST_MEMORY) return result; 1090 if (NULL != expanded_target_list) { 1091 result = loader_add_layer_properties_to_list(inst, expanded_target_list, search_prop); 1092 if (result == VK_ERROR_OUT_OF_HOST_MEMORY) return result; 1093 } 1094 } 1095 } 1096 } else { 1097 loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0, 1098 "Failed to find layer name \"%s\" component layer \"%s\" to activate (Policy #LLP_LAYER_7)", 1099 prop->component_layer_names.list[comp_layer], prop->component_layer_names.list[comp_layer]); 1100 found_all_component_layers = false; 1101 } 1102 } 1103 1104 // Add this layer to the overall target list (not the expanded one) 1105 if (found_all_component_layers) { 1106 result = loader_add_layer_properties_to_list(inst, target_list, prop); 1107 if (result == VK_ERROR_OUT_OF_HOST_MEMORY) return result; 1108 // Write the result to out_found_all_component_layers in case this function is being recursed 1109 if (out_found_all_component_layers) *out_found_all_component_layers = found_all_component_layers; 1110 } 1111 1112 return result; 1113} 1114 1115VkExtensionProperties *get_extension_property(const char *name, const struct loader_extension_list *list) { 1116 for (uint32_t i = 0; i < list->count; i++) { 1117 if (strcmp(name, list->list[i].extensionName) == 0) return &list->list[i]; 1118 } 1119 return NULL; 1120} 1121 1122VkExtensionProperties *get_dev_extension_property(const char *name, const struct loader_device_extension_list *list) { 1123 for (uint32_t i = 0; i < list->count; i++) { 1124 if (strcmp(name, list->list[i].props.extensionName) == 0) return &list->list[i].props; 1125 } 1126 return NULL; 1127} 1128 1129// For Instance extensions implemented within the loader (i.e. DEBUG_REPORT 1130// the extension must provide two entry points for the loader to use: 1131// - "trampoline" entry point - this is the address returned by GetProcAddr 1132// and will always do what's necessary to support a 1133// global call. 1134// - "terminator" function - this function will be put at the end of the 1135// instance chain and will contain the necessary logic 1136// to call / process the extension for the appropriate 1137// ICDs that are available. 1138// There is no generic mechanism for including these functions, the references 1139// must be placed into the appropriate loader entry points. 1140// GetInstanceProcAddr: call extension GetInstanceProcAddr to check for GetProcAddr 1141// requests 1142// loader_coalesce_extensions(void) - add extension records to the list of global 1143// extension available to the app. 1144// instance_disp - add function pointer for terminator function 1145// to this array. 1146// The extension itself should be in a separate file that will be linked directly 1147// with the loader. 1148VkResult loader_get_icd_loader_instance_extensions(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list, 1149 struct loader_extension_list *inst_exts) { 1150 struct loader_extension_list icd_exts; 1151 VkResult res = VK_SUCCESS; 1152 char *env_value; 1153 bool filter_extensions = true; 1154 1155 // Check if a user wants to disable the instance extension filtering behavior 1156 env_value = loader_getenv("VK_LOADER_DISABLE_INST_EXT_FILTER", inst); 1157 if (NULL != env_value && atoi(env_value) != 0) { 1158 filter_extensions = false; 1159 } 1160 loader_free_getenv(env_value, inst); 1161 1162 // traverse scanned icd list adding non-duplicate extensions to the list 1163 for (uint32_t i = 0; i < icd_tramp_list->count; i++) { 1164 res = loader_init_generic_list(inst, (struct loader_generic_list *)&icd_exts, sizeof(VkExtensionProperties)); 1165 if (VK_SUCCESS != res) { 1166 goto out; 1167 } 1168 res = loader_add_instance_extensions(inst, icd_tramp_list->scanned_list[i].EnumerateInstanceExtensionProperties, 1169 icd_tramp_list->scanned_list[i].lib_name, &icd_exts); 1170 if (VK_SUCCESS == res) { 1171 if (filter_extensions) { 1172 // Remove any extensions not recognized by the loader 1173 for (int32_t j = 0; j < (int32_t)icd_exts.count; j++) { 1174 // See if the extension is in the list of supported extensions 1175 bool found = false; 1176 for (uint32_t k = 0; LOADER_INSTANCE_EXTENSIONS[k] != NULL; k++) { 1177 if (strcmp(icd_exts.list[j].extensionName, LOADER_INSTANCE_EXTENSIONS[k]) == 0) { 1178 found = true; 1179 break; 1180 } 1181 } 1182 1183 // If it isn't in the list, remove it 1184 if (!found) { 1185 for (uint32_t k = j + 1; k < icd_exts.count; k++) { 1186 icd_exts.list[k - 1] = icd_exts.list[k]; 1187 } 1188 --icd_exts.count; 1189 --j; 1190 } 1191 } 1192 } 1193 1194 res = loader_add_to_ext_list(inst, inst_exts, icd_exts.count, icd_exts.list); 1195 } 1196 loader_destroy_generic_list(inst, (struct loader_generic_list *)&icd_exts); 1197 if (VK_SUCCESS != res) { 1198 goto out; 1199 } 1200 }; 1201 1202 // Traverse loader's extensions, adding non-duplicate extensions to the list 1203 res = add_debug_extensions_to_ext_list(inst, inst_exts); 1204 if (res == VK_ERROR_OUT_OF_HOST_MEMORY) { 1205 goto out; 1206 } 1207 const VkExtensionProperties portability_enumeration_extension_info[] = { 1208 {VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME, VK_KHR_PORTABILITY_ENUMERATION_SPEC_VERSION}}; 1209 1210 // Add VK_KHR_portability_subset 1211 res = loader_add_to_ext_list(inst, inst_exts, sizeof(portability_enumeration_extension_info) / sizeof(VkExtensionProperties), 1212 portability_enumeration_extension_info); 1213 if (res == VK_ERROR_OUT_OF_HOST_MEMORY) { 1214 goto out; 1215 } 1216 1217 const VkExtensionProperties direct_driver_loading_extension_info[] = { 1218 {VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME, VK_LUNARG_DIRECT_DRIVER_LOADING_SPEC_VERSION}}; 1219 1220 // Add VK_LUNARG_direct_driver_loading 1221 res = loader_add_to_ext_list(inst, inst_exts, sizeof(direct_driver_loading_extension_info) / sizeof(VkExtensionProperties), 1222 direct_driver_loading_extension_info); 1223 if (res == VK_ERROR_OUT_OF_HOST_MEMORY) { 1224 goto out; 1225 } 1226 1227out: 1228 return res; 1229} 1230 1231struct loader_icd_term *loader_get_icd_and_device(const void *device, struct loader_device **found_dev, uint32_t *icd_index) { 1232 VkLayerDispatchTable *dispatch_table_device = loader_get_dispatch(device); 1233 if (NULL == dispatch_table_device) { 1234 *found_dev = NULL; 1235 return NULL; 1236 } 1237 loader_platform_thread_lock_mutex(&loader_global_instance_list_lock); 1238 *found_dev = NULL; 1239 1240 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) { 1241 uint32_t index = 0; 1242 for (struct loader_icd_term *icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) { 1243 for (struct loader_device *dev = icd_term->logical_device_list; dev; dev = dev->next) { 1244 // Value comparison of device prevents object wrapping by layers 1245 if (loader_get_dispatch(dev->icd_device) == dispatch_table_device || 1246 (dev->chain_device != VK_NULL_HANDLE && loader_get_dispatch(dev->chain_device) == dispatch_table_device)) { 1247 *found_dev = dev; 1248 if (NULL != icd_index) { 1249 *icd_index = index; 1250 } 1251 loader_platform_thread_unlock_mutex(&loader_global_instance_list_lock); 1252 return icd_term; 1253 } 1254 } 1255 index++; 1256 } 1257 } 1258 loader_platform_thread_unlock_mutex(&loader_global_instance_list_lock); 1259 return NULL; 1260} 1261 1262void loader_destroy_logical_device(struct loader_device *dev, const VkAllocationCallbacks *pAllocator) { 1263 if (pAllocator) { 1264 dev->alloc_callbacks = *pAllocator; 1265 } 1266 loader_device_heap_free(dev, dev); 1267} 1268 1269struct loader_device *loader_create_logical_device(const struct loader_instance *inst, const VkAllocationCallbacks *pAllocator) { 1270 struct loader_device *new_dev; 1271 new_dev = loader_calloc(pAllocator, sizeof(struct loader_device), VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); 1272 1273 if (!new_dev) { 1274 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_create_logical_device: Failed to alloc struct loader_device"); 1275 return NULL; 1276 } 1277 1278 new_dev->loader_dispatch.core_dispatch.magic = DEVICE_DISP_TABLE_MAGIC_NUMBER; 1279 1280 if (pAllocator) { 1281 new_dev->alloc_callbacks = *pAllocator; 1282 } 1283 1284 return new_dev; 1285} 1286 1287void loader_add_logical_device(struct loader_icd_term *icd_term, struct loader_device *dev) { 1288 dev->next = icd_term->logical_device_list; 1289 icd_term->logical_device_list = dev; 1290} 1291 1292void loader_remove_logical_device(struct loader_icd_term *icd_term, struct loader_device *found_dev, 1293 const VkAllocationCallbacks *pAllocator) { 1294 struct loader_device *dev, *prev_dev; 1295 1296 if (!icd_term || !found_dev) return; 1297 1298 prev_dev = NULL; 1299 dev = icd_term->logical_device_list; 1300 while (dev && dev != found_dev) { 1301 prev_dev = dev; 1302 dev = dev->next; 1303 } 1304 1305 if (prev_dev) 1306 prev_dev->next = found_dev->next; 1307 else 1308 icd_term->logical_device_list = found_dev->next; 1309 loader_destroy_logical_device(found_dev, pAllocator); 1310} 1311 1312void loader_icd_destroy(struct loader_instance *ptr_inst, struct loader_icd_term *icd_term, 1313 const VkAllocationCallbacks *pAllocator) { 1314 ptr_inst->total_icd_count--; 1315 for (struct loader_device *dev = icd_term->logical_device_list; dev;) { 1316 struct loader_device *next_dev = dev->next; 1317 loader_destroy_logical_device(dev, pAllocator); 1318 dev = next_dev; 1319 } 1320 1321 loader_instance_heap_free(ptr_inst, icd_term); 1322} 1323 1324struct loader_icd_term *loader_icd_add(struct loader_instance *ptr_inst, const struct loader_scanned_icd *scanned_icd) { 1325 struct loader_icd_term *icd_term; 1326 1327 icd_term = loader_instance_heap_calloc(ptr_inst, sizeof(struct loader_icd_term), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1328 if (!icd_term) { 1329 return NULL; 1330 } 1331 1332 icd_term->scanned_icd = scanned_icd; 1333 icd_term->this_instance = ptr_inst; 1334 1335 // Prepend to the list 1336 icd_term->next = ptr_inst->icd_terms; 1337 ptr_inst->icd_terms = icd_term; 1338 ptr_inst->total_icd_count++; 1339 1340 return icd_term; 1341} 1342 1343// Determine the ICD interface version to use. 1344// @param icd 1345// @param pVersion Output parameter indicating which version to use or 0 if 1346// the negotiation API is not supported by the ICD 1347// @return bool indicating true if the selected interface version is supported 1348// by the loader, false indicates the version is not supported 1349bool loader_get_icd_interface_version(PFN_vkNegotiateLoaderICDInterfaceVersion fp_negotiate_icd_version, uint32_t *pVersion) { 1350 if (fp_negotiate_icd_version == NULL) { 1351 // ICD does not support the negotiation API, it supports version 0 or 1 1352 // calling code must determine if it is version 0 or 1 1353 *pVersion = 0; 1354 } else { 1355 // ICD supports the negotiation API, so call it with the loader's 1356 // latest version supported 1357 *pVersion = CURRENT_LOADER_ICD_INTERFACE_VERSION; 1358 VkResult result = fp_negotiate_icd_version(pVersion); 1359 1360 if (result == VK_ERROR_INCOMPATIBLE_DRIVER) { 1361 // ICD no longer supports the loader's latest interface version so 1362 // fail loading the ICD 1363 return false; 1364 } 1365 } 1366 1367#if MIN_SUPPORTED_LOADER_ICD_INTERFACE_VERSION > 0 1368 if (*pVersion < MIN_SUPPORTED_LOADER_ICD_INTERFACE_VERSION) { 1369 // Loader no longer supports the ICD's latest interface version so fail 1370 // loading the ICD 1371 return false; 1372 } 1373#endif 1374 return true; 1375} 1376 1377void loader_scanned_icd_clear(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list) { 1378 if (0 != icd_tramp_list->capacity && icd_tramp_list->scanned_list) { 1379 for (uint32_t i = 0; i < icd_tramp_list->count; i++) { 1380 if (icd_tramp_list->scanned_list[i].handle) { 1381 loader_platform_close_library(icd_tramp_list->scanned_list[i].handle); 1382 icd_tramp_list->scanned_list[i].handle = NULL; 1383 } 1384 loader_instance_heap_free(inst, icd_tramp_list->scanned_list[i].lib_name); 1385 } 1386 loader_instance_heap_free(inst, icd_tramp_list->scanned_list); 1387 } 1388 memset(icd_tramp_list, 0, sizeof(struct loader_icd_tramp_list)); 1389} 1390 1391VkResult loader_scanned_icd_init(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list) { 1392 VkResult res = VK_SUCCESS; 1393 loader_scanned_icd_clear(inst, icd_tramp_list); 1394 icd_tramp_list->capacity = 8 * sizeof(struct loader_scanned_icd); 1395 icd_tramp_list->scanned_list = loader_instance_heap_alloc(inst, icd_tramp_list->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1396 if (NULL == icd_tramp_list->scanned_list) { 1397 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 1398 "loader_scanned_icd_init: Realloc failed for layer list when attempting to add new layer"); 1399 res = VK_ERROR_OUT_OF_HOST_MEMORY; 1400 } 1401 return res; 1402} 1403 1404VkResult loader_add_direct_driver(const struct loader_instance *inst, uint32_t index, 1405 const VkDirectDriverLoadingInfoLUNARG *pDriver, struct loader_icd_tramp_list *icd_tramp_list) { 1406 // Assume pDriver is valid, since there is no real way to check it. Calling code should make sure the pointer to the array 1407 // of VkDirectDriverLoadingInfoLUNARG structures is non-null. 1408 if (NULL == pDriver->pfnGetInstanceProcAddr) { 1409 loader_log( 1410 inst, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_DRIVER_BIT, 0, 1411 "loader_add_direct_driver: VkDirectDriverLoadingInfoLUNARG structure at index %d contains a NULL pointer for the " 1412 "pfnGetInstanceProcAddr member, skipping.", 1413 index); 1414 return VK_ERROR_INITIALIZATION_FAILED; 1415 } 1416 1417 PFN_vkGetInstanceProcAddr fp_get_proc_addr = pDriver->pfnGetInstanceProcAddr; 1418 PFN_vkCreateInstance fp_create_inst = NULL; 1419 PFN_vkEnumerateInstanceExtensionProperties fp_get_inst_ext_props = NULL; 1420 PFN_GetPhysicalDeviceProcAddr fp_get_phys_dev_proc_addr = NULL; 1421 PFN_vkNegotiateLoaderICDInterfaceVersion fp_negotiate_icd_version = NULL; 1422#if defined(VK_USE_PLATFORM_WIN32_KHR) 1423 PFN_vk_icdEnumerateAdapterPhysicalDevices fp_enum_dxgi_adapter_phys_devs = NULL; 1424#endif 1425 struct loader_scanned_icd *new_scanned_icd; 1426 uint32_t interface_version = 0; 1427 1428 // Try to get the negotiate ICD interface version function 1429 fp_negotiate_icd_version = (PFN_vk_icdNegotiateLoaderICDInterfaceVersion)pDriver->pfnGetInstanceProcAddr( 1430 NULL, "vk_icdNegotiateLoaderICDInterfaceVersion"); 1431 1432 if (NULL == fp_negotiate_icd_version) { 1433 loader_log(inst, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_DRIVER_BIT, 0, 1434 "loader_add_direct_driver: Could not get 'vk_icdNegotiateLoaderICDInterfaceVersion' from " 1435 "VkDirectDriverLoadingInfoLUNARG structure at " 1436 "index %d, skipping.", 1437 index); 1438 return VK_ERROR_INITIALIZATION_FAILED; 1439 } 1440 1441 if (!loader_get_icd_interface_version(fp_negotiate_icd_version, &interface_version)) { 1442 loader_log( 1443 inst, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_DRIVER_BIT, 0, 1444 "loader_add_direct_driver: VkDirectDriverLoadingInfoLUNARG structure at index %d supports interface version %d, " 1445 "which is incompatible with the Loader Driver Interface version that supports the VK_LUNARG_direct_driver_loading " 1446 "extension, skipping.", 1447 index, interface_version); 1448 return VK_ERROR_INITIALIZATION_FAILED; 1449 } 1450 1451 if (interface_version < 7) { 1452 loader_log( 1453 inst, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_DRIVER_BIT, 0, 1454 "loader_add_direct_driver: VkDirectDriverLoadingInfoLUNARG structure at index %d supports interface version %d, " 1455 "which is incompatible with the Loader Driver Interface version that supports the VK_LUNARG_direct_driver_loading " 1456 "extension, skipping.", 1457 index, interface_version); 1458 return VK_ERROR_INITIALIZATION_FAILED; 1459 } 1460 1461 fp_create_inst = (PFN_vkCreateInstance)pDriver->pfnGetInstanceProcAddr(NULL, "vkCreateInstance"); 1462 if (NULL == fp_create_inst) { 1463 loader_log(inst, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_DRIVER_BIT, 0, 1464 "loader_add_direct_driver: Could not get 'vkCreateInstance' from VkDirectDriverLoadingInfoLUNARG structure at " 1465 "index %d, skipping.", 1466 index); 1467 return VK_ERROR_INITIALIZATION_FAILED; 1468 } 1469 fp_get_inst_ext_props = 1470 (PFN_vkEnumerateInstanceExtensionProperties)pDriver->pfnGetInstanceProcAddr(NULL, "vkEnumerateInstanceExtensionProperties"); 1471 if (NULL == fp_get_inst_ext_props) { 1472 loader_log(inst, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_DRIVER_BIT, 0, 1473 "loader_add_direct_driver: Could not get 'vkEnumerateInstanceExtensionProperties' from " 1474 "VkDirectDriverLoadingInfoLUNARG structure at index %d, skipping.", 1475 index); 1476 return VK_ERROR_INITIALIZATION_FAILED; 1477 } 1478 1479 fp_get_phys_dev_proc_addr = 1480 (PFN_vk_icdGetPhysicalDeviceProcAddr)pDriver->pfnGetInstanceProcAddr(NULL, "vk_icdGetPhysicalDeviceProcAddr"); 1481#if defined(VK_USE_PLATFORM_WIN32_KHR) 1482 // Query "vk_icdEnumerateAdapterPhysicalDevices" with vk_icdGetInstanceProcAddr if the library reports interface version 1483 // 7 or greater, otherwise fallback to loading it from the platform dynamic linker 1484 fp_enum_dxgi_adapter_phys_devs = 1485 (PFN_vk_icdEnumerateAdapterPhysicalDevices)pDriver->pfnGetInstanceProcAddr(NULL, "vk_icdEnumerateAdapterPhysicalDevices"); 1486#endif 1487 1488 // check for enough capacity 1489 if ((icd_tramp_list->count * sizeof(struct loader_scanned_icd)) >= icd_tramp_list->capacity) { 1490 void *new_ptr = loader_instance_heap_realloc(inst, icd_tramp_list->scanned_list, icd_tramp_list->capacity, 1491 icd_tramp_list->capacity * 2, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1492 if (NULL == new_ptr) { 1493 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 1494 "loader_add_direct_driver: Realloc failed on icd library list for ICD index %u", index); 1495 return VK_ERROR_OUT_OF_HOST_MEMORY; 1496 } 1497 icd_tramp_list->scanned_list = new_ptr; 1498 1499 // double capacity 1500 icd_tramp_list->capacity *= 2; 1501 } 1502 1503 // Driver must be 1.1 to support version 7 1504 uint32_t api_version = VK_API_VERSION_1_1; 1505 PFN_vkEnumerateInstanceVersion icd_enumerate_instance_version = 1506 (PFN_vkEnumerateInstanceVersion)pDriver->pfnGetInstanceProcAddr(NULL, "vkEnumerateInstanceVersion"); 1507 1508 if (icd_enumerate_instance_version) { 1509 VkResult res = icd_enumerate_instance_version(&api_version); 1510 if (res != VK_SUCCESS) { 1511 return res; 1512 } 1513 } 1514 1515 new_scanned_icd = &(icd_tramp_list->scanned_list[icd_tramp_list->count]); 1516 new_scanned_icd->handle = NULL; 1517 new_scanned_icd->api_version = api_version; 1518 new_scanned_icd->GetInstanceProcAddr = fp_get_proc_addr; 1519 new_scanned_icd->GetPhysicalDeviceProcAddr = fp_get_phys_dev_proc_addr; 1520 new_scanned_icd->EnumerateInstanceExtensionProperties = fp_get_inst_ext_props; 1521 new_scanned_icd->CreateInstance = fp_create_inst; 1522#if defined(VK_USE_PLATFORM_WIN32_KHR) 1523 new_scanned_icd->EnumerateAdapterPhysicalDevices = fp_enum_dxgi_adapter_phys_devs; 1524#endif 1525 new_scanned_icd->interface_version = interface_version; 1526 1527 new_scanned_icd->lib_name = NULL; 1528 icd_tramp_list->count++; 1529 1530 loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_DRIVER_BIT, 0, 1531 "loader_add_direct_driver: Adding driver found in index %d of " 1532 "VkDirectDriverLoadingListLUNARG::pDrivers structure. pfnGetInstanceProcAddr was set to %p", 1533 index, pDriver->pfnGetInstanceProcAddr); 1534 1535 return VK_SUCCESS; 1536} 1537 1538// Search through VkInstanceCreateInfo's pNext chain for any drivers from the direct driver loading extension and load them. 1539VkResult loader_scan_for_direct_drivers(const struct loader_instance *inst, const VkInstanceCreateInfo *pCreateInfo, 1540 struct loader_icd_tramp_list *icd_tramp_list, bool *direct_driver_loading_exclusive_mode) { 1541 if (NULL == pCreateInfo) { 1542 // Don't do this logic unless we are being called from vkCreateInstance, when pCreateInfo will be non-null 1543 return VK_SUCCESS; 1544 } 1545 bool direct_driver_loading_enabled = false; 1546 // Try to if VK_LUNARG_direct_driver_loading is enabled and if we are using it exclusively 1547 // Skip this step if inst is NULL, aka when this function is being called before instance creation 1548 if (inst != NULL && pCreateInfo->ppEnabledExtensionNames && pCreateInfo->enabledExtensionCount > 0) { 1549 // Look through the enabled extension list, make sure VK_LUNARG_direct_driver_loading is present 1550 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) { 1551 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME) == 0) { 1552 direct_driver_loading_enabled = true; 1553 break; 1554 } 1555 } 1556 } 1557 const VkDirectDriverLoadingListLUNARG *ddl_list = NULL; 1558 // Find the VkDirectDriverLoadingListLUNARG struct in the pNext chain of vkInstanceCreateInfo 1559 const VkBaseOutStructure *chain = pCreateInfo->pNext; 1560 while (chain) { 1561 if (chain->sType == VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_LIST_LUNARG) { 1562 ddl_list = (VkDirectDriverLoadingListLUNARG *)chain; 1563 break; 1564 } 1565 chain = (const VkBaseOutStructure *)chain->pNext; 1566 } 1567 if (NULL == ddl_list) { 1568 if (direct_driver_loading_enabled) { 1569 loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0, 1570 "loader_scan_for_direct_drivers: The VK_LUNARG_direct_driver_loading extension was enabled but the " 1571 "pNext chain of " 1572 "VkInstanceCreateInfo did not contain the " 1573 "VkDirectDriverLoadingListLUNARG structure."); 1574 } 1575 // Always want to exit early if there was no VkDirectDriverLoadingListLUNARG in the pNext chain 1576 return VK_SUCCESS; 1577 } 1578 1579 if (!direct_driver_loading_enabled) { 1580 loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0, 1581 "loader_scan_for_direct_drivers: The pNext chain of VkInstanceCreateInfo contained the " 1582 "VkDirectDriverLoadingListLUNARG structure, but the VK_LUNARG_direct_driver_loading extension was " 1583 "not enabled."); 1584 return VK_SUCCESS; 1585 } 1586 // If we are using exclusive mode, skip looking for any more drivers from system or environment variables 1587 if (ddl_list->mode == VK_DIRECT_DRIVER_LOADING_MODE_EXCLUSIVE_LUNARG) { 1588 *direct_driver_loading_exclusive_mode = true; 1589 loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_DRIVER_BIT, 0, 1590 "loader_scan_for_direct_drivers: The VK_LUNARG_direct_driver_loading extension is active and specified " 1591 "VK_DIRECT_DRIVER_LOADING_MODE_EXCLUSIVE_LUNARG, skipping system and environment " 1592 "variable driver search mechanisms."); 1593 } 1594 if (NULL == ddl_list->pDrivers) { 1595 loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0, 1596 "loader_scan_for_direct_drivers: The VkDirectDriverLoadingListLUNARG structure in the pNext chain of " 1597 "VkInstanceCreateInfo has a NULL pDrivers member."); 1598 return VK_SUCCESS; 1599 } 1600 if (ddl_list->driverCount == 0) { 1601 loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0, 1602 "loader_scan_for_direct_drivers: The VkDirectDriverLoadingListLUNARG structure in the pNext chain of " 1603 "VkInstanceCreateInfo has a non-null pDrivers member but a driverCount member with a value " 1604 "of zero."); 1605 return VK_SUCCESS; 1606 } 1607 // Go through all VkDirectDriverLoadingInfoLUNARG entries and add each driver 1608 // Because icd_tramp's are prepended, this will result in the drivers appearing at the end 1609 for (uint32_t i = 0; i < ddl_list->driverCount; i++) { 1610 VkResult res = loader_add_direct_driver(inst, i, &ddl_list->pDrivers[i], icd_tramp_list); 1611 if (res == VK_ERROR_OUT_OF_HOST_MEMORY) { 1612 return res; 1613 } 1614 } 1615 1616 return VK_SUCCESS; 1617} 1618 1619VkResult loader_scanned_icd_add(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list, 1620 const char *filename, uint32_t api_version, enum loader_layer_library_status *lib_status) { 1621 loader_platform_dl_handle handle = NULL; 1622 PFN_vkCreateInstance fp_create_inst = NULL; 1623 PFN_vkEnumerateInstanceExtensionProperties fp_get_inst_ext_props = NULL; 1624 PFN_vkGetInstanceProcAddr fp_get_proc_addr = NULL; 1625 PFN_GetPhysicalDeviceProcAddr fp_get_phys_dev_proc_addr = NULL; 1626 PFN_vkNegotiateLoaderICDInterfaceVersion fp_negotiate_icd_version = NULL; 1627#if defined(VK_USE_PLATFORM_WIN32_KHR) 1628 PFN_vk_icdEnumerateAdapterPhysicalDevices fp_enum_dxgi_adapter_phys_devs = NULL; 1629#endif 1630 struct loader_scanned_icd *new_scanned_icd = NULL; 1631 uint32_t interface_vers; 1632 VkResult res = VK_SUCCESS; 1633 1634 // This shouldn't happen, but the check is necessary because dlopen returns a handle to the main program when 1635 // filename is NULL 1636 if (filename == NULL) { 1637 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_scanned_icd_add: A NULL filename was used, skipping this ICD", 1638 filename); 1639 res = VK_ERROR_INCOMPATIBLE_DRIVER; 1640 goto out; 1641 } 1642 1643// TODO implement smarter opening/closing of libraries. For now this 1644// function leaves libraries open and the scanned_icd_clear closes them 1645#if defined(__Fuchsia__) 1646 handle = loader_platform_open_driver(filename); 1647#else 1648 handle = loader_platform_open_library(filename); 1649#endif 1650 if (NULL == handle) { 1651 loader_handle_load_library_error(inst, filename, lib_status); 1652 if (lib_status && *lib_status == LOADER_LAYER_LIB_ERROR_OUT_OF_MEMORY) { 1653 res = VK_ERROR_OUT_OF_HOST_MEMORY; 1654 } else { 1655 res = VK_ERROR_INCOMPATIBLE_DRIVER; 1656 } 1657 goto out; 1658 } 1659 1660 // Try to load the driver's exported vk_icdNegotiateLoaderICDInterfaceVersion 1661 fp_negotiate_icd_version = loader_platform_get_proc_address(handle, "vk_icdNegotiateLoaderICDInterfaceVersion"); 1662 1663 // If it isn't exported, we are dealing with either a v0, v1, or a v7 and up driver 1664 if (NULL == fp_negotiate_icd_version) { 1665 // Try to load the driver's exported vk_icdGetInstanceProcAddr - if this is a v7 or up driver, we can use it to get 1666 // the driver's vk_icdNegotiateLoaderICDInterfaceVersion function 1667 fp_get_proc_addr = loader_platform_get_proc_address(handle, "vk_icdGetInstanceProcAddr"); 1668 1669 // If we successfully loaded vk_icdGetInstanceProcAddr, try to get vk_icdNegotiateLoaderICDInterfaceVersion 1670 if (fp_get_proc_addr) { 1671 fp_negotiate_icd_version = 1672 (PFN_vk_icdNegotiateLoaderICDInterfaceVersion)fp_get_proc_addr(NULL, "vk_icdNegotiateLoaderICDInterfaceVersion"); 1673 } 1674 } 1675 1676 // Try to negotiate the Loader and Driver Interface Versions 1677 // loader_get_icd_interface_version will check if fp_negotiate_icd_version is NULL, so we don't have to. 1678 // If it *is* NULL, that means this driver uses interface version 0 or 1 1679 if (!loader_get_icd_interface_version(fp_negotiate_icd_version, &interface_vers)) { 1680 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 1681 "loader_scanned_icd_add: ICD %s doesn't support interface version compatible with loader, skip this ICD.", 1682 filename); 1683 goto out; 1684 } 1685 1686 // If we didn't already query vk_icdGetInstanceProcAddr, try now 1687 if (NULL == fp_get_proc_addr) { 1688 fp_get_proc_addr = loader_platform_get_proc_address(handle, "vk_icdGetInstanceProcAddr"); 1689 } 1690 1691 // If vk_icdGetInstanceProcAddr is NULL, this ICD is using version 0 and so we should respond accordingly. 1692 if (NULL == fp_get_proc_addr) { 1693 // Exporting vk_icdNegotiateLoaderICDInterfaceVersion but not vk_icdGetInstanceProcAddr violates Version 2's 1694 // requirements, as for Version 2 to be supported Version 1 must also be supported 1695 if (interface_vers != 0) { 1696 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 1697 "loader_scanned_icd_add: ICD %s reports an interface version of %d but doesn't export " 1698 "vk_icdGetInstanceProcAddr, skip this ICD.", 1699 filename, interface_vers); 1700 goto out; 1701 } 1702 // Use deprecated interface from version 0 1703 fp_get_proc_addr = loader_platform_get_proc_address(handle, "vkGetInstanceProcAddr"); 1704 if (NULL == fp_get_proc_addr) { 1705 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 1706 "loader_scanned_icd_add: Attempt to retrieve either \'vkGetInstanceProcAddr\' or " 1707 "\'vk_icdGetInstanceProcAddr\' from ICD %s failed.", 1708 filename); 1709 goto out; 1710 } else { 1711 loader_log(inst, VULKAN_LOADER_WARN_BIT, 0, 1712 "loader_scanned_icd_add: Using deprecated ICD interface of \'vkGetInstanceProcAddr\' instead of " 1713 "\'vk_icdGetInstanceProcAddr\' for ICD %s", 1714 filename); 1715 } 1716 fp_create_inst = loader_platform_get_proc_address(handle, "vkCreateInstance"); 1717 if (NULL == fp_create_inst) { 1718 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 1719 "loader_scanned_icd_add: Failed querying \'vkCreateInstance\' via dlsym/LoadLibrary for ICD %s", filename); 1720 goto out; 1721 } 1722 fp_get_inst_ext_props = loader_platform_get_proc_address(handle, "vkEnumerateInstanceExtensionProperties"); 1723 if (NULL == fp_get_inst_ext_props) { 1724 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 1725 "loader_scanned_icd_add: Could not get \'vkEnumerateInstanceExtensionProperties\' via dlsym/LoadLibrary " 1726 "for ICD %s", 1727 filename); 1728 goto out; 1729 } 1730 } else { 1731 // vk_icdGetInstanceProcAddr was successfully found, we can assume the version is at least one 1732 // If vk_icdNegotiateLoaderICDInterfaceVersion was also found, interface_vers must be 2 or greater, so this check is 1733 // fine 1734 if (interface_vers == 0) { 1735 interface_vers = 1; 1736 } 1737 1738 fp_create_inst = (PFN_vkCreateInstance)fp_get_proc_addr(NULL, "vkCreateInstance"); 1739 if (NULL == fp_create_inst) { 1740 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 1741 "loader_scanned_icd_add: Could not get \'vkCreateInstance\' via \'vk_icdGetInstanceProcAddr\' for ICD %s", 1742 filename); 1743 goto out; 1744 } 1745 fp_get_inst_ext_props = 1746 (PFN_vkEnumerateInstanceExtensionProperties)fp_get_proc_addr(NULL, "vkEnumerateInstanceExtensionProperties"); 1747 if (NULL == fp_get_inst_ext_props) { 1748 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 1749 "loader_scanned_icd_add: Could not get \'vkEnumerateInstanceExtensionProperties\' via " 1750 "\'vk_icdGetInstanceProcAddr\' for ICD %s", 1751 filename); 1752 goto out; 1753 } 1754 // Query "vk_icdGetPhysicalDeviceProcAddr" with vk_icdGetInstanceProcAddr if the library reports interface version 7 or 1755 // greater, otherwise fallback to loading it from the platform dynamic linker 1756 if (interface_vers >= 7) { 1757 fp_get_phys_dev_proc_addr = 1758 (PFN_vk_icdGetPhysicalDeviceProcAddr)fp_get_proc_addr(NULL, "vk_icdGetPhysicalDeviceProcAddr"); 1759 } 1760 if (NULL == fp_get_phys_dev_proc_addr && interface_vers >= 3) { 1761 fp_get_phys_dev_proc_addr = loader_platform_get_proc_address(handle, "vk_icdGetPhysicalDeviceProcAddr"); 1762 } 1763#if defined(VK_USE_PLATFORM_WIN32_KHR) 1764 // Query "vk_icdEnumerateAdapterPhysicalDevices" with vk_icdGetInstanceProcAddr if the library reports interface version 1765 // 7 or greater, otherwise fallback to loading it from the platform dynamic linker 1766 if (interface_vers >= 7) { 1767 fp_enum_dxgi_adapter_phys_devs = 1768 (PFN_vk_icdEnumerateAdapterPhysicalDevices)fp_get_proc_addr(NULL, "vk_icdEnumerateAdapterPhysicalDevices"); 1769 } 1770 if (NULL == fp_enum_dxgi_adapter_phys_devs && interface_vers >= 6) { 1771 fp_enum_dxgi_adapter_phys_devs = loader_platform_get_proc_address(handle, "vk_icdEnumerateAdapterPhysicalDevices"); 1772 } 1773#endif 1774 } 1775 1776 // check for enough capacity 1777 if ((icd_tramp_list->count * sizeof(struct loader_scanned_icd)) >= icd_tramp_list->capacity) { 1778 void *new_ptr = loader_instance_heap_realloc(inst, icd_tramp_list->scanned_list, icd_tramp_list->capacity, 1779 icd_tramp_list->capacity * 2, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1780 if (NULL == new_ptr) { 1781 res = VK_ERROR_OUT_OF_HOST_MEMORY; 1782 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_scanned_icd_add: Realloc failed on icd library list for ICD %s", 1783 filename); 1784 goto out; 1785 } 1786 icd_tramp_list->scanned_list = new_ptr; 1787 1788 // double capacity 1789 icd_tramp_list->capacity *= 2; 1790 } 1791 1792 loader_api_version api_version_struct = loader_make_version(api_version); 1793 if (interface_vers <= 4 && loader_check_version_meets_required(LOADER_VERSION_1_1_0, api_version_struct)) { 1794 loader_log(inst, VULKAN_LOADER_WARN_BIT, 0, 1795 "loader_scanned_icd_add: Driver %s supports Vulkan %u.%u, but only supports loader interface version %u." 1796 " Interface version 5 or newer required to support this version of Vulkan (Policy #LDP_DRIVER_7)", 1797 filename, api_version_struct.major, api_version_struct.minor, interface_vers); 1798 } 1799 1800 new_scanned_icd = &(icd_tramp_list->scanned_list[icd_tramp_list->count]); 1801 new_scanned_icd->handle = handle; 1802 new_scanned_icd->api_version = api_version; 1803 new_scanned_icd->GetInstanceProcAddr = fp_get_proc_addr; 1804 new_scanned_icd->GetPhysicalDeviceProcAddr = fp_get_phys_dev_proc_addr; 1805 new_scanned_icd->EnumerateInstanceExtensionProperties = fp_get_inst_ext_props; 1806 new_scanned_icd->CreateInstance = fp_create_inst; 1807#if defined(VK_USE_PLATFORM_WIN32_KHR) 1808 new_scanned_icd->EnumerateAdapterPhysicalDevices = fp_enum_dxgi_adapter_phys_devs; 1809#endif 1810 new_scanned_icd->interface_version = interface_vers; 1811 1812 res = loader_copy_to_new_str(inst, filename, &new_scanned_icd->lib_name); 1813 if (VK_ERROR_OUT_OF_HOST_MEMORY == res) { 1814 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_scanned_icd_add: Out of memory can't add ICD %s", filename); 1815 goto out; 1816 } 1817 icd_tramp_list->count++; 1818 1819out: 1820 1821 return res; 1822} 1823 1824void loader_initialize(void) { 1825 // initialize mutexes 1826 loader_platform_thread_create_mutex(&loader_lock); 1827 loader_platform_thread_create_mutex(&loader_preload_icd_lock); 1828 loader_platform_thread_create_mutex(&loader_global_instance_list_lock); 1829 init_global_loader_settings(); 1830 1831 // initialize logging 1832 loader_init_global_debug_level(); 1833#if defined(_WIN32) 1834 windows_initialization(); 1835#endif 1836 1837 loader_api_version version = loader_make_full_version(VK_HEADER_VERSION_COMPLETE); 1838 loader_log(NULL, VULKAN_LOADER_INFO_BIT, 0, "Vulkan Loader Version %d.%d.%d", version.major, version.minor, version.patch); 1839 1840#if defined(GIT_BRANCH_NAME) && defined(GIT_TAG_INFO) 1841 loader_log(NULL, VULKAN_LOADER_INFO_BIT, 0, "[Vulkan Loader Git - Tag: " GIT_BRANCH_NAME ", Branch/Commit: " GIT_TAG_INFO "]"); 1842#endif 1843 1844 char *loader_disable_dynamic_library_unloading_env_var = loader_getenv("VK_LOADER_DISABLE_DYNAMIC_LIBRARY_UNLOADING", NULL); 1845 if (loader_disable_dynamic_library_unloading_env_var && 1846 0 == strncmp(loader_disable_dynamic_library_unloading_env_var, "1", 2)) { 1847 loader_disable_dynamic_library_unloading = true; 1848 loader_log(NULL, VULKAN_LOADER_WARN_BIT, 0, "Vulkan Loader: library unloading is disabled"); 1849 } else { 1850 loader_disable_dynamic_library_unloading = false; 1851 } 1852 loader_free_getenv(loader_disable_dynamic_library_unloading_env_var, NULL); 1853#if defined(LOADER_USE_UNSAFE_FILE_SEARCH) 1854 loader_log(NULL, VULKAN_LOADER_WARN_BIT, 0, "Vulkan Loader: unsafe searching is enabled"); 1855#endif 1856} 1857 1858void loader_release() { 1859 // Guarantee release of the preloaded ICD libraries. This may have already been called in vkDestroyInstance. 1860 loader_unload_preloaded_icds(); 1861 1862 // release mutexes 1863 teardown_global_loader_settings(); 1864 loader_platform_thread_delete_mutex(&loader_lock); 1865 loader_platform_thread_delete_mutex(&loader_preload_icd_lock); 1866 loader_platform_thread_delete_mutex(&loader_global_instance_list_lock); 1867} 1868 1869// Preload the ICD libraries that are likely to be needed so we don't repeatedly load/unload them later 1870void loader_preload_icds(void) { 1871 loader_platform_thread_lock_mutex(&loader_preload_icd_lock); 1872 1873 // Already preloaded, skip loading again. 1874 if (scanned_icds.scanned_list != NULL) { 1875 loader_platform_thread_unlock_mutex(&loader_preload_icd_lock); 1876 return; 1877 } 1878 1879 VkResult result = loader_icd_scan(NULL, &scanned_icds, NULL, NULL); 1880 if (result != VK_SUCCESS) { 1881 loader_scanned_icd_clear(NULL, &scanned_icds); 1882 } 1883 loader_platform_thread_unlock_mutex(&loader_preload_icd_lock); 1884} 1885 1886// Release the ICD libraries that were preloaded 1887void loader_unload_preloaded_icds(void) { 1888 loader_platform_thread_lock_mutex(&loader_preload_icd_lock); 1889 loader_scanned_icd_clear(NULL, &scanned_icds); 1890 loader_platform_thread_unlock_mutex(&loader_preload_icd_lock); 1891} 1892 1893#if !defined(_WIN32) 1894__attribute__((constructor)) void loader_init_library(void) { loader_initialize(); } 1895 1896__attribute__((destructor)) void loader_free_library(void) { loader_release(); } 1897#endif 1898 1899// Get next file or dirname given a string list or registry key path 1900// 1901// \returns 1902// A pointer to first char in the next path. 1903// The next path (or NULL) in the list is returned in next_path. 1904// Note: input string is modified in some cases. PASS IN A COPY! 1905char *loader_get_next_path(char *path) { 1906 uint32_t len; 1907 char *next; 1908 1909 if (path == NULL) return NULL; 1910 next = strchr(path, PATH_SEPARATOR); 1911 if (next == NULL) { 1912 len = (uint32_t)strlen(path); 1913 next = path + len; 1914 } else { 1915 *next = '\0'; 1916 next++; 1917 } 1918 1919 return next; 1920} 1921 1922/* Processes a json manifest's library_path and the location of the json manifest to create the path of the library 1923 * The output is stored in out_fullpath by allocating a string - so its the caller's responsibility to free it 1924 * The output is the combination of the base path of manifest_file_path concatenated with library path 1925 * If library_path is an absolute path, we do not prepend the base path of manifest_file_path 1926 * 1927 * This function takes ownership of library_path - caller does not need to worry about freeing it. 1928 */ 1929VkResult combine_manifest_directory_and_library_path(const struct loader_instance *inst, char *library_path, 1930 const char *manifest_file_path, char **out_fullpath) { 1931 assert(library_path && manifest_file_path && out_fullpath); 1932 if (loader_platform_is_path_absolute(library_path)) { 1933 *out_fullpath = library_path; 1934 return VK_SUCCESS; 1935 } 1936 VkResult res = VK_SUCCESS; 1937 1938 size_t library_path_len = strlen(library_path); 1939 size_t manifest_file_path_str_len = strlen(manifest_file_path); 1940 bool library_path_contains_directory_symbol = false; 1941 for (size_t i = 0; i < library_path_len; i++) { 1942 if (library_path[i] == DIRECTORY_SYMBOL) { 1943 library_path_contains_directory_symbol = true; 1944 break; 1945 } 1946 } 1947 // Means that the library_path is neither absolute nor relative - thus we should not modify it at all 1948 if (!library_path_contains_directory_symbol) { 1949 *out_fullpath = library_path; 1950 return VK_SUCCESS; 1951 } 1952 // must include both a directory symbol and the null terminator 1953 size_t new_str_len = library_path_len + manifest_file_path_str_len + 1 + 1; 1954 1955 *out_fullpath = loader_instance_heap_calloc(inst, new_str_len, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1956 if (NULL == *out_fullpath) { 1957 res = VK_ERROR_OUT_OF_HOST_MEMORY; 1958 goto out; 1959 } 1960 size_t cur_loc_in_out_fullpath = 0; 1961 // look for the last occurrence of DIRECTORY_SYMBOL in manifest_file_path 1962 size_t last_directory_symbol = 0; 1963 bool found_directory_symbol = false; 1964 for (size_t i = 0; i < manifest_file_path_str_len; i++) { 1965 if (manifest_file_path[i] == DIRECTORY_SYMBOL) { 1966 last_directory_symbol = i + 1; // we want to include the symbol 1967 found_directory_symbol = true; 1968 // dont break because we want to find the last occurrence 1969 } 1970 } 1971 // Add manifest_file_path up to the last directory symbol 1972 if (found_directory_symbol) { 1973 loader_strncpy(*out_fullpath, new_str_len, manifest_file_path, last_directory_symbol); 1974 cur_loc_in_out_fullpath += last_directory_symbol; 1975 } 1976 loader_strncpy(&(*out_fullpath)[cur_loc_in_out_fullpath], new_str_len - cur_loc_in_out_fullpath, library_path, 1977 library_path_len); 1978 cur_loc_in_out_fullpath += library_path_len + 1; 1979 (*out_fullpath)[cur_loc_in_out_fullpath] = '\0'; 1980 1981out: 1982 loader_instance_heap_free(inst, library_path); 1983 1984 return res; 1985} 1986 1987// Given a filename (file) and a list of paths (in_dirs), try to find an existing 1988// file in the paths. If filename already is a path then no searching in the given paths. 1989// 1990// @return - A string in out_fullpath of either the full path or file. 1991void loader_get_fullpath(const char *file, const char *in_dirs, size_t out_size, char *out_fullpath) { 1992 if (!loader_platform_is_path(file) && *in_dirs) { 1993 size_t dirs_copy_len = strlen(in_dirs) + 1; 1994 char *dirs_copy = loader_stack_alloc(dirs_copy_len); 1995 loader_strncpy(dirs_copy, dirs_copy_len, in_dirs, dirs_copy_len); 1996 1997 // find if file exists after prepending paths in given list 1998 // for (dir = dirs_copy; *dir && (next_dir = loader_get_next_path(dir)); dir = next_dir) { 1999 char *dir = dirs_copy; 2000 char *next_dir = loader_get_next_path(dir); 2001 while (*dir && next_dir) { 2002 int path_concat_ret = snprintf(out_fullpath, out_size, "%s%c%s", dir, DIRECTORY_SYMBOL, file); 2003 if (path_concat_ret < 0) { 2004 continue; 2005 } 2006 if (loader_platform_file_exists(out_fullpath)) { 2007 return; 2008 } 2009 dir = next_dir; 2010 next_dir = loader_get_next_path(dir); 2011 } 2012 } 2013 2014 (void)snprintf(out_fullpath, out_size, "%s", file); 2015} 2016 2017// Verify that all component layers in a meta-layer are valid. 2018bool verify_meta_layer_component_layers(const struct loader_instance *inst, struct loader_layer_properties *prop, 2019 struct loader_layer_list *instance_layers) { 2020 loader_api_version meta_layer_version = loader_make_version(prop->info.specVersion); 2021 2022 for (uint32_t comp_layer = 0; comp_layer < prop->component_layer_names.count; comp_layer++) { 2023 struct loader_layer_properties *comp_prop = 2024 loader_find_layer_property(prop->component_layer_names.list[comp_layer], instance_layers); 2025 if (comp_prop == NULL) { 2026 loader_log(inst, VULKAN_LOADER_WARN_BIT, 0, 2027 "verify_meta_layer_component_layers: Meta-layer %s can't find component layer %s at index %d." 2028 " Skipping this layer.", 2029 prop->info.layerName, prop->component_layer_names.list[comp_layer], comp_layer); 2030 2031 return false; 2032 } 2033 2034 // Check the version of each layer, they need to be at least MAJOR and MINOR 2035 loader_api_version comp_prop_version = loader_make_version(comp_prop->info.specVersion); 2036 if (!loader_check_version_meets_required(meta_layer_version, comp_prop_version)) { 2037 loader_log(inst, VULKAN_LOADER_WARN_BIT, 0, 2038 "verify_meta_layer_component_layers: Meta-layer uses API version %d.%d, but component " 2039 "layer %d has API version %d.%d that is lower. Skipping this layer.", 2040 meta_layer_version.major, meta_layer_version.minor, comp_layer, comp_prop_version.major, 2041 comp_prop_version.minor); 2042 2043 return false; 2044 } 2045 2046 // Make sure the layer isn't using it's own name 2047 if (!strcmp(prop->info.layerName, prop->component_layer_names.list[comp_layer])) { 2048 loader_log(inst, VULKAN_LOADER_WARN_BIT, 0, 2049 "verify_meta_layer_component_layers: Meta-layer %s lists itself in its component layer " 2050 "list at index %d. Skipping this layer.", 2051 prop->info.layerName, comp_layer); 2052 2053 return false; 2054 } 2055 if (comp_prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER) { 2056 loader_log(inst, VULKAN_LOADER_INFO_BIT, 0, 2057 "verify_meta_layer_component_layers: Adding meta-layer %s which also contains meta-layer %s", 2058 prop->info.layerName, comp_prop->info.layerName); 2059 2060 // Make sure if the layer is using a meta-layer in its component list that we also verify that. 2061 if (!verify_meta_layer_component_layers(inst, comp_prop, instance_layers)) { 2062 loader_log(inst, VULKAN_LOADER_WARN_BIT, 0, 2063 "Meta-layer %s component layer %s can not find all component layers." 2064 " Skipping this layer.", 2065 prop->info.layerName, prop->component_layer_names.list[comp_layer]); 2066 return false; 2067 } 2068 } 2069 } 2070 // Didn't exit early so that means it passed all checks 2071 loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0, 2072 "Meta-layer \"%s\" all %d component layers appear to be valid.", prop->info.layerName, 2073 prop->component_layer_names.count); 2074 2075 // If layer logging is on, list the internals included in the meta-layer 2076 for (uint32_t comp_layer = 0; comp_layer < prop->component_layer_names.count; comp_layer++) { 2077 loader_log(inst, VULKAN_LOADER_LAYER_BIT, 0, " [%d] %s", comp_layer, prop->component_layer_names.list[comp_layer]); 2078 } 2079 return true; 2080} 2081 2082// Add any instance and device extensions from component layers to this layer 2083// list, so that anyone querying extensions will only need to look at the meta-layer 2084bool update_meta_layer_extensions_from_component_layers(const struct loader_instance *inst, struct loader_layer_properties *prop, 2085 struct loader_layer_list *instance_layers) { 2086 VkResult res = VK_SUCCESS; 2087 for (uint32_t comp_layer = 0; comp_layer < prop->component_layer_names.count; comp_layer++) { 2088 struct loader_layer_properties *comp_prop = 2089 loader_find_layer_property(prop->component_layer_names.list[comp_layer], instance_layers); 2090 2091 if (NULL != comp_prop->instance_extension_list.list) { 2092 for (uint32_t ext = 0; ext < comp_prop->instance_extension_list.count; ext++) { 2093 loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Meta-layer %s component layer %s adding instance extension %s", 2094 prop->info.layerName, prop->component_layer_names.list[comp_layer], 2095 comp_prop->instance_extension_list.list[ext].extensionName); 2096 2097 if (!has_vk_extension_property(&comp_prop->instance_extension_list.list[ext], &prop->instance_extension_list)) { 2098 res = loader_add_to_ext_list(inst, &prop->instance_extension_list, 1, 2099 &comp_prop->instance_extension_list.list[ext]); 2100 if (VK_ERROR_OUT_OF_HOST_MEMORY == res) { 2101 return res; 2102 } 2103 } 2104 } 2105 } 2106 if (NULL != comp_prop->device_extension_list.list) { 2107 for (uint32_t ext = 0; ext < comp_prop->device_extension_list.count; ext++) { 2108 loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Meta-layer %s component layer %s adding device extension %s", 2109 prop->info.layerName, prop->component_layer_names.list[comp_layer], 2110 comp_prop->device_extension_list.list[ext].props.extensionName); 2111 2112 if (!has_vk_dev_ext_property(&comp_prop->device_extension_list.list[ext].props, &prop->device_extension_list)) { 2113 loader_add_to_dev_ext_list(inst, &prop->device_extension_list, 2114 &comp_prop->device_extension_list.list[ext].props, NULL); 2115 if (VK_ERROR_OUT_OF_HOST_MEMORY == res) { 2116 return res; 2117 } 2118 } 2119 } 2120 } 2121 } 2122 return res; 2123} 2124 2125// Verify that all meta-layers in a layer list are valid. 2126VkResult verify_all_meta_layers(struct loader_instance *inst, const struct loader_envvar_all_filters *filters, 2127 struct loader_layer_list *instance_layers, bool *override_layer_present) { 2128 VkResult res = VK_SUCCESS; 2129 *override_layer_present = false; 2130 for (int32_t i = 0; i < (int32_t)instance_layers->count; i++) { 2131 struct loader_layer_properties *prop = &instance_layers->list[i]; 2132 2133 // If this is a meta-layer, make sure it is valid 2134 if (prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER) { 2135 if (verify_meta_layer_component_layers(inst, prop, instance_layers)) { 2136 // If any meta layer is valid, update its extension list to include the extensions from its component layers. 2137 res = update_meta_layer_extensions_from_component_layers(inst, prop, instance_layers); 2138 if (VK_ERROR_OUT_OF_HOST_MEMORY == res) { 2139 return res; 2140 } 2141 if (prop->is_override && loader_implicit_layer_is_enabled(inst, filters, prop)) { 2142 *override_layer_present = true; 2143 } 2144 } else { 2145 loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, 2146 "Removing meta-layer %s from instance layer list since it appears invalid.", prop->info.layerName); 2147 2148 loader_remove_layer_in_list(inst, instance_layers, i); 2149 i--; 2150 } 2151 } 2152 } 2153 return res; 2154} 2155 2156// If the current working directory matches any app_key_path of the layers, remove all other override layers. 2157// Otherwise if no matching app_key was found, remove all but the global override layer, which has no app_key_path. 2158void remove_all_non_valid_override_layers(struct loader_instance *inst, struct loader_layer_list *instance_layers) { 2159 if (instance_layers == NULL) { 2160 return; 2161 } 2162 2163 char cur_path[1024]; 2164 char *ret = loader_platform_executable_path(cur_path, 1024); 2165 if (NULL == ret) { 2166 return; 2167 } 2168 // Find out if there is an override layer with same the app_key_path as the path to the current executable. 2169 // If more than one is found, remove it and use the first layer 2170 // Remove any layers which aren't global and do not have the same app_key_path as the path to the current executable. 2171 bool found_active_override_layer = false; 2172 int global_layer_index = -1; 2173 for (uint32_t i = 0; i < instance_layers->count; i++) { 2174 struct loader_layer_properties *props = &instance_layers->list[i]; 2175 if (strcmp(props->info.layerName, VK_OVERRIDE_LAYER_NAME) == 0) { 2176 if (props->app_key_paths.count > 0) { // not the global layer 2177 for (uint32_t j = 0; j < props->app_key_paths.count; j++) { 2178 if (strcmp(props->app_key_paths.list[j], cur_path) == 0) { 2179 if (!found_active_override_layer) { 2180 found_active_override_layer = true; 2181 } else { 2182 loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0, 2183 "remove_all_non_valid_override_layers: Multiple override layers where the same path in " 2184 "app_keys " 2185 "was found. Using the first layer found"); 2186 2187 // Remove duplicate active override layers that have the same app_key_path 2188 loader_remove_layer_in_list(inst, instance_layers, i); 2189 i--; 2190 } 2191 } 2192 } 2193 if (!found_active_override_layer) { 2194 loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0, 2195 "--Override layer found but not used because app \'%s\' is not in \'app_keys\' list!", cur_path); 2196 2197 // Remove non-global override layers that don't have an app_key that matches cur_path 2198 loader_remove_layer_in_list(inst, instance_layers, i); 2199 i--; 2200 } 2201 } else { 2202 if (global_layer_index == -1) { 2203 global_layer_index = i; 2204 } else { 2205 loader_log( 2206 inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0, 2207 "remove_all_non_valid_override_layers: Multiple global override layers found. Using the first global " 2208 "layer found"); 2209 loader_remove_layer_in_list(inst, instance_layers, i); 2210 i--; 2211 } 2212 } 2213 } 2214 } 2215 // Remove global layer if layer with same the app_key_path as the path to the current executable is found 2216 if (found_active_override_layer && global_layer_index >= 0) { 2217 loader_remove_layer_in_list(inst, instance_layers, global_layer_index); 2218 } 2219 // Should be at most 1 override layer in the list now. 2220 if (found_active_override_layer) { 2221 loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0, "Using the override layer for app key %s", cur_path); 2222 } else if (global_layer_index >= 0) { 2223 loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0, "Using the global override layer"); 2224 } 2225} 2226 2227/* The following are required in the "layer" object: 2228 * "name" 2229 * "type" 2230 * (for non-meta layers) "library_path" 2231 * (for meta layers) "component_layers" 2232 * "api_version" 2233 * "implementation_version" 2234 * "description" 2235 * (for implicit layers) "disable_environment" 2236 */ 2237 2238VkResult loader_read_layer_json(const struct loader_instance *inst, struct loader_layer_list *layer_instance_list, 2239 cJSON *layer_node, loader_api_version version, bool is_implicit, char *filename) { 2240 assert(layer_instance_list); 2241 char *type = NULL; 2242 char *api_version = NULL; 2243 char *implementation_version = NULL; 2244 VkResult result = VK_SUCCESS; 2245 struct loader_layer_properties props = {0}; 2246 2247 // Parse name 2248 2249 result = loader_parse_json_string_to_existing_str(inst, layer_node, "name", VK_MAX_EXTENSION_NAME_SIZE, props.info.layerName); 2250 if (VK_ERROR_OUT_OF_HOST_MEMORY == result) goto out; 2251 if (VK_ERROR_INITIALIZATION_FAILED == result) { 2252 loader_log(inst, VULKAN_LOADER_WARN_BIT, 0, 2253 "Layer located at %s didn't find required layer value \"name\" in manifest JSON file, skipping this layer", 2254 filename); 2255 goto out; 2256 } 2257 2258 // Check if this layer's name matches the override layer name, set is_override to true if so. 2259 if (!strcmp(props.info.layerName, VK_OVERRIDE_LAYER_NAME)) { 2260 props.is_override = true; 2261 } 2262 2263 if (0 != strncmp(props.info.layerName, "VK_LAYER_", 9)) { 2264 loader_log(inst, VULKAN_LOADER_WARN_BIT, 0, "Layer name %s does not conform to naming standard (Policy #LLP_LAYER_3)", 2265 props.info.layerName); 2266 } 2267 2268 // Parse type 2269 2270 result = loader_parse_json_string(layer_node, "type", &type); 2271 if (VK_ERROR_OUT_OF_HOST_MEMORY == result) goto out; 2272 if (VK_ERROR_INITIALIZATION_FAILED == result) { 2273 loader_log(inst, VULKAN_LOADER_WARN_BIT, 0, 2274 "Layer located at %s didn't find required layer value \"type\" in manifest JSON file, skipping this layer", 2275 filename); 2276 goto out; 2277 } 2278 2279 // Add list entry 2280 if (!strcmp(type, "DEVICE")) { 2281 loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0, "Device layers are deprecated. Skipping this layer"); 2282 result = VK_ERROR_INITIALIZATION_FAILED; 2283 goto out; 2284 } 2285 2286 // Allow either GLOBAL or INSTANCE type interchangeably to handle layers that must work with older loaders 2287 if (!strcmp(type, "INSTANCE") || !strcmp(type, "GLOBAL")) { 2288 props.type_flags = VK_LAYER_TYPE_FLAG_INSTANCE_LAYER; 2289 if (!is_implicit) { 2290 props.type_flags |= VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER; 2291 } 2292 } else { 2293 result = VK_ERROR_INITIALIZATION_FAILED; 2294 goto out; 2295 } 2296 2297 // Parse api_version 2298 2299 result = loader_parse_json_string(layer_node, "api_version", &api_version); 2300 if (VK_ERROR_OUT_OF_HOST_MEMORY == result) goto out; 2301 if (VK_ERROR_INITIALIZATION_FAILED == result) { 2302 loader_log( 2303 inst, VULKAN_LOADER_WARN_BIT, 0, 2304 "Layer located at %s didn't find required layer value \"api_version\" in manifest JSON file, skipping this layer", 2305 filename); 2306 goto out; 2307 } 2308 2309 props.info.specVersion = loader_parse_version_string(api_version); 2310 2311 // Make sure the layer's manifest doesn't contain a non zero variant value 2312 if (VK_API_VERSION_VARIANT(props.info.specVersion) != 0) { 2313 loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0, 2314 "Layer \"%s\" has an \'api_version\' field which contains a non-zero variant value of %d. " 2315 " Skipping Layer.", 2316 props.info.layerName, VK_API_VERSION_VARIANT(props.info.specVersion)); 2317 result = VK_ERROR_INITIALIZATION_FAILED; 2318 goto out; 2319 } 2320 2321 // Parse implementation_version 2322 2323 result = loader_parse_json_string(layer_node, "implementation_version", &implementation_version); 2324 if (VK_ERROR_OUT_OF_HOST_MEMORY == result) goto out; 2325 if (VK_ERROR_INITIALIZATION_FAILED == result) { 2326 loader_log(inst, VULKAN_LOADER_WARN_BIT, 0, 2327 "Layer located at %s didn't find required layer value \"implementation_version\" in manifest JSON file, " 2328 "skipping this layer", 2329 filename); 2330 goto out; 2331 } 2332 props.info.implementationVersion = atoi(implementation_version); 2333 2334 // Parse description 2335 2336 result = loader_parse_json_string_to_existing_str(inst, layer_node, "description", VK_MAX_EXTENSION_NAME_SIZE, 2337 props.info.description); 2338 if (VK_ERROR_OUT_OF_HOST_MEMORY == result) goto out; 2339 if (VK_ERROR_INITIALIZATION_FAILED == result) { 2340 loader_log( 2341 inst, VULKAN_LOADER_WARN_BIT, 0, 2342 "Layer located at %s didn't find required layer value \"description\" in manifest JSON file, skipping this layer", 2343 filename); 2344 goto out; 2345 } 2346 2347 // Parse library_path 2348 2349 // Library path no longer required unless component_layers is also not defined 2350 cJSON *library_path = loader_cJSON_GetObjectItem(layer_node, "library_path"); 2351 2352 if (NULL != library_path) { 2353 if (NULL != loader_cJSON_GetObjectItem(layer_node, "component_layers")) { 2354 loader_log(inst, VULKAN_LOADER_WARN_BIT, 0, 2355 "Indicating meta-layer-specific component_layers, but also defining layer library path. Both are not " 2356 "compatible, so skipping this layer"); 2357 result = VK_ERROR_INITIALIZATION_FAILED; 2358 goto out; 2359 } 2360 2361 result = loader_copy_to_new_str(inst, filename, &props.manifest_file_name); 2362 if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out; 2363 2364 char *library_path_str = loader_cJSON_Print(library_path); 2365 if (NULL == library_path_str) { 2366 loader_log(inst, VULKAN_LOADER_WARN_BIT, 0, 2367 "Skipping layer due to problem accessing the library_path value in manifest JSON file %s", filename); 2368 result = VK_ERROR_OUT_OF_HOST_MEMORY; 2369 goto out; 2370 } 2371 2372 // This function takes ownership of library_path_str - so we don't need to clean it up 2373 result = combine_manifest_directory_and_library_path(inst, library_path_str, filename, &props.lib_name); 2374 if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out; 2375 } 2376 2377 // Parse component_layers 2378 2379 if (NULL == library_path) { 2380 if (!loader_check_version_meets_required(LOADER_VERSION_1_1_0, version)) { 2381 loader_log(inst, VULKAN_LOADER_WARN_BIT, 0, 2382 "Indicating meta-layer-specific component_layers, but using older JSON file version."); 2383 } 2384 2385 result = loader_parse_json_array_of_strings(inst, layer_node, "component_layers", &(props.component_layer_names)); 2386 if (VK_ERROR_OUT_OF_HOST_MEMORY == result) { 2387 goto out; 2388 } 2389 if (VK_ERROR_INITIALIZATION_FAILED == result) { 2390 loader_log(inst, VULKAN_LOADER_WARN_BIT, 0, 2391 "Layer missing both library_path and component_layers fields. One or the other MUST be defined. Skipping " 2392 "this layer"); 2393 goto out; 2394 } 2395 // This is now, officially, a meta-layer 2396 props.type_flags |= VK_LAYER_TYPE_FLAG_META_LAYER; 2397 loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0, "Encountered meta-layer \"%s\"", 2398 props.info.layerName); 2399 } 2400 2401 // Parse blacklisted_layers 2402 2403 if (props.is_override) { 2404 result = loader_parse_json_array_of_strings(inst, layer_node, "blacklisted_layers", &(props.blacklist_layer_names)); 2405 if (VK_ERROR_OUT_OF_HOST_MEMORY == result) { 2406 goto out; 2407 } 2408 } 2409 2410 // Parse override_paths 2411 2412 result = loader_parse_json_array_of_strings(inst, layer_node, "override_paths", &(props.override_paths)); 2413 if (VK_ERROR_OUT_OF_HOST_MEMORY == result) { 2414 goto out; 2415 } 2416 if (NULL != props.override_paths.list && !loader_check_version_meets_required(loader_combine_version(1, 1, 0), version)) { 2417 loader_log(inst, VULKAN_LOADER_WARN_BIT, 0, 2418 "Indicating meta-layer-specific override paths, but using older JSON file version."); 2419 } 2420 2421 // Parse disable_environment 2422 2423 if (is_implicit) { 2424 cJSON *disable_environment = loader_cJSON_GetObjectItem(layer_node, "disable_environment"); 2425 if (disable_environment == NULL) { 2426 loader_log(inst, VULKAN_LOADER_WARN_BIT, 0, 2427 "Didn't find required layer object disable_environment in manifest JSON file, skipping this layer"); 2428 result = VK_ERROR_INITIALIZATION_FAILED; 2429 goto out; 2430 } 2431 2432 if (!disable_environment->child || disable_environment->child->type != cJSON_String) { 2433 loader_log(inst, VULKAN_LOADER_WARN_BIT, 0, 2434 "Didn't find required layer child value disable_environment in manifest JSON file, skipping this layer " 2435 "(Policy #LLP_LAYER_9)"); 2436 result = VK_ERROR_INITIALIZATION_FAILED; 2437 goto out; 2438 } 2439 result = loader_copy_to_new_str(inst, disable_environment->child->string, &(props.disable_env_var.name)); 2440 if (VK_SUCCESS != result) goto out; 2441 result = loader_copy_to_new_str(inst, disable_environment->child->valuestring, &(props.disable_env_var.value)); 2442 if (VK_SUCCESS != result) goto out; 2443 } 2444 2445 // Now get all optional items and objects and put in list: 2446 // functions 2447 // instance_extensions 2448 // device_extensions 2449 // enable_environment (implicit layers only) 2450 // library_arch 2451 2452 // Layer interface functions 2453 // vkGetInstanceProcAddr 2454 // vkGetDeviceProcAddr 2455 // vkNegotiateLoaderLayerInterfaceVersion (starting with JSON file 1.1.0) 2456 cJSON *functions = loader_cJSON_GetObjectItem(layer_node, "functions"); 2457 if (functions != NULL) { 2458 if (loader_check_version_meets_required(loader_combine_version(1, 1, 0), version)) { 2459 result = loader_parse_json_string(functions, "vkNegotiateLoaderLayerInterfaceVersion", 2460 &props.functions.str_negotiate_interface); 2461 if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out; 2462 } 2463 result = loader_parse_json_string(functions, "vkGetInstanceProcAddr", &props.functions.str_gipa); 2464 if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out; 2465 2466 if (props.functions.str_gipa && loader_check_version_meets_required(loader_combine_version(1, 1, 0), version)) { 2467 loader_log(inst, VULKAN_LOADER_INFO_BIT, 0, 2468 "Layer \"%s\" using deprecated \'vkGetInstanceProcAddr\' tag which was deprecated starting with JSON " 2469 "file version 1.1.0. The new vkNegotiateLoaderLayerInterfaceVersion function is preferred, though for " 2470 "compatibility reasons it may be desirable to continue using the deprecated tag.", 2471 props.info.layerName); 2472 } 2473 2474 result = loader_parse_json_string(functions, "vkGetDeviceProcAddr", &props.functions.str_gdpa); 2475 if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out; 2476 2477 if (props.functions.str_gdpa && loader_check_version_meets_required(loader_combine_version(1, 1, 0), version)) { 2478 loader_log(inst, VULKAN_LOADER_INFO_BIT, 0, 2479 "Layer \"%s\" using deprecated \'vkGetDeviceProcAddr\' tag which was deprecated starting with JSON " 2480 "file version 1.1.0. The new vkNegotiateLoaderLayerInterfaceVersion function is preferred, though for " 2481 "compatibility reasons it may be desirable to continue using the deprecated tag.", 2482 props.info.layerName); 2483 } 2484 } 2485 2486 // instance_extensions 2487 // array of { 2488 // name 2489 // spec_version 2490 // } 2491 2492 cJSON *instance_extensions = loader_cJSON_GetObjectItem(layer_node, "instance_extensions"); 2493 if (instance_extensions != NULL) { 2494 int count = loader_cJSON_GetArraySize(instance_extensions); 2495 for (int i = 0; i < count; i++) { 2496 VkExtensionProperties ext_prop = {0}; 2497 cJSON *ext_item = loader_cJSON_GetArrayItem(instance_extensions, i); 2498 result = loader_parse_json_string_to_existing_str(inst, ext_item, "name", VK_MAX_EXTENSION_NAME_SIZE, 2499 ext_prop.extensionName); 2500 if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out; 2501 if (result == VK_ERROR_INITIALIZATION_FAILED) continue; 2502 char *spec_version = NULL; 2503 result = loader_parse_json_string(ext_item, "spec_version", &spec_version); 2504 if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out; 2505 if (NULL != spec_version) { 2506 ext_prop.specVersion = atoi(spec_version); 2507 } 2508 loader_instance_heap_free(inst, spec_version); 2509 bool ext_unsupported = wsi_unsupported_instance_extension(&ext_prop); 2510 if (!ext_unsupported) { 2511 loader_add_to_ext_list(inst, &props.instance_extension_list, 1, &ext_prop); 2512 } 2513 } 2514 } 2515 2516 // device_extensions 2517 // array of { 2518 // name 2519 // spec_version 2520 // entrypoints 2521 // } 2522 cJSON *device_extensions = loader_cJSON_GetObjectItem(layer_node, "device_extensions"); 2523 if (device_extensions != NULL) { 2524 int count = loader_cJSON_GetArraySize(device_extensions); 2525 for (int i = 0; i < count; i++) { 2526 VkExtensionProperties ext_prop = {0}; 2527 2528 cJSON *ext_item = loader_cJSON_GetArrayItem(device_extensions, i); 2529 2530 result = loader_parse_json_string_to_existing_str(inst, ext_item, "name", VK_MAX_EXTENSION_NAME_SIZE, 2531 ext_prop.extensionName); 2532 if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out; 2533 2534 char *spec_version = NULL; 2535 result = loader_parse_json_string(ext_item, "spec_version", &spec_version); 2536 if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out; 2537 if (NULL != spec_version) { 2538 ext_prop.specVersion = atoi(spec_version); 2539 } 2540 loader_instance_heap_free(inst, spec_version); 2541 2542 cJSON *entrypoints = loader_cJSON_GetObjectItem(ext_item, "entrypoints"); 2543 if (entrypoints == NULL) { 2544 result = loader_add_to_dev_ext_list(inst, &props.device_extension_list, &ext_prop, NULL); 2545 if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out; 2546 continue; 2547 } 2548 2549 struct loader_string_list entrys = {0}; 2550 result = loader_parse_json_array_of_strings(inst, ext_item, "entrypoints", &entrys); 2551 if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out; 2552 result = loader_add_to_dev_ext_list(inst, &props.device_extension_list, &ext_prop, &entrys); 2553 if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out; 2554 } 2555 } 2556 if (is_implicit) { 2557 cJSON *enable_environment = loader_cJSON_GetObjectItem(layer_node, "enable_environment"); 2558 2559 // enable_environment is optional 2560 if (enable_environment && enable_environment->child && enable_environment->child->type == cJSON_String) { 2561 result = loader_copy_to_new_str(inst, enable_environment->child->string, &(props.enable_env_var.name)); 2562 if (VK_SUCCESS != result) goto out; 2563 result = loader_copy_to_new_str(inst, enable_environment->child->valuestring, &(props.enable_env_var.value)); 2564 if (VK_SUCCESS != result) goto out; 2565 } 2566 } 2567 2568 // Read in the pre-instance stuff 2569 cJSON *pre_instance = loader_cJSON_GetObjectItem(layer_node, "pre_instance_functions"); 2570 if (NULL != pre_instance) { 2571 // Supported versions started in 1.1.2, so anything newer 2572 if (!loader_check_version_meets_required(loader_combine_version(1, 1, 2), version)) { 2573 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 2574 "Found pre_instance_functions section in layer from \"%s\". This section is only valid in manifest version " 2575 "1.1.2 or later. The section will be ignored", 2576 filename); 2577 } else if (!is_implicit) { 2578 loader_log(inst, VULKAN_LOADER_WARN_BIT, 0, 2579 "Found pre_instance_functions section in explicit layer from \"%s\". This section is only valid in implicit " 2580 "layers. The section will be ignored", 2581 filename); 2582 } else { 2583 result = loader_parse_json_string(pre_instance, "vkEnumerateInstanceExtensionProperties", 2584 &props.pre_instance_functions.enumerate_instance_extension_properties); 2585 if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out; 2586 2587 result = loader_parse_json_string(pre_instance, "vkEnumerateInstanceLayerProperties", 2588 &props.pre_instance_functions.enumerate_instance_layer_properties); 2589 if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out; 2590 2591 result = loader_parse_json_string(pre_instance, "vkEnumerateInstanceVersion", 2592 &props.pre_instance_functions.enumerate_instance_version); 2593 if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out; 2594 } 2595 } 2596 2597 if (loader_cJSON_GetObjectItem(layer_node, "app_keys")) { 2598 if (!props.is_override) { 2599 loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0, 2600 "Layer %s contains app_keys, but any app_keys can only be provided by the override meta layer. " 2601 "These will be ignored.", 2602 props.info.layerName); 2603 } 2604 2605 result = loader_parse_json_array_of_strings(inst, layer_node, "app_keys", &props.app_key_paths); 2606 if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out; 2607 } 2608 2609 char *library_arch = NULL; 2610 result = loader_parse_json_string(layer_node, "library_arch", &library_arch); 2611 if (result == VK_ERROR_OUT_OF_HOST_MEMORY) goto out; 2612 if (library_arch != NULL) { 2613 if ((strncmp(library_arch, "32", 2) == 0 && sizeof(void *) != 4) || 2614 (strncmp(library_arch, "64", 2) == 0 && sizeof(void *) != 8)) { 2615 loader_log(inst, VULKAN_LOADER_INFO_BIT, 0, 2616 "Layer library architecture doesn't match the current running architecture, skipping this layer"); 2617 loader_instance_heap_free(inst, library_arch); 2618 result = VK_ERROR_INITIALIZATION_FAILED; 2619 goto out; 2620 } 2621 loader_instance_heap_free(inst, library_arch); 2622 } 2623 2624 result = VK_SUCCESS; 2625 2626out: 2627 // Try to append the layer property 2628 if (VK_SUCCESS == result) { 2629 result = loader_append_layer_property(inst, layer_instance_list, &props); 2630 } 2631 // If appending fails - free all the memory allocated in it 2632 if (VK_SUCCESS != result) { 2633 loader_free_layer_properties(inst, &props); 2634 } 2635 loader_instance_heap_free(inst, type); 2636 loader_instance_heap_free(inst, api_version); 2637 loader_instance_heap_free(inst, implementation_version); 2638 return result; 2639} 2640 2641bool is_valid_layer_json_version(const loader_api_version *layer_json) { 2642 // Supported versions are: 1.0.0, 1.0.1, 1.1.0 - 1.1.2, and 1.2.0 - 1.2.1. 2643 if ((layer_json->major == 1 && layer_json->minor == 2 && layer_json->patch < 2) || 2644 (layer_json->major == 1 && layer_json->minor == 1 && layer_json->patch < 3) || 2645 (layer_json->major == 1 && layer_json->minor == 0 && layer_json->patch < 2)) { 2646 return true; 2647 } 2648 return false; 2649} 2650 2651// Given a cJSON struct (json) of the top level JSON object from layer manifest 2652// file, add entry to the layer_list. Fill out the layer_properties in this list 2653// entry from the input cJSON object. 2654// 2655// \returns 2656// void 2657// layer_list has a new entry and initialized accordingly. 2658// If the json input object does not have all the required fields no entry 2659// is added to the list. 2660VkResult loader_add_layer_properties(const struct loader_instance *inst, struct loader_layer_list *layer_instance_list, cJSON *json, 2661 bool is_implicit, char *filename) { 2662 // The following Fields in layer manifest file that are required: 2663 // - "file_format_version" 2664 // - If more than one "layer" object are used, then the "layers" array is 2665 // required 2666 VkResult result = VK_ERROR_INITIALIZATION_FAILED; 2667 cJSON *item, *layers_node, *layer_node; 2668 loader_api_version json_version = {0, 0, 0}; 2669 char *file_vers = NULL; 2670 // Make sure sure the top level json value is an object 2671 if (!json || json->type != 6) { 2672 goto out; 2673 } 2674 item = loader_cJSON_GetObjectItem(json, "file_format_version"); 2675 if (item == NULL) { 2676 goto out; 2677 } 2678 file_vers = loader_cJSON_PrintUnformatted(item); 2679 if (NULL == file_vers) { 2680 result = VK_ERROR_OUT_OF_HOST_MEMORY; 2681 goto out; 2682 } 2683 loader_log(inst, VULKAN_LOADER_INFO_BIT, 0, "Found manifest file %s (file version %s)", filename, file_vers); 2684 // Get the major/minor/and patch as integers for easier comparison 2685 json_version = loader_make_full_version(loader_parse_version_string(file_vers)); 2686 2687 if (!is_valid_layer_json_version(&json_version)) { 2688 loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0, 2689 "loader_add_layer_properties: %s has unknown layer manifest file version %d.%d.%d. May cause errors.", filename, 2690 json_version.major, json_version.minor, json_version.patch); 2691 } 2692 2693 // If "layers" is present, read in the array of layer objects 2694 layers_node = loader_cJSON_GetObjectItem(json, "layers"); 2695 if (layers_node != NULL) { 2696 int numItems = loader_cJSON_GetArraySize(layers_node); 2697 // Supported versions started in 1.0.1, so anything newer 2698 if (!loader_check_version_meets_required(loader_combine_version(1, 0, 1), json_version)) { 2699 loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0, 2700 "loader_add_layer_properties: \'layers\' tag not supported until file version 1.0.1, but %s is reporting " 2701 "version %s", 2702 filename, file_vers); 2703 } 2704 for (int curLayer = 0; curLayer < numItems; curLayer++) { 2705 layer_node = loader_cJSON_GetArrayItem(layers_node, curLayer); 2706 if (layer_node == NULL) { 2707 loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0, 2708 "loader_add_layer_properties: Can not find 'layers' array element %d object in manifest JSON file %s. " 2709 "Skipping this file", 2710 curLayer, filename); 2711 goto out; 2712 } 2713 result = loader_read_layer_json(inst, layer_instance_list, layer_node, json_version, is_implicit, filename); 2714 } 2715 } else { 2716 // Otherwise, try to read in individual layers 2717 layer_node = loader_cJSON_GetObjectItem(json, "layer"); 2718 if (layer_node == NULL) { 2719 loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0, 2720 "loader_add_layer_properties: Can not find 'layer' object in manifest JSON file %s. Skipping this file.", 2721 filename); 2722 goto out; 2723 } 2724 // Loop through all "layer" objects in the file to get a count of them 2725 // first. 2726 uint16_t layer_count = 0; 2727 cJSON *tempNode = layer_node; 2728 do { 2729 tempNode = tempNode->next; 2730 layer_count++; 2731 } while (tempNode != NULL); 2732 2733 // Throw a warning if we encounter multiple "layer" objects in file 2734 // versions newer than 1.0.0. Having multiple objects with the same 2735 // name at the same level is actually a JSON standard violation. 2736 if (layer_count > 1 && loader_check_version_meets_required(loader_combine_version(1, 0, 1), json_version)) { 2737 loader_log(inst, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_LAYER_BIT, 0, 2738 "loader_add_layer_properties: Multiple 'layer' nodes are deprecated starting in file version \"1.0.1\". " 2739 "Please use 'layers' : [] array instead in %s.", 2740 filename); 2741 } else { 2742 do { 2743 result = loader_read_layer_json(inst, layer_instance_list, layer_node, json_version, is_implicit, filename); 2744 layer_node = layer_node->next; 2745 } while (layer_node != NULL); 2746 } 2747 } 2748 2749out: 2750 loader_instance_heap_free(inst, file_vers); 2751 2752 return result; 2753} 2754 2755size_t determine_data_file_path_size(const char *cur_path, size_t relative_path_size) { 2756 size_t path_size = 0; 2757 2758 if (NULL != cur_path) { 2759 // For each folder in cur_path, (detected by finding additional 2760 // path separators in the string) we need to add the relative path on 2761 // the end. Plus, leave an additional two slots on the end to add an 2762 // additional directory slash and path separator if needed 2763 path_size += strlen(cur_path) + relative_path_size + 2; 2764 for (const char *x = cur_path; *x; ++x) { 2765 if (*x == PATH_SEPARATOR) { 2766 path_size += relative_path_size + 2; 2767 } 2768 } 2769 } 2770 2771 return path_size; 2772} 2773 2774void copy_data_file_info(const char *cur_path, const char *relative_path, size_t relative_path_size, char **output_path) { 2775 if (NULL != cur_path) { 2776 uint32_t start = 0; 2777 uint32_t stop = 0; 2778 char *cur_write = *output_path; 2779 2780 while (cur_path[start] != '\0') { 2781 while (cur_path[start] == PATH_SEPARATOR) { 2782 start++; 2783 } 2784 stop = start; 2785 while (cur_path[stop] != PATH_SEPARATOR && cur_path[stop] != '\0') { 2786 stop++; 2787 } 2788 const size_t s = stop - start; 2789 if (s) { 2790 memcpy(cur_write, &cur_path[start], s); 2791 cur_write += s; 2792 2793 // If this is a specific JSON file, just add it and don't add any 2794 // relative path or directory symbol to it. 2795 if (!is_json(cur_write - 5, s)) { 2796 // Add the relative directory if present. 2797 if (relative_path_size > 0) { 2798 // If last symbol written was not a directory symbol, add it. 2799 if (*(cur_write - 1) != DIRECTORY_SYMBOL) { 2800 *cur_write++ = DIRECTORY_SYMBOL; 2801 } 2802 memcpy(cur_write, relative_path, relative_path_size); 2803 cur_write += relative_path_size; 2804 } 2805 } 2806 2807 *cur_write++ = PATH_SEPARATOR; 2808 start = stop; 2809 } 2810 } 2811 *output_path = cur_write; 2812 } 2813} 2814 2815// If the file found is a manifest file name, add it to the out_files manifest list. 2816VkResult add_if_manifest_file(const struct loader_instance *inst, const char *file_name, struct loader_string_list *out_files) { 2817 VkResult vk_result = VK_SUCCESS; 2818 2819 assert(NULL != file_name && "add_if_manifest_file: Received NULL pointer for file_name"); 2820 assert(NULL != out_files && "add_if_manifest_file: Received NULL pointer for out_files"); 2821 2822 // Look for files ending with ".json" suffix 2823 size_t name_len = strlen(file_name); 2824 const char *name_suffix = file_name + name_len - 5; 2825 if (!is_json(name_suffix, name_len)) { 2826 // Use incomplete to indicate invalid name, but to keep going. 2827 vk_result = VK_INCOMPLETE; 2828 goto out; 2829 } 2830 2831 vk_result = copy_str_to_string_list(inst, out_files, file_name, name_len); 2832 2833out: 2834 2835 return vk_result; 2836} 2837 2838// Add any files found in the search_path. If any path in the search path points to a specific JSON, attempt to 2839// only open that one JSON. Otherwise, if the path is a folder, search the folder for JSON files. 2840VkResult add_data_files(const struct loader_instance *inst, char *search_path, struct loader_string_list *out_files, 2841 bool use_first_found_manifest) { 2842 VkResult vk_result = VK_SUCCESS; 2843 DIR *dir_stream = NULL; 2844 struct dirent *dir_entry; 2845 char *cur_file; 2846 char *next_file; 2847 char *name; 2848 char full_path[2048]; 2849#if !defined(_WIN32) 2850 char temp_path[2048]; 2851#endif 2852 2853 // Now, parse the paths 2854 next_file = search_path; 2855 while (NULL != next_file && *next_file != '\0') { 2856 name = NULL; 2857 cur_file = next_file; 2858 next_file = loader_get_next_path(cur_file); 2859 2860 // Is this a JSON file, then try to open it. 2861 size_t len = strlen(cur_file); 2862 if (is_json(cur_file + len - 5, len)) { 2863#if defined(_WIN32) 2864 name = cur_file; 2865#elif COMMON_UNIX_PLATFORMS 2866 // Only Linux has relative paths, make a copy of location so it isn't modified 2867 size_t str_len; 2868 if (NULL != next_file) { 2869 str_len = next_file - cur_file + 1; 2870 } else { 2871 str_len = strlen(cur_file) + 1; 2872 } 2873 if (str_len > sizeof(temp_path)) { 2874 loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "add_data_files: Path to %s too long", cur_file); 2875 continue; 2876 } 2877 strncpy(temp_path, cur_file, str_len); 2878 name = temp_path; 2879#else 2880#warning add_data_files must define relative path copy for this platform 2881#endif 2882 loader_get_fullpath(cur_file, name, sizeof(full_path), full_path); 2883 name = full_path; 2884 2885 VkResult local_res; 2886 local_res = add_if_manifest_file(inst, name, out_files); 2887 2888 // Incomplete means this was not a valid data file. 2889 if (local_res == VK_INCOMPLETE) { 2890 continue; 2891 } else if (local_res != VK_SUCCESS) { 2892 vk_result = local_res; 2893 break; 2894 } 2895 } else { // Otherwise, treat it as a directory 2896 dir_stream = loader_opendir(inst, cur_file); 2897 if (NULL == dir_stream) { 2898 continue; 2899 } 2900 while (1) { 2901 dir_entry = readdir(dir_stream); 2902 if (NULL == dir_entry) { 2903 break; 2904 } 2905 2906 name = &(dir_entry->d_name[0]); 2907 loader_get_fullpath(name, cur_file, sizeof(full_path), full_path); 2908 name = full_path; 2909 2910 VkResult local_res; 2911 local_res = add_if_manifest_file(inst, name, out_files); 2912 2913 // Incomplete means this was not a valid data file. 2914 if (local_res == VK_INCOMPLETE) { 2915 continue; 2916 } else if (local_res != VK_SUCCESS) { 2917 vk_result = local_res; 2918 break; 2919 } 2920 } 2921 loader_closedir(inst, dir_stream); 2922 if (vk_result != VK_SUCCESS) { 2923 goto out; 2924 } 2925 } 2926 if (use_first_found_manifest && out_files->count > 0) { 2927 break; 2928 } 2929 } 2930 2931out: 2932 2933 return vk_result; 2934} 2935 2936// Look for data files in the provided paths, but first check the environment override to determine if we should use that 2937// instead. 2938VkResult read_data_files_in_search_paths(const struct loader_instance *inst, enum loader_data_files_type manifest_type, 2939 const char *path_override, bool *override_active, struct loader_string_list *out_files) { 2940 VkResult vk_result = VK_SUCCESS; 2941 char *override_env = NULL; 2942 const char *override_path = NULL; 2943 char *additional_env = NULL; 2944 size_t search_path_size = 0; 2945 char *search_path = NULL; 2946 char *cur_path_ptr = NULL; 2947 bool use_first_found_manifest = false; 2948#if COMMON_UNIX_PLATFORMS 2949 char *relative_location = NULL; // Only used on unix platforms 2950 size_t rel_size = 0; // unused in windows, dont declare so no compiler warnings are generated 2951#endif 2952 2953#if defined(_WIN32) 2954 char *package_path = NULL; 2955#elif COMMON_UNIX_PLATFORMS 2956 // Determine how much space is needed to generate the full search path 2957 // for the current manifest files. 2958 char *xdg_config_home = loader_secure_getenv("XDG_CONFIG_HOME", inst); 2959 char *xdg_config_dirs = loader_secure_getenv("XDG_CONFIG_DIRS", inst); 2960 2961#if !defined(__Fuchsia__) && !defined(__QNX__) && !defined(__OHOS__) 2962 if (NULL == xdg_config_dirs || '\0' == xdg_config_dirs[0]) { 2963 xdg_config_dirs = FALLBACK_CONFIG_DIRS; 2964 } 2965#endif 2966 2967 char *xdg_data_home = loader_secure_getenv("XDG_DATA_HOME", inst); 2968 char *xdg_data_dirs = loader_secure_getenv("XDG_DATA_DIRS", inst); 2969 2970#if !defined(__Fuchsia__) && !defined(__QNX__) && !defined(__OHOS__) 2971 if (NULL == xdg_data_dirs || '\0' == xdg_data_dirs[0]) { 2972 xdg_data_dirs = FALLBACK_DATA_DIRS; 2973 } 2974#endif 2975 2976 char *home = NULL; 2977 char *default_data_home = NULL; 2978 char *default_config_home = NULL; 2979 char *home_data_dir = NULL; 2980 char *home_config_dir = NULL; 2981 2982 // Only use HOME if XDG_DATA_HOME is not present on the system 2983 home = loader_secure_getenv("HOME", inst); 2984 if (home != NULL) { 2985 if (NULL == xdg_config_home || '\0' == xdg_config_home[0]) { 2986 const char config_suffix[] = "/.config"; 2987 size_t default_config_home_len = strlen(home) + sizeof(config_suffix) + 1; 2988 default_config_home = loader_instance_heap_calloc(inst, default_config_home_len, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 2989 if (default_config_home == NULL) { 2990 vk_result = VK_ERROR_OUT_OF_HOST_MEMORY; 2991 goto out; 2992 } 2993 strncpy(default_config_home, home, default_config_home_len); 2994 strncat(default_config_home, config_suffix, default_config_home_len); 2995 } 2996 if (NULL == xdg_data_home || '\0' == xdg_data_home[0]) { 2997 const char data_suffix[] = "/.local/share"; 2998 size_t default_data_home_len = strlen(home) + sizeof(data_suffix) + 1; 2999 default_data_home = loader_instance_heap_calloc(inst, default_data_home_len, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 3000 if (default_data_home == NULL) { 3001 vk_result = VK_ERROR_OUT_OF_HOST_MEMORY; 3002 goto out; 3003 } 3004 strncpy(default_data_home, home, default_data_home_len); 3005 strncat(default_data_home, data_suffix, default_data_home_len); 3006 } 3007 } 3008 3009 if (NULL != default_config_home) { 3010 home_config_dir = default_config_home; 3011 } else { 3012 home_config_dir = xdg_config_home; 3013 } 3014 if (NULL != default_data_home) { 3015 home_data_dir = default_data_home; 3016 } else { 3017 home_data_dir = xdg_data_home; 3018 } 3019 3020#if defined(__OHOS__) 3021 char *debug_layer_name = loader_secure_getenv("debug.graphic.debug_layer", inst); // squid squidsubcapture 3022 char *debug_hap_name = loader_secure_getenv("debug.graphic.debug_hap", inst); 3023 char *debug_layer_json_path = NULL; 3024 3025 bool currentProcessEnableDebugLayer = false; 3026 if (NULL != debug_layer_name && '\0' != debug_layer_name[0] && InitBundleInfo(debug_hap_name)) { 3027 currentProcessEnableDebugLayer = true; 3028 debug_layer_json_path = loader_secure_getenv("debug.graphic.vklayer_json_path",inst); 3029 if (NULL == debug_layer_json_path || '\0' == debug_layer_json_path[0]){ 3030 const char default_json_path[] = "/data/storage/el2/base/haps/entry/files/"; 3031 const char json_suffix[] = ".json"; 3032 size_t debug_layer_json_path_len = strlen(default_json_path) + sizeof(debug_layer_name) + sizeof(json_suffix) +1; 3033 debug_layer_json_path = loader_instance_heap_calloc(inst,debug_layer_json_path_len,VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 3034 if(debug_layer_json_path == NULL){ 3035 vk_result = VK_ERROR_OUT_OF_HOST_MEMORY; 3036 goto out; 3037 } 3038 strncpy(debug_layer_json_path,default_json_path,debug_layer_json_path_len); 3039 strncat(debug_layer_json_path,debug_layer_name,debug_layer_json_path_len); 3040 strncat(debug_layer_json_path,json_suffix,debug_layer_json_path_len); 3041 } 3042 loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "OHOS:: debug_layer_json_path: %s", debug_layer_json_path); 3043 } 3044#endif 3045 3046#else 3047#warning read_data_files_in_search_paths unsupported platform 3048#endif 3049 3050 switch (manifest_type) { 3051 case LOADER_DATA_FILE_MANIFEST_DRIVER: 3052 override_env = loader_secure_getenv(VK_DRIVER_FILES_ENV_VAR, inst); 3053 if (NULL == override_env) { 3054 // Not there, so fall back to the old name 3055 override_env = loader_secure_getenv(VK_ICD_FILENAMES_ENV_VAR, inst); 3056 } 3057 additional_env = loader_secure_getenv(VK_ADDITIONAL_DRIVER_FILES_ENV_VAR, inst); 3058#if COMMON_UNIX_PLATFORMS 3059 relative_location = VK_DRIVERS_INFO_RELATIVE_DIR; 3060#endif 3061#if defined(_WIN32) 3062 package_path = windows_get_app_package_manifest_path(inst); 3063#endif 3064 break; 3065 case LOADER_DATA_FILE_MANIFEST_IMPLICIT_LAYER: 3066#if COMMON_UNIX_PLATFORMS 3067 relative_location = VK_ILAYERS_INFO_RELATIVE_DIR; 3068#endif 3069 break; 3070 case LOADER_DATA_FILE_MANIFEST_EXPLICIT_LAYER: 3071 override_env = loader_secure_getenv(VK_LAYER_PATH_ENV_VAR, inst); 3072 additional_env = loader_secure_getenv(VK_ADDITIONAL_LAYER_PATH_ENV_VAR, inst); 3073#if COMMON_UNIX_PLATFORMS 3074 relative_location = VK_ELAYERS_INFO_RELATIVE_DIR; 3075#endif 3076 break; 3077 default: 3078 assert(false && "Shouldn't get here!"); 3079 break; 3080 } 3081 3082 // Log a message when VK_LAYER_PATH is set but the override layer paths take priority 3083 if (manifest_type == LOADER_DATA_FILE_MANIFEST_EXPLICIT_LAYER && NULL != override_env && NULL != path_override) { 3084 loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0, 3085 "Ignoring VK_LAYER_PATH. The Override layer is active and has override paths set, which takes priority. " 3086 "VK_LAYER_PATH is set to %s", 3087 override_env); 3088 } 3089 3090 if (path_override != NULL) { 3091 override_path = path_override; 3092 } else if (override_env != NULL) { 3093 override_path = override_env; 3094 } 3095 3096 // Add two by default for NULL terminator and one path separator on end (just in case) 3097 search_path_size = 2; 3098 3099 // If there's an override, use that (and the local folder if required) and nothing else 3100 if (NULL != override_path) { 3101 // Local folder and null terminator 3102 search_path_size += strlen(override_path) + 2; 3103 } else { 3104 // Add the size of any additional search paths defined in the additive environment variable 3105 if (NULL != additional_env) { 3106 search_path_size += determine_data_file_path_size(additional_env, 0) + 2; 3107#if defined(_WIN32) 3108 } 3109 if (NULL != package_path) { 3110 search_path_size += determine_data_file_path_size(package_path, 0) + 2; 3111 } 3112 if (search_path_size == 2) { 3113 goto out; 3114 } 3115#elif COMMON_UNIX_PLATFORMS 3116 } 3117 3118 // Add the general search folders (with the appropriate relative folder added) 3119 rel_size = strlen(relative_location); 3120 if (rel_size > 0) { 3121#if defined(__APPLE__) 3122 search_path_size += MAXPATHLEN; 3123#endif 3124 // Only add the home folders if defined 3125 if (NULL != home_config_dir) { 3126 search_path_size += determine_data_file_path_size(home_config_dir, rel_size); 3127 } 3128 search_path_size += determine_data_file_path_size(xdg_config_dirs, rel_size); 3129 search_path_size += determine_data_file_path_size(SYSCONFDIR, rel_size); 3130#if defined(EXTRASYSCONFDIR) 3131 search_path_size += determine_data_file_path_size(EXTRASYSCONFDIR, rel_size); 3132#endif 3133 // Only add the home folders if defined 3134 if (NULL != home_data_dir) { 3135 search_path_size += determine_data_file_path_size(home_data_dir, rel_size); 3136 } 3137 search_path_size += determine_data_file_path_size(xdg_data_dirs, rel_size); 3138#if defined (__OHOS__) 3139 if(currentProcessEnableDebugLayer) { 3140 search_path_size += determine_data_file_path_size(debug_layer_json_path, rel_size); 3141 } 3142 search_path_size += determine_data_file_path_size("/system/etc/vulkan/swapchain", rel_size); 3143#endif 3144 } 3145#else 3146#warning read_data_files_in_search_paths unsupported platform 3147#endif 3148 } 3149 3150 // Allocate the required space 3151 search_path = loader_instance_heap_calloc(inst, search_path_size, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 3152 if (NULL == search_path) { 3153 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 3154 "read_data_files_in_search_paths: Failed to allocate space for search path of length %d", 3155 (uint32_t)search_path_size); 3156 vk_result = VK_ERROR_OUT_OF_HOST_MEMORY; 3157 goto out; 3158 } 3159 3160 cur_path_ptr = search_path; 3161 3162 // Add the remaining paths to the list 3163 if (NULL != override_path) { 3164 size_t override_path_len = strlen(override_path); 3165 loader_strncpy(cur_path_ptr, search_path_size, override_path, override_path_len); 3166 cur_path_ptr += override_path_len; 3167 } else { 3168 // Add any additional search paths defined in the additive environment variable 3169 if (NULL != additional_env) { 3170 copy_data_file_info(additional_env, NULL, 0, &cur_path_ptr); 3171 } 3172 3173#if defined(_WIN32) 3174 if (NULL != package_path) { 3175 copy_data_file_info(package_path, NULL, 0, &cur_path_ptr); 3176 } 3177#elif COMMON_UNIX_PLATFORMS 3178 if (rel_size > 0) { 3179#if defined(__APPLE__) 3180 // Add the bundle's Resources dir to the beginning of the search path. 3181 // Looks for manifests in the bundle first, before any system directories. 3182 // This also appears to work unmodified for iOS, it finds the app bundle on the devices 3183 // file system. (RSW) 3184 CFBundleRef main_bundle = CFBundleGetMainBundle(); 3185 if (NULL != main_bundle) { 3186 CFURLRef ref = CFBundleCopyResourcesDirectoryURL(main_bundle); 3187 if (NULL != ref) { 3188 if (CFURLGetFileSystemRepresentation(ref, TRUE, (UInt8 *)cur_path_ptr, search_path_size)) { 3189 cur_path_ptr += strlen(cur_path_ptr); 3190 *cur_path_ptr++ = DIRECTORY_SYMBOL; 3191 memcpy(cur_path_ptr, relative_location, rel_size); 3192 cur_path_ptr += rel_size; 3193 *cur_path_ptr++ = PATH_SEPARATOR; 3194 if (manifest_type == LOADER_DATA_FILE_MANIFEST_DRIVER) { 3195 use_first_found_manifest = true; 3196 } 3197 } 3198 CFRelease(ref); 3199 } 3200 } 3201#endif // __APPLE__ 3202 3203 // Only add the home folders if not NULL 3204 if (NULL != home_config_dir) { 3205 copy_data_file_info(home_config_dir, relative_location, rel_size, &cur_path_ptr); 3206 } 3207 copy_data_file_info(xdg_config_dirs, relative_location, rel_size, &cur_path_ptr); 3208 copy_data_file_info(SYSCONFDIR, relative_location, rel_size, &cur_path_ptr); 3209#if defined(EXTRASYSCONFDIR) 3210 copy_data_file_info(EXTRASYSCONFDIR, relative_location, rel_size, &cur_path_ptr); 3211#endif 3212 3213 // Only add the home folders if not NULL 3214 if (NULL != home_data_dir) { 3215 copy_data_file_info(home_data_dir, relative_location, rel_size, &cur_path_ptr); 3216 } 3217 copy_data_file_info(xdg_data_dirs, relative_location, rel_size, &cur_path_ptr); 3218#if defined (__OHOS__) 3219 if(currentProcessEnableDebugLayer){ 3220 copy_data_file_info(debug_layer_json_path,relative_location,rel_size,&cur_path_ptr); 3221 } 3222 copy_data_file_info("/system/etc/vulkan/swapchain/",relative_location,rel_size,&cur_path_ptr); 3223#endif 3224 } 3225 3226 // Remove the last path separator 3227 --cur_path_ptr; 3228 3229 assert(cur_path_ptr - search_path < (ptrdiff_t)search_path_size); 3230 *cur_path_ptr = '\0'; 3231#else 3232#warning read_data_files_in_search_paths unsupported platform 3233#endif 3234 } 3235 3236 // Remove duplicate paths, or it would result in duplicate extensions, duplicate devices, etc. 3237 // This uses minimal memory, but is O(N^2) on the number of paths. Expect only a few paths. 3238 char path_sep_str[2] = {PATH_SEPARATOR, '\0'}; 3239 size_t search_path_updated_size = strlen(search_path); 3240 for (size_t first = 0; first < search_path_updated_size;) { 3241 // If this is an empty path, erase it 3242 if (search_path[first] == PATH_SEPARATOR) { 3243 memmove(&search_path[first], &search_path[first + 1], search_path_updated_size - first + 1); 3244 search_path_updated_size -= 1; 3245 continue; 3246 } 3247 3248 size_t first_end = first + 1; 3249 first_end += strcspn(&search_path[first_end], path_sep_str); 3250 for (size_t second = first_end + 1; second < search_path_updated_size;) { 3251 size_t second_end = second + 1; 3252 second_end += strcspn(&search_path[second_end], path_sep_str); 3253 if (first_end - first == second_end - second && 3254 !strncmp(&search_path[first], &search_path[second], second_end - second)) { 3255 // Found duplicate. Include PATH_SEPARATOR in second_end, then erase it from search_path. 3256 if (search_path[second_end] == PATH_SEPARATOR) { 3257 second_end++; 3258 } 3259 memmove(&search_path[second], &search_path[second_end], search_path_updated_size - second_end + 1); 3260 search_path_updated_size -= second_end - second; 3261 } else { 3262 second = second_end + 1; 3263 } 3264 } 3265 first = first_end + 1; 3266 } 3267 search_path_size = search_path_updated_size; 3268 3269 // Print out the paths being searched if debugging is enabled 3270 uint32_t log_flags = 0; 3271 if (search_path_size > 0) { 3272 char *tmp_search_path = loader_instance_heap_alloc(inst, search_path_size + 1, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 3273 if (NULL != tmp_search_path) { 3274 loader_strncpy(tmp_search_path, search_path_size + 1, search_path, search_path_size); 3275 tmp_search_path[search_path_size] = '\0'; 3276 if (manifest_type == LOADER_DATA_FILE_MANIFEST_DRIVER) { 3277 log_flags = VULKAN_LOADER_DRIVER_BIT; 3278 loader_log(inst, VULKAN_LOADER_DRIVER_BIT, 0, "Searching for driver manifest files"); 3279 } else { 3280 log_flags = VULKAN_LOADER_LAYER_BIT; 3281 loader_log(inst, VULKAN_LOADER_LAYER_BIT, 0, "Searching for %s layer manifest files", 3282 manifest_type == LOADER_DATA_FILE_MANIFEST_EXPLICIT_LAYER ? "explicit" : "implicit"); 3283 } 3284 loader_log(inst, log_flags, 0, " In following locations:"); 3285 char *cur_file; 3286 char *next_file = tmp_search_path; 3287 while (NULL != next_file && *next_file != '\0') { 3288 cur_file = next_file; 3289 next_file = loader_get_next_path(cur_file); 3290 loader_log(inst, log_flags, 0, " %s", cur_file); 3291 } 3292 loader_instance_heap_free(inst, tmp_search_path); 3293 } 3294 } 3295 3296 // Now, parse the paths and add any manifest files found in them. 3297 vk_result = add_data_files(inst, search_path, out_files, use_first_found_manifest); 3298 3299 if (log_flags != 0 && out_files->count > 0) { 3300 loader_log(inst, log_flags, 0, " Found the following files:"); 3301 for (uint32_t cur_file = 0; cur_file < out_files->count; ++cur_file) { 3302 loader_log(inst, log_flags, 0, " %s", out_files->list[cur_file]); 3303 } 3304 } else { 3305 loader_log(inst, log_flags, 0, " Found no files"); 3306 } 3307 3308 if (NULL != override_path) { 3309 *override_active = true; 3310 } else { 3311 *override_active = false; 3312 } 3313 3314out: 3315 3316 loader_free_getenv(additional_env, inst); 3317 loader_free_getenv(override_env, inst); 3318#if defined(_WIN32) 3319 loader_instance_heap_free(inst, package_path); 3320#elif COMMON_UNIX_PLATFORMS 3321 loader_free_getenv(xdg_config_home, inst); 3322 loader_free_getenv(xdg_config_dirs, inst); 3323 loader_free_getenv(xdg_data_home, inst); 3324 loader_free_getenv(xdg_data_dirs, inst); 3325 loader_free_getenv(xdg_data_home, inst); 3326 loader_free_getenv(home, inst); 3327 loader_instance_heap_free(inst, default_data_home); 3328 loader_instance_heap_free(inst, default_config_home); 3329#elif defined(__OHOS__) 3330 if(currentProcessEnableDebugLayer){ 3331 loader_free_getenv(debug_layer_json_path, inst); 3332 } 3333 loader_free_getenv(debug_layer_name, inst); 3334 loader_free_getenv(debug_hap_name, inst); 3335#else 3336#warning read_data_files_in_search_paths unsupported platform 3337#endif 3338 3339 loader_instance_heap_free(inst, search_path); 3340 3341 return vk_result; 3342} 3343 3344// Find the Vulkan library manifest files. 3345// 3346// This function scans the appropriate locations for a list of JSON manifest files based on the 3347// "manifest_type". The location is interpreted as Registry path on Windows and a directory path(s) 3348// on Linux. 3349// "home_location" is an additional directory in the users home directory to look at. It is 3350// expanded into the dir path $XDG_DATA_HOME/home_location or $HOME/.local/share/home_location 3351// depending on environment variables. This "home_location" is only used on Linux. 3352// 3353// \returns 3354// VKResult 3355// A string list of manifest files to be opened in out_files param. 3356// List has a pointer to string for each manifest filename. 3357// When done using the list in out_files, pointers should be freed. 3358// Location or override string lists can be either files or directories as 3359// follows: 3360// | location | override 3361// -------------------------------- 3362// Win ICD | files | files 3363// Win Layer | files | dirs 3364// Linux ICD | dirs | files 3365// Linux Layer| dirs | dirs 3366 3367VkResult loader_get_data_files(const struct loader_instance *inst, enum loader_data_files_type manifest_type, 3368 const char *path_override, struct loader_string_list *out_files) { 3369 VkResult res = VK_SUCCESS; 3370 bool override_active = false; 3371 3372 // Free and init the out_files information so there's no false data left from uninitialized variables. 3373 free_string_list(inst, out_files); 3374 3375 res = read_data_files_in_search_paths(inst, manifest_type, path_override, &override_active, out_files); 3376 if (VK_SUCCESS != res) { 3377 goto out; 3378 } 3379 3380#if defined(_WIN32) 3381 // Read the registry if the override wasn't active. 3382 if (!override_active) { 3383 bool warn_if_not_present = false; 3384 char *registry_location = NULL; 3385 3386 switch (manifest_type) { 3387 default: 3388 goto out; 3389 case LOADER_DATA_FILE_MANIFEST_DRIVER: 3390 warn_if_not_present = true; 3391 registry_location = VK_DRIVERS_INFO_REGISTRY_LOC; 3392 break; 3393 case LOADER_DATA_FILE_MANIFEST_IMPLICIT_LAYER: 3394 registry_location = VK_ILAYERS_INFO_REGISTRY_LOC; 3395 break; 3396 case LOADER_DATA_FILE_MANIFEST_EXPLICIT_LAYER: 3397 warn_if_not_present = true; 3398 registry_location = VK_ELAYERS_INFO_REGISTRY_LOC; 3399 break; 3400 } 3401 VkResult tmp_res = 3402 windows_read_data_files_in_registry(inst, manifest_type, warn_if_not_present, registry_location, out_files); 3403 // Only return an error if there was an error this time, and no manifest files from before. 3404 if (VK_SUCCESS != tmp_res && out_files->count == 0) { 3405 res = tmp_res; 3406 goto out; 3407 } 3408 } 3409#endif 3410 3411out: 3412 3413 if (VK_SUCCESS != res) { 3414 free_string_list(inst, out_files); 3415 } 3416 3417 return res; 3418} 3419 3420struct ICDManifestInfo { 3421 char *full_library_path; 3422 uint32_t version; 3423}; 3424 3425// Takes a json file, opens, reads, and parses an ICD Manifest out of it. 3426// Should only return VK_SUCCESS, VK_ERROR_INCOMPATIBLE_DRIVER, or VK_ERROR_OUT_OF_HOST_MEMORY 3427VkResult loader_parse_icd_manifest(const struct loader_instance *inst, char *file_str, struct ICDManifestInfo *icd, 3428 bool *skipped_portability_drivers) { 3429 VkResult res = VK_SUCCESS; 3430 cJSON *json = NULL; 3431 char *file_vers_str = NULL; 3432 char *library_arch_str = NULL; 3433 char *version_str = NULL; 3434 3435 if (file_str == NULL) { 3436 goto out; 3437 } 3438 3439 res = loader_get_json(inst, file_str, &json); 3440 if (res == VK_ERROR_OUT_OF_HOST_MEMORY) { 3441 goto out; 3442 } 3443 if (res != VK_SUCCESS || NULL == json) { 3444 res = VK_ERROR_INCOMPATIBLE_DRIVER; 3445 goto out; 3446 } 3447 3448 cJSON *item = loader_cJSON_GetObjectItem(json, "file_format_version"); 3449 if (item == NULL) { 3450 loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0, 3451 "loader_parse_icd_manifest: ICD JSON %s does not have a \'file_format_version\' field. Skipping ICD JSON.", 3452 file_str); 3453 res = VK_ERROR_INCOMPATIBLE_DRIVER; 3454 goto out; 3455 } 3456 3457 file_vers_str = loader_cJSON_Print(item); 3458 if (NULL == file_vers_str) { 3459 // Only reason the print can fail is if there was an allocation issue 3460 loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0, 3461 "loader_parse_icd_manifest: Failed retrieving ICD JSON %s \'file_format_version\' field. Skipping ICD JSON", 3462 file_str); 3463 res = VK_ERROR_OUT_OF_HOST_MEMORY; 3464 goto out; 3465 } 3466 loader_log(inst, VULKAN_LOADER_DRIVER_BIT, 0, "Found ICD manifest file %s, version %s", file_str, file_vers_str); 3467 3468 // Get the version of the driver manifest 3469 loader_api_version json_file_version = loader_make_full_version(loader_parse_version_string(file_vers_str)); 3470 3471 // Loader only knows versions 1.0.0 and 1.0.1, anything above it is unknown 3472 if (loader_check_version_meets_required(loader_combine_version(1, 0, 2), json_file_version)) { 3473 loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_DRIVER_BIT, 0, 3474 "loader_parse_icd_manifest: %s has unknown icd manifest file version %d.%d.%d. May cause errors.", file_str, 3475 json_file_version.major, json_file_version.minor, json_file_version.patch); 3476 } 3477 3478 cJSON *itemICD = loader_cJSON_GetObjectItem(json, "ICD"); 3479 if (itemICD == NULL) { 3480 loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0, 3481 "loader_parse_icd_manifest: Can not find \'ICD\' object in ICD JSON file %s. Skipping ICD JSON", file_str); 3482 res = VK_ERROR_INCOMPATIBLE_DRIVER; 3483 goto out; 3484 } 3485 3486 item = loader_cJSON_GetObjectItem(itemICD, "library_path"); 3487 if (item == NULL) { 3488 loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0, 3489 "loader_parse_icd_manifest: Failed to find \'library_path\' object in ICD JSON file %s. Skipping ICD JSON.", 3490 file_str); 3491 res = VK_ERROR_INCOMPATIBLE_DRIVER; 3492 goto out; 3493 } 3494 char *library_path = loader_cJSON_Print(item); 3495 if (!library_path) { 3496 loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0, 3497 "loader_parse_icd_manifest: Failed retrieving ICD JSON %s \'library_path\' field. Skipping ICD JSON.", file_str); 3498 res = VK_ERROR_OUT_OF_HOST_MEMORY; 3499 goto out; 3500 } 3501 3502 if (strlen(library_path) == 0) { 3503 loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0, 3504 "loader_parse_icd_manifest: ICD JSON %s \'library_path\' field is empty. Skipping ICD JSON.", file_str); 3505 res = VK_ERROR_INCOMPATIBLE_DRIVER; 3506 goto out; 3507 } 3508 3509 // Print out the paths being searched if debugging is enabled 3510 loader_log(inst, VULKAN_LOADER_DEBUG_BIT | VULKAN_LOADER_DRIVER_BIT, 0, "Searching for ICD drivers named %s", library_path); 3511 // This function takes ownership of library_path - so we don't need to clean it up 3512 res = combine_manifest_directory_and_library_path(inst, library_path, file_str, &icd->full_library_path); 3513 if (VK_SUCCESS != res) { 3514 goto out; 3515 } 3516 3517 item = loader_cJSON_GetObjectItem(itemICD, "api_version"); 3518 if (item == NULL) { 3519 loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0, 3520 "loader_parse_icd_manifest: ICD JSON %s does not have an \'api_version\' field. Skipping ICD JSON.", file_str); 3521 res = VK_ERROR_INCOMPATIBLE_DRIVER; 3522 goto out; 3523 } 3524 version_str = loader_cJSON_Print(item); 3525 if (NULL == version_str) { 3526 // Only reason the print can fail is if there was an allocation issue 3527 loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0, 3528 "loader_parse_icd_manifest: Failed retrieving ICD JSON %s \'api_version\' field. Skipping ICD JSON.", file_str); 3529 3530 res = VK_ERROR_OUT_OF_HOST_MEMORY; 3531 goto out; 3532 } 3533 icd->version = loader_parse_version_string(version_str); 3534 3535 if (VK_API_VERSION_VARIANT(icd->version) != 0) { 3536 loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_DRIVER_BIT, 0, 3537 "loader_parse_icd_manifest: Driver's ICD JSON %s \'api_version\' field contains a non-zero variant value of %d. " 3538 " Skipping ICD JSON.", 3539 file_str, VK_API_VERSION_VARIANT(icd->version)); 3540 res = VK_ERROR_INCOMPATIBLE_DRIVER; 3541 goto out; 3542 } 3543 3544 // Skip over ICD's which contain a true "is_portability_driver" value whenever the application doesn't enable 3545 // portability enumeration. 3546 item = loader_cJSON_GetObjectItem(itemICD, "is_portability_driver"); 3547 if (item != NULL && item->type == cJSON_True && inst && !inst->portability_enumeration_enabled) { 3548 if (skipped_portability_drivers) { 3549 *skipped_portability_drivers = true; 3550 } 3551 res = VK_ERROR_INCOMPATIBLE_DRIVER; 3552 goto out; 3553 } 3554 3555 item = loader_cJSON_GetObjectItem(itemICD, "library_arch"); 3556 if (item != NULL) { 3557 library_arch_str = loader_cJSON_Print(item); 3558 if (NULL != library_arch_str) { 3559 // cJSON includes the quotes by default, so we need to look for those here 3560 if ((strncmp(library_arch_str, "32", 4) == 0 && sizeof(void *) != 4) || 3561 (strncmp(library_arch_str, "64", 4) == 0 && sizeof(void *) != 8)) { 3562 loader_log(inst, VULKAN_LOADER_INFO_BIT, 0, 3563 "loader_parse_icd_manifest: Driver library architecture doesn't match the current running " 3564 "architecture, skipping this driver"); 3565 res = VK_ERROR_INCOMPATIBLE_DRIVER; 3566 goto out; 3567 } 3568 } else { 3569 res = VK_ERROR_OUT_OF_HOST_MEMORY; 3570 goto out; 3571 } 3572 } 3573out: 3574 loader_cJSON_Delete(json); 3575 loader_instance_heap_free(inst, file_vers_str); 3576 loader_instance_heap_free(inst, version_str); 3577 loader_instance_heap_free(inst, library_arch_str); 3578 return res; 3579} 3580 3581// Try to find the Vulkan ICD driver(s). 3582// 3583// This function scans the default system loader path(s) or path specified by either the 3584// VK_DRIVER_FILES or VK_ICD_FILENAMES environment variable in order to find loadable 3585// VK ICDs manifest files. 3586// From these manifest files it finds the ICD libraries. 3587// 3588// skipped_portability_drivers is used to report whether the loader found drivers which report 3589// portability but the application didn't enable the bit to enumerate them 3590// Can be NULL 3591// 3592// \returns 3593// Vulkan result 3594// (on result == VK_SUCCESS) a list of icds that were discovered 3595VkResult loader_icd_scan(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list, 3596 const VkInstanceCreateInfo *pCreateInfo, bool *skipped_portability_drivers) { 3597 VkResult res = VK_SUCCESS; 3598 struct loader_string_list manifest_files = {0}; 3599 struct loader_envvar_filter select_filter = {0}; 3600 struct loader_envvar_filter disable_filter = {0}; 3601 struct ICDManifestInfo *icd_details = NULL; 3602 3603 // Set up the ICD Trampoline list so elements can be written into it. 3604 res = loader_scanned_icd_init(inst, icd_tramp_list); 3605 if (res == VK_ERROR_OUT_OF_HOST_MEMORY) { 3606 return res; 3607 } 3608 3609 bool direct_driver_loading_exclusive_mode = false; 3610 res = loader_scan_for_direct_drivers(inst, pCreateInfo, icd_tramp_list, &direct_driver_loading_exclusive_mode); 3611 if (res == VK_ERROR_OUT_OF_HOST_MEMORY) { 3612 goto out; 3613 } 3614 if (direct_driver_loading_exclusive_mode) { 3615 // Make sure to jump over the system & env-var driver discovery mechanisms if exclusive mode is set, even if no drivers 3616 // were successfully found through the direct driver loading mechanism 3617 goto out; 3618 } 3619 3620 // Parse the filter environment variables to determine if we have any special behavior 3621 res = parse_generic_filter_environment_var(inst, VK_DRIVERS_SELECT_ENV_VAR, &select_filter); 3622 if (VK_SUCCESS != res) { 3623 goto out; 3624 } 3625 res = parse_generic_filter_environment_var(inst, VK_DRIVERS_DISABLE_ENV_VAR, &disable_filter); 3626 if (VK_SUCCESS != res) { 3627 goto out; 3628 } 3629 3630 // Get a list of manifest files for ICDs 3631 res = loader_get_data_files(inst, LOADER_DATA_FILE_MANIFEST_DRIVER, NULL, &manifest_files); 3632 if (VK_SUCCESS != res) { 3633 goto out; 3634 } 3635 3636 icd_details = loader_stack_alloc(sizeof(struct ICDManifestInfo) * manifest_files.count); 3637 if (NULL == icd_details) { 3638 res = VK_ERROR_OUT_OF_HOST_MEMORY; 3639 goto out; 3640 } 3641 memset(icd_details, 0, sizeof(struct ICDManifestInfo) * manifest_files.count); 3642 3643 for (uint32_t i = 0; i < manifest_files.count; i++) { 3644 VkResult icd_res = VK_SUCCESS; 3645 3646 icd_res = loader_parse_icd_manifest(inst, manifest_files.list[i], &icd_details[i], skipped_portability_drivers); 3647 if (VK_ERROR_OUT_OF_HOST_MEMORY == icd_res) { 3648 res = icd_res; 3649 goto out; 3650 } else if (VK_ERROR_INCOMPATIBLE_DRIVER == icd_res) { 3651 continue; 3652 } 3653 3654 if (select_filter.count > 0 || disable_filter.count > 0) { 3655 // Get only the filename for comparing to the filters 3656 char *just_filename_str = strrchr(manifest_files.list[i], DIRECTORY_SYMBOL); 3657 3658 // No directory symbol, just the filename 3659 if (NULL == just_filename_str) { 3660 just_filename_str = manifest_files.list[i]; 3661 } else { 3662 just_filename_str++; 3663 } 3664 3665 bool name_matches_select = 3666 (select_filter.count > 0 && check_name_matches_filter_environment_var(just_filename_str, &select_filter)); 3667 bool name_matches_disable = 3668 (disable_filter.count > 0 && check_name_matches_filter_environment_var(just_filename_str, &disable_filter)); 3669 3670 if (name_matches_disable && !name_matches_select) { 3671 loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0, 3672 "Driver \"%s\" ignored because it was disabled by env var \'%s\'", just_filename_str, 3673 VK_DRIVERS_DISABLE_ENV_VAR); 3674 continue; 3675 } 3676 if (select_filter.count != 0 && !name_matches_select) { 3677 loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0, 3678 "Driver \"%s\" ignored because not selected by env var \'%s\'", just_filename_str, 3679 VK_DRIVERS_SELECT_ENV_VAR); 3680 continue; 3681 } 3682 } 3683 3684 enum loader_layer_library_status lib_status; 3685 icd_res = 3686 loader_scanned_icd_add(inst, icd_tramp_list, icd_details[i].full_library_path, icd_details[i].version, &lib_status); 3687 if (VK_ERROR_OUT_OF_HOST_MEMORY == icd_res) { 3688 res = icd_res; 3689 goto out; 3690 } else if (VK_ERROR_INCOMPATIBLE_DRIVER == icd_res) { 3691 switch (lib_status) { 3692 case LOADER_LAYER_LIB_NOT_LOADED: 3693 case LOADER_LAYER_LIB_ERROR_FAILED_TO_LOAD: 3694 loader_log(inst, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_DRIVER_BIT, 0, 3695 "loader_icd_scan: Failed loading library associated with ICD JSON %s. Ignoring this JSON", 3696 icd_details[i].full_library_path); 3697 break; 3698 case LOADER_LAYER_LIB_ERROR_WRONG_BIT_TYPE: { 3699 loader_log(inst, VULKAN_LOADER_DRIVER_BIT, 0, "Requested ICD %s was wrong bit-type. Ignoring this JSON", 3700 icd_details[i].full_library_path); 3701 break; 3702 } 3703 case LOADER_LAYER_LIB_SUCCESS_LOADED: 3704 case LOADER_LAYER_LIB_ERROR_OUT_OF_MEMORY: 3705 // Shouldn't be able to reach this but if it is, best to report a debug 3706 loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0, 3707 "Shouldn't reach this. A valid version of requested ICD %s was loaded but something bad " 3708 "happened afterwards.", 3709 icd_details[i].full_library_path); 3710 break; 3711 } 3712 } 3713 } 3714 3715out: 3716 if (NULL != icd_details) { 3717 // Successfully got the icd_details structure, which means we need to free the paths contained within 3718 for (uint32_t i = 0; i < manifest_files.count; i++) { 3719 loader_instance_heap_free(inst, icd_details[i].full_library_path); 3720 } 3721 } 3722 free_string_list(inst, &manifest_files); 3723 return res; 3724} 3725 3726// Gets the layer data files corresponding to manifest_type & path_override, then parses the resulting json objects 3727// into instance_layers 3728// Manifest type must be either implicit or explicit 3729VkResult loader_parse_instance_layers(struct loader_instance *inst, enum loader_data_files_type manifest_type, 3730 const char *path_override, struct loader_layer_list *instance_layers) { 3731 assert(manifest_type == LOADER_DATA_FILE_MANIFEST_IMPLICIT_LAYER || manifest_type == LOADER_DATA_FILE_MANIFEST_EXPLICIT_LAYER); 3732 VkResult res = VK_SUCCESS; 3733 struct loader_string_list manifest_files = {0}; 3734 3735 res = loader_get_data_files(inst, manifest_type, path_override, &manifest_files); 3736 if (VK_SUCCESS != res) { 3737 goto out; 3738 } 3739 3740 for (uint32_t i = 0; i < manifest_files.count; i++) { 3741 char *file_str = manifest_files.list[i]; 3742 if (file_str == NULL) { 3743 continue; 3744 } 3745 3746 // Parse file into JSON struct 3747 cJSON *json = NULL; 3748 VkResult local_res = loader_get_json(inst, file_str, &json); 3749 if (VK_ERROR_OUT_OF_HOST_MEMORY == local_res) { 3750 res = VK_ERROR_OUT_OF_HOST_MEMORY; 3751 goto out; 3752 } else if (VK_SUCCESS != local_res || NULL == json) { 3753 continue; 3754 } 3755 3756 local_res = loader_add_layer_properties(inst, instance_layers, json, 3757 manifest_type == LOADER_DATA_FILE_MANIFEST_IMPLICIT_LAYER, file_str); 3758 loader_cJSON_Delete(json); 3759 3760 // If the error is anything other than out of memory we still want to try to load the other layers 3761 if (VK_ERROR_OUT_OF_HOST_MEMORY == local_res) { 3762 res = VK_ERROR_OUT_OF_HOST_MEMORY; 3763 goto out; 3764 } 3765 } 3766out: 3767 free_string_list(inst, &manifest_files); 3768 3769 return res; 3770} 3771 3772// Given a loader_layer_properties struct that is a valid override layer, concatenate the properties override paths and put them 3773// into the output parameter override_paths 3774VkResult get_override_layer_override_paths(struct loader_instance *inst, struct loader_layer_properties *prop, 3775 char **override_paths) { 3776 if (prop->override_paths.count > 0) { 3777 char *cur_write_ptr = NULL; 3778 size_t override_path_size = 0; 3779 for (uint32_t j = 0; j < prop->override_paths.count; j++) { 3780 override_path_size += determine_data_file_path_size(prop->override_paths.list[j], 0); 3781 } 3782 *override_paths = loader_instance_heap_alloc(inst, override_path_size, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 3783 if (*override_paths == NULL) { 3784 return VK_ERROR_OUT_OF_HOST_MEMORY; 3785 } 3786 cur_write_ptr = &(*override_paths)[0]; 3787 for (uint32_t j = 0; j < prop->override_paths.count; j++) { 3788 copy_data_file_info(prop->override_paths.list[j], NULL, 0, &cur_write_ptr); 3789 } 3790 // Remove the last path separator 3791 --cur_write_ptr; 3792 assert(cur_write_ptr - (*override_paths) < (ptrdiff_t)override_path_size); 3793 *cur_write_ptr = '\0'; 3794 loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0, "Override layer has override paths set to %s", 3795 *override_paths); 3796 } 3797 return VK_SUCCESS; 3798} 3799 3800VkResult loader_scan_for_layers(struct loader_instance *inst, struct loader_layer_list *instance_layers, 3801 const struct loader_envvar_all_filters *filters) { 3802 VkResult res = VK_SUCCESS; 3803 struct loader_layer_list settings_layers = {0}; 3804 struct loader_layer_list regular_instance_layers = {0}; 3805 bool override_layer_valid = false; 3806 char *override_paths = NULL; 3807 3808 bool should_search_for_other_layers = true; 3809 res = get_settings_layers(inst, &settings_layers, &should_search_for_other_layers); 3810 if (VK_SUCCESS != res) { 3811 goto out; 3812 } 3813 3814 // If we should not look for layers using other mechanisms, assign settings_layers to instance_layers and jump to the 3815 // output 3816 if (!should_search_for_other_layers) { 3817 *instance_layers = settings_layers; 3818 memset(&settings_layers, 0, sizeof(struct loader_layer_list)); 3819 goto out; 3820 } 3821 3822 res = loader_parse_instance_layers(inst, LOADER_DATA_FILE_MANIFEST_IMPLICIT_LAYER, NULL, ®ular_instance_layers); 3823 if (VK_SUCCESS != res) { 3824 goto out; 3825 } 3826 3827 // Remove any extraneous override layers. 3828 remove_all_non_valid_override_layers(inst, ®ular_instance_layers); 3829 3830 // Check to see if the override layer is present, and use it's override paths. 3831 for (uint32_t i = 0; i < regular_instance_layers.count; i++) { 3832 struct loader_layer_properties *prop = ®ular_instance_layers.list[i]; 3833 if (prop->is_override && loader_implicit_layer_is_enabled(inst, filters, prop) && prop->override_paths.count > 0) { 3834 res = get_override_layer_override_paths(inst, prop, &override_paths); 3835 if (VK_SUCCESS != res) { 3836 goto out; 3837 } 3838 break; 3839 } 3840 } 3841 3842 // Get a list of manifest files for explicit layers 3843 res = loader_parse_instance_layers(inst, LOADER_DATA_FILE_MANIFEST_EXPLICIT_LAYER, override_paths, ®ular_instance_layers); 3844 if (VK_SUCCESS != res) { 3845 goto out; 3846 } 3847 3848 // Verify any meta-layers in the list are valid and all the component layers are 3849 // actually present in the available layer list 3850 res = verify_all_meta_layers(inst, filters, ®ular_instance_layers, &override_layer_valid); 3851 if (VK_ERROR_OUT_OF_HOST_MEMORY == res) { 3852 return res; 3853 } 3854 3855 if (override_layer_valid) { 3856 loader_remove_layers_in_blacklist(inst, ®ular_instance_layers); 3857 if (NULL != inst) { 3858 inst->override_layer_present = true; 3859 } 3860 } 3861 3862 // Remove disabled layers 3863 for (uint32_t i = 0; i < regular_instance_layers.count; ++i) { 3864 if (!loader_layer_is_available(inst, filters, ®ular_instance_layers.list[i])) { 3865 loader_remove_layer_in_list(inst, ®ular_instance_layers, i); 3866 i--; 3867 } 3868 } 3869 3870 res = combine_settings_layers_with_regular_layers(inst, &settings_layers, ®ular_instance_layers, instance_layers); 3871 3872out: 3873 loader_delete_layer_list_and_properties(inst, &settings_layers); 3874 loader_delete_layer_list_and_properties(inst, ®ular_instance_layers); 3875 3876 loader_instance_heap_free(inst, override_paths); 3877 return res; 3878} 3879 3880VkResult loader_scan_for_implicit_layers(struct loader_instance *inst, struct loader_layer_list *instance_layers, 3881 const struct loader_envvar_all_filters *layer_filters) { 3882 VkResult res = VK_SUCCESS; 3883 struct loader_layer_list settings_layers = {0}; 3884 struct loader_layer_list regular_instance_layers = {0}; 3885 bool override_layer_valid = false; 3886 char *override_paths = NULL; 3887 bool implicit_metalayer_present = false; 3888 3889 bool should_search_for_other_layers = true; 3890 res = get_settings_layers(inst, &settings_layers, &should_search_for_other_layers); 3891 if (VK_SUCCESS != res) { 3892 goto out; 3893 } 3894 3895 // If we should not look for layers using other mechanisms, assign settings_layers to instance_layers and jump to the 3896 // output 3897 if (!should_search_for_other_layers) { 3898 *instance_layers = settings_layers; 3899 memset(&settings_layers, 0, sizeof(struct loader_layer_list)); 3900 goto out; 3901 } 3902 3903 res = loader_parse_instance_layers(inst, LOADER_DATA_FILE_MANIFEST_IMPLICIT_LAYER, NULL, ®ular_instance_layers); 3904 if (VK_SUCCESS != res) { 3905 goto out; 3906 } 3907 3908 // Remove any extraneous override layers. 3909 remove_all_non_valid_override_layers(inst, ®ular_instance_layers); 3910 3911 // Check to see if either the override layer is present, or another implicit meta-layer. 3912 // Each of these may require explicit layers to be enabled at this time. 3913 for (uint32_t i = 0; i < regular_instance_layers.count; i++) { 3914 struct loader_layer_properties *prop = ®ular_instance_layers.list[i]; 3915 if (prop->is_override && loader_implicit_layer_is_enabled(inst, layer_filters, prop)) { 3916 override_layer_valid = true; 3917 res = get_override_layer_override_paths(inst, prop, &override_paths); 3918 if (VK_SUCCESS != res) { 3919 goto out; 3920 } 3921 } else if (!prop->is_override && prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER) { 3922 implicit_metalayer_present = true; 3923 } 3924 } 3925 3926 // If either the override layer or an implicit meta-layer are present, we need to add 3927 // explicit layer info as well. Not to worry, though, all explicit layers not included 3928 // in the override layer will be removed below in loader_remove_layers_in_blacklist(). 3929 if (override_layer_valid || implicit_metalayer_present) { 3930 res = 3931 loader_parse_instance_layers(inst, LOADER_DATA_FILE_MANIFEST_EXPLICIT_LAYER, override_paths, ®ular_instance_layers); 3932 if (VK_SUCCESS != res) { 3933 goto out; 3934 } 3935 } 3936 3937 // Verify any meta-layers in the list are valid and all the component layers are 3938 // actually present in the available layer list 3939 res = verify_all_meta_layers(inst, layer_filters, ®ular_instance_layers, &override_layer_valid); 3940 if (VK_ERROR_OUT_OF_HOST_MEMORY == res) { 3941 return res; 3942 } 3943 3944 if (override_layer_valid || implicit_metalayer_present) { 3945 loader_remove_layers_not_in_implicit_meta_layers(inst, ®ular_instance_layers); 3946 if (override_layer_valid && inst != NULL) { 3947 inst->override_layer_present = true; 3948 } 3949 } 3950 3951 // Remove disabled layers 3952 for (uint32_t i = 0; i < regular_instance_layers.count; ++i) { 3953 if (!loader_implicit_layer_is_enabled(inst, layer_filters, ®ular_instance_layers.list[i])) { 3954 loader_remove_layer_in_list(inst, ®ular_instance_layers, i); 3955 i--; 3956 } 3957 } 3958 3959 res = combine_settings_layers_with_regular_layers(inst, &settings_layers, ®ular_instance_layers, instance_layers); 3960 3961out: 3962 loader_delete_layer_list_and_properties(inst, &settings_layers); 3963 loader_delete_layer_list_and_properties(inst, ®ular_instance_layers); 3964 3965 loader_instance_heap_free(inst, override_paths); 3966 return res; 3967} 3968 3969VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL loader_gpdpa_instance_terminator(VkInstance inst, const char *pName) { 3970 // inst is not wrapped 3971 if (inst == VK_NULL_HANDLE) { 3972 return NULL; 3973 } 3974 3975 VkLayerInstanceDispatchTable *disp_table = *(VkLayerInstanceDispatchTable **)inst; 3976 3977 if (disp_table == NULL) return NULL; 3978 3979 struct loader_instance *loader_inst = loader_get_instance(inst); 3980 3981 if (loader_inst->instance_finished_creation) { 3982 disp_table = &loader_inst->terminator_dispatch; 3983 } 3984 3985 bool found_name; 3986 void *addr = loader_lookup_instance_dispatch_table(disp_table, pName, &found_name); 3987 if (found_name) { 3988 return addr; 3989 } 3990 3991 // Check if any drivers support the function, and if so, add it to the unknown function list 3992 addr = loader_phys_dev_ext_gpa_term(loader_get_instance(inst), pName); 3993 if (NULL != addr) return addr; 3994 3995 // Don't call down the chain, this would be an infinite loop 3996 loader_log(NULL, VULKAN_LOADER_DEBUG_BIT, 0, "loader_gpdpa_instance_terminator() unrecognized name %s", pName); 3997 return NULL; 3998} 3999 4000VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL loader_gpa_instance_terminator(VkInstance inst, const char *pName) { 4001 // Global functions - Do not need a valid instance handle to query 4002 if (!strcmp(pName, "vkGetInstanceProcAddr")) { 4003 return (PFN_vkVoidFunction)loader_gpa_instance_terminator; 4004 } 4005 if (!strcmp(pName, "vk_layerGetPhysicalDeviceProcAddr")) { 4006 return (PFN_vkVoidFunction)loader_gpdpa_instance_terminator; 4007 } 4008 if (!strcmp(pName, "vkCreateInstance")) { 4009 return (PFN_vkVoidFunction)terminator_CreateInstance; 4010 } 4011 4012 // While the spec is very clear that querying vkCreateDevice requires a valid VkInstance, because the loader allowed querying 4013 // with a NULL VkInstance handle for a long enough time, it is impractical to fix this bug in the loader 4014 4015 // As such, this is a bug to maintain compatibility for the RTSS layer (Riva Tuner Statistics Server) but may 4016 // be depended upon by other layers out in the wild. 4017 if (!strcmp(pName, "vkCreateDevice")) { 4018 return (PFN_vkVoidFunction)terminator_CreateDevice; 4019 } 4020 4021 // inst is not wrapped 4022 if (inst == VK_NULL_HANDLE) { 4023 return NULL; 4024 } 4025 VkLayerInstanceDispatchTable *disp_table = *(VkLayerInstanceDispatchTable **)inst; 4026 4027 if (disp_table == NULL) return NULL; 4028 4029 struct loader_instance *loader_inst = loader_get_instance(inst); 4030 4031 // The VK_EXT_debug_utils functions need a special case here so the terminators can still be found from 4032 // vkGetInstanceProcAddr This is because VK_EXT_debug_utils is an instance level extension with device level functions, and 4033 // is 'supported' by the loader. 4034 // These functions need a terminator to handle the case of a driver not supporting VK_EXT_debug_utils when there are layers 4035 // present which not check for NULL before calling the function. 4036 if (!strcmp(pName, "vkSetDebugUtilsObjectNameEXT")) { 4037 return loader_inst->enabled_known_extensions.ext_debug_utils ? (PFN_vkVoidFunction)terminator_SetDebugUtilsObjectNameEXT 4038 : NULL; 4039 } 4040 if (!strcmp(pName, "vkSetDebugUtilsObjectTagEXT")) { 4041 return loader_inst->enabled_known_extensions.ext_debug_utils ? (PFN_vkVoidFunction)terminator_SetDebugUtilsObjectTagEXT 4042 : NULL; 4043 } 4044 if (!strcmp(pName, "vkQueueBeginDebugUtilsLabelEXT")) { 4045 return loader_inst->enabled_known_extensions.ext_debug_utils ? (PFN_vkVoidFunction)terminator_QueueBeginDebugUtilsLabelEXT 4046 : NULL; 4047 } 4048 if (!strcmp(pName, "vkQueueEndDebugUtilsLabelEXT")) { 4049 return loader_inst->enabled_known_extensions.ext_debug_utils ? (PFN_vkVoidFunction)terminator_QueueEndDebugUtilsLabelEXT 4050 : NULL; 4051 } 4052 if (!strcmp(pName, "vkQueueInsertDebugUtilsLabelEXT")) { 4053 return loader_inst->enabled_known_extensions.ext_debug_utils ? (PFN_vkVoidFunction)terminator_QueueInsertDebugUtilsLabelEXT 4054 : NULL; 4055 } 4056 if (!strcmp(pName, "vkCmdBeginDebugUtilsLabelEXT")) { 4057 return loader_inst->enabled_known_extensions.ext_debug_utils ? (PFN_vkVoidFunction)terminator_CmdBeginDebugUtilsLabelEXT 4058 : NULL; 4059 } 4060 if (!strcmp(pName, "vkCmdEndDebugUtilsLabelEXT")) { 4061 return loader_inst->enabled_known_extensions.ext_debug_utils ? (PFN_vkVoidFunction)terminator_CmdEndDebugUtilsLabelEXT 4062 : NULL; 4063 } 4064 if (!strcmp(pName, "vkCmdInsertDebugUtilsLabelEXT")) { 4065 return loader_inst->enabled_known_extensions.ext_debug_utils ? (PFN_vkVoidFunction)terminator_CmdInsertDebugUtilsLabelEXT 4066 : NULL; 4067 } 4068 4069 if (loader_inst->instance_finished_creation) { 4070 disp_table = &loader_inst->terminator_dispatch; 4071 } 4072 4073 bool found_name; 4074 void *addr = loader_lookup_instance_dispatch_table(disp_table, pName, &found_name); 4075 if (found_name) { 4076 return addr; 4077 } 4078 4079 // Check if it is an unknown physical device function, to see if any drivers support it. 4080 addr = loader_phys_dev_ext_gpa_term(loader_get_instance(inst), pName); 4081 if (addr) { 4082 return addr; 4083 } 4084 4085 // Assume it is an unknown device function, check to see if any drivers support it. 4086 addr = loader_dev_ext_gpa_term(loader_get_instance(inst), pName); 4087 if (addr) { 4088 return addr; 4089 } 4090 4091 // Don't call down the chain, this would be an infinite loop 4092 loader_log(NULL, VULKAN_LOADER_DEBUG_BIT, 0, "loader_gpa_instance_terminator() unrecognized name %s", pName); 4093 return NULL; 4094} 4095 4096VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL loader_gpa_device_terminator(VkDevice device, const char *pName) { 4097 struct loader_device *dev; 4098 struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev, NULL); 4099 4100 // Return this function if a layer above here is asking for the vkGetDeviceProcAddr. 4101 // This is so we can properly intercept any device commands needing a terminator. 4102 if (!strcmp(pName, "vkGetDeviceProcAddr")) { 4103 return (PFN_vkVoidFunction)loader_gpa_device_terminator; 4104 } 4105 4106 // NOTE: Device Funcs needing Trampoline/Terminator. 4107 // Overrides for device functions needing a trampoline and 4108 // a terminator because certain device entry-points still need to go 4109 // through a terminator before hitting the ICD. This could be for 4110 // several reasons, but the main one is currently unwrapping an 4111 // object before passing the appropriate info along to the ICD. 4112 // This is why we also have to override the direct ICD call to 4113 // vkGetDeviceProcAddr to intercept those calls. 4114 // If the pName is for a 'known' function but isn't available, due to 4115 // the corresponding extension/feature not being enabled, we need to 4116 // return NULL and not call down to the driver's GetDeviceProcAddr. 4117 if (NULL != dev) { 4118 bool found_name = false; 4119 PFN_vkVoidFunction addr = get_extension_device_proc_terminator(dev, pName, &found_name); 4120 if (found_name) { 4121 return addr; 4122 } 4123 } 4124 4125 if (icd_term == NULL) { 4126 return NULL; 4127 } 4128 4129 return icd_term->dispatch.GetDeviceProcAddr(device, pName); 4130} 4131 4132struct loader_instance *loader_get_instance(const VkInstance instance) { 4133 // look up the loader_instance in our list by comparing dispatch tables, as 4134 // there is no guarantee the instance is still a loader_instance* after any 4135 // layers which wrap the instance object. 4136 const VkLayerInstanceDispatchTable *disp; 4137 struct loader_instance *ptr_instance = (struct loader_instance *)instance; 4138 if (VK_NULL_HANDLE == instance || LOADER_MAGIC_NUMBER != ptr_instance->magic) { 4139 return NULL; 4140 } else { 4141 disp = loader_get_instance_layer_dispatch(instance); 4142 loader_platform_thread_lock_mutex(&loader_global_instance_list_lock); 4143 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) { 4144 if (&inst->disp->layer_inst_disp == disp) { 4145 ptr_instance = inst; 4146 break; 4147 } 4148 } 4149 loader_platform_thread_unlock_mutex(&loader_global_instance_list_lock); 4150 } 4151 return ptr_instance; 4152} 4153 4154loader_platform_dl_handle loader_open_layer_file(const struct loader_instance *inst, struct loader_layer_properties *prop) { 4155 char* libPath = prop->lib_name; 4156#if defined(__OHOS__) 4157 char *debug_layer_name = loader_secure_getenv("debug.graphic.debug_layer", inst); 4158 char *debug_hap_name = loader_secure_getenv("debug.graphic.debug_hap", inst); 4159 bool isDebugLayer = false; 4160 char* debugLayerLibPath = NULL; 4161 if (NULL != debug_layer_name && '\0' != debug_layer_name[0] && InitBundleInfo(debug_hap_name)) { 4162 const char lib_prefix[] = "lib"; 4163 const char so_suffix[] = ".so"; 4164 size_t totalLen = strlen(debug_layer_name) + strlen(lib_prefix) + strlen(so_suffix) + 1; 4165 char* layerSoName = loader_instance_heap_calloc(inst, totalLen, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 4166 if (layerSoName == NULL) { 4167 loader_log(inst, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_LAYER_BIT, 0, "malloc layerSoName fail"); 4168 goto mallocErr; 4169 } 4170 strncpy(layerSoName, lib_prefix, totalLen); 4171 strncat(layerSoName, debug_layer_name, totalLen); 4172 strncat(layerSoName, so_suffix, totalLen); 4173 if (strcmp(layerSoName, libPath) == 0) { 4174 isDebugLayer = true; 4175 debugLayerLibPath = GetDebugLayerLibPath(inst, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 4176 if(debugLayerLibPath == NULL) { 4177 loader_instance_heap_free(inst, layerSoName); 4178 isDebugLayer = false; 4179 goto mallocErr; 4180 } 4181 size_t totalLength = strlen(libPath) + strlen(debugLayerLibPath) + 1; 4182 libPath = loader_instance_heap_calloc(inst, totalLength, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 4183 if (libPath == NULL) { 4184 loader_log(inst, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_LAYER_BIT, 0, "malloc libPath fail"); 4185 loader_instance_heap_free(inst, layerSoName); 4186 loader_instance_heap_free(inst, debugLayerLibPath); 4187 libPath = prop->lib_name; 4188 isDebugLayer = false; 4189 goto mallocErr; 4190 } 4191 strncpy(libPath, debugLayerLibPath, totalLength); 4192 strncat(libPath, prop->lib_name, totalLength); 4193 } else { 4194 loader_log(inst, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_LAYER_BIT, 0, "layerSoName != libPath : %s != %s", 4195 layerSoName, libPath); 4196 } 4197 loader_instance_heap_free(inst, layerSoName); 4198 } 4199mallocErr: 4200 loader_free_getenv(debug_layer_name, inst); 4201 loader_free_getenv(debug_hap_name, inst); 4202#endif 4203 loader_log(inst, VULKAN_LOADER_DEBUG_BIT | VULKAN_LOADER_LAYER_BIT, 0, "try to open libPath: %s", libPath); 4204 if ((prop->lib_handle = loader_platform_open_library(libPath)) == NULL) { 4205 loader_handle_load_library_error(inst, prop->lib_name, &prop->lib_status); 4206 } else { 4207 prop->lib_status = LOADER_LAYER_LIB_SUCCESS_LOADED; 4208 loader_log(inst, VULKAN_LOADER_DEBUG_BIT | VULKAN_LOADER_LAYER_BIT, 0, "Loading layer library %s", prop->lib_name); 4209 } 4210#if defined(__OHOS__) 4211 if (isDebugLayer) { 4212 loader_instance_heap_free(inst, debugLayerLibPath); 4213 loader_instance_heap_free(inst, libPath); 4214 } 4215#endif 4216 return prop->lib_handle; 4217} 4218 4219// Go through the search_list and find any layers which match type. If layer 4220// type match is found in then add it to ext_list. 4221VkResult loader_add_implicit_layers(const struct loader_instance *inst, const struct loader_envvar_all_filters *filters, 4222 struct loader_pointer_layer_list *target_list, 4223 struct loader_pointer_layer_list *expanded_target_list, 4224 const struct loader_layer_list *source_list) { 4225 for (uint32_t src_layer = 0; src_layer < source_list->count; src_layer++) { 4226 struct loader_layer_properties *prop = &source_list->list[src_layer]; 4227 if (0 == (prop->type_flags & VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER)) { 4228 VkResult result = loader_add_implicit_layer(inst, prop, filters, target_list, expanded_target_list, source_list); 4229 if (result == VK_ERROR_OUT_OF_HOST_MEMORY) return result; 4230 } 4231 } 4232 return VK_SUCCESS; 4233} 4234 4235void warn_if_layers_are_older_than_application(struct loader_instance *inst) { 4236 for (uint32_t i = 0; i < inst->expanded_activated_layer_list.count; i++) { 4237 // Verify that the layer api version is at least that of the application's request, if not, throw a warning since 4238 // undefined behavior could occur. 4239 struct loader_layer_properties *prop = inst->expanded_activated_layer_list.list[i]; 4240 loader_api_version prop_spec_version = loader_make_version(prop->info.specVersion); 4241 if (!loader_check_version_meets_required(inst->app_api_version, prop_spec_version)) { 4242 loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0, 4243 "Layer %s uses API version %u.%u which is older than the application specified " 4244 "API version of %u.%u. May cause issues.", 4245 prop->info.layerName, prop_spec_version.major, prop_spec_version.minor, inst->app_api_version.major, 4246 inst->app_api_version.minor); 4247 } 4248 } 4249} 4250 4251VkResult loader_enable_instance_layers(struct loader_instance *inst, const VkInstanceCreateInfo *pCreateInfo, 4252 const struct loader_layer_list *instance_layers, 4253 const struct loader_envvar_all_filters *layer_filters) { 4254 VkResult res = VK_SUCCESS; 4255 4256 assert(inst && "Cannot have null instance"); 4257 4258 if (!loader_init_pointer_layer_list(inst, &inst->app_activated_layer_list)) { 4259 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 4260 "loader_enable_instance_layers: Failed to initialize application version of the layer list"); 4261 res = VK_ERROR_OUT_OF_HOST_MEMORY; 4262 goto out; 4263 } 4264 4265 if (!loader_init_pointer_layer_list(inst, &inst->expanded_activated_layer_list)) { 4266 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 4267 "loader_enable_instance_layers: Failed to initialize expanded version of the layer list"); 4268 res = VK_ERROR_OUT_OF_HOST_MEMORY; 4269 goto out; 4270 } 4271 4272 if (inst->settings.settings_active) { 4273 res = enable_correct_layers_from_settings(inst, layer_filters, pCreateInfo->enabledLayerCount, 4274 pCreateInfo->ppEnabledLayerNames, &inst->instance_layer_list, 4275 &inst->app_activated_layer_list, &inst->expanded_activated_layer_list); 4276 warn_if_layers_are_older_than_application(inst); 4277 4278 goto out; 4279 } 4280 4281 // Add any implicit layers first 4282 res = loader_add_implicit_layers(inst, layer_filters, &inst->app_activated_layer_list, &inst->expanded_activated_layer_list, 4283 instance_layers); 4284 if (res != VK_SUCCESS) { 4285 goto out; 4286 } 4287 4288 // Add any layers specified via environment variable next 4289 res = loader_add_environment_layers(inst, VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER, layer_filters, &inst->app_activated_layer_list, 4290 &inst->expanded_activated_layer_list, instance_layers); 4291 if (res != VK_SUCCESS) { 4292 goto out; 4293 } 4294 4295 // Add layers specified by the application 4296 res = loader_add_layer_names_to_list(inst, layer_filters, &inst->app_activated_layer_list, &inst->expanded_activated_layer_list, 4297 pCreateInfo->enabledLayerCount, pCreateInfo->ppEnabledLayerNames, instance_layers); 4298 4299 warn_if_layers_are_older_than_application(inst); 4300out: 4301 return res; 4302} 4303 4304// Determine the layer interface version to use. 4305bool loader_get_layer_interface_version(PFN_vkNegotiateLoaderLayerInterfaceVersion fp_negotiate_layer_version, 4306 VkNegotiateLayerInterface *interface_struct) { 4307 memset(interface_struct, 0, sizeof(VkNegotiateLayerInterface)); 4308 interface_struct->sType = LAYER_NEGOTIATE_INTERFACE_STRUCT; 4309 interface_struct->loaderLayerInterfaceVersion = 1; 4310 interface_struct->pNext = NULL; 4311 4312 if (fp_negotiate_layer_version != NULL) { 4313 // Layer supports the negotiation API, so call it with the loader's 4314 // latest version supported 4315 interface_struct->loaderLayerInterfaceVersion = CURRENT_LOADER_LAYER_INTERFACE_VERSION; 4316 VkResult result = fp_negotiate_layer_version(interface_struct); 4317 4318 if (result != VK_SUCCESS) { 4319 // Layer no longer supports the loader's latest interface version so 4320 // fail loading the Layer 4321 return false; 4322 } 4323 } 4324 4325 if (interface_struct->loaderLayerInterfaceVersion < MIN_SUPPORTED_LOADER_LAYER_INTERFACE_VERSION) { 4326 // Loader no longer supports the layer's latest interface version so 4327 // fail loading the layer 4328 return false; 4329 } 4330 4331 return true; 4332} 4333 4334// Every extension that has a loader-defined trampoline needs to be marked as enabled or disabled so that we know whether or 4335// not to return that trampoline when vkGetDeviceProcAddr is called 4336void setup_logical_device_enabled_layer_extensions(const struct loader_instance *inst, struct loader_device *dev, 4337 const struct loader_extension_list *icd_exts, 4338 const VkDeviceCreateInfo *pCreateInfo) { 4339 // Can only setup debug marker as debug utils is an instance extensions. 4340 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; ++i) { 4341 if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_EXT_DEBUG_MARKER_EXTENSION_NAME)) { 4342 // Check if its supported by the driver 4343 for (uint32_t j = 0; j < icd_exts->count; ++j) { 4344 if (!strcmp(icd_exts->list[j].extensionName, VK_EXT_DEBUG_MARKER_EXTENSION_NAME)) { 4345 dev->layer_extensions.ext_debug_marker_enabled = true; 4346 } 4347 } 4348 // also check if any layers support it. 4349 for (uint32_t j = 0; j < inst->app_activated_layer_list.count; j++) { 4350 struct loader_layer_properties *layer = inst->app_activated_layer_list.list[j]; 4351 for (uint32_t k = 0; k < layer->device_extension_list.count; k++) { 4352 if (!strcmp(layer->device_extension_list.list[k].props.extensionName, VK_EXT_DEBUG_MARKER_EXTENSION_NAME)) { 4353 dev->layer_extensions.ext_debug_marker_enabled = true; 4354 } 4355 } 4356 } 4357 } 4358 } 4359} 4360 4361VKAPI_ATTR VkResult VKAPI_CALL loader_layer_create_device(VkInstance instance, VkPhysicalDevice physicalDevice, 4362 const VkDeviceCreateInfo *pCreateInfo, 4363 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice, 4364 PFN_vkGetInstanceProcAddr layerGIPA, PFN_vkGetDeviceProcAddr *nextGDPA) { 4365 VkResult res; 4366 VkPhysicalDevice internal_device = VK_NULL_HANDLE; 4367 struct loader_device *dev = NULL; 4368 struct loader_instance *inst = NULL; 4369 4370 if (instance != VK_NULL_HANDLE) { 4371 inst = loader_get_instance(instance); 4372 internal_device = physicalDevice; 4373 } else { 4374 struct loader_physical_device_tramp *phys_dev = (struct loader_physical_device_tramp *)physicalDevice; 4375 internal_device = phys_dev->phys_dev; 4376 inst = (struct loader_instance *)phys_dev->this_instance; 4377 } 4378 4379 // Get the physical device (ICD) extensions 4380 struct loader_extension_list icd_exts = {0}; 4381 icd_exts.list = NULL; 4382 res = loader_init_generic_list(inst, (struct loader_generic_list *)&icd_exts, sizeof(VkExtensionProperties)); 4383 if (VK_SUCCESS != res) { 4384 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "vkCreateDevice: Failed to create ICD extension list"); 4385 goto out; 4386 } 4387 4388 PFN_vkEnumerateDeviceExtensionProperties enumDeviceExtensionProperties = NULL; 4389 if (layerGIPA != NULL) { 4390 enumDeviceExtensionProperties = 4391 (PFN_vkEnumerateDeviceExtensionProperties)layerGIPA(instance, "vkEnumerateDeviceExtensionProperties"); 4392 } else { 4393 enumDeviceExtensionProperties = inst->disp->layer_inst_disp.EnumerateDeviceExtensionProperties; 4394 } 4395 res = loader_add_device_extensions(inst, enumDeviceExtensionProperties, internal_device, "Unknown", &icd_exts); 4396 if (res != VK_SUCCESS) { 4397 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "vkCreateDevice: Failed to add extensions to list"); 4398 goto out; 4399 } 4400 4401 // Make sure requested extensions to be enabled are supported 4402 res = loader_validate_device_extensions(inst, &inst->expanded_activated_layer_list, &icd_exts, pCreateInfo); 4403 if (res != VK_SUCCESS) { 4404 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "vkCreateDevice: Failed to validate extensions in list"); 4405 goto out; 4406 } 4407 4408 dev = loader_create_logical_device(inst, pAllocator); 4409 if (dev == NULL) { 4410 res = VK_ERROR_OUT_OF_HOST_MEMORY; 4411 goto out; 4412 } 4413 4414 setup_logical_device_enabled_layer_extensions(inst, dev, &icd_exts, pCreateInfo); 4415 4416 res = loader_create_device_chain(internal_device, pCreateInfo, pAllocator, inst, dev, layerGIPA, nextGDPA); 4417 if (res != VK_SUCCESS) { 4418 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "vkCreateDevice: Failed to create device chain."); 4419 goto out; 4420 } 4421 4422 *pDevice = dev->chain_device; 4423 4424 // Initialize any device extension dispatch entry's from the instance list 4425 loader_init_dispatch_dev_ext(inst, dev); 4426 4427 // Initialize WSI device extensions as part of core dispatch since loader 4428 // has dedicated trampoline code for these 4429 loader_init_device_extension_dispatch_table(&dev->loader_dispatch, inst->disp->layer_inst_disp.GetInstanceProcAddr, 4430 dev->loader_dispatch.core_dispatch.GetDeviceProcAddr, inst->instance, *pDevice); 4431 4432out: 4433 4434 // Failure cleanup 4435 if (VK_SUCCESS != res) { 4436 if (NULL != dev) { 4437 // Find the icd_term this device belongs to then remove it from that icd_term. 4438 // Need to iterate the linked lists and remove the device from it. Don't delete 4439 // the device here since it may not have been added to the icd_term and there 4440 // are other allocations attached to it. 4441 struct loader_icd_term *icd_term = inst->icd_terms; 4442 bool found = false; 4443 while (!found && NULL != icd_term) { 4444 struct loader_device *cur_dev = icd_term->logical_device_list; 4445 struct loader_device *prev_dev = NULL; 4446 while (NULL != cur_dev) { 4447 if (cur_dev == dev) { 4448 if (cur_dev == icd_term->logical_device_list) { 4449 icd_term->logical_device_list = cur_dev->next; 4450 } else if (prev_dev) { 4451 prev_dev->next = cur_dev->next; 4452 } 4453 4454 found = true; 4455 break; 4456 } 4457 prev_dev = cur_dev; 4458 cur_dev = cur_dev->next; 4459 } 4460 icd_term = icd_term->next; 4461 } 4462 // Now destroy the device and the allocations associated with it. 4463 loader_destroy_logical_device(dev, pAllocator); 4464 } 4465 } 4466 4467 if (NULL != icd_exts.list) { 4468 loader_destroy_generic_list(inst, (struct loader_generic_list *)&icd_exts); 4469 } 4470 return res; 4471} 4472 4473VKAPI_ATTR void VKAPI_CALL loader_layer_destroy_device(VkDevice device, const VkAllocationCallbacks *pAllocator, 4474 PFN_vkDestroyDevice destroyFunction) { 4475 struct loader_device *dev; 4476 4477 if (device == VK_NULL_HANDLE) { 4478 return; 4479 } 4480 4481 struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev, NULL); 4482 4483 destroyFunction(device, pAllocator); 4484 if (NULL != dev) { 4485 dev->chain_device = NULL; 4486 dev->icd_device = NULL; 4487 loader_remove_logical_device(icd_term, dev, pAllocator); 4488 } 4489} 4490 4491// Given the list of layers to activate in the loader_instance 4492// structure. This function will add a VkLayerInstanceCreateInfo 4493// structure to the VkInstanceCreateInfo.pNext pointer. 4494// Each activated layer will have it's own VkLayerInstanceLink 4495// structure that tells the layer what Get*ProcAddr to call to 4496// get function pointers to the next layer down. 4497// Once the chain info has been created this function will 4498// execute the CreateInstance call chain. Each layer will 4499// then have an opportunity in it's CreateInstance function 4500// to setup it's dispatch table when the lower layer returns 4501// successfully. 4502// Each layer can wrap or not-wrap the returned VkInstance object 4503// as it sees fit. 4504// The instance chain is terminated by a loader function 4505// that will call CreateInstance on all available ICD's and 4506// cache those VkInstance objects for future use. 4507VkResult loader_create_instance_chain(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, 4508 struct loader_instance *inst, VkInstance *created_instance) { 4509 uint32_t num_activated_layers = 0; 4510 struct activated_layer_info *activated_layers = NULL; 4511 VkLayerInstanceCreateInfo chain_info; 4512 VkLayerInstanceLink *layer_instance_link_info = NULL; 4513 VkInstanceCreateInfo loader_create_info; 4514 VkResult res; 4515 4516 PFN_vkGetInstanceProcAddr next_gipa = loader_gpa_instance_terminator; 4517 PFN_vkGetInstanceProcAddr cur_gipa = loader_gpa_instance_terminator; 4518 PFN_vkGetDeviceProcAddr cur_gdpa = loader_gpa_device_terminator; 4519 PFN_GetPhysicalDeviceProcAddr next_gpdpa = loader_gpdpa_instance_terminator; 4520 PFN_GetPhysicalDeviceProcAddr cur_gpdpa = loader_gpdpa_instance_terminator; 4521 4522 memcpy(&loader_create_info, pCreateInfo, sizeof(VkInstanceCreateInfo)); 4523 4524 if (inst->expanded_activated_layer_list.count > 0) { 4525 chain_info.u.pLayerInfo = NULL; 4526 chain_info.pNext = pCreateInfo->pNext; 4527 chain_info.sType = VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO; 4528 chain_info.function = VK_LAYER_LINK_INFO; 4529 loader_create_info.pNext = &chain_info; 4530 4531 layer_instance_link_info = loader_stack_alloc(sizeof(VkLayerInstanceLink) * inst->expanded_activated_layer_list.count); 4532 if (!layer_instance_link_info) { 4533 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 4534 "loader_create_instance_chain: Failed to alloc Instance objects for layer"); 4535 return VK_ERROR_OUT_OF_HOST_MEMORY; 4536 } 4537 4538 activated_layers = loader_stack_alloc(sizeof(struct activated_layer_info) * inst->expanded_activated_layer_list.count); 4539 if (!activated_layers) { 4540 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 4541 "loader_create_instance_chain: Failed to alloc activated layer storage array"); 4542 return VK_ERROR_OUT_OF_HOST_MEMORY; 4543 } 4544 4545 // Create instance chain of enabled layers 4546 for (int32_t i = inst->expanded_activated_layer_list.count - 1; i >= 0; i--) { 4547 struct loader_layer_properties *layer_prop = inst->expanded_activated_layer_list.list[i]; 4548 loader_platform_dl_handle lib_handle; 4549 4550 // Skip it if a Layer with the same name has been already successfully activated 4551 if (loader_names_array_has_layer_property(&layer_prop->info, num_activated_layers, activated_layers)) { 4552 continue; 4553 } 4554 4555 lib_handle = loader_open_layer_file(inst, layer_prop); 4556 if (layer_prop->lib_status == LOADER_LAYER_LIB_ERROR_OUT_OF_MEMORY) { 4557 return VK_ERROR_OUT_OF_HOST_MEMORY; 4558 } 4559 if (!lib_handle) { 4560 continue; 4561 } 4562 4563 if (NULL == layer_prop->functions.negotiate_layer_interface) { 4564 PFN_vkNegotiateLoaderLayerInterfaceVersion negotiate_interface = NULL; 4565 bool functions_in_interface = false; 4566 if (!layer_prop->functions.str_negotiate_interface || strlen(layer_prop->functions.str_negotiate_interface) == 0) { 4567 negotiate_interface = (PFN_vkNegotiateLoaderLayerInterfaceVersion)loader_platform_get_proc_address( 4568 lib_handle, "vkNegotiateLoaderLayerInterfaceVersion"); 4569 } else { 4570 negotiate_interface = (PFN_vkNegotiateLoaderLayerInterfaceVersion)loader_platform_get_proc_address( 4571 lib_handle, layer_prop->functions.str_negotiate_interface); 4572 } 4573 4574 // If we can negotiate an interface version, then we can also 4575 // get everything we need from the one function call, so try 4576 // that first, and see if we can get all the function pointers 4577 // necessary from that one call. 4578 if (NULL != negotiate_interface) { 4579 layer_prop->functions.negotiate_layer_interface = negotiate_interface; 4580 4581 VkNegotiateLayerInterface interface_struct; 4582 4583 if (loader_get_layer_interface_version(negotiate_interface, &interface_struct)) { 4584 // Go ahead and set the properties version to the 4585 // correct value. 4586 layer_prop->interface_version = interface_struct.loaderLayerInterfaceVersion; 4587 4588 // If the interface is 2 or newer, we have access to the 4589 // new GetPhysicalDeviceProcAddr function, so grab it, 4590 // and the other necessary functions, from the 4591 // structure. 4592 if (interface_struct.loaderLayerInterfaceVersion > 1) { 4593 cur_gipa = interface_struct.pfnGetInstanceProcAddr; 4594 cur_gdpa = interface_struct.pfnGetDeviceProcAddr; 4595 cur_gpdpa = interface_struct.pfnGetPhysicalDeviceProcAddr; 4596 if (cur_gipa != NULL) { 4597 // We've set the functions, so make sure we 4598 // don't do the unnecessary calls later. 4599 functions_in_interface = true; 4600 } 4601 } 4602 } 4603 } 4604 4605 if (!functions_in_interface) { 4606 if ((cur_gipa = layer_prop->functions.get_instance_proc_addr) == NULL) { 4607 if (layer_prop->functions.str_gipa == NULL || strlen(layer_prop->functions.str_gipa) == 0) { 4608 cur_gipa = 4609 (PFN_vkGetInstanceProcAddr)loader_platform_get_proc_address(lib_handle, "vkGetInstanceProcAddr"); 4610 layer_prop->functions.get_instance_proc_addr = cur_gipa; 4611 4612 if (NULL == cur_gipa) { 4613 loader_log(inst, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_LAYER_BIT, 0, 4614 "loader_create_instance_chain: Failed to find \'vkGetInstanceProcAddr\' in layer \"%s\"", 4615 layer_prop->lib_name); 4616 continue; 4617 } 4618 } else { 4619 cur_gipa = (PFN_vkGetInstanceProcAddr)loader_platform_get_proc_address(lib_handle, 4620 layer_prop->functions.str_gipa); 4621 4622 if (NULL == cur_gipa) { 4623 loader_log(inst, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_LAYER_BIT, 0, 4624 "loader_create_instance_chain: Failed to find \'%s\' in layer \"%s\"", 4625 layer_prop->functions.str_gipa, layer_prop->lib_name); 4626 continue; 4627 } 4628 } 4629 } 4630 } 4631 } 4632 4633 layer_instance_link_info[num_activated_layers].pNext = chain_info.u.pLayerInfo; 4634 layer_instance_link_info[num_activated_layers].pfnNextGetInstanceProcAddr = next_gipa; 4635 layer_instance_link_info[num_activated_layers].pfnNextGetPhysicalDeviceProcAddr = next_gpdpa; 4636 next_gipa = cur_gipa; 4637 if (layer_prop->interface_version > 1 && cur_gpdpa != NULL) { 4638 layer_prop->functions.get_physical_device_proc_addr = cur_gpdpa; 4639 next_gpdpa = cur_gpdpa; 4640 } 4641 if (layer_prop->interface_version > 1 && cur_gipa != NULL) { 4642 layer_prop->functions.get_instance_proc_addr = cur_gipa; 4643 } 4644 if (layer_prop->interface_version > 1 && cur_gdpa != NULL) { 4645 layer_prop->functions.get_device_proc_addr = cur_gdpa; 4646 } 4647 4648 chain_info.u.pLayerInfo = &layer_instance_link_info[num_activated_layers]; 4649 4650 activated_layers[num_activated_layers].name = layer_prop->info.layerName; 4651 activated_layers[num_activated_layers].manifest = layer_prop->manifest_file_name; 4652 activated_layers[num_activated_layers].library = layer_prop->lib_name; 4653 activated_layers[num_activated_layers].is_implicit = !(layer_prop->type_flags & VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER); 4654 if (activated_layers[num_activated_layers].is_implicit) { 4655 activated_layers[num_activated_layers].disable_env = layer_prop->disable_env_var.name; 4656 } 4657 4658 loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0, "Insert instance layer \"%s\" (%s)", 4659 layer_prop->info.layerName, layer_prop->lib_name); 4660 4661 num_activated_layers++; 4662 } 4663 } 4664 4665 // Make sure each layer requested by the application was actually loaded 4666 for (uint32_t exp = 0; exp < inst->expanded_activated_layer_list.count; ++exp) { 4667 struct loader_layer_properties *exp_layer_prop = inst->expanded_activated_layer_list.list[exp]; 4668 bool found = false; 4669 for (uint32_t act = 0; act < num_activated_layers; ++act) { 4670 if (!strcmp(activated_layers[act].name, exp_layer_prop->info.layerName)) { 4671 found = true; 4672 break; 4673 } 4674 } 4675 // If it wasn't found, we want to at least log an error. However, if it was enabled by the application directly, 4676 // we want to return a bad layer error. 4677 if (!found) { 4678 bool app_requested = false; 4679 for (uint32_t act = 0; act < pCreateInfo->enabledLayerCount; ++act) { 4680 if (!strcmp(pCreateInfo->ppEnabledLayerNames[act], exp_layer_prop->info.layerName)) { 4681 app_requested = true; 4682 break; 4683 } 4684 } 4685 VkFlags log_flag = VULKAN_LOADER_LAYER_BIT; 4686 char ending = '.'; 4687 if (app_requested) { 4688 log_flag |= VULKAN_LOADER_ERROR_BIT; 4689 ending = '!'; 4690 } else { 4691 log_flag |= VULKAN_LOADER_INFO_BIT; 4692 } 4693 switch (exp_layer_prop->lib_status) { 4694 case LOADER_LAYER_LIB_NOT_LOADED: 4695 loader_log(inst, log_flag, 0, "Requested layer \"%s\" was not loaded%c", exp_layer_prop->info.layerName, 4696 ending); 4697 break; 4698 case LOADER_LAYER_LIB_ERROR_WRONG_BIT_TYPE: { 4699 loader_log(inst, log_flag, 0, "Requested layer \"%s\" was wrong bit-type%c", exp_layer_prop->info.layerName, 4700 ending); 4701 break; 4702 } 4703 case LOADER_LAYER_LIB_ERROR_FAILED_TO_LOAD: 4704 loader_log(inst, log_flag, 0, "Requested layer \"%s\" failed to load%c", exp_layer_prop->info.layerName, 4705 ending); 4706 break; 4707 case LOADER_LAYER_LIB_SUCCESS_LOADED: 4708 case LOADER_LAYER_LIB_ERROR_OUT_OF_MEMORY: 4709 // Shouldn't be able to reach this but if it is, best to report a debug 4710 loader_log(inst, log_flag, 0, 4711 "Shouldn't reach this. A valid version of requested layer %s was loaded but was not found in the " 4712 "list of activated layers%c", 4713 exp_layer_prop->info.layerName, ending); 4714 break; 4715 } 4716 if (app_requested) { 4717 return VK_ERROR_LAYER_NOT_PRESENT; 4718 } 4719 } 4720 } 4721 4722 VkLoaderFeatureFlags feature_flags = 0; 4723#if defined(_WIN32) 4724 feature_flags = windows_initialize_dxgi(); 4725#endif 4726 4727 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)next_gipa(*created_instance, "vkCreateInstance"); 4728 if (fpCreateInstance) { 4729 VkLayerInstanceCreateInfo instance_dispatch; 4730 instance_dispatch.sType = VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO; 4731 instance_dispatch.pNext = loader_create_info.pNext; 4732 instance_dispatch.function = VK_LOADER_DATA_CALLBACK; 4733 instance_dispatch.u.pfnSetInstanceLoaderData = vkSetInstanceDispatch; 4734 4735 VkLayerInstanceCreateInfo device_callback; 4736 device_callback.sType = VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO; 4737 device_callback.pNext = &instance_dispatch; 4738 device_callback.function = VK_LOADER_LAYER_CREATE_DEVICE_CALLBACK; 4739 device_callback.u.layerDevice.pfnLayerCreateDevice = loader_layer_create_device; 4740 device_callback.u.layerDevice.pfnLayerDestroyDevice = loader_layer_destroy_device; 4741 4742 VkLayerInstanceCreateInfo loader_features; 4743 loader_features.sType = VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO; 4744 loader_features.pNext = &device_callback; 4745 loader_features.function = VK_LOADER_FEATURES; 4746 loader_features.u.loaderFeatures = feature_flags; 4747 4748 loader_create_info.pNext = &loader_features; 4749 4750 // If layer debugging is enabled, let's print out the full callstack with layers in their 4751 // defined order. 4752 loader_log(inst, VULKAN_LOADER_LAYER_BIT, 0, "vkCreateInstance layer callstack setup to:"); 4753 loader_log(inst, VULKAN_LOADER_LAYER_BIT, 0, " <Application>"); 4754 loader_log(inst, VULKAN_LOADER_LAYER_BIT, 0, " ||"); 4755 loader_log(inst, VULKAN_LOADER_LAYER_BIT, 0, " <Loader>"); 4756 loader_log(inst, VULKAN_LOADER_LAYER_BIT, 0, " ||"); 4757 for (uint32_t cur_layer = 0; cur_layer < num_activated_layers; ++cur_layer) { 4758 uint32_t index = num_activated_layers - cur_layer - 1; 4759 loader_log(inst, VULKAN_LOADER_LAYER_BIT, 0, " %s", activated_layers[index].name); 4760 loader_log(inst, VULKAN_LOADER_LAYER_BIT, 0, " Type: %s", 4761 activated_layers[index].is_implicit ? "Implicit" : "Explicit"); 4762 if (activated_layers[index].is_implicit) { 4763 loader_log(inst, VULKAN_LOADER_LAYER_BIT, 0, " Disable Env Var: %s", 4764 activated_layers[index].disable_env); 4765 } 4766 loader_log(inst, VULKAN_LOADER_LAYER_BIT, 0, " Manifest: %s", activated_layers[index].manifest); 4767 loader_log(inst, VULKAN_LOADER_LAYER_BIT, 0, " Library: %s", activated_layers[index].library); 4768 loader_log(inst, VULKAN_LOADER_LAYER_BIT, 0, " ||"); 4769 } 4770 loader_log(inst, VULKAN_LOADER_LAYER_BIT, 0, " <Drivers>"); 4771 4772 res = fpCreateInstance(&loader_create_info, pAllocator, created_instance); 4773 } else { 4774 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_create_instance_chain: Failed to find \'vkCreateInstance\'"); 4775 // Couldn't find CreateInstance function! 4776 res = VK_ERROR_INITIALIZATION_FAILED; 4777 } 4778 4779 if (res == VK_SUCCESS) { 4780 // Copy the current disp table into the terminator_dispatch table so we can use it in loader_gpa_instance_terminator() 4781 memcpy(&inst->terminator_dispatch, &inst->disp->layer_inst_disp, sizeof(VkLayerInstanceDispatchTable)); 4782 4783 loader_init_instance_core_dispatch_table(&inst->disp->layer_inst_disp, next_gipa, *created_instance); 4784 inst->instance = *created_instance; 4785 4786 if (pCreateInfo->enabledLayerCount > 0 && pCreateInfo->ppEnabledLayerNames != NULL) { 4787 res = create_string_list(inst, pCreateInfo->enabledLayerCount, &inst->enabled_layer_names); 4788 if (res != VK_SUCCESS) { 4789 return res; 4790 } 4791 4792 for (uint32_t i = 0; i < pCreateInfo->enabledLayerCount; ++i) { 4793 res = copy_str_to_string_list(inst, &inst->enabled_layer_names, pCreateInfo->ppEnabledLayerNames[i], 4794 strlen(pCreateInfo->ppEnabledLayerNames[i])); 4795 if (res != VK_SUCCESS) return res; 4796 } 4797 } 4798 } 4799 4800 return res; 4801} 4802 4803void loader_activate_instance_layer_extensions(struct loader_instance *inst, VkInstance created_inst) { 4804 loader_init_instance_extension_dispatch_table(&inst->disp->layer_inst_disp, inst->disp->layer_inst_disp.GetInstanceProcAddr, 4805 created_inst); 4806} 4807 4808#if defined(__APPLE__) 4809VkResult loader_create_device_chain(const VkPhysicalDevice pd, const VkDeviceCreateInfo *pCreateInfo, 4810 const VkAllocationCallbacks *pAllocator, const struct loader_instance *inst, 4811 struct loader_device *dev, PFN_vkGetInstanceProcAddr callingLayer, 4812 PFN_vkGetDeviceProcAddr *layerNextGDPA) __attribute__((optnone)) { 4813#else 4814VkResult loader_create_device_chain(const VkPhysicalDevice pd, const VkDeviceCreateInfo *pCreateInfo, 4815 const VkAllocationCallbacks *pAllocator, const struct loader_instance *inst, 4816 struct loader_device *dev, PFN_vkGetInstanceProcAddr callingLayer, 4817 PFN_vkGetDeviceProcAddr *layerNextGDPA) { 4818#endif 4819 uint32_t num_activated_layers = 0; 4820 struct activated_layer_info *activated_layers = NULL; 4821 VkLayerDeviceLink *layer_device_link_info; 4822 VkLayerDeviceCreateInfo chain_info; 4823 VkDeviceCreateInfo loader_create_info; 4824 VkDeviceGroupDeviceCreateInfo *original_device_group_create_info_struct = NULL; 4825 VkResult res; 4826 4827 PFN_vkGetDeviceProcAddr fpGDPA = NULL, nextGDPA = loader_gpa_device_terminator; 4828 PFN_vkGetInstanceProcAddr fpGIPA = NULL, nextGIPA = loader_gpa_instance_terminator; 4829 4830 memcpy(&loader_create_info, pCreateInfo, sizeof(VkDeviceCreateInfo)); 4831 4832 if (loader_create_info.enabledLayerCount > 0 && loader_create_info.ppEnabledLayerNames != NULL) { 4833 bool invalid_device_layer_usage = false; 4834 4835 if (loader_create_info.enabledLayerCount != inst->enabled_layer_names.count && loader_create_info.enabledLayerCount > 0) { 4836 invalid_device_layer_usage = true; 4837 } else if (loader_create_info.enabledLayerCount > 0 && loader_create_info.ppEnabledLayerNames == NULL) { 4838 invalid_device_layer_usage = true; 4839 } else if (loader_create_info.enabledLayerCount == 0 && loader_create_info.ppEnabledLayerNames != NULL) { 4840 invalid_device_layer_usage = true; 4841 } else if (inst->enabled_layer_names.list != NULL) { 4842 for (uint32_t i = 0; i < loader_create_info.enabledLayerCount; i++) { 4843 const char *device_layer_names = loader_create_info.ppEnabledLayerNames[i]; 4844 4845 if (strcmp(device_layer_names, inst->enabled_layer_names.list[i]) != 0) { 4846 invalid_device_layer_usage = true; 4847 break; 4848 } 4849 } 4850 } 4851 4852 if (invalid_device_layer_usage) { 4853 loader_log( 4854 inst, VULKAN_LOADER_WARN_BIT, 0, 4855 "loader_create_device_chain: Using deprecated and ignored 'ppEnabledLayerNames' member of 'VkDeviceCreateInfo' " 4856 "when creating a Vulkan device."); 4857 } 4858 } 4859 4860 // Before we continue, we need to find out if the KHR_device_group extension is in the enabled list. If it is, we then 4861 // need to look for the corresponding VkDeviceGroupDeviceCreateInfo struct in the device list. This is because we 4862 // need to replace all the incoming physical device values (which are really loader trampoline physical device values) 4863 // with the layer/ICD version. 4864 { 4865 VkBaseOutStructure *pNext = (VkBaseOutStructure *)loader_create_info.pNext; 4866 VkBaseOutStructure *pPrev = (VkBaseOutStructure *)&loader_create_info; 4867 while (NULL != pNext) { 4868 if (VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO == pNext->sType) { 4869 VkDeviceGroupDeviceCreateInfo *cur_struct = (VkDeviceGroupDeviceCreateInfo *)pNext; 4870 if (0 < cur_struct->physicalDeviceCount && NULL != cur_struct->pPhysicalDevices) { 4871 VkDeviceGroupDeviceCreateInfo *temp_struct = loader_stack_alloc(sizeof(VkDeviceGroupDeviceCreateInfo)); 4872 VkPhysicalDevice *phys_dev_array = NULL; 4873 if (NULL == temp_struct) { 4874 return VK_ERROR_OUT_OF_HOST_MEMORY; 4875 } 4876 memcpy(temp_struct, cur_struct, sizeof(VkDeviceGroupDeviceCreateInfo)); 4877 phys_dev_array = loader_stack_alloc(sizeof(VkPhysicalDevice) * cur_struct->physicalDeviceCount); 4878 if (NULL == phys_dev_array) { 4879 return VK_ERROR_OUT_OF_HOST_MEMORY; 4880 } 4881 4882 // Before calling down, replace the incoming physical device values (which are really loader trampoline 4883 // physical devices) with the next layer (or possibly even the terminator) physical device values. 4884 struct loader_physical_device_tramp *cur_tramp; 4885 for (uint32_t phys_dev = 0; phys_dev < cur_struct->physicalDeviceCount; phys_dev++) { 4886 cur_tramp = (struct loader_physical_device_tramp *)cur_struct->pPhysicalDevices[phys_dev]; 4887 phys_dev_array[phys_dev] = cur_tramp->phys_dev; 4888 } 4889 temp_struct->pPhysicalDevices = phys_dev_array; 4890 4891 original_device_group_create_info_struct = (VkDeviceGroupDeviceCreateInfo *)pPrev->pNext; 4892 4893 // Replace the old struct in the pNext chain with this one. 4894 pPrev->pNext = (VkBaseOutStructure *)temp_struct; 4895 } 4896 break; 4897 } 4898 4899 pPrev = pNext; 4900 pNext = pNext->pNext; 4901 } 4902 } 4903 if (inst->expanded_activated_layer_list.count > 0) { 4904 layer_device_link_info = loader_stack_alloc(sizeof(VkLayerDeviceLink) * inst->expanded_activated_layer_list.count); 4905 if (!layer_device_link_info) { 4906 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 4907 "loader_create_device_chain: Failed to alloc Device objects for layer. Skipping Layer."); 4908 return VK_ERROR_OUT_OF_HOST_MEMORY; 4909 } 4910 4911 activated_layers = loader_stack_alloc(sizeof(struct activated_layer_info) * inst->expanded_activated_layer_list.count); 4912 if (!activated_layers) { 4913 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 4914 "loader_create_device_chain: Failed to alloc activated layer storage array"); 4915 return VK_ERROR_OUT_OF_HOST_MEMORY; 4916 } 4917 4918 chain_info.sType = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO; 4919 chain_info.function = VK_LAYER_LINK_INFO; 4920 chain_info.u.pLayerInfo = NULL; 4921 chain_info.pNext = loader_create_info.pNext; 4922 loader_create_info.pNext = &chain_info; 4923 4924 // Create instance chain of enabled layers 4925 for (int32_t i = inst->expanded_activated_layer_list.count - 1; i >= 0; i--) { 4926 struct loader_layer_properties *layer_prop = inst->expanded_activated_layer_list.list[i]; 4927 loader_platform_dl_handle lib_handle = layer_prop->lib_handle; 4928 4929 // Skip it if a Layer with the same name has been already successfully activated 4930 if (loader_names_array_has_layer_property(&layer_prop->info, num_activated_layers, activated_layers)) { 4931 continue; 4932 } 4933 4934 // Skip the layer if the handle is NULL - this is likely because the library failed to load but wasn't removed from 4935 // the list. 4936 if (!lib_handle) { 4937 continue; 4938 } 4939 4940 // The Get*ProcAddr pointers will already be filled in if they were received from either the json file or the 4941 // version negotiation 4942 if ((fpGIPA = layer_prop->functions.get_instance_proc_addr) == NULL) { 4943 if (layer_prop->functions.str_gipa == NULL || strlen(layer_prop->functions.str_gipa) == 0) { 4944 fpGIPA = (PFN_vkGetInstanceProcAddr)loader_platform_get_proc_address(lib_handle, "vkGetInstanceProcAddr"); 4945 layer_prop->functions.get_instance_proc_addr = fpGIPA; 4946 } else 4947 fpGIPA = 4948 (PFN_vkGetInstanceProcAddr)loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gipa); 4949 if (!fpGIPA) { 4950 loader_log(inst, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_LAYER_BIT, 0, 4951 "loader_create_device_chain: Failed to find \'vkGetInstanceProcAddr\' in layer \"%s\". " 4952 "Skipping layer.", 4953 layer_prop->lib_name); 4954 continue; 4955 } 4956 } 4957 4958 if (fpGIPA == callingLayer) { 4959 if (layerNextGDPA != NULL) { 4960 *layerNextGDPA = nextGDPA; 4961 } 4962 // Break here because if fpGIPA is the same as callingLayer, that means a layer is trying to create a device, 4963 // and once we don't want to continue any further as the next layer will be the calling layer 4964 break; 4965 } 4966 4967 if ((fpGDPA = layer_prop->functions.get_device_proc_addr) == NULL) { 4968 if (layer_prop->functions.str_gdpa == NULL || strlen(layer_prop->functions.str_gdpa) == 0) { 4969 fpGDPA = (PFN_vkGetDeviceProcAddr)loader_platform_get_proc_address(lib_handle, "vkGetDeviceProcAddr"); 4970 layer_prop->functions.get_device_proc_addr = fpGDPA; 4971 } else 4972 fpGDPA = (PFN_vkGetDeviceProcAddr)loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gdpa); 4973 if (!fpGDPA) { 4974 loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0, 4975 "Failed to find vkGetDeviceProcAddr in layer \"%s\"", layer_prop->lib_name); 4976 continue; 4977 } 4978 } 4979 4980 layer_device_link_info[num_activated_layers].pNext = chain_info.u.pLayerInfo; 4981 layer_device_link_info[num_activated_layers].pfnNextGetInstanceProcAddr = nextGIPA; 4982 layer_device_link_info[num_activated_layers].pfnNextGetDeviceProcAddr = nextGDPA; 4983 chain_info.u.pLayerInfo = &layer_device_link_info[num_activated_layers]; 4984 nextGIPA = fpGIPA; 4985 nextGDPA = fpGDPA; 4986 4987 activated_layers[num_activated_layers].name = layer_prop->info.layerName; 4988 activated_layers[num_activated_layers].manifest = layer_prop->manifest_file_name; 4989 activated_layers[num_activated_layers].library = layer_prop->lib_name; 4990 activated_layers[num_activated_layers].is_implicit = !(layer_prop->type_flags & VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER); 4991 if (activated_layers[num_activated_layers].is_implicit) { 4992 activated_layers[num_activated_layers].disable_env = layer_prop->disable_env_var.name; 4993 } 4994 4995 loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0, "Inserted device layer \"%s\" (%s)", 4996 layer_prop->info.layerName, layer_prop->lib_name); 4997 4998 num_activated_layers++; 4999 } 5000 } 5001 5002 VkDevice created_device = (VkDevice)dev; 5003 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)nextGIPA(inst->instance, "vkCreateDevice"); 5004 if (fpCreateDevice) { 5005 VkLayerDeviceCreateInfo create_info_disp; 5006 5007 create_info_disp.sType = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO; 5008 create_info_disp.function = VK_LOADER_DATA_CALLBACK; 5009 5010 create_info_disp.u.pfnSetDeviceLoaderData = vkSetDeviceDispatch; 5011 5012 // If layer debugging is enabled, let's print out the full callstack with layers in their 5013 // defined order. 5014 uint32_t layer_driver_bits = VULKAN_LOADER_LAYER_BIT | VULKAN_LOADER_DRIVER_BIT; 5015 loader_log(inst, layer_driver_bits, 0, "vkCreateDevice layer callstack setup to:"); 5016 loader_log(inst, layer_driver_bits, 0, " <Application>"); 5017 loader_log(inst, layer_driver_bits, 0, " ||"); 5018 loader_log(inst, layer_driver_bits, 0, " <Loader>"); 5019 loader_log(inst, layer_driver_bits, 0, " ||"); 5020 for (uint32_t cur_layer = 0; cur_layer < num_activated_layers; ++cur_layer) { 5021 uint32_t index = num_activated_layers - cur_layer - 1; 5022 loader_log(inst, VULKAN_LOADER_LAYER_BIT, 0, " %s", activated_layers[index].name); 5023 loader_log(inst, VULKAN_LOADER_LAYER_BIT, 0, " Type: %s", 5024 activated_layers[index].is_implicit ? "Implicit" : "Explicit"); 5025 if (activated_layers[index].is_implicit) { 5026 loader_log(inst, VULKAN_LOADER_LAYER_BIT, 0, " Disable Env Var: %s", 5027 activated_layers[index].disable_env); 5028 } 5029 loader_log(inst, VULKAN_LOADER_LAYER_BIT, 0, " Manifest: %s", activated_layers[index].manifest); 5030 loader_log(inst, VULKAN_LOADER_LAYER_BIT, 0, " Library: %s", activated_layers[index].library); 5031 loader_log(inst, VULKAN_LOADER_LAYER_BIT, 0, " ||"); 5032 } 5033 loader_log(inst, layer_driver_bits, 0, " <Device>"); 5034 create_info_disp.pNext = loader_create_info.pNext; 5035 loader_create_info.pNext = &create_info_disp; 5036 res = fpCreateDevice(pd, &loader_create_info, pAllocator, &created_device); 5037 if (res != VK_SUCCESS) { 5038 return res; 5039 } 5040 dev->chain_device = created_device; 5041 5042 // Because we changed the pNext chain to use our own VkDeviceGroupDeviceCreateInfo, we need to fixup the chain to 5043 // point back at the original VkDeviceGroupDeviceCreateInfo. 5044 VkBaseOutStructure *pNext = (VkBaseOutStructure *)loader_create_info.pNext; 5045 VkBaseOutStructure *pPrev = (VkBaseOutStructure *)&loader_create_info; 5046 while (NULL != pNext) { 5047 if (VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO == pNext->sType) { 5048 VkDeviceGroupDeviceCreateInfo *cur_struct = (VkDeviceGroupDeviceCreateInfo *)pNext; 5049 if (0 < cur_struct->physicalDeviceCount && NULL != cur_struct->pPhysicalDevices) { 5050 pPrev->pNext = (VkBaseOutStructure *)original_device_group_create_info_struct; 5051 } 5052 break; 5053 } 5054 5055 pPrev = pNext; 5056 pNext = pNext->pNext; 5057 } 5058 5059 } else { 5060 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 5061 "loader_create_device_chain: Failed to find \'vkCreateDevice\' in layers or ICD"); 5062 // Couldn't find CreateDevice function! 5063 return VK_ERROR_INITIALIZATION_FAILED; 5064 } 5065 5066 // Initialize device dispatch table 5067 loader_init_device_dispatch_table(&dev->loader_dispatch, nextGDPA, dev->chain_device); 5068 // Initialize the dispatch table to functions which need terminators 5069 // These functions point directly to the driver, not the terminator functions 5070 init_extension_device_proc_terminator_dispatch(dev); 5071 5072 return res; 5073} 5074 5075VkResult loader_validate_layers(const struct loader_instance *inst, const uint32_t layer_count, 5076 const char *const *ppEnabledLayerNames, const struct loader_layer_list *list) { 5077 struct loader_layer_properties *prop; 5078 5079 if (layer_count > 0 && ppEnabledLayerNames == NULL) { 5080 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 5081 "loader_validate_layers: ppEnabledLayerNames is NULL but enabledLayerCount is greater than zero"); 5082 return VK_ERROR_LAYER_NOT_PRESENT; 5083 } 5084 5085 for (uint32_t i = 0; i < layer_count; i++) { 5086 VkStringErrorFlags result = vk_string_validate(MaxLoaderStringLength, ppEnabledLayerNames[i]); 5087 if (result != VK_STRING_ERROR_NONE) { 5088 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 5089 "loader_validate_layers: ppEnabledLayerNames contains string that is too long or is badly formed"); 5090 return VK_ERROR_LAYER_NOT_PRESENT; 5091 } 5092 5093 prop = loader_find_layer_property(ppEnabledLayerNames[i], list); 5094 if (NULL == prop) { 5095 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 5096 "loader_validate_layers: Layer %d does not exist in the list of available layers", i); 5097 return VK_ERROR_LAYER_NOT_PRESENT; 5098 } 5099 if (inst->settings.settings_active && prop->settings_control_value != LOADER_SETTINGS_LAYER_CONTROL_ON && 5100 prop->settings_control_value != LOADER_SETTINGS_LAYER_CONTROL_DEFAULT) { 5101 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 5102 "loader_validate_layers: Layer %d was explicitly prevented from being enabled by the loader settings file", 5103 i); 5104 return VK_ERROR_LAYER_NOT_PRESENT; 5105 } 5106 } 5107 return VK_SUCCESS; 5108} 5109 5110VkResult loader_validate_instance_extensions(struct loader_instance *inst, const struct loader_extension_list *icd_exts, 5111 const struct loader_layer_list *instance_layers, 5112 const struct loader_envvar_all_filters *layer_filters, 5113 const VkInstanceCreateInfo *pCreateInfo) { 5114 VkExtensionProperties *extension_prop; 5115 char *env_value; 5116 bool check_if_known = true; 5117 VkResult res = VK_SUCCESS; 5118 5119 struct loader_pointer_layer_list active_layers = {0}; 5120 struct loader_pointer_layer_list expanded_layers = {0}; 5121 5122 if (pCreateInfo->enabledExtensionCount > 0 && pCreateInfo->ppEnabledExtensionNames == NULL) { 5123 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 5124 "loader_validate_instance_extensions: Instance ppEnabledExtensionNames is NULL but enabledExtensionCount is " 5125 "greater than zero"); 5126 return VK_ERROR_EXTENSION_NOT_PRESENT; 5127 } 5128 if (!loader_init_pointer_layer_list(inst, &active_layers)) { 5129 res = VK_ERROR_OUT_OF_HOST_MEMORY; 5130 goto out; 5131 } 5132 if (!loader_init_pointer_layer_list(inst, &expanded_layers)) { 5133 res = VK_ERROR_OUT_OF_HOST_MEMORY; 5134 goto out; 5135 } 5136 5137 if (inst->settings.settings_active) { 5138 res = enable_correct_layers_from_settings(inst, layer_filters, pCreateInfo->enabledLayerCount, 5139 pCreateInfo->ppEnabledLayerNames, instance_layers, &active_layers, 5140 &expanded_layers); 5141 if (res != VK_SUCCESS) { 5142 goto out; 5143 } 5144 } else { 5145 // Build the lists of active layers (including meta layers) and expanded layers (with meta layers resolved to their 5146 // components) 5147 res = loader_add_implicit_layers(inst, layer_filters, &active_layers, &expanded_layers, instance_layers); 5148 if (res != VK_SUCCESS) { 5149 goto out; 5150 } 5151 res = loader_add_environment_layers(inst, VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER, layer_filters, &active_layers, 5152 &expanded_layers, instance_layers); 5153 if (res != VK_SUCCESS) { 5154 goto out; 5155 } 5156 res = loader_add_layer_names_to_list(inst, layer_filters, &active_layers, &expanded_layers, pCreateInfo->enabledLayerCount, 5157 pCreateInfo->ppEnabledLayerNames, instance_layers); 5158 if (VK_SUCCESS != res) { 5159 goto out; 5160 } 5161 } 5162 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) { 5163 VkStringErrorFlags result = vk_string_validate(MaxLoaderStringLength, pCreateInfo->ppEnabledExtensionNames[i]); 5164 if (result != VK_STRING_ERROR_NONE) { 5165 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 5166 "loader_validate_instance_extensions: Instance ppEnabledExtensionNames contains " 5167 "string that is too long or is badly formed"); 5168 res = VK_ERROR_EXTENSION_NOT_PRESENT; 5169 goto out; 5170 } 5171 5172 // Check if a user wants to disable the instance extension filtering behavior 5173 env_value = loader_getenv("VK_LOADER_DISABLE_INST_EXT_FILTER", inst); 5174 if (NULL != env_value && atoi(env_value) != 0) { 5175 check_if_known = false; 5176 } 5177 loader_free_getenv(env_value, inst); 5178 5179 if (check_if_known) { 5180 // See if the extension is in the list of supported extensions 5181 bool found = false; 5182 for (uint32_t j = 0; LOADER_INSTANCE_EXTENSIONS[j] != NULL; j++) { 5183 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], LOADER_INSTANCE_EXTENSIONS[j]) == 0) { 5184 found = true; 5185 break; 5186 } 5187 } 5188 5189 // If it isn't in the list, return an error 5190 if (!found) { 5191 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 5192 "loader_validate_instance_extensions: Extension %s not found in list of known instance extensions.", 5193 pCreateInfo->ppEnabledExtensionNames[i]); 5194 res = VK_ERROR_EXTENSION_NOT_PRESENT; 5195 goto out; 5196 } 5197 } 5198 5199 extension_prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i], icd_exts); 5200 5201 if (extension_prop) { 5202 continue; 5203 } 5204 5205 extension_prop = NULL; 5206 5207 // Not in global list, search layer extension lists 5208 for (uint32_t j = 0; NULL == extension_prop && j < expanded_layers.count; ++j) { 5209 extension_prop = 5210 get_extension_property(pCreateInfo->ppEnabledExtensionNames[i], &expanded_layers.list[j]->instance_extension_list); 5211 if (extension_prop) { 5212 // Found the extension in one of the layers enabled by the app. 5213 break; 5214 } 5215 5216 struct loader_layer_properties *layer_prop = 5217 loader_find_layer_property(expanded_layers.list[j]->info.layerName, instance_layers); 5218 if (NULL == layer_prop) { 5219 // Should NOT get here, loader_validate_layers should have already filtered this case out. 5220 continue; 5221 } 5222 } 5223 5224 if (!extension_prop) { 5225 // Didn't find extension name in any of the global layers, error out 5226 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 5227 "loader_validate_instance_extensions: Instance extension %s not supported by available ICDs or enabled " 5228 "layers.", 5229 pCreateInfo->ppEnabledExtensionNames[i]); 5230 res = VK_ERROR_EXTENSION_NOT_PRESENT; 5231 goto out; 5232 } 5233 } 5234 5235out: 5236 loader_destroy_pointer_layer_list(inst, &active_layers); 5237 loader_destroy_pointer_layer_list(inst, &expanded_layers); 5238 return res; 5239} 5240 5241VkResult loader_validate_device_extensions(struct loader_instance *this_instance, 5242 const struct loader_pointer_layer_list *activated_device_layers, 5243 const struct loader_extension_list *icd_exts, const VkDeviceCreateInfo *pCreateInfo) { 5244 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) { 5245 VkStringErrorFlags result = vk_string_validate(MaxLoaderStringLength, pCreateInfo->ppEnabledExtensionNames[i]); 5246 if (result != VK_STRING_ERROR_NONE) { 5247 loader_log(this_instance, VULKAN_LOADER_ERROR_BIT, 0, 5248 "loader_validate_device_extensions: Device ppEnabledExtensionNames contains " 5249 "string that is too long or is badly formed"); 5250 return VK_ERROR_EXTENSION_NOT_PRESENT; 5251 } 5252 5253 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i]; 5254 VkExtensionProperties *extension_prop = get_extension_property(extension_name, icd_exts); 5255 5256 if (extension_prop) { 5257 continue; 5258 } 5259 5260 // Not in global list, search activated layer extension lists 5261 for (uint32_t j = 0; j < activated_device_layers->count; j++) { 5262 struct loader_layer_properties *layer_prop = activated_device_layers->list[j]; 5263 5264 extension_prop = get_dev_extension_property(extension_name, &layer_prop->device_extension_list); 5265 if (extension_prop) { 5266 // Found the extension in one of the layers enabled by the app. 5267 break; 5268 } 5269 } 5270 5271 if (!extension_prop) { 5272 // Didn't find extension name in any of the device layers, error out 5273 loader_log(this_instance, VULKAN_LOADER_ERROR_BIT, 0, 5274 "loader_validate_device_extensions: Device extension %s not supported by selected physical device " 5275 "or enabled layers.", 5276 pCreateInfo->ppEnabledExtensionNames[i]); 5277 return VK_ERROR_EXTENSION_NOT_PRESENT; 5278 } 5279 } 5280 return VK_SUCCESS; 5281} 5282 5283// Terminator functions for the Instance chain 5284// All named terminator_<Vulkan API name> 5285VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateInstance(const VkInstanceCreateInfo *pCreateInfo, 5286 const VkAllocationCallbacks *pAllocator, VkInstance *pInstance) { 5287 struct loader_icd_term *icd_term; 5288 VkExtensionProperties *prop; 5289 char **filtered_extension_names = NULL; 5290 VkInstanceCreateInfo icd_create_info; 5291 VkResult res = VK_SUCCESS; 5292 bool one_icd_successful = false; 5293 5294 struct loader_instance *ptr_instance = (struct loader_instance *)*pInstance; 5295 if (NULL == ptr_instance) { 5296 loader_log(ptr_instance, VULKAN_LOADER_WARN_BIT, 0, 5297 "terminator_CreateInstance: Loader instance pointer null encountered. Possibly set by active layer. (Policy " 5298 "#LLP_LAYER_21)"); 5299 } else if (LOADER_MAGIC_NUMBER != ptr_instance->magic) { 5300 loader_log(ptr_instance, VULKAN_LOADER_WARN_BIT, 0, 5301 "terminator_CreateInstance: Instance pointer (%p) has invalid MAGIC value 0x%08lx. Instance value possibly " 5302 "corrupted by active layer (Policy #LLP_LAYER_21). ", 5303 ptr_instance, ptr_instance->magic); 5304 } 5305 5306 // Save the application version if it has been modified - layers sometimes needs features in newer API versions than 5307 // what the application requested, and thus will increase the instance version to a level that suites their needs. 5308 if (pCreateInfo->pApplicationInfo && pCreateInfo->pApplicationInfo->apiVersion) { 5309 loader_api_version altered_version = loader_make_version(pCreateInfo->pApplicationInfo->apiVersion); 5310 if (altered_version.major != ptr_instance->app_api_version.major || 5311 altered_version.minor != ptr_instance->app_api_version.minor) { 5312 ptr_instance->app_api_version = altered_version; 5313 } 5314 } 5315 5316 memcpy(&icd_create_info, pCreateInfo, sizeof(icd_create_info)); 5317 5318 icd_create_info.enabledLayerCount = 0; 5319 icd_create_info.ppEnabledLayerNames = NULL; 5320 5321 // NOTE: Need to filter the extensions to only those supported by the ICD. 5322 // No ICD will advertise support for layers. An ICD library could 5323 // support a layer, but it would be independent of the actual ICD, 5324 // just in the same library. 5325 uint32_t extension_count = pCreateInfo->enabledExtensionCount; 5326#if defined(LOADER_ENABLE_LINUX_SORT) 5327 extension_count += 1; 5328#endif // LOADER_ENABLE_LINUX_SORT 5329 filtered_extension_names = loader_stack_alloc(extension_count * sizeof(char *)); 5330 if (!filtered_extension_names) { 5331 loader_log(ptr_instance, VULKAN_LOADER_ERROR_BIT, 0, 5332 "terminator_CreateInstance: Failed create extension name array for %d extensions", extension_count); 5333 res = VK_ERROR_OUT_OF_HOST_MEMORY; 5334 goto out; 5335 } 5336 icd_create_info.ppEnabledExtensionNames = (const char *const *)filtered_extension_names; 5337 5338 // Determine if Get Physical Device Properties 2 is available to this Instance 5339 if (pCreateInfo->pApplicationInfo && pCreateInfo->pApplicationInfo->apiVersion >= VK_API_VERSION_1_1) { 5340 ptr_instance->supports_get_dev_prop_2 = true; 5341 } else { 5342 for (uint32_t j = 0; j < pCreateInfo->enabledExtensionCount; j++) { 5343 if (!strcmp(pCreateInfo->ppEnabledExtensionNames[j], VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { 5344 ptr_instance->supports_get_dev_prop_2 = true; 5345 break; 5346 } 5347 } 5348 } 5349 5350 for (uint32_t i = 0; i < ptr_instance->icd_tramp_list.count; i++) { 5351 icd_term = loader_icd_add(ptr_instance, &ptr_instance->icd_tramp_list.scanned_list[i]); 5352 if (NULL == icd_term) { 5353 loader_log(ptr_instance, VULKAN_LOADER_ERROR_BIT, 0, 5354 "terminator_CreateInstance: Failed to add ICD %d to ICD trampoline list.", i); 5355 res = VK_ERROR_OUT_OF_HOST_MEMORY; 5356 goto out; 5357 } 5358 5359 // If any error happens after here, we need to remove the ICD from the list, 5360 // because we've already added it, but haven't validated it 5361 5362 // Make sure that we reset the pApplicationInfo so we don't get an old pointer 5363 icd_create_info.pApplicationInfo = pCreateInfo->pApplicationInfo; 5364 icd_create_info.enabledExtensionCount = 0; 5365 struct loader_extension_list icd_exts = {0}; 5366 5367 // traverse scanned icd list adding non-duplicate extensions to the list 5368 res = loader_init_generic_list(ptr_instance, (struct loader_generic_list *)&icd_exts, sizeof(VkExtensionProperties)); 5369 if (VK_ERROR_OUT_OF_HOST_MEMORY == res) { 5370 // If out of memory, bail immediately. 5371 goto out; 5372 } else if (VK_SUCCESS != res) { 5373 // Something bad happened with this ICD, so free it and try the 5374 // next. 5375 ptr_instance->icd_terms = icd_term->next; 5376 icd_term->next = NULL; 5377 loader_icd_destroy(ptr_instance, icd_term, pAllocator); 5378 continue; 5379 } 5380 5381 res = loader_add_instance_extensions(ptr_instance, icd_term->scanned_icd->EnumerateInstanceExtensionProperties, 5382 icd_term->scanned_icd->lib_name, &icd_exts); 5383 if (VK_SUCCESS != res) { 5384 loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *)&icd_exts); 5385 if (VK_ERROR_OUT_OF_HOST_MEMORY == res) { 5386 // If out of memory, bail immediately. 5387 goto out; 5388 } else { 5389 // Something bad happened with this ICD, so free it and try the next. 5390 ptr_instance->icd_terms = icd_term->next; 5391 icd_term->next = NULL; 5392 loader_icd_destroy(ptr_instance, icd_term, pAllocator); 5393 continue; 5394 } 5395 } 5396 5397 for (uint32_t j = 0; j < pCreateInfo->enabledExtensionCount; j++) { 5398 prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[j], &icd_exts); 5399 if (prop) { 5400 filtered_extension_names[icd_create_info.enabledExtensionCount] = (char *)pCreateInfo->ppEnabledExtensionNames[j]; 5401 icd_create_info.enabledExtensionCount++; 5402 } 5403 } 5404#if defined(LOADER_ENABLE_LINUX_SORT) 5405 // Force on "VK_KHR_get_physical_device_properties2" for Linux as we use it for GPU sorting. This 5406 // should be done if the API version of either the application or the driver does not natively support 5407 // the core version of vkGetPhysicalDeviceProperties2 entrypoint. 5408 if ((ptr_instance->app_api_version.major == 1 && ptr_instance->app_api_version.minor == 0) || 5409 (VK_API_VERSION_MAJOR(icd_term->scanned_icd->api_version) == 1 && 5410 VK_API_VERSION_MINOR(icd_term->scanned_icd->api_version) == 0)) { 5411 prop = get_extension_property(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, &icd_exts); 5412 if (prop) { 5413 filtered_extension_names[icd_create_info.enabledExtensionCount] = 5414 (char *)VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME; 5415 icd_create_info.enabledExtensionCount++; 5416 5417 // At least one ICD supports this, so the instance should be able to support it 5418 ptr_instance->supports_get_dev_prop_2 = true; 5419 } 5420 } 5421#endif // LOADER_ENABLE_LINUX_SORT 5422 5423 // Determine if vkGetPhysicalDeviceProperties2 is available to this Instance 5424 if (icd_term->scanned_icd->api_version >= VK_API_VERSION_1_1) { 5425 icd_term->supports_get_dev_prop_2 = true; 5426 } else { 5427 for (uint32_t j = 0; j < icd_create_info.enabledExtensionCount; j++) { 5428 if (!strcmp(filtered_extension_names[j], VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { 5429 icd_term->supports_get_dev_prop_2 = true; 5430 break; 5431 } 5432 } 5433 } 5434 5435 loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *)&icd_exts); 5436 5437 // Get the driver version from vkEnumerateInstanceVersion 5438 uint32_t icd_version = VK_API_VERSION_1_0; 5439 VkResult icd_result = VK_SUCCESS; 5440 if (icd_term->scanned_icd->api_version >= VK_API_VERSION_1_1) { 5441 PFN_vkEnumerateInstanceVersion icd_enumerate_instance_version = 5442 (PFN_vkEnumerateInstanceVersion)icd_term->scanned_icd->GetInstanceProcAddr(NULL, "vkEnumerateInstanceVersion"); 5443 if (icd_enumerate_instance_version != NULL) { 5444 icd_result = icd_enumerate_instance_version(&icd_version); 5445 if (icd_result != VK_SUCCESS) { 5446 icd_version = VK_API_VERSION_1_0; 5447 loader_log(ptr_instance, VULKAN_LOADER_DEBUG_BIT | VULKAN_LOADER_DRIVER_BIT, 0, 5448 "terminator_CreateInstance: ICD \"%s\" vkEnumerateInstanceVersion returned error. The ICD will be " 5449 "treated as a 1.0 ICD", 5450 icd_term->scanned_icd->lib_name); 5451 } else if (VK_API_VERSION_MINOR(icd_version) == 0) { 5452 loader_log(ptr_instance, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0, 5453 "terminator_CreateInstance: Manifest ICD for \"%s\" contained a 1.1 or greater API version, but " 5454 "vkEnumerateInstanceVersion returned 1.0, treating as a 1.0 ICD", 5455 icd_term->scanned_icd->lib_name); 5456 } 5457 } else { 5458 loader_log(ptr_instance, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0, 5459 "terminator_CreateInstance: Manifest ICD for \"%s\" contained a 1.1 or greater API version, but does " 5460 "not support vkEnumerateInstanceVersion, treating as a 1.0 ICD", 5461 icd_term->scanned_icd->lib_name); 5462 } 5463 } 5464 5465 // Remove the portability enumeration flag bit if the ICD doesn't support the extension 5466 if ((pCreateInfo->flags & VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR) == 1) { 5467 bool supports_portability_enumeration = false; 5468 for (uint32_t j = 0; j < icd_create_info.enabledExtensionCount; j++) { 5469 if (strcmp(filtered_extension_names[j], VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME) == 0) { 5470 supports_portability_enumeration = true; 5471 break; 5472 } 5473 } 5474 // If the icd supports the extension, use the flags as given, otherwise remove the portability bit 5475 icd_create_info.flags = supports_portability_enumeration 5476 ? pCreateInfo->flags 5477 : pCreateInfo->flags & (~VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR); 5478 } 5479 5480 // Create an instance, substituting the version to 1.0 if necessary 5481 VkApplicationInfo icd_app_info; 5482 const uint32_t api_variant = 0; 5483 const uint32_t api_version_1_0 = VK_API_VERSION_1_0; 5484 uint32_t icd_version_nopatch = 5485 VK_MAKE_API_VERSION(api_variant, VK_API_VERSION_MAJOR(icd_version), VK_API_VERSION_MINOR(icd_version), 0); 5486 uint32_t requested_version = (pCreateInfo == NULL || pCreateInfo->pApplicationInfo == NULL) 5487 ? api_version_1_0 5488 : pCreateInfo->pApplicationInfo->apiVersion; 5489 if ((requested_version != 0) && (icd_version_nopatch == api_version_1_0)) { 5490 if (icd_create_info.pApplicationInfo == NULL) { 5491 memset(&icd_app_info, 0, sizeof(icd_app_info)); 5492 } else { 5493 memmove(&icd_app_info, icd_create_info.pApplicationInfo, sizeof(icd_app_info)); 5494 } 5495 icd_app_info.apiVersion = icd_version; 5496 icd_create_info.pApplicationInfo = &icd_app_info; 5497 } 5498 icd_result = 5499 ptr_instance->icd_tramp_list.scanned_list[i].CreateInstance(&icd_create_info, pAllocator, &(icd_term->instance)); 5500 if (VK_ERROR_OUT_OF_HOST_MEMORY == icd_result) { 5501 // If out of memory, bail immediately. 5502 res = VK_ERROR_OUT_OF_HOST_MEMORY; 5503 goto out; 5504 } else if (VK_SUCCESS != icd_result) { 5505 loader_log(ptr_instance, VULKAN_LOADER_WARN_BIT, 0, 5506 "terminator_CreateInstance: Received return code %i from call to vkCreateInstance in ICD %s. Skipping " 5507 "this driver.", 5508 icd_result, icd_term->scanned_icd->lib_name); 5509 ptr_instance->icd_terms = icd_term->next; 5510 icd_term->next = NULL; 5511 loader_icd_destroy(ptr_instance, icd_term, pAllocator); 5512 continue; 5513 } 5514 5515 if (!loader_icd_init_entries(ptr_instance, icd_term)) { 5516 loader_log(ptr_instance, VULKAN_LOADER_WARN_BIT, 0, 5517 "terminator_CreateInstance: Failed to find required entrypoints in ICD %s. Skipping this driver.", 5518 icd_term->scanned_icd->lib_name); 5519 ptr_instance->icd_terms = icd_term->next; 5520 icd_term->next = NULL; 5521 loader_icd_destroy(ptr_instance, icd_term, pAllocator); 5522 continue; 5523 } 5524 5525 if (ptr_instance->icd_tramp_list.scanned_list[i].interface_version < 3 && 5526 ( 5527#if defined(VK_USE_PLATFORM_XLIB_KHR) 5528 NULL != icd_term->dispatch.CreateXlibSurfaceKHR || 5529#endif // VK_USE_PLATFORM_XLIB_KHR 5530#if defined(VK_USE_PLATFORM_XCB_KHR) 5531 NULL != icd_term->dispatch.CreateXcbSurfaceKHR || 5532#endif // VK_USE_PLATFORM_XCB_KHR 5533#if defined(VK_USE_PLATFORM_WAYLAND_KHR) 5534 NULL != icd_term->dispatch.CreateWaylandSurfaceKHR || 5535#endif // VK_USE_PLATFORM_WAYLAND_KHR 5536#if defined(VK_USE_PLATFORM_ANDROID_KHR) 5537 NULL != icd_term->dispatch.CreateAndroidSurfaceKHR || 5538#endif // VK_USE_PLATFORM_ANDROID_KHR 5539#if defined(VK_USE_PLATFORM_OHOS) 5540 NULL != icd_term->dispatch.CreateSurfaceOHOS || 5541#endif // VK_USE_PLATFORM_OHOS 5542#if defined(VK_USE_PLATFORM_WIN32_KHR) 5543 NULL != icd_term->dispatch.CreateWin32SurfaceKHR || 5544#endif // VK_USE_PLATFORM_WIN32_KHR 5545 NULL != icd_term->dispatch.DestroySurfaceKHR)) { 5546 loader_log(ptr_instance, VULKAN_LOADER_WARN_BIT, 0, 5547 "terminator_CreateInstance: Driver %s supports interface version %u but still exposes VkSurfaceKHR" 5548 " create/destroy entrypoints (Policy #LDP_DRIVER_8)", 5549 ptr_instance->icd_tramp_list.scanned_list[i].lib_name, 5550 ptr_instance->icd_tramp_list.scanned_list[i].interface_version); 5551 } 5552 5553 // If we made it this far, at least one ICD was successful 5554 one_icd_successful = true; 5555 } 5556 5557 // For vkGetPhysicalDeviceProperties2, at least one ICD needs to support the extension for the 5558 // instance to have it 5559 if (ptr_instance->supports_get_dev_prop_2) { 5560 bool at_least_one_supports = false; 5561 icd_term = ptr_instance->icd_terms; 5562 while (icd_term != NULL) { 5563 if (icd_term->supports_get_dev_prop_2) { 5564 at_least_one_supports = true; 5565 break; 5566 } 5567 icd_term = icd_term->next; 5568 } 5569 if (!at_least_one_supports) { 5570 ptr_instance->supports_get_dev_prop_2 = false; 5571 } 5572 } 5573 5574 // If no ICDs were added to instance list and res is unchanged from it's initial value, the loader was unable to 5575 // find a suitable ICD. 5576 if (VK_SUCCESS == res && (ptr_instance->icd_terms == NULL || !one_icd_successful)) { 5577 loader_log(ptr_instance, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_DRIVER_BIT, 0, 5578 "terminator_CreateInstance: Found no drivers!"); 5579 res = VK_ERROR_INCOMPATIBLE_DRIVER; 5580 } 5581 5582out: 5583 5584 ptr_instance->create_terminator_invalid_extension = false; 5585 5586 if (VK_SUCCESS != res) { 5587 if (VK_ERROR_EXTENSION_NOT_PRESENT == res) { 5588 ptr_instance->create_terminator_invalid_extension = true; 5589 } 5590 5591 while (NULL != ptr_instance->icd_terms) { 5592 icd_term = ptr_instance->icd_terms; 5593 ptr_instance->icd_terms = icd_term->next; 5594 if (NULL != icd_term->instance) { 5595 icd_term->dispatch.DestroyInstance(icd_term->instance, pAllocator); 5596 } 5597 loader_icd_destroy(ptr_instance, icd_term, pAllocator); 5598 } 5599 } else { 5600 // Check for enabled extensions here to setup the loader structures so the loader knows what extensions 5601 // it needs to worry about. 5602 // We do it here and again above the layers in the trampoline function since the trampoline function 5603 // may think different extensions are enabled than what's down here. 5604 // This is why we don't clear inside of these function calls. 5605 // The clearing should actually be handled by the overall memset of the pInstance structure in the 5606 // trampoline. 5607 wsi_create_instance(ptr_instance, pCreateInfo); 5608 check_for_enabled_debug_extensions(ptr_instance, pCreateInfo); 5609 extensions_create_instance(ptr_instance, pCreateInfo); 5610 } 5611 5612 return res; 5613} 5614 5615VKAPI_ATTR void VKAPI_CALL terminator_DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) { 5616 struct loader_instance *ptr_instance = loader_get_instance(instance); 5617 if (NULL == ptr_instance) { 5618 return; 5619 } 5620 struct loader_icd_term *icd_terms = ptr_instance->icd_terms; 5621 struct loader_icd_term *next_icd_term; 5622 5623 // Remove this instance from the list of instances: 5624 struct loader_instance *prev = NULL; 5625 loader_platform_thread_lock_mutex(&loader_global_instance_list_lock); 5626 struct loader_instance *next = loader.instances; 5627 while (next != NULL) { 5628 if (next == ptr_instance) { 5629 // Remove this instance from the list: 5630 if (prev) 5631 prev->next = next->next; 5632 else 5633 loader.instances = next->next; 5634 break; 5635 } 5636 prev = next; 5637 next = next->next; 5638 } 5639 loader_platform_thread_unlock_mutex(&loader_global_instance_list_lock); 5640 5641 while (NULL != icd_terms) { 5642 if (icd_terms->instance) { 5643 icd_terms->dispatch.DestroyInstance(icd_terms->instance, pAllocator); 5644 } 5645 next_icd_term = icd_terms->next; 5646 icd_terms->instance = VK_NULL_HANDLE; 5647 loader_icd_destroy(ptr_instance, icd_terms, pAllocator); 5648 5649 icd_terms = next_icd_term; 5650 } 5651 5652 loader_scanned_icd_clear(ptr_instance, &ptr_instance->icd_tramp_list); 5653 loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *)&ptr_instance->ext_list); 5654 if (NULL != ptr_instance->phys_devs_term) { 5655 for (uint32_t i = 0; i < ptr_instance->phys_dev_count_term; i++) { 5656 for (uint32_t j = i + 1; j < ptr_instance->phys_dev_count_term; j++) { 5657 if (ptr_instance->phys_devs_term[i] == ptr_instance->phys_devs_term[j]) { 5658 ptr_instance->phys_devs_term[j] = NULL; 5659 } 5660 } 5661 } 5662 for (uint32_t i = 0; i < ptr_instance->phys_dev_count_term; i++) { 5663 loader_instance_heap_free(ptr_instance, ptr_instance->phys_devs_term[i]); 5664 } 5665 loader_instance_heap_free(ptr_instance, ptr_instance->phys_devs_term); 5666 } 5667 if (NULL != ptr_instance->phys_dev_groups_term) { 5668 for (uint32_t i = 0; i < ptr_instance->phys_dev_group_count_term; i++) { 5669 loader_instance_heap_free(ptr_instance, ptr_instance->phys_dev_groups_term[i]); 5670 } 5671 loader_instance_heap_free(ptr_instance, ptr_instance->phys_dev_groups_term); 5672 } 5673 loader_free_dev_ext_table(ptr_instance); 5674 loader_free_phys_dev_ext_table(ptr_instance); 5675 5676 free_string_list(ptr_instance, &ptr_instance->enabled_layer_names); 5677} 5678 5679VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo, 5680 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) { 5681 VkResult res = VK_SUCCESS; 5682 struct loader_physical_device_term *phys_dev_term; 5683 phys_dev_term = (struct loader_physical_device_term *)physicalDevice; 5684 struct loader_icd_term *icd_term = phys_dev_term->this_icd_term; 5685 5686 struct loader_device *dev = (struct loader_device *)*pDevice; 5687 PFN_vkCreateDevice fpCreateDevice = icd_term->dispatch.CreateDevice; 5688 struct loader_extension_list icd_exts; 5689 5690 VkBaseOutStructure *caller_dgci_container = NULL; 5691 VkDeviceGroupDeviceCreateInfo *caller_dgci = NULL; 5692 5693 if (NULL == dev) { 5694 loader_log(icd_term->this_instance, VULKAN_LOADER_WARN_BIT, 0, 5695 "terminator_CreateDevice: Loader device pointer null encountered. Possibly set by active layer. (Policy " 5696 "#LLP_LAYER_22)"); 5697 } else if (DEVICE_DISP_TABLE_MAGIC_NUMBER != dev->loader_dispatch.core_dispatch.magic) { 5698 loader_log(icd_term->this_instance, VULKAN_LOADER_WARN_BIT, 0, 5699 "terminator_CreateDevice: Device pointer (%p) has invalid MAGIC value 0x%08lx. The expected value is " 5700 "0x10ADED040410ADED. Device value possibly " 5701 "corrupted by active layer (Policy #LLP_LAYER_22). ", 5702 dev, dev->loader_dispatch.core_dispatch.magic); 5703 } 5704 5705 dev->phys_dev_term = phys_dev_term; 5706 5707 icd_exts.list = NULL; 5708 5709 if (fpCreateDevice == NULL) { 5710 loader_log(icd_term->this_instance, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_DRIVER_BIT, 0, 5711 "terminator_CreateDevice: No vkCreateDevice command exposed by ICD %s", icd_term->scanned_icd->lib_name); 5712 res = VK_ERROR_INITIALIZATION_FAILED; 5713 goto out; 5714 } 5715 5716 VkDeviceCreateInfo localCreateInfo; 5717 memcpy(&localCreateInfo, pCreateInfo, sizeof(localCreateInfo)); 5718 5719 // NOTE: Need to filter the extensions to only those supported by the ICD. 5720 // No ICD will advertise support for layers. An ICD library could support a layer, 5721 // but it would be independent of the actual ICD, just in the same library. 5722 char **filtered_extension_names = NULL; 5723 if (0 < pCreateInfo->enabledExtensionCount) { 5724 filtered_extension_names = loader_stack_alloc(pCreateInfo->enabledExtensionCount * sizeof(char *)); 5725 if (NULL == filtered_extension_names) { 5726 loader_log(icd_term->this_instance, VULKAN_LOADER_ERROR_BIT, 0, 5727 "terminator_CreateDevice: Failed to create extension name storage for %d extensions", 5728 pCreateInfo->enabledExtensionCount); 5729 return VK_ERROR_OUT_OF_HOST_MEMORY; 5730 } 5731 } 5732 5733 localCreateInfo.enabledLayerCount = 0; 5734 localCreateInfo.ppEnabledLayerNames = NULL; 5735 5736 localCreateInfo.enabledExtensionCount = 0; 5737 localCreateInfo.ppEnabledExtensionNames = (const char *const *)filtered_extension_names; 5738 5739 // Get the physical device (ICD) extensions 5740 res = loader_init_generic_list(icd_term->this_instance, (struct loader_generic_list *)&icd_exts, sizeof(VkExtensionProperties)); 5741 if (VK_SUCCESS != res) { 5742 goto out; 5743 } 5744 5745 res = loader_add_device_extensions(icd_term->this_instance, icd_term->dispatch.EnumerateDeviceExtensionProperties, 5746 phys_dev_term->phys_dev, icd_term->scanned_icd->lib_name, &icd_exts); 5747 if (res != VK_SUCCESS) { 5748 goto out; 5749 } 5750 5751 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) { 5752 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i]; 5753 VkExtensionProperties *prop = get_extension_property(extension_name, &icd_exts); 5754 if (prop) { 5755 filtered_extension_names[localCreateInfo.enabledExtensionCount] = (char *)extension_name; 5756 localCreateInfo.enabledExtensionCount++; 5757 } else { 5758 loader_log(icd_term->this_instance, VULKAN_LOADER_DEBUG_BIT | VULKAN_LOADER_DRIVER_BIT, 0, 5759 "vkCreateDevice extension %s not available for devices associated with ICD %s", extension_name, 5760 icd_term->scanned_icd->lib_name); 5761 } 5762 } 5763 5764 // Before we continue, If KHX_device_group is the list of enabled and viable extensions, then we then need to look for the 5765 // corresponding VkDeviceGroupDeviceCreateInfo struct in the device list and replace all the physical device values (which 5766 // are really loader physical device terminator values) with the ICD versions. 5767 // if (icd_term->this_instance->enabled_known_extensions.khr_device_group_creation == 1) { 5768 { 5769 VkBaseOutStructure *pNext = (VkBaseOutStructure *)localCreateInfo.pNext; 5770 VkBaseOutStructure *pPrev = (VkBaseOutStructure *)&localCreateInfo; 5771 while (NULL != pNext) { 5772 if (VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO == pNext->sType) { 5773 VkDeviceGroupDeviceCreateInfo *cur_struct = (VkDeviceGroupDeviceCreateInfo *)pNext; 5774 if (0 < cur_struct->physicalDeviceCount && NULL != cur_struct->pPhysicalDevices) { 5775 VkDeviceGroupDeviceCreateInfo *temp_struct = loader_stack_alloc(sizeof(VkDeviceGroupDeviceCreateInfo)); 5776 VkPhysicalDevice *phys_dev_array = NULL; 5777 if (NULL == temp_struct) { 5778 return VK_ERROR_OUT_OF_HOST_MEMORY; 5779 } 5780 memcpy(temp_struct, cur_struct, sizeof(VkDeviceGroupDeviceCreateInfo)); 5781 phys_dev_array = loader_stack_alloc(sizeof(VkPhysicalDevice) * cur_struct->physicalDeviceCount); 5782 if (NULL == phys_dev_array) { 5783 return VK_ERROR_OUT_OF_HOST_MEMORY; 5784 } 5785 5786 // Before calling down, replace the incoming physical device values (which are really loader terminator 5787 // physical devices) with the ICDs physical device values. 5788 struct loader_physical_device_term *cur_term; 5789 for (uint32_t phys_dev = 0; phys_dev < cur_struct->physicalDeviceCount; phys_dev++) { 5790 cur_term = (struct loader_physical_device_term *)cur_struct->pPhysicalDevices[phys_dev]; 5791 phys_dev_array[phys_dev] = cur_term->phys_dev; 5792 } 5793 temp_struct->pPhysicalDevices = phys_dev_array; 5794 5795 // Keep track of pointers to restore pNext chain before returning 5796 caller_dgci_container = pPrev; 5797 caller_dgci = cur_struct; 5798 5799 // Replace the old struct in the pNext chain with this one. 5800 pPrev->pNext = (VkBaseOutStructure *)temp_struct; 5801 } 5802 break; 5803 } 5804 5805 pPrev = pNext; 5806 pNext = pNext->pNext; 5807 } 5808 } 5809 5810 // Handle loader emulation for structs that are not supported by the ICD: 5811 // Presently, the emulation leaves the pNext chain alone. This means that the ICD will receive items in the chain which 5812 // are not recognized by the ICD. If this causes the ICD to fail, then the items would have to be removed here. The current 5813 // implementation does not remove them because copying the pNext chain would be impossible if the loader does not recognize 5814 // the any of the struct types, as the loader would not know the size to allocate and copy. 5815 // if (icd_term->dispatch.GetPhysicalDeviceFeatures2 == NULL && icd_term->dispatch.GetPhysicalDeviceFeatures2KHR == NULL) { 5816 { 5817 const void *pNext = localCreateInfo.pNext; 5818 while (pNext != NULL) { 5819 switch (*(VkStructureType *)pNext) { 5820 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2: { 5821 const VkPhysicalDeviceFeatures2KHR *features = pNext; 5822 5823 if (icd_term->dispatch.GetPhysicalDeviceFeatures2 == NULL && 5824 icd_term->dispatch.GetPhysicalDeviceFeatures2KHR == NULL) { 5825 loader_log(icd_term->this_instance, VULKAN_LOADER_INFO_BIT, 0, 5826 "vkCreateDevice: Emulating handling of VkPhysicalDeviceFeatures2 in pNext chain for ICD \"%s\"", 5827 icd_term->scanned_icd->lib_name); 5828 5829 // Verify that VK_KHR_get_physical_device_properties2 is enabled 5830 if (icd_term->this_instance->enabled_known_extensions.khr_get_physical_device_properties2) { 5831 localCreateInfo.pEnabledFeatures = &features->features; 5832 } 5833 } 5834 5835 // Leave this item in the pNext chain for now 5836 5837 pNext = features->pNext; 5838 break; 5839 } 5840 5841 case VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO: { 5842 const VkDeviceGroupDeviceCreateInfo *group_info = pNext; 5843 5844 if (icd_term->dispatch.EnumeratePhysicalDeviceGroups == NULL && 5845 icd_term->dispatch.EnumeratePhysicalDeviceGroupsKHR == NULL) { 5846 loader_log(icd_term->this_instance, VULKAN_LOADER_INFO_BIT, 0, 5847 "vkCreateDevice: Emulating handling of VkPhysicalDeviceGroupProperties in pNext chain for " 5848 "ICD \"%s\"", 5849 icd_term->scanned_icd->lib_name); 5850 5851 // The group must contain only this one device, since physical device groups aren't actually supported 5852 if (group_info->physicalDeviceCount != 1) { 5853 loader_log(icd_term->this_instance, VULKAN_LOADER_ERROR_BIT, 0, 5854 "vkCreateDevice: Emulation failed to create device from device group info"); 5855 res = VK_ERROR_INITIALIZATION_FAILED; 5856 goto out; 5857 } 5858 } 5859 5860 // Nothing needs to be done here because we're leaving the item in the pNext chain and because the spec 5861 // states that the physicalDevice argument must be included in the device group, and we've already checked 5862 // that it is 5863 5864 pNext = group_info->pNext; 5865 break; 5866 } 5867 5868 // Multiview properties are also allowed, but since VK_KHX_multiview is a device extension, we'll just let the 5869 // ICD handle that error when the user enables the extension here 5870 default: { 5871 const VkBaseInStructure *header = pNext; 5872 pNext = header->pNext; 5873 break; 5874 } 5875 } 5876 } 5877 } 5878 5879 VkBool32 maintenance5_feature_enabled = false; 5880 // Look for the VkPhysicalDeviceMaintenance5FeaturesKHR struct to see if the feature was enabled 5881 { 5882 const void *pNext = localCreateInfo.pNext; 5883 while (pNext != NULL) { 5884 switch (*(VkStructureType *)pNext) { 5885 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_FEATURES_KHR: { 5886 const VkPhysicalDeviceMaintenance5FeaturesKHR *maintenance_features = pNext; 5887 if (maintenance_features->maintenance5 == VK_TRUE) { 5888 maintenance5_feature_enabled = true; 5889 } 5890 pNext = maintenance_features->pNext; 5891 break; 5892 } 5893 5894 default: { 5895 const VkBaseInStructure *header = pNext; 5896 pNext = header->pNext; 5897 break; 5898 } 5899 } 5900 } 5901 } 5902 5903 // Every extension that has a loader-defined terminator needs to be marked as enabled or disabled so that we know whether or 5904 // not to return that terminator when vkGetDeviceProcAddr is called 5905 for (uint32_t i = 0; i < localCreateInfo.enabledExtensionCount; ++i) { 5906 if (!strcmp(localCreateInfo.ppEnabledExtensionNames[i], VK_KHR_SWAPCHAIN_EXTENSION_NAME)) { 5907 dev->driver_extensions.khr_swapchain_enabled = true; 5908 } else if (!strcmp(localCreateInfo.ppEnabledExtensionNames[i], VK_KHR_DISPLAY_SWAPCHAIN_EXTENSION_NAME)) { 5909 dev->driver_extensions.khr_display_swapchain_enabled = true; 5910 } else if (!strcmp(localCreateInfo.ppEnabledExtensionNames[i], VK_KHR_DEVICE_GROUP_EXTENSION_NAME)) { 5911 dev->driver_extensions.khr_device_group_enabled = true; 5912 } else if (!strcmp(localCreateInfo.ppEnabledExtensionNames[i], VK_EXT_DEBUG_MARKER_EXTENSION_NAME)) { 5913 dev->driver_extensions.ext_debug_marker_enabled = true; 5914 } else if (!strcmp(localCreateInfo.ppEnabledExtensionNames[i], "VK_EXT_full_screen_exclusive")) { 5915 dev->driver_extensions.ext_full_screen_exclusive_enabled = true; 5916 } else if (!strcmp(localCreateInfo.ppEnabledExtensionNames[i], VK_KHR_MAINTENANCE_5_EXTENSION_NAME) && 5917 maintenance5_feature_enabled) { 5918 dev->should_ignore_device_commands_from_newer_version = true; 5919 } 5920 } 5921 dev->layer_extensions.ext_debug_utils_enabled = icd_term->this_instance->enabled_known_extensions.ext_debug_utils; 5922 dev->driver_extensions.ext_debug_utils_enabled = icd_term->this_instance->enabled_known_extensions.ext_debug_utils; 5923 5924 VkPhysicalDeviceProperties properties; 5925 icd_term->dispatch.GetPhysicalDeviceProperties(phys_dev_term->phys_dev, &properties); 5926 if (!dev->driver_extensions.khr_device_group_enabled) { 5927 if (properties.apiVersion >= VK_API_VERSION_1_1) { 5928 dev->driver_extensions.khr_device_group_enabled = true; 5929 } 5930 } 5931 5932 loader_log(icd_term->this_instance, VULKAN_LOADER_LAYER_BIT | VULKAN_LOADER_DRIVER_BIT, 0, 5933 " Using \"%s\" with driver: \"%s\"", properties.deviceName, icd_term->scanned_icd->lib_name); 5934 5935 res = fpCreateDevice(phys_dev_term->phys_dev, &localCreateInfo, pAllocator, &dev->icd_device); 5936 if (res != VK_SUCCESS) { 5937 loader_log(icd_term->this_instance, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_DRIVER_BIT, 0, 5938 "terminator_CreateDevice: Failed in ICD %s vkCreateDevice call", icd_term->scanned_icd->lib_name); 5939 goto out; 5940 } 5941 5942 *pDevice = dev->icd_device; 5943 loader_add_logical_device(icd_term, dev); 5944 5945 // Init dispatch pointer in new device object 5946 loader_init_dispatch(*pDevice, &dev->loader_dispatch); 5947 5948out: 5949 if (NULL != icd_exts.list) { 5950 loader_destroy_generic_list(icd_term->this_instance, (struct loader_generic_list *)&icd_exts); 5951 } 5952 5953 // Restore pNext pointer to old VkDeviceGroupDeviceCreateInfo 5954 // in the chain to maintain consistency for the caller. 5955 if (caller_dgci_container != NULL) { 5956 caller_dgci_container->pNext = (VkBaseOutStructure *)caller_dgci; 5957 } 5958 5959 return res; 5960} 5961 5962// Update the trampoline physical devices with the wrapped version. 5963// We always want to re-use previous physical device pointers since they may be used by an application 5964// after returning previously. 5965VkResult setup_loader_tramp_phys_devs(struct loader_instance *inst, uint32_t phys_dev_count, VkPhysicalDevice *phys_devs) { 5966 VkResult res = VK_SUCCESS; 5967 uint32_t found_count = 0; 5968 uint32_t old_count = inst->phys_dev_count_tramp; 5969 uint32_t new_count = inst->total_gpu_count; 5970 struct loader_physical_device_tramp **new_phys_devs = NULL; 5971 5972 if (0 == phys_dev_count) { 5973 return VK_SUCCESS; 5974 } 5975 if (phys_dev_count > new_count) { 5976 new_count = phys_dev_count; 5977 } 5978 5979 // We want an old to new index array and a new to old index array 5980 int32_t *old_to_new_index = (int32_t *)loader_stack_alloc(sizeof(int32_t) * old_count); 5981 int32_t *new_to_old_index = (int32_t *)loader_stack_alloc(sizeof(int32_t) * new_count); 5982 if (NULL == old_to_new_index || NULL == new_to_old_index) { 5983 return VK_ERROR_OUT_OF_HOST_MEMORY; 5984 } 5985 5986 // Initialize both 5987 for (uint32_t cur_idx = 0; cur_idx < old_count; ++cur_idx) { 5988 old_to_new_index[cur_idx] = -1; 5989 } 5990 for (uint32_t cur_idx = 0; cur_idx < new_count; ++cur_idx) { 5991 new_to_old_index[cur_idx] = -1; 5992 } 5993 5994 // Figure out the old->new and new->old indices 5995 for (uint32_t cur_idx = 0; cur_idx < old_count; ++cur_idx) { 5996 for (uint32_t new_idx = 0; new_idx < phys_dev_count; ++new_idx) { 5997 if (inst->phys_devs_tramp[cur_idx]->phys_dev == phys_devs[new_idx]) { 5998 old_to_new_index[cur_idx] = (int32_t)new_idx; 5999 new_to_old_index[new_idx] = (int32_t)cur_idx; 6000 found_count++; 6001 break; 6002 } 6003 } 6004 } 6005 6006 // If we found exactly the number of items we were looking for as we had before. Then everything 6007 // we already have is good enough and we just need to update the array that was passed in with 6008 // the loader values. 6009 if (found_count == phys_dev_count && 0 != old_count && old_count == new_count) { 6010 for (uint32_t new_idx = 0; new_idx < phys_dev_count; ++new_idx) { 6011 for (uint32_t cur_idx = 0; cur_idx < old_count; ++cur_idx) { 6012 if (old_to_new_index[cur_idx] == (int32_t)new_idx) { 6013 phys_devs[new_idx] = (VkPhysicalDevice)inst->phys_devs_tramp[cur_idx]; 6014 break; 6015 } 6016 } 6017 } 6018 // Nothing else to do for this path 6019 res = VK_SUCCESS; 6020 } else { 6021 // Something is different, so do the full path of checking every device and creating a new array to use. 6022 // This can happen if a device was added, or removed, or we hadn't previously queried all the data and we 6023 // have more to store. 6024 new_phys_devs = loader_instance_heap_calloc(inst, sizeof(struct loader_physical_device_tramp *) * new_count, 6025 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 6026 if (NULL == new_phys_devs) { 6027 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 6028 "setup_loader_tramp_phys_devs: Failed to allocate new physical device array of size %d", new_count); 6029 res = VK_ERROR_OUT_OF_HOST_MEMORY; 6030 goto out; 6031 } 6032 6033 if (new_count > phys_dev_count) { 6034 found_count = phys_dev_count; 6035 } else { 6036 found_count = new_count; 6037 } 6038 6039 // First try to see if an old item exists that matches the new item. If so, just copy it over. 6040 for (uint32_t new_idx = 0; new_idx < found_count; ++new_idx) { 6041 bool old_item_found = false; 6042 for (uint32_t cur_idx = 0; cur_idx < old_count; ++cur_idx) { 6043 if (old_to_new_index[cur_idx] == (int32_t)new_idx) { 6044 // Copy over old item to correct spot in the new array 6045 new_phys_devs[new_idx] = inst->phys_devs_tramp[cur_idx]; 6046 old_item_found = true; 6047 break; 6048 } 6049 } 6050 // Something wasn't found, so it's new so add it to the new list 6051 if (!old_item_found) { 6052 new_phys_devs[new_idx] = loader_instance_heap_alloc(inst, sizeof(struct loader_physical_device_tramp), 6053 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 6054 if (NULL == new_phys_devs[new_idx]) { 6055 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 6056 "setup_loader_tramp_phys_devs: Failed to allocate new trampoline physical device"); 6057 res = VK_ERROR_OUT_OF_HOST_MEMORY; 6058 goto out; 6059 } 6060 6061 // Initialize the new physicalDevice object 6062 loader_set_dispatch((void *)new_phys_devs[new_idx], inst->disp); 6063 new_phys_devs[new_idx]->this_instance = inst; 6064 new_phys_devs[new_idx]->phys_dev = phys_devs[new_idx]; 6065 new_phys_devs[new_idx]->magic = PHYS_TRAMP_MAGIC_NUMBER; 6066 } 6067 6068 phys_devs[new_idx] = (VkPhysicalDevice)new_phys_devs[new_idx]; 6069 } 6070 6071 // We usually get here if the user array is smaller than the total number of devices, so copy the 6072 // remaining devices we have over to the new array. 6073 uint32_t start = found_count; 6074 for (uint32_t new_idx = start; new_idx < new_count; ++new_idx) { 6075 for (uint32_t cur_idx = 0; cur_idx < old_count; ++cur_idx) { 6076 if (old_to_new_index[cur_idx] == -1) { 6077 new_phys_devs[new_idx] = inst->phys_devs_tramp[cur_idx]; 6078 old_to_new_index[cur_idx] = new_idx; 6079 found_count++; 6080 break; 6081 } 6082 } 6083 } 6084 } 6085 6086out: 6087 6088 if (NULL != new_phys_devs) { 6089 if (VK_SUCCESS != res) { 6090 for (uint32_t new_idx = 0; new_idx < found_count; ++new_idx) { 6091 // If an OOM occurred inside the copying of the new physical devices into the existing array 6092 // will leave some of the old physical devices in the array which may have been copied into 6093 // the new array, leading to them being freed twice. To avoid this we just make sure to not 6094 // delete physical devices which were copied. 6095 bool found = false; 6096 for (uint32_t cur_idx = 0; cur_idx < inst->phys_dev_count_tramp; cur_idx++) { 6097 if (new_phys_devs[new_idx] == inst->phys_devs_tramp[cur_idx]) { 6098 found = true; 6099 break; 6100 } 6101 } 6102 if (!found) { 6103 loader_instance_heap_free(inst, new_phys_devs[new_idx]); 6104 } 6105 } 6106 loader_instance_heap_free(inst, new_phys_devs); 6107 } else { 6108 if (new_count > inst->total_gpu_count) { 6109 inst->total_gpu_count = new_count; 6110 } 6111 // Free everything in the old array that was not copied into the new array 6112 // here. We can't attempt to do that before here since the previous loop 6113 // looking before the "out:" label may hit an out of memory condition resulting 6114 // in memory leaking. 6115 if (NULL != inst->phys_devs_tramp) { 6116 for (uint32_t i = 0; i < inst->phys_dev_count_tramp; i++) { 6117 bool found = false; 6118 for (uint32_t j = 0; j < inst->total_gpu_count; j++) { 6119 if (inst->phys_devs_tramp[i] == new_phys_devs[j]) { 6120 found = true; 6121 break; 6122 } 6123 } 6124 if (!found) { 6125 loader_instance_heap_free(inst, inst->phys_devs_tramp[i]); 6126 } 6127 } 6128 loader_instance_heap_free(inst, inst->phys_devs_tramp); 6129 } 6130 inst->phys_devs_tramp = new_phys_devs; 6131 inst->phys_dev_count_tramp = found_count; 6132 } 6133 } 6134 if (VK_SUCCESS != res) { 6135 inst->total_gpu_count = 0; 6136 } 6137 6138 return res; 6139} 6140 6141#if defined(LOADER_ENABLE_LINUX_SORT) 6142bool is_linux_sort_enabled(struct loader_instance *inst) { 6143 bool sort_items = inst->supports_get_dev_prop_2; 6144 char *env_value = loader_getenv("VK_LOADER_DISABLE_SELECT", inst); 6145 if (NULL != env_value) { 6146 int32_t int_env_val = atoi(env_value); 6147 loader_free_getenv(env_value, inst); 6148 if (int_env_val != 0) { 6149 sort_items = false; 6150 } 6151 } 6152 return sort_items; 6153} 6154#endif // LOADER_ENABLE_LINUX_SORT 6155 6156// Look for physical_device in the provided phys_devs list, return true if found and put the index into out_idx, otherwise 6157// return false 6158bool find_phys_dev(VkPhysicalDevice physical_device, uint32_t phys_devs_count, struct loader_physical_device_term **phys_devs, 6159 uint32_t *out_idx) { 6160 if (NULL == phys_devs) return false; 6161 for (uint32_t idx = 0; idx < phys_devs_count; idx++) { 6162 if (NULL != phys_devs[idx] && physical_device == phys_devs[idx]->phys_dev) { 6163 *out_idx = idx; 6164 return true; 6165 } 6166 } 6167 return false; 6168} 6169 6170// Add physical_device to new_phys_devs 6171VkResult check_and_add_to_new_phys_devs(struct loader_instance *inst, VkPhysicalDevice physical_device, 6172 struct loader_icd_physical_devices *dev_array, uint32_t *cur_new_phys_dev_count, 6173 struct loader_physical_device_term **new_phys_devs) { 6174 uint32_t out_idx = 0; 6175 uint32_t idx = *cur_new_phys_dev_count; 6176 // Check if the physical_device already exists in the new_phys_devs buffer, that means it was found from both 6177 // EnumerateAdapterPhysicalDevices and EnumeratePhysicalDevices and we need to skip it. 6178 if (find_phys_dev(physical_device, idx, new_phys_devs, &out_idx)) { 6179 return VK_SUCCESS; 6180 } 6181 // Check if it was found in a previous call to vkEnumeratePhysicalDevices, we can just copy over the old data. 6182 if (find_phys_dev(physical_device, inst->phys_dev_count_term, inst->phys_devs_term, &out_idx)) { 6183 new_phys_devs[idx] = inst->phys_devs_term[out_idx]; 6184 (*cur_new_phys_dev_count)++; 6185 return VK_SUCCESS; 6186 } 6187 6188 // Exit in case something is already present - this shouldn't happen but better to be safe than overwrite existing data 6189 // since this code has been refactored a half dozen times. 6190 if (NULL != new_phys_devs[idx]) { 6191 return VK_SUCCESS; 6192 } 6193 // If this physical device is new, we need to allocate space for it. 6194 new_phys_devs[idx] = 6195 loader_instance_heap_alloc(inst, sizeof(struct loader_physical_device_term), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 6196 if (NULL == new_phys_devs[idx]) { 6197 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 6198 "check_and_add_to_new_phys_devs: Failed to allocate physical device terminator object %d", idx); 6199 return VK_ERROR_OUT_OF_HOST_MEMORY; 6200 } 6201 6202 loader_set_dispatch((void *)new_phys_devs[idx], inst->disp); 6203 new_phys_devs[idx]->this_icd_term = dev_array->icd_term; 6204 new_phys_devs[idx]->icd_index = (uint8_t)(dev_array->icd_index); 6205 new_phys_devs[idx]->phys_dev = physical_device; 6206 6207 // Increment the count of new physical devices 6208 (*cur_new_phys_dev_count)++; 6209 return VK_SUCCESS; 6210} 6211 6212/* Enumerate all physical devices from ICDs and add them to inst->phys_devs_term 6213 * 6214 * There are two methods to find VkPhysicalDevices - vkEnumeratePhysicalDevices and vkEnumerateAdapterPhysicalDevices 6215 * The latter is supported on windows only and on devices supporting ICD Interface Version 6 and greater. 6216 * 6217 * Once all physical devices are acquired, they need to be pulled into a single list of `loader_physical_device_term`'s. 6218 * They also need to be setup - the icd_term, icd_index, phys_dev, and disp (dispatch table) all need the correct data. 6219 * Additionally, we need to keep using already setup physical devices as they may be in use, thus anything enumerated 6220 * that is already in inst->phys_devs_term will be carried over. 6221 */ 6222 6223VkResult setup_loader_term_phys_devs(struct loader_instance *inst) { 6224 VkResult res = VK_SUCCESS; 6225 struct loader_icd_term *icd_term; 6226 uint32_t icd_idx = 0; 6227 uint32_t windows_sorted_devices_count = 0; 6228 struct loader_icd_physical_devices *windows_sorted_devices_array = NULL; 6229 uint32_t icd_count = 0; 6230 struct loader_icd_physical_devices *icd_phys_dev_array = NULL; 6231 uint32_t new_phys_devs_capacity = 0; 6232 uint32_t new_phys_devs_count = 0; 6233 struct loader_physical_device_term **new_phys_devs = NULL; 6234 6235#if defined(_WIN32) 6236 // Get the physical devices supported by platform sorting mechanism into a separate list 6237 res = windows_read_sorted_physical_devices(inst, &windows_sorted_devices_count, &windows_sorted_devices_array); 6238 if (VK_SUCCESS != res) { 6239 goto out; 6240 } 6241#endif 6242 6243 icd_count = inst->total_icd_count; 6244 6245 // Allocate something to store the physical device characteristics that we read from each ICD. 6246 icd_phys_dev_array = 6247 (struct loader_icd_physical_devices *)loader_stack_alloc(sizeof(struct loader_icd_physical_devices) * icd_count); 6248 if (NULL == icd_phys_dev_array) { 6249 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 6250 "setup_loader_term_phys_devs: Failed to allocate temporary ICD Physical device info array of size %d", 6251 icd_count); 6252 res = VK_ERROR_OUT_OF_HOST_MEMORY; 6253 goto out; 6254 } 6255 memset(icd_phys_dev_array, 0, sizeof(struct loader_icd_physical_devices) * icd_count); 6256 6257 // For each ICD, query the number of physical devices, and then get an 6258 // internal value for those physical devices. 6259 icd_term = inst->icd_terms; 6260 while (NULL != icd_term) { 6261 res = icd_term->dispatch.EnumeratePhysicalDevices(icd_term->instance, &icd_phys_dev_array[icd_idx].device_count, NULL); 6262 if (VK_SUCCESS != res) { 6263 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 6264 "setup_loader_term_phys_devs: Call to ICD %d's \'vkEnumeratePhysicalDevices\' failed with error 0x%08x", 6265 icd_idx, res); 6266 goto out; 6267 } 6268 6269 icd_phys_dev_array[icd_idx].physical_devices = 6270 (VkPhysicalDevice *)loader_stack_alloc(icd_phys_dev_array[icd_idx].device_count * sizeof(VkPhysicalDevice)); 6271 if (NULL == icd_phys_dev_array[icd_idx].physical_devices) { 6272 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 6273 "setup_loader_term_phys_devs: Failed to allocate temporary ICD Physical device array for ICD %d of size %d", 6274 icd_idx, icd_phys_dev_array[icd_idx].device_count); 6275 res = VK_ERROR_OUT_OF_HOST_MEMORY; 6276 goto out; 6277 } 6278 6279 res = icd_term->dispatch.EnumeratePhysicalDevices(icd_term->instance, &(icd_phys_dev_array[icd_idx].device_count), 6280 icd_phys_dev_array[icd_idx].physical_devices); 6281 if (VK_SUCCESS != res) { 6282 goto out; 6283 } 6284 icd_phys_dev_array[icd_idx].icd_term = icd_term; 6285 icd_phys_dev_array[icd_idx].icd_index = icd_idx; 6286 icd_term = icd_term->next; 6287 ++icd_idx; 6288 } 6289 6290 // Add up both the windows sorted and non windows found physical device counts 6291 for (uint32_t i = 0; i < windows_sorted_devices_count; ++i) { 6292 new_phys_devs_capacity += windows_sorted_devices_array[i].device_count; 6293 } 6294 for (uint32_t i = 0; i < icd_count; ++i) { 6295 new_phys_devs_capacity += icd_phys_dev_array[i].device_count; 6296 } 6297 6298 // Bail out if there are no physical devices reported 6299 if (0 == new_phys_devs_capacity) { 6300 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 6301 "setup_loader_term_phys_devs: Failed to detect any valid GPUs in the current config"); 6302 res = VK_ERROR_INITIALIZATION_FAILED; 6303 goto out; 6304 } 6305 6306 // Create an allocation large enough to hold both the windows sorting enumeration and non-windows physical device 6307 // enumeration 6308 new_phys_devs = loader_instance_heap_calloc(inst, sizeof(struct loader_physical_device_term *) * new_phys_devs_capacity, 6309 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 6310 if (NULL == new_phys_devs) { 6311 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 6312 "setup_loader_term_phys_devs: Failed to allocate new physical device array of size %d", new_phys_devs_capacity); 6313 res = VK_ERROR_OUT_OF_HOST_MEMORY; 6314 goto out; 6315 } 6316 6317 // Copy over everything found through sorted enumeration 6318 for (uint32_t i = 0; i < windows_sorted_devices_count; ++i) { 6319 for (uint32_t j = 0; j < windows_sorted_devices_array[i].device_count; ++j) { 6320 res = check_and_add_to_new_phys_devs(inst, windows_sorted_devices_array[i].physical_devices[j], 6321 &windows_sorted_devices_array[i], &new_phys_devs_count, new_phys_devs); 6322 if (res == VK_ERROR_OUT_OF_HOST_MEMORY) { 6323 goto out; 6324 } 6325 } 6326 } 6327 6328// Now go through the rest of the physical devices and add them to new_phys_devs 6329#if defined(LOADER_ENABLE_LINUX_SORT) 6330 6331 if (is_linux_sort_enabled(inst)) { 6332 for (uint32_t dev = new_phys_devs_count; dev < new_phys_devs_capacity; ++dev) { 6333 new_phys_devs[dev] = 6334 loader_instance_heap_alloc(inst, sizeof(struct loader_physical_device_term), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 6335 if (NULL == new_phys_devs[dev]) { 6336 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 6337 "setup_loader_term_phys_devs: Failed to allocate physical device terminator object %d", dev); 6338 res = VK_ERROR_OUT_OF_HOST_MEMORY; 6339 goto out; 6340 } 6341 } 6342 6343 // Get the physical devices supported by platform sorting mechanism into a separate list 6344 // Pass in a sublist to the function so it only operates on the correct elements. This means passing in a pointer to the 6345 // current next element in new_phys_devs and passing in a `count` of currently unwritten elements 6346 res = linux_read_sorted_physical_devices(inst, icd_count, icd_phys_dev_array, new_phys_devs_capacity - new_phys_devs_count, 6347 &new_phys_devs[new_phys_devs_count]); 6348 if (res == VK_ERROR_OUT_OF_HOST_MEMORY) { 6349 goto out; 6350 } 6351 // Keep previously allocated physical device info since apps may already be using that! 6352 for (uint32_t new_idx = new_phys_devs_count; new_idx < new_phys_devs_capacity; new_idx++) { 6353 for (uint32_t old_idx = 0; old_idx < inst->phys_dev_count_term; old_idx++) { 6354 if (new_phys_devs[new_idx]->phys_dev == inst->phys_devs_term[old_idx]->phys_dev) { 6355 loader_log(inst, VULKAN_LOADER_DEBUG_BIT | VULKAN_LOADER_DRIVER_BIT, 0, 6356 "Copying old device %u into new device %u", old_idx, new_idx); 6357 // Free the old new_phys_devs info since we're not using it before we assign the new info 6358 loader_instance_heap_free(inst, new_phys_devs[new_idx]); 6359 new_phys_devs[new_idx] = inst->phys_devs_term[old_idx]; 6360 break; 6361 } 6362 } 6363 } 6364 // now set the count to the capacity, as now the list is filled in 6365 new_phys_devs_count = new_phys_devs_capacity; 6366 // We want the following code to run if either linux sorting is disabled at compile time or runtime 6367 } else { 6368#endif // LOADER_ENABLE_LINUX_SORT 6369 6370 // Copy over everything found through the non-sorted means. 6371 for (uint32_t i = 0; i < icd_count; ++i) { 6372 for (uint32_t j = 0; j < icd_phys_dev_array[i].device_count; ++j) { 6373 res = check_and_add_to_new_phys_devs(inst, icd_phys_dev_array[i].physical_devices[j], &icd_phys_dev_array[i], 6374 &new_phys_devs_count, new_phys_devs); 6375 if (res == VK_ERROR_OUT_OF_HOST_MEMORY) { 6376 goto out; 6377 } 6378 } 6379 } 6380#if defined(LOADER_ENABLE_LINUX_SORT) 6381 } 6382#endif // LOADER_ENABLE_LINUX_SORT 6383out: 6384 6385 if (VK_SUCCESS != res) { 6386 if (NULL != new_phys_devs) { 6387 // We've encountered an error, so we should free the new buffers. 6388 for (uint32_t i = 0; i < new_phys_devs_capacity; i++) { 6389 // May not have allocated this far, skip it if we hadn't. 6390 if (new_phys_devs[i] == NULL) continue; 6391 6392 // If an OOM occurred inside the copying of the new physical devices into the existing array 6393 // will leave some of the old physical devices in the array which may have been copied into 6394 // the new array, leading to them being freed twice. To avoid this we just make sure to not 6395 // delete physical devices which were copied. 6396 bool found = false; 6397 if (NULL != inst->phys_devs_term) { 6398 for (uint32_t old_idx = 0; old_idx < inst->phys_dev_count_term; old_idx++) { 6399 if (new_phys_devs[i] == inst->phys_devs_term[old_idx]) { 6400 found = true; 6401 break; 6402 } 6403 } 6404 } 6405 if (!found) { 6406 loader_instance_heap_free(inst, new_phys_devs[i]); 6407 } 6408 } 6409 loader_instance_heap_free(inst, new_phys_devs); 6410 } 6411 inst->total_gpu_count = 0; 6412 } else { 6413 if (NULL != inst->phys_devs_term) { 6414 // Free everything in the old array that was not copied into the new array 6415 // here. We can't attempt to do that before here since the previous loop 6416 // looking before the "out:" label may hit an out of memory condition resulting 6417 // in memory leaking. 6418 for (uint32_t i = 0; i < inst->phys_dev_count_term; i++) { 6419 bool found = false; 6420 for (uint32_t j = 0; j < new_phys_devs_count; j++) { 6421 if (new_phys_devs != NULL && inst->phys_devs_term[i] == new_phys_devs[j]) { 6422 found = true; 6423 break; 6424 } 6425 } 6426 if (!found) { 6427 loader_instance_heap_free(inst, inst->phys_devs_term[i]); 6428 } 6429 } 6430 loader_instance_heap_free(inst, inst->phys_devs_term); 6431 } 6432 6433 // Swap out old and new devices list 6434 inst->phys_dev_count_term = new_phys_devs_count; 6435 inst->phys_devs_term = new_phys_devs; 6436 inst->total_gpu_count = new_phys_devs_count; 6437 } 6438 6439 if (windows_sorted_devices_array != NULL) { 6440 for (uint32_t i = 0; i < windows_sorted_devices_count; ++i) { 6441 if (windows_sorted_devices_array[i].device_count > 0 && windows_sorted_devices_array[i].physical_devices != NULL) { 6442 loader_instance_heap_free(inst, windows_sorted_devices_array[i].physical_devices); 6443 } 6444 } 6445 loader_instance_heap_free(inst, windows_sorted_devices_array); 6446 } 6447 6448 return res; 6449} 6450 6451VkResult setup_loader_tramp_phys_dev_groups(struct loader_instance *inst, uint32_t group_count, 6452 VkPhysicalDeviceGroupProperties *groups) { 6453 VkResult res = VK_SUCCESS; 6454 uint32_t cur_idx; 6455 uint32_t dev_idx; 6456 6457 if (0 == group_count) { 6458 return VK_SUCCESS; 6459 } 6460 6461 // Generate a list of all the devices and convert them to the loader ID 6462 uint32_t phys_dev_count = 0; 6463 for (cur_idx = 0; cur_idx < group_count; ++cur_idx) { 6464 phys_dev_count += groups[cur_idx].physicalDeviceCount; 6465 } 6466 VkPhysicalDevice *devices = (VkPhysicalDevice *)loader_stack_alloc(sizeof(VkPhysicalDevice) * phys_dev_count); 6467 if (NULL == devices) { 6468 return VK_ERROR_OUT_OF_HOST_MEMORY; 6469 } 6470 6471 uint32_t cur_device = 0; 6472 for (cur_idx = 0; cur_idx < group_count; ++cur_idx) { 6473 for (dev_idx = 0; dev_idx < groups[cur_idx].physicalDeviceCount; ++dev_idx) { 6474 devices[cur_device++] = groups[cur_idx].physicalDevices[dev_idx]; 6475 } 6476 } 6477 6478 // Update the devices based on the loader physical device values. 6479 res = setup_loader_tramp_phys_devs(inst, phys_dev_count, devices); 6480 if (VK_SUCCESS != res) { 6481 return res; 6482 } 6483 6484 // Update the devices in the group structures now 6485 cur_device = 0; 6486 for (cur_idx = 0; cur_idx < group_count; ++cur_idx) { 6487 for (dev_idx = 0; dev_idx < groups[cur_idx].physicalDeviceCount; ++dev_idx) { 6488 groups[cur_idx].physicalDevices[dev_idx] = devices[cur_device++]; 6489 } 6490 } 6491 6492 return res; 6493} 6494 6495VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount, 6496 VkPhysicalDevice *pPhysicalDevices) { 6497 struct loader_instance *inst = (struct loader_instance *)instance; 6498 VkResult res = VK_SUCCESS; 6499 6500 // Always call the setup loader terminator physical devices because they may 6501 // have changed at any point. 6502 res = setup_loader_term_phys_devs(inst); 6503 if (VK_SUCCESS != res) { 6504 goto out; 6505 } 6506 6507 uint32_t copy_count = inst->phys_dev_count_term; 6508 if (NULL != pPhysicalDevices) { 6509 if (copy_count > *pPhysicalDeviceCount) { 6510 copy_count = *pPhysicalDeviceCount; 6511 loader_log(inst, VULKAN_LOADER_INFO_BIT, 0, 6512 "terminator_EnumeratePhysicalDevices : Trimming device count from %d to %d.", inst->phys_dev_count_term, 6513 copy_count); 6514 res = VK_INCOMPLETE; 6515 } 6516 6517 for (uint32_t i = 0; i < copy_count; i++) { 6518 pPhysicalDevices[i] = (VkPhysicalDevice)inst->phys_devs_term[i]; 6519 } 6520 } 6521 6522 *pPhysicalDeviceCount = copy_count; 6523 6524out: 6525 6526 return res; 6527} 6528 6529VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, 6530 const char *pLayerName, uint32_t *pPropertyCount, 6531 VkExtensionProperties *pProperties) { 6532 if (NULL == pPropertyCount) { 6533 return VK_INCOMPLETE; 6534 } 6535 6536 struct loader_physical_device_term *phys_dev_term; 6537 6538 // Any layer or trampoline wrapping should be removed at this point in time can just cast to the expected 6539 // type for VkPhysicalDevice. 6540 phys_dev_term = (struct loader_physical_device_term *)physicalDevice; 6541 6542 // if we got here with a non-empty pLayerName, look up the extensions 6543 // from the json 6544 if (pLayerName != NULL && strlen(pLayerName) > 0) { 6545 uint32_t count; 6546 uint32_t copy_size; 6547 const struct loader_instance *inst = phys_dev_term->this_icd_term->this_instance; 6548 struct loader_device_extension_list *dev_ext_list = NULL; 6549 struct loader_device_extension_list local_ext_list; 6550 memset(&local_ext_list, 0, sizeof(local_ext_list)); 6551 if (vk_string_validate(MaxLoaderStringLength, pLayerName) == VK_STRING_ERROR_NONE) { 6552 for (uint32_t i = 0; i < inst->instance_layer_list.count; i++) { 6553 struct loader_layer_properties *props = &inst->instance_layer_list.list[i]; 6554 if (strcmp(props->info.layerName, pLayerName) == 0) { 6555 dev_ext_list = &props->device_extension_list; 6556 } 6557 } 6558 6559 count = (dev_ext_list == NULL) ? 0 : dev_ext_list->count; 6560 if (pProperties == NULL) { 6561 *pPropertyCount = count; 6562 loader_destroy_generic_list(inst, (struct loader_generic_list *)&local_ext_list); 6563 return VK_SUCCESS; 6564 } 6565 6566 copy_size = *pPropertyCount < count ? *pPropertyCount : count; 6567 for (uint32_t i = 0; i < copy_size; i++) { 6568 memcpy(&pProperties[i], &dev_ext_list->list[i].props, sizeof(VkExtensionProperties)); 6569 } 6570 *pPropertyCount = copy_size; 6571 6572 loader_destroy_generic_list(inst, (struct loader_generic_list *)&local_ext_list); 6573 if (copy_size < count) { 6574 return VK_INCOMPLETE; 6575 } 6576 } else { 6577 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 6578 "vkEnumerateDeviceExtensionProperties: pLayerName is too long or is badly formed"); 6579 return VK_ERROR_EXTENSION_NOT_PRESENT; 6580 } 6581 6582 return VK_SUCCESS; 6583 } 6584 6585 // user is querying driver extensions and has supplied their own storage - just fill it out 6586 else if (pProperties) { 6587 struct loader_icd_term *icd_term = phys_dev_term->this_icd_term; 6588 uint32_t written_count = *pPropertyCount; 6589 VkResult res = 6590 icd_term->dispatch.EnumerateDeviceExtensionProperties(phys_dev_term->phys_dev, NULL, &written_count, pProperties); 6591 if (res != VK_SUCCESS) { 6592 return res; 6593 } 6594 6595 // Iterate over active layers, if they are an implicit layer, add their device extensions 6596 // After calling into the driver, written_count contains the amount of device extensions written. We can therefore write 6597 // layer extensions starting at that point in pProperties 6598 for (uint32_t i = 0; i < icd_term->this_instance->expanded_activated_layer_list.count; i++) { 6599 struct loader_layer_properties *layer_props = icd_term->this_instance->expanded_activated_layer_list.list[i]; 6600 if (0 == (layer_props->type_flags & VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER)) { 6601 struct loader_device_extension_list *layer_ext_list = &layer_props->device_extension_list; 6602 for (uint32_t j = 0; j < layer_ext_list->count; j++) { 6603 struct loader_dev_ext_props *cur_ext_props = &layer_ext_list->list[j]; 6604 // look for duplicates 6605 if (has_vk_extension_property_array(&cur_ext_props->props, written_count, pProperties)) { 6606 continue; 6607 } 6608 6609 if (*pPropertyCount <= written_count) { 6610 return VK_INCOMPLETE; 6611 } 6612 6613 memcpy(&pProperties[written_count], &cur_ext_props->props, sizeof(VkExtensionProperties)); 6614 written_count++; 6615 } 6616 } 6617 } 6618 // Make sure we update the pPropertyCount with the how many were written 6619 *pPropertyCount = written_count; 6620 return res; 6621 } 6622 // Use `goto out;` for rest of this function 6623 6624 // This case is during the call down the instance chain with pLayerName == NULL and pProperties == NULL 6625 struct loader_icd_term *icd_term = phys_dev_term->this_icd_term; 6626 struct loader_extension_list all_exts = {0}; 6627 VkResult res; 6628 6629 // We need to find the count without duplicates. This requires querying the driver for the names of the extensions. 6630 res = icd_term->dispatch.EnumerateDeviceExtensionProperties(phys_dev_term->phys_dev, NULL, &all_exts.count, NULL); 6631 if (res != VK_SUCCESS) { 6632 goto out; 6633 } 6634 // Then allocate memory to store the physical device extension list + the extensions layers provide 6635 // all_exts.count currently is the number of driver extensions 6636 all_exts.capacity = sizeof(VkExtensionProperties) * (all_exts.count + 20); 6637 all_exts.list = loader_instance_heap_alloc(icd_term->this_instance, all_exts.capacity, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 6638 if (NULL == all_exts.list) { 6639 res = VK_ERROR_OUT_OF_HOST_MEMORY; 6640 goto out; 6641 } 6642 6643 // Get the available device extensions and put them in all_exts.list 6644 res = icd_term->dispatch.EnumerateDeviceExtensionProperties(phys_dev_term->phys_dev, NULL, &all_exts.count, all_exts.list); 6645 if (res != VK_SUCCESS) { 6646 goto out; 6647 } 6648 6649 // Iterate over active layers, if they are an implicit layer, add their device extensions to all_exts.list 6650 for (uint32_t i = 0; i < icd_term->this_instance->expanded_activated_layer_list.count; i++) { 6651 struct loader_layer_properties *layer_props = icd_term->this_instance->expanded_activated_layer_list.list[i]; 6652 if (0 == (layer_props->type_flags & VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER)) { 6653 struct loader_device_extension_list *layer_ext_list = &layer_props->device_extension_list; 6654 for (uint32_t j = 0; j < layer_ext_list->count; j++) { 6655 res = loader_add_to_ext_list(icd_term->this_instance, &all_exts, 1, &layer_ext_list->list[j].props); 6656 if (res != VK_SUCCESS) { 6657 goto out; 6658 } 6659 } 6660 } 6661 } 6662 6663 // Write out the final de-duplicated count to pPropertyCount 6664 *pPropertyCount = all_exts.count; 6665 res = VK_SUCCESS; 6666 6667out: 6668 6669 loader_destroy_generic_list(icd_term->this_instance, (struct loader_generic_list *)&all_exts); 6670 return res; 6671} 6672 6673VkStringErrorFlags vk_string_validate(const int max_length, const char *utf8) { 6674 VkStringErrorFlags result = VK_STRING_ERROR_NONE; 6675 int num_char_bytes = 0; 6676 int i, j; 6677 6678 if (utf8 == NULL) { 6679 return VK_STRING_ERROR_NULL_PTR; 6680 } 6681 6682 for (i = 0; i <= max_length; i++) { 6683 if (utf8[i] == 0) { 6684 break; 6685 } else if (i == max_length) { 6686 result |= VK_STRING_ERROR_LENGTH; 6687 break; 6688 } else if ((utf8[i] >= 0x20) && (utf8[i] < 0x7f)) { 6689 num_char_bytes = 0; 6690 } else if ((utf8[i] & UTF8_ONE_BYTE_MASK) == UTF8_ONE_BYTE_CODE) { 6691 num_char_bytes = 1; 6692 } else if ((utf8[i] & UTF8_TWO_BYTE_MASK) == UTF8_TWO_BYTE_CODE) { 6693 num_char_bytes = 2; 6694 } else if ((utf8[i] & UTF8_THREE_BYTE_MASK) == UTF8_THREE_BYTE_CODE) { 6695 num_char_bytes = 3; 6696 } else { 6697 result = VK_STRING_ERROR_BAD_DATA; 6698 } 6699 6700 // Validate the following num_char_bytes of data 6701 for (j = 0; (j < num_char_bytes) && (i < max_length); j++) { 6702 if (++i == max_length) { 6703 result |= VK_STRING_ERROR_LENGTH; 6704 break; 6705 } 6706 if ((utf8[i] & UTF8_DATA_BYTE_MASK) != UTF8_DATA_BYTE_CODE) { 6707 result |= VK_STRING_ERROR_BAD_DATA; 6708 } 6709 } 6710 } 6711 return result; 6712} 6713 6714VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateInstanceVersion(const VkEnumerateInstanceVersionChain *chain, 6715 uint32_t *pApiVersion) { 6716 (void)chain; 6717 // NOTE: The Vulkan WG doesn't want us checking pApiVersion for NULL, but instead 6718 // prefers us crashing. 6719 *pApiVersion = VK_HEADER_VERSION_COMPLETE; 6720 return VK_SUCCESS; 6721} 6722 6723VKAPI_ATTR VkResult VKAPI_CALL 6724terminator_EnumerateInstanceExtensionProperties(const VkEnumerateInstanceExtensionPropertiesChain *chain, const char *pLayerName, 6725 uint32_t *pPropertyCount, VkExtensionProperties *pProperties) { 6726 (void)chain; 6727 struct loader_extension_list *global_ext_list = NULL; 6728 struct loader_layer_list instance_layers; 6729 struct loader_extension_list local_ext_list; 6730 struct loader_icd_tramp_list icd_tramp_list; 6731 uint32_t copy_size; 6732 VkResult res = VK_SUCCESS; 6733 struct loader_envvar_all_filters layer_filters = {0}; 6734 6735 memset(&local_ext_list, 0, sizeof(local_ext_list)); 6736 memset(&instance_layers, 0, sizeof(instance_layers)); 6737 memset(&icd_tramp_list, 0, sizeof(icd_tramp_list)); 6738 6739 res = parse_layer_environment_var_filters(NULL, &layer_filters); 6740 if (VK_SUCCESS != res) { 6741 goto out; 6742 } 6743 6744 // Get layer libraries if needed 6745 if (pLayerName && strlen(pLayerName) != 0) { 6746 if (vk_string_validate(MaxLoaderStringLength, pLayerName) != VK_STRING_ERROR_NONE) { 6747 assert(VK_FALSE && "vkEnumerateInstanceExtensionProperties: pLayerName is too long or is badly formed"); 6748 res = VK_ERROR_EXTENSION_NOT_PRESENT; 6749 goto out; 6750 } 6751 6752 res = loader_scan_for_layers(NULL, &instance_layers, &layer_filters); 6753 if (VK_SUCCESS != res) { 6754 goto out; 6755 } 6756 for (uint32_t i = 0; i < instance_layers.count; i++) { 6757 struct loader_layer_properties *props = &instance_layers.list[i]; 6758 if (strcmp(props->info.layerName, pLayerName) == 0) { 6759 global_ext_list = &props->instance_extension_list; 6760 break; 6761 } 6762 } 6763 } else { 6764 // Preload ICD libraries so subsequent calls to EnumerateInstanceExtensionProperties don't have to load them 6765 loader_preload_icds(); 6766 6767 // Scan/discover all ICD libraries 6768 res = loader_icd_scan(NULL, &icd_tramp_list, NULL, NULL); 6769 // EnumerateInstanceExtensionProperties can't return anything other than OOM or VK_ERROR_LAYER_NOT_PRESENT 6770 if ((VK_SUCCESS != res && icd_tramp_list.count > 0) || res == VK_ERROR_OUT_OF_HOST_MEMORY) { 6771 goto out; 6772 } 6773 // Get extensions from all ICD's, merge so no duplicates 6774 res = loader_get_icd_loader_instance_extensions(NULL, &icd_tramp_list, &local_ext_list); 6775 if (VK_SUCCESS != res) { 6776 goto out; 6777 } 6778 loader_scanned_icd_clear(NULL, &icd_tramp_list); 6779 6780 // Append enabled implicit layers. 6781 res = loader_scan_for_implicit_layers(NULL, &instance_layers, &layer_filters); 6782 if (VK_SUCCESS != res) { 6783 goto out; 6784 } 6785 for (uint32_t i = 0; i < instance_layers.count; i++) { 6786 struct loader_extension_list *ext_list = &instance_layers.list[i].instance_extension_list; 6787 loader_add_to_ext_list(NULL, &local_ext_list, ext_list->count, ext_list->list); 6788 } 6789 6790 global_ext_list = &local_ext_list; 6791 } 6792 6793 if (global_ext_list == NULL) { 6794 res = VK_ERROR_LAYER_NOT_PRESENT; 6795 goto out; 6796 } 6797 6798 if (pProperties == NULL) { 6799 *pPropertyCount = global_ext_list->count; 6800 goto out; 6801 } 6802 6803 copy_size = *pPropertyCount < global_ext_list->count ? *pPropertyCount : global_ext_list->count; 6804 for (uint32_t i = 0; i < copy_size; i++) { 6805 memcpy(&pProperties[i], &global_ext_list->list[i], sizeof(VkExtensionProperties)); 6806 } 6807 *pPropertyCount = copy_size; 6808 6809 if (copy_size < global_ext_list->count) { 6810 res = VK_INCOMPLETE; 6811 goto out; 6812 } 6813 6814out: 6815 loader_destroy_generic_list(NULL, (struct loader_generic_list *)&icd_tramp_list); 6816 loader_destroy_generic_list(NULL, (struct loader_generic_list *)&local_ext_list); 6817 loader_delete_layer_list_and_properties(NULL, &instance_layers); 6818 return res; 6819} 6820 6821VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateInstanceLayerProperties(const VkEnumerateInstanceLayerPropertiesChain *chain, 6822 uint32_t *pPropertyCount, 6823 VkLayerProperties *pProperties) { 6824 (void)chain; 6825 VkResult result = VK_SUCCESS; 6826 struct loader_layer_list instance_layer_list; 6827 struct loader_envvar_all_filters layer_filters = {0}; 6828 6829 LOADER_PLATFORM_THREAD_ONCE(&once_init, loader_initialize); 6830 6831 uint32_t copy_size; 6832 6833 result = parse_layer_environment_var_filters(NULL, &layer_filters); 6834 if (VK_SUCCESS != result) { 6835 goto out; 6836 } 6837 6838 // Get layer libraries 6839 memset(&instance_layer_list, 0, sizeof(instance_layer_list)); 6840 result = loader_scan_for_layers(NULL, &instance_layer_list, &layer_filters); 6841 if (VK_SUCCESS != result) { 6842 goto out; 6843 } 6844 6845 uint32_t active_layer_count = 0; 6846 for (uint32_t i = 0; i < instance_layer_list.count; i++) { 6847 if (instance_layer_list.list[i].settings_control_value == LOADER_SETTINGS_LAYER_CONTROL_ON || 6848 instance_layer_list.list[i].settings_control_value == LOADER_SETTINGS_LAYER_CONTROL_DEFAULT) { 6849 active_layer_count++; 6850 } 6851 } 6852 6853 if (pProperties == NULL) { 6854 *pPropertyCount = active_layer_count; 6855 goto out; 6856 } 6857 6858 copy_size = (*pPropertyCount < active_layer_count) ? *pPropertyCount : active_layer_count; 6859 uint32_t output_properties_index = 0; 6860 for (uint32_t i = 0; i < copy_size; i++) { 6861 if (instance_layer_list.list[i].settings_control_value == LOADER_SETTINGS_LAYER_CONTROL_ON || 6862 instance_layer_list.list[i].settings_control_value == LOADER_SETTINGS_LAYER_CONTROL_DEFAULT) { 6863 memcpy(&pProperties[output_properties_index], &instance_layer_list.list[i].info, sizeof(VkLayerProperties)); 6864 output_properties_index++; 6865 } 6866 } 6867 6868 *pPropertyCount = copy_size; 6869 6870 if (copy_size < instance_layer_list.count) { 6871 result = VK_INCOMPLETE; 6872 goto out; 6873 } 6874 6875out: 6876 6877 loader_delete_layer_list_and_properties(NULL, &instance_layer_list); 6878 return result; 6879} 6880 6881// ---- Vulkan Core 1.1 terminators 6882 6883VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumeratePhysicalDeviceGroups( 6884 VkInstance instance, uint32_t *pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties *pPhysicalDeviceGroupProperties) { 6885 struct loader_instance *inst = (struct loader_instance *)instance; 6886 6887 VkResult res = VK_SUCCESS; 6888 struct loader_icd_term *icd_term; 6889 uint32_t total_count = 0; 6890 uint32_t cur_icd_group_count = 0; 6891 VkPhysicalDeviceGroupProperties **new_phys_dev_groups = NULL; 6892 struct loader_physical_device_group_term *local_phys_dev_groups = NULL; 6893 PFN_vkEnumeratePhysicalDeviceGroups fpEnumeratePhysicalDeviceGroups = NULL; 6894 struct loader_icd_physical_devices *sorted_phys_dev_array = NULL; 6895 uint32_t sorted_count = 0; 6896 6897 // For each ICD, query the number of physical device groups, and then get an 6898 // internal value for those physical devices. 6899 icd_term = inst->icd_terms; 6900 for (uint32_t icd_idx = 0; NULL != icd_term; icd_term = icd_term->next, icd_idx++) { 6901 cur_icd_group_count = 0; 6902 6903 // Get the function pointer to use to call into the ICD. This could be the core or KHR version 6904 if (inst->enabled_known_extensions.khr_device_group_creation) { 6905 fpEnumeratePhysicalDeviceGroups = icd_term->dispatch.EnumeratePhysicalDeviceGroupsKHR; 6906 } else { 6907 fpEnumeratePhysicalDeviceGroups = icd_term->dispatch.EnumeratePhysicalDeviceGroups; 6908 } 6909 6910 if (NULL == fpEnumeratePhysicalDeviceGroups) { 6911 // Treat each ICD's GPU as it's own group if the extension isn't supported 6912 res = icd_term->dispatch.EnumeratePhysicalDevices(icd_term->instance, &cur_icd_group_count, NULL); 6913 if (res != VK_SUCCESS) { 6914 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 6915 "terminator_EnumeratePhysicalDeviceGroups: Failed during dispatch call of \'EnumeratePhysicalDevices\' " 6916 "to ICD %d to get plain phys dev count.", 6917 icd_idx); 6918 continue; 6919 } 6920 } else { 6921 // Query the actual group info 6922 res = fpEnumeratePhysicalDeviceGroups(icd_term->instance, &cur_icd_group_count, NULL); 6923 if (res != VK_SUCCESS) { 6924 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 6925 "terminator_EnumeratePhysicalDeviceGroups: Failed during dispatch call of " 6926 "\'EnumeratePhysicalDeviceGroups\' to ICD %d to get count.", 6927 icd_idx); 6928 continue; 6929 } 6930 } 6931 total_count += cur_icd_group_count; 6932 } 6933 6934 // If GPUs not sorted yet, look through them and generate list of all available GPUs 6935 if (0 == total_count || 0 == inst->total_gpu_count) { 6936 res = setup_loader_term_phys_devs(inst); 6937 if (VK_SUCCESS != res) { 6938 goto out; 6939 } 6940 } 6941 6942 if (NULL != pPhysicalDeviceGroupProperties) { 6943 // Create an array for the new physical device groups, which will be stored 6944 // in the instance for the Terminator code. 6945 new_phys_dev_groups = (VkPhysicalDeviceGroupProperties **)loader_instance_heap_calloc( 6946 inst, total_count * sizeof(VkPhysicalDeviceGroupProperties *), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 6947 if (NULL == new_phys_dev_groups) { 6948 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 6949 "terminator_EnumeratePhysicalDeviceGroups: Failed to allocate new physical device group array of size %d", 6950 total_count); 6951 res = VK_ERROR_OUT_OF_HOST_MEMORY; 6952 goto out; 6953 } 6954 6955 // Create a temporary array (on the stack) to keep track of the 6956 // returned VkPhysicalDevice values. 6957 local_phys_dev_groups = loader_stack_alloc(sizeof(struct loader_physical_device_group_term) * total_count); 6958 // Initialize the memory to something valid 6959 memset(local_phys_dev_groups, 0, sizeof(struct loader_physical_device_group_term) * total_count); 6960 6961#if defined(_WIN32) 6962 // Get the physical devices supported by platform sorting mechanism into a separate list 6963 res = windows_read_sorted_physical_devices(inst, &sorted_count, &sorted_phys_dev_array); 6964 if (VK_SUCCESS != res) { 6965 goto out; 6966 } 6967#endif 6968 6969 cur_icd_group_count = 0; 6970 icd_term = inst->icd_terms; 6971 for (uint8_t icd_idx = 0; NULL != icd_term; icd_term = icd_term->next, icd_idx++) { 6972 uint32_t count_this_time = total_count - cur_icd_group_count; 6973 6974 // Get the function pointer to use to call into the ICD. This could be the core or KHR version 6975 if (inst->enabled_known_extensions.khr_device_group_creation) { 6976 fpEnumeratePhysicalDeviceGroups = icd_term->dispatch.EnumeratePhysicalDeviceGroupsKHR; 6977 } else { 6978 fpEnumeratePhysicalDeviceGroups = icd_term->dispatch.EnumeratePhysicalDeviceGroups; 6979 } 6980 6981 if (NULL == fpEnumeratePhysicalDeviceGroups) { 6982 icd_term->dispatch.EnumeratePhysicalDevices(icd_term->instance, &count_this_time, NULL); 6983 6984 VkPhysicalDevice *phys_dev_array = loader_stack_alloc(sizeof(VkPhysicalDevice) * count_this_time); 6985 if (NULL == phys_dev_array) { 6986 loader_log( 6987 inst, VULKAN_LOADER_ERROR_BIT, 0, 6988 "terminator_EnumeratePhysicalDeviceGroups: Failed to allocate local physical device array of size %d", 6989 count_this_time); 6990 res = VK_ERROR_OUT_OF_HOST_MEMORY; 6991 goto out; 6992 } 6993 6994 res = icd_term->dispatch.EnumeratePhysicalDevices(icd_term->instance, &count_this_time, phys_dev_array); 6995 if (res != VK_SUCCESS) { 6996 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 6997 "terminator_EnumeratePhysicalDeviceGroups: Failed during dispatch call of " 6998 "\'EnumeratePhysicalDevices\' to ICD %d to get plain phys dev count.", 6999 icd_idx); 7000 goto out; 7001 } 7002 7003 // Add each GPU as it's own group 7004 for (uint32_t indiv_gpu = 0; indiv_gpu < count_this_time; indiv_gpu++) { 7005 uint32_t cur_index = indiv_gpu + cur_icd_group_count; 7006 local_phys_dev_groups[cur_index].this_icd_term = icd_term; 7007 local_phys_dev_groups[cur_index].icd_index = icd_idx; 7008 local_phys_dev_groups[cur_index].group_props.physicalDeviceCount = 1; 7009 local_phys_dev_groups[cur_index].group_props.physicalDevices[0] = phys_dev_array[indiv_gpu]; 7010 } 7011 7012 } else { 7013 res = fpEnumeratePhysicalDeviceGroups(icd_term->instance, &count_this_time, NULL); 7014 if (res != VK_SUCCESS) { 7015 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 7016 "terminator_EnumeratePhysicalDeviceGroups: Failed during dispatch call of " 7017 "\'EnumeratePhysicalDeviceGroups\' to ICD %d to get group count.", 7018 icd_idx); 7019 goto out; 7020 } 7021 if (cur_icd_group_count + count_this_time < *pPhysicalDeviceGroupCount) { 7022 // The total amount is still less than the amount of physical device group data passed in 7023 // by the callee. Therefore, we don't have to allocate any temporary structures and we 7024 // can just use the data that was passed in. 7025 res = fpEnumeratePhysicalDeviceGroups(icd_term->instance, &count_this_time, 7026 &pPhysicalDeviceGroupProperties[cur_icd_group_count]); 7027 if (res != VK_SUCCESS) { 7028 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 7029 "terminator_EnumeratePhysicalDeviceGroups: Failed during dispatch call of " 7030 "\'EnumeratePhysicalDeviceGroups\' to ICD %d to get group information.", 7031 icd_idx); 7032 goto out; 7033 } 7034 for (uint32_t group = 0; group < count_this_time; ++group) { 7035 uint32_t cur_index = group + cur_icd_group_count; 7036 local_phys_dev_groups[cur_index].group_props = pPhysicalDeviceGroupProperties[cur_index]; 7037 local_phys_dev_groups[cur_index].this_icd_term = icd_term; 7038 local_phys_dev_groups[cur_index].icd_index = icd_idx; 7039 } 7040 } else { 7041 // There's not enough space in the callee's allocated pPhysicalDeviceGroupProperties structs, 7042 // so we have to allocate temporary versions to collect all the data. However, we need to make 7043 // sure that at least the ones we do query utilize any pNext data in the callee's version. 7044 VkPhysicalDeviceGroupProperties *tmp_group_props = 7045 loader_stack_alloc(count_this_time * sizeof(VkPhysicalDeviceGroupProperties)); 7046 for (uint32_t group = 0; group < count_this_time; group++) { 7047 tmp_group_props[group].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES; 7048 uint32_t cur_index = group + cur_icd_group_count; 7049 if (*pPhysicalDeviceGroupCount > cur_index) { 7050 tmp_group_props[group].pNext = pPhysicalDeviceGroupProperties[cur_index].pNext; 7051 } else { 7052 tmp_group_props[group].pNext = NULL; 7053 } 7054 tmp_group_props[group].subsetAllocation = false; 7055 } 7056 7057 res = fpEnumeratePhysicalDeviceGroups(icd_term->instance, &count_this_time, tmp_group_props); 7058 if (res != VK_SUCCESS) { 7059 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 7060 "terminator_EnumeratePhysicalDeviceGroups: Failed during dispatch call of " 7061 "\'EnumeratePhysicalDeviceGroups\' to ICD %d to get group information for temp data.", 7062 icd_idx); 7063 goto out; 7064 } 7065 for (uint32_t group = 0; group < count_this_time; ++group) { 7066 uint32_t cur_index = group + cur_icd_group_count; 7067 local_phys_dev_groups[cur_index].group_props = tmp_group_props[group]; 7068 local_phys_dev_groups[cur_index].this_icd_term = icd_term; 7069 local_phys_dev_groups[cur_index].icd_index = icd_idx; 7070 } 7071 } 7072 if (VK_SUCCESS != res) { 7073 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 7074 "terminator_EnumeratePhysicalDeviceGroups: Failed during dispatch call of " 7075 "\'EnumeratePhysicalDeviceGroups\' to ICD %d to get content.", 7076 icd_idx); 7077 goto out; 7078 } 7079 } 7080 7081 cur_icd_group_count += count_this_time; 7082 } 7083 7084#if defined(LOADER_ENABLE_LINUX_SORT) 7085 if (is_linux_sort_enabled(inst)) { 7086 // Get the physical devices supported by platform sorting mechanism into a separate list 7087 res = linux_sort_physical_device_groups(inst, total_count, local_phys_dev_groups); 7088 } 7089#elif defined(_WIN32) 7090 // The Windows sorting information is only on physical devices. We need to take that and convert it to the group 7091 // information if it's present. 7092 if (sorted_count > 0) { 7093 res = 7094 windows_sort_physical_device_groups(inst, total_count, local_phys_dev_groups, sorted_count, sorted_phys_dev_array); 7095 } 7096#endif // LOADER_ENABLE_LINUX_SORT 7097 7098 // Just to be safe, make sure we successfully completed setup_loader_term_phys_devs above 7099 // before attempting to do the following. By verifying that setup_loader_term_phys_devs ran 7100 // first, it guarantees that each physical device will have a loader-specific handle. 7101 if (NULL != inst->phys_devs_term) { 7102 for (uint32_t group = 0; group < total_count; group++) { 7103 for (uint32_t group_gpu = 0; group_gpu < local_phys_dev_groups[group].group_props.physicalDeviceCount; 7104 group_gpu++) { 7105 bool found = false; 7106 for (uint32_t term_gpu = 0; term_gpu < inst->phys_dev_count_term; term_gpu++) { 7107 if (local_phys_dev_groups[group].group_props.physicalDevices[group_gpu] == 7108 inst->phys_devs_term[term_gpu]->phys_dev) { 7109 local_phys_dev_groups[group].group_props.physicalDevices[group_gpu] = 7110 (VkPhysicalDevice)inst->phys_devs_term[term_gpu]; 7111 found = true; 7112 break; 7113 } 7114 } 7115 if (!found) { 7116 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 7117 "terminator_EnumeratePhysicalDeviceGroups: Failed to find GPU %d in group %d returned by " 7118 "\'EnumeratePhysicalDeviceGroups\' in list returned by \'EnumeratePhysicalDevices\'", 7119 group_gpu, group); 7120 res = VK_ERROR_INITIALIZATION_FAILED; 7121 goto out; 7122 } 7123 } 7124 } 7125 } 7126 7127 uint32_t idx = 0; 7128 7129 // Copy or create everything to fill the new array of physical device groups 7130 for (uint32_t group = 0; group < total_count; group++) { 7131 // Skip groups which have been included through sorting 7132 if (local_phys_dev_groups[group].group_props.physicalDeviceCount == 0) { 7133 continue; 7134 } 7135 7136 // Find the VkPhysicalDeviceGroupProperties object in local_phys_dev_groups 7137 VkPhysicalDeviceGroupProperties *group_properties = &local_phys_dev_groups[group].group_props; 7138 7139 // Check if this physical device group with the same contents is already in the old buffer 7140 for (uint32_t old_idx = 0; old_idx < inst->phys_dev_group_count_term; old_idx++) { 7141 if (NULL != group_properties && NULL != inst->phys_dev_groups_term[old_idx] && 7142 group_properties->physicalDeviceCount == inst->phys_dev_groups_term[old_idx]->physicalDeviceCount) { 7143 bool found_all_gpus = true; 7144 for (uint32_t old_gpu = 0; old_gpu < inst->phys_dev_groups_term[old_idx]->physicalDeviceCount; old_gpu++) { 7145 bool found_gpu = false; 7146 for (uint32_t new_gpu = 0; new_gpu < group_properties->physicalDeviceCount; new_gpu++) { 7147 if (group_properties->physicalDevices[new_gpu] == 7148 inst->phys_dev_groups_term[old_idx]->physicalDevices[old_gpu]) { 7149 found_gpu = true; 7150 break; 7151 } 7152 } 7153 7154 if (!found_gpu) { 7155 found_all_gpus = false; 7156 break; 7157 } 7158 } 7159 if (!found_all_gpus) { 7160 continue; 7161 } else { 7162 new_phys_dev_groups[idx] = inst->phys_dev_groups_term[old_idx]; 7163 break; 7164 } 7165 } 7166 } 7167 // If this physical device group isn't in the old buffer, create it 7168 if (group_properties != NULL && NULL == new_phys_dev_groups[idx]) { 7169 new_phys_dev_groups[idx] = (VkPhysicalDeviceGroupProperties *)loader_instance_heap_alloc( 7170 inst, sizeof(VkPhysicalDeviceGroupProperties), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 7171 if (NULL == new_phys_dev_groups[idx]) { 7172 loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, 7173 "terminator_EnumeratePhysicalDeviceGroups: Failed to allocate physical device group Terminator " 7174 "object %d", 7175 idx); 7176 total_count = idx; 7177 res = VK_ERROR_OUT_OF_HOST_MEMORY; 7178 goto out; 7179 } 7180 memcpy(new_phys_dev_groups[idx], group_properties, sizeof(VkPhysicalDeviceGroupProperties)); 7181 } 7182 7183 ++idx; 7184 } 7185 } 7186 7187out: 7188 7189 if (NULL != pPhysicalDeviceGroupProperties) { 7190 if (VK_SUCCESS != res) { 7191 if (NULL != new_phys_dev_groups) { 7192 // We've encountered an error, so we should free the new buffers. 7193 for (uint32_t i = 0; i < total_count; i++) { 7194 // If an OOM occurred inside the copying of the new physical device groups into the existing array will 7195 // leave some of the old physical device groups in the array which may have been copied into the new array, 7196 // leading to them being freed twice. To avoid this we just make sure to not delete physical device groups 7197 // which were copied. 7198 bool found = false; 7199 if (NULL != inst->phys_devs_term) { 7200 for (uint32_t old_idx = 0; old_idx < inst->phys_dev_group_count_term; old_idx++) { 7201 if (new_phys_dev_groups[i] == inst->phys_dev_groups_term[old_idx]) { 7202 found = true; 7203 break; 7204 } 7205 } 7206 } 7207 if (!found) { 7208 loader_instance_heap_free(inst, new_phys_dev_groups[i]); 7209 } 7210 } 7211 loader_instance_heap_free(inst, new_phys_dev_groups); 7212 } 7213 } else { 7214 if (NULL != inst->phys_dev_groups_term) { 7215 // Free everything in the old array that was not copied into the new array 7216 // here. We can't attempt to do that before here since the previous loop 7217 // looking before the "out:" label may hit an out of memory condition resulting 7218 // in memory leaking. 7219 for (uint32_t i = 0; i < inst->phys_dev_group_count_term; i++) { 7220 bool found = false; 7221 for (uint32_t j = 0; j < total_count; j++) { 7222 if (inst->phys_dev_groups_term[i] == new_phys_dev_groups[j]) { 7223 found = true; 7224 break; 7225 } 7226 } 7227 if (!found) { 7228 loader_instance_heap_free(inst, inst->phys_dev_groups_term[i]); 7229 } 7230 } 7231 loader_instance_heap_free(inst, inst->phys_dev_groups_term); 7232 } 7233 7234 // Swap in the new physical device group list 7235 inst->phys_dev_group_count_term = total_count; 7236 inst->phys_dev_groups_term = new_phys_dev_groups; 7237 } 7238 7239 if (sorted_phys_dev_array != NULL) { 7240 for (uint32_t i = 0; i < sorted_count; ++i) { 7241 if (sorted_phys_dev_array[i].device_count > 0 && sorted_phys_dev_array[i].physical_devices != NULL) { 7242 loader_instance_heap_free(inst, sorted_phys_dev_array[i].physical_devices); 7243 } 7244 } 7245 loader_instance_heap_free(inst, sorted_phys_dev_array); 7246 } 7247 7248 uint32_t copy_count = inst->phys_dev_group_count_term; 7249 if (NULL != pPhysicalDeviceGroupProperties) { 7250 if (copy_count > *pPhysicalDeviceGroupCount) { 7251 copy_count = *pPhysicalDeviceGroupCount; 7252 loader_log(inst, VULKAN_LOADER_INFO_BIT, 0, 7253 "terminator_EnumeratePhysicalDeviceGroups : Trimming device count from %d to %d.", 7254 inst->phys_dev_group_count_term, copy_count); 7255 res = VK_INCOMPLETE; 7256 } 7257 7258 for (uint32_t i = 0; i < copy_count; i++) { 7259 memcpy(&pPhysicalDeviceGroupProperties[i], inst->phys_dev_groups_term[i], sizeof(VkPhysicalDeviceGroupProperties)); 7260 } 7261 } 7262 7263 *pPhysicalDeviceGroupCount = copy_count; 7264 7265 } else { 7266 *pPhysicalDeviceGroupCount = total_count; 7267 } 7268 return res; 7269} 7270