blob: b55ddcf86390450d0c8e1ead1c61925d865cccdd [file] [log] [blame]
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001/*
Courtney Goeltzenleuchterd8e229c2015-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 Wu701f3f62014-09-02 08:32:09 +080023 *
24 * Authors:
25 * Chia-I Wu <olv@lunarg.com>
Jon Ashburn01e2d662014-11-14 09:52:42 -070026 * Jon Ashburn <jon@lunarg.com>
Chia-I Wu701f3f62014-09-02 08:32:09 +080027 * Courtney Goeltzenleuchter <courtney@lunarg.com>
Ian Elliott5aa4ea22015-03-31 15:32:41 -060028 * Ian Elliott <ian@lunarg.com>
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080029 */
Jon Ashburn6b4d70c2014-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 Wu13a61a52014-08-04 11:18:20 +080037#include <sys/types.h>
Ian Elliott2d4ab1e2015-01-13 17:52:38 -070038#if defined(WIN32)
39#include "dirent_on_windows.h"
40#else // WIN32
Chia-I Wu13a61a52014-08-04 11:18:20 +080041#include <dirent.h>
Ian Elliott2d4ab1e2015-01-13 17:52:38 -070042#endif // WIN32
43#include "loader_platform.h"
Chia-I Wu19300602014-08-04 08:03:57 +080044#include "loader.h"
Jon Ashburn07daee72015-05-21 18:13:33 -060045#include "wsi_lunarg.h"
Jon Ashburn27cd5842015-05-12 17:26:48 -060046#include "gpa_helper.h"
47#include "table_ops.h"
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -060048#include "debug_report.h"
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -060049#include "vkIcd.h"
Ian Elliott655cad72015-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 Goeltzenleuchterf579fa62015-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 Goeltzenleuchterf579fa62015-06-10 17:39:03 -060061/* TODO: do we need to lock around access to linked lists and such? */
Jon Ashburn27cd5842015-05-12 17:26:48 -060062struct loader_struct loader = {0};
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080063
Jon Ashburn27cd5842015-05-12 17:26:48 -060064VkLayerInstanceDispatchTable instance_disp = {
65 .GetInstanceProcAddr = vkGetInstanceProcAddr,
Jon Ashburn27cd5842015-05-12 17:26:48 -060066 .CreateInstance = loader_CreateInstance,
67 .DestroyInstance = loader_DestroyInstance,
68 .EnumeratePhysicalDevices = loader_EnumeratePhysicalDevices,
Jon Ashburn95a77ba2015-05-15 15:09:35 -060069 .GetPhysicalDeviceInfo = loader_GetPhysicalDeviceInfo,
70 .CreateDevice = loader_CreateDevice,
Jon Ashburneceb13e2015-05-18 15:28:32 -060071 .GetGlobalExtensionInfo = vkGetGlobalExtensionInfo,
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -060072 .GetPhysicalDeviceExtensionInfo = vkGetPhysicalDeviceExtensionInfo,
Jon Ashburn95a77ba2015-05-15 15:09:35 -060073 .GetMultiDeviceCompatibility = loader_GetMultiDeviceCompatibility,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -060074 .GetDisplayInfoWSI = loader_GetDisplayInfoWSI,
75 .DbgCreateMsgCallback = loader_DbgCreateMsgCallback,
76 .DbgDestroyMsgCallback = loader_DbgDestroyMsgCallback,
Jon Ashburn27cd5842015-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 Elliott2d4ab1e2015-01-13 17:52:38 -070082
Ian Elliott4470a302015-02-17 10:33:47 -070083#if defined(WIN32)
Ian Elliott5aa4ea22015-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 Elliottf851ddf2015-04-28 15:57:32 -060091 VkResult rtn_value;
Ian Elliott5aa4ea22015-03-31 15:32:41 -060092 char *rtn_str = NULL;
Tony Barbour18f71552015-04-22 11:36:22 -060093 DWORD rtn_len = 0;
Ian Elliott5aa4ea22015-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 Elliottf851ddf2015-04-28 15:57:32 -0600109 (PVOID) rtn_str, (LPDWORD) &rtn_len);
Ian Elliott5aa4ea22015-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 Elliottf851ddf2015-04-28 15:57:32 -0600116 (PVOID) rtn_str, (LPDWORD) &rtn_len);
Ian Elliott5aa4ea22015-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 Elliott4470a302015-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 Elliott5aa4ea22015-03-31 15:32:41 -0600142 char *registry_str = NULL;
Tony Barbour18f71552015-04-22 11:36:22 -0600143 size_t registry_len = 0;
Ian Elliott4470a302015-02-17 10:33:47 -0700144 char *rtn_str = NULL;
145 size_t rtn_len;
146
Ian Elliott5aa4ea22015-03-31 15:32:41 -0600147 registry_str = loader_get_registry_string(HKEY_LOCAL_MACHINE,
Ian Elliott06ebd752015-04-09 18:07:15 -0600148 "Software\\Vulkan",
Ian Elliott5aa4ea22015-03-31 15:32:41 -0600149 registry_value);
Ian Elliottf851ddf2015-04-28 15:57:32 -0600150 registry_len = (registry_str) ? (DWORD) strlen(registry_str) : 0;
Ian Elliott4470a302015-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 Elliott5aa4ea22015-03-31 15:32:41 -0600163 if (registry_len == 0) {
Ian Elliott4470a302015-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 Elliott2de26bc2015-04-03 13:13:01 -0600176 if (registry_str) {
177 free(registry_str);
178 }
Ian Elliott4470a302015-02-17 10:33:47 -0700179
180 return(rtn_str);
181}
182#endif // WIN32
183
184
Courtney Goeltzenleuchterf579fa62015-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 Elliott42045842015-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 Ashburnae053e92015-04-24 14:10:50 -0700199#if defined(WIN32)
200 OutputDebugString(msg);
Jon Ashburn1de39402015-05-05 16:20:46 -0600201#endif
Courtney Goeltzenleuchterc80a5572015-04-13 14:10:06 -0600202 fputs(msg, stderr);
203 fputc('\n', stderr);
Jon Ashburn1de39402015-05-05 16:20:46 -0600204
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800205}
206
Courtney Goeltzenleuchterf579fa62015-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 Ashburn9fd4cc42015-04-10 14:33:07 -0600221{
222 uint32_t i;
223 for (i = 0; i < count; i++) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600224 if (!strcmp(exts[i].info.name, target_ext_name) && (!must_be_hosted || exts[i].hosted))
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600225 return true;
226 }
227 return false;
228}
229
Courtney Goeltzenleuchterf579fa62015-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 Ashburn9fd4cc42015-04-10 14:33:07 -0600235{
Courtney Goeltzenleuchterf579fa62015-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 Ashburn9fd4cc42015-04-10 14:33:07 -0600281 size_t siz = sizeof(count);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600282 struct loader_extension_property ext_props;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600283 VkResult res;
284
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600285 res = fp_get(VK_EXTENSION_INFO_TYPE_COUNT, 0, &siz, &count);
286 if (res != VK_SUCCESS) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600287 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Error getting global extension count from ICD");
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600288 return;
289 }
290 siz = sizeof(VkExtensionProperties);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600291 for (i = 0; i < count; i++) {
Courtney Goeltzenleuchterf579fa62015-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 Ashburn9fd4cc42015-04-10 14:33:07 -0600294 if (res == VK_SUCCESS) {
Courtney Goeltzenleuchterf579fa62015-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 Ashburn9fd4cc42015-04-10 14:33:07 -0600299 }
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600300 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600301
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600302 return;
303}
304
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600305static void get_physical_device_layer_extensions(
306 struct loader_instance *ptr_instance,
307 VkPhysicalDevice physical_device,
308 const uint32_t layer_index,
309 struct loader_extension_list *ext_list)
310{
311 uint32_t i, count;
312 size_t siz = sizeof(count);
313 VkResult res;
314 loader_platform_dl_handle lib_handle;
315 PFN_vkGetPhysicalDeviceExtensionInfo fp_get;
316 struct loader_extension_property ext_props;
317
318 if (!loader.scanned_layers[layer_index].physical_device_extensions_supported) {
319 return;
320 }
321
322 ext_props.origin = VK_EXTENSION_ORIGIN_LAYER;
323 ext_props.lib_name = loader.scanned_layers[layer_index].lib_name;
324 char funcStr[256];
325 snprintf(funcStr, 256, "%sGetPhysicalDeviceExtensionInfo", ext_props.info.name);
326 lib_handle = loader_add_layer_lib("device", &ext_props);
327 fp_get = (PFN_vkGetPhysicalDeviceExtensionInfo) loader_platform_get_proc_address(lib_handle, "vkGetPhysicalDeviceExtensionInfo");
328 if (fp_get) {
329 res = fp_get(physical_device, VK_EXTENSION_INFO_TYPE_COUNT, 0, &siz, &count);
330 if (res == VK_SUCCESS) {
331 siz = sizeof(VkExtensionProperties);
332 for (i = 0; i < count; i++) {
333 memset(&ext_props, 0, sizeof(ext_props));
334 res = fp_get(physical_device, VK_EXTENSION_INFO_TYPE_PROPERTIES, i, &siz, &ext_props.info);
335 if (res == VK_SUCCESS && (ext_props.info.sType == VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES)) {
336 ext_props.hosted = false;
337 ext_props.origin = VK_EXTENSION_ORIGIN_LAYER;
338 ext_props.lib_name = loader.scanned_layers[layer_index].lib_name;
339 loader_add_to_ext_list(ext_list, 1, &ext_props);
340 }
341 }
342 } else {
343 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Error getting physical device extension info count from Layer %s", ext_props.lib_name);
344 }
345 }
346
347 loader_remove_layer_lib(ptr_instance, &ext_props);
348 return;
349}
350
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600351static bool loader_init_ext_list(struct loader_extension_list *ext_info)
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600352{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600353 ext_info->capacity = 32 * sizeof(struct loader_extension_property);
354 ext_info->list = malloc(ext_info->capacity);
355 if (ext_info->list == NULL) {
356 return false;
357 }
358 memset(ext_info->list, 0, ext_info->capacity);
359 ext_info->count = 0;
360 return true;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600361}
362
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600363static void loader_destroy_ext_list(struct loader_extension_list *ext_info)
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600364{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600365 free(ext_info->list);
366 ext_info->count = 0;
367 ext_info->capacity = 0;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600368}
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600369
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600370static void loader_add_vk_ext_to_ext_list(
371 struct loader_extension_list *ext_list,
372 uint32_t prop_list_count,
373 const VkExtensionProperties *props,
374 const struct loader_extension_list *search_list)
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600375{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600376 struct loader_extension_property *ext_prop;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600377
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600378 for (uint32_t i = 0; i < prop_list_count; i++) {
379 // look for duplicates
380 if (has_vk_extension_property(&props[i], ext_list)) {
381 continue;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600382 }
383
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600384 ext_prop = get_extension_property_from_vkext(&props[i], search_list);
385 if (!ext_prop) {
386 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Unable to find extension %s", props[i].name);
387 continue;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600388 }
389
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600390 loader_add_to_ext_list(ext_list, 1, ext_prop);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600391 }
392}
393
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600394/*
395 * Append non-duplicate extension properties defined in prop_list
396 * to the given ext_info list
397 */
398void loader_add_to_ext_list(
399 struct loader_extension_list *ext_list,
400 uint32_t prop_list_count,
401 const struct loader_extension_property *props)
402{
403 uint32_t i;
404 struct loader_extension_property *cur_ext;
405
406 if (ext_list->list == NULL || ext_list->capacity == 0) {
407 loader_init_ext_list(ext_list);
408 }
409
410 if (ext_list->list == NULL)
411 return;
412
413 for (i = 0; i < prop_list_count; i++) {
414 cur_ext = (struct loader_extension_property *) &props[i];
415
416 // look for duplicates
417 if (has_vk_extension_property(&cur_ext->info, ext_list)) {
418 continue;
419 }
420
421 // add to list at end
422 // check for enough capacity
423 if (ext_list->count * sizeof(struct loader_extension_property)
424 >= ext_list->capacity) {
425 // double capacity
426 ext_list->capacity *= 2;
427 ext_list->list = realloc(ext_list->list, ext_list->capacity);
428 }
429 memcpy(&ext_list->list[ext_list->count], cur_ext, sizeof(struct loader_extension_property));
430 ext_list->count++;
431 }
432}
433
434/*
435 * Search the search_list for any extension with
436 * a name that matches the given ext_name.
437 * Add all matching extensions to the found_list
438 * Do not add if found VkExtensionProperties is already
439 * on the found_list
440 */
441static void loader_search_ext_list_for_name(
442 const char *ext_name,
443 const struct loader_extension_list *search_list,
444 struct loader_extension_list *found_list)
445{
446 for (uint32_t i = 0; i < search_list->count; i++) {
447 struct loader_extension_property *ext_prop = &search_list->list[i];
448 if (0 == strcmp(ext_prop->info.name, ext_name)) {
449 /* Found an extension with the same name, add to found_list */
450 loader_add_to_ext_list(found_list, 1, &search_list->list[i]);
451 }
452 }
453}
454
455bool loader_is_extension_scanned(const VkExtensionProperties *ext_prop)
Jon Ashburnfc2e38c2015-04-14 09:15:32 -0600456{
457 uint32_t i;
458
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600459 for (i = 0; i < loader.global_extensions.count; i++) {
460 if (compare_vk_extension_properties(&loader.global_extensions.list[i].info, ext_prop))
Jon Ashburnfc2e38c2015-04-14 09:15:32 -0600461 return true;
462 }
463 return false;
464}
465
Jon Ashburn27cd5842015-05-12 17:26:48 -0600466void loader_coalesce_extensions(void)
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600467{
468 uint32_t i;
469 struct loader_scanned_icds *icd_list = loader.scanned_icd_list;
470
471 // traverse scanned icd list adding non-duplicate extensions to the list
472 while (icd_list != NULL) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600473 /* TODO: convert to use ext_list */
474 loader_add_to_ext_list(&loader.global_extensions,
475 icd_list->global_extension_list.count,
476 icd_list->global_extension_list.list);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600477 icd_list = icd_list->next;
478 };
479
480 //Traverse layers list adding non-duplicate extensions to the list
481 for (i = 0; i < loader.scanned_layer_count; i++) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600482 loader_add_to_ext_list(&loader.global_extensions,
483 loader.scanned_layers[i].global_extension_list.count,
484 loader.scanned_layers[i].global_extension_list.list);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600485 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600486
487 // Traverse loader's extensions, adding non-duplicate extensions to the list
488 debug_report_add_instance_extensions(&loader.global_extensions);
Jon Ashburn0c5d4ab2015-05-26 13:57:35 -0600489 wsi_lunarg_add_instance_extensions(&loader.global_extensions);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600490}
491
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600492static void loader_icd_destroy(
493 struct loader_instance *ptr_inst,
494 struct loader_icd *icd)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800495{
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700496 loader_platform_close_library(icd->scanned_icds->handle);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600497 ptr_inst->total_icd_count--;
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800498 free(icd);
499}
500
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600501static struct loader_icd * loader_icd_create(const struct loader_scanned_icds *scanned)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800502{
503 struct loader_icd *icd;
504
505 icd = malloc(sizeof(*icd));
506 if (!icd)
507 return NULL;
508
Courtney Goeltzenleuchter55001bb2014-10-28 10:29:27 -0600509 memset(icd, 0, sizeof(*icd));
510
Jon Ashburn46d1f582015-01-28 11:01:35 -0700511 icd->scanned_icds = scanned;
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800512
513 return icd;
514}
515
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600516static struct loader_icd *loader_icd_add(
517 struct loader_instance *ptr_inst,
518 const struct loader_scanned_icds *scanned)
Chia-I Wu13a61a52014-08-04 11:18:20 +0800519{
520 struct loader_icd *icd;
521
Jon Ashburn46d1f582015-01-28 11:01:35 -0700522 icd = loader_icd_create(scanned);
Chia-I Wu13a61a52014-08-04 11:18:20 +0800523 if (!icd)
524 return NULL;
525
Chia-I Wu13a61a52014-08-04 11:18:20 +0800526 /* prepend to the list */
Jon Ashburn46888392015-01-29 15:45:51 -0700527 icd->next = ptr_inst->icds;
528 ptr_inst->icds = icd;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600529 ptr_inst->total_icd_count++;
Chia-I Wu13a61a52014-08-04 11:18:20 +0800530
531 return icd;
532}
533
Jon Ashburn46d1f582015-01-28 11:01:35 -0700534static void loader_scanned_icd_add(const char *filename)
535{
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700536 loader_platform_dl_handle handle;
Jon Ashburn3da71f22015-05-14 12:43:38 -0600537 void *fp_create_inst;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600538 void *fp_get_global_ext_info;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600539 void *fp_get_device_ext_info;
Jon Ashburn46d1f582015-01-28 11:01:35 -0700540 struct loader_scanned_icds *new_node;
541
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700542 // Used to call: dlopen(filename, RTLD_LAZY);
543 handle = loader_platform_open_library(filename);
Jon Ashburn46d1f582015-01-28 11:01:35 -0700544 if (!handle) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600545 loader_log(VK_DBG_REPORT_WARN_BIT, 0, loader_platform_open_library_error(filename));
Jon Ashburn46d1f582015-01-28 11:01:35 -0700546 return;
547 }
548
549#define LOOKUP(func_ptr, func) do { \
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600550 func_ptr = (PFN_vk ##func) loader_platform_get_proc_address(handle, "vk" #func); \
Jon Ashburn46d1f582015-01-28 11:01:35 -0700551 if (!func_ptr) { \
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600552 loader_log(VK_DBG_REPORT_WARN_BIT, 0, loader_platform_get_proc_address_error("vk" #func)); \
Jon Ashburn46d1f582015-01-28 11:01:35 -0700553 return; \
554 } \
555} while (0)
556
Jon Ashburn46888392015-01-29 15:45:51 -0700557 LOOKUP(fp_create_inst, CreateInstance);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600558 LOOKUP(fp_get_global_ext_info, GetGlobalExtensionInfo);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600559 LOOKUP(fp_get_device_ext_info, GetPhysicalDeviceExtensionInfo);
Jon Ashburn46d1f582015-01-28 11:01:35 -0700560#undef LOOKUP
561
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600562 new_node = (struct loader_scanned_icds *) malloc(sizeof(struct loader_scanned_icds)
563 + strlen(filename) + 1);
Jon Ashburn46d1f582015-01-28 11:01:35 -0700564 if (!new_node) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600565 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Out of memory can't add icd");
Jon Ashburn46d1f582015-01-28 11:01:35 -0700566 return;
567 }
568
569 new_node->handle = handle;
Jon Ashburn46888392015-01-29 15:45:51 -0700570 new_node->CreateInstance = fp_create_inst;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600571 new_node->GetGlobalExtensionInfo = fp_get_global_ext_info;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600572 loader_init_ext_list(&new_node->global_extension_list);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600573 loader_init_ext_list(&new_node->device_extension_list);
Jon Ashburn46d1f582015-01-28 11:01:35 -0700574 new_node->next = loader.scanned_icd_list;
Jon Ashburn46d1f582015-01-28 11:01:35 -0700575
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600576 new_node->lib_name = (char *) (new_node + 1);
577 if (!new_node->lib_name) {
578 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Out of memory can't add icd");
579 return;
580 }
581 strcpy(new_node->lib_name, filename);
582
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600583 loader.scanned_icd_list = new_node;
584
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600585 get_global_extensions(
586 (PFN_vkGetGlobalExtensionInfo) fp_get_global_ext_info,
587 new_node->lib_name,
588 VK_EXTENSION_ORIGIN_ICD,
589 &new_node->global_extension_list);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600590}
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700591
Jon Ashburn3da71f22015-05-14 12:43:38 -0600592static void loader_icd_init_entrys(struct loader_icd *icd,
593 struct loader_scanned_icds *scanned_icds)
594{
595 /* initialize entrypoint function pointers */
596
597 #define LOOKUP(func) do { \
598 icd->func = (PFN_vk ##func) loader_platform_get_proc_address(scanned_icds->handle, "vk" #func); \
599 if (!icd->func) { \
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600600 loader_log(VK_DBG_REPORT_WARN_BIT, 0, loader_platform_get_proc_address_error("vk" #func)); \
Jon Ashburn3da71f22015-05-14 12:43:38 -0600601 return; \
602 } \
603 } while (0)
604
Jon Ashburn8d1b0b52015-05-18 13:20:15 -0600605 /* could change this to use GetInstanceProcAddr in driver instead of dlsym */
606 LOOKUP(GetDeviceProcAddr);
Jon Ashburn3da71f22015-05-14 12:43:38 -0600607 LOOKUP(DestroyInstance);
608 LOOKUP(EnumeratePhysicalDevices);
609 LOOKUP(GetPhysicalDeviceInfo);
610 LOOKUP(CreateDevice);
611 LOOKUP(GetPhysicalDeviceExtensionInfo);
Jon Ashburn3da71f22015-05-14 12:43:38 -0600612 LOOKUP(GetMultiDeviceCompatibility);
Jon Ashburn95a77ba2015-05-15 15:09:35 -0600613 LOOKUP(GetDisplayInfoWSI);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600614 LOOKUP(DbgCreateMsgCallback);
615 LOOKUP(DbgDestroyMsgCallback);
Jon Ashburn3da71f22015-05-14 12:43:38 -0600616#undef LOOKUP
617
618 return;
619}
620
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600621/**
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600622 * Try to \c loader_icd_scan VK driver(s).
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600623 *
624 * This function scans the default system path or path
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600625 * specified by the \c LIBVK_DRIVERS_PATH environment variable in
626 * order to find loadable VK ICDs with the name of libVK_*.
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600627 *
628 * \returns
629 * void; but side effect is to set loader_icd_scanned to true
630 */
Jon Ashburn27cd5842015-05-12 17:26:48 -0600631void loader_icd_scan(void)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800632{
Ian Elliott4470a302015-02-17 10:33:47 -0700633 const char *p, *next;
634 char *libPaths = NULL;
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600635 DIR *sysdir;
636 struct dirent *dent;
637 char icd_library[1024];
Jon Ashburn5cda59c2014-10-03 16:31:35 -0600638 char path[1024];
Ian Elliott19628802015-02-04 12:06:46 -0700639 uint32_t len;
Ian Elliott4470a302015-02-17 10:33:47 -0700640#if defined(WIN32)
641 bool must_free_libPaths;
642 libPaths = loader_get_registry_and_env(DRIVER_PATH_ENV,
643 DRIVER_PATH_REGISTRY_VALUE);
644 if (libPaths != NULL) {
645 must_free_libPaths = true;
646 } else {
647 must_free_libPaths = false;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600648 libPaths = DEFAULT_VK_DRIVERS_PATH;
Ian Elliott4470a302015-02-17 10:33:47 -0700649 }
650#else // WIN32
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600651 if (geteuid() == getuid()) {
Ian Elliott4470a302015-02-17 10:33:47 -0700652 /* Don't allow setuid apps to use the DRIVER_PATH_ENV env var: */
653 libPaths = getenv(DRIVER_PATH_ENV);
654 }
655 if (libPaths == NULL) {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600656 libPaths = DEFAULT_VK_DRIVERS_PATH;
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600657 }
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700658#endif // WIN32
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800659
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600660 for (p = libPaths; *p; p = next) {
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700661 next = strchr(p, PATH_SEPERATOR);
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600662 if (next == NULL) {
Ian Elliott19628802015-02-04 12:06:46 -0700663 len = (uint32_t) strlen(p);
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600664 next = p + len;
665 }
666 else {
Ian Elliott19628802015-02-04 12:06:46 -0700667 len = (uint32_t) (next - p);
Jon Ashburn5cda59c2014-10-03 16:31:35 -0600668 sprintf(path, "%.*s", (len > sizeof(path) - 1) ? (int) sizeof(path) - 1 : len, p);
669 p = path;
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600670 next++;
671 }
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800672
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700673 // TODO/TBD: Do we want to do this on Windows, or just let Windows take
674 // care of its own search path (which it apparently has)?
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600675 sysdir = opendir(p);
676 if (sysdir) {
677 dent = readdir(sysdir);
678 while (dent) {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600679 /* Look for ICDs starting with VK_DRIVER_LIBRARY_PREFIX and
680 * ending with VK_LIBRARY_SUFFIX
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700681 */
682 if (!strncmp(dent->d_name,
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600683 VK_DRIVER_LIBRARY_PREFIX,
684 VK_DRIVER_LIBRARY_PREFIX_LEN)) {
Ian Elliott19628802015-02-04 12:06:46 -0700685 uint32_t nlen = (uint32_t) strlen(dent->d_name);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600686 const char *suf = dent->d_name + nlen - VK_LIBRARY_SUFFIX_LEN;
687 if ((nlen > VK_LIBRARY_SUFFIX_LEN) &&
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700688 !strncmp(suf,
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600689 VK_LIBRARY_SUFFIX,
690 VK_LIBRARY_SUFFIX_LEN)) {
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700691 snprintf(icd_library, 1024, "%s" DIRECTORY_SYMBOL "%s", p,dent->d_name);
692 loader_scanned_icd_add(icd_library);
693 }
694 }
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600695
696 dent = readdir(sysdir);
697 }
698 closedir(sysdir);
699 }
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800700 }
701
Ian Elliott4470a302015-02-17 10:33:47 -0700702#if defined(WIN32)
703 // Free any allocated memory:
704 if (must_free_libPaths) {
705 free(libPaths);
706 }
707#endif // WIN32
708
709 // Note that we've scanned for ICDs:
Jon Ashburn46d1f582015-01-28 11:01:35 -0700710 loader.icds_scanned = true;
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800711}
712
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600713
Jon Ashburn27cd5842015-05-12 17:26:48 -0600714void layer_lib_scan(void)
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600715{
716 const char *p, *next;
Ian Elliott4470a302015-02-17 10:33:47 -0700717 char *libPaths = NULL;
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600718 DIR *curdir;
719 struct dirent *dent;
Ian Elliott4470a302015-02-17 10:33:47 -0700720 size_t len, i;
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600721 char temp_str[1024];
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600722 uint32_t count;
723 PFN_vkGetGlobalExtensionInfo fp_get_ext;
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600724
Ian Elliott4470a302015-02-17 10:33:47 -0700725#if defined(WIN32)
726 bool must_free_libPaths;
727 libPaths = loader_get_registry_and_env(LAYERS_PATH_ENV,
728 LAYERS_PATH_REGISTRY_VALUE);
729 if (libPaths != NULL) {
730 must_free_libPaths = true;
731 } else {
732 must_free_libPaths = false;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600733 libPaths = DEFAULT_VK_LAYERS_PATH;
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600734 }
Ian Elliott4470a302015-02-17 10:33:47 -0700735#else // WIN32
736 if (geteuid() == getuid()) {
737 /* Don't allow setuid apps to use the DRIVER_PATH_ENV env var: */
Courtney Goeltzenleuchter66b72f92015-02-18 20:03:02 -0700738 libPaths = getenv(LAYERS_PATH_ENV);
Ian Elliott4470a302015-02-17 10:33:47 -0700739 }
740 if (libPaths == NULL) {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600741 libPaths = DEFAULT_VK_LAYERS_PATH;
Ian Elliott4470a302015-02-17 10:33:47 -0700742 }
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700743#endif // WIN32
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600744
Ian Elliott4470a302015-02-17 10:33:47 -0700745 if (libPaths == NULL) {
746 // Have no paths to search:
Courtney Goeltzenleuchter57985ce2014-12-01 09:29:42 -0700747 return;
748 }
Ian Elliott4470a302015-02-17 10:33:47 -0700749 len = strlen(libPaths);
Courtney Goeltzenleuchter57985ce2014-12-01 09:29:42 -0700750 loader.layer_dirs = malloc(len+1);
Ian Elliott4470a302015-02-17 10:33:47 -0700751 if (loader.layer_dirs == NULL) {
752 free(libPaths);
Courtney Goeltzenleuchtera66265b2014-12-02 18:12:51 -0700753 return;
Ian Elliott4470a302015-02-17 10:33:47 -0700754 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600755 // Alloc passed, so we know there is enough space to hold the string
Ian Elliott4470a302015-02-17 10:33:47 -0700756 strcpy(loader.layer_dirs, libPaths);
757#if defined(WIN32)
758 // Free any allocated memory:
759 if (must_free_libPaths) {
760 free(libPaths);
761 must_free_libPaths = false;
762 }
763#endif // WIN32
Courtney Goeltzenleuchter57985ce2014-12-01 09:29:42 -0700764 libPaths = loader.layer_dirs;
765
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600766 /* cleanup any previously scanned libraries */
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600767 for (i = 0; i < loader.scanned_layer_count; i++) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600768 if (loader.scanned_layers[i].lib_name != NULL)
769 free(loader.scanned_layers[i].lib_name);
770 loader_destroy_ext_list(&loader.scanned_layers[i].global_extension_list);
771 loader.scanned_layers[i].lib_name = NULL;
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600772 }
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600773 loader.scanned_layer_count = 0;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600774 count = 0;
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600775
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600776 for (p = libPaths; *p; p = next) {
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600777 next = strchr(p, PATH_SEPERATOR);
778 if (next == NULL) {
779 len = (uint32_t) strlen(p);
780 next = p + len;
781 }
782 else {
783 len = (uint32_t) (next - p);
784 *(char *) next = '\0';
785 next++;
786 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600787
788 curdir = opendir(p);
789 if (curdir) {
790 dent = readdir(curdir);
791 while (dent) {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600792 /* Look for layers starting with VK_LAYER_LIBRARY_PREFIX and
793 * ending with VK_LIBRARY_SUFFIX
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700794 */
795 if (!strncmp(dent->d_name,
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600796 VK_LAYER_LIBRARY_PREFIX,
797 VK_LAYER_LIBRARY_PREFIX_LEN)) {
Ian Elliott19628802015-02-04 12:06:46 -0700798 uint32_t nlen = (uint32_t) strlen(dent->d_name);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600799 const char *suf = dent->d_name + nlen - VK_LIBRARY_SUFFIX_LEN;
800 if ((nlen > VK_LIBRARY_SUFFIX_LEN) &&
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700801 !strncmp(suf,
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600802 VK_LIBRARY_SUFFIX,
803 VK_LIBRARY_SUFFIX_LEN)) {
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700804 loader_platform_dl_handle handle;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600805 snprintf(temp_str, sizeof(temp_str),
806 "%s" DIRECTORY_SYMBOL "%s",p,dent->d_name);
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700807 // Used to call: dlopen(temp_str, RTLD_LAZY)
808 if ((handle = loader_platform_open_library(temp_str)) == NULL) {
809 dent = readdir(curdir);
810 continue;
811 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600812 /* TODO: Remove fixed count */
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600813 if (count == MAX_LAYER_LIBRARIES) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600814 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600815 "%s ignored: max layer libraries exceed",
816 temp_str);
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700817 break;
818 }
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600819 fp_get_ext = loader_platform_get_proc_address(handle,
820 "vkGetGlobalExtensionInfo");
821
822 if (!fp_get_ext) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600823 loader_log(VK_DBG_REPORT_WARN_BIT, 0,
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600824 "Couldn't dlsym vkGetGlobalExtensionInfo from library %s",
825 temp_str);
826 dent = readdir(curdir);
827 loader_platform_close_library(handle);
828 continue;
829 }
830
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600831 loader.scanned_layers[count].lib_name =
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600832 malloc(strlen(temp_str) + 1);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600833 if (loader.scanned_layers[count].lib_name == NULL) {
834 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "%s ignored: out of memory", temp_str);
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700835 break;
836 }
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600837
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600838 strcpy(loader.scanned_layers[count].lib_name, temp_str);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600839
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600840 get_global_extensions(
841 fp_get_ext,
842 loader.scanned_layers[count].lib_name,
843 VK_EXTENSION_ORIGIN_LAYER,
844 &loader.scanned_layers[count].global_extension_list);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600845
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600846 fp_get_ext = loader_platform_get_proc_address(handle,
847 "vkGetPhysicalDeviceExtensionInfo");
848 if (fp_get_ext) {
849 loader.scanned_layers[count].physical_device_extensions_supported = true;
850 }
851
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600852 count++;
853 loader_platform_close_library(handle);
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700854 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600855 }
856
857 dent = readdir(curdir);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600858 } // while (dir_entry)
859 if (count == MAX_LAYER_LIBRARIES)
860 break;
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600861 closedir(curdir);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600862 } // if (curdir))
863 } // for (libpaths)
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600864
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600865 loader.scanned_layer_count = count;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600866 loader.layers_scanned = true;
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600867}
868
Jon Ashburn27cd5842015-05-12 17:26:48 -0600869static void* VKAPI loader_gpa_instance_internal(VkInstance inst, const char * pName)
870{
871 // inst is not wrapped
872 if (inst == VK_NULL_HANDLE) {
873 return NULL;
874 }
875 VkLayerInstanceDispatchTable* disp_table = * (VkLayerInstanceDispatchTable **) inst;
876 void *addr;
877
Jon Ashburn8fd08252015-05-28 16:25:02 -0600878 if (!strcmp(pName, "vkGetInstanceProcAddr"))
879 return (void *) loader_gpa_instance_internal;
880
Jon Ashburn27cd5842015-05-12 17:26:48 -0600881 if (disp_table == NULL)
882 return NULL;
883
884 addr = loader_lookup_instance_dispatch_table(disp_table, pName);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600885 if (addr) {
Jon Ashburn27cd5842015-05-12 17:26:48 -0600886 return addr;
Jon Ashburn3d526cb2015-04-13 18:10:06 -0600887 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600888
889 if (disp_table->GetInstanceProcAddr == NULL) {
890 return NULL;
891 }
892 return disp_table->GetInstanceProcAddr(inst, pName);
Jon Ashburn3d526cb2015-04-13 18:10:06 -0600893}
894
Jon Ashburn1ed042c2015-05-01 18:00:33 -0600895struct loader_icd * loader_get_icd(const VkBaseLayerObject *gpu, uint32_t *gpu_index)
Jon Ashburn876b1ac2014-10-17 15:09:07 -0600896{
Jon Ashburn4d9f4652015-04-08 21:33:34 -0600897 /*
898 * NOTE: at this time icd->gpus is pointing to wrapped GPUs, but no where else
899 * are wrapped gpus used. Should go away. The incoming gpu is NOT wrapped so
900 * need to test it against the wrapped GPU's base object.
901 */
Jon Ashburn98bd4542015-01-29 16:44:24 -0700902 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
903 for (struct loader_icd *icd = inst->icds; icd; icd = icd->next) {
904 for (uint32_t i = 0; i < icd->gpu_count; i++)
Mike Stroyanb050c682015-04-17 12:36:38 -0600905 if ((icd->gpus + i) == gpu || (void*)(icd->gpus +i)->baseObject == gpu) {
Jon Ashburn98bd4542015-01-29 16:44:24 -0700906 *gpu_index = i;
907 return icd;
908 }
909 }
Jon Ashburn876b1ac2014-10-17 15:09:07 -0600910 }
911 return NULL;
912}
913
Mark Lobodzinski17caf572015-01-29 08:55:56 -0600914static bool loader_layers_activated(const struct loader_icd *icd, const uint32_t gpu_index)
Jon Ashburn876b1ac2014-10-17 15:09:07 -0600915{
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600916 if (icd->layer_count[gpu_index])
917 return true;
918 else
919 return false;
Jon Ashburn876b1ac2014-10-17 15:09:07 -0600920}
921
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600922static loader_platform_dl_handle loader_add_layer_lib(
Jon Ashburn4f67d742015-05-27 13:19:22 -0600923 const char *chain_type,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600924 struct loader_extension_property *ext_prop)
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600925{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600926 struct loader_lib_info *new_layer_lib_list, *my_lib;
927
928 /* Only loader layer libraries here */
929 if (ext_prop->origin != VK_EXTENSION_ORIGIN_LAYER) {
930 return NULL;
931 }
932
933 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) {
934 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, ext_prop->lib_name) == 0) {
935 /* Have already loaded this library, just increment ref count */
936 loader.loaded_layer_lib_list[i].ref_count++;
Jon Ashburne68a9ff2015-05-25 14:11:37 -0600937 loader_log(VK_DBG_REPORT_INFO_BIT, 0,
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600938 "%s Chain: Increment layer reference count for layer library %s",
939 chain_type, ext_prop->lib_name);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600940 return loader.loaded_layer_lib_list[i].lib_handle;
941 }
942 }
943
944 /* Haven't seen this library so load it */
945 new_layer_lib_list = realloc(loader.loaded_layer_lib_list,
946 (loader.loaded_layer_lib_count + 1) * sizeof(struct loader_lib_info));
947 if (!new_layer_lib_list) {
948 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "loader: malloc failed");
949 return NULL;
950 }
951
952 my_lib = &new_layer_lib_list[loader.loaded_layer_lib_count];
953
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600954 /* NOTE: We require that the extension property be immutable */
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600955 my_lib->lib_name = ext_prop->lib_name;
956 my_lib->ref_count = 0;
957 my_lib->lib_handle = NULL;
958
959 if ((my_lib->lib_handle = loader_platform_open_library(my_lib->lib_name)) == NULL) {
960 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
961 loader_platform_open_library_error(my_lib->lib_name));
962 return NULL;
963 } else {
964 loader_log(VK_DBG_REPORT_INFO_BIT, 0,
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600965 "Chain: %s: Loading layer library %s",
966 chain_type, ext_prop->lib_name);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600967 }
968 loader.loaded_layer_lib_count++;
969 loader.loaded_layer_lib_list = new_layer_lib_list;
970 my_lib->ref_count++;
971
972 return my_lib->lib_handle;
973}
974
975static void loader_remove_layer_lib(
976 struct loader_instance *inst,
977 struct loader_extension_property *ext_prop)
978{
979 uint32_t idx;
980 struct loader_lib_info *new_layer_lib_list, *my_lib;
981
982 /* Only loader layer libraries here */
983 if (ext_prop->origin != VK_EXTENSION_ORIGIN_LAYER) {
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600984 return;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600985 }
Jon Ashburndf7d5842014-10-16 15:48:50 -0600986
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600987 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) {
988 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, ext_prop->lib_name) == 0) {
989 /* found matching library */
990 idx = i;
991 my_lib = &loader.loaded_layer_lib_list[i];
992 break;
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600993 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600994 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600995
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600996 my_lib->ref_count--;
997 inst->layer_count--;
998 if (my_lib->ref_count > 0) {
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600999 loader_log(VK_DBG_REPORT_INFO_BIT, 0,
1000 "Decrement reference count for layer library %s", ext_prop->lib_name);
Jon Ashburn27cd5842015-05-12 17:26:48 -06001001 return;
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07001002 }
Jon Ashburn19c25022015-04-14 14:14:48 -06001003
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001004 loader_platform_close_library(my_lib->lib_handle);
1005 loader_log(VK_DBG_REPORT_INFO_BIT, 0,
1006 "Unloading layer library %s", ext_prop->lib_name);
1007
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001008 /* Need to remove unused library from list */
1009 new_layer_lib_list = malloc((loader.loaded_layer_lib_count - 1) * sizeof(struct loader_lib_info));
1010 if (!new_layer_lib_list) {
1011 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "loader: malloc failed");
1012 return;
1013 }
1014
1015 if (idx > 0) {
1016 /* Copy records before idx */
1017 memcpy(new_layer_lib_list, &loader.loaded_layer_lib_list[0],
1018 sizeof(struct loader_lib_info) * idx);
1019 }
1020 if (idx < (loader.loaded_layer_lib_count - 1)) {
1021 /* Copy records after idx */
1022 memcpy(&new_layer_lib_list[idx], &loader.loaded_layer_lib_list[idx+1],
1023 sizeof(struct loader_lib_info) * (loader.loaded_layer_lib_count - idx - 1));
1024 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001025
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001026 free(loader.loaded_layer_lib_list);
1027 loader.loaded_layer_lib_count--;
1028 loader.loaded_layer_lib_list = new_layer_lib_list;
Jon Ashburnb8358052014-11-18 09:06:04 -07001029}
1030
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001031static void loader_add_layer_env(
1032 struct loader_extension_list *ext_list,
1033 const struct loader_extension_list *search_list)
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001034{
Ian Elliott4470a302015-02-17 10:33:47 -07001035 char *layerEnv;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001036 uint32_t len;
Jon Ashburnd09bd102014-10-22 21:15:26 -06001037 char *p, *pOrig, *next, *name;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001038
Ian Elliott4470a302015-02-17 10:33:47 -07001039#if defined(WIN32)
1040 layerEnv = loader_get_registry_and_env(LAYER_NAMES_ENV,
1041 LAYER_NAMES_REGISTRY_VALUE);
1042#else // WIN32
1043 layerEnv = getenv(LAYER_NAMES_ENV);
1044#endif // WIN32
1045 if (layerEnv == NULL) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001046 return;
Ian Elliott4470a302015-02-17 10:33:47 -07001047 }
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06001048 p = malloc(strlen(layerEnv) + 1);
Ian Elliott4470a302015-02-17 10:33:47 -07001049 if (p == NULL) {
1050#if defined(WIN32)
1051 free(layerEnv);
1052#endif // WIN32
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001053 return;
Ian Elliott4470a302015-02-17 10:33:47 -07001054 }
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06001055 strcpy(p, layerEnv);
Ian Elliott4470a302015-02-17 10:33:47 -07001056#if defined(WIN32)
1057 free(layerEnv);
1058#endif // WIN32
Jon Ashburnd09bd102014-10-22 21:15:26 -06001059 pOrig = p;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001060
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001061 while (p && *p ) {
Jon Ashburn19c25022015-04-14 14:14:48 -06001062 //memset(&lib_name[0], 0, sizeof(const char *) * MAX_LAYER_LIBRARIES);
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001063 next = strchr(p, PATH_SEPERATOR);
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001064 if (next == NULL) {
Ian Elliott19628802015-02-04 12:06:46 -07001065 len = (uint32_t) strlen(p);
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001066 next = p + len;
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07001067 } else {
Ian Elliott19628802015-02-04 12:06:46 -07001068 len = (uint32_t) (next - p);
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001069 *(char *) next = '\0';
1070 next++;
1071 }
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06001072 name = basename(p);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001073 loader_search_ext_list_for_name(name, search_list, ext_list);
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001074 p = next;
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07001075 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001076
Jon Ashburnd09bd102014-10-22 21:15:26 -06001077 free(pOrig);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001078 return;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001079}
1080
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06001081
Jon Ashburn27cd5842015-05-12 17:26:48 -06001082//TODO static void loader_deactivate_device_layer(device)
1083
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001084static void loader_deactivate_instance_layers(struct loader_instance *instance)
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06001085{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001086 if (!instance->layer_count) {
1087 return;
1088 }
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06001089
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001090 /* Create instance chain of enabled layers */
1091 for (uint32_t i = 0; i < instance->enabled_instance_extensions.count; i++) {
1092 struct loader_extension_property *ext_prop = &instance->enabled_instance_extensions.list[i];
1093
1094 if (ext_prop->origin == VK_EXTENSION_ORIGIN_ICD) {
1095 continue;
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06001096 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001097
1098 loader_remove_layer_lib(instance, ext_prop);
1099
1100 instance->layer_count--;
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06001101 }
Jon Ashburn27cd5842015-05-12 17:26:48 -06001102
1103 free(instance->wrappedInstance);
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06001104}
1105
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001106void loader_enable_instance_layers(struct loader_instance *inst)
1107{
1108 if (inst == NULL)
1109 return;
1110
1111 /* Add any layers specified in the environment first */
1112 loader_add_layer_env(&inst->enabled_instance_extensions, &loader.global_extensions);
1113
1114 /* Add layers / extensions specified by the application */
1115 loader_add_vk_ext_to_ext_list(
1116 &inst->enabled_instance_extensions,
1117 inst->app_extension_count,
1118 inst->app_extension_props,
1119 &loader.global_extensions);
1120}
1121
Jon Ashburn27cd5842015-05-12 17:26:48 -06001122uint32_t loader_activate_instance_layers(struct loader_instance *inst)
1123{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001124 uint32_t layer_idx;
1125
Jon Ashburn27cd5842015-05-12 17:26:48 -06001126 if (inst == NULL)
1127 return 0;
1128
1129 // NOTE inst is unwrapped at this point in time
1130 VkObject baseObj = (VkObject) inst;
1131 VkObject nextObj = (VkObject) inst;
1132 VkBaseLayerObject *nextInstObj;
1133 PFN_vkGetInstanceProcAddr nextGPA = loader_gpa_instance_internal;
1134
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001135 /*
1136 * Figure out how many actual layers will need to be wrapped.
1137 */
1138 inst->layer_count = 0;
1139 for (uint32_t i = 0; i < inst->enabled_instance_extensions.count; i++) {
1140 struct loader_extension_property *ext_prop = &inst->enabled_instance_extensions.list[i];
1141 if (ext_prop->origin == VK_EXTENSION_ORIGIN_LAYER) {
1142 inst->layer_count++;
1143 }
1144 }
Jon Ashburn27cd5842015-05-12 17:26:48 -06001145
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001146 if (!inst->layer_count) {
Jon Ashburn27cd5842015-05-12 17:26:48 -06001147 return 0;
1148 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001149
1150 inst->wrappedInstance = malloc(sizeof(VkBaseLayerObject)
1151 * inst->layer_count);
1152 if (!inst->wrappedInstance) {
1153 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to malloc Instance objects for layer");
1154 return 0;
1155 }
1156
1157 /* Create instance chain of enabled layers */
1158 layer_idx = inst->layer_count - 1;
1159 for (int32_t i = inst->enabled_instance_extensions.count - 1; i >= 0; i--) {
1160 struct loader_extension_property *ext_prop = &inst->enabled_instance_extensions.list[i];
1161 loader_platform_dl_handle lib_handle;
1162
1163 /*
1164 * TODO: Need to figure out how to hook in extensions implemented
1165 * within the loader.
1166 * What GetProcAddr do we use?
1167 * How do we make the loader call first in the chain? It may not be first
1168 * in the list. Does it have to be first?
1169 * How does the chain for DbgCreateMsgCallback get made?
1170 * Do we need to add the function pointer to the VkLayerInstanceDispatchTable?
1171 * Seems like we will.
1172 * What happens with more than one loader implemented extension?
1173 * Issue: Process of building instance chain requires that we call GetInstanceProcAddr
1174 * on the various extension components. However, if we are asking for an extension
1175 * entry point we won't get it because we haven't enabled the extension yet.
1176 * Must not call GPA on extensions at this time.
1177 */
1178 if (ext_prop->origin != VK_EXTENSION_ORIGIN_LAYER) {
1179 continue;
1180 }
1181
1182 nextInstObj = (inst->wrappedInstance + layer_idx);
Jon Ashburn27cd5842015-05-12 17:26:48 -06001183 nextInstObj->pGPA = nextGPA;
1184 nextInstObj->baseObject = baseObj;
1185 nextInstObj->nextObject = nextObj;
1186 nextObj = (VkObject) nextInstObj;
1187
1188 char funcStr[256];
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001189 snprintf(funcStr, 256, "%sGetInstanceProcAddr", ext_prop->info.name);
Jon Ashburn4f67d742015-05-27 13:19:22 -06001190 lib_handle = loader_add_layer_lib("instance", ext_prop);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001191 if ((nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, funcStr)) == NULL)
1192 nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetInstanceProcAddr");
Jon Ashburn27cd5842015-05-12 17:26:48 -06001193 if (!nextGPA) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001194 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to find vkGetInstanceProcAddr in layer %s", ext_prop->lib_name);
Jon Ashburn27cd5842015-05-12 17:26:48 -06001195 continue;
1196 }
1197
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001198 loader_log(VK_DBG_REPORT_INFO_BIT, 0,
1199 "Insert instance layer library %s for extension: %s",
1200 ext_prop->lib_name, ext_prop->info.name);
1201
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001202 layer_idx--;
Jon Ashburn27cd5842015-05-12 17:26:48 -06001203 }
1204
Jon Ashburn8fd08252015-05-28 16:25:02 -06001205 loader_init_instance_core_dispatch_table(inst->disp, nextGPA, (VkInstance) nextObj, (VkInstance) baseObj);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001206
Jon Ashburn27cd5842015-05-12 17:26:48 -06001207 return inst->layer_count;
1208}
1209
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001210void loader_activate_instance_layer_extensions(struct loader_instance *inst)
1211{
1212
1213 loader_init_instance_extension_dispatch_table(inst->disp,
1214 inst->disp->GetInstanceProcAddr,
1215 (VkInstance) inst->wrappedInstance);
1216}
1217
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001218void loader_enable_device_layers(struct loader_icd *icd, uint32_t gpu_index)
1219{
1220 if (icd == NULL)
1221 return;
1222
1223 /* Add any layers specified in the environment first */
1224 loader_add_layer_env(&icd->enabled_device_extensions[gpu_index], &loader.global_extensions);
1225
1226 /* Add layers / extensions specified by the application */
1227 loader_add_vk_ext_to_ext_list(
1228 &icd->enabled_device_extensions[gpu_index],
1229 icd->app_extension_count[gpu_index],
1230 icd->app_extension_props[gpu_index],
1231 &loader.global_extensions);
1232}
1233
1234extern uint32_t loader_activate_device_layers(
1235 VkDevice device,
1236 struct loader_icd *icd,
1237 uint32_t gpu_index,
1238 uint32_t ext_count,
1239 const VkExtensionProperties *ext_props)
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06001240{
Mark Lobodzinski17caf572015-01-29 08:55:56 -06001241 uint32_t count;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001242 uint32_t layer_idx;
1243
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06001244 if (!icd)
1245 return 0;
Jon Ashburn83a64252015-04-15 11:31:12 -06001246 assert(gpu_index < MAX_GPUS_FOR_LAYER);
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06001247
1248 /* activate any layer libraries */
1249 if (!loader_layers_activated(icd, gpu_index)) {
Jon Ashburn95a77ba2015-05-15 15:09:35 -06001250 VkObject nextObj = (VkObject) device;
1251 VkObject baseObj = nextObj;
1252 VkBaseLayerObject *nextGpuObj;
Jon Ashburn7c096122015-05-22 09:19:49 -06001253 PFN_vkGetDeviceProcAddr nextGPA = icd->GetDeviceProcAddr;
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06001254
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001255 count = 0;
1256 for (uint32_t i = 0; i < icd->enabled_device_extensions[gpu_index].count; i++) {
1257 struct loader_extension_property *ext_prop = &icd->enabled_device_extensions[gpu_index].list[i];
1258 if (ext_prop->origin == VK_EXTENSION_ORIGIN_LAYER) {
1259 count++;
1260 }
1261 }
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06001262 if (!count)
1263 return 0;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001264
1265 icd->layer_count[gpu_index] = count;
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06001266
Jon Ashburnbacb0f52015-04-06 10:58:22 -06001267 icd->wrappedGpus[gpu_index] = malloc(sizeof(VkBaseLayerObject) * icd->layer_count[gpu_index]);
Jon Ashburn27cd5842015-05-12 17:26:48 -06001268 if (! icd->wrappedGpus[gpu_index]) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001269 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to malloc Gpu objects for layer");
Jon Ashburn27cd5842015-05-12 17:26:48 -06001270 return 0;
1271 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001272 layer_idx = count - 1;
Mark Lobodzinski17caf572015-01-29 08:55:56 -06001273 for (int32_t i = icd->layer_count[gpu_index] - 1; i >= 0; i--) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001274 struct loader_extension_property *ext_prop = &icd->enabled_device_extensions[gpu_index].list[i];
1275 loader_platform_dl_handle lib_handle;
1276
1277 if (ext_prop->origin != VK_EXTENSION_ORIGIN_LAYER) {
1278 continue;
1279 }
1280
Jon Ashburnd09bd102014-10-22 21:15:26 -06001281 nextGpuObj = (icd->wrappedGpus[gpu_index] + i);
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06001282 nextGpuObj->pGPA = nextGPA;
Jon Ashburn95a77ba2015-05-15 15:09:35 -06001283 nextGpuObj->baseObject = baseObj;
1284 nextGpuObj->nextObject = nextObj;
1285 nextObj = (VkObject) nextGpuObj;
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06001286
Jon Ashburn79113cc2014-12-01 14:22:40 -07001287 char funcStr[256];
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001288 snprintf(funcStr, 256, "%sGetDeviceProcAddr", ext_prop->info.name);
Jon Ashburn4f67d742015-05-27 13:19:22 -06001289 lib_handle = loader_add_layer_lib("device", ext_prop);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001290 if ((nextGPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, funcStr)) == NULL)
1291 nextGPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetDeviceProcAddr");
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06001292 if (!nextGPA) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001293 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to find vkGetDeviceProcAddr in layer %s", ext_prop->info.name);
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06001294 continue;
1295 }
1296
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001297 loader_log(VK_DBG_REPORT_INFO_BIT, 0,
1298 "Insert device layer library %s for extension: %s",
1299 ext_prop->lib_name, ext_prop->info.name);
1300
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001301 layer_idx--;
1302 }
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06001303
Jon Ashburn8fd08252015-05-28 16:25:02 -06001304 loader_init_device_dispatch_table(icd->loader_dispatch + gpu_index, nextGPA,
1305 (VkPhysicalDevice) nextObj, (VkPhysicalDevice) baseObj);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001306 } else {
1307 // TODO: Check that active layers match requested?
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06001308 }
1309 return icd->layer_count[gpu_index];
1310}
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001311
Jon Ashburn27cd5842015-05-12 17:26:48 -06001312VkResult loader_CreateInstance(
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001313 const VkInstanceCreateInfo* pCreateInfo,
1314 VkInstance* pInstance)
Jon Ashburn1beab2d2015-01-26 14:51:40 -07001315{
Jon Ashburneed0c002015-05-21 17:42:17 -06001316 struct loader_instance *ptr_instance = *(struct loader_instance **) pInstance;
Jon Ashburn46888392015-01-29 15:45:51 -07001317 struct loader_scanned_icds *scanned_icds;
1318 struct loader_icd *icd;
Jon Ashburn27cd5842015-05-12 17:26:48 -06001319 VkResult res;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07001320
Jon Ashburn46888392015-01-29 15:45:51 -07001321 scanned_icds = loader.scanned_icd_list;
1322 while (scanned_icds) {
1323 icd = loader_icd_add(ptr_instance, scanned_icds);
1324 if (icd) {
Jon Ashburnb317fad2015-04-04 14:52:07 -06001325 res = scanned_icds->CreateInstance(pCreateInfo,
Jon Ashburn3da71f22015-05-14 12:43:38 -06001326 &(icd->instance));
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001327 if (res != VK_SUCCESS)
Jon Ashburn46888392015-01-29 15:45:51 -07001328 {
1329 ptr_instance->icds = ptr_instance->icds->next;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001330 loader_icd_destroy(ptr_instance, icd);
Jon Ashburn3da71f22015-05-14 12:43:38 -06001331 icd->instance = VK_NULL_HANDLE;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001332 loader_log(VK_DBG_REPORT_WARN_BIT, 0,
Jon Ashburn46888392015-01-29 15:45:51 -07001333 "ICD ignored: failed to CreateInstance on device");
Jon Ashburn3da71f22015-05-14 12:43:38 -06001334 } else
1335 {
1336 loader_icd_init_entrys(icd, scanned_icds);
Jon Ashburn46888392015-01-29 15:45:51 -07001337 }
1338 }
1339 scanned_icds = scanned_icds->next;
1340 }
Jon Ashburn1beab2d2015-01-26 14:51:40 -07001341
Ian Elliotteb450762015-02-05 15:19:15 -07001342 if (ptr_instance->icds == NULL) {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001343 return VK_ERROR_INCOMPATIBLE_DRIVER;
Ian Elliotteb450762015-02-05 15:19:15 -07001344 }
Jon Ashburn46888392015-01-29 15:45:51 -07001345
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001346 return res;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07001347}
1348
Jon Ashburn27cd5842015-05-12 17:26:48 -06001349VkResult loader_DestroyInstance(
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -06001350 VkInstance instance)
Jon Ashburn1beab2d2015-01-26 14:51:40 -07001351{
1352 struct loader_instance *ptr_instance = (struct loader_instance *) instance;
Jon Ashburn3da71f22015-05-14 12:43:38 -06001353 struct loader_icd *icds = ptr_instance->icds;
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -06001354 VkResult res;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07001355
1356 // Remove this instance from the list of instances:
1357 struct loader_instance *prev = NULL;
1358 struct loader_instance *next = loader.instances;
1359 while (next != NULL) {
1360 if (next == ptr_instance) {
1361 // Remove this instance from the list:
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001362 free(ptr_instance->app_extension_props);
Jon Ashburn1beab2d2015-01-26 14:51:40 -07001363 if (prev)
1364 prev->next = next->next;
Jon Ashburnc5c49602015-02-03 09:26:59 -07001365 else
1366 loader.instances = next->next;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07001367 break;
1368 }
1369 prev = next;
1370 next = next->next;
1371 }
1372 if (next == NULL) {
1373 // This must be an invalid instance handle or empty list
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001374 return VK_ERROR_INVALID_HANDLE;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07001375 }
1376
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001377 loader_deactivate_instance_layers(ptr_instance);
1378 loader_destroy_ext_list(&ptr_instance->enabled_instance_extensions);
Jon Ashburn1beab2d2015-01-26 14:51:40 -07001379
Jon Ashburn3da71f22015-05-14 12:43:38 -06001380 while (icds) {
1381 if (icds->instance) {
1382 res = icds->DestroyInstance(icds->instance);
Tony Barbourf20f87b2015-04-22 09:02:32 -06001383 if (res != VK_SUCCESS)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001384 loader_log(VK_DBG_REPORT_WARN_BIT, 0,
Tony Barbourf20f87b2015-04-22 09:02:32 -06001385 "ICD ignored: failed to DestroyInstance on device");
1386 }
Jon Ashburn3da71f22015-05-14 12:43:38 -06001387 icds->instance = VK_NULL_HANDLE;
1388 icds = icds->next;
Jon Ashburn46888392015-01-29 15:45:51 -07001389 }
1390
Jon Ashburn1beab2d2015-01-26 14:51:40 -07001391 free(ptr_instance);
1392
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001393 return VK_SUCCESS;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07001394}
1395
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001396VkResult loader_init_physical_device_info(
1397 struct loader_instance *ptr_instance)
1398{
1399 struct loader_icd *icd;
1400 uint32_t n, count = 0;
1401 VkResult res = VK_ERROR_UNKNOWN;
1402
1403 icd = ptr_instance->icds;
1404 while (icd) {
1405 res = icd->EnumeratePhysicalDevices(icd->instance, &n, NULL);
1406 if (res != VK_SUCCESS)
1407 return res;
1408 icd->gpu_count = n;
1409 count += n;
1410 icd = icd->next;
1411 }
1412
1413 ptr_instance->total_gpu_count = count;
1414
1415 VkPhysicalDevice* gpus;
1416 gpus = malloc( sizeof(VkPhysicalDevice) * count);
1417 if (!gpus) {
1418 return VK_ERROR_OUT_OF_HOST_MEMORY;
1419 }
1420
1421 icd = ptr_instance->icds;
1422 while (icd) {
1423 VkBaseLayerObject * wrapped_gpus;
1424 PFN_vkGetDeviceProcAddr get_proc_addr = icd->GetDeviceProcAddr;
1425
1426 n = icd->gpu_count;
1427 res = icd->EnumeratePhysicalDevices(
1428 icd->instance,
1429 &n,
1430 gpus);
1431 if (res == VK_SUCCESS && n) {
1432 wrapped_gpus = (VkBaseLayerObject*) malloc(n *
1433 sizeof(VkBaseLayerObject));
1434 if (!wrapped_gpus) {
1435 /* TODO: Add cleanup code here */
1436 return VK_ERROR_OUT_OF_HOST_MEMORY;
1437 }
1438
1439 icd->gpus = wrapped_gpus;
1440 icd->loader_dispatch = (VkLayerDispatchTable *) malloc(n *
1441 sizeof(VkLayerDispatchTable));
1442 for (unsigned int i = 0; i < n; i++) {
1443 (wrapped_gpus + i)->baseObject = gpus[i];
1444 (wrapped_gpus + i)->pGPA = get_proc_addr;
1445 (wrapped_gpus + i)->nextObject = gpus[i];
1446
1447 loader_init_device_dispatch_table(icd->loader_dispatch + i,
1448 get_proc_addr, gpus[i], gpus[i]);
1449
1450 loader_init_dispatch(gpus[i], ptr_instance->disp);
1451
1452 if (!loader_init_ext_list(&icd->device_extension_cache[i])) {
1453 /* TODO: Add cleanup code here */
1454 res = VK_ERROR_OUT_OF_HOST_MEMORY;
1455 }
1456 if (res == VK_SUCCESS && icd->GetPhysicalDeviceExtensionInfo) {
1457 size_t data_size;
1458 uint32_t extension_count;
1459
1460 data_size = sizeof(extension_count);
1461 res = icd->GetPhysicalDeviceExtensionInfo(gpus[i], VK_EXTENSION_INFO_TYPE_COUNT, 0, &data_size, &extension_count);
1462 if (data_size == sizeof(extension_count) && res == VK_SUCCESS) {
1463 struct loader_extension_property ext_props;
1464
1465 /* Gather all the ICD extensions */
1466 for (uint32_t extension_id = 0; extension_id < extension_count; extension_id++) {
1467 data_size = sizeof(VkExtensionProperties);
1468 res = icd->GetPhysicalDeviceExtensionInfo(gpus[i], VK_EXTENSION_INFO_TYPE_PROPERTIES,
1469 extension_id, &data_size, &ext_props.info);
1470 if (data_size == sizeof(VkExtensionProperties) && res == VK_SUCCESS) {
1471 ext_props.hosted = false;
1472 ext_props.origin = VK_EXTENSION_ORIGIN_ICD;
1473 ext_props.lib_name = icd->scanned_icds->lib_name;
1474 loader_add_to_ext_list(&icd->device_extension_cache[i], 1, &ext_props);
1475 }
1476 }
1477
1478 // Traverse layers list adding non-duplicate extensions to the list
1479 for (uint32_t l = 0; l < loader.scanned_layer_count; l++) {
1480 get_physical_device_layer_extensions(ptr_instance, gpus[i], l, &icd->device_extension_cache[i]);
1481 }
1482 }
1483 }
1484
1485 if (res != VK_SUCCESS) {
1486 /* clean up any extension lists previously created before this request failed */
1487 for (uint32_t j = 0; j < i; j++) {
1488 loader_destroy_ext_list(&icd->device_extension_cache[i]);
1489 }
1490 return res;
1491 }
1492 }
1493
1494 count += n;
1495 }
1496
1497 icd = icd->next;
1498 }
1499
1500 return VK_SUCCESS;
1501}
1502
Jon Ashburn27cd5842015-05-12 17:26:48 -06001503VkResult loader_EnumeratePhysicalDevices(
Courtney Goeltzenleuchter5e41f1d2015-04-20 12:48:54 -06001504 VkInstance instance,
1505 uint32_t* pPhysicalDeviceCount,
1506 VkPhysicalDevice* pPhysicalDevices)
Jon Ashburn1beab2d2015-01-26 14:51:40 -07001507{
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001508 uint32_t index = 0;
Jon Ashburn4c392fb2015-01-28 19:57:09 -07001509 struct loader_instance *ptr_instance = (struct loader_instance *) instance;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001510 struct loader_icd *icd = ptr_instance->icds;
Jon Ashburn4c392fb2015-01-28 19:57:09 -07001511
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001512 /* TODO: How do we only do this once? */
1513 if (ptr_instance->total_gpu_count == 0) {
1514 loader_init_physical_device_info(ptr_instance);
Jon Ashburn4c392fb2015-01-28 19:57:09 -07001515 }
1516
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001517 *pPhysicalDeviceCount = ptr_instance->total_gpu_count;
1518 if (!pPhysicalDevices) {
1519 return VK_SUCCESS;
1520 }
Jon Ashburn4c392fb2015-01-28 19:57:09 -07001521
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001522 while (icd) {
1523 assert((index + icd->gpu_count) <= *pPhysicalDeviceCount);
1524 for (uint32_t i = 0; i < icd->gpu_count; i++) {
1525 memcpy(&pPhysicalDevices[index], &icd->gpus[i].baseObject, sizeof(VkPhysicalDevice));
1526 }
1527 index += icd->gpu_count;
1528 icd = icd->next;
1529 }
1530
1531 return VK_SUCCESS;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07001532}
1533
Jon Ashburn3da71f22015-05-14 12:43:38 -06001534VkResult loader_GetPhysicalDeviceInfo(
1535 VkPhysicalDevice gpu,
1536 VkPhysicalDeviceInfoType infoType,
1537 size_t* pDataSize,
1538 void* pData)
1539{
1540 uint32_t gpu_index;
1541 struct loader_icd *icd = loader_get_icd((const VkBaseLayerObject *) gpu, &gpu_index);
1542 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
1543
1544 if (icd->GetPhysicalDeviceInfo)
1545 res = icd->GetPhysicalDeviceInfo(gpu, infoType, pDataSize, pData);
1546
1547 return res;
1548}
1549
Jon Ashburn95a77ba2015-05-15 15:09:35 -06001550VkResult loader_CreateDevice(
1551 VkPhysicalDevice gpu,
1552 const VkDeviceCreateInfo* pCreateInfo,
1553 VkDevice* pDevice)
1554{
1555 uint32_t gpu_index;
1556 struct loader_icd *icd = loader_get_icd((const VkBaseLayerObject *) gpu, &gpu_index);
1557 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
Jon Ashburn95a77ba2015-05-15 15:09:35 -06001558
Jon Ashburn95a77ba2015-05-15 15:09:35 -06001559 if (icd->CreateDevice) {
1560 res = icd->CreateDevice(gpu, pCreateInfo, pDevice);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001561 if (res != VK_SUCCESS) {
1562 return res;
Jon Ashburn95a77ba2015-05-15 15:09:35 -06001563 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001564
1565 VkLayerDispatchTable *dev_disp = icd->loader_dispatch + gpu_index;
1566 loader_init_dispatch(*pDevice, dev_disp);
1567
1568 icd->app_extension_count[gpu_index] = pCreateInfo->extensionCount;
1569 icd->app_extension_props[gpu_index] = (VkExtensionProperties *) malloc(sizeof(VkExtensionProperties) * pCreateInfo->extensionCount);
1570 if (icd->app_extension_props[gpu_index] == NULL && (icd->app_extension_count[gpu_index] > 0)) {
1571 return VK_ERROR_OUT_OF_HOST_MEMORY;
1572 }
1573
1574 /* Make local copy of extension list */
1575 if (icd->app_extension_count[gpu_index] > 0 && icd->app_extension_props[gpu_index] != NULL) {
1576 memcpy(icd->app_extension_props[gpu_index], pCreateInfo->pEnabledExtensions, sizeof(VkExtensionProperties) * pCreateInfo->extensionCount);
1577 }
1578
1579 // TODO: Add dependency check here.
1580
1581 loader_enable_device_layers(icd, gpu_index);
1582
Jon Ashburn95a77ba2015-05-15 15:09:35 -06001583 //TODO fix this extension parameters once support GetDeviceExtensionInfo()
1584 // don't know which instance we are on with this call
1585
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001586 loader_activate_device_layers(*pDevice, icd, gpu_index,
1587 icd->app_extension_count[gpu_index],
1588 icd->app_extension_props[gpu_index]);
Jon Ashburn95a77ba2015-05-15 15:09:35 -06001589 }
1590
1591 return res;
1592}
1593
Jon Ashburnb0fbe912015-05-06 10:15:07 -06001594LOADER_EXPORT void * VKAPI vkGetInstanceProcAddr(VkInstance instance, const char * pName)
1595{
Jon Ashburn07daee72015-05-21 18:13:33 -06001596 if (instance == VK_NULL_HANDLE)
1597 return NULL;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001598
Jon Ashburn07daee72015-05-21 18:13:33 -06001599 void *addr;
1600 /* get entrypoint addresses that are global (in the loader)*/
1601 addr = globalGetProcAddr(pName);
1602 if (addr)
1603 return addr;
Jon Ashburnb0fbe912015-05-06 10:15:07 -06001604
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001605 struct loader_instance *ptr_instance = (struct loader_instance *) instance;
1606
1607 addr = debug_report_instance_gpa(ptr_instance, pName);
1608 if (addr) {
1609 return addr;
1610 }
1611
Jon Ashburn07daee72015-05-21 18:13:33 -06001612 /* return any extension global entrypoints */
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001613 addr = wsi_lunarg_GetInstanceProcAddr(instance, pName);
Jon Ashburn07daee72015-05-21 18:13:33 -06001614 if (addr)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001615 return (ptr_instance->wsi_lunarg_enabled) ? addr : NULL;
Jon Ashburn07daee72015-05-21 18:13:33 -06001616
1617 /* return the instance dispatch table entrypoint for extensions */
1618 const VkLayerInstanceDispatchTable *disp_table = * (VkLayerInstanceDispatchTable **) instance;
1619 if (disp_table == NULL)
1620 return NULL;
1621
1622 addr = loader_lookup_instance_dispatch_table(disp_table, pName);
1623 if (addr)
1624 return addr;
Jon Ashburnb0fbe912015-05-06 10:15:07 -06001625
1626 return NULL;
1627}
1628
Jon Ashburn8d1b0b52015-05-18 13:20:15 -06001629LOADER_EXPORT void * VKAPI vkGetDeviceProcAddr(VkDevice device, const char * pName)
Jon Ashburn1beab2d2015-01-26 14:51:40 -07001630{
Jon Ashburn8d1b0b52015-05-18 13:20:15 -06001631 if (device == VK_NULL_HANDLE) {
1632 return NULL;
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001633 }
Jon Ashburn3d526cb2015-04-13 18:10:06 -06001634
Chia-I Wuf46b81a2015-01-04 11:12:47 +08001635 void *addr;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001636
Jon Ashburn3d526cb2015-04-13 18:10:06 -06001637 /* for entrypoints that loader must handle (ie non-dispatchable or create object)
1638 make sure the loader entrypoint is returned */
1639 addr = loader_non_passthrough_gpa(pName);
Ian Elliotte19c9152015-04-15 12:53:19 -06001640 if (addr) {
Jon Ashburn3d526cb2015-04-13 18:10:06 -06001641 return addr;
Ian Elliotte19c9152015-04-15 12:53:19 -06001642 }
Jon Ashburn3d526cb2015-04-13 18:10:06 -06001643
Jon Ashburn07daee72015-05-21 18:13:33 -06001644 /* return any extension device entrypoints the loader knows about */
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001645 addr = wsi_lunarg_GetDeviceProcAddr(device, pName);
1646 /* TODO: Where does device wsi_enabled go? */
Jon Ashburn07daee72015-05-21 18:13:33 -06001647 if (addr)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001648 return addr;
Jon Ashburn07daee72015-05-21 18:13:33 -06001649
Jon Ashburn3d526cb2015-04-13 18:10:06 -06001650 /* return the dispatch table entrypoint for the fastest case */
Jon Ashburn8d1b0b52015-05-18 13:20:15 -06001651 const VkLayerDispatchTable *disp_table = * (VkLayerDispatchTable **) device;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001652 if (disp_table == NULL)
1653 return NULL;
1654
Jon Ashburn27cd5842015-05-12 17:26:48 -06001655 addr = loader_lookup_device_dispatch_table(disp_table, pName);
Chia-I Wuf46b81a2015-01-04 11:12:47 +08001656 if (addr)
1657 return addr;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001658 else {
Jon Ashburn8d1b0b52015-05-18 13:20:15 -06001659 if (disp_table->GetDeviceProcAddr == NULL)
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001660 return NULL;
Jon Ashburn8d1b0b52015-05-18 13:20:15 -06001661 return disp_table->GetDeviceProcAddr(device, pName);
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001662 }
1663}
1664
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001665//TODO make sure createInstance enables extensions that are valid (loader does)
1666//TODO make sure CreateDevice enables extensions that are valid (left for layers/drivers to do)
1667
1668//TODO how is layer extension going to be enabled?
1669//Need to call createInstance on the layer or something
1670
Jon Ashburneceb13e2015-05-18 15:28:32 -06001671LOADER_EXPORT VkResult VKAPI vkGetGlobalExtensionInfo(
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001672 VkExtensionInfoType infoType,
1673 uint32_t extensionIndex,
1674 size_t* pDataSize,
1675 void* pData)
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07001676{
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001677 uint32_t *count;
1678 /* Scan/discover all ICD libraries in a single-threaded manner */
1679 loader_platform_thread_once(&once_icd, loader_icd_scan);
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07001680
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001681 /* get layer libraries in a single-threaded manner */
1682 loader_platform_thread_once(&once_layer, layer_lib_scan);
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07001683
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001684 /* merge any duplicate extensions */
1685 loader_platform_thread_once(&once_exts, loader_coalesce_extensions);
1686
1687
1688 if (pDataSize == NULL)
1689 return VK_ERROR_INVALID_POINTER;
1690
1691 switch (infoType) {
1692 case VK_EXTENSION_INFO_TYPE_COUNT:
1693 *pDataSize = sizeof(uint32_t);
1694 if (pData == NULL)
1695 return VK_SUCCESS;
1696 count = (uint32_t *) pData;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001697 *count = loader.global_extensions.count;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001698 break;
1699 case VK_EXTENSION_INFO_TYPE_PROPERTIES:
1700 *pDataSize = sizeof(VkExtensionProperties);
1701 if (pData == NULL)
1702 return VK_SUCCESS;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001703 if (extensionIndex >= loader.global_extensions.count)
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001704 return VK_ERROR_INVALID_VALUE;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001705 memcpy((VkExtensionProperties *) pData,
1706 &loader.global_extensions.list[extensionIndex],
1707 sizeof(VkExtensionProperties));
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001708 break;
1709 default:
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001710 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Invalid infoType in vkGetGlobalExtensionInfo");
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001711 return VK_ERROR_INVALID_VALUE;
1712 };
1713
1714 return VK_SUCCESS;
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07001715}
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001716
1717LOADER_EXPORT VkResult VKAPI vkGetPhysicalDeviceExtensionInfo(
Jon Ashburn95a77ba2015-05-15 15:09:35 -06001718 VkPhysicalDevice gpu,
1719 VkExtensionInfoType infoType,
1720 uint32_t extensionIndex,
1721 size_t* pDataSize,
1722 void* pData)
1723{
1724 uint32_t gpu_index;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001725 uint32_t *count;
Jon Ashburn95a77ba2015-05-15 15:09:35 -06001726 struct loader_icd *icd = loader_get_icd((const VkBaseLayerObject *) gpu, &gpu_index);
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07001727
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001728 if (pDataSize == NULL)
1729 return VK_ERROR_INVALID_POINTER;
Jon Ashburn95a77ba2015-05-15 15:09:35 -06001730
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001731 switch (infoType) {
1732 case VK_EXTENSION_INFO_TYPE_COUNT:
1733 *pDataSize = sizeof(uint32_t);
1734 if (pData == NULL)
1735 return VK_SUCCESS;
1736 count = (uint32_t *) pData;
1737 *count = icd->device_extension_cache[gpu_index].count;
1738 break;
1739 case VK_EXTENSION_INFO_TYPE_PROPERTIES:
1740 *pDataSize = sizeof(VkExtensionProperties);
1741 if (pData == NULL)
1742 return VK_SUCCESS;
1743 if (extensionIndex >= icd->device_extension_cache[gpu_index].count)
1744 return VK_ERROR_INVALID_VALUE;
1745 memcpy((VkExtensionProperties *) pData,
1746 &icd->device_extension_cache[gpu_index].list[extensionIndex],
1747 sizeof(VkExtensionProperties));
1748 break;
1749 default:
1750 return VK_ERROR_INVALID_VALUE;
1751 };
1752
1753 return VK_SUCCESS;
Jon Ashburn95a77ba2015-05-15 15:09:35 -06001754}
1755
Jon Ashburn95a77ba2015-05-15 15:09:35 -06001756VkResult loader_GetMultiDeviceCompatibility(
1757 VkPhysicalDevice gpu0,
1758 VkPhysicalDevice gpu1,
1759 VkPhysicalDeviceCompatibilityInfo* pInfo)
1760{
1761 uint32_t gpu_index;
1762 struct loader_icd *icd = loader_get_icd((const VkBaseLayerObject *) gpu0, &gpu_index);
1763 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
1764
1765 if (icd->GetMultiDeviceCompatibility)
1766 res = icd->GetMultiDeviceCompatibility(gpu0, gpu1, pInfo);
1767
1768 return res;
1769}