blob: 2d3b067a81699be804ab83454d60c87f77c6e640 [file] [log] [blame]
Chia-I Wu19300602014-08-04 08:03:57 +08001/*
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06002 * Vulkan
Chia-I Wu19300602014-08-04 08:03:57 +08003 *
4 * Copyright (C) 2014 LunarG, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
Chia-I Wu701f3f62014-09-02 08:32:09 +080023 *
24 * Authors:
25 * Chia-I Wu <olv@lunarg.com>
Chia-I Wu19300602014-08-04 08:03:57 +080026 */
27
28#ifndef LOADER_H
29#define LOADER_H
30
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -060031#include <vulkan.h>
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -060032#include <vk_debug_report_lunarg.h>
Chia-I Wuf8693382015-04-16 22:02:10 +080033#include <vk_wsi_lunarg.h>
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -060034#include <vkLayer.h>
35#include <vkIcd.h>
Chia-I Wu5291c762015-04-11 15:34:07 +080036#include <assert.h>
37
Chia-I Wu19300602014-08-04 08:03:57 +080038#if defined(__GNUC__) && __GNUC__ >= 4
39# define LOADER_EXPORT __attribute__((visibility("default")))
40#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)
41# define LOADER_EXPORT __attribute__((visibility("default")))
42#else
43# define LOADER_EXPORT
44#endif
45
Jon Ashburn27cd5842015-05-12 17:26:48 -060046#define MAX_LAYER_LIBRARIES 64
47#define MAX_GPUS_FOR_LAYER 16
48
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -060049enum extension_origin {
50 VK_EXTENSION_ORIGIN_ICD,
51 VK_EXTENSION_ORIGIN_LAYER,
52 VK_EXTENSION_ORIGIN_LOADER
Jon Ashburn27cd5842015-05-12 17:26:48 -060053};
54
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -060055struct loader_extension_property {
56 VkExtensionProperties info;
57 const char *lib_name;
58 enum extension_origin origin;
59 bool hosted; // does the extension reside in one driver/layer
60};
61
62struct loader_extension_list {
63 size_t capacity;
64 uint32_t count;
65 struct loader_extension_property *list;
66};
67
68struct loader_scanned_layers {
69 char *lib_name;
70
71 /* cache of global extensions for a specific layer */
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -060072 struct loader_extension_list global_extension_list;
73
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -060074 bool physical_device_extensions_supported;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -060075 /*
76 * cache of device extensions for a specific layer,
77 * filled in at CreateInstance time
78 */
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -060079 struct loader_extension_list physical_device_extension_list;
Jon Ashburn27cd5842015-05-12 17:26:48 -060080};
81
Jon Ashburn95a77ba2015-05-15 15:09:35 -060082struct loader_icd {
83 const struct loader_scanned_icds *scanned_icds;
84
85 VkLayerDispatchTable *loader_dispatch;
86 uint32_t layer_count[MAX_GPUS_FOR_LAYER];
Jon Ashburn95a77ba2015-05-15 15:09:35 -060087 VkBaseLayerObject *wrappedGpus[MAX_GPUS_FOR_LAYER];
88 uint32_t gpu_count;
89 VkBaseLayerObject *gpus;
90 VkInstance instance; // instance object from the icd
Jon Ashburn8d1b0b52015-05-18 13:20:15 -060091 PFN_vkGetDeviceProcAddr GetDeviceProcAddr;
Jon Ashburn95a77ba2015-05-15 15:09:35 -060092 PFN_vkDestroyInstance DestroyInstance;
93 PFN_vkEnumeratePhysicalDevices EnumeratePhysicalDevices;
94 PFN_vkGetPhysicalDeviceInfo GetPhysicalDeviceInfo;
95 PFN_vkCreateDevice CreateDevice;
96 PFN_vkGetPhysicalDeviceExtensionInfo GetPhysicalDeviceExtensionInfo;
Jon Ashburn95a77ba2015-05-15 15:09:35 -060097 PFN_vkGetMultiDeviceCompatibility GetMultiDeviceCompatibility;
Jon Ashburn95a77ba2015-05-15 15:09:35 -060098 PFN_vkGetDisplayInfoWSI GetDisplayInfoWSI;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -060099 PFN_vkDbgCreateMsgCallback DbgCreateMsgCallback;
100 PFN_vkDbgDestroyMsgCallback DbgDestroyMsgCallback;
Jon Ashburn95a77ba2015-05-15 15:09:35 -0600101 struct loader_icd *next;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600102
103 uint32_t app_extension_count[MAX_GPUS_FOR_LAYER];
104 VkExtensionProperties *app_extension_props[MAX_GPUS_FOR_LAYER];
105
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600106 /*
107 * Fill in the cache of available extensions from all layers that
108 * operate with this physical device.
109 * This cache will be used to satisfy calls to GetPhysicalDeviceExtensionInfo
110 */
111 struct loader_extension_list device_extension_cache[MAX_GPUS_FOR_LAYER];
112
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600113 struct loader_extension_list enabled_device_extensions[MAX_GPUS_FOR_LAYER];
Jon Ashburn95a77ba2015-05-15 15:09:35 -0600114};
115
Jon Ashburn27cd5842015-05-12 17:26:48 -0600116struct loader_instance {
Jon Ashburn95a77ba2015-05-15 15:09:35 -0600117 VkLayerInstanceDispatchTable *disp; // must be first entry in structure
118
Jon Ashburn27cd5842015-05-12 17:26:48 -0600119 uint32_t layer_count;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600120// struct loader_layers layer_libs[MAX_LAYER_LIBRARIES];
Jon Ashburn27cd5842015-05-12 17:26:48 -0600121 VkBaseLayerObject *wrappedInstance;
122 uint32_t total_gpu_count;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600123 uint32_t total_icd_count;
Jon Ashburn27cd5842015-05-12 17:26:48 -0600124 struct loader_icd *icds;
125 struct loader_instance *next;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600126
127 /* TODO: Should keep track of application provided allocation functions */
128
129 /*
130 * CreateMsgCallback is global and needs to be
131 * applied to all layers and ICDs.
132 * What happens if a layer is enabled on both the instance chain
133 * as well as the device chain and a call to CreateMsgCallback is made?
134 * Do we need to make sure that each layer / driver only gets called once?
135 * Should a layer implementing support for CreateMsgCallback only be allowed (?)
136 * to live on one chain? Or maybe make it the application's responsibility.
137 * If the app enables DRAW_STATE on at both CreateInstance time and CreateDevice
138 * time, CreateMsgCallback will call the DRAW_STATE layer twice. Once via
139 * the instance chain and once via the device chain.
140 * The loader should only return the DEBUG_REPORT extension as supported
141 * for the GetGlobalExtensionSupport call. That should help eliminate one
142 * duplication.
143 * Since the instance chain requires us iterating over the available ICDs
144 * and each ICD will have it's own unique MsgCallback object we need to
145 * track those objects to give back the right one.
146 * This also implies that the loader has to intercept vkDestroyObject and
147 * if the extension is enabled and the object type is a MsgCallback then
148 * we must translate the object into the proper ICD specific ones.
149 * DestroyObject works on a device chain. Should not be what's destroying
150 * the MsgCallback object. That needs to be an instance thing. So, since
151 * we used an instance to create it, we need a custom Destroy that also
152 * takes an instance. That way we can iterate over the ICDs properly.
153 * Example use:
154 * CreateInstance: DEBUG_REPORT
155 * Loader will create instance chain with enabled extensions.
156 * TODO: Should validation layers be enabled here? If not, they will not be in the instance chain.
157 * fn = GetProcAddr(INSTANCE, "vkCreateMsgCallback") -> point to loader's vkCreateMsgCallback
158 * App creates a callback object: fn(..., &MsgCallbackObject1)
159 * Have only established the instance chain so far. Loader will call the instance chain.
160 * Each layer in the instance chain will call down to the next layer, terminating with
161 * the CreateMsgCallback loader terminator function that creates the actual MsgCallbackObject1 object.
162 * The loader CreateMsgCallback terminator will iterate over the ICDs.
163 * Calling each ICD that supports vkCreateMsgCallback and collect answers in icd_msg_callback_map here.
164 * As result is sent back up the chain each layer has opportunity to record the callback operation and
165 * appropriate MsgCallback object.
166 * ...
167 * Any reports matching the flags set in MsgCallbackObject1 will generate the defined callback behavior
168 * in the layer / ICD that initiated that report.
169 * ...
170 * CreateDevice: MemTracker:...
171 * App does not include DEBUG_REPORT as that is a global extension.
172 * TODO: GetExtensionSupport must not report DEBUG_REPORT when using instance.
173 * App MUST include any desired validation layers or they will not participate in the device call chain.
174 * App creates a callback object: fn(..., &MsgCallbackObject2)
175 * Loader's vkCreateMsgCallback is called.
176 * Loader sends call down instance chain - this is a global extension - any validation layer that was
177 * enabled at CreateInstance will be able to register the callback. Loader will iterate over the ICDs and
178 * will record the ICD's version of the MsgCallback2 object here.
179 * ...
180 * Any report will go to the layer's report function and it will check the flags for MsgCallbackObject1
181 * and MsgCallbackObject2 and take the appropriate action as indicated by the app.
182 * ...
183 * App calls vkDestroyMsgCallback( MsgCallbackObject1 )
184 * Loader's DestroyMsgCallback is where call starts. DestroyMsgCallback will be sent down instance chain
185 * ending in the loader's DestroyMsgCallback terminator which will iterate over the ICD's destroying each
186 * ICD version of that MsgCallback object and then destroy the loader's version of the object.
187 * Any reports generated after this will only have MsgCallbackObject2 available.
188 */
189 struct loader_msg_callback_map_entry *icd_msg_callback_map;
190
191 struct loader_extension_list enabled_instance_extensions;
192
193 uint32_t app_extension_count;
194 VkExtensionProperties *app_extension_props;
195
196 bool debug_report_enabled;
197 bool wsi_lunarg_enabled;
198 VkLayerDbgFunctionNode *DbgFunctionHead;
199};
200
201struct loader_lib_info {
202 const char *lib_name;
203 uint32_t ref_count;
204 loader_platform_dl_handle lib_handle;
Jon Ashburn27cd5842015-05-12 17:26:48 -0600205};
206
207struct loader_struct {
208 struct loader_instance *instances;
209 bool icds_scanned;
210 struct loader_scanned_icds *scanned_icd_list;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600211 bool layers_scanned;
212
213 unsigned int loaded_layer_lib_count;
214 struct loader_lib_info *loaded_layer_lib_list;
215
Jon Ashburn27cd5842015-05-12 17:26:48 -0600216 char *layer_dirs;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600217
218 /* TODO: eliminate fixed limit */
219 unsigned int scanned_layer_count; // indicate number of scanned layers
Jon Ashburn27cd5842015-05-12 17:26:48 -0600220 size_t scanned_ext_list_capacity;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600221 struct loader_scanned_layers scanned_layers[MAX_LAYER_LIBRARIES];
222
223 /* Keep track of all the extensions available via GetGlobalExtensionInfo */
224 struct loader_extension_list global_extensions;
225};
226
227struct loader_scanned_icds {
228 char *lib_name;
229 loader_platform_dl_handle handle;
230
231 PFN_vkCreateInstance CreateInstance;
232 PFN_vkDestroyInstance DestroyInstance;
233 PFN_vkEnumeratePhysicalDevices EnumeratePhysicalDevices;
234 PFN_vkGetGlobalExtensionInfo GetGlobalExtensionInfo;
235 PFN_vkGetPhysicalDeviceExtensionInfo GetPhysicalDeviceExtensionInfo;
236 VkInstance instance;
237 struct loader_scanned_icds *next;
238
239 /* cache of global extensions for specific ICD */
240 struct loader_extension_list global_extension_list;
241
242 /*
243 * cache of device extensions for specific ICD,
244 * filled in at CreateInstance time
245 */
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600246 struct loader_extension_list device_extension_list;
Jon Ashburn27cd5842015-05-12 17:26:48 -0600247};
248
Jon Ashburn1ed042c2015-05-01 18:00:33 -0600249static inline void loader_set_dispatch(VkObject obj, const void *data)
Chia-I Wu5291c762015-04-11 15:34:07 +0800250{
251 *((const void **) obj) = data;
252}
253
Jon Ashburn1ed042c2015-05-01 18:00:33 -0600254static inline VkLayerDispatchTable *loader_get_dispatch(const VkObject obj)
Chia-I Wu5291c762015-04-11 15:34:07 +0800255{
Jon Ashburn1ed042c2015-05-01 18:00:33 -0600256 return *((VkLayerDispatchTable **) obj);
Chia-I Wu5291c762015-04-11 15:34:07 +0800257}
258
Jon Ashburn27cd5842015-05-12 17:26:48 -0600259static inline VkLayerInstanceDispatchTable *loader_get_instance_dispatch(const VkObject obj)
260{
261 return *((VkLayerInstanceDispatchTable **) obj);
262}
263
Jon Ashburn1ed042c2015-05-01 18:00:33 -0600264static inline void loader_init_dispatch(VkObject obj, const void *data)
Chia-I Wu5291c762015-04-11 15:34:07 +0800265{
Jon Ashburn40066642015-04-15 13:34:33 -0600266#ifdef DEBUG
Chia-I Wu5291c762015-04-11 15:34:07 +0800267 assert(valid_loader_magic_value(obj) &&
268 "Incompatible ICD, first dword must be initialized to ICD_LOADER_MAGIC. See loader/README.md for details.");
Jon Ashburn40066642015-04-15 13:34:33 -0600269#endif
Chia-I Wu5291c762015-04-11 15:34:07 +0800270
Jon Ashburn1ed042c2015-05-01 18:00:33 -0600271 loader_set_dispatch(obj, data);
Chia-I Wu5291c762015-04-11 15:34:07 +0800272}
273
Jon Ashburn27cd5842015-05-12 17:26:48 -0600274/* global variables used across files */
275extern struct loader_struct loader;
276extern LOADER_PLATFORM_THREAD_ONCE_DEFINITION(once_icd);
277extern LOADER_PLATFORM_THREAD_ONCE_DEFINITION(once_layer);
278extern LOADER_PLATFORM_THREAD_ONCE_DEFINITION(once_exts);
279extern VkLayerInstanceDispatchTable instance_disp;
Jon Ashburnbacb0f52015-04-06 10:58:22 -0600280
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600281struct loader_msg_callback_map_entry {
282 VkDbgMsgCallback icd_obj;
283 VkDbgMsgCallback loader_obj;
284};
285
286bool compare_vk_extension_properties(
287 const VkExtensionProperties* op1,
288 const VkExtensionProperties* op2);
289
Jon Ashburn27cd5842015-05-12 17:26:48 -0600290/* instance layer chain termination entrypoint definitions */
291VkResult loader_CreateInstance(
292 const VkInstanceCreateInfo* pCreateInfo,
293 VkInstance* pInstance);
Chia-I Wu5291c762015-04-11 15:34:07 +0800294
Jon Ashburn27cd5842015-05-12 17:26:48 -0600295VkResult loader_DestroyInstance(
296 VkInstance instance);
297
298VkResult loader_EnumeratePhysicalDevices(
299 VkInstance instance,
300 uint32_t* pPhysicalDeviceCount,
301 VkPhysicalDevice* pPhysicalDevices);
Jon Ashburn95a77ba2015-05-15 15:09:35 -0600302VkResult loader_GetPhysicalDeviceInfo(
303 VkPhysicalDevice gpu,
304 VkPhysicalDeviceInfoType infoType,
305 size_t* pDataSize,
306 void* pData);
307
308VkResult loader_CreateDevice(
309 VkPhysicalDevice gpu,
310 const VkDeviceCreateInfo* pCreateInfo,
311 VkDevice* pDevice);
Jon Ashburn27cd5842015-05-12 17:26:48 -0600312
Jon Ashburneceb13e2015-05-18 15:28:32 -0600313#if 0
Jon Ashburn27cd5842015-05-12 17:26:48 -0600314VkResult VKAPI loader_GetGlobalExtensionInfo(
315 VkExtensionInfoType infoType,
316 uint32_t extensionIndex,
317 size_t* pDataSize,
318 void* pData);
319
Jon Ashburn95a77ba2015-05-15 15:09:35 -0600320VkResult loader_GetPhysicalDeviceExtensionInfo(
321 VkPhysicalDevice gpu,
322 VkExtensionInfoType infoType,
323 uint32_t extensionIndex,
324 size_t* pDataSize,
325 void* pData);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600326#endif
Jon Ashburn95a77ba2015-05-15 15:09:35 -0600327
Jon Ashburn95a77ba2015-05-15 15:09:35 -0600328VkResult loader_GetMultiDeviceCompatibility(
329 VkPhysicalDevice gpu0,
330 VkPhysicalDevice gpu1,
331 VkPhysicalDeviceCompatibilityInfo* pInfo);
332
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600333/* helper function definitions */
334bool has_vk_extension_property(
335 const VkExtensionProperties *vk_ext_prop,
336 const struct loader_extension_list *ext_list);
Jon Ashburn27cd5842015-05-12 17:26:48 -0600337
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600338void loader_add_to_ext_list(
339 struct loader_extension_list *ext_list,
340 uint32_t prop_list_count,
341 const struct loader_extension_property *props);
Jon Ashburn27cd5842015-05-12 17:26:48 -0600342
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600343void loader_enable_instance_layers(struct loader_instance *inst);
Jon Ashburn27cd5842015-05-12 17:26:48 -0600344
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600345bool loader_is_extension_scanned(const VkExtensionProperties *ext_prop);
Jon Ashburn27cd5842015-05-12 17:26:48 -0600346void loader_icd_scan(void);
347void layer_lib_scan(void);
348void loader_coalesce_extensions(void);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600349
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600350static loader_platform_dl_handle loader_add_layer_lib(
351 const char *chain_type,
352 struct loader_extension_property *ext_prop);
353static void loader_remove_layer_lib(
354 struct loader_instance *inst,
355 struct loader_extension_property *ext_prop);
356
Jon Ashburn95a77ba2015-05-15 15:09:35 -0600357struct loader_icd * loader_get_icd(const VkBaseLayerObject *gpu,
358 uint32_t *gpu_index);
Jon Ashburn27cd5842015-05-12 17:26:48 -0600359uint32_t loader_activate_instance_layers(struct loader_instance *inst);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600360void loader_activate_instance_layer_extensions(struct loader_instance *inst);
Chia-I Wu19300602014-08-04 08:03:57 +0800361#endif /* LOADER_H */