1/* 2 * 3 * Copyright (c) 2014-2022 The Khronos Group Inc. 4 * Copyright (c) 2014-2022 Valve Corporation 5 * Copyright (c) 2014-2022 LunarG, Inc. 6 * Copyright (C) 2015 Google Inc. 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 * 20 * Author: Jon Ashburn <jon@lunarg.com> 21 * Author: Courtney Goeltzenleuchter <courtney@LunarG.com> 22 * Author: Chia-I Wu <olvaffe@gmail.com> 23 * Author: Chia-I Wu <olv@lunarg.com> 24 * Author: Mark Lobodzinski <mark@LunarG.com> 25 * Author: Lenny Komow <lenny@lunarg.com> 26 * Author: Charles Giessen <charles@lunarg.com> 27 * 28 */ 29 30#pragma once 31 32#include "vulkan/vk_platform.h" 33#include <vulkan/vulkan.h> 34#include <vulkan/vk_layer.h> 35#include <vulkan/vk_icd.h> 36 37#include "vk_loader_platform.h" 38#include "vk_loader_layer.h" 39#include "vk_layer_dispatch_table.h" 40#include "vk_loader_extensions.h" 41 42#include "settings.h" 43 44typedef enum VkStringErrorFlagBits { 45 VK_STRING_ERROR_NONE = 0x00000000, 46 VK_STRING_ERROR_LENGTH = 0x00000001, 47 VK_STRING_ERROR_BAD_DATA = 0x00000002, 48 VK_STRING_ERROR_NULL_PTR = 0x00000004, 49} VkStringErrorFlagBits; 50typedef VkFlags VkStringErrorFlags; 51 52static const int MaxLoaderStringLength = 256; // 0xFF; 53static const unsigned char UTF8_ONE_BYTE_CODE = 192; // 0xC0; 54static const unsigned char UTF8_ONE_BYTE_MASK = 224; // 0xE0; 55static const unsigned char UTF8_TWO_BYTE_CODE = 224; // 0xE0; 56static const unsigned char UTF8_TWO_BYTE_MASK = 240; // 0xF0; 57static const unsigned char UTF8_THREE_BYTE_CODE = 240; // 0xF0; 58static const unsigned char UTF8_THREE_BYTE_MASK = 248; // 0xF8; 59static const unsigned char UTF8_DATA_BYTE_CODE = 128; // 0x80; 60static const unsigned char UTF8_DATA_BYTE_MASK = 192; // 0xC0; 61 62// form of all dynamic lists/arrays 63// only the list element should be changed 64struct loader_generic_list { 65 size_t capacity; 66 uint32_t count; 67 void *list; 68}; 69 70struct loader_string_list { 71 uint32_t allocated_count; 72 uint32_t count; 73 char **list; 74}; 75 76struct loader_extension_list { 77 size_t capacity; 78 uint32_t count; 79 VkExtensionProperties *list; 80}; 81 82struct loader_dev_ext_props { 83 VkExtensionProperties props; 84 struct loader_string_list entrypoints; 85}; 86 87struct loader_device_extension_list { 88 size_t capacity; 89 uint32_t count; 90 struct loader_dev_ext_props *list; 91}; 92 93struct loader_name_value { 94 char *name; 95 char *value; 96}; 97 98struct loader_layer_functions { 99 char *str_gipa; 100 char *str_gdpa; 101 char *str_negotiate_interface; 102 PFN_vkNegotiateLoaderLayerInterfaceVersion negotiate_layer_interface; 103 PFN_vkGetInstanceProcAddr get_instance_proc_addr; 104 PFN_vkGetDeviceProcAddr get_device_proc_addr; 105 PFN_GetPhysicalDeviceProcAddr get_physical_device_proc_addr; 106}; 107 108// This structure is used to store the json file version in a more manageable way. 109typedef struct { 110 uint16_t major; 111 uint16_t minor; 112 uint16_t patch; 113} loader_api_version; 114 115// Enumeration used to clearly identify reason for library load failure. 116enum loader_layer_library_status { 117 LOADER_LAYER_LIB_NOT_LOADED = 0, 118 119 LOADER_LAYER_LIB_SUCCESS_LOADED = 1, 120 121 LOADER_LAYER_LIB_ERROR_WRONG_BIT_TYPE = 20, 122 LOADER_LAYER_LIB_ERROR_FAILED_TO_LOAD = 21, 123 LOADER_LAYER_LIB_ERROR_OUT_OF_MEMORY = 22, 124}; 125 126enum layer_type_flags { 127 VK_LAYER_TYPE_FLAG_INSTANCE_LAYER = 0x1, // If not set, indicates Device layer 128 VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER = 0x2, // If not set, indicates Implicit layer 129 VK_LAYER_TYPE_FLAG_META_LAYER = 0x4, // If not set, indicates standard layer 130}; 131 132struct loader_layer_properties { 133 VkLayerProperties info; 134 enum layer_type_flags type_flags; 135 enum loader_settings_layer_control settings_control_value; 136 137 uint32_t interface_version; // PFN_vkNegotiateLoaderLayerInterfaceVersion 138 char *manifest_file_name; 139 char *lib_name; 140 enum loader_layer_library_status lib_status; 141 loader_platform_dl_handle lib_handle; 142 struct loader_layer_functions functions; 143 struct loader_extension_list instance_extension_list; 144 struct loader_device_extension_list device_extension_list; 145 struct loader_name_value disable_env_var; 146 struct loader_name_value enable_env_var; 147 struct loader_string_list component_layer_names; 148 struct { 149 char *enumerate_instance_extension_properties; 150 char *enumerate_instance_layer_properties; 151 char *enumerate_instance_version; 152 } pre_instance_functions; 153 struct loader_string_list override_paths; 154 bool is_override; 155 bool keep; 156 struct loader_string_list blacklist_layer_names; 157 struct loader_string_list app_key_paths; 158}; 159 160// Stores a list of loader_layer_properties 161struct loader_layer_list { 162 size_t capacity; 163 uint32_t count; 164 struct loader_layer_properties *list; 165}; 166 167// Stores a list of pointers to loader_layer_properties 168// Used for app_activated_layer_list and expanded_activated_layer_list 169struct loader_pointer_layer_list { 170 size_t capacity; 171 uint32_t count; 172 struct loader_layer_properties **list; 173}; 174 175typedef VkResult(VKAPI_PTR *PFN_vkDevExt)(VkDevice device); 176 177struct loader_dev_dispatch_table { 178 VkLayerDispatchTable core_dispatch; 179 PFN_vkDevExt ext_dispatch[MAX_NUM_UNKNOWN_EXTS]; 180 struct loader_device_terminator_dispatch extension_terminator_dispatch; 181}; 182 183// per CreateDevice structure 184struct loader_device { 185 struct loader_dev_dispatch_table loader_dispatch; 186 VkDevice chain_device; // device object from the dispatch chain 187 VkDevice icd_device; // device object from the icd 188 struct loader_physical_device_term *phys_dev_term; 189 190 VkAllocationCallbacks alloc_callbacks; 191 192 // List of activated device extensions that layers support (but not necessarily the driver which have functions that require 193 // trampolines to work correctly. EX - vkDebugMarkerSetObjectNameEXT can name wrapped handles like instance, physical device, 194 // or surface 195 struct { 196 bool ext_debug_marker_enabled; 197 bool ext_debug_utils_enabled; 198 } layer_extensions; 199 200 // List of activated device extensions that have terminators implemented in the loader 201 struct { 202 bool khr_swapchain_enabled; 203 bool khr_display_swapchain_enabled; 204 bool khr_device_group_enabled; 205 bool ext_debug_marker_enabled; 206 bool ext_debug_utils_enabled; 207 bool ext_full_screen_exclusive_enabled; 208 } driver_extensions; 209 210 struct loader_device *next; 211 212 // Makes vkGetDeviceProcAddr check if core functions are supported by the current app_api_version. 213 // Only set to true if VK_KHR_maintenance5 is enabled. 214 bool should_ignore_device_commands_from_newer_version; 215}; 216 217// Per ICD information 218 219// Per ICD structure 220struct loader_icd_term { 221 // pointers to find other structs 222 const struct loader_scanned_icd *scanned_icd; 223 const struct loader_instance *this_instance; 224 struct loader_device *logical_device_list; 225 VkInstance instance; // instance object from the icd 226 struct loader_icd_term_dispatch dispatch; 227 228 struct loader_icd_term *next; 229 230 PFN_PhysDevExt phys_dev_ext[MAX_NUM_UNKNOWN_EXTS]; 231 bool supports_get_dev_prop_2; 232}; 233 234// Per ICD library structure 235struct loader_icd_tramp_list { 236 size_t capacity; 237 uint32_t count; 238 struct loader_scanned_icd *scanned_list; 239}; 240 241struct loader_instance_dispatch_table { 242 VkLayerInstanceDispatchTable layer_inst_disp; // must be first entry in structure 243 244 // Physical device functions unknown to the loader 245 PFN_PhysDevExt phys_dev_ext[MAX_NUM_UNKNOWN_EXTS]; 246}; 247 248// Unique magic number identifier for the loader. 249#define LOADER_MAGIC_NUMBER 0x10ADED010110ADEDUL 250 251// Per instance structure 252struct loader_instance { 253 struct loader_instance_dispatch_table *disp; // must be first entry in structure 254 uint64_t magic; // Should be LOADER_MAGIC_NUMBER 255 256 // Store all the terminators for instance functions in case a layer queries one *after* vkCreateInstance 257 VkLayerInstanceDispatchTable terminator_dispatch; 258 259 // Vulkan API version the app is intending to use. 260 loader_api_version app_api_version; 261 262 // We need to manually track physical devices over time. If the user 263 // re-queries the information, we don't want to delete old data or 264 // create new data unless necessary. 265 uint32_t total_gpu_count; 266 uint32_t phys_dev_count_term; 267 struct loader_physical_device_term **phys_devs_term; 268 uint32_t phys_dev_count_tramp; 269 struct loader_physical_device_tramp **phys_devs_tramp; 270 271 // We also need to manually track physical device groups, but we don't need 272 // loader specific structures since we have that content in the physical 273 // device stored internal to the public structures. 274 uint32_t phys_dev_group_count_term; 275 struct VkPhysicalDeviceGroupProperties **phys_dev_groups_term; 276 277 struct loader_instance *next; 278 279 uint32_t total_icd_count; 280 struct loader_icd_term *icd_terms; 281 struct loader_icd_tramp_list icd_tramp_list; 282 283 // Must store the strings inside loader_instance directly - since the asm code will offset into 284 // loader_instance to get the function name 285 uint32_t dev_ext_disp_function_count; 286 char *dev_ext_disp_functions[MAX_NUM_UNKNOWN_EXTS]; 287 uint32_t phys_dev_ext_disp_function_count; 288 char *phys_dev_ext_disp_functions[MAX_NUM_UNKNOWN_EXTS]; 289 290 struct loader_msg_callback_map_entry *icd_msg_callback_map; 291 292 struct loader_string_list enabled_layer_names; 293 294 struct loader_layer_list instance_layer_list; 295 bool override_layer_present; 296 297 // List of activated layers. 298 // app_ is the version based on exactly what the application asked for. 299 // This is what must be returned to the application on Enumerate calls. 300 // expanded_ is the version based on expanding meta-layers into their 301 // individual component layers. This is what is used internally. 302 struct loader_pointer_layer_list app_activated_layer_list; 303 struct loader_pointer_layer_list expanded_activated_layer_list; 304 305 VkInstance instance; // layers/ICD instance returned to trampoline 306 307 struct loader_extension_list ext_list; // icds and loaders extensions 308 struct loader_instance_extension_enables enabled_known_extensions; 309 310 // Stores debug callbacks - used in the log. 311 VkLayerDbgFunctionNode *current_dbg_function_head; // Current head 312 VkLayerDbgFunctionNode *instance_only_dbg_function_head; // Only used for instance create/destroy 313 314 VkAllocationCallbacks alloc_callbacks; 315 316 // Set to true after vkCreateInstance has returned - necessary for loader_gpa_instance_terminator() 317 bool instance_finished_creation; 318 319 loader_settings settings; 320 321 bool portability_enumeration_enabled; 322 bool portability_enumeration_flag_bit_set; 323 bool portability_enumeration_extension_enabled; 324 325 bool wsi_surface_enabled; 326#if defined(VK_USE_PLATFORM_WIN32_KHR) 327 bool wsi_win32_surface_enabled; 328#endif 329#if defined(VK_USE_PLATFORM_WAYLAND_KHR) 330 bool wsi_wayland_surface_enabled; 331#endif 332#if defined(VK_USE_PLATFORM_XCB_KHR) 333 bool wsi_xcb_surface_enabled; 334#endif 335#if defined(VK_USE_PLATFORM_XLIB_KHR) 336 bool wsi_xlib_surface_enabled; 337#endif 338#if defined(VK_USE_PLATFORM_DIRECTFB_EXT) 339 bool wsi_directfb_surface_enabled; 340#endif 341#if defined(VK_USE_PLATFORM_ANDROID_KHR) 342 bool wsi_android_surface_enabled; 343#endif 344#if defined(VK_USE_PLATFORM_OHOS) 345 bool wsi_ohos_surface_enabled; 346#endif 347#if defined(VK_USE_PLATFORM_MACOS_MVK) 348 bool wsi_macos_surface_enabled; 349#endif 350#if defined(VK_USE_PLATFORM_IOS_MVK) 351 bool wsi_ios_surface_enabled; 352#endif 353#if defined(VK_USE_PLATFORM_GGP) 354 bool wsi_ggp_surface_enabled; 355#endif 356 bool wsi_headless_surface_enabled; 357#if defined(VK_USE_PLATFORM_METAL_EXT) 358 bool wsi_metal_surface_enabled; 359#endif 360#if defined(VK_USE_PLATFORM_FUCHSIA) 361 bool wsi_imagepipe_surface_enabled; 362#endif 363#if defined(VK_USE_PLATFORM_SCREEN_QNX) 364 bool wsi_screen_surface_enabled; 365#endif 366#if defined(VK_USE_PLATFORM_VI_NN) 367 bool wsi_vi_surface_enabled; 368#endif 369 bool wsi_display_enabled; 370 bool wsi_display_props2_enabled; 371 bool create_terminator_invalid_extension; 372 bool supports_get_dev_prop_2; 373}; 374 375// VkPhysicalDevice requires special treatment by loader. Firstly, terminator 376// code must be able to get the struct loader_icd_term to call into the proper 377// driver (multiple ICD/gpu case). This can be accomplished by wrapping the 378// created VkPhysicalDevice in loader terminate_EnumeratePhysicalDevices(). 379// Secondly, the loader must be able to handle wrapped by layer VkPhysicalDevice 380// in trampoline code. This implies, that the loader trampoline code must also 381// wrap the VkPhysicalDevice object in trampoline code. Thus, loader has to 382// wrap the VkPhysicalDevice created object twice. In trampoline code it can't 383// rely on the terminator object wrapping since a layer may also wrap. Since 384// trampoline code wraps the VkPhysicalDevice this means all loader trampoline 385// code that passes a VkPhysicalDevice should unwrap it. 386 387// Unique identifier for physical devices 388#define PHYS_TRAMP_MAGIC_NUMBER 0x10ADED020210ADEDUL 389 390// Per enumerated PhysicalDevice structure, used to wrap in trampoline code and 391// also same structure used to wrap in terminator code 392struct loader_physical_device_tramp { 393 struct loader_instance_dispatch_table *disp; // must be first entry in structure 394 struct loader_instance *this_instance; 395 uint64_t magic; // Should be PHYS_TRAMP_MAGIC_NUMBER 396 VkPhysicalDevice phys_dev; // object from layers/loader terminator 397}; 398 399// Per enumerated PhysicalDevice structure, used to wrap in terminator code 400struct loader_physical_device_term { 401 struct loader_instance_dispatch_table *disp; // must be first entry in structure 402 struct loader_icd_term *this_icd_term; 403 uint8_t icd_index; 404 VkPhysicalDevice phys_dev; // object from ICD 405}; 406 407#if defined(LOADER_ENABLE_LINUX_SORT) 408// Structure for storing the relevant device information for selecting a device. 409// NOTE: Needs to be defined here so we can store this content in the term structure 410// for quicker sorting. 411struct LinuxSortedDeviceInfo { 412 // Associated Vulkan Physical Device 413 VkPhysicalDevice physical_device; 414 bool default_device; 415 416 // Loader specific items about the driver providing support for this physical device 417 uint32_t icd_index; 418 struct loader_icd_term *icd_term; 419 420 // Some generic device properties 421 VkPhysicalDeviceType device_type; 422 char device_name[VK_MAX_PHYSICAL_DEVICE_NAME_SIZE]; 423 uint32_t vendor_id; 424 uint32_t device_id; 425 426 // PCI information on this device 427 bool has_pci_bus_info; 428 uint32_t pci_domain; 429 uint32_t pci_bus; 430 uint32_t pci_device; 431 uint32_t pci_function; 432}; 433#endif // LOADER_ENABLE_LINUX_SORT 434 435// Per enumerated PhysicalDeviceGroup structure, used to wrap in terminator code 436struct loader_physical_device_group_term { 437 struct loader_icd_term *this_icd_term; 438 uint8_t icd_index; 439 VkPhysicalDeviceGroupProperties group_props; 440#if defined(LOADER_ENABLE_LINUX_SORT) 441 struct LinuxSortedDeviceInfo internal_device_info[VK_MAX_DEVICE_GROUP_SIZE]; 442#endif // LOADER_ENABLE_LINUX_SORT 443}; 444 445struct loader_struct { 446 struct loader_instance *instances; 447}; 448 449struct loader_scanned_icd { 450 char *lib_name; 451 loader_platform_dl_handle handle; 452 uint32_t api_version; 453 uint32_t interface_version; 454 PFN_vkGetInstanceProcAddr GetInstanceProcAddr; 455 PFN_GetPhysicalDeviceProcAddr GetPhysicalDeviceProcAddr; 456 PFN_vkCreateInstance CreateInstance; 457 PFN_vkEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties; 458#if defined(VK_USE_PLATFORM_WIN32_KHR) 459 PFN_vk_icdEnumerateAdapterPhysicalDevices EnumerateAdapterPhysicalDevices; 460#endif 461}; 462 463enum loader_data_files_type { 464 LOADER_DATA_FILE_MANIFEST_DRIVER = 0, 465 LOADER_DATA_FILE_MANIFEST_EXPLICIT_LAYER, 466 LOADER_DATA_FILE_MANIFEST_IMPLICIT_LAYER, 467 LOADER_DATA_FILE_NUM_TYPES // Not a real field, used for possible loop terminator 468}; 469 470struct loader_icd_physical_devices { 471 uint32_t device_count; 472 VkPhysicalDevice *physical_devices; 473 uint32_t icd_index; 474 struct loader_icd_term *icd_term; 475#if defined(WIN32) 476 LUID windows_adapter_luid; 477#endif 478}; 479 480struct loader_msg_callback_map_entry { 481 VkDebugReportCallbackEXT icd_obj; 482 VkDebugReportCallbackEXT loader_obj; 483}; 484 485typedef enum loader_filter_string_type { 486 FILTER_STRING_FULLNAME = 0, 487 FILTER_STRING_SUBSTRING, 488 FILTER_STRING_PREFIX, 489 FILTER_STRING_SUFFIX, 490 FILTER_STRING_SPECIAL, 491} loader_filter_string_type; 492 493struct loader_envvar_filter_value { 494 char value[VK_MAX_EXTENSION_NAME_SIZE]; 495 size_t length; 496 loader_filter_string_type type; 497}; 498 499#define MAX_ADDITIONAL_FILTERS 16 500struct loader_envvar_filter { 501 uint32_t count; 502 struct loader_envvar_filter_value filters[MAX_ADDITIONAL_FILTERS]; 503}; 504struct loader_envvar_disable_layers_filter { 505 struct loader_envvar_filter additional_filters; 506 bool disable_all; 507 bool disable_all_implicit; 508 bool disable_all_explicit; 509}; 510 511struct loader_envvar_all_filters { 512 struct loader_envvar_filter enable_filter; 513 struct loader_envvar_disable_layers_filter disable_filter; 514 struct loader_envvar_filter allow_filter; 515}; 516