• 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/vk_sdk_platform.h"
34 #include <vulkan/vulkan.h>
35 #include <vulkan/vk_layer.h>
36 #include <vulkan/vk_icd.h>
37 
38 #include "vk_loader_platform.h"
39 #include "vk_loader_layer.h"
40 #include "vk_layer_dispatch_table.h"
41 #include "vk_loader_extensions.h"
42 
43 typedef enum VkStringErrorFlagBits {
44     VK_STRING_ERROR_NONE = 0x00000000,
45     VK_STRING_ERROR_LENGTH = 0x00000001,
46     VK_STRING_ERROR_BAD_DATA = 0x00000002,
47     VK_STRING_ERROR_NULL_PTR = 0x00000004,
48 } VkStringErrorFlagBits;
49 typedef VkFlags VkStringErrorFlags;
50 
51 static const int MaxLoaderStringLength = 256;           // 0xFF;
52 static const unsigned char UTF8_ONE_BYTE_CODE = 192;    // 0xC0;
53 static const unsigned char UTF8_ONE_BYTE_MASK = 224;    // 0xE0;
54 static const unsigned char UTF8_TWO_BYTE_CODE = 224;    // 0xE0;
55 static const unsigned char UTF8_TWO_BYTE_MASK = 240;    // 0xF0;
56 static const unsigned char UTF8_THREE_BYTE_CODE = 240;  // 0xF0;
57 static const unsigned char UTF8_THREE_BYTE_MASK = 248;  // 0xF8;
58 static const unsigned char UTF8_DATA_BYTE_CODE = 128;   // 0x80;
59 static const unsigned char UTF8_DATA_BYTE_MASK = 192;   // 0xC0;
60 
61 // form of all dynamic lists/arrays
62 // only the list element should be changed
63 struct loader_generic_list {
64     size_t capacity;
65     uint32_t count;
66     void *list;
67 };
68 
69 struct loader_extension_list {
70     size_t capacity;
71     uint32_t count;
72     VkExtensionProperties *list;
73 };
74 
75 struct loader_dev_ext_props {
76     VkExtensionProperties props;
77     uint32_t entrypoint_count;
78     char **entrypoints;
79 };
80 
81 struct loader_device_extension_list {
82     size_t capacity;
83     uint32_t count;
84     struct loader_dev_ext_props *list;
85 };
86 
87 struct loader_name_value {
88     char name[MAX_STRING_SIZE];
89     char value[MAX_STRING_SIZE];
90 };
91 
92 struct loader_layer_functions {
93     char str_gipa[MAX_STRING_SIZE];
94     char str_gdpa[MAX_STRING_SIZE];
95     char str_negotiate_interface[MAX_STRING_SIZE];
96     PFN_vkNegotiateLoaderLayerInterfaceVersion negotiate_layer_interface;
97     PFN_vkGetInstanceProcAddr get_instance_proc_addr;
98     PFN_vkGetDeviceProcAddr get_device_proc_addr;
99     PFN_GetPhysicalDeviceProcAddr get_physical_device_proc_addr;
100 };
101 
102 struct loader_override_expiration {
103     uint16_t year;
104     uint8_t month;
105     uint8_t day;
106     uint8_t hour;
107     uint8_t minute;
108 };
109 
110 // This structure is used to store the json file version in a more manageable way.
111 typedef struct {
112     uint16_t major;
113     uint16_t minor;
114     uint16_t patch;
115 } loader_api_version;
116 
117 // Enumeration used to clearly identify reason for library load failure.
118 enum loader_layer_library_status {
119     LOADER_LAYER_LIB_NOT_LOADED = 0,
120 
121     LOADER_LAYER_LIB_SUCCESS_LOADED = 1,
122 
123     LOADER_LAYER_LIB_ERROR_WRONG_BIT_TYPE = 20,
124     LOADER_LAYER_LIB_ERROR_FAILED_TO_LOAD = 21,
125 };
126 
127 enum layer_type_flags {
128     VK_LAYER_TYPE_FLAG_INSTANCE_LAYER = 0x1,  // If not set, indicates Device layer
129     VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER = 0x2,  // If not set, indicates Implicit layer
130     VK_LAYER_TYPE_FLAG_META_LAYER = 0x4,      // If not set, indicates standard layer
131 };
132 
133 struct loader_layer_properties {
134     VkLayerProperties info;
135     enum layer_type_flags type_flags;
136     uint32_t interface_version;  // PFN_vkNegotiateLoaderLayerInterfaceVersion
137     char manifest_file_name[MAX_STRING_SIZE];
138     char lib_name[MAX_STRING_SIZE];
139     enum loader_layer_library_status lib_status;
140     loader_platform_dl_handle lib_handle;
141     struct loader_layer_functions functions;
142     struct loader_extension_list instance_extension_list;
143     struct loader_device_extension_list device_extension_list;
144     struct loader_name_value disable_env_var;
145     struct loader_name_value enable_env_var;
146     uint32_t num_component_layers;
147     char (*component_layer_names)[MAX_STRING_SIZE];
148     struct {
149         char enumerate_instance_extension_properties[MAX_STRING_SIZE];
150         char enumerate_instance_layer_properties[MAX_STRING_SIZE];
151         char enumerate_instance_version[MAX_STRING_SIZE];
152     } pre_instance_functions;
153     uint32_t num_override_paths;
154     char (*override_paths)[MAX_STRING_SIZE];
155     bool is_override;
156     bool has_expiration;
157     struct loader_override_expiration expiration;
158     bool keep;
159     uint32_t num_blacklist_layers;
160     char (*blacklist_layer_names)[MAX_STRING_SIZE];
161     uint32_t num_app_key_paths;
162     char (*app_key_paths)[MAX_STRING_SIZE];
163 };
164 
165 struct loader_layer_list {
166     size_t capacity;
167     uint32_t count;
168     struct loader_layer_properties *list;
169 };
170 
171 typedef VkResult(VKAPI_PTR *PFN_vkDevExt)(VkDevice device);
172 
173 struct loader_dev_dispatch_table {
174     VkLayerDispatchTable core_dispatch;
175     PFN_vkDevExt ext_dispatch[MAX_NUM_UNKNOWN_EXTS];
176 };
177 
178 // per CreateDevice structure
179 struct loader_device {
180     struct loader_dev_dispatch_table loader_dispatch;
181     VkDevice chain_device;  // device object from the dispatch chain
182     VkDevice icd_device;    // device object from the icd
183     struct loader_physical_device_term *phys_dev_term;
184 
185     // List of activated layers.
186     //  app_      is the version based on exactly what the application asked for.
187     //            This is what must be returned to the application on Enumerate calls.
188     //  expanded_ is the version based on expanding meta-layers into their
189     //            individual component layers.  This is what is used internally.
190     struct loader_layer_list app_activated_layer_list;
191     struct loader_layer_list expanded_activated_layer_list;
192 
193     VkAllocationCallbacks alloc_callbacks;
194 
195     // List of activated device extensions that have terminators implemented in the loader
196     struct {
197         bool khr_swapchain_enabled;
198         bool khr_display_swapchain_enabled;
199         bool khr_device_group_enabled;
200         bool ext_debug_marker_enabled;
201         bool ext_debug_utils_enabled;
202         bool ext_full_screen_exclusive_enabled;
203     } extensions;
204 
205     struct loader_device *next;
206 };
207 
208 // Per ICD information
209 
210 // Per ICD structure
211 struct loader_icd_term {
212     // pointers to find other structs
213     const struct loader_scanned_icd *scanned_icd;
214     const struct loader_instance *this_instance;
215     struct loader_device *logical_device_list;
216     VkInstance instance;  // instance object from the icd
217     struct loader_icd_term_dispatch dispatch;
218 
219     struct loader_icd_term *next;
220 
221     PFN_PhysDevExt phys_dev_ext[MAX_NUM_UNKNOWN_EXTS];
222     bool supports_get_dev_prop_2;
223 };
224 
225 // Per ICD library structure
226 struct loader_icd_tramp_list {
227     size_t capacity;
228     uint32_t count;
229     struct loader_scanned_icd *scanned_list;
230 };
231 
232 struct loader_instance_dispatch_table {
233     VkLayerInstanceDispatchTable layer_inst_disp;  // must be first entry in structure
234 
235     // Physical device functions unknown to the loader
236     PFN_PhysDevExt phys_dev_ext[MAX_NUM_UNKNOWN_EXTS];
237 };
238 
239 // Unique magic number identifier for the loader.
240 #define LOADER_MAGIC_NUMBER 0x10ADED010110ADEDUL
241 
242 // Per instance structure
243 struct loader_instance {
244     struct loader_instance_dispatch_table *disp;  // must be first entry in structure
245     uint64_t magic;                               // Should be LOADER_MAGIC_NUMBER
246 
247     // Vulkan API version the app is intending to use.
248     loader_api_version app_api_version;
249 
250     // We need to manually track physical devices over time.  If the user
251     // re-queries the information, we don't want to delete old data or
252     // create new data unless necessary.
253     uint32_t total_gpu_count;
254     uint32_t phys_dev_count_term;
255     struct loader_physical_device_term **phys_devs_term;
256     uint32_t phys_dev_count_tramp;
257     struct loader_physical_device_tramp **phys_devs_tramp;
258 
259     // We also need to manually track physical device groups, but we don't need
260     // loader specific structures since we have that content in the physical
261     // device stored internal to the public structures.
262     uint32_t phys_dev_group_count_term;
263     struct VkPhysicalDeviceGroupProperties **phys_dev_groups_term;
264 
265     struct loader_instance *next;
266 
267     uint32_t total_icd_count;
268     struct loader_icd_term *icd_terms;
269     struct loader_icd_tramp_list icd_tramp_list;
270 
271     uint32_t dev_ext_disp_function_count;
272     char *dev_ext_disp_functions[MAX_NUM_UNKNOWN_EXTS];
273     uint32_t phys_dev_ext_disp_function_count;
274     char *phys_dev_ext_disp_functions[MAX_NUM_UNKNOWN_EXTS];
275 
276     struct loader_msg_callback_map_entry *icd_msg_callback_map;
277 
278     struct loader_layer_list instance_layer_list;
279     bool override_layer_present;
280 
281     // List of activated layers.
282     //  app_      is the version based on exactly what the application asked for.
283     //            This is what must be returned to the application on Enumerate calls.
284     //  expanded_ is the version based on expanding meta-layers into their
285     //            individual component layers.  This is what is used internally.
286     struct loader_layer_list app_activated_layer_list;
287     struct loader_layer_list expanded_activated_layer_list;
288 
289     VkInstance instance;  // layers/ICD instance returned to trampoline
290 
291     struct loader_extension_list ext_list;  // icds and loaders extensions
292     struct loader_instance_extension_enables enabled_known_extensions;
293 
294     // Stores debug callbacks - used in the log
295     VkLayerDbgFunctionNode *DbgFunctionHead;
296 
297     // Stores the debug callbacks set during instance creation
298     // These are kept separate because they aren't to be used outside of instance creation and destruction
299     // So they are swapped out at the end of instance creation and swapped in at instance destruction
300     VkLayerDbgFunctionNode *InstanceCreationDeletionDebugFunctionHead;
301 
302     VkAllocationCallbacks alloc_callbacks;
303 
304     bool portability_enumeration_enabled;
305 
306     bool wsi_surface_enabled;
307 #ifdef VK_USE_PLATFORM_WIN32_KHR
308     bool wsi_win32_surface_enabled;
309 #endif
310 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
311     bool wsi_wayland_surface_enabled;
312 #endif
313 #ifdef VK_USE_PLATFORM_XCB_KHR
314     bool wsi_xcb_surface_enabled;
315 #endif
316 #ifdef VK_USE_PLATFORM_XLIB_KHR
317     bool wsi_xlib_surface_enabled;
318 #endif
319 #ifdef VK_USE_PLATFORM_DIRECTFB_EXT
320     bool wsi_directfb_surface_enabled;
321 #endif
322 #ifdef VK_USE_PLATFORM_ANDROID_KHR
323     bool wsi_android_surface_enabled;
324 #endif
325 #ifdef VK_USE_PLATFORM_OHOS
326     bool wsi_ohos_surface_enabled;
327 #endif
328 #ifdef VK_USE_PLATFORM_MACOS_MVK
329     bool wsi_macos_surface_enabled;
330 #endif
331 #ifdef VK_USE_PLATFORM_IOS_MVK
332     bool wsi_ios_surface_enabled;
333 #endif
334 #ifdef VK_USE_PLATFORM_GGP
335     bool wsi_ggp_surface_enabled;
336 #endif
337     bool wsi_headless_surface_enabled;
338 #if defined(VK_USE_PLATFORM_METAL_EXT)
339     bool wsi_metal_surface_enabled;
340 #endif
341 #ifdef VK_USE_PLATFORM_FUCHSIA
342     bool wsi_imagepipe_surface_enabled;
343 #endif
344 #ifdef VK_USE_PLATFORM_SCREEN_QNX
345     bool wsi_screen_surface_enabled;
346 #endif
347 #ifdef VK_USE_PLATFORM_VI_NN
348     bool wsi_vi_surface_enabled;
349 #endif
350     bool wsi_display_enabled;
351     bool wsi_display_props2_enabled;
352     bool create_terminator_invalid_extension;
353     bool supports_get_dev_prop_2;
354 };
355 
356 // VkPhysicalDevice requires special treatment by loader.  Firstly, terminator
357 // code must be able to get the struct loader_icd_term to call into the proper
358 // driver  (multiple ICD/gpu case). This can be accomplished by wrapping the
359 // created VkPhysicalDevice in loader terminate_EnumeratePhysicalDevices().
360 // Secondly, the loader must be able to handle wrapped by layer VkPhysicalDevice
361 // in trampoline code.  This implies, that the loader trampoline code must also
362 // wrap the VkPhysicalDevice object in trampoline code.  Thus, loader has to
363 // wrap the VkPhysicalDevice created object twice. In trampoline code it can't
364 // rely on the terminator object wrapping since a layer may also wrap. Since
365 // trampoline code wraps the VkPhysicalDevice this means all loader trampoline
366 // code that passes a VkPhysicalDevice should unwrap it.
367 
368 // Unique identifier for physical devices
369 #define PHYS_TRAMP_MAGIC_NUMBER 0x10ADED020210ADEDUL
370 
371 // Per enumerated PhysicalDevice structure, used to wrap in trampoline code and
372 // also same structure used to wrap in terminator code
373 struct loader_physical_device_tramp {
374     struct loader_instance_dispatch_table *disp;  // must be first entry in structure
375     struct loader_instance *this_instance;
376     uint64_t magic;             // Should be PHYS_TRAMP_MAGIC_NUMBER
377     VkPhysicalDevice phys_dev;  // object from layers/loader terminator
378 };
379 
380 // Per enumerated PhysicalDevice structure, used to wrap in terminator code
381 struct loader_physical_device_term {
382     struct loader_instance_dispatch_table *disp;  // must be first entry in structure
383     struct loader_icd_term *this_icd_term;
384     uint8_t icd_index;
385     VkPhysicalDevice phys_dev;  // object from ICD
386 };
387 
388 #ifdef LOADER_ENABLE_LINUX_SORT
389 // Structure for storing the relevent device information for selecting a device.
390 // NOTE: Needs to be defined here so we can store this content in the term structrue
391 //       for quicker sorting.
392 struct LinuxSortedDeviceInfo {
393     // Associated Vulkan Physical Device
394     VkPhysicalDevice physical_device;
395     bool default_device;
396 
397     // Loader specific items about the driver providing support for this physical device
398     uint32_t icd_index;
399     struct loader_icd_term *icd_term;
400 
401     // Some generic device properties
402     VkPhysicalDeviceType device_type;
403     char device_name[VK_MAX_PHYSICAL_DEVICE_NAME_SIZE];
404     uint32_t vendor_id;
405     uint32_t device_id;
406 
407     // PCI information on this device
408     bool has_pci_bus_info;
409     uint32_t pci_domain;
410     uint32_t pci_bus;
411     uint32_t pci_device;
412     uint32_t pci_function;
413 };
414 #endif  // LOADER_ENABLE_LINUX_SORT
415 
416 // Per enumerated PhysicalDeviceGroup structure, used to wrap in terminator code
417 struct loader_physical_device_group_term {
418     struct loader_icd_term *this_icd_term;
419     uint8_t icd_index;
420     VkPhysicalDeviceGroupProperties group_props;
421 #ifdef LOADER_ENABLE_LINUX_SORT
422     struct LinuxSortedDeviceInfo internal_device_info[VK_MAX_DEVICE_GROUP_SIZE];
423 #endif  // LOADER_ENABLE_LINUX_SORT
424 };
425 
426 struct loader_struct {
427     struct loader_instance *instances;
428 };
429 
430 struct loader_scanned_icd {
431     char *lib_name;
432     loader_platform_dl_handle handle;
433     uint32_t api_version;
434     uint32_t interface_version;
435     PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
436     PFN_GetPhysicalDeviceProcAddr GetPhysicalDeviceProcAddr;
437     PFN_vkCreateInstance CreateInstance;
438     PFN_vkEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties;
439 #if defined(VK_USE_PLATFORM_WIN32_KHR)
440     PFN_vk_icdEnumerateAdapterPhysicalDevices EnumerateAdapterPhysicalDevices;
441 #endif
442 };
443 
444 enum loader_data_files_type {
445     LOADER_DATA_FILE_MANIFEST_DRIVER = 0,
446     LOADER_DATA_FILE_MANIFEST_EXPLICIT_LAYER,
447     LOADER_DATA_FILE_MANIFEST_IMPLICIT_LAYER,
448     LOADER_DATA_FILE_NUM_TYPES  // Not a real field, used for possible loop terminator
449 };
450 
451 struct loader_data_files {
452     uint32_t count;
453     uint32_t alloc_count;
454     char **filename_list;
455 };
456 
457 struct loader_phys_dev_per_icd {
458     uint32_t device_count;
459     VkPhysicalDevice *physical_devices;
460     uint32_t icd_index;
461     struct loader_icd_term *icd_term;
462 };
463 
464 struct loader_msg_callback_map_entry {
465     VkDebugReportCallbackEXT icd_obj;
466     VkDebugReportCallbackEXT loader_obj;
467 };
468