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