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