blob: 064b3dca5061a70130327d878db0f629133e38a3 [file] [log] [blame]
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001/*
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06002 * Vulkan
Chia-I Wu5f72d0f2014-08-01 11:21:23 +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 Wu44e42362014-09-02 08:32:09 +080023 *
24 * Authors:
25 * Chia-I Wu <olv@lunarg.com>
Jon Ashburn406a0fe2014-11-14 09:52:42 -070026 * Jon Ashburn <jon@lunarg.com>
Chia-I Wu44e42362014-09-02 08:32:09 +080027 * Courtney Goeltzenleuchter <courtney@lunarg.com>
Ian Elliott76005132015-03-31 15:32:41 -060028 * Ian Elliott <ian@lunarg.com>
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080029 */
Jon Ashburn183dfd02014-10-22 18:13:16 -060030#define _GNU_SOURCE
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080031#include <stdio.h>
32#include <stdlib.h>
33#include <stdarg.h>
34#include <stdbool.h>
35#include <string.h>
36
Chia-I Wu894a1172014-08-04 11:18:20 +080037#include <sys/types.h>
Ian Elliott81ac44c2015-01-13 17:52:38 -070038#if defined(WIN32)
39#include "dirent_on_windows.h"
40#else // WIN32
Chia-I Wu894a1172014-08-04 11:18:20 +080041#include <dirent.h>
Ian Elliott81ac44c2015-01-13 17:52:38 -070042#endif // WIN32
43#include "loader_platform.h"
Chia-I Wu468e3c32014-08-04 08:03:57 +080044#include "loader.h"
Jon Ashburncedc15f2015-05-21 18:13:33 -060045#include "wsi_lunarg.h"
Jon Ashburnfce93d92015-05-12 17:26:48 -060046#include "gpa_helper.h"
47#include "table_ops.h"
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -060048#include "debug_report.h"
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -060049#include "vkIcd.h"
Ian Elliott20f06872015-02-12 17:08:34 -070050// The following is #included again to catch certain OS-specific functions
51// being used:
52#include "loader_platform.h"
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080053
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -060054void loader_add_to_ext_list(
55 struct loader_extension_list *ext_list,
56 uint32_t prop_list_count,
57 const struct loader_extension_property *prop_list);
58
59static void loader_deactivate_instance_layers(struct loader_instance *instance);
60
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -060061/* TODO: do we need to lock around access to linked lists and such? */
Jon Ashburnfce93d92015-05-12 17:26:48 -060062struct loader_struct loader = {0};
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080063
Jon Ashburnfce93d92015-05-12 17:26:48 -060064VkLayerInstanceDispatchTable instance_disp = {
65 .GetInstanceProcAddr = vkGetInstanceProcAddr,
Jon Ashburnfce93d92015-05-12 17:26:48 -060066 .CreateInstance = loader_CreateInstance,
67 .DestroyInstance = loader_DestroyInstance,
68 .EnumeratePhysicalDevices = loader_EnumeratePhysicalDevices,
Jon Ashburn2666e2f2015-05-15 15:09:35 -060069 .GetPhysicalDeviceInfo = loader_GetPhysicalDeviceInfo,
70 .CreateDevice = loader_CreateDevice,
Jon Ashburn9de95602015-05-18 15:28:32 -060071 .GetGlobalExtensionInfo = vkGetGlobalExtensionInfo,
Jon Ashburn2666e2f2015-05-15 15:09:35 -060072 .GetPhysicalDeviceExtensionInfo = loader_GetPhysicalDeviceExtensionInfo,
Jon Ashburn2666e2f2015-05-15 15:09:35 -060073 .GetMultiDeviceCompatibility = loader_GetMultiDeviceCompatibility,
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -060074 .GetDisplayInfoWSI = loader_GetDisplayInfoWSI,
75 .DbgCreateMsgCallback = loader_DbgCreateMsgCallback,
76 .DbgDestroyMsgCallback = loader_DbgDestroyMsgCallback,
Jon Ashburnfce93d92015-05-12 17:26:48 -060077};
78
79LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_icd);
80LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_layer);
81LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_exts);
Ian Elliott81ac44c2015-01-13 17:52:38 -070082
Ian Elliott225188f2015-02-17 10:33:47 -070083#if defined(WIN32)
Ian Elliott76005132015-03-31 15:32:41 -060084char *loader_get_registry_string(const HKEY hive,
85 const LPCTSTR sub_key,
86 const char *value)
87{
88 DWORD access_flags = KEY_QUERY_VALUE;
89 DWORD value_type;
90 HKEY key;
Ian Elliott464711a2015-04-28 15:57:32 -060091 VkResult rtn_value;
Ian Elliott76005132015-03-31 15:32:41 -060092 char *rtn_str = NULL;
Tony Barboura938abb2015-04-22 11:36:22 -060093 DWORD rtn_len = 0;
Ian Elliott76005132015-03-31 15:32:41 -060094 size_t allocated_len = 0;
95
96 rtn_value = RegOpenKeyEx(hive, sub_key, 0, access_flags, &key);
97 if (rtn_value != ERROR_SUCCESS) {
98 // We didn't find the key. Try the 32-bit hive (where we've seen the
99 // key end up on some people's systems):
100 access_flags |= KEY_WOW64_32KEY;
101 rtn_value = RegOpenKeyEx(hive, sub_key, 0, access_flags, &key);
102 if (rtn_value != ERROR_SUCCESS) {
103 // We still couldn't find the key, so give up:
104 return NULL;
105 }
106 }
107
108 rtn_value = RegQueryValueEx(key, value, NULL, &value_type,
Ian Elliott464711a2015-04-28 15:57:32 -0600109 (PVOID) rtn_str, (LPDWORD) &rtn_len);
Ian Elliott76005132015-03-31 15:32:41 -0600110 if (rtn_value == ERROR_SUCCESS) {
111 // If we get to here, we found the key, and need to allocate memory
112 // large enough for rtn_str, and query again:
113 allocated_len = rtn_len + 4;
114 rtn_str = malloc(allocated_len);
115 rtn_value = RegQueryValueEx(key, value, NULL, &value_type,
Ian Elliott464711a2015-04-28 15:57:32 -0600116 (PVOID) rtn_str, (LPDWORD) &rtn_len);
Ian Elliott76005132015-03-31 15:32:41 -0600117 if (rtn_value == ERROR_SUCCESS) {
118 // We added 4 extra bytes to rtn_str, so that we can ensure that
119 // the string is NULL-terminated (albeit, in a brute-force manner):
120 rtn_str[allocated_len-1] = '\0';
121 } else {
122 // This should never occur, but in case it does, clean up:
123 free(rtn_str);
124 rtn_str = NULL;
125 }
126 } // else - shouldn't happen, but if it does, return rtn_str, which is NULL
127
128 // Close the registry key that was opened:
129 RegCloseKey(key);
130
131 return rtn_str;
132}
133
134
Ian Elliott225188f2015-02-17 10:33:47 -0700135// For ICD developers, look in the registry, and look for an environment
136// variable for a path(s) where to find the ICD(s):
137static char *loader_get_registry_and_env(const char *env_var,
138 const char *registry_value)
139{
140 char *env_str = getenv(env_var);
141 size_t env_len = (env_str == NULL) ? 0 : strlen(env_str);
Ian Elliott76005132015-03-31 15:32:41 -0600142 char *registry_str = NULL;
Tony Barboura938abb2015-04-22 11:36:22 -0600143 size_t registry_len = 0;
Ian Elliott225188f2015-02-17 10:33:47 -0700144 char *rtn_str = NULL;
145 size_t rtn_len;
146
Ian Elliott76005132015-03-31 15:32:41 -0600147 registry_str = loader_get_registry_string(HKEY_LOCAL_MACHINE,
Ian Elliott10ec9622015-04-09 18:07:15 -0600148 "Software\\Vulkan",
Ian Elliott76005132015-03-31 15:32:41 -0600149 registry_value);
Ian Elliott464711a2015-04-28 15:57:32 -0600150 registry_len = (registry_str) ? (DWORD) strlen(registry_str) : 0;
Ian Elliott225188f2015-02-17 10:33:47 -0700151
152 rtn_len = env_len + registry_len + 1;
153 if (rtn_len <= 2) {
154 // We found neither the desired registry value, nor the environment
155 // variable; return NULL:
156 return NULL;
157 } else {
158 // We found something, and so we need to allocate memory for the string
159 // to return:
160 rtn_str = malloc(rtn_len);
161 }
162
Ian Elliott76005132015-03-31 15:32:41 -0600163 if (registry_len == 0) {
Ian Elliott225188f2015-02-17 10:33:47 -0700164 // We didn't find the desired registry value, and so we must have found
165 // only the environment variable:
166 _snprintf(rtn_str, rtn_len, "%s", env_str);
167 } else if (env_str != NULL) {
168 // We found both the desired registry value and the environment
169 // variable, so concatenate them both:
170 _snprintf(rtn_str, rtn_len, "%s;%s", registry_str, env_str);
171 } else {
172 // We must have only found the desired registry value:
173 _snprintf(rtn_str, rtn_len, "%s", registry_str);
174 }
175
Ian Elliott7518ecd2015-04-03 13:13:01 -0600176 if (registry_str) {
177 free(registry_str);
178 }
Ian Elliott225188f2015-02-17 10:33:47 -0700179
180 return(rtn_str);
181}
182#endif // WIN32
183
184
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600185static void loader_log(VkFlags msg_type, int32_t msg_code,
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800186 const char *format, ...)
187{
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800188 char msg[256];
189 va_list ap;
190 int ret;
191
192 va_start(ap, format);
193 ret = vsnprintf(msg, sizeof(msg), format, ap);
Ian Elliott642f8922015-02-13 14:29:21 -0700194 if ((ret >= (int) sizeof(msg)) || ret < 0) {
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800195 msg[sizeof(msg) - 1] = '\0';
196 }
197 va_end(ap);
198
Jon Ashburnb67859d2015-04-24 14:10:50 -0700199#if defined(WIN32)
200 OutputDebugString(msg);
Jon Ashburn1da405d2015-05-05 16:20:46 -0600201#endif
Courtney Goeltzenleuchter9d36ef42015-04-13 14:10:06 -0600202 fputs(msg, stderr);
203 fputc('\n', stderr);
Jon Ashburn1da405d2015-05-05 16:20:46 -0600204
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800205}
206
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600207bool compare_vk_extension_properties(const VkExtensionProperties *op1, const VkExtensionProperties *op2)
208{
209 return memcmp(op1, op2, sizeof(VkExtensionProperties)) == 0 ? true : false;
210}
211
212/*
213 * Used to look for an extension with a specific name.
214 * Ignores all other extension info (i.e. version, origin & dependencies)
215 */
216static bool has_extension_name(
217 uint32_t count,
218 struct loader_extension_property *exts,
219 const char *target_ext_name,
220 bool must_be_hosted)
Jon Ashburneb2728b2015-04-10 14:33:07 -0600221{
222 uint32_t i;
223 for (i = 0; i < count; i++) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600224 if (!strcmp(exts[i].info.name, target_ext_name) && (!must_be_hosted || exts[i].hosted))
Jon Ashburneb2728b2015-04-10 14:33:07 -0600225 return true;
226 }
227 return false;
228}
229
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600230static bool has_extension(
231 uint32_t count,
232 struct loader_extension_property *exts,
233 const VkExtensionProperties *target_ext,
234 bool must_be_hosted)
Jon Ashburneb2728b2015-04-10 14:33:07 -0600235{
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600236 uint32_t i;
237 for (i = 0; i < count; i++) {
238 if (compare_vk_extension_properties(&exts[i].info, target_ext) && (!must_be_hosted || exts[i].hosted))
239 return true;
240 }
241 return false;
242}
243
244/*
245 * Search the given ext_list for an extension
246 * matching the given vk_ext_prop
247 */
248bool has_vk_extension_property(
249 const VkExtensionProperties *vk_ext_prop,
250 const struct loader_extension_list *ext_list)
251{
252 for (uint32_t i = 0; i < ext_list->count; i++) {
253 if (compare_vk_extension_properties(&ext_list->list[i].info, vk_ext_prop))
254 return true;
255 }
256 return false;
257}
258
259/*
260 * Search the given ext_list for an extension
261 * matching the given vk_ext_prop
262 */
263static struct loader_extension_property *get_extension_property_from_vkext(
264 const VkExtensionProperties *vk_ext_prop,
265 const struct loader_extension_list *ext_list)
266{
267 for (uint32_t i = 0; i < ext_list->count; i++) {
268 if (compare_vk_extension_properties(&ext_list->list[i].info, vk_ext_prop))
269 return &ext_list->list[i];
270 }
271 return NULL;
272}
273
274static void get_global_extensions(
275 const PFN_vkGetGlobalExtensionInfo fp_get,
276 const char *lib_name,
277 const enum extension_origin origin,
278 struct loader_extension_list *ext_list)
279{
280 uint32_t i, count;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600281 size_t siz = sizeof(count);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600282 struct loader_extension_property ext_props;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600283 VkResult res;
284
Jon Ashburneb2728b2015-04-10 14:33:07 -0600285 res = fp_get(VK_EXTENSION_INFO_TYPE_COUNT, 0, &siz, &count);
286 if (res != VK_SUCCESS) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600287 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Error getting global extension count from ICD");
Jon Ashburneb2728b2015-04-10 14:33:07 -0600288 return;
289 }
290 siz = sizeof(VkExtensionProperties);
Jon Ashburneb2728b2015-04-10 14:33:07 -0600291 for (i = 0; i < count; i++) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600292 memset(&ext_props, 1, sizeof(ext_props));
293 res = fp_get(VK_EXTENSION_INFO_TYPE_PROPERTIES, i, &siz, &ext_props.info);
Jon Ashburneb2728b2015-04-10 14:33:07 -0600294 if (res == VK_SUCCESS) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600295 ext_props.hosted = false;
296 ext_props.origin = origin;
297 ext_props.lib_name = lib_name;
298 loader_add_to_ext_list(ext_list, 1, &ext_props);
Jon Ashburneb2728b2015-04-10 14:33:07 -0600299 }
Jon Ashburneb2728b2015-04-10 14:33:07 -0600300 }
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600301
Jon Ashburneb2728b2015-04-10 14:33:07 -0600302 return;
303}
304
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600305static bool loader_init_ext_list(struct loader_extension_list *ext_info)
Jon Ashburneb2728b2015-04-10 14:33:07 -0600306{
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600307 ext_info->capacity = 32 * sizeof(struct loader_extension_property);
308 ext_info->list = malloc(ext_info->capacity);
309 if (ext_info->list == NULL) {
310 return false;
311 }
312 memset(ext_info->list, 0, ext_info->capacity);
313 ext_info->count = 0;
314 return true;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600315}
316
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600317static void loader_destroy_ext_list(struct loader_extension_list *ext_info)
Jon Ashburneb2728b2015-04-10 14:33:07 -0600318{
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600319 free(ext_info->list);
320 ext_info->count = 0;
321 ext_info->capacity = 0;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600322}
Jon Ashburneb2728b2015-04-10 14:33:07 -0600323
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600324static void loader_add_vk_ext_to_ext_list(
325 struct loader_extension_list *ext_list,
326 uint32_t prop_list_count,
327 const VkExtensionProperties *props,
328 const struct loader_extension_list *search_list)
Jon Ashburneb2728b2015-04-10 14:33:07 -0600329{
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600330 struct loader_extension_property *ext_prop;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600331
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600332 for (uint32_t i = 0; i < prop_list_count; i++) {
333 // look for duplicates
334 if (has_vk_extension_property(&props[i], ext_list)) {
335 continue;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600336 }
337
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600338 ext_prop = get_extension_property_from_vkext(&props[i], search_list);
339 if (!ext_prop) {
340 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Unable to find extension %s", props[i].name);
341 continue;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600342 }
343
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600344 loader_add_to_ext_list(ext_list, 1, ext_prop);
Jon Ashburneb2728b2015-04-10 14:33:07 -0600345 }
346}
347
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600348/*
349 * Append non-duplicate extension properties defined in prop_list
350 * to the given ext_info list
351 */
352void loader_add_to_ext_list(
353 struct loader_extension_list *ext_list,
354 uint32_t prop_list_count,
355 const struct loader_extension_property *props)
356{
357 uint32_t i;
358 struct loader_extension_property *cur_ext;
359
360 if (ext_list->list == NULL || ext_list->capacity == 0) {
361 loader_init_ext_list(ext_list);
362 }
363
364 if (ext_list->list == NULL)
365 return;
366
367 for (i = 0; i < prop_list_count; i++) {
368 cur_ext = (struct loader_extension_property *) &props[i];
369
370 // look for duplicates
371 if (has_vk_extension_property(&cur_ext->info, ext_list)) {
372 continue;
373 }
374
375 // add to list at end
376 // check for enough capacity
377 if (ext_list->count * sizeof(struct loader_extension_property)
378 >= ext_list->capacity) {
379 // double capacity
380 ext_list->capacity *= 2;
381 ext_list->list = realloc(ext_list->list, ext_list->capacity);
382 }
383 memcpy(&ext_list->list[ext_list->count], cur_ext, sizeof(struct loader_extension_property));
384 ext_list->count++;
385 }
386}
387
388/*
389 * Search the search_list for any extension with
390 * a name that matches the given ext_name.
391 * Add all matching extensions to the found_list
392 * Do not add if found VkExtensionProperties is already
393 * on the found_list
394 */
395static void loader_search_ext_list_for_name(
396 const char *ext_name,
397 const struct loader_extension_list *search_list,
398 struct loader_extension_list *found_list)
399{
400 for (uint32_t i = 0; i < search_list->count; i++) {
401 struct loader_extension_property *ext_prop = &search_list->list[i];
402 if (0 == strcmp(ext_prop->info.name, ext_name)) {
403 /* Found an extension with the same name, add to found_list */
404 loader_add_to_ext_list(found_list, 1, &search_list->list[i]);
405 }
406 }
407}
408
409bool loader_is_extension_scanned(const VkExtensionProperties *ext_prop)
Jon Ashburn42e41032015-04-14 09:15:32 -0600410{
411 uint32_t i;
412
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600413 for (i = 0; i < loader.global_extensions.count; i++) {
414 if (compare_vk_extension_properties(&loader.global_extensions.list[i].info, ext_prop))
Jon Ashburn42e41032015-04-14 09:15:32 -0600415 return true;
416 }
417 return false;
418}
419
Jon Ashburnfce93d92015-05-12 17:26:48 -0600420void loader_coalesce_extensions(void)
Jon Ashburneb2728b2015-04-10 14:33:07 -0600421{
422 uint32_t i;
423 struct loader_scanned_icds *icd_list = loader.scanned_icd_list;
424
425 // traverse scanned icd list adding non-duplicate extensions to the list
426 while (icd_list != NULL) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600427 /* TODO: convert to use ext_list */
428 loader_add_to_ext_list(&loader.global_extensions,
429 icd_list->global_extension_list.count,
430 icd_list->global_extension_list.list);
Jon Ashburneb2728b2015-04-10 14:33:07 -0600431 icd_list = icd_list->next;
432 };
433
434 //Traverse layers list adding non-duplicate extensions to the list
435 for (i = 0; i < loader.scanned_layer_count; i++) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600436 loader_add_to_ext_list(&loader.global_extensions,
437 loader.scanned_layers[i].global_extension_list.count,
438 loader.scanned_layers[i].global_extension_list.list);
Jon Ashburneb2728b2015-04-10 14:33:07 -0600439 }
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600440
441 // Traverse loader's extensions, adding non-duplicate extensions to the list
442 debug_report_add_instance_extensions(&loader.global_extensions);
Jon Ashburna445e092015-05-26 13:57:35 -0600443 wsi_lunarg_add_instance_extensions(&loader.global_extensions);
Jon Ashburneb2728b2015-04-10 14:33:07 -0600444}
445
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600446static void loader_icd_destroy(
447 struct loader_instance *ptr_inst,
448 struct loader_icd *icd)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800449{
Ian Elliott81ac44c2015-01-13 17:52:38 -0700450 loader_platform_close_library(icd->scanned_icds->handle);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600451 ptr_inst->total_icd_count--;
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800452 free(icd);
453}
454
Jon Ashburneb2728b2015-04-10 14:33:07 -0600455static struct loader_icd * loader_icd_create(const struct loader_scanned_icds *scanned)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800456{
457 struct loader_icd *icd;
458
459 icd = malloc(sizeof(*icd));
460 if (!icd)
461 return NULL;
462
Courtney Goeltzenleuchter6f928162014-10-28 10:29:27 -0600463 memset(icd, 0, sizeof(*icd));
464
Jon Ashburn14275da2015-01-28 11:01:35 -0700465 icd->scanned_icds = scanned;
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800466
467 return icd;
468}
469
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600470static struct loader_icd *loader_icd_add(
471 struct loader_instance *ptr_inst,
472 const struct loader_scanned_icds *scanned)
Chia-I Wu894a1172014-08-04 11:18:20 +0800473{
474 struct loader_icd *icd;
475
Jon Ashburn14275da2015-01-28 11:01:35 -0700476 icd = loader_icd_create(scanned);
Chia-I Wu894a1172014-08-04 11:18:20 +0800477 if (!icd)
478 return NULL;
479
Chia-I Wu894a1172014-08-04 11:18:20 +0800480 /* prepend to the list */
Jon Ashburn3336df82015-01-29 15:45:51 -0700481 icd->next = ptr_inst->icds;
482 ptr_inst->icds = icd;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600483 ptr_inst->total_icd_count++;
Chia-I Wu894a1172014-08-04 11:18:20 +0800484
485 return icd;
486}
487
Jon Ashburn14275da2015-01-28 11:01:35 -0700488static void loader_scanned_icd_add(const char *filename)
489{
Ian Elliott81ac44c2015-01-13 17:52:38 -0700490 loader_platform_dl_handle handle;
Jon Ashburn0dd356d2015-05-14 12:43:38 -0600491 void *fp_create_inst;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600492 void *fp_get_global_ext_info;
Jon Ashburn14275da2015-01-28 11:01:35 -0700493 struct loader_scanned_icds *new_node;
494
Ian Elliott81ac44c2015-01-13 17:52:38 -0700495 // Used to call: dlopen(filename, RTLD_LAZY);
496 handle = loader_platform_open_library(filename);
Jon Ashburn14275da2015-01-28 11:01:35 -0700497 if (!handle) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600498 loader_log(VK_DBG_REPORT_WARN_BIT, 0, loader_platform_open_library_error(filename));
Jon Ashburn14275da2015-01-28 11:01:35 -0700499 return;
500 }
501
502#define LOOKUP(func_ptr, func) do { \
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600503 func_ptr = (PFN_vk ##func) loader_platform_get_proc_address(handle, "vk" #func); \
Jon Ashburn14275da2015-01-28 11:01:35 -0700504 if (!func_ptr) { \
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600505 loader_log(VK_DBG_REPORT_WARN_BIT, 0, loader_platform_get_proc_address_error("vk" #func)); \
Jon Ashburn14275da2015-01-28 11:01:35 -0700506 return; \
507 } \
508} while (0)
509
Jon Ashburn3336df82015-01-29 15:45:51 -0700510 LOOKUP(fp_create_inst, CreateInstance);
Jon Ashburneb2728b2015-04-10 14:33:07 -0600511 LOOKUP(fp_get_global_ext_info, GetGlobalExtensionInfo);
Jon Ashburn14275da2015-01-28 11:01:35 -0700512#undef LOOKUP
513
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600514 new_node = (struct loader_scanned_icds *) malloc(sizeof(struct loader_scanned_icds)
515 + strlen(filename) + 1);
Jon Ashburn14275da2015-01-28 11:01:35 -0700516 if (!new_node) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600517 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Out of memory can't add icd");
Jon Ashburn14275da2015-01-28 11:01:35 -0700518 return;
519 }
520
521 new_node->handle = handle;
Jon Ashburn3336df82015-01-29 15:45:51 -0700522 new_node->CreateInstance = fp_create_inst;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600523 new_node->GetGlobalExtensionInfo = fp_get_global_ext_info;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600524 loader_init_ext_list(&new_node->global_extension_list);
Jon Ashburn14275da2015-01-28 11:01:35 -0700525 new_node->next = loader.scanned_icd_list;
Jon Ashburn14275da2015-01-28 11:01:35 -0700526
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600527 new_node->lib_name = (char *) (new_node + 1);
528 if (!new_node->lib_name) {
529 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Out of memory can't add icd");
530 return;
531 }
532 strcpy(new_node->lib_name, filename);
533
Jon Ashburneb2728b2015-04-10 14:33:07 -0600534 loader.scanned_icd_list = new_node;
535
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600536 get_global_extensions(
537 (PFN_vkGetGlobalExtensionInfo) fp_get_global_ext_info,
538 new_node->lib_name,
539 VK_EXTENSION_ORIGIN_ICD,
540 &new_node->global_extension_list);
Jon Ashburneb2728b2015-04-10 14:33:07 -0600541}
Ian Elliott81ac44c2015-01-13 17:52:38 -0700542
Jon Ashburn0dd356d2015-05-14 12:43:38 -0600543static void loader_icd_init_entrys(struct loader_icd *icd,
544 struct loader_scanned_icds *scanned_icds)
545{
546 /* initialize entrypoint function pointers */
547
548 #define LOOKUP(func) do { \
549 icd->func = (PFN_vk ##func) loader_platform_get_proc_address(scanned_icds->handle, "vk" #func); \
550 if (!icd->func) { \
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600551 loader_log(VK_DBG_REPORT_WARN_BIT, 0, loader_platform_get_proc_address_error("vk" #func)); \
Jon Ashburn0dd356d2015-05-14 12:43:38 -0600552 return; \
553 } \
554 } while (0)
555
Jon Ashburn1245cec2015-05-18 13:20:15 -0600556 /* could change this to use GetInstanceProcAddr in driver instead of dlsym */
557 LOOKUP(GetDeviceProcAddr);
Jon Ashburn0dd356d2015-05-14 12:43:38 -0600558 LOOKUP(DestroyInstance);
559 LOOKUP(EnumeratePhysicalDevices);
560 LOOKUP(GetPhysicalDeviceInfo);
561 LOOKUP(CreateDevice);
562 LOOKUP(GetPhysicalDeviceExtensionInfo);
Jon Ashburn0dd356d2015-05-14 12:43:38 -0600563 LOOKUP(GetMultiDeviceCompatibility);
Jon Ashburn2666e2f2015-05-15 15:09:35 -0600564 LOOKUP(GetDisplayInfoWSI);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600565 LOOKUP(DbgCreateMsgCallback);
566 LOOKUP(DbgDestroyMsgCallback);
Jon Ashburn0dd356d2015-05-14 12:43:38 -0600567#undef LOOKUP
568
569 return;
570}
571
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600572/**
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600573 * Try to \c loader_icd_scan VK driver(s).
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600574 *
575 * This function scans the default system path or path
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600576 * specified by the \c LIBVK_DRIVERS_PATH environment variable in
577 * order to find loadable VK ICDs with the name of libVK_*.
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600578 *
579 * \returns
580 * void; but side effect is to set loader_icd_scanned to true
581 */
Jon Ashburnfce93d92015-05-12 17:26:48 -0600582void loader_icd_scan(void)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800583{
Ian Elliott225188f2015-02-17 10:33:47 -0700584 const char *p, *next;
585 char *libPaths = NULL;
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600586 DIR *sysdir;
587 struct dirent *dent;
588 char icd_library[1024];
Jon Ashburn0f45b2a2014-10-03 16:31:35 -0600589 char path[1024];
Ian Elliott64f74a82015-02-04 12:06:46 -0700590 uint32_t len;
Ian Elliott225188f2015-02-17 10:33:47 -0700591#if defined(WIN32)
592 bool must_free_libPaths;
593 libPaths = loader_get_registry_and_env(DRIVER_PATH_ENV,
594 DRIVER_PATH_REGISTRY_VALUE);
595 if (libPaths != NULL) {
596 must_free_libPaths = true;
597 } else {
598 must_free_libPaths = false;
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600599 libPaths = DEFAULT_VK_DRIVERS_PATH;
Ian Elliott225188f2015-02-17 10:33:47 -0700600 }
601#else // WIN32
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600602 if (geteuid() == getuid()) {
Ian Elliott225188f2015-02-17 10:33:47 -0700603 /* Don't allow setuid apps to use the DRIVER_PATH_ENV env var: */
604 libPaths = getenv(DRIVER_PATH_ENV);
605 }
606 if (libPaths == NULL) {
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600607 libPaths = DEFAULT_VK_DRIVERS_PATH;
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600608 }
Ian Elliott81ac44c2015-01-13 17:52:38 -0700609#endif // WIN32
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800610
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600611 for (p = libPaths; *p; p = next) {
Ian Elliott81ac44c2015-01-13 17:52:38 -0700612 next = strchr(p, PATH_SEPERATOR);
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600613 if (next == NULL) {
Ian Elliott64f74a82015-02-04 12:06:46 -0700614 len = (uint32_t) strlen(p);
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600615 next = p + len;
616 }
617 else {
Ian Elliott64f74a82015-02-04 12:06:46 -0700618 len = (uint32_t) (next - p);
Jon Ashburn0f45b2a2014-10-03 16:31:35 -0600619 sprintf(path, "%.*s", (len > sizeof(path) - 1) ? (int) sizeof(path) - 1 : len, p);
620 p = path;
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600621 next++;
622 }
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800623
Ian Elliott81ac44c2015-01-13 17:52:38 -0700624 // TODO/TBD: Do we want to do this on Windows, or just let Windows take
625 // care of its own search path (which it apparently has)?
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600626 sysdir = opendir(p);
627 if (sysdir) {
628 dent = readdir(sysdir);
629 while (dent) {
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600630 /* Look for ICDs starting with VK_DRIVER_LIBRARY_PREFIX and
631 * ending with VK_LIBRARY_SUFFIX
Ian Elliott81ac44c2015-01-13 17:52:38 -0700632 */
633 if (!strncmp(dent->d_name,
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600634 VK_DRIVER_LIBRARY_PREFIX,
635 VK_DRIVER_LIBRARY_PREFIX_LEN)) {
Ian Elliott64f74a82015-02-04 12:06:46 -0700636 uint32_t nlen = (uint32_t) strlen(dent->d_name);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600637 const char *suf = dent->d_name + nlen - VK_LIBRARY_SUFFIX_LEN;
638 if ((nlen > VK_LIBRARY_SUFFIX_LEN) &&
Ian Elliott81ac44c2015-01-13 17:52:38 -0700639 !strncmp(suf,
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600640 VK_LIBRARY_SUFFIX,
641 VK_LIBRARY_SUFFIX_LEN)) {
Ian Elliott81ac44c2015-01-13 17:52:38 -0700642 snprintf(icd_library, 1024, "%s" DIRECTORY_SYMBOL "%s", p,dent->d_name);
643 loader_scanned_icd_add(icd_library);
644 }
645 }
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600646
647 dent = readdir(sysdir);
648 }
649 closedir(sysdir);
650 }
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800651 }
652
Ian Elliott225188f2015-02-17 10:33:47 -0700653#if defined(WIN32)
654 // Free any allocated memory:
655 if (must_free_libPaths) {
656 free(libPaths);
657 }
658#endif // WIN32
659
660 // Note that we've scanned for ICDs:
Jon Ashburn14275da2015-01-28 11:01:35 -0700661 loader.icds_scanned = true;
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800662}
663
Jon Ashburnd43f9b62014-10-14 19:15:22 -0600664
Jon Ashburnfce93d92015-05-12 17:26:48 -0600665void layer_lib_scan(void)
Jon Ashburnd43f9b62014-10-14 19:15:22 -0600666{
667 const char *p, *next;
Ian Elliott225188f2015-02-17 10:33:47 -0700668 char *libPaths = NULL;
Jon Ashburnd43f9b62014-10-14 19:15:22 -0600669 DIR *curdir;
670 struct dirent *dent;
Ian Elliott225188f2015-02-17 10:33:47 -0700671 size_t len, i;
Jon Ashburn183dfd02014-10-22 18:13:16 -0600672 char temp_str[1024];
Jon Ashburneb2728b2015-04-10 14:33:07 -0600673 uint32_t count;
674 PFN_vkGetGlobalExtensionInfo fp_get_ext;
Jon Ashburnd43f9b62014-10-14 19:15:22 -0600675
Ian Elliott225188f2015-02-17 10:33:47 -0700676#if defined(WIN32)
677 bool must_free_libPaths;
678 libPaths = loader_get_registry_and_env(LAYERS_PATH_ENV,
679 LAYERS_PATH_REGISTRY_VALUE);
680 if (libPaths != NULL) {
681 must_free_libPaths = true;
682 } else {
683 must_free_libPaths = false;
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600684 libPaths = DEFAULT_VK_LAYERS_PATH;
Jon Ashburnd43f9b62014-10-14 19:15:22 -0600685 }
Ian Elliott225188f2015-02-17 10:33:47 -0700686#else // WIN32
687 if (geteuid() == getuid()) {
688 /* Don't allow setuid apps to use the DRIVER_PATH_ENV env var: */
Courtney Goeltzenleuchter4ee01712015-02-18 20:03:02 -0700689 libPaths = getenv(LAYERS_PATH_ENV);
Ian Elliott225188f2015-02-17 10:33:47 -0700690 }
691 if (libPaths == NULL) {
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600692 libPaths = DEFAULT_VK_LAYERS_PATH;
Ian Elliott225188f2015-02-17 10:33:47 -0700693 }
Ian Elliott81ac44c2015-01-13 17:52:38 -0700694#endif // WIN32
Jon Ashburnd43f9b62014-10-14 19:15:22 -0600695
Ian Elliott225188f2015-02-17 10:33:47 -0700696 if (libPaths == NULL) {
697 // Have no paths to search:
Courtney Goeltzenleuchterbce445a2014-12-01 09:29:42 -0700698 return;
699 }
Ian Elliott225188f2015-02-17 10:33:47 -0700700 len = strlen(libPaths);
Courtney Goeltzenleuchterbce445a2014-12-01 09:29:42 -0700701 loader.layer_dirs = malloc(len+1);
Ian Elliott225188f2015-02-17 10:33:47 -0700702 if (loader.layer_dirs == NULL) {
703 free(libPaths);
Courtney Goeltzenleuchter688c74b2014-12-02 18:12:51 -0700704 return;
Ian Elliott225188f2015-02-17 10:33:47 -0700705 }
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600706 // Alloc passed, so we know there is enough space to hold the string
Ian Elliott225188f2015-02-17 10:33:47 -0700707 strcpy(loader.layer_dirs, libPaths);
708#if defined(WIN32)
709 // Free any allocated memory:
710 if (must_free_libPaths) {
711 free(libPaths);
712 must_free_libPaths = false;
713 }
714#endif // WIN32
Courtney Goeltzenleuchterbce445a2014-12-01 09:29:42 -0700715 libPaths = loader.layer_dirs;
716
Jon Ashburnd43f9b62014-10-14 19:15:22 -0600717 /* cleanup any previously scanned libraries */
Jon Ashburn183dfd02014-10-22 18:13:16 -0600718 for (i = 0; i < loader.scanned_layer_count; i++) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600719 if (loader.scanned_layers[i].lib_name != NULL)
720 free(loader.scanned_layers[i].lib_name);
721 loader_destroy_ext_list(&loader.scanned_layers[i].global_extension_list);
722 loader.scanned_layers[i].lib_name = NULL;
Jon Ashburnd43f9b62014-10-14 19:15:22 -0600723 }
Jon Ashburn183dfd02014-10-22 18:13:16 -0600724 loader.scanned_layer_count = 0;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600725 count = 0;
Jon Ashburnd43f9b62014-10-14 19:15:22 -0600726
Jon Ashburnd43f9b62014-10-14 19:15:22 -0600727 for (p = libPaths; *p; p = next) {
Jon Ashburneb2728b2015-04-10 14:33:07 -0600728 next = strchr(p, PATH_SEPERATOR);
729 if (next == NULL) {
730 len = (uint32_t) strlen(p);
731 next = p + len;
732 }
733 else {
734 len = (uint32_t) (next - p);
735 *(char *) next = '\0';
736 next++;
737 }
Jon Ashburnd43f9b62014-10-14 19:15:22 -0600738
739 curdir = opendir(p);
740 if (curdir) {
741 dent = readdir(curdir);
742 while (dent) {
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600743 /* Look for layers starting with VK_LAYER_LIBRARY_PREFIX and
744 * ending with VK_LIBRARY_SUFFIX
Ian Elliott81ac44c2015-01-13 17:52:38 -0700745 */
746 if (!strncmp(dent->d_name,
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600747 VK_LAYER_LIBRARY_PREFIX,
748 VK_LAYER_LIBRARY_PREFIX_LEN)) {
Ian Elliott64f74a82015-02-04 12:06:46 -0700749 uint32_t nlen = (uint32_t) strlen(dent->d_name);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600750 const char *suf = dent->d_name + nlen - VK_LIBRARY_SUFFIX_LEN;
751 if ((nlen > VK_LIBRARY_SUFFIX_LEN) &&
Ian Elliott81ac44c2015-01-13 17:52:38 -0700752 !strncmp(suf,
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600753 VK_LIBRARY_SUFFIX,
754 VK_LIBRARY_SUFFIX_LEN)) {
Ian Elliott81ac44c2015-01-13 17:52:38 -0700755 loader_platform_dl_handle handle;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600756 snprintf(temp_str, sizeof(temp_str),
757 "%s" DIRECTORY_SYMBOL "%s",p,dent->d_name);
Ian Elliott81ac44c2015-01-13 17:52:38 -0700758 // Used to call: dlopen(temp_str, RTLD_LAZY)
759 if ((handle = loader_platform_open_library(temp_str)) == NULL) {
760 dent = readdir(curdir);
761 continue;
762 }
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600763 /* TODO: Remove fixed count */
Jon Ashburneb2728b2015-04-10 14:33:07 -0600764 if (count == MAX_LAYER_LIBRARIES) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600765 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
Jon Ashburneb2728b2015-04-10 14:33:07 -0600766 "%s ignored: max layer libraries exceed",
767 temp_str);
Ian Elliott81ac44c2015-01-13 17:52:38 -0700768 break;
769 }
Jon Ashburneb2728b2015-04-10 14:33:07 -0600770 fp_get_ext = loader_platform_get_proc_address(handle,
771 "vkGetGlobalExtensionInfo");
772
773 if (!fp_get_ext) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600774 loader_log(VK_DBG_REPORT_WARN_BIT, 0,
Jon Ashburneb2728b2015-04-10 14:33:07 -0600775 "Couldn't dlsym vkGetGlobalExtensionInfo from library %s",
776 temp_str);
777 dent = readdir(curdir);
778 loader_platform_close_library(handle);
779 continue;
780 }
781
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600782 loader.scanned_layers[count].lib_name =
Jon Ashburneb2728b2015-04-10 14:33:07 -0600783 malloc(strlen(temp_str) + 1);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600784 if (loader.scanned_layers[count].lib_name == NULL) {
785 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "%s ignored: out of memory", temp_str);
Ian Elliott81ac44c2015-01-13 17:52:38 -0700786 break;
787 }
Jon Ashburneb2728b2015-04-10 14:33:07 -0600788
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600789 strcpy(loader.scanned_layers[count].lib_name, temp_str);
Jon Ashburneb2728b2015-04-10 14:33:07 -0600790
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600791 get_global_extensions(
792 fp_get_ext,
793 loader.scanned_layers[count].lib_name,
794 VK_EXTENSION_ORIGIN_LAYER,
795 &loader.scanned_layers[count].global_extension_list);
Jon Ashburneb2728b2015-04-10 14:33:07 -0600796
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600797 count++;
798 loader_platform_close_library(handle);
Ian Elliott81ac44c2015-01-13 17:52:38 -0700799 }
Jon Ashburnd43f9b62014-10-14 19:15:22 -0600800 }
801
802 dent = readdir(curdir);
Jon Ashburneb2728b2015-04-10 14:33:07 -0600803 } // while (dir_entry)
804 if (count == MAX_LAYER_LIBRARIES)
805 break;
Jon Ashburnd43f9b62014-10-14 19:15:22 -0600806 closedir(curdir);
Jon Ashburneb2728b2015-04-10 14:33:07 -0600807 } // if (curdir))
808 } // for (libpaths)
Jon Ashburnd43f9b62014-10-14 19:15:22 -0600809
Jon Ashburneb2728b2015-04-10 14:33:07 -0600810 loader.scanned_layer_count = count;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600811 loader.layers_scanned = true;
Jon Ashburnd43f9b62014-10-14 19:15:22 -0600812}
813
Jon Ashburnfce93d92015-05-12 17:26:48 -0600814static void* VKAPI loader_gpa_instance_internal(VkInstance inst, const char * pName)
815{
816 // inst is not wrapped
817 if (inst == VK_NULL_HANDLE) {
818 return NULL;
819 }
820 VkLayerInstanceDispatchTable* disp_table = * (VkLayerInstanceDispatchTable **) inst;
821 void *addr;
822
823 if (disp_table == NULL)
824 return NULL;
825
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600826// addr = debug_report_instance_gpa((struct loader_instance *) inst, pName);
827// if (addr) {
828// return addr;
829// }
830
Jon Ashburnfce93d92015-05-12 17:26:48 -0600831 addr = loader_lookup_instance_dispatch_table(disp_table, pName);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600832 if (addr) {
Jon Ashburnfce93d92015-05-12 17:26:48 -0600833 return addr;
Jon Ashburne18431b2015-04-13 18:10:06 -0600834 }
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600835
836 if (disp_table->GetInstanceProcAddr == NULL) {
837 return NULL;
838 }
839 return disp_table->GetInstanceProcAddr(inst, pName);
Jon Ashburne18431b2015-04-13 18:10:06 -0600840}
841
Jon Ashburnda7c20d2015-05-01 18:00:33 -0600842struct loader_icd * loader_get_icd(const VkBaseLayerObject *gpu, uint32_t *gpu_index)
Jon Ashburnb55278a2014-10-17 15:09:07 -0600843{
Jon Ashburn630e44f2015-04-08 21:33:34 -0600844 /*
845 * NOTE: at this time icd->gpus is pointing to wrapped GPUs, but no where else
846 * are wrapped gpus used. Should go away. The incoming gpu is NOT wrapped so
847 * need to test it against the wrapped GPU's base object.
848 */
Jon Ashburndc67ef52015-01-29 16:44:24 -0700849 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
850 for (struct loader_icd *icd = inst->icds; icd; icd = icd->next) {
851 for (uint32_t i = 0; i < icd->gpu_count; i++)
Mike Stroyan230e6252015-04-17 12:36:38 -0600852 if ((icd->gpus + i) == gpu || (void*)(icd->gpus +i)->baseObject == gpu) {
Jon Ashburndc67ef52015-01-29 16:44:24 -0700853 *gpu_index = i;
854 return icd;
855 }
856 }
Jon Ashburnb55278a2014-10-17 15:09:07 -0600857 }
858 return NULL;
859}
860
Mark Lobodzinskie2d07a52015-01-29 08:55:56 -0600861static bool loader_layers_activated(const struct loader_icd *icd, const uint32_t gpu_index)
Jon Ashburnb55278a2014-10-17 15:09:07 -0600862{
Jon Ashburn183dfd02014-10-22 18:13:16 -0600863 if (icd->layer_count[gpu_index])
864 return true;
865 else
866 return false;
Jon Ashburnb55278a2014-10-17 15:09:07 -0600867}
868
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600869static loader_platform_dl_handle loader_add_layer_lib(
Jon Ashburn9a9de1f2015-05-27 13:19:22 -0600870 const char *chain_type,
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600871 struct loader_extension_property *ext_prop)
Jon Ashburnd43f9b62014-10-14 19:15:22 -0600872{
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600873 struct loader_lib_info *new_layer_lib_list, *my_lib;
874
875 /* Only loader layer libraries here */
876 if (ext_prop->origin != VK_EXTENSION_ORIGIN_LAYER) {
877 return NULL;
878 }
879
880 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) {
881 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, ext_prop->lib_name) == 0) {
882 /* Have already loaded this library, just increment ref count */
883 loader.loaded_layer_lib_list[i].ref_count++;
Jon Ashburnf0615e22015-05-25 14:11:37 -0600884 loader_log(VK_DBG_REPORT_INFO_BIT, 0,
Jon Ashburn9a9de1f2015-05-27 13:19:22 -0600885 "Inserting %s layer %s from library %s", chain_type,
Jon Ashburnf0615e22015-05-25 14:11:37 -0600886 ext_prop->info.name, ext_prop->lib_name);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600887 return loader.loaded_layer_lib_list[i].lib_handle;
888 }
889 }
890
891 /* Haven't seen this library so load it */
892 new_layer_lib_list = realloc(loader.loaded_layer_lib_list,
893 (loader.loaded_layer_lib_count + 1) * sizeof(struct loader_lib_info));
894 if (!new_layer_lib_list) {
895 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "loader: malloc failed");
896 return NULL;
897 }
898
899 my_lib = &new_layer_lib_list[loader.loaded_layer_lib_count];
900
901 /* NOTE: We require that the extension property to be immutable */
902 my_lib->lib_name = ext_prop->lib_name;
903 my_lib->ref_count = 0;
904 my_lib->lib_handle = NULL;
905
906 if ((my_lib->lib_handle = loader_platform_open_library(my_lib->lib_name)) == NULL) {
907 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
908 loader_platform_open_library_error(my_lib->lib_name));
909 return NULL;
910 } else {
911 loader_log(VK_DBG_REPORT_INFO_BIT, 0,
Jon Ashburn9a9de1f2015-05-27 13:19:22 -0600912 "Inserting %s layer %s from library %s", chain_type,
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600913 ext_prop->info.name, ext_prop->lib_name);
914 }
915 loader.loaded_layer_lib_count++;
916 loader.loaded_layer_lib_list = new_layer_lib_list;
917 my_lib->ref_count++;
918
919 return my_lib->lib_handle;
920}
921
922static void loader_remove_layer_lib(
923 struct loader_instance *inst,
924 struct loader_extension_property *ext_prop)
925{
926 uint32_t idx;
927 struct loader_lib_info *new_layer_lib_list, *my_lib;
928
929 /* Only loader layer libraries here */
930 if (ext_prop->origin != VK_EXTENSION_ORIGIN_LAYER) {
Jon Ashburn183dfd02014-10-22 18:13:16 -0600931 return;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600932 }
Jon Ashburn815bddd2014-10-16 15:48:50 -0600933
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600934 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) {
935 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, ext_prop->lib_name) == 0) {
936 /* found matching library */
937 idx = i;
938 my_lib = &loader.loaded_layer_lib_list[i];
939 break;
Jon Ashburnd43f9b62014-10-14 19:15:22 -0600940 }
Jon Ashburnd43f9b62014-10-14 19:15:22 -0600941 }
Jon Ashburnd43f9b62014-10-14 19:15:22 -0600942
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600943 my_lib->ref_count--;
944 inst->layer_count--;
945 if (my_lib->ref_count > 0) {
Jon Ashburnfce93d92015-05-12 17:26:48 -0600946 return;
Courtney Goeltzenleuchter0199e952015-02-27 15:19:33 -0700947 }
Jon Ashburn4d3b7522015-04-14 14:14:48 -0600948
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600949 /* Need to remove unused library from list */
950 new_layer_lib_list = malloc((loader.loaded_layer_lib_count - 1) * sizeof(struct loader_lib_info));
951 if (!new_layer_lib_list) {
952 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "loader: malloc failed");
953 return;
954 }
955
956 if (idx > 0) {
957 /* Copy records before idx */
958 memcpy(new_layer_lib_list, &loader.loaded_layer_lib_list[0],
959 sizeof(struct loader_lib_info) * idx);
960 }
961 if (idx < (loader.loaded_layer_lib_count - 1)) {
962 /* Copy records after idx */
963 memcpy(&new_layer_lib_list[idx], &loader.loaded_layer_lib_list[idx+1],
964 sizeof(struct loader_lib_info) * (loader.loaded_layer_lib_count - idx - 1));
965 }
966 free(loader.loaded_layer_lib_list);
967 loader.loaded_layer_lib_count--;
968 loader.loaded_layer_lib_list = new_layer_lib_list;
Jon Ashburnead95c52014-11-18 09:06:04 -0700969}
970
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600971static void loader_add_layer_env(
972 struct loader_extension_list *ext_list,
973 const struct loader_extension_list *search_list)
Jon Ashburnd43f9b62014-10-14 19:15:22 -0600974{
Ian Elliott225188f2015-02-17 10:33:47 -0700975 char *layerEnv;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600976 uint32_t len;
Jon Ashburnb4d00532014-10-22 21:15:26 -0600977 char *p, *pOrig, *next, *name;
Jon Ashburnd43f9b62014-10-14 19:15:22 -0600978
Ian Elliott225188f2015-02-17 10:33:47 -0700979#if defined(WIN32)
980 layerEnv = loader_get_registry_and_env(LAYER_NAMES_ENV,
981 LAYER_NAMES_REGISTRY_VALUE);
982#else // WIN32
983 layerEnv = getenv(LAYER_NAMES_ENV);
984#endif // WIN32
985 if (layerEnv == NULL) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600986 return;
Ian Elliott225188f2015-02-17 10:33:47 -0700987 }
Jon Ashburn183dfd02014-10-22 18:13:16 -0600988 p = malloc(strlen(layerEnv) + 1);
Ian Elliott225188f2015-02-17 10:33:47 -0700989 if (p == NULL) {
990#if defined(WIN32)
991 free(layerEnv);
992#endif // WIN32
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600993 return;
Ian Elliott225188f2015-02-17 10:33:47 -0700994 }
Jon Ashburn183dfd02014-10-22 18:13:16 -0600995 strcpy(p, layerEnv);
Ian Elliott225188f2015-02-17 10:33:47 -0700996#if defined(WIN32)
997 free(layerEnv);
998#endif // WIN32
Jon Ashburnb4d00532014-10-22 21:15:26 -0600999 pOrig = p;
Jon Ashburnd43f9b62014-10-14 19:15:22 -06001000
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001001 while (p && *p ) {
Jon Ashburn4d3b7522015-04-14 14:14:48 -06001002 //memset(&lib_name[0], 0, sizeof(const char *) * MAX_LAYER_LIBRARIES);
Ian Elliott81ac44c2015-01-13 17:52:38 -07001003 next = strchr(p, PATH_SEPERATOR);
Jon Ashburnd43f9b62014-10-14 19:15:22 -06001004 if (next == NULL) {
Ian Elliott64f74a82015-02-04 12:06:46 -07001005 len = (uint32_t) strlen(p);
Jon Ashburnd43f9b62014-10-14 19:15:22 -06001006 next = p + len;
Courtney Goeltzenleuchter0199e952015-02-27 15:19:33 -07001007 } else {
Ian Elliott64f74a82015-02-04 12:06:46 -07001008 len = (uint32_t) (next - p);
Jon Ashburnd43f9b62014-10-14 19:15:22 -06001009 *(char *) next = '\0';
1010 next++;
1011 }
Jon Ashburn183dfd02014-10-22 18:13:16 -06001012 name = basename(p);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001013 loader_search_ext_list_for_name(name, search_list, ext_list);
Jon Ashburnd43f9b62014-10-14 19:15:22 -06001014 p = next;
Courtney Goeltzenleuchter0199e952015-02-27 15:19:33 -07001015 }
Jon Ashburnd43f9b62014-10-14 19:15:22 -06001016
Jon Ashburnb4d00532014-10-22 21:15:26 -06001017 free(pOrig);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001018 return;
Jon Ashburnd43f9b62014-10-14 19:15:22 -06001019}
1020
Jon Ashburn183dfd02014-10-22 18:13:16 -06001021
Jon Ashburnfce93d92015-05-12 17:26:48 -06001022//TODO static void loader_deactivate_device_layer(device)
1023
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001024static void loader_deactivate_instance_layers(struct loader_instance *instance)
Jon Ashburn183dfd02014-10-22 18:13:16 -06001025{
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001026 if (!instance->layer_count) {
1027 return;
1028 }
Jon Ashburn183dfd02014-10-22 18:13:16 -06001029
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001030 /* Create instance chain of enabled layers */
1031 for (uint32_t i = 0; i < instance->enabled_instance_extensions.count; i++) {
1032 struct loader_extension_property *ext_prop = &instance->enabled_instance_extensions.list[i];
1033
1034 if (ext_prop->origin == VK_EXTENSION_ORIGIN_ICD) {
1035 continue;
Jon Ashburn183dfd02014-10-22 18:13:16 -06001036 }
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001037
1038 loader_remove_layer_lib(instance, ext_prop);
1039
1040 instance->layer_count--;
Jon Ashburn183dfd02014-10-22 18:13:16 -06001041 }
Jon Ashburnfce93d92015-05-12 17:26:48 -06001042
1043 free(instance->wrappedInstance);
Jon Ashburn183dfd02014-10-22 18:13:16 -06001044}
1045
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001046void loader_enable_instance_layers(struct loader_instance *inst)
1047{
1048 if (inst == NULL)
1049 return;
1050
1051 /* Add any layers specified in the environment first */
1052 loader_add_layer_env(&inst->enabled_instance_extensions, &loader.global_extensions);
1053
1054 /* Add layers / extensions specified by the application */
1055 loader_add_vk_ext_to_ext_list(
1056 &inst->enabled_instance_extensions,
1057 inst->app_extension_count,
1058 inst->app_extension_props,
1059 &loader.global_extensions);
1060}
1061
Jon Ashburnfce93d92015-05-12 17:26:48 -06001062uint32_t loader_activate_instance_layers(struct loader_instance *inst)
1063{
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001064 uint32_t layer_idx;
1065
Jon Ashburnfce93d92015-05-12 17:26:48 -06001066 if (inst == NULL)
1067 return 0;
1068
1069 // NOTE inst is unwrapped at this point in time
1070 VkObject baseObj = (VkObject) inst;
1071 VkObject nextObj = (VkObject) inst;
1072 VkBaseLayerObject *nextInstObj;
1073 PFN_vkGetInstanceProcAddr nextGPA = loader_gpa_instance_internal;
1074
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001075 /*
1076 * Figure out how many actual layers will need to be wrapped.
1077 */
1078 inst->layer_count = 0;
1079 for (uint32_t i = 0; i < inst->enabled_instance_extensions.count; i++) {
1080 struct loader_extension_property *ext_prop = &inst->enabled_instance_extensions.list[i];
1081 if (ext_prop->origin == VK_EXTENSION_ORIGIN_LAYER) {
1082 inst->layer_count++;
1083 }
1084 }
Jon Ashburnfce93d92015-05-12 17:26:48 -06001085
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001086 if (!inst->layer_count) {
Jon Ashburnfce93d92015-05-12 17:26:48 -06001087 return 0;
1088 }
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001089
1090 inst->wrappedInstance = malloc(sizeof(VkBaseLayerObject)
1091 * inst->layer_count);
1092 if (!inst->wrappedInstance) {
1093 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to malloc Instance objects for layer");
1094 return 0;
1095 }
1096
1097 /* Create instance chain of enabled layers */
1098 layer_idx = inst->layer_count - 1;
1099 for (int32_t i = inst->enabled_instance_extensions.count - 1; i >= 0; i--) {
1100 struct loader_extension_property *ext_prop = &inst->enabled_instance_extensions.list[i];
1101 loader_platform_dl_handle lib_handle;
1102
1103 /*
1104 * TODO: Need to figure out how to hook in extensions implemented
1105 * within the loader.
1106 * What GetProcAddr do we use?
1107 * How do we make the loader call first in the chain? It may not be first
1108 * in the list. Does it have to be first?
1109 * How does the chain for DbgCreateMsgCallback get made?
1110 * Do we need to add the function pointer to the VkLayerInstanceDispatchTable?
1111 * Seems like we will.
1112 * What happens with more than one loader implemented extension?
1113 * Issue: Process of building instance chain requires that we call GetInstanceProcAddr
1114 * on the various extension components. However, if we are asking for an extension
1115 * entry point we won't get it because we haven't enabled the extension yet.
1116 * Must not call GPA on extensions at this time.
1117 */
1118 if (ext_prop->origin != VK_EXTENSION_ORIGIN_LAYER) {
1119 continue;
1120 }
1121
1122 nextInstObj = (inst->wrappedInstance + layer_idx);
Jon Ashburnfce93d92015-05-12 17:26:48 -06001123 nextInstObj->pGPA = nextGPA;
1124 nextInstObj->baseObject = baseObj;
1125 nextInstObj->nextObject = nextObj;
1126 nextObj = (VkObject) nextInstObj;
1127
1128 char funcStr[256];
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001129 snprintf(funcStr, 256, "%sGetInstanceProcAddr", ext_prop->info.name);
Jon Ashburn9a9de1f2015-05-27 13:19:22 -06001130 lib_handle = loader_add_layer_lib("instance", ext_prop);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001131 if ((nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, funcStr)) == NULL)
1132 nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetInstanceProcAddr");
Jon Ashburnfce93d92015-05-12 17:26:48 -06001133 if (!nextGPA) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001134 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to find vkGetInstanceProcAddr in layer %s", ext_prop->lib_name);
Jon Ashburnfce93d92015-05-12 17:26:48 -06001135 continue;
1136 }
1137
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001138 layer_idx--;
Jon Ashburnfce93d92015-05-12 17:26:48 -06001139 }
1140
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001141 loader_init_instance_core_dispatch_table(inst->disp, nextGPA, (VkInstance) nextObj);
1142
Jon Ashburnfce93d92015-05-12 17:26:48 -06001143 return inst->layer_count;
1144}
1145
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001146void loader_enable_device_layers(struct loader_icd *icd, uint32_t gpu_index)
1147{
1148 if (icd == NULL)
1149 return;
1150
1151 /* Add any layers specified in the environment first */
1152 loader_add_layer_env(&icd->enabled_device_extensions[gpu_index], &loader.global_extensions);
1153
1154 /* Add layers / extensions specified by the application */
1155 loader_add_vk_ext_to_ext_list(
1156 &icd->enabled_device_extensions[gpu_index],
1157 icd->app_extension_count[gpu_index],
1158 icd->app_extension_props[gpu_index],
1159 &loader.global_extensions);
1160}
1161
1162extern uint32_t loader_activate_device_layers(
1163 VkDevice device,
1164 struct loader_icd *icd,
1165 uint32_t gpu_index,
1166 uint32_t ext_count,
1167 const VkExtensionProperties *ext_props)
Jon Ashburn183dfd02014-10-22 18:13:16 -06001168{
Mark Lobodzinskie2d07a52015-01-29 08:55:56 -06001169 uint32_t count;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001170 uint32_t layer_idx;
1171
Jon Ashburn183dfd02014-10-22 18:13:16 -06001172 if (!icd)
1173 return 0;
Jon Ashburn07b309a2015-04-15 11:31:12 -06001174 assert(gpu_index < MAX_GPUS_FOR_LAYER);
Jon Ashburn183dfd02014-10-22 18:13:16 -06001175
1176 /* activate any layer libraries */
1177 if (!loader_layers_activated(icd, gpu_index)) {
Jon Ashburn2666e2f2015-05-15 15:09:35 -06001178 VkObject nextObj = (VkObject) device;
1179 VkObject baseObj = nextObj;
1180 VkBaseLayerObject *nextGpuObj;
Jon Ashburneedbb5e2015-05-22 09:19:49 -06001181 PFN_vkGetDeviceProcAddr nextGPA = icd->GetDeviceProcAddr;
Jon Ashburn183dfd02014-10-22 18:13:16 -06001182
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001183 count = 0;
1184 for (uint32_t i = 0; i < icd->enabled_device_extensions[gpu_index].count; i++) {
1185 struct loader_extension_property *ext_prop = &icd->enabled_device_extensions[gpu_index].list[i];
1186 if (ext_prop->origin == VK_EXTENSION_ORIGIN_LAYER) {
1187 count++;
1188 }
1189 }
Jon Ashburn183dfd02014-10-22 18:13:16 -06001190 if (!count)
1191 return 0;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001192
1193 icd->layer_count[gpu_index] = count;
Jon Ashburn183dfd02014-10-22 18:13:16 -06001194
Jon Ashburn301c5f02015-04-06 10:58:22 -06001195 icd->wrappedGpus[gpu_index] = malloc(sizeof(VkBaseLayerObject) * icd->layer_count[gpu_index]);
Jon Ashburnfce93d92015-05-12 17:26:48 -06001196 if (! icd->wrappedGpus[gpu_index]) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001197 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to malloc Gpu objects for layer");
Jon Ashburnfce93d92015-05-12 17:26:48 -06001198 return 0;
1199 }
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001200 layer_idx = count - 1;
Mark Lobodzinskie2d07a52015-01-29 08:55:56 -06001201 for (int32_t i = icd->layer_count[gpu_index] - 1; i >= 0; i--) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001202 struct loader_extension_property *ext_prop = &icd->enabled_device_extensions[gpu_index].list[i];
1203 loader_platform_dl_handle lib_handle;
1204
1205 if (ext_prop->origin != VK_EXTENSION_ORIGIN_LAYER) {
1206 continue;
1207 }
1208
Jon Ashburnb4d00532014-10-22 21:15:26 -06001209 nextGpuObj = (icd->wrappedGpus[gpu_index] + i);
Jon Ashburn183dfd02014-10-22 18:13:16 -06001210 nextGpuObj->pGPA = nextGPA;
Jon Ashburn2666e2f2015-05-15 15:09:35 -06001211 nextGpuObj->baseObject = baseObj;
1212 nextGpuObj->nextObject = nextObj;
1213 nextObj = (VkObject) nextGpuObj;
Jon Ashburn183dfd02014-10-22 18:13:16 -06001214
Jon Ashburn8d8dad02014-12-01 14:22:40 -07001215 char funcStr[256];
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001216 snprintf(funcStr, 256, "%sGetDeviceProcAddr", ext_prop->info.name);
Jon Ashburn9a9de1f2015-05-27 13:19:22 -06001217 lib_handle = loader_add_layer_lib("device", ext_prop);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001218 if ((nextGPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, funcStr)) == NULL)
1219 nextGPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetDeviceProcAddr");
Jon Ashburn183dfd02014-10-22 18:13:16 -06001220 if (!nextGPA) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001221 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to find vkGetDeviceProcAddr in layer %s", ext_prop->info.name);
Jon Ashburn183dfd02014-10-22 18:13:16 -06001222 continue;
1223 }
1224
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001225 layer_idx--;
1226 }
Jon Ashburn183dfd02014-10-22 18:13:16 -06001227
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001228 loader_init_device_dispatch_table(icd->loader_dispatch + gpu_index, nextGPA, (VkPhysicalDevice) nextObj);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001229 } else {
1230 // TODO: Check that active layers match requested?
Jon Ashburn183dfd02014-10-22 18:13:16 -06001231 }
1232 return icd->layer_count[gpu_index];
1233}
Jon Ashburnd43f9b62014-10-14 19:15:22 -06001234
Jon Ashburnfce93d92015-05-12 17:26:48 -06001235VkResult loader_CreateInstance(
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001236 const VkInstanceCreateInfo* pCreateInfo,
1237 VkInstance* pInstance)
Jon Ashburn349508d2015-01-26 14:51:40 -07001238{
Jon Ashburna179dcf2015-05-21 17:42:17 -06001239 struct loader_instance *ptr_instance = *(struct loader_instance **) pInstance;
Jon Ashburn3336df82015-01-29 15:45:51 -07001240 struct loader_scanned_icds *scanned_icds;
1241 struct loader_icd *icd;
Jon Ashburnfce93d92015-05-12 17:26:48 -06001242 VkResult res;
Jon Ashburn349508d2015-01-26 14:51:40 -07001243
Jon Ashburn3336df82015-01-29 15:45:51 -07001244 scanned_icds = loader.scanned_icd_list;
1245 while (scanned_icds) {
1246 icd = loader_icd_add(ptr_instance, scanned_icds);
1247 if (icd) {
Jon Ashburn29669a42015-04-04 14:52:07 -06001248 res = scanned_icds->CreateInstance(pCreateInfo,
Jon Ashburn0dd356d2015-05-14 12:43:38 -06001249 &(icd->instance));
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001250 if (res != VK_SUCCESS)
Jon Ashburn3336df82015-01-29 15:45:51 -07001251 {
1252 ptr_instance->icds = ptr_instance->icds->next;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001253 loader_icd_destroy(ptr_instance, icd);
Jon Ashburn0dd356d2015-05-14 12:43:38 -06001254 icd->instance = VK_NULL_HANDLE;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001255 loader_log(VK_DBG_REPORT_WARN_BIT, 0,
Jon Ashburn3336df82015-01-29 15:45:51 -07001256 "ICD ignored: failed to CreateInstance on device");
Jon Ashburn0dd356d2015-05-14 12:43:38 -06001257 } else
1258 {
1259 loader_icd_init_entrys(icd, scanned_icds);
Jon Ashburn3336df82015-01-29 15:45:51 -07001260 }
1261 }
1262 scanned_icds = scanned_icds->next;
1263 }
Jon Ashburn349508d2015-01-26 14:51:40 -07001264
Ian Elliott617fdec2015-02-05 15:19:15 -07001265 if (ptr_instance->icds == NULL) {
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001266 return VK_ERROR_INCOMPATIBLE_DRIVER;
Ian Elliott617fdec2015-02-05 15:19:15 -07001267 }
Jon Ashburn3336df82015-01-29 15:45:51 -07001268
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001269 return res;
Jon Ashburn349508d2015-01-26 14:51:40 -07001270}
1271
Jon Ashburnfce93d92015-05-12 17:26:48 -06001272VkResult loader_DestroyInstance(
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -06001273 VkInstance instance)
Jon Ashburn349508d2015-01-26 14:51:40 -07001274{
1275 struct loader_instance *ptr_instance = (struct loader_instance *) instance;
Jon Ashburn0dd356d2015-05-14 12:43:38 -06001276 struct loader_icd *icds = ptr_instance->icds;
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -06001277 VkResult res;
Jon Ashburn349508d2015-01-26 14:51:40 -07001278
1279 // Remove this instance from the list of instances:
1280 struct loader_instance *prev = NULL;
1281 struct loader_instance *next = loader.instances;
1282 while (next != NULL) {
1283 if (next == ptr_instance) {
1284 // Remove this instance from the list:
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001285 free(ptr_instance->app_extension_props);
Jon Ashburn349508d2015-01-26 14:51:40 -07001286 if (prev)
1287 prev->next = next->next;
Jon Ashburn2cabd252015-02-03 09:26:59 -07001288 else
1289 loader.instances = next->next;
Jon Ashburn349508d2015-01-26 14:51:40 -07001290 break;
1291 }
1292 prev = next;
1293 next = next->next;
1294 }
1295 if (next == NULL) {
1296 // This must be an invalid instance handle or empty list
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001297 return VK_ERROR_INVALID_HANDLE;
Jon Ashburn349508d2015-01-26 14:51:40 -07001298 }
1299
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001300 loader_deactivate_instance_layers(ptr_instance);
1301 loader_destroy_ext_list(&ptr_instance->enabled_instance_extensions);
Jon Ashburn349508d2015-01-26 14:51:40 -07001302
Jon Ashburn0dd356d2015-05-14 12:43:38 -06001303 while (icds) {
1304 if (icds->instance) {
1305 res = icds->DestroyInstance(icds->instance);
Tony Barbour22a30862015-04-22 09:02:32 -06001306 if (res != VK_SUCCESS)
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001307 loader_log(VK_DBG_REPORT_WARN_BIT, 0,
Tony Barbour22a30862015-04-22 09:02:32 -06001308 "ICD ignored: failed to DestroyInstance on device");
1309 }
Jon Ashburn0dd356d2015-05-14 12:43:38 -06001310 icds->instance = VK_NULL_HANDLE;
1311 icds = icds->next;
Jon Ashburn3336df82015-01-29 15:45:51 -07001312 }
1313
Jon Ashburn349508d2015-01-26 14:51:40 -07001314 free(ptr_instance);
1315
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001316 return VK_SUCCESS;
Jon Ashburn349508d2015-01-26 14:51:40 -07001317}
1318
Jon Ashburnfce93d92015-05-12 17:26:48 -06001319VkResult loader_EnumeratePhysicalDevices(
Courtney Goeltzenleuchter9f530cb2015-04-20 12:48:54 -06001320 VkInstance instance,
1321 uint32_t* pPhysicalDeviceCount,
1322 VkPhysicalDevice* pPhysicalDevices)
Jon Ashburn349508d2015-01-26 14:51:40 -07001323{
Jon Ashburnb048a9b2015-01-28 19:57:09 -07001324 struct loader_instance *ptr_instance = (struct loader_instance *) instance;
1325 struct loader_icd *icd;
Jon Ashburn07b309a2015-04-15 11:31:12 -06001326 uint32_t n, count = 0;
Tony Barbour22a30862015-04-22 09:02:32 -06001327 VkResult res = VK_ERROR_UNKNOWN;
Jon Ashburnb048a9b2015-01-28 19:57:09 -07001328
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001329 //in spirit of VK don't error check on the instance parameter
Jon Ashburnb048a9b2015-01-28 19:57:09 -07001330 icd = ptr_instance->icds;
Jon Ashburn07b309a2015-04-15 11:31:12 -06001331 if (pPhysicalDevices == NULL) {
1332 while (icd) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001333 res = icd->EnumeratePhysicalDevices(icd->instance, &n, NULL);
Jon Ashburn07b309a2015-04-15 11:31:12 -06001334 if (res != VK_SUCCESS)
1335 return res;
1336 icd->gpu_count = n;
1337 count += n;
1338 icd = icd->next;
Jon Ashburnb048a9b2015-01-28 19:57:09 -07001339 }
1340
Jon Ashburn07b309a2015-04-15 11:31:12 -06001341 ptr_instance->total_gpu_count = count;
Courtney Goeltzenleuchterba7133b2015-02-10 18:40:14 -07001342
Jon Ashburn07b309a2015-04-15 11:31:12 -06001343 } else
1344 {
Tony Barbour8205d902015-04-16 15:59:00 -06001345 VkPhysicalDevice* gpus;
Jon Ashburn07b309a2015-04-15 11:31:12 -06001346 if (*pPhysicalDeviceCount < ptr_instance->total_gpu_count)
1347 return VK_ERROR_INVALID_VALUE;
Tony Barbour8205d902015-04-16 15:59:00 -06001348 gpus = malloc( sizeof(VkPhysicalDevice) * *pPhysicalDeviceCount);
Jon Ashburn07b309a2015-04-15 11:31:12 -06001349 if (!gpus)
Tony Barbour8205d902015-04-16 15:59:00 -06001350 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburn07b309a2015-04-15 11:31:12 -06001351 while (icd) {
1352 VkBaseLayerObject * wrapped_gpus;
Jon Ashburn1245cec2015-05-18 13:20:15 -06001353 PFN_vkGetDeviceProcAddr get_proc_addr = icd->GetDeviceProcAddr;
Jon Ashburn07b309a2015-04-15 11:31:12 -06001354
Courtney Goeltzenleuchter9f530cb2015-04-20 12:48:54 -06001355 n = *pPhysicalDeviceCount;
Jon Ashburn0dd356d2015-05-14 12:43:38 -06001356 res = icd->EnumeratePhysicalDevices(
1357 icd->instance,
Jon Ashburn07b309a2015-04-15 11:31:12 -06001358 &n,
1359 gpus);
1360 if (res == VK_SUCCESS && n) {
1361 wrapped_gpus = (VkBaseLayerObject*) malloc(n *
1362 sizeof(VkBaseLayerObject));
1363 icd->gpus = wrapped_gpus;
1364 icd->gpu_count = n;
1365 icd->loader_dispatch = (VkLayerDispatchTable *) malloc(n *
1366 sizeof(VkLayerDispatchTable));
1367 for (unsigned int i = 0; i < n; i++) {
1368 (wrapped_gpus + i)->baseObject = gpus[i];
1369 (wrapped_gpus + i)->pGPA = get_proc_addr;
1370 (wrapped_gpus + i)->nextObject = gpus[i];
1371 memcpy(pPhysicalDevices + count, gpus, sizeof(*pPhysicalDevices));
Jon Ashburn9a9bb642015-05-04 16:27:53 -06001372 loader_init_device_dispatch_table(icd->loader_dispatch + i,
Jon Ashburn07b309a2015-04-15 11:31:12 -06001373 get_proc_addr, gpus[i]);
1374
Jon Ashburn2666e2f2015-05-15 15:09:35 -06001375 loader_init_dispatch(gpus[i], ptr_instance->disp);
Courtney Goeltzenleuchterba7133b2015-02-10 18:40:14 -07001376 }
1377
Jon Ashburn07b309a2015-04-15 11:31:12 -06001378 count += n;
1379
1380 if (count >= *pPhysicalDeviceCount) {
1381 break;
1382 }
Jon Ashburnb048a9b2015-01-28 19:57:09 -07001383 }
1384
Jon Ashburn07b309a2015-04-15 11:31:12 -06001385 icd = icd->next;
Jon Ashburnb048a9b2015-01-28 19:57:09 -07001386 }
Jon Ashburnb048a9b2015-01-28 19:57:09 -07001387 }
1388
Jon Ashburn07b309a2015-04-15 11:31:12 -06001389 *pPhysicalDeviceCount = count;
Jon Ashburnb048a9b2015-01-28 19:57:09 -07001390
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001391 return (count > 0) ? VK_SUCCESS : res;
Jon Ashburn349508d2015-01-26 14:51:40 -07001392}
1393
Jon Ashburn0dd356d2015-05-14 12:43:38 -06001394VkResult loader_GetPhysicalDeviceInfo(
1395 VkPhysicalDevice gpu,
1396 VkPhysicalDeviceInfoType infoType,
1397 size_t* pDataSize,
1398 void* pData)
1399{
1400 uint32_t gpu_index;
1401 struct loader_icd *icd = loader_get_icd((const VkBaseLayerObject *) gpu, &gpu_index);
1402 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
1403
1404 if (icd->GetPhysicalDeviceInfo)
1405 res = icd->GetPhysicalDeviceInfo(gpu, infoType, pDataSize, pData);
1406
1407 return res;
1408}
1409
Jon Ashburn2666e2f2015-05-15 15:09:35 -06001410VkResult loader_CreateDevice(
1411 VkPhysicalDevice gpu,
1412 const VkDeviceCreateInfo* pCreateInfo,
1413 VkDevice* pDevice)
1414{
1415 uint32_t gpu_index;
1416 struct loader_icd *icd = loader_get_icd((const VkBaseLayerObject *) gpu, &gpu_index);
1417 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
Jon Ashburn2666e2f2015-05-15 15:09:35 -06001418
Jon Ashburn2666e2f2015-05-15 15:09:35 -06001419 if (icd->CreateDevice) {
1420 res = icd->CreateDevice(gpu, pCreateInfo, pDevice);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001421 if (res != VK_SUCCESS) {
1422 return res;
Jon Ashburn2666e2f2015-05-15 15:09:35 -06001423 }
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001424
1425 VkLayerDispatchTable *dev_disp = icd->loader_dispatch + gpu_index;
1426 loader_init_dispatch(*pDevice, dev_disp);
1427
1428 icd->app_extension_count[gpu_index] = pCreateInfo->extensionCount;
1429 icd->app_extension_props[gpu_index] = (VkExtensionProperties *) malloc(sizeof(VkExtensionProperties) * pCreateInfo->extensionCount);
1430 if (icd->app_extension_props[gpu_index] == NULL && (icd->app_extension_count[gpu_index] > 0)) {
1431 return VK_ERROR_OUT_OF_HOST_MEMORY;
1432 }
1433
1434 /* Make local copy of extension list */
1435 if (icd->app_extension_count[gpu_index] > 0 && icd->app_extension_props[gpu_index] != NULL) {
1436 memcpy(icd->app_extension_props[gpu_index], pCreateInfo->pEnabledExtensions, sizeof(VkExtensionProperties) * pCreateInfo->extensionCount);
1437 }
1438
1439 // TODO: Add dependency check here.
1440
1441 loader_enable_device_layers(icd, gpu_index);
1442
Jon Ashburn2666e2f2015-05-15 15:09:35 -06001443 //TODO fix this extension parameters once support GetDeviceExtensionInfo()
1444 // don't know which instance we are on with this call
1445
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001446 loader_activate_device_layers(*pDevice, icd, gpu_index,
1447 icd->app_extension_count[gpu_index],
1448 icd->app_extension_props[gpu_index]);
Jon Ashburn2666e2f2015-05-15 15:09:35 -06001449 }
1450
1451 return res;
1452}
1453
Jon Ashburn53c16772015-05-06 10:15:07 -06001454LOADER_EXPORT void * VKAPI vkGetInstanceProcAddr(VkInstance instance, const char * pName)
1455{
Jon Ashburncedc15f2015-05-21 18:13:33 -06001456 if (instance == VK_NULL_HANDLE)
1457 return NULL;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001458
Jon Ashburncedc15f2015-05-21 18:13:33 -06001459 void *addr;
1460 /* get entrypoint addresses that are global (in the loader)*/
1461 addr = globalGetProcAddr(pName);
1462 if (addr)
1463 return addr;
Jon Ashburn53c16772015-05-06 10:15:07 -06001464
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001465 struct loader_instance *ptr_instance = (struct loader_instance *) instance;
1466
1467 addr = debug_report_instance_gpa(ptr_instance, pName);
1468 if (addr) {
1469 return addr;
1470 }
1471
Jon Ashburncedc15f2015-05-21 18:13:33 -06001472 /* return any extension global entrypoints */
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001473 addr = wsi_lunarg_GetInstanceProcAddr(instance, pName);
Jon Ashburncedc15f2015-05-21 18:13:33 -06001474 if (addr)
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001475 return (ptr_instance->wsi_lunarg_enabled) ? addr : NULL;
Jon Ashburncedc15f2015-05-21 18:13:33 -06001476
1477 /* return the instance dispatch table entrypoint for extensions */
1478 const VkLayerInstanceDispatchTable *disp_table = * (VkLayerInstanceDispatchTable **) instance;
1479 if (disp_table == NULL)
1480 return NULL;
1481
1482 addr = loader_lookup_instance_dispatch_table(disp_table, pName);
1483 if (addr)
1484 return addr;
Jon Ashburn53c16772015-05-06 10:15:07 -06001485
1486 return NULL;
1487}
1488
Jon Ashburn1245cec2015-05-18 13:20:15 -06001489LOADER_EXPORT void * VKAPI vkGetDeviceProcAddr(VkDevice device, const char * pName)
Jon Ashburn349508d2015-01-26 14:51:40 -07001490{
Jon Ashburn1245cec2015-05-18 13:20:15 -06001491 if (device == VK_NULL_HANDLE) {
1492 return NULL;
Ian Elliott81ac44c2015-01-13 17:52:38 -07001493 }
Jon Ashburne18431b2015-04-13 18:10:06 -06001494
Chia-I Wu38e5a2c2015-01-04 11:12:47 +08001495 void *addr;
Jon Ashburnd43f9b62014-10-14 19:15:22 -06001496
Jon Ashburne18431b2015-04-13 18:10:06 -06001497 /* for entrypoints that loader must handle (ie non-dispatchable or create object)
1498 make sure the loader entrypoint is returned */
1499 addr = loader_non_passthrough_gpa(pName);
Ian Elliottfdf00b62015-04-15 12:53:19 -06001500 if (addr) {
Jon Ashburne18431b2015-04-13 18:10:06 -06001501 return addr;
Ian Elliottfdf00b62015-04-15 12:53:19 -06001502 }
Jon Ashburne18431b2015-04-13 18:10:06 -06001503
Jon Ashburncedc15f2015-05-21 18:13:33 -06001504 /* return any extension device entrypoints the loader knows about */
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001505 addr = wsi_lunarg_GetDeviceProcAddr(device, pName);
1506 /* TODO: Where does device wsi_enabled go? */
Jon Ashburncedc15f2015-05-21 18:13:33 -06001507 if (addr)
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001508 return addr;
Jon Ashburncedc15f2015-05-21 18:13:33 -06001509
Jon Ashburne18431b2015-04-13 18:10:06 -06001510 /* return the dispatch table entrypoint for the fastest case */
Jon Ashburn1245cec2015-05-18 13:20:15 -06001511 const VkLayerDispatchTable *disp_table = * (VkLayerDispatchTable **) device;
Jon Ashburnd43f9b62014-10-14 19:15:22 -06001512 if (disp_table == NULL)
1513 return NULL;
1514
Jon Ashburnfce93d92015-05-12 17:26:48 -06001515 addr = loader_lookup_device_dispatch_table(disp_table, pName);
Chia-I Wu38e5a2c2015-01-04 11:12:47 +08001516 if (addr)
1517 return addr;
Jon Ashburnd43f9b62014-10-14 19:15:22 -06001518 else {
Jon Ashburn1245cec2015-05-18 13:20:15 -06001519 if (disp_table->GetDeviceProcAddr == NULL)
Jon Ashburnd43f9b62014-10-14 19:15:22 -06001520 return NULL;
Jon Ashburn1245cec2015-05-18 13:20:15 -06001521 return disp_table->GetDeviceProcAddr(device, pName);
Jon Ashburnd43f9b62014-10-14 19:15:22 -06001522 }
1523}
1524
Jon Ashburneb2728b2015-04-10 14:33:07 -06001525//TODO make sure createInstance enables extensions that are valid (loader does)
1526//TODO make sure CreateDevice enables extensions that are valid (left for layers/drivers to do)
1527
1528//TODO how is layer extension going to be enabled?
1529//Need to call createInstance on the layer or something
1530
Jon Ashburn9de95602015-05-18 15:28:32 -06001531LOADER_EXPORT VkResult VKAPI vkGetGlobalExtensionInfo(
Jon Ashburneb2728b2015-04-10 14:33:07 -06001532 VkExtensionInfoType infoType,
1533 uint32_t extensionIndex,
1534 size_t* pDataSize,
1535 void* pData)
Courtney Goeltzenleuchter0199e952015-02-27 15:19:33 -07001536{
Jon Ashburneb2728b2015-04-10 14:33:07 -06001537 uint32_t *count;
1538 /* Scan/discover all ICD libraries in a single-threaded manner */
1539 loader_platform_thread_once(&once_icd, loader_icd_scan);
Courtney Goeltzenleuchter0199e952015-02-27 15:19:33 -07001540
Jon Ashburneb2728b2015-04-10 14:33:07 -06001541 /* get layer libraries in a single-threaded manner */
1542 loader_platform_thread_once(&once_layer, layer_lib_scan);
Courtney Goeltzenleuchter0199e952015-02-27 15:19:33 -07001543
Jon Ashburneb2728b2015-04-10 14:33:07 -06001544 /* merge any duplicate extensions */
1545 loader_platform_thread_once(&once_exts, loader_coalesce_extensions);
1546
1547
1548 if (pDataSize == NULL)
1549 return VK_ERROR_INVALID_POINTER;
1550
1551 switch (infoType) {
1552 case VK_EXTENSION_INFO_TYPE_COUNT:
1553 *pDataSize = sizeof(uint32_t);
1554 if (pData == NULL)
1555 return VK_SUCCESS;
1556 count = (uint32_t *) pData;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001557 *count = loader.global_extensions.count;
Jon Ashburneb2728b2015-04-10 14:33:07 -06001558 break;
1559 case VK_EXTENSION_INFO_TYPE_PROPERTIES:
1560 *pDataSize = sizeof(VkExtensionProperties);
1561 if (pData == NULL)
1562 return VK_SUCCESS;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001563 if (extensionIndex >= loader.global_extensions.count)
Jon Ashburneb2728b2015-04-10 14:33:07 -06001564 return VK_ERROR_INVALID_VALUE;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001565 memcpy((VkExtensionProperties *) pData,
1566 &loader.global_extensions.list[extensionIndex],
1567 sizeof(VkExtensionProperties));
Jon Ashburneb2728b2015-04-10 14:33:07 -06001568 break;
1569 default:
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001570 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Invalid infoType in vkGetGlobalExtensionInfo");
Jon Ashburneb2728b2015-04-10 14:33:07 -06001571 return VK_ERROR_INVALID_VALUE;
1572 };
1573
1574 return VK_SUCCESS;
Courtney Goeltzenleuchter0199e952015-02-27 15:19:33 -07001575}
Jon Ashburn2666e2f2015-05-15 15:09:35 -06001576VkResult loader_GetPhysicalDeviceExtensionInfo(
1577 VkPhysicalDevice gpu,
1578 VkExtensionInfoType infoType,
1579 uint32_t extensionIndex,
1580 size_t* pDataSize,
1581 void* pData)
1582{
1583 uint32_t gpu_index;
1584 struct loader_icd *icd = loader_get_icd((const VkBaseLayerObject *) gpu, &gpu_index);
1585 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
Courtney Goeltzenleuchter0199e952015-02-27 15:19:33 -07001586
Jon Ashburn2666e2f2015-05-15 15:09:35 -06001587 if (icd->GetPhysicalDeviceExtensionInfo)
1588 res = icd->GetPhysicalDeviceExtensionInfo(gpu, infoType, extensionIndex,
1589 pDataSize, pData);
1590
1591 return res;
1592}
1593
Jon Ashburn2666e2f2015-05-15 15:09:35 -06001594VkResult loader_GetMultiDeviceCompatibility(
1595 VkPhysicalDevice gpu0,
1596 VkPhysicalDevice gpu1,
1597 VkPhysicalDeviceCompatibilityInfo* pInfo)
1598{
1599 uint32_t gpu_index;
1600 struct loader_icd *icd = loader_get_icd((const VkBaseLayerObject *) gpu0, &gpu_index);
1601 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
1602
1603 if (icd->GetMultiDeviceCompatibility)
1604 res = icd->GetMultiDeviceCompatibility(gpu0, gpu1, pInfo);
1605
1606 return res;
1607}