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