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