1 /* 2 * 3 * Copyright (c) 2014-2017 The Khronos Group Inc. 4 * Copyright (c) 2014-2017 Valve Corporation 5 * Copyright (c) 2014-2017 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 (at) lunarg.com> 21 * Author: Courtney Goeltzenleuchter <courtney (at) LunarG.com> 22 * Author: Chia-I Wu <olvaffe (at) gmail.com> 23 * Author: Chia-I Wu <olv (at) lunarg.com> 24 * Author: Mark Lobodzinski <mark (at) LunarG.com> 25 * 26 */ 27 28 #ifndef LOADER_H 29 #define LOADER_H 30 31 #include <vulkan/vulkan.h> 32 #include "vk_loader_platform.h" 33 #include "vk_loader_layer.h" 34 #include <vulkan/vk_layer.h> 35 #include <vulkan/vk_icd.h> 36 #include <assert.h> 37 #include "vk_loader_extensions.h" 38 39 #if defined(__GNUC__) && __GNUC__ >= 4 40 #define LOADER_EXPORT __attribute__((visibility("default"))) 41 #elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590) 42 #define LOADER_EXPORT __attribute__((visibility("default"))) 43 #else 44 #define LOADER_EXPORT 45 #endif 46 47 // A debug option to disable allocators at compile time to investigate future issues. 48 #define DEBUG_DISABLE_APP_ALLOCATORS 0 49 50 #define MAX_STRING_SIZE 1024 51 52 // This is defined in vk_layer.h, but if there's problems we need to create the define 53 // here. 54 #ifndef MAX_NUM_UNKNOWN_EXTS 55 #define MAX_NUM_UNKNOWN_EXTS 250 56 #endif 57 58 enum layer_type_flags { 59 VK_LAYER_TYPE_FLAG_INSTANCE_LAYER = 0x1, // If not set, indicates Device layer 60 VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER = 0x2, // If not set, indicates Implicit layer 61 VK_LAYER_TYPE_FLAG_META_LAYER = 0x4, // If not set, indicates standard layer 62 }; 63 64 typedef enum VkStringErrorFlagBits { 65 VK_STRING_ERROR_NONE = 0x00000000, 66 VK_STRING_ERROR_LENGTH = 0x00000001, 67 VK_STRING_ERROR_BAD_DATA = 0x00000002, 68 } VkStringErrorFlagBits; 69 typedef VkFlags VkStringErrorFlags; 70 71 static const int MaxLoaderStringLength = 256; 72 static const char UTF8_ONE_BYTE_CODE = 0xC0; 73 static const char UTF8_ONE_BYTE_MASK = 0xE0; 74 static const char UTF8_TWO_BYTE_CODE = 0xE0; 75 static const char UTF8_TWO_BYTE_MASK = 0xF0; 76 static const char UTF8_THREE_BYTE_CODE = 0xF0; 77 static const char UTF8_THREE_BYTE_MASK = 0xF8; 78 static const char UTF8_DATA_BYTE_CODE = 0x80; 79 static const char UTF8_DATA_BYTE_MASK = 0xC0; 80 81 struct VkStructureHeader { 82 VkStructureType sType; 83 const void *pNext; 84 }; 85 86 // form of all dynamic lists/arrays 87 // only the list element should be changed 88 struct loader_generic_list { 89 size_t capacity; 90 uint32_t count; 91 void *list; 92 }; 93 94 struct loader_extension_list { 95 size_t capacity; 96 uint32_t count; 97 VkExtensionProperties *list; 98 }; 99 100 struct loader_dev_ext_props { 101 VkExtensionProperties props; 102 uint32_t entrypoint_count; 103 char **entrypoints; 104 }; 105 106 struct loader_device_extension_list { 107 size_t capacity; 108 uint32_t count; 109 struct loader_dev_ext_props *list; 110 }; 111 112 struct loader_name_value { 113 char name[MAX_STRING_SIZE]; 114 char value[MAX_STRING_SIZE]; 115 }; 116 117 struct loader_layer_functions { 118 char str_gipa[MAX_STRING_SIZE]; 119 char str_gdpa[MAX_STRING_SIZE]; 120 char str_negotiate_interface[MAX_STRING_SIZE]; 121 PFN_vkNegotiateLoaderLayerInterfaceVersion negotiate_layer_interface; 122 PFN_vkGetInstanceProcAddr get_instance_proc_addr; 123 PFN_vkGetDeviceProcAddr get_device_proc_addr; 124 PFN_GetPhysicalDeviceProcAddr get_physical_device_proc_addr; 125 }; 126 127 struct loader_layer_properties { 128 VkLayerProperties info; 129 enum layer_type_flags type_flags; 130 uint32_t interface_version; // PFN_vkNegotiateLoaderLayerInterfaceVersion 131 char lib_name[MAX_STRING_SIZE]; 132 loader_platform_dl_handle lib_handle; 133 struct loader_layer_functions functions; 134 struct loader_extension_list instance_extension_list; 135 struct loader_device_extension_list device_extension_list; 136 struct loader_name_value disable_env_var; 137 struct loader_name_value enable_env_var; 138 uint32_t num_component_layers; 139 char (*component_layer_names)[MAX_STRING_SIZE]; 140 struct { 141 char enumerate_instance_extension_properties[MAX_STRING_SIZE]; 142 char enumerate_instance_layer_properties[MAX_STRING_SIZE]; 143 } pre_instance_functions; 144 }; 145 146 struct loader_layer_list { 147 size_t capacity; 148 uint32_t count; 149 struct loader_layer_properties *list; 150 }; 151 152 struct loader_dispatch_hash_list { 153 size_t capacity; 154 uint32_t count; 155 uint32_t *index; // index into the dev_ext dispatch table 156 }; 157 158 // loader_dispatch_hash_entry and loader_dev_ext_dispatch_table.dev_ext have 159 // one to one correspondence; one loader_dispatch_hash_entry for one dev_ext 160 // dispatch entry. 161 // Also have a one to one correspondence with functions in dev_ext_trampoline.c 162 struct loader_dispatch_hash_entry { 163 char *func_name; 164 struct loader_dispatch_hash_list list; // to handle hashing collisions 165 }; 166 167 typedef void(VKAPI_PTR *PFN_vkDevExt)(VkDevice device); 168 struct loader_dev_ext_dispatch_table { 169 PFN_vkDevExt dev_ext[MAX_NUM_UNKNOWN_EXTS]; 170 }; 171 172 struct loader_dev_dispatch_table { 173 VkLayerDispatchTable core_dispatch; 174 struct loader_dev_ext_dispatch_table ext_dispatch; 175 }; 176 177 // per CreateDevice structure 178 struct loader_device { 179 struct loader_dev_dispatch_table loader_dispatch; 180 VkDevice chain_device; // device object from the dispatch chain 181 VkDevice icd_device; // device object from the icd 182 struct loader_physical_device_term *phys_dev_term; 183 184 // List of activated layers. 185 // app_ is the version based on exactly what the application asked for. 186 // This is what must be returned to the application on Enumerate calls. 187 // expanded_ is the version based on expanding meta-layers into their 188 // individual component layers. This is what is used internally. 189 struct loader_layer_list app_activated_layer_list; 190 struct loader_layer_list expanded_activated_layer_list; 191 192 VkAllocationCallbacks alloc_callbacks; 193 194 struct loader_device *next; 195 }; 196 197 // Per ICD information 198 199 // Per ICD structure 200 struct loader_icd_term { 201 // pointers to find other structs 202 const struct loader_scanned_icd *scanned_icd; 203 const struct loader_instance *this_instance; 204 struct loader_device *logical_device_list; 205 VkInstance instance; // instance object from the icd 206 struct loader_icd_term_dispatch dispatch; 207 208 struct loader_icd_term *next; 209 210 PFN_PhysDevExt phys_dev_ext[MAX_NUM_UNKNOWN_EXTS]; 211 }; 212 213 // Per ICD library structure 214 struct loader_icd_tramp_list { 215 size_t capacity; 216 uint32_t count; 217 struct loader_scanned_icd *scanned_list; 218 }; 219 220 struct loader_instance_dispatch_table { 221 VkLayerInstanceDispatchTable layer_inst_disp; // must be first entry in structure 222 223 // Physical device functions unknown to the loader 224 PFN_PhysDevExt phys_dev_ext[MAX_NUM_UNKNOWN_EXTS]; 225 }; 226 227 // Per instance structure 228 struct loader_instance { 229 struct loader_instance_dispatch_table *disp; // must be first entry in structure 230 231 // We need to manually track physical devices over time. If the user 232 // re-queries the information, we don't want to delete old data or 233 // create new data unless necessary. 234 uint32_t total_gpu_count; 235 uint32_t phys_dev_count_term; 236 struct loader_physical_device_term **phys_devs_term; 237 uint32_t phys_dev_count_tramp; 238 struct loader_physical_device_tramp **phys_devs_tramp; 239 240 // We also need to manually track physical device groups, but we don't need 241 // loader specific structures since we have that content in the physical 242 // device stored internal to the public structures. 243 uint32_t phys_dev_group_count_term; 244 struct VkPhysicalDeviceGroupPropertiesKHX **phys_dev_groups_term; 245 uint32_t phys_dev_group_count_tramp; 246 struct VkPhysicalDeviceGroupPropertiesKHX **phys_dev_groups_tramp; 247 248 struct loader_instance *next; 249 250 uint32_t total_icd_count; 251 struct loader_icd_term *icd_terms; 252 struct loader_icd_tramp_list icd_tramp_list; 253 254 struct loader_dispatch_hash_entry dev_ext_disp_hash[MAX_NUM_UNKNOWN_EXTS]; 255 struct loader_dispatch_hash_entry phys_dev_ext_disp_hash[MAX_NUM_UNKNOWN_EXTS]; 256 257 struct loader_msg_callback_map_entry *icd_msg_callback_map; 258 259 struct loader_layer_list instance_layer_list; 260 261 // List of activated layers. 262 // app_ is the version based on exactly what the application asked for. 263 // This is what must be returned to the application on Enumerate calls. 264 // expanded_ is the version based on expanding meta-layers into their 265 // individual component layers. This is what is used internally. 266 struct loader_layer_list app_activated_layer_list; 267 struct loader_layer_list expanded_activated_layer_list; 268 269 VkInstance instance; // layers/ICD instance returned to trampoline 270 271 struct loader_extension_list ext_list; // icds and loaders extensions 272 union loader_instance_extension_enables enabled_known_extensions; 273 274 VkLayerDbgFunctionNode *DbgFunctionHead; 275 uint32_t num_tmp_callbacks; 276 VkDebugReportCallbackCreateInfoEXT *tmp_dbg_create_infos; 277 VkDebugReportCallbackEXT *tmp_callbacks; 278 279 VkAllocationCallbacks alloc_callbacks; 280 281 bool wsi_surface_enabled; 282 #ifdef VK_USE_PLATFORM_WIN32_KHR 283 bool wsi_win32_surface_enabled; 284 #endif 285 #ifdef VK_USE_PLATFORM_MIR_KHR 286 bool wsi_mir_surface_enabled; 287 #endif 288 #ifdef VK_USE_PLATFORM_WAYLAND_KHR 289 bool wsi_wayland_surface_enabled; 290 #endif 291 #ifdef VK_USE_PLATFORM_XCB_KHR 292 bool wsi_xcb_surface_enabled; 293 #endif 294 #ifdef VK_USE_PLATFORM_XLIB_KHR 295 bool wsi_xlib_surface_enabled; 296 #endif 297 #ifdef VK_USE_PLATFORM_ANDROID_KHR 298 bool wsi_android_surface_enabled; 299 #endif 300 bool wsi_display_enabled; 301 }; 302 303 // VkPhysicalDevice requires special treatment by loader. Firstly, terminator 304 // code must be able to get the struct loader_icd_term to call into the proper 305 // driver (multiple ICD/gpu case). This can be accomplished by wrapping the 306 // created VkPhysicalDevice in loader terminate_EnumeratePhysicalDevices(). 307 // Secondly, the loader must be able to handle wrapped by layer VkPhysicalDevice 308 // in trampoline code. This implies, that the loader trampoline code must also 309 // wrap the VkPhysicalDevice object in trampoline code. Thus, loader has to 310 // wrap the VkPhysicalDevice created object twice. In trampoline code it can't 311 // rely on the terminator object wrapping since a layer may also wrap. Since 312 // trampoline code wraps the VkPhysicalDevice this means all loader trampoline 313 // code that passes a VkPhysicalDevice should unwrap it. 314 315 // Per enumerated PhysicalDevice structure, used to wrap in trampoline code and 316 // also same structure used to wrap in terminator code 317 struct loader_physical_device_tramp { 318 struct loader_instance_dispatch_table *disp; // must be first entry in structure 319 struct loader_instance *this_instance; 320 VkPhysicalDevice phys_dev; // object from layers/loader terminator 321 }; 322 323 // Per enumerated PhysicalDevice structure, used to wrap in terminator code 324 struct loader_physical_device_term { 325 struct loader_instance_dispatch_table *disp; // must be first entry in structure 326 struct loader_icd_term *this_icd_term; 327 uint8_t icd_index; 328 VkPhysicalDevice phys_dev; // object from ICD 329 }; 330 331 struct loader_struct { 332 struct loader_instance *instances; 333 }; 334 335 struct loader_scanned_icd { 336 char *lib_name; 337 loader_platform_dl_handle handle; 338 uint32_t api_version; 339 uint32_t interface_version; 340 PFN_vkGetInstanceProcAddr GetInstanceProcAddr; 341 PFN_GetPhysicalDeviceProcAddr GetPhysicalDeviceProcAddr; 342 PFN_vkCreateInstance CreateInstance; 343 PFN_vkEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties; 344 }; 345 346 static inline struct loader_instance *loader_instance(VkInstance instance) { return (struct loader_instance *)instance; } 347 348 static inline VkPhysicalDevice loader_unwrap_physical_device(VkPhysicalDevice physicalDevice) { 349 struct loader_physical_device_tramp *phys_dev = (struct loader_physical_device_tramp *)physicalDevice; 350 return phys_dev->phys_dev; 351 } 352 353 static inline void loader_set_dispatch(void *obj, const void *data) { *((const void **)obj) = data; } 354 355 static inline VkLayerDispatchTable *loader_get_dispatch(const void *obj) { return *((VkLayerDispatchTable **)obj); } 356 357 static inline struct loader_dev_dispatch_table *loader_get_dev_dispatch(const void *obj) { 358 return *((struct loader_dev_dispatch_table **)obj); 359 } 360 361 static inline VkLayerInstanceDispatchTable *loader_get_instance_layer_dispatch(const void *obj) { 362 return *((VkLayerInstanceDispatchTable **)obj); 363 } 364 365 static inline struct loader_instance_dispatch_table *loader_get_instance_dispatch(const void *obj) { 366 return *((struct loader_instance_dispatch_table **)obj); 367 } 368 369 static inline void loader_init_dispatch(void *obj, const void *data) { 370 #ifdef DEBUG 371 assert(valid_loader_magic_value(obj) && 372 "Incompatible ICD, first dword must be initialized to " 373 "ICD_LOADER_MAGIC. See loader/README.md for details."); 374 #endif 375 376 loader_set_dispatch(obj, data); 377 } 378 379 // Global variables used across files 380 extern struct loader_struct loader; 381 extern THREAD_LOCAL_DECL struct loader_instance *tls_instance; 382 #if defined(_WIN32) && !defined(LOADER_DYNAMIC_LIB) 383 extern LOADER_PLATFORM_THREAD_ONCE_DEFINITION(once_init); 384 #endif 385 extern loader_platform_thread_mutex loader_lock; 386 extern loader_platform_thread_mutex loader_json_lock; 387 388 struct loader_msg_callback_map_entry { 389 VkDebugReportCallbackEXT icd_obj; 390 VkDebugReportCallbackEXT loader_obj; 391 }; 392 393 // Helper function definitions 394 void *loader_instance_heap_alloc(const struct loader_instance *instance, size_t size, VkSystemAllocationScope allocationScope); 395 void loader_instance_heap_free(const struct loader_instance *instance, void *pMemory); 396 void *loader_instance_heap_realloc(const struct loader_instance *instance, void *pMemory, size_t orig_size, size_t size, 397 VkSystemAllocationScope alloc_scope); 398 void *loader_instance_tls_heap_alloc(size_t size); 399 void loader_instance_tls_heap_free(void *pMemory); 400 void *loader_device_heap_alloc(const struct loader_device *device, size_t size, VkSystemAllocationScope allocationScope); 401 void loader_device_heap_free(const struct loader_device *device, void *pMemory); 402 void *loader_device_heap_realloc(const struct loader_device *device, void *pMemory, size_t orig_size, size_t size, 403 VkSystemAllocationScope alloc_scope); 404 405 void loader_log(const struct loader_instance *inst, VkFlags msg_type, int32_t msg_code, const char *format, ...); 406 407 bool compare_vk_extension_properties(const VkExtensionProperties *op1, const VkExtensionProperties *op2); 408 409 VkResult loader_validate_layers(const struct loader_instance *inst, const uint32_t layer_count, 410 const char *const *ppEnabledLayerNames, const struct loader_layer_list *list); 411 412 VkResult loader_validate_instance_extensions(const struct loader_instance *inst, const struct loader_extension_list *icd_exts, 413 const struct loader_layer_list *instance_layer, 414 const VkInstanceCreateInfo *pCreateInfo); 415 416 void loader_initialize(void); 417 VkResult loader_copy_layer_properties(const struct loader_instance *inst, struct loader_layer_properties *dst, 418 struct loader_layer_properties *src); 419 bool has_vk_extension_property_array(const VkExtensionProperties *vk_ext_prop, const uint32_t count, 420 const VkExtensionProperties *ext_array); 421 bool has_vk_extension_property(const VkExtensionProperties *vk_ext_prop, const struct loader_extension_list *ext_list); 422 423 VkResult loader_add_to_ext_list(const struct loader_instance *inst, struct loader_extension_list *ext_list, 424 uint32_t prop_list_count, const VkExtensionProperties *props); 425 VkResult loader_add_to_dev_ext_list(const struct loader_instance *inst, struct loader_device_extension_list *ext_list, 426 const VkExtensionProperties *props, uint32_t entry_count, char **entrys); 427 VkResult loader_add_device_extensions(const struct loader_instance *inst, 428 PFN_vkEnumerateDeviceExtensionProperties fpEnumerateDeviceExtensionProperties, 429 VkPhysicalDevice physical_device, const char *lib_name, 430 struct loader_extension_list *ext_list); 431 VkResult loader_init_generic_list(const struct loader_instance *inst, struct loader_generic_list *list_info, size_t element_size); 432 void loader_destroy_generic_list(const struct loader_instance *inst, struct loader_generic_list *list); 433 void loader_destroy_layer_list(const struct loader_instance *inst, struct loader_device *device, 434 struct loader_layer_list *layer_list); 435 void loader_delete_layer_properties(const struct loader_instance *inst, struct loader_layer_list *layer_list); 436 bool loader_find_layer_name_array(const char *name, uint32_t layer_count, const char layer_list[][VK_MAX_EXTENSION_NAME_SIZE]); 437 VkResult loader_add_to_layer_list(const struct loader_instance *inst, struct loader_layer_list *list, uint32_t prop_list_count, 438 const struct loader_layer_properties *props); 439 void loader_find_layer_name_add_list(const struct loader_instance *inst, const char *name, const enum layer_type_flags type_flags, 440 const struct loader_layer_list *source_list, struct loader_layer_list *target_list, 441 struct loader_layer_list *expanded_target_list); 442 void loader_scanned_icd_clear(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list); 443 VkResult loader_icd_scan(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list); 444 void loader_layer_scan(const struct loader_instance *inst, struct loader_layer_list *instance_layers); 445 void loader_implicit_layer_scan(const struct loader_instance *inst, struct loader_layer_list *instance_layers); 446 bool loader_is_implicit_layer_enabled(const struct loader_instance *inst, const struct loader_layer_properties *prop); 447 VkResult loader_get_icd_loader_instance_extensions(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list, 448 struct loader_extension_list *inst_exts); 449 struct loader_icd_term *loader_get_icd_and_device(const VkDevice device, struct loader_device **found_dev, uint32_t *icd_index); 450 void loader_init_dispatch_dev_ext(struct loader_instance *inst, struct loader_device *dev); 451 void *loader_dev_ext_gpa(struct loader_instance *inst, const char *funcName); 452 void *loader_get_dev_ext_trampoline(uint32_t index); 453 bool loader_phys_dev_ext_gpa(struct loader_instance *inst, const char *funcName, bool perform_checking, void **tramp_addr, 454 void **term_addr); 455 void *loader_get_phys_dev_ext_tramp(uint32_t index); 456 void *loader_get_phys_dev_ext_termin(uint32_t index); 457 struct loader_instance *loader_get_instance(const VkInstance instance); 458 void loader_deactivate_layers(const struct loader_instance *instance, struct loader_device *device, struct loader_layer_list *list); 459 struct loader_device *loader_create_logical_device(const struct loader_instance *inst, const VkAllocationCallbacks *pAllocator); 460 void loader_add_logical_device(const struct loader_instance *inst, struct loader_icd_term *icd_term, 461 struct loader_device *found_dev); 462 void loader_remove_logical_device(const struct loader_instance *inst, struct loader_icd_term *icd_term, 463 struct loader_device *found_dev, const VkAllocationCallbacks *pAllocator); 464 // NOTE: Outside of loader, this entry-point is only provided for error 465 // cleanup. 466 void loader_destroy_logical_device(const struct loader_instance *inst, struct loader_device *dev, 467 const VkAllocationCallbacks *pAllocator); 468 469 VkResult loader_enable_instance_layers(struct loader_instance *inst, const VkInstanceCreateInfo *pCreateInfo, 470 const struct loader_layer_list *instance_layers); 471 472 VkResult loader_create_instance_chain(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, 473 struct loader_instance *inst, VkInstance *created_instance); 474 475 void loader_activate_instance_layer_extensions(struct loader_instance *inst, VkInstance created_inst); 476 477 VkResult loader_create_device_chain(const struct loader_physical_device_tramp *pd, const VkDeviceCreateInfo *pCreateInfo, 478 const VkAllocationCallbacks *pAllocator, const struct loader_instance *inst, 479 struct loader_device *dev); 480 481 VkResult loader_validate_device_extensions(struct loader_physical_device_tramp *phys_dev, 482 const struct loader_layer_list *activated_device_layers, 483 const struct loader_extension_list *icd_exts, const VkDeviceCreateInfo *pCreateInfo); 484 485 VkResult setupLoaderTrampPhysDevs(VkInstance instance); 486 VkResult setupLoaderTermPhysDevs(struct loader_instance *inst); 487 488 VkStringErrorFlags vk_string_validate(const int max_length, const char *char_array); 489 490 #endif // LOADER_H 491