1 /*
2 *
3 * Copyright (c) 2014-2017 The Khronos Group Inc.
4 * Copyright (c) 2014-2017 Valve Corporation
5 * Copyright (c) 2014-2017 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 *
26 */
27
28 #ifndef LOADER_H
29 #define LOADER_H
30
31 #include <vulkan/vulkan.h>
32 #include "vk_loader_platform.h"
33 #include "vk_loader_layer.h"
34 #include <vulkan/vk_layer.h>
35 #include <vulkan/vk_icd.h>
36 #include <assert.h>
37 #include "vk_loader_extensions.h"
38
39 #if defined(__GNUC__) && __GNUC__ >= 4
40 #define LOADER_EXPORT __attribute__((visibility("default")))
41 #elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)
42 #define LOADER_EXPORT __attribute__((visibility("default")))
43 #else
44 #define LOADER_EXPORT
45 #endif
46
47 // A debug option to disable allocators at compile time to investigate future issues.
48 #define DEBUG_DISABLE_APP_ALLOCATORS 0
49
50 #define MAX_STRING_SIZE 1024
51
52 // This is defined in vk_layer.h, but if there's problems we need to create the define
53 // here.
54 #ifndef MAX_NUM_UNKNOWN_EXTS
55 #define MAX_NUM_UNKNOWN_EXTS 250
56 #endif
57
58 enum layer_type_flags {
59 VK_LAYER_TYPE_FLAG_INSTANCE_LAYER = 0x1, // If not set, indicates Device layer
60 VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER = 0x2, // If not set, indicates Implicit layer
61 VK_LAYER_TYPE_FLAG_META_LAYER = 0x4, // If not set, indicates standard layer
62 };
63
64 typedef enum VkStringErrorFlagBits {
65 VK_STRING_ERROR_NONE = 0x00000000,
66 VK_STRING_ERROR_LENGTH = 0x00000001,
67 VK_STRING_ERROR_BAD_DATA = 0x00000002,
68 } VkStringErrorFlagBits;
69 typedef VkFlags VkStringErrorFlags;
70
71 static const int MaxLoaderStringLength = 256;
72 static const char UTF8_ONE_BYTE_CODE = 0xC0;
73 static const char UTF8_ONE_BYTE_MASK = 0xE0;
74 static const char UTF8_TWO_BYTE_CODE = 0xE0;
75 static const char UTF8_TWO_BYTE_MASK = 0xF0;
76 static const char UTF8_THREE_BYTE_CODE = 0xF0;
77 static const char UTF8_THREE_BYTE_MASK = 0xF8;
78 static const char UTF8_DATA_BYTE_CODE = 0x80;
79 static const char UTF8_DATA_BYTE_MASK = 0xC0;
80
81 struct VkStructureHeader {
82 VkStructureType sType;
83 const void *pNext;
84 };
85
86 // form of all dynamic lists/arrays
87 // only the list element should be changed
88 struct loader_generic_list {
89 size_t capacity;
90 uint32_t count;
91 void *list;
92 };
93
94 struct loader_extension_list {
95 size_t capacity;
96 uint32_t count;
97 VkExtensionProperties *list;
98 };
99
100 struct loader_dev_ext_props {
101 VkExtensionProperties props;
102 uint32_t entrypoint_count;
103 char **entrypoints;
104 };
105
106 struct loader_device_extension_list {
107 size_t capacity;
108 uint32_t count;
109 struct loader_dev_ext_props *list;
110 };
111
112 struct loader_name_value {
113 char name[MAX_STRING_SIZE];
114 char value[MAX_STRING_SIZE];
115 };
116
117 struct loader_layer_functions {
118 char str_gipa[MAX_STRING_SIZE];
119 char str_gdpa[MAX_STRING_SIZE];
120 char str_negotiate_interface[MAX_STRING_SIZE];
121 PFN_vkNegotiateLoaderLayerInterfaceVersion negotiate_layer_interface;
122 PFN_vkGetInstanceProcAddr get_instance_proc_addr;
123 PFN_vkGetDeviceProcAddr get_device_proc_addr;
124 PFN_GetPhysicalDeviceProcAddr get_physical_device_proc_addr;
125 };
126
127 struct loader_layer_properties {
128 VkLayerProperties info;
129 enum layer_type_flags type_flags;
130 uint32_t interface_version; // PFN_vkNegotiateLoaderLayerInterfaceVersion
131 char lib_name[MAX_STRING_SIZE];
132 loader_platform_dl_handle lib_handle;
133 struct loader_layer_functions functions;
134 struct loader_extension_list instance_extension_list;
135 struct loader_device_extension_list device_extension_list;
136 struct loader_name_value disable_env_var;
137 struct loader_name_value enable_env_var;
138 uint32_t num_component_layers;
139 char (*component_layer_names)[MAX_STRING_SIZE];
140 struct {
141 char enumerate_instance_extension_properties[MAX_STRING_SIZE];
142 char enumerate_instance_layer_properties[MAX_STRING_SIZE];
143 } pre_instance_functions;
144 };
145
146 struct loader_layer_list {
147 size_t capacity;
148 uint32_t count;
149 struct loader_layer_properties *list;
150 };
151
152 struct loader_dispatch_hash_list {
153 size_t capacity;
154 uint32_t count;
155 uint32_t *index; // index into the dev_ext dispatch table
156 };
157
158 // loader_dispatch_hash_entry and loader_dev_ext_dispatch_table.dev_ext have
159 // one to one correspondence; one loader_dispatch_hash_entry for one dev_ext
160 // dispatch entry.
161 // Also have a one to one correspondence with functions in dev_ext_trampoline.c
162 struct loader_dispatch_hash_entry {
163 char *func_name;
164 struct loader_dispatch_hash_list list; // to handle hashing collisions
165 };
166
167 typedef void(VKAPI_PTR *PFN_vkDevExt)(VkDevice device);
168 struct loader_dev_ext_dispatch_table {
169 PFN_vkDevExt dev_ext[MAX_NUM_UNKNOWN_EXTS];
170 };
171
172 struct loader_dev_dispatch_table {
173 VkLayerDispatchTable core_dispatch;
174 struct loader_dev_ext_dispatch_table ext_dispatch;
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 struct loader_device *next;
195 };
196
197 // Per ICD information
198
199 // Per ICD structure
200 struct loader_icd_term {
201 // pointers to find other structs
202 const struct loader_scanned_icd *scanned_icd;
203 const struct loader_instance *this_instance;
204 struct loader_device *logical_device_list;
205 VkInstance instance; // instance object from the icd
206 struct loader_icd_term_dispatch dispatch;
207
208 struct loader_icd_term *next;
209
210 PFN_PhysDevExt phys_dev_ext[MAX_NUM_UNKNOWN_EXTS];
211 };
212
213 // Per ICD library structure
214 struct loader_icd_tramp_list {
215 size_t capacity;
216 uint32_t count;
217 struct loader_scanned_icd *scanned_list;
218 };
219
220 struct loader_instance_dispatch_table {
221 VkLayerInstanceDispatchTable layer_inst_disp; // must be first entry in structure
222
223 // Physical device functions unknown to the loader
224 PFN_PhysDevExt phys_dev_ext[MAX_NUM_UNKNOWN_EXTS];
225 };
226
227 // Per instance structure
228 struct loader_instance {
229 struct loader_instance_dispatch_table *disp; // must be first entry in structure
230
231 // We need to manually track physical devices over time. If the user
232 // re-queries the information, we don't want to delete old data or
233 // create new data unless necessary.
234 uint32_t total_gpu_count;
235 uint32_t phys_dev_count_term;
236 struct loader_physical_device_term **phys_devs_term;
237 uint32_t phys_dev_count_tramp;
238 struct loader_physical_device_tramp **phys_devs_tramp;
239
240 // We also need to manually track physical device groups, but we don't need
241 // loader specific structures since we have that content in the physical
242 // device stored internal to the public structures.
243 uint32_t phys_dev_group_count_term;
244 struct VkPhysicalDeviceGroupPropertiesKHX **phys_dev_groups_term;
245 uint32_t phys_dev_group_count_tramp;
246 struct VkPhysicalDeviceGroupPropertiesKHX **phys_dev_groups_tramp;
247
248 struct loader_instance *next;
249
250 uint32_t total_icd_count;
251 struct loader_icd_term *icd_terms;
252 struct loader_icd_tramp_list icd_tramp_list;
253
254 struct loader_dispatch_hash_entry dev_ext_disp_hash[MAX_NUM_UNKNOWN_EXTS];
255 struct loader_dispatch_hash_entry phys_dev_ext_disp_hash[MAX_NUM_UNKNOWN_EXTS];
256
257 struct loader_msg_callback_map_entry *icd_msg_callback_map;
258
259 struct loader_layer_list instance_layer_list;
260
261 // List of activated layers.
262 // app_ is the version based on exactly what the application asked for.
263 // This is what must be returned to the application on Enumerate calls.
264 // expanded_ is the version based on expanding meta-layers into their
265 // individual component layers. This is what is used internally.
266 struct loader_layer_list app_activated_layer_list;
267 struct loader_layer_list expanded_activated_layer_list;
268
269 VkInstance instance; // layers/ICD instance returned to trampoline
270
271 struct loader_extension_list ext_list; // icds and loaders extensions
272 union loader_instance_extension_enables enabled_known_extensions;
273
274 VkLayerDbgFunctionNode *DbgFunctionHead;
275 uint32_t num_tmp_callbacks;
276 VkDebugReportCallbackCreateInfoEXT *tmp_dbg_create_infos;
277 VkDebugReportCallbackEXT *tmp_callbacks;
278
279 VkAllocationCallbacks alloc_callbacks;
280
281 bool wsi_surface_enabled;
282 #ifdef VK_USE_PLATFORM_WIN32_KHR
283 bool wsi_win32_surface_enabled;
284 #endif
285 #ifdef VK_USE_PLATFORM_MIR_KHR
286 bool wsi_mir_surface_enabled;
287 #endif
288 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
289 bool wsi_wayland_surface_enabled;
290 #endif
291 #ifdef VK_USE_PLATFORM_XCB_KHR
292 bool wsi_xcb_surface_enabled;
293 #endif
294 #ifdef VK_USE_PLATFORM_XLIB_KHR
295 bool wsi_xlib_surface_enabled;
296 #endif
297 #ifdef VK_USE_PLATFORM_ANDROID_KHR
298 bool wsi_android_surface_enabled;
299 #endif
300 bool wsi_display_enabled;
301 };
302
303 // VkPhysicalDevice requires special treatment by loader. Firstly, terminator
304 // code must be able to get the struct loader_icd_term to call into the proper
305 // driver (multiple ICD/gpu case). This can be accomplished by wrapping the
306 // created VkPhysicalDevice in loader terminate_EnumeratePhysicalDevices().
307 // Secondly, the loader must be able to handle wrapped by layer VkPhysicalDevice
308 // in trampoline code. This implies, that the loader trampoline code must also
309 // wrap the VkPhysicalDevice object in trampoline code. Thus, loader has to
310 // wrap the VkPhysicalDevice created object twice. In trampoline code it can't
311 // rely on the terminator object wrapping since a layer may also wrap. Since
312 // trampoline code wraps the VkPhysicalDevice this means all loader trampoline
313 // code that passes a VkPhysicalDevice should unwrap it.
314
315 // Per enumerated PhysicalDevice structure, used to wrap in trampoline code and
316 // also same structure used to wrap in terminator code
317 struct loader_physical_device_tramp {
318 struct loader_instance_dispatch_table *disp; // must be first entry in structure
319 struct loader_instance *this_instance;
320 VkPhysicalDevice phys_dev; // object from layers/loader terminator
321 };
322
323 // Per enumerated PhysicalDevice structure, used to wrap in terminator code
324 struct loader_physical_device_term {
325 struct loader_instance_dispatch_table *disp; // must be first entry in structure
326 struct loader_icd_term *this_icd_term;
327 uint8_t icd_index;
328 VkPhysicalDevice phys_dev; // object from ICD
329 };
330
331 struct loader_struct {
332 struct loader_instance *instances;
333 };
334
335 struct loader_scanned_icd {
336 char *lib_name;
337 loader_platform_dl_handle handle;
338 uint32_t api_version;
339 uint32_t interface_version;
340 PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
341 PFN_GetPhysicalDeviceProcAddr GetPhysicalDeviceProcAddr;
342 PFN_vkCreateInstance CreateInstance;
343 PFN_vkEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties;
344 };
345
loader_instance(VkInstance instance)346 static inline struct loader_instance *loader_instance(VkInstance instance) { return (struct loader_instance *)instance; }
347
loader_unwrap_physical_device(VkPhysicalDevice physicalDevice)348 static inline VkPhysicalDevice loader_unwrap_physical_device(VkPhysicalDevice physicalDevice) {
349 struct loader_physical_device_tramp *phys_dev = (struct loader_physical_device_tramp *)physicalDevice;
350 return phys_dev->phys_dev;
351 }
352
loader_set_dispatch(void * obj,const void * data)353 static inline void loader_set_dispatch(void *obj, const void *data) { *((const void **)obj) = data; }
354
loader_get_dispatch(const void * obj)355 static inline VkLayerDispatchTable *loader_get_dispatch(const void *obj) { return *((VkLayerDispatchTable **)obj); }
356
loader_get_dev_dispatch(const void * obj)357 static inline struct loader_dev_dispatch_table *loader_get_dev_dispatch(const void *obj) {
358 return *((struct loader_dev_dispatch_table **)obj);
359 }
360
loader_get_instance_layer_dispatch(const void * obj)361 static inline VkLayerInstanceDispatchTable *loader_get_instance_layer_dispatch(const void *obj) {
362 return *((VkLayerInstanceDispatchTable **)obj);
363 }
364
loader_get_instance_dispatch(const void * obj)365 static inline struct loader_instance_dispatch_table *loader_get_instance_dispatch(const void *obj) {
366 return *((struct loader_instance_dispatch_table **)obj);
367 }
368
loader_init_dispatch(void * obj,const void * data)369 static inline void loader_init_dispatch(void *obj, const void *data) {
370 #ifdef DEBUG
371 assert(valid_loader_magic_value(obj) &&
372 "Incompatible ICD, first dword must be initialized to "
373 "ICD_LOADER_MAGIC. See loader/README.md for details.");
374 #endif
375
376 loader_set_dispatch(obj, data);
377 }
378
379 // Global variables used across files
380 extern struct loader_struct loader;
381 extern THREAD_LOCAL_DECL struct loader_instance *tls_instance;
382 #if defined(_WIN32) && !defined(LOADER_DYNAMIC_LIB)
383 extern LOADER_PLATFORM_THREAD_ONCE_DEFINITION(once_init);
384 #endif
385 extern loader_platform_thread_mutex loader_lock;
386 extern loader_platform_thread_mutex loader_json_lock;
387
388 struct loader_msg_callback_map_entry {
389 VkDebugReportCallbackEXT icd_obj;
390 VkDebugReportCallbackEXT loader_obj;
391 };
392
393 // Helper function definitions
394 void *loader_instance_heap_alloc(const struct loader_instance *instance, size_t size, VkSystemAllocationScope allocationScope);
395 void loader_instance_heap_free(const struct loader_instance *instance, void *pMemory);
396 void *loader_instance_heap_realloc(const struct loader_instance *instance, void *pMemory, size_t orig_size, size_t size,
397 VkSystemAllocationScope alloc_scope);
398 void *loader_instance_tls_heap_alloc(size_t size);
399 void loader_instance_tls_heap_free(void *pMemory);
400 void *loader_device_heap_alloc(const struct loader_device *device, size_t size, VkSystemAllocationScope allocationScope);
401 void loader_device_heap_free(const struct loader_device *device, void *pMemory);
402 void *loader_device_heap_realloc(const struct loader_device *device, void *pMemory, size_t orig_size, size_t size,
403 VkSystemAllocationScope alloc_scope);
404
405 void loader_log(const struct loader_instance *inst, VkFlags msg_type, int32_t msg_code, const char *format, ...);
406
407 bool compare_vk_extension_properties(const VkExtensionProperties *op1, const VkExtensionProperties *op2);
408
409 VkResult loader_validate_layers(const struct loader_instance *inst, const uint32_t layer_count,
410 const char *const *ppEnabledLayerNames, const struct loader_layer_list *list);
411
412 VkResult loader_validate_instance_extensions(const struct loader_instance *inst, const struct loader_extension_list *icd_exts,
413 const struct loader_layer_list *instance_layer,
414 const VkInstanceCreateInfo *pCreateInfo);
415
416 void loader_initialize(void);
417 VkResult loader_copy_layer_properties(const struct loader_instance *inst, struct loader_layer_properties *dst,
418 struct loader_layer_properties *src);
419 bool has_vk_extension_property_array(const VkExtensionProperties *vk_ext_prop, const uint32_t count,
420 const VkExtensionProperties *ext_array);
421 bool has_vk_extension_property(const VkExtensionProperties *vk_ext_prop, const struct loader_extension_list *ext_list);
422
423 VkResult loader_add_to_ext_list(const struct loader_instance *inst, struct loader_extension_list *ext_list,
424 uint32_t prop_list_count, const VkExtensionProperties *props);
425 VkResult loader_add_to_dev_ext_list(const struct loader_instance *inst, struct loader_device_extension_list *ext_list,
426 const VkExtensionProperties *props, uint32_t entry_count, char **entrys);
427 VkResult loader_add_device_extensions(const struct loader_instance *inst,
428 PFN_vkEnumerateDeviceExtensionProperties fpEnumerateDeviceExtensionProperties,
429 VkPhysicalDevice physical_device, const char *lib_name,
430 struct loader_extension_list *ext_list);
431 VkResult loader_init_generic_list(const struct loader_instance *inst, struct loader_generic_list *list_info, size_t element_size);
432 void loader_destroy_generic_list(const struct loader_instance *inst, struct loader_generic_list *list);
433 void loader_destroy_layer_list(const struct loader_instance *inst, struct loader_device *device,
434 struct loader_layer_list *layer_list);
435 void loader_delete_layer_properties(const struct loader_instance *inst, struct loader_layer_list *layer_list);
436 bool loader_find_layer_name_array(const char *name, uint32_t layer_count, const char layer_list[][VK_MAX_EXTENSION_NAME_SIZE]);
437 VkResult loader_add_to_layer_list(const struct loader_instance *inst, struct loader_layer_list *list, uint32_t prop_list_count,
438 const struct loader_layer_properties *props);
439 void loader_find_layer_name_add_list(const struct loader_instance *inst, const char *name, const enum layer_type_flags type_flags,
440 const struct loader_layer_list *source_list, struct loader_layer_list *target_list,
441 struct loader_layer_list *expanded_target_list);
442 void loader_scanned_icd_clear(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list);
443 VkResult loader_icd_scan(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list);
444 void loader_layer_scan(const struct loader_instance *inst, struct loader_layer_list *instance_layers);
445 void loader_implicit_layer_scan(const struct loader_instance *inst, struct loader_layer_list *instance_layers);
446 bool loader_is_implicit_layer_enabled(const struct loader_instance *inst, const struct loader_layer_properties *prop);
447 VkResult loader_get_icd_loader_instance_extensions(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list,
448 struct loader_extension_list *inst_exts);
449 struct loader_icd_term *loader_get_icd_and_device(const VkDevice device, struct loader_device **found_dev, uint32_t *icd_index);
450 void loader_init_dispatch_dev_ext(struct loader_instance *inst, struct loader_device *dev);
451 void *loader_dev_ext_gpa(struct loader_instance *inst, const char *funcName);
452 void *loader_get_dev_ext_trampoline(uint32_t index);
453 bool loader_phys_dev_ext_gpa(struct loader_instance *inst, const char *funcName, bool perform_checking, void **tramp_addr,
454 void **term_addr);
455 void *loader_get_phys_dev_ext_tramp(uint32_t index);
456 void *loader_get_phys_dev_ext_termin(uint32_t index);
457 struct loader_instance *loader_get_instance(const VkInstance instance);
458 void loader_deactivate_layers(const struct loader_instance *instance, struct loader_device *device, struct loader_layer_list *list);
459 struct loader_device *loader_create_logical_device(const struct loader_instance *inst, const VkAllocationCallbacks *pAllocator);
460 void loader_add_logical_device(const struct loader_instance *inst, struct loader_icd_term *icd_term,
461 struct loader_device *found_dev);
462 void loader_remove_logical_device(const struct loader_instance *inst, struct loader_icd_term *icd_term,
463 struct loader_device *found_dev, const VkAllocationCallbacks *pAllocator);
464 // NOTE: Outside of loader, this entry-point is only provided for error
465 // cleanup.
466 void loader_destroy_logical_device(const struct loader_instance *inst, struct loader_device *dev,
467 const VkAllocationCallbacks *pAllocator);
468
469 VkResult loader_enable_instance_layers(struct loader_instance *inst, const VkInstanceCreateInfo *pCreateInfo,
470 const struct loader_layer_list *instance_layers);
471
472 VkResult loader_create_instance_chain(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
473 struct loader_instance *inst, VkInstance *created_instance);
474
475 void loader_activate_instance_layer_extensions(struct loader_instance *inst, VkInstance created_inst);
476
477 VkResult loader_create_device_chain(const struct loader_physical_device_tramp *pd, const VkDeviceCreateInfo *pCreateInfo,
478 const VkAllocationCallbacks *pAllocator, const struct loader_instance *inst,
479 struct loader_device *dev);
480
481 VkResult loader_validate_device_extensions(struct loader_physical_device_tramp *phys_dev,
482 const struct loader_layer_list *activated_device_layers,
483 const struct loader_extension_list *icd_exts, const VkDeviceCreateInfo *pCreateInfo);
484
485 VkResult setupLoaderTrampPhysDevs(VkInstance instance);
486 VkResult setupLoaderTermPhysDevs(struct loader_instance *inst);
487
488 VkStringErrorFlags vk_string_validate(const int max_length, const char *char_array);
489
490 #endif // LOADER_H
491