blob: c958d82976d613728aa59e9a00b6a2e3860eb778 [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
Courtney Goeltzenleuchtered488302015-06-01 14:09:34 -060059static loader_platform_dl_handle loader_add_layer_lib(
60 const char *chain_type,
61 struct loader_extension_property *ext_prop);
62
63static void loader_remove_layer_lib(
64 struct loader_instance *inst,
65 struct loader_extension_property *ext_prop);
66
Jon Ashburn27cd5842015-05-12 17:26:48 -060067struct loader_struct loader = {0};
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080068
Courtney Goeltzenleuchter9ec39ac2015-06-22 17:45:21 -060069static void * VKAPI loader_GetInstanceProcAddr(VkInstance instance, const char * pName);
70
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -060071enum loader_debug {
72 LOADER_INFO_BIT = VK_BIT(0),
73 LOADER_WARN_BIT = VK_BIT(1),
74 LOADER_PERF_BIT = VK_BIT(2),
75 LOADER_ERROR_BIT = VK_BIT(3),
76 LOADER_DEBUG_BIT = VK_BIT(4),
77};
78
79uint32_t g_loader_debug = 0;
80uint32_t g_loader_log_msgs = 0;
81
Jon Ashburn6301a0f2015-05-29 13:15:39 -060082//thread safety lock for accessing global data structures such as "loader"
83// all entrypoints on the instance chain need to be locked except GPA
84// additionally DestroyDevice needs to be locked
85loader_platform_thread_mutex loader_lock;
86
87const VkLayerInstanceDispatchTable instance_disp = {
Courtney Goeltzenleuchter9ec39ac2015-06-22 17:45:21 -060088 .GetInstanceProcAddr = loader_GetInstanceProcAddr,
Jon Ashburn27cd5842015-05-12 17:26:48 -060089 .CreateInstance = loader_CreateInstance,
90 .DestroyInstance = loader_DestroyInstance,
91 .EnumeratePhysicalDevices = loader_EnumeratePhysicalDevices,
Chris Forbesbc0bb772015-06-21 22:55:02 +120092 .GetPhysicalDeviceFeatures = loader_GetPhysicalDeviceFeatures,
93 .GetPhysicalDeviceFormatInfo = loader_GetPhysicalDeviceFormatInfo,
94 .GetPhysicalDeviceLimits = loader_GetPhysicalDeviceLimits,
Jon Ashburn95a77ba2015-05-15 15:09:35 -060095 .CreateDevice = loader_CreateDevice,
Tony Barbour59a47322015-06-24 16:06:58 -060096 .GetPhysicalDeviceProperties = loader_GetPhysicalDeviceProperties,
97 .GetPhysicalDevicePerformance = loader_GetPhysicalDevicePerformance,
98 .GetPhysicalDeviceQueueCount = loader_GetPhysicalDeviceQueueCount,
99 .GetPhysicalDeviceQueueProperties = loader_GetPhysicalDeviceQueueProperties,
100 .GetPhysicalDeviceMemoryProperties = loader_GetPhysicalDeviceMemoryProperties,
101 .GetPhysicalDeviceExtensionCount = loader_GetPhysicalDeviceExtensionCount,
102 .GetPhysicalDeviceExtensionProperties = loader_GetPhysicalDeviceExtensionProperties,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600103 .DbgCreateMsgCallback = loader_DbgCreateMsgCallback,
104 .DbgDestroyMsgCallback = loader_DbgDestroyMsgCallback,
Jon Ashburn27cd5842015-05-12 17:26:48 -0600105};
106
107LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_icd);
108LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_layer);
109LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_exts);
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700110
Ian Elliott4470a302015-02-17 10:33:47 -0700111#if defined(WIN32)
Ian Elliott5aa4ea22015-03-31 15:32:41 -0600112char *loader_get_registry_string(const HKEY hive,
113 const LPCTSTR sub_key,
114 const char *value)
115{
116 DWORD access_flags = KEY_QUERY_VALUE;
117 DWORD value_type;
118 HKEY key;
Ian Elliottf851ddf2015-04-28 15:57:32 -0600119 VkResult rtn_value;
Ian Elliott5aa4ea22015-03-31 15:32:41 -0600120 char *rtn_str = NULL;
Tony Barbour18f71552015-04-22 11:36:22 -0600121 DWORD rtn_len = 0;
Ian Elliott5aa4ea22015-03-31 15:32:41 -0600122 size_t allocated_len = 0;
123
124 rtn_value = RegOpenKeyEx(hive, sub_key, 0, access_flags, &key);
125 if (rtn_value != ERROR_SUCCESS) {
126 // We didn't find the key. Try the 32-bit hive (where we've seen the
127 // key end up on some people's systems):
128 access_flags |= KEY_WOW64_32KEY;
129 rtn_value = RegOpenKeyEx(hive, sub_key, 0, access_flags, &key);
130 if (rtn_value != ERROR_SUCCESS) {
131 // We still couldn't find the key, so give up:
132 return NULL;
133 }
134 }
135
136 rtn_value = RegQueryValueEx(key, value, NULL, &value_type,
Ian Elliottf851ddf2015-04-28 15:57:32 -0600137 (PVOID) rtn_str, (LPDWORD) &rtn_len);
Ian Elliott5aa4ea22015-03-31 15:32:41 -0600138 if (rtn_value == ERROR_SUCCESS) {
139 // If we get to here, we found the key, and need to allocate memory
140 // large enough for rtn_str, and query again:
141 allocated_len = rtn_len + 4;
142 rtn_str = malloc(allocated_len);
143 rtn_value = RegQueryValueEx(key, value, NULL, &value_type,
Ian Elliottf851ddf2015-04-28 15:57:32 -0600144 (PVOID) rtn_str, (LPDWORD) &rtn_len);
Ian Elliott5aa4ea22015-03-31 15:32:41 -0600145 if (rtn_value == ERROR_SUCCESS) {
146 // We added 4 extra bytes to rtn_str, so that we can ensure that
147 // the string is NULL-terminated (albeit, in a brute-force manner):
148 rtn_str[allocated_len-1] = '\0';
149 } else {
150 // This should never occur, but in case it does, clean up:
151 free(rtn_str);
152 rtn_str = NULL;
153 }
154 } // else - shouldn't happen, but if it does, return rtn_str, which is NULL
155
156 // Close the registry key that was opened:
157 RegCloseKey(key);
158
159 return rtn_str;
160}
161
162
Ian Elliott4470a302015-02-17 10:33:47 -0700163// For ICD developers, look in the registry, and look for an environment
164// variable for a path(s) where to find the ICD(s):
165static char *loader_get_registry_and_env(const char *env_var,
166 const char *registry_value)
167{
168 char *env_str = getenv(env_var);
169 size_t env_len = (env_str == NULL) ? 0 : strlen(env_str);
Ian Elliott5aa4ea22015-03-31 15:32:41 -0600170 char *registry_str = NULL;
Tony Barbour18f71552015-04-22 11:36:22 -0600171 size_t registry_len = 0;
Ian Elliott4470a302015-02-17 10:33:47 -0700172 char *rtn_str = NULL;
173 size_t rtn_len;
174
Ian Elliott5aa4ea22015-03-31 15:32:41 -0600175 registry_str = loader_get_registry_string(HKEY_LOCAL_MACHINE,
Ian Elliott06ebd752015-04-09 18:07:15 -0600176 "Software\\Vulkan",
Ian Elliott5aa4ea22015-03-31 15:32:41 -0600177 registry_value);
Ian Elliottf851ddf2015-04-28 15:57:32 -0600178 registry_len = (registry_str) ? (DWORD) strlen(registry_str) : 0;
Ian Elliott4470a302015-02-17 10:33:47 -0700179
180 rtn_len = env_len + registry_len + 1;
181 if (rtn_len <= 2) {
182 // We found neither the desired registry value, nor the environment
183 // variable; return NULL:
184 return NULL;
185 } else {
186 // We found something, and so we need to allocate memory for the string
187 // to return:
188 rtn_str = malloc(rtn_len);
189 }
190
Ian Elliott5aa4ea22015-03-31 15:32:41 -0600191 if (registry_len == 0) {
Ian Elliott4470a302015-02-17 10:33:47 -0700192 // We didn't find the desired registry value, and so we must have found
193 // only the environment variable:
194 _snprintf(rtn_str, rtn_len, "%s", env_str);
195 } else if (env_str != NULL) {
196 // We found both the desired registry value and the environment
197 // variable, so concatenate them both:
198 _snprintf(rtn_str, rtn_len, "%s;%s", registry_str, env_str);
199 } else {
200 // We must have only found the desired registry value:
201 _snprintf(rtn_str, rtn_len, "%s", registry_str);
202 }
203
Ian Elliott2de26bc2015-04-03 13:13:01 -0600204 if (registry_str) {
205 free(registry_str);
206 }
Ian Elliott4470a302015-02-17 10:33:47 -0700207
208 return(rtn_str);
209}
210#endif // WIN32
211
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600212static void loader_log(VkFlags msg_type, int32_t msg_code,
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800213 const char *format, ...)
214{
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800215 char msg[256];
216 va_list ap;
217 int ret;
218
Courtney Goeltzenleuchtera585ecb2015-06-09 09:42:23 -0600219 if (!(msg_type & g_loader_log_msgs)) {
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -0600220 return;
221 }
222
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800223 va_start(ap, format);
224 ret = vsnprintf(msg, sizeof(msg), format, ap);
Ian Elliott42045842015-02-13 14:29:21 -0700225 if ((ret >= (int) sizeof(msg)) || ret < 0) {
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800226 msg[sizeof(msg) - 1] = '\0';
227 }
228 va_end(ap);
229
Jon Ashburnae053e92015-04-24 14:10:50 -0700230#if defined(WIN32)
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -0600231 OutputDebugString(msg);
Jon Ashburn1de39402015-05-05 16:20:46 -0600232#endif
Courtney Goeltzenleuchterc80a5572015-04-13 14:10:06 -0600233 fputs(msg, stderr);
234 fputc('\n', stderr);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800235}
236
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600237bool compare_vk_extension_properties(const VkExtensionProperties *op1, const VkExtensionProperties *op2)
238{
239 return memcmp(op1, op2, sizeof(VkExtensionProperties)) == 0 ? true : false;
240}
241
242/*
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600243 * Search the given ext_list for an extension
244 * matching the given vk_ext_prop
245 */
246bool has_vk_extension_property(
247 const VkExtensionProperties *vk_ext_prop,
248 const struct loader_extension_list *ext_list)
249{
250 for (uint32_t i = 0; i < ext_list->count; i++) {
251 if (compare_vk_extension_properties(&ext_list->list[i].info, vk_ext_prop))
252 return true;
253 }
254 return false;
255}
256
257/*
258 * Search the given ext_list for an extension
259 * matching the given vk_ext_prop
260 */
261static struct loader_extension_property *get_extension_property_from_vkext(
262 const VkExtensionProperties *vk_ext_prop,
263 const struct loader_extension_list *ext_list)
264{
265 for (uint32_t i = 0; i < ext_list->count; i++) {
Courtney Goeltzenleuchter509e9732015-06-25 16:26:55 -0600266 const VkExtensionProperties *item = &ext_list->list[i].info;
267 if (compare_vk_extension_properties(item, vk_ext_prop))
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600268 return &ext_list->list[i];
269 }
270 return NULL;
271}
272
Jon Ashburn953bb3c2015-06-10 16:11:42 -0600273static void loader_get_global_extensions(
Tony Barbour59a47322015-06-24 16:06:58 -0600274 const PFN_vkGetGlobalExtensionCount fp_get_count,
275 const PFN_vkGetGlobalExtensionProperties fp_get_props,
Jon Ashburn953bb3c2015-06-10 16:11:42 -0600276 const PFN_vkGPA get_proc_addr,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600277 const char *lib_name,
Jon Ashburn953bb3c2015-06-10 16:11:42 -0600278 const loader_platform_dl_handle lib_handle,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600279 const enum extension_origin origin,
280 struct loader_extension_list *ext_list)
281{
282 uint32_t i, count;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600283 struct loader_extension_property ext_props;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600284 VkResult res;
Jon Ashburn953bb3c2015-06-10 16:11:42 -0600285 PFN_vkGPA ext_get_proc_addr;
286 PFN_vkGetInstanceProcAddr get_instance_proc_addr;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600287
Tony Barbour59a47322015-06-24 16:06:58 -0600288 res = fp_get_count(&count);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600289 if (res != VK_SUCCESS) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600290 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Error getting global extension count from ICD");
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600291 return;
292 }
Jon Ashburn953bb3c2015-06-10 16:11:42 -0600293
294 if (get_proc_addr == NULL)
295 get_instance_proc_addr = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetInstanceProcAddr");
Tony Barbour59a47322015-06-24 16:06:58 -0600296
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600297 for (i = 0; i < count; i++) {
Courtney Goeltzenleuchter0f1d8eb2015-06-07 17:28:17 -0600298 memset(&ext_props, 0, sizeof(ext_props));
Tony Barbour59a47322015-06-24 16:06:58 -0600299 res = fp_get_props(i, &ext_props.info);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600300 if (res == VK_SUCCESS) {
Jon Ashburn953bb3c2015-06-10 16:11:42 -0600301 //TODO eventually get this from the layer config file
302 if (get_proc_addr == NULL) {
303 char funcStr[MAX_EXTENSION_NAME_SIZE+1];
304 snprintf(funcStr, MAX_EXTENSION_NAME_SIZE, "%sGetInstanceProcAddr", ext_props.info.name);
305
306 if ((ext_get_proc_addr = (PFN_vkGPA) loader_platform_get_proc_address(lib_handle, funcStr)) == NULL)
307 ext_get_proc_addr = get_instance_proc_addr;
308 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600309 ext_props.origin = origin;
310 ext_props.lib_name = lib_name;
Courtney Goeltzenleuchter509e9732015-06-25 16:26:55 -0600311 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
312 "Global Extension: %s: %s", ext_props.info.name, ext_props.info.description);
Jon Ashburn953bb3c2015-06-10 16:11:42 -0600313 ext_props.get_proc_addr = (get_proc_addr == NULL) ? ext_get_proc_addr : get_proc_addr;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600314 loader_add_to_ext_list(ext_list, 1, &ext_props);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600315 }
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600316 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600317
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600318 return;
319}
320
Jon Ashburn953bb3c2015-06-10 16:11:42 -0600321static void loader_get_physical_device_layer_extensions(
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600322 struct loader_instance *ptr_instance,
323 VkPhysicalDevice physical_device,
324 const uint32_t layer_index,
325 struct loader_extension_list *ext_list)
326{
327 uint32_t i, count;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600328 VkResult res;
329 loader_platform_dl_handle lib_handle;
Tony Barbour59a47322015-06-24 16:06:58 -0600330 PFN_vkGetPhysicalDeviceExtensionProperties get_phys_dev_ext_props;
331 PFN_vkGetPhysicalDeviceExtensionCount get_phys_dev_ext_count;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600332 struct loader_extension_property ext_props;
Jon Ashburn953bb3c2015-06-10 16:11:42 -0600333 PFN_vkGPA ext_get_proc_addr;
334 PFN_vkGetDeviceProcAddr get_device_proc_addr;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600335
336 if (!loader.scanned_layers[layer_index].physical_device_extensions_supported) {
337 return;
338 }
339
340 ext_props.origin = VK_EXTENSION_ORIGIN_LAYER;
341 ext_props.lib_name = loader.scanned_layers[layer_index].lib_name;
Jon Ashburn128f9422015-05-28 19:16:58 -0600342 char funcStr[MAX_EXTENSION_NAME_SIZE+1]; // add one character for 0 termination
Jon Ashburn953bb3c2015-06-10 16:11:42 -0600343
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600344 lib_handle = loader_add_layer_lib("device", &ext_props);
Courtney Goeltzenleuchter0f1d8eb2015-06-07 17:28:17 -0600345
Tony Barbour59a47322015-06-24 16:06:58 -0600346 get_phys_dev_ext_props = (PFN_vkGetPhysicalDeviceExtensionProperties) loader_platform_get_proc_address(lib_handle, "vkGetPhysicalDeviceExtensionProperties");
347 get_phys_dev_ext_count = (PFN_vkGetPhysicalDeviceExtensionCount) loader_platform_get_proc_address(lib_handle, "vkGetPhysicalDeviceExtensionCount");
Jon Ashburn953bb3c2015-06-10 16:11:42 -0600348 get_device_proc_addr = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetDeviceProcAddr");
Tony Barbour59a47322015-06-24 16:06:58 -0600349 if (get_phys_dev_ext_count) {
350 res = get_phys_dev_ext_count(physical_device, &count);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600351 if (res == VK_SUCCESS) {
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600352 for (i = 0; i < count; i++) {
353 memset(&ext_props, 0, sizeof(ext_props));
Tony Barbour59a47322015-06-24 16:06:58 -0600354 res = get_phys_dev_ext_props(physical_device, i, &ext_props.info);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600355 if (res == VK_SUCCESS && (ext_props.info.sType == VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES)) {
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600356 ext_props.origin = VK_EXTENSION_ORIGIN_LAYER;
Jon Ashburn953bb3c2015-06-10 16:11:42 -0600357 //TODO eventually get this from the layer config file
358 snprintf(funcStr, MAX_EXTENSION_NAME_SIZE, "%sGetDeviceProcAddr", ext_props.info.name);
359
360 if ((ext_get_proc_addr = (PFN_vkGPA) loader_platform_get_proc_address(lib_handle, funcStr)) == NULL)
361 ext_get_proc_addr = get_device_proc_addr;
362 ext_props.get_proc_addr = ext_get_proc_addr;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600363 ext_props.lib_name = loader.scanned_layers[layer_index].lib_name;
Courtney Goeltzenleuchter509e9732015-06-25 16:26:55 -0600364 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
365 "PhysicalDevice Extension: %s: %s", ext_props.info.name, ext_props.info.description);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600366 loader_add_to_ext_list(ext_list, 1, &ext_props);
367 }
368 }
369 } else {
370 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Error getting physical device extension info count from Layer %s", ext_props.lib_name);
371 }
372 }
373
374 loader_remove_layer_lib(ptr_instance, &ext_props);
375 return;
376}
377
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600378static bool loader_init_ext_list(struct loader_extension_list *ext_info)
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600379{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600380 ext_info->capacity = 32 * sizeof(struct loader_extension_property);
381 ext_info->list = malloc(ext_info->capacity);
382 if (ext_info->list == NULL) {
383 return false;
384 }
385 memset(ext_info->list, 0, ext_info->capacity);
386 ext_info->count = 0;
387 return true;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600388}
389
Courtney Goeltzenleuchter7d0023c2015-06-08 15:09:22 -0600390void loader_destroy_ext_list(struct loader_extension_list *ext_info)
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600391{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600392 free(ext_info->list);
393 ext_info->count = 0;
394 ext_info->capacity = 0;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600395}
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600396
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600397static void loader_add_vk_ext_to_ext_list(
398 struct loader_extension_list *ext_list,
399 uint32_t prop_list_count,
400 const VkExtensionProperties *props,
401 const struct loader_extension_list *search_list)
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600402{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600403 struct loader_extension_property *ext_prop;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600404
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600405 for (uint32_t i = 0; i < prop_list_count; i++) {
Courtney Goeltzenleuchter509e9732015-06-25 16:26:55 -0600406 const VkExtensionProperties *search_target = &props[i];
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600407 // look for duplicates
Courtney Goeltzenleuchter509e9732015-06-25 16:26:55 -0600408 if (has_vk_extension_property(search_target, ext_list)) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600409 continue;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600410 }
411
Courtney Goeltzenleuchter509e9732015-06-25 16:26:55 -0600412 ext_prop = get_extension_property_from_vkext(search_target, search_list);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600413 if (!ext_prop) {
Courtney Goeltzenleuchter509e9732015-06-25 16:26:55 -0600414 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Unable to find extension %s", search_target->name);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600415 continue;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600416 }
417
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600418 loader_add_to_ext_list(ext_list, 1, ext_prop);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600419 }
420}
421
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600422/*
423 * Append non-duplicate extension properties defined in prop_list
424 * to the given ext_info list
425 */
426void loader_add_to_ext_list(
427 struct loader_extension_list *ext_list,
428 uint32_t prop_list_count,
429 const struct loader_extension_property *props)
430{
431 uint32_t i;
432 struct loader_extension_property *cur_ext;
433
434 if (ext_list->list == NULL || ext_list->capacity == 0) {
435 loader_init_ext_list(ext_list);
436 }
437
438 if (ext_list->list == NULL)
439 return;
440
441 for (i = 0; i < prop_list_count; i++) {
442 cur_ext = (struct loader_extension_property *) &props[i];
443
444 // look for duplicates
445 if (has_vk_extension_property(&cur_ext->info, ext_list)) {
446 continue;
447 }
448
449 // add to list at end
450 // check for enough capacity
451 if (ext_list->count * sizeof(struct loader_extension_property)
452 >= ext_list->capacity) {
453 // double capacity
454 ext_list->capacity *= 2;
455 ext_list->list = realloc(ext_list->list, ext_list->capacity);
456 }
Courtney Goeltzenleuchter0f1d8eb2015-06-07 17:28:17 -0600457
458 /*
459 * Check if any extensions already on the list come from the same
Jon Ashburn953bb3c2015-06-10 16:11:42 -0600460 * library and use the same Get*ProcAddr. If so, link this
Courtney Goeltzenleuchter0f1d8eb2015-06-07 17:28:17 -0600461 * extension to the previous as an alias. That way when we activate
462 * extensions we only activiate the associated layer once no
463 * matter how many extensions are used.
464 */
465 for (uint32_t j = 0; j < ext_list->count; j++) {
466 struct loader_extension_property *active_property = &ext_list->list[j];
467 if (cur_ext->lib_name &&
468 cur_ext->origin == VK_EXTENSION_ORIGIN_LAYER &&
469 active_property->origin == VK_EXTENSION_ORIGIN_LAYER &&
470 strcmp(cur_ext->lib_name, active_property->lib_name) == 0 &&
Jon Ashburn953bb3c2015-06-10 16:11:42 -0600471 (cur_ext->get_proc_addr == active_property->get_proc_addr) &&
Courtney Goeltzenleuchter0f1d8eb2015-06-07 17:28:17 -0600472 active_property->alias == NULL) {
473 cur_ext->alias = active_property;
474 break;
475 }
476 }
477
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600478 memcpy(&ext_list->list[ext_list->count], cur_ext, sizeof(struct loader_extension_property));
479 ext_list->count++;
480 }
481}
482
483/*
484 * Search the search_list for any extension with
485 * a name that matches the given ext_name.
486 * Add all matching extensions to the found_list
487 * Do not add if found VkExtensionProperties is already
488 * on the found_list
489 */
490static void loader_search_ext_list_for_name(
491 const char *ext_name,
492 const struct loader_extension_list *search_list,
493 struct loader_extension_list *found_list)
494{
495 for (uint32_t i = 0; i < search_list->count; i++) {
496 struct loader_extension_property *ext_prop = &search_list->list[i];
Courtney Goeltzenleuchtera6743522015-06-09 09:14:48 -0600497 if (ext_prop->origin == VK_EXTENSION_ORIGIN_LAYER &&
498 0 == strcmp(ext_prop->info.name, ext_name)) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600499 /* Found an extension with the same name, add to found_list */
500 loader_add_to_ext_list(found_list, 1, &search_list->list[i]);
501 }
502 }
503}
504
505bool loader_is_extension_scanned(const VkExtensionProperties *ext_prop)
Jon Ashburnfc2e38c2015-04-14 09:15:32 -0600506{
507 uint32_t i;
508
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600509 for (i = 0; i < loader.global_extensions.count; i++) {
510 if (compare_vk_extension_properties(&loader.global_extensions.list[i].info, ext_prop))
Jon Ashburnfc2e38c2015-04-14 09:15:32 -0600511 return true;
512 }
513 return false;
514}
515
Jon Ashburn27cd5842015-05-12 17:26:48 -0600516void loader_coalesce_extensions(void)
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600517{
518 uint32_t i;
519 struct loader_scanned_icds *icd_list = loader.scanned_icd_list;
520
521 // traverse scanned icd list adding non-duplicate extensions to the list
522 while (icd_list != NULL) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600523 loader_add_to_ext_list(&loader.global_extensions,
524 icd_list->global_extension_list.count,
525 icd_list->global_extension_list.list);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600526 icd_list = icd_list->next;
527 };
528
529 //Traverse layers list adding non-duplicate extensions to the list
530 for (i = 0; i < loader.scanned_layer_count; i++) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600531 loader_add_to_ext_list(&loader.global_extensions,
532 loader.scanned_layers[i].global_extension_list.count,
533 loader.scanned_layers[i].global_extension_list.list);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600534 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600535
536 // Traverse loader's extensions, adding non-duplicate extensions to the list
537 debug_report_add_instance_extensions(&loader.global_extensions);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600538}
539
Jon Ashburndc6fcad2015-06-10 10:06:06 -0600540static struct loader_icd *loader_get_icd_and_device(const VkDevice device,
541 struct loader_device **found_dev)
542{
543 *found_dev = NULL;
544 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
545 for (struct loader_icd *icd = inst->icds; icd; icd = icd->next) {
546 for (struct loader_device *dev = icd->logical_device_list; dev; dev = dev->next)
547 if (dev->device == device) {
548 *found_dev = dev;
549 return icd;
550 }
551 }
552 }
553 return NULL;
554}
555
556static void loader_destroy_logical_device(struct loader_device *dev)
557{
558 free(dev->app_extension_props);
559 if (dev->enabled_device_extensions.count)
560 loader_destroy_ext_list(&dev->enabled_device_extensions);
561 if (dev->activated_layer_list.count)
562 loader_destroy_ext_list(&dev->activated_layer_list);
563 free(dev);
564}
565
566static struct loader_device *loader_add_logical_device(const VkDevice dev, struct loader_device **device_list)
567{
568 struct loader_device *new_dev;
569
570 new_dev = malloc(sizeof(struct loader_device));
571 if (!new_dev) {
572 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to malloc struct laoder-device");
573 return NULL;
574 }
575
576 memset(new_dev, 0, sizeof(struct loader_device));
577
578 new_dev->next = *device_list;
579 new_dev->device = dev;
580 *device_list = new_dev;
581 return new_dev;
582}
583
584void loader_remove_logical_device(VkDevice device)
585{
586 struct loader_device *found_dev, *dev, *prev_dev;
587 struct loader_icd *icd;
588 icd = loader_get_icd_and_device(device, &found_dev);
589
590 if (!icd || !found_dev)
591 return;
592
593 prev_dev = NULL;
594 dev = icd->logical_device_list;
595 while (dev && dev != found_dev) {
596 prev_dev = dev;
597 dev = dev->next;
598 }
599
600 if (prev_dev)
601 prev_dev->next = found_dev->next;
602 else
603 icd->logical_device_list = found_dev->next;
604 loader_destroy_logical_device(found_dev);
605}
606
607
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600608static void loader_icd_destroy(
609 struct loader_instance *ptr_inst,
610 struct loader_icd *icd)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800611{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600612 ptr_inst->total_icd_count--;
Jon Ashburn128f9422015-05-28 19:16:58 -0600613 free(icd->gpus);
Courtney Goeltzenleuchter1f157ac2015-06-14 19:57:15 -0600614 for (struct loader_device *dev = icd->logical_device_list; dev; ) {
615 struct loader_device *next_dev = dev->next;
Jon Ashburndc6fcad2015-06-10 10:06:06 -0600616 loader_destroy_logical_device(dev);
Courtney Goeltzenleuchter1f157ac2015-06-14 19:57:15 -0600617 dev = next_dev;
618 }
Jon Ashburndc6fcad2015-06-10 10:06:06 -0600619
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800620 free(icd);
621}
622
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600623static struct loader_icd * loader_icd_create(const struct loader_scanned_icds *scanned)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800624{
625 struct loader_icd *icd;
626
627 icd = malloc(sizeof(*icd));
628 if (!icd)
629 return NULL;
630
Courtney Goeltzenleuchter55001bb2014-10-28 10:29:27 -0600631 memset(icd, 0, sizeof(*icd));
632
Jon Ashburn46d1f582015-01-28 11:01:35 -0700633 icd->scanned_icds = scanned;
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800634
635 return icd;
636}
637
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600638static struct loader_icd *loader_icd_add(
639 struct loader_instance *ptr_inst,
640 const struct loader_scanned_icds *scanned)
Chia-I Wu13a61a52014-08-04 11:18:20 +0800641{
642 struct loader_icd *icd;
643
Jon Ashburn46d1f582015-01-28 11:01:35 -0700644 icd = loader_icd_create(scanned);
Chia-I Wu13a61a52014-08-04 11:18:20 +0800645 if (!icd)
646 return NULL;
647
Chia-I Wu13a61a52014-08-04 11:18:20 +0800648 /* prepend to the list */
Jon Ashburn46888392015-01-29 15:45:51 -0700649 icd->next = ptr_inst->icds;
650 ptr_inst->icds = icd;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600651 ptr_inst->total_icd_count++;
Chia-I Wu13a61a52014-08-04 11:18:20 +0800652
653 return icd;
654}
655
Jon Ashburn46d1f582015-01-28 11:01:35 -0700656static void loader_scanned_icd_add(const char *filename)
657{
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700658 loader_platform_dl_handle handle;
Jon Ashburn3da71f22015-05-14 12:43:38 -0600659 void *fp_create_inst;
Tony Barbour59a47322015-06-24 16:06:58 -0600660 void *fp_get_global_ext_props;
661 void *fp_get_global_ext_count;
662 void *fp_get_device_ext_props;
663 void *fp_get_device_ext_count;
Jon Ashburn953bb3c2015-06-10 16:11:42 -0600664 PFN_vkGPA fp_get_proc_addr;
Jon Ashburn46d1f582015-01-28 11:01:35 -0700665 struct loader_scanned_icds *new_node;
666
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700667 // Used to call: dlopen(filename, RTLD_LAZY);
668 handle = loader_platform_open_library(filename);
Jon Ashburn46d1f582015-01-28 11:01:35 -0700669 if (!handle) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600670 loader_log(VK_DBG_REPORT_WARN_BIT, 0, loader_platform_open_library_error(filename));
Jon Ashburn46d1f582015-01-28 11:01:35 -0700671 return;
672 }
673
674#define LOOKUP(func_ptr, func) do { \
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600675 func_ptr = (PFN_vk ##func) loader_platform_get_proc_address(handle, "vk" #func); \
Jon Ashburn46d1f582015-01-28 11:01:35 -0700676 if (!func_ptr) { \
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600677 loader_log(VK_DBG_REPORT_WARN_BIT, 0, loader_platform_get_proc_address_error("vk" #func)); \
Jon Ashburn46d1f582015-01-28 11:01:35 -0700678 return; \
679 } \
680} while (0)
681
Jon Ashburn46888392015-01-29 15:45:51 -0700682 LOOKUP(fp_create_inst, CreateInstance);
Tony Barbour59a47322015-06-24 16:06:58 -0600683 LOOKUP(fp_get_global_ext_props, GetGlobalExtensionProperties);
684 LOOKUP(fp_get_global_ext_count, GetGlobalExtensionCount);
685 LOOKUP(fp_get_device_ext_props, GetPhysicalDeviceExtensionProperties);
686 LOOKUP(fp_get_device_ext_count, GetPhysicalDeviceExtensionCount);
Jon Ashburn953bb3c2015-06-10 16:11:42 -0600687 LOOKUP(fp_get_proc_addr, GetDeviceProcAddr);
Jon Ashburn46d1f582015-01-28 11:01:35 -0700688#undef LOOKUP
689
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600690 new_node = (struct loader_scanned_icds *) malloc(sizeof(struct loader_scanned_icds)
691 + strlen(filename) + 1);
Jon Ashburn46d1f582015-01-28 11:01:35 -0700692 if (!new_node) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600693 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Out of memory can't add icd");
Jon Ashburn46d1f582015-01-28 11:01:35 -0700694 return;
695 }
696
697 new_node->handle = handle;
Jon Ashburn46888392015-01-29 15:45:51 -0700698 new_node->CreateInstance = fp_create_inst;
Tony Barbour59a47322015-06-24 16:06:58 -0600699 new_node->GetGlobalExtensionProperties = fp_get_global_ext_props;
700 new_node->GetGlobalExtensionCount = fp_get_global_ext_count;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600701 loader_init_ext_list(&new_node->global_extension_list);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600702 loader_init_ext_list(&new_node->device_extension_list);
Jon Ashburn46d1f582015-01-28 11:01:35 -0700703 new_node->next = loader.scanned_icd_list;
Jon Ashburn46d1f582015-01-28 11:01:35 -0700704
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600705 new_node->lib_name = (char *) (new_node + 1);
706 if (!new_node->lib_name) {
707 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Out of memory can't add icd");
708 return;
709 }
710 strcpy(new_node->lib_name, filename);
711
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600712 loader.scanned_icd_list = new_node;
713
Jon Ashburn953bb3c2015-06-10 16:11:42 -0600714 loader_get_global_extensions(
Tony Barbour59a47322015-06-24 16:06:58 -0600715 (PFN_vkGetGlobalExtensionCount) fp_get_global_ext_count,
716 (PFN_vkGetGlobalExtensionProperties) fp_get_global_ext_props,
Jon Ashburn953bb3c2015-06-10 16:11:42 -0600717 fp_get_proc_addr,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600718 new_node->lib_name,
Jon Ashburn953bb3c2015-06-10 16:11:42 -0600719 handle,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600720 VK_EXTENSION_ORIGIN_ICD,
721 &new_node->global_extension_list);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600722}
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700723
Jon Ashburn3da71f22015-05-14 12:43:38 -0600724static void loader_icd_init_entrys(struct loader_icd *icd,
725 struct loader_scanned_icds *scanned_icds)
726{
727 /* initialize entrypoint function pointers */
728
729 #define LOOKUP(func) do { \
730 icd->func = (PFN_vk ##func) loader_platform_get_proc_address(scanned_icds->handle, "vk" #func); \
731 if (!icd->func) { \
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600732 loader_log(VK_DBG_REPORT_WARN_BIT, 0, loader_platform_get_proc_address_error("vk" #func)); \
Jon Ashburn3da71f22015-05-14 12:43:38 -0600733 return; \
734 } \
735 } while (0)
736
Jon Ashburn8d1b0b52015-05-18 13:20:15 -0600737 /* could change this to use GetInstanceProcAddr in driver instead of dlsym */
738 LOOKUP(GetDeviceProcAddr);
Jon Ashburn3da71f22015-05-14 12:43:38 -0600739 LOOKUP(DestroyInstance);
740 LOOKUP(EnumeratePhysicalDevices);
Chris Forbesbc0bb772015-06-21 22:55:02 +1200741 LOOKUP(GetPhysicalDeviceFeatures);
742 LOOKUP(GetPhysicalDeviceFormatInfo);
743 LOOKUP(GetPhysicalDeviceLimits);
Jon Ashburn3da71f22015-05-14 12:43:38 -0600744 LOOKUP(CreateDevice);
Tony Barbour59a47322015-06-24 16:06:58 -0600745 LOOKUP(GetPhysicalDeviceProperties);
746 LOOKUP(GetPhysicalDeviceMemoryProperties);
747 LOOKUP(GetPhysicalDevicePerformance);
748 LOOKUP(GetPhysicalDeviceQueueCount);
749 LOOKUP(GetPhysicalDeviceQueueProperties);
750 LOOKUP(GetPhysicalDeviceExtensionProperties);
751 LOOKUP(GetPhysicalDeviceExtensionCount);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600752 LOOKUP(DbgCreateMsgCallback);
753 LOOKUP(DbgDestroyMsgCallback);
Jon Ashburn3da71f22015-05-14 12:43:38 -0600754#undef LOOKUP
755
756 return;
757}
758
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -0600759static void loader_debug_init(void)
760{
761 const char *env;
762
763 if (g_loader_debug > 0)
764 return;
765
766 g_loader_debug = 0;
767
768 /* parse comma-separated debug options */
769 env = getenv("LOADER_DEBUG");
770 while (env) {
771 const char *p = strchr(env, ',');
772 size_t len;
773
774 if (p)
775 len = p - env;
776 else
777 len = strlen(env);
778
779 if (len > 0) {
780 if (strncmp(env, "warn", len) == 0) {
781 g_loader_debug |= LOADER_WARN_BIT;
782 g_loader_log_msgs |= VK_DBG_REPORT_WARN_BIT;
783 } else if (strncmp(env, "info", len) == 0) {
784 g_loader_debug |= LOADER_INFO_BIT;
785 g_loader_log_msgs |= VK_DBG_REPORT_INFO_BIT;
786 } else if (strncmp(env, "perf", len) == 0) {
787 g_loader_debug |= LOADER_PERF_BIT;
788 g_loader_log_msgs |= VK_DBG_REPORT_PERF_WARN_BIT;
789 } else if (strncmp(env, "error", len) == 0) {
790 g_loader_debug |= LOADER_ERROR_BIT;
791 g_loader_log_msgs |= VK_DBG_REPORT_ERROR_BIT;
792 } else if (strncmp(env, "debug", len) == 0) {
793 g_loader_debug |= LOADER_DEBUG_BIT;
794 g_loader_log_msgs |= VK_DBG_REPORT_DEBUG_BIT;
795 }
796 }
797
798 if (!p)
799 break;
800
801 env = p + 1;
802 }
803}
804
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600805/**
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600806 * Try to \c loader_icd_scan VK driver(s).
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600807 *
808 * This function scans the default system path or path
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600809 * specified by the \c LIBVK_DRIVERS_PATH environment variable in
810 * order to find loadable VK ICDs with the name of libVK_*.
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600811 *
812 * \returns
813 * void; but side effect is to set loader_icd_scanned to true
814 */
Jon Ashburn27cd5842015-05-12 17:26:48 -0600815void loader_icd_scan(void)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800816{
Ian Elliott4470a302015-02-17 10:33:47 -0700817 const char *p, *next;
818 char *libPaths = NULL;
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600819 DIR *sysdir;
820 struct dirent *dent;
821 char icd_library[1024];
Jon Ashburn5cda59c2014-10-03 16:31:35 -0600822 char path[1024];
Ian Elliott19628802015-02-04 12:06:46 -0700823 uint32_t len;
Jon Ashburn6301a0f2015-05-29 13:15:39 -0600824
825 // convenient place to initialize a mutex
826 loader_platform_thread_create_mutex(&loader_lock);
827
Ian Elliott4470a302015-02-17 10:33:47 -0700828#if defined(WIN32)
829 bool must_free_libPaths;
830 libPaths = loader_get_registry_and_env(DRIVER_PATH_ENV,
831 DRIVER_PATH_REGISTRY_VALUE);
832 if (libPaths != NULL) {
833 must_free_libPaths = true;
834 } else {
835 must_free_libPaths = false;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600836 libPaths = DEFAULT_VK_DRIVERS_PATH;
Ian Elliott4470a302015-02-17 10:33:47 -0700837 }
838#else // WIN32
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600839 if (geteuid() == getuid()) {
Ian Elliott4470a302015-02-17 10:33:47 -0700840 /* Don't allow setuid apps to use the DRIVER_PATH_ENV env var: */
841 libPaths = getenv(DRIVER_PATH_ENV);
842 }
843 if (libPaths == NULL) {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600844 libPaths = DEFAULT_VK_DRIVERS_PATH;
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600845 }
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700846#endif // WIN32
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800847
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -0600848 loader_debug_init();
849
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600850 for (p = libPaths; *p; p = next) {
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700851 next = strchr(p, PATH_SEPERATOR);
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600852 if (next == NULL) {
Ian Elliott19628802015-02-04 12:06:46 -0700853 len = (uint32_t) strlen(p);
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600854 next = p + len;
855 }
856 else {
Ian Elliott19628802015-02-04 12:06:46 -0700857 len = (uint32_t) (next - p);
Jon Ashburn5cda59c2014-10-03 16:31:35 -0600858 sprintf(path, "%.*s", (len > sizeof(path) - 1) ? (int) sizeof(path) - 1 : len, p);
859 p = path;
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600860 next++;
861 }
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800862
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700863 // TODO/TBD: Do we want to do this on Windows, or just let Windows take
864 // care of its own search path (which it apparently has)?
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600865 sysdir = opendir(p);
866 if (sysdir) {
867 dent = readdir(sysdir);
868 while (dent) {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600869 /* Look for ICDs starting with VK_DRIVER_LIBRARY_PREFIX and
870 * ending with VK_LIBRARY_SUFFIX
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700871 */
872 if (!strncmp(dent->d_name,
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600873 VK_DRIVER_LIBRARY_PREFIX,
874 VK_DRIVER_LIBRARY_PREFIX_LEN)) {
Ian Elliott19628802015-02-04 12:06:46 -0700875 uint32_t nlen = (uint32_t) strlen(dent->d_name);
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600876 const char *suf = dent->d_name + nlen - VK_LIBRARY_SUFFIX_LEN;
877 if ((nlen > VK_LIBRARY_SUFFIX_LEN) &&
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700878 !strncmp(suf,
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600879 VK_LIBRARY_SUFFIX,
880 VK_LIBRARY_SUFFIX_LEN)) {
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700881 snprintf(icd_library, 1024, "%s" DIRECTORY_SYMBOL "%s", p,dent->d_name);
882 loader_scanned_icd_add(icd_library);
883 }
884 }
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -0600885
886 dent = readdir(sysdir);
887 }
888 closedir(sysdir);
889 }
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800890 }
891
Ian Elliott4470a302015-02-17 10:33:47 -0700892#if defined(WIN32)
893 // Free any allocated memory:
894 if (must_free_libPaths) {
895 free(libPaths);
896 }
897#endif // WIN32
898
899 // Note that we've scanned for ICDs:
Jon Ashburn46d1f582015-01-28 11:01:35 -0700900 loader.icds_scanned = true;
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800901}
902
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600903
Jon Ashburn27cd5842015-05-12 17:26:48 -0600904void layer_lib_scan(void)
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600905{
906 const char *p, *next;
Ian Elliott4470a302015-02-17 10:33:47 -0700907 char *libPaths = NULL;
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600908 DIR *curdir;
909 struct dirent *dent;
Ian Elliott4470a302015-02-17 10:33:47 -0700910 size_t len, i;
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600911 char temp_str[1024];
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600912 uint32_t count;
Tony Barbour59a47322015-06-24 16:06:58 -0600913 PFN_vkGetGlobalExtensionProperties fp_get_props;
914 PFN_vkGetGlobalExtensionCount fp_get_count;
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600915
Ian Elliott4470a302015-02-17 10:33:47 -0700916#if defined(WIN32)
917 bool must_free_libPaths;
918 libPaths = loader_get_registry_and_env(LAYERS_PATH_ENV,
919 LAYERS_PATH_REGISTRY_VALUE);
920 if (libPaths != NULL) {
921 must_free_libPaths = true;
922 } else {
923 must_free_libPaths = false;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600924 libPaths = DEFAULT_VK_LAYERS_PATH;
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600925 }
Ian Elliott4470a302015-02-17 10:33:47 -0700926#else // WIN32
927 if (geteuid() == getuid()) {
928 /* Don't allow setuid apps to use the DRIVER_PATH_ENV env var: */
Courtney Goeltzenleuchter66b72f92015-02-18 20:03:02 -0700929 libPaths = getenv(LAYERS_PATH_ENV);
Ian Elliott4470a302015-02-17 10:33:47 -0700930 }
931 if (libPaths == NULL) {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600932 libPaths = DEFAULT_VK_LAYERS_PATH;
Ian Elliott4470a302015-02-17 10:33:47 -0700933 }
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700934#endif // WIN32
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600935
Ian Elliott4470a302015-02-17 10:33:47 -0700936 if (libPaths == NULL) {
937 // Have no paths to search:
Courtney Goeltzenleuchter57985ce2014-12-01 09:29:42 -0700938 return;
939 }
Ian Elliott4470a302015-02-17 10:33:47 -0700940 len = strlen(libPaths);
Courtney Goeltzenleuchter57985ce2014-12-01 09:29:42 -0700941 loader.layer_dirs = malloc(len+1);
Ian Elliott4470a302015-02-17 10:33:47 -0700942 if (loader.layer_dirs == NULL) {
Jon Ashburn90c6a0e2015-06-04 15:30:58 -0600943 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Out of memory can't add layer directories");
944
Ian Elliott4470a302015-02-17 10:33:47 -0700945 free(libPaths);
Courtney Goeltzenleuchtera66265b2014-12-02 18:12:51 -0700946 return;
Ian Elliott4470a302015-02-17 10:33:47 -0700947 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600948 // Alloc passed, so we know there is enough space to hold the string
Ian Elliott4470a302015-02-17 10:33:47 -0700949 strcpy(loader.layer_dirs, libPaths);
950#if defined(WIN32)
951 // Free any allocated memory:
952 if (must_free_libPaths) {
953 free(libPaths);
954 must_free_libPaths = false;
955 }
956#endif // WIN32
Courtney Goeltzenleuchter57985ce2014-12-01 09:29:42 -0700957 libPaths = loader.layer_dirs;
958
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600959 /* cleanup any previously scanned libraries */
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600960 for (i = 0; i < loader.scanned_layer_count; i++) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600961 if (loader.scanned_layers[i].lib_name != NULL)
962 free(loader.scanned_layers[i].lib_name);
963 loader_destroy_ext_list(&loader.scanned_layers[i].global_extension_list);
964 loader.scanned_layers[i].lib_name = NULL;
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600965 }
Jon Ashburn6b4d70c2014-10-22 18:13:16 -0600966 loader.scanned_layer_count = 0;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600967 count = 0;
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600968
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600969 for (p = libPaths; *p; p = next) {
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600970 next = strchr(p, PATH_SEPERATOR);
971 if (next == NULL) {
Courtney Goeltzenleuchter0f1d8eb2015-06-07 17:28:17 -0600972 len = (uint32_t) strlen(p);
973 next = p + len;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600974 }
975 else {
Courtney Goeltzenleuchter0f1d8eb2015-06-07 17:28:17 -0600976 len = (uint32_t) (next - p);
977 *(char *) next = '\0';
978 next++;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600979 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600980
Courtney Goeltzenleuchter0f1d8eb2015-06-07 17:28:17 -0600981 curdir = opendir(p);
982 if (curdir) {
983 dent = readdir(curdir);
984 while (dent) {
985 /* Look for layers starting with VK_LAYER_LIBRARY_PREFIX and
986 * ending with VK_LIBRARY_SUFFIX
987 */
988 if (!strncmp(dent->d_name,
989 VK_LAYER_LIBRARY_PREFIX,
990 VK_LAYER_LIBRARY_PREFIX_LEN)) {
991 uint32_t nlen = (uint32_t) strlen(dent->d_name);
992 const char *suf = dent->d_name + nlen - VK_LIBRARY_SUFFIX_LEN;
993 if ((nlen > VK_LIBRARY_SUFFIX_LEN) &&
994 !strncmp(suf,
995 VK_LIBRARY_SUFFIX,
996 VK_LIBRARY_SUFFIX_LEN)) {
997 loader_platform_dl_handle handle;
998 snprintf(temp_str, sizeof(temp_str),
999 "%s" DIRECTORY_SYMBOL "%s",p,dent->d_name);
1000 // Used to call: dlopen(temp_str, RTLD_LAZY)
1001 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Courtney Goeltzenleuchter1e4602f2015-06-09 09:44:13 -06001002 "Attempt to open library: %s", temp_str);
Courtney Goeltzenleuchter0f1d8eb2015-06-07 17:28:17 -06001003 if ((handle = loader_platform_open_library(temp_str)) == NULL) {
Courtney Goeltzenleuchter1e4602f2015-06-09 09:44:13 -06001004 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, "open library failed");
Courtney Goeltzenleuchter0f1d8eb2015-06-07 17:28:17 -06001005 dent = readdir(curdir);
1006 continue;
1007 }
1008 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Courtney Goeltzenleuchter1e4602f2015-06-09 09:44:13 -06001009 "Opened library: %s", temp_str);
Courtney Goeltzenleuchtera9e4af42015-06-01 14:49:17 -06001010
Courtney Goeltzenleuchter0f1d8eb2015-06-07 17:28:17 -06001011 /* TODO: Remove fixed count */
1012 if (count == MAX_LAYER_LIBRARIES) {
1013 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
1014 "%s ignored: max layer libraries exceed",
1015 temp_str);
1016 break;
1017 }
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001018
Tony Barbour59a47322015-06-24 16:06:58 -06001019 fp_get_count = loader_platform_get_proc_address(handle, "vkGetGlobalExtensionCount");
1020 fp_get_props = loader_platform_get_proc_address(handle, "vkGetGlobalExtensionProperties");
1021 if (!fp_get_props || !fp_get_count) {
Courtney Goeltzenleuchter0f1d8eb2015-06-07 17:28:17 -06001022 loader_log(VK_DBG_REPORT_WARN_BIT, 0,
Tony Barbour59a47322015-06-24 16:06:58 -06001023 "Couldn't dlsym vkGetGlobalExtensionCount and/or vkGetGlobalExtensionProperties from library %s",
Courtney Goeltzenleuchter0f1d8eb2015-06-07 17:28:17 -06001024 temp_str);
1025 dent = readdir(curdir);
1026 loader_platform_close_library(handle);
1027 continue;
1028 }
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001029
Courtney Goeltzenleuchter0f1d8eb2015-06-07 17:28:17 -06001030 loader.scanned_layers[count].lib_name =
1031 malloc(strlen(temp_str) + 1);
1032 if (loader.scanned_layers[count].lib_name == NULL) {
1033 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "%s ignored: out of memory", temp_str);
1034 break;
1035 }
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001036
Courtney Goeltzenleuchter0f1d8eb2015-06-07 17:28:17 -06001037 strcpy(loader.scanned_layers[count].lib_name, temp_str);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001038
Courtney Goeltzenleuchter1e4602f2015-06-09 09:44:13 -06001039 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, "Collecting global extensions for %s", temp_str);
Jon Ashburn953bb3c2015-06-10 16:11:42 -06001040 loader_get_global_extensions(
Tony Barbour59a47322015-06-24 16:06:58 -06001041 fp_get_count,
1042 fp_get_props,
Jon Ashburn953bb3c2015-06-10 16:11:42 -06001043 NULL,
Courtney Goeltzenleuchter0f1d8eb2015-06-07 17:28:17 -06001044 loader.scanned_layers[count].lib_name,
Jon Ashburn953bb3c2015-06-10 16:11:42 -06001045 handle,
Courtney Goeltzenleuchter0f1d8eb2015-06-07 17:28:17 -06001046 VK_EXTENSION_ORIGIN_LAYER,
1047 &loader.scanned_layers[count].global_extension_list);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001048
Tony Barbour59a47322015-06-24 16:06:58 -06001049 fp_get_count = loader_platform_get_proc_address(handle,
1050 "vkGetPhysicalDeviceExtensionCount");
1051 fp_get_props = loader_platform_get_proc_address(handle,
1052 "vkGetPhysicalDeviceExtensionProperties");
1053 if (fp_get_props && fp_get_count) {
Courtney Goeltzenleuchter0f1d8eb2015-06-07 17:28:17 -06001054 loader.scanned_layers[count].physical_device_extensions_supported = true;
1055 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001056
Courtney Goeltzenleuchter0f1d8eb2015-06-07 17:28:17 -06001057 count++;
1058 loader_platform_close_library(handle);
1059 }
1060 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001061
Courtney Goeltzenleuchter0f1d8eb2015-06-07 17:28:17 -06001062 dent = readdir(curdir);
1063 } // while (dir_entry)
1064 if (count == MAX_LAYER_LIBRARIES)
1065 break;
1066 closedir(curdir);
1067 } // if (curdir))
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001068 } // for (libpaths)
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001069
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001070 loader.scanned_layer_count = count;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001071 loader.layers_scanned = true;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001072}
1073
Jon Ashburn27cd5842015-05-12 17:26:48 -06001074static void* VKAPI loader_gpa_instance_internal(VkInstance inst, const char * pName)
1075{
1076 // inst is not wrapped
1077 if (inst == VK_NULL_HANDLE) {
1078 return NULL;
1079 }
1080 VkLayerInstanceDispatchTable* disp_table = * (VkLayerInstanceDispatchTable **) inst;
1081 void *addr;
1082
Jon Ashburn8fd08252015-05-28 16:25:02 -06001083 if (!strcmp(pName, "vkGetInstanceProcAddr"))
1084 return (void *) loader_gpa_instance_internal;
1085
Jon Ashburn27cd5842015-05-12 17:26:48 -06001086 if (disp_table == NULL)
1087 return NULL;
1088
1089 addr = loader_lookup_instance_dispatch_table(disp_table, pName);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001090 if (addr) {
Jon Ashburn27cd5842015-05-12 17:26:48 -06001091 return addr;
Jon Ashburn3d526cb2015-04-13 18:10:06 -06001092 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001093
1094 if (disp_table->GetInstanceProcAddr == NULL) {
1095 return NULL;
1096 }
1097 return disp_table->GetInstanceProcAddr(inst, pName);
Jon Ashburn3d526cb2015-04-13 18:10:06 -06001098}
1099
Jon Ashburn128f9422015-05-28 19:16:58 -06001100struct loader_icd * loader_get_icd(const VkPhysicalDevice gpu, uint32_t *gpu_index)
Jon Ashburn876b1ac2014-10-17 15:09:07 -06001101{
Jon Ashburn128f9422015-05-28 19:16:58 -06001102
Jon Ashburn98bd4542015-01-29 16:44:24 -07001103 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
1104 for (struct loader_icd *icd = inst->icds; icd; icd = icd->next) {
1105 for (uint32_t i = 0; i < icd->gpu_count; i++)
Jon Ashburn128f9422015-05-28 19:16:58 -06001106 if (icd->gpus[i] == gpu) {
Jon Ashburn98bd4542015-01-29 16:44:24 -07001107 *gpu_index = i;
1108 return icd;
1109 }
1110 }
Jon Ashburn876b1ac2014-10-17 15:09:07 -06001111 }
1112 return NULL;
1113}
1114
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001115static loader_platform_dl_handle loader_add_layer_lib(
Jon Ashburn4f67d742015-05-27 13:19:22 -06001116 const char *chain_type,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001117 struct loader_extension_property *ext_prop)
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001118{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001119 struct loader_lib_info *new_layer_lib_list, *my_lib;
1120
1121 /* Only loader layer libraries here */
1122 if (ext_prop->origin != VK_EXTENSION_ORIGIN_LAYER) {
1123 return NULL;
1124 }
1125
1126 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) {
1127 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, ext_prop->lib_name) == 0) {
1128 /* Have already loaded this library, just increment ref count */
1129 loader.loaded_layer_lib_list[i].ref_count++;
Courtney Goeltzenleuchterca8c81a2015-06-14 11:59:07 -06001130 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001131 "%s Chain: Increment layer reference count for layer library %s",
1132 chain_type, ext_prop->lib_name);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001133 return loader.loaded_layer_lib_list[i].lib_handle;
1134 }
1135 }
1136
1137 /* Haven't seen this library so load it */
1138 new_layer_lib_list = realloc(loader.loaded_layer_lib_list,
1139 (loader.loaded_layer_lib_count + 1) * sizeof(struct loader_lib_info));
1140 if (!new_layer_lib_list) {
1141 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "loader: malloc failed");
1142 return NULL;
1143 }
1144
1145 my_lib = &new_layer_lib_list[loader.loaded_layer_lib_count];
1146
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001147 /* NOTE: We require that the extension property be immutable */
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001148 my_lib->lib_name = ext_prop->lib_name;
1149 my_lib->ref_count = 0;
1150 my_lib->lib_handle = NULL;
1151
1152 if ((my_lib->lib_handle = loader_platform_open_library(my_lib->lib_name)) == NULL) {
1153 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
1154 loader_platform_open_library_error(my_lib->lib_name));
1155 return NULL;
1156 } else {
Courtney Goeltzenleuchterca8c81a2015-06-14 11:59:07 -06001157 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001158 "Chain: %s: Loading layer library %s",
1159 chain_type, ext_prop->lib_name);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001160 }
1161 loader.loaded_layer_lib_count++;
1162 loader.loaded_layer_lib_list = new_layer_lib_list;
1163 my_lib->ref_count++;
1164
1165 return my_lib->lib_handle;
1166}
1167
1168static void loader_remove_layer_lib(
1169 struct loader_instance *inst,
1170 struct loader_extension_property *ext_prop)
1171{
1172 uint32_t idx;
1173 struct loader_lib_info *new_layer_lib_list, *my_lib;
1174
1175 /* Only loader layer libraries here */
1176 if (ext_prop->origin != VK_EXTENSION_ORIGIN_LAYER) {
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06001177 return;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001178 }
Jon Ashburndf7d5842014-10-16 15:48:50 -06001179
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001180 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) {
1181 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, ext_prop->lib_name) == 0) {
1182 /* found matching library */
1183 idx = i;
1184 my_lib = &loader.loaded_layer_lib_list[i];
1185 break;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001186 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001187 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001188
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001189 my_lib->ref_count--;
1190 inst->layer_count--;
1191 if (my_lib->ref_count > 0) {
Courtney Goeltzenleuchterca8c81a2015-06-14 11:59:07 -06001192 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001193 "Decrement reference count for layer library %s", ext_prop->lib_name);
Jon Ashburn27cd5842015-05-12 17:26:48 -06001194 return;
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07001195 }
Jon Ashburn19c25022015-04-14 14:14:48 -06001196
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001197 loader_platform_close_library(my_lib->lib_handle);
Courtney Goeltzenleuchterca8c81a2015-06-14 11:59:07 -06001198 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001199 "Unloading layer library %s", ext_prop->lib_name);
1200
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001201 /* Need to remove unused library from list */
1202 new_layer_lib_list = malloc((loader.loaded_layer_lib_count - 1) * sizeof(struct loader_lib_info));
1203 if (!new_layer_lib_list) {
1204 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "loader: malloc failed");
1205 return;
1206 }
1207
1208 if (idx > 0) {
1209 /* Copy records before idx */
1210 memcpy(new_layer_lib_list, &loader.loaded_layer_lib_list[0],
1211 sizeof(struct loader_lib_info) * idx);
1212 }
1213 if (idx < (loader.loaded_layer_lib_count - 1)) {
1214 /* Copy records after idx */
1215 memcpy(&new_layer_lib_list[idx], &loader.loaded_layer_lib_list[idx+1],
1216 sizeof(struct loader_lib_info) * (loader.loaded_layer_lib_count - idx - 1));
1217 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001218
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001219 free(loader.loaded_layer_lib_list);
1220 loader.loaded_layer_lib_count--;
1221 loader.loaded_layer_lib_list = new_layer_lib_list;
Jon Ashburnb8358052014-11-18 09:06:04 -07001222}
1223
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001224static void loader_add_layer_env(
1225 struct loader_extension_list *ext_list,
1226 const struct loader_extension_list *search_list)
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001227{
Ian Elliott4470a302015-02-17 10:33:47 -07001228 char *layerEnv;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001229 uint32_t len;
Jon Ashburnd09bd102014-10-22 21:15:26 -06001230 char *p, *pOrig, *next, *name;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001231
Ian Elliott4470a302015-02-17 10:33:47 -07001232#if defined(WIN32)
1233 layerEnv = loader_get_registry_and_env(LAYER_NAMES_ENV,
1234 LAYER_NAMES_REGISTRY_VALUE);
1235#else // WIN32
1236 layerEnv = getenv(LAYER_NAMES_ENV);
1237#endif // WIN32
1238 if (layerEnv == NULL) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001239 return;
Ian Elliott4470a302015-02-17 10:33:47 -07001240 }
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06001241 p = malloc(strlen(layerEnv) + 1);
Ian Elliott4470a302015-02-17 10:33:47 -07001242 if (p == NULL) {
1243#if defined(WIN32)
1244 free(layerEnv);
1245#endif // WIN32
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001246 return;
Ian Elliott4470a302015-02-17 10:33:47 -07001247 }
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06001248 strcpy(p, layerEnv);
Ian Elliott4470a302015-02-17 10:33:47 -07001249#if defined(WIN32)
1250 free(layerEnv);
1251#endif // WIN32
Jon Ashburnd09bd102014-10-22 21:15:26 -06001252 pOrig = p;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001253
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001254 while (p && *p ) {
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001255 next = strchr(p, PATH_SEPERATOR);
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001256 if (next == NULL) {
Ian Elliott19628802015-02-04 12:06:46 -07001257 len = (uint32_t) strlen(p);
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001258 next = p + len;
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07001259 } else {
Ian Elliott19628802015-02-04 12:06:46 -07001260 len = (uint32_t) (next - p);
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001261 *(char *) next = '\0';
1262 next++;
1263 }
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06001264 name = basename(p);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001265 loader_search_ext_list_for_name(name, search_list, ext_list);
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001266 p = next;
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07001267 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001268
Jon Ashburnd09bd102014-10-22 21:15:26 -06001269 free(pOrig);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001270 return;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001271}
1272
Courtney Goeltzenleuchter7d0023c2015-06-08 15:09:22 -06001273void loader_deactivate_instance_layers(struct loader_instance *instance)
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06001274{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001275 if (!instance->layer_count) {
1276 return;
1277 }
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06001278
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001279 /* Create instance chain of enabled layers */
Courtney Goeltzenleuchter7d0023c2015-06-08 15:09:22 -06001280 for (uint32_t i = 0; i < instance->activated_layer_list.count; i++) {
1281 struct loader_extension_property *ext_prop = &instance->activated_layer_list.list[i];
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001282
1283 loader_remove_layer_lib(instance, ext_prop);
1284
1285 instance->layer_count--;
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06001286 }
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001287 loader_destroy_ext_list(&instance->activated_layer_list);
Jon Ashburn27cd5842015-05-12 17:26:48 -06001288
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06001289}
1290
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001291void loader_enable_instance_layers(struct loader_instance *inst)
1292{
1293 if (inst == NULL)
1294 return;
1295
1296 /* Add any layers specified in the environment first */
1297 loader_add_layer_env(&inst->enabled_instance_extensions, &loader.global_extensions);
1298
1299 /* Add layers / extensions specified by the application */
1300 loader_add_vk_ext_to_ext_list(
1301 &inst->enabled_instance_extensions,
1302 inst->app_extension_count,
1303 inst->app_extension_props,
1304 &loader.global_extensions);
1305}
1306
Jon Ashburn27cd5842015-05-12 17:26:48 -06001307uint32_t loader_activate_instance_layers(struct loader_instance *inst)
1308{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001309 uint32_t layer_idx;
Jon Ashburn128f9422015-05-28 19:16:58 -06001310 VkBaseLayerObject *wrappedInstance;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001311
David Pinedoa0a8a242015-06-24 15:29:18 -06001312 if (inst == NULL) {
Jon Ashburn27cd5842015-05-12 17:26:48 -06001313 return 0;
David Pinedoa0a8a242015-06-24 15:29:18 -06001314 }
Jon Ashburn27cd5842015-05-12 17:26:48 -06001315
1316 // NOTE inst is unwrapped at this point in time
1317 VkObject baseObj = (VkObject) inst;
1318 VkObject nextObj = (VkObject) inst;
1319 VkBaseLayerObject *nextInstObj;
1320 PFN_vkGetInstanceProcAddr nextGPA = loader_gpa_instance_internal;
1321
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001322 /*
1323 * Figure out how many actual layers will need to be wrapped.
1324 */
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001325 for (uint32_t i = 0; i < inst->enabled_instance_extensions.count; i++) {
1326 struct loader_extension_property *ext_prop = &inst->enabled_instance_extensions.list[i];
Courtney Goeltzenleuchter0f1d8eb2015-06-07 17:28:17 -06001327 if (ext_prop->alias) {
1328 ext_prop = ext_prop->alias;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001329 }
Courtney Goeltzenleuchter0f1d8eb2015-06-07 17:28:17 -06001330 if (ext_prop->origin != VK_EXTENSION_ORIGIN_LAYER) {
1331 continue;
1332 }
1333 loader_add_to_ext_list(&inst->activated_layer_list, 1, ext_prop);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001334 }
Jon Ashburn27cd5842015-05-12 17:26:48 -06001335
Courtney Goeltzenleuchter0f1d8eb2015-06-07 17:28:17 -06001336 inst->layer_count = inst->activated_layer_list.count;
1337
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001338 if (!inst->layer_count) {
Jon Ashburn27cd5842015-05-12 17:26:48 -06001339 return 0;
1340 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001341
Jon Ashburn128f9422015-05-28 19:16:58 -06001342 wrappedInstance = malloc(sizeof(VkBaseLayerObject)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001343 * inst->layer_count);
Jon Ashburn128f9422015-05-28 19:16:58 -06001344 if (!wrappedInstance) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001345 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to malloc Instance objects for layer");
1346 return 0;
1347 }
1348
1349 /* Create instance chain of enabled layers */
1350 layer_idx = inst->layer_count - 1;
Courtney Goeltzenleuchter0f1d8eb2015-06-07 17:28:17 -06001351 for (int32_t i = inst->activated_layer_list.count - 1; i >= 0; i--) {
1352 struct loader_extension_property *ext_prop = &inst->activated_layer_list.list[i];
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001353 loader_platform_dl_handle lib_handle;
1354
1355 /*
Jon Ashburn922c8f62015-06-18 09:05:37 -06001356 * For global exenstions implemented within the loader (i.e. DEBUG_REPORT
Courtney Goeltzenleuchteree3b16a2015-06-01 14:12:42 -06001357 * the extension must provide two entry points for the loader to use:
1358 * - "trampoline" entry point - this is the address returned by GetProcAddr
1359 * and will always do what's necessary to support a global call.
1360 * - "terminator" function - this function will be put at the end of the
1361 * instance chain and will contain the necessary logica to call / process
1362 * the extension for the appropriate ICDs that are available.
1363 * There is no generic mechanism for including these functions, the references
1364 * must be placed into the appropriate loader entry points.
1365 * GetInstanceProcAddr: call extension GetInstanceProcAddr to check for GetProcAddr requests
1366 * loader_coalesce_extensions(void) - add extension records to the list of global
1367 * extension available to the app.
1368 * instance_disp - add function pointer for terminator function to this array.
1369 * The extension itself should be in a separate file that will be
1370 * linked directly with the loader.
1371 * Note: An extension's Get*ProcAddr should not return a function pointer for
1372 * any extension entry points until the extension has been enabled.
1373 * To do this requires a different behavior from Get*ProcAddr functions implemented
1374 * in layers.
1375 * The very first call to a layer will be it's Get*ProcAddr function requesting
1376 * the layer's vkGet*ProcAddr. The layer should intialize it's internal dispatch table
1377 * with the wrapped object given (either Instance or Device) and return the layer's
1378 * Get*ProcAddr function. The layer should also use this opportunity to record the
1379 * baseObject so that it can find the correct local dispatch table on future calls.
1380 * Subsequent calls to Get*ProcAddr, CreateInstance, CreateDevice
1381 * will not use a wrapped object and must look up their local dispatch table from
1382 * the given baseObject.
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001383 */
Courtney Goeltzenleuchter0f1d8eb2015-06-07 17:28:17 -06001384 assert(ext_prop->origin == VK_EXTENSION_ORIGIN_LAYER);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001385
Jon Ashburn128f9422015-05-28 19:16:58 -06001386 nextInstObj = (wrappedInstance + layer_idx);
Jon Ashburn27cd5842015-05-12 17:26:48 -06001387 nextInstObj->pGPA = nextGPA;
1388 nextInstObj->baseObject = baseObj;
1389 nextInstObj->nextObject = nextObj;
1390 nextObj = (VkObject) nextInstObj;
1391
1392 char funcStr[256];
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001393 snprintf(funcStr, 256, "%sGetInstanceProcAddr", ext_prop->info.name);
Jon Ashburn4f67d742015-05-27 13:19:22 -06001394 lib_handle = loader_add_layer_lib("instance", ext_prop);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001395 if ((nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, funcStr)) == NULL)
1396 nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetInstanceProcAddr");
Jon Ashburn27cd5842015-05-12 17:26:48 -06001397 if (!nextGPA) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001398 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to find vkGetInstanceProcAddr in layer %s", ext_prop->lib_name);
Courtney Goeltzenleuchtera9e4af42015-06-01 14:49:17 -06001399
1400 /* TODO: Should we return nextObj, nextGPA to previous? */
Jon Ashburn27cd5842015-05-12 17:26:48 -06001401 continue;
1402 }
1403
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001404 loader_log(VK_DBG_REPORT_INFO_BIT, 0,
1405 "Insert instance layer library %s for extension: %s",
1406 ext_prop->lib_name, ext_prop->info.name);
1407
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001408 layer_idx--;
Jon Ashburn27cd5842015-05-12 17:26:48 -06001409 }
1410
Jon Ashburn8fd08252015-05-28 16:25:02 -06001411 loader_init_instance_core_dispatch_table(inst->disp, nextGPA, (VkInstance) nextObj, (VkInstance) baseObj);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001412
Jon Ashburn128f9422015-05-28 19:16:58 -06001413 free(wrappedInstance);
Jon Ashburn27cd5842015-05-12 17:26:48 -06001414 return inst->layer_count;
1415}
1416
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001417void loader_activate_instance_layer_extensions(struct loader_instance *inst)
1418{
1419
1420 loader_init_instance_extension_dispatch_table(inst->disp,
1421 inst->disp->GetInstanceProcAddr,
Jon Ashburn128f9422015-05-28 19:16:58 -06001422 (VkInstance) inst);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001423}
1424
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001425static void loader_enable_device_layers(struct loader_device *dev)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001426{
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001427 if (dev == NULL)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001428 return;
1429
1430 /* Add any layers specified in the environment first */
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001431 loader_add_layer_env(&dev->enabled_device_extensions, &loader.global_extensions);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001432
1433 /* Add layers / extensions specified by the application */
1434 loader_add_vk_ext_to_ext_list(
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001435 &dev->enabled_device_extensions,
1436 dev->app_extension_count,
1437 dev->app_extension_props,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001438 &loader.global_extensions);
1439}
1440
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001441static uint32_t loader_activate_device_layers(
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001442 VkDevice device,
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001443 struct loader_device *dev,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001444 struct loader_icd *icd,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001445 uint32_t ext_count,
1446 const VkExtensionProperties *ext_props)
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06001447{
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06001448 if (!icd)
1449 return 0;
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06001450
David Pinedoa0a8a242015-06-24 15:29:18 -06001451 if (!dev) {
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001452 return 0;
David Pinedoa0a8a242015-06-24 15:29:18 -06001453 }
Jon Ashburn94e70492015-06-10 10:13:10 -06001454
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06001455 /* activate any layer libraries */
Jon Ashburn94e70492015-06-10 10:13:10 -06001456 VkObject nextObj = (VkObject) device;
1457 VkObject baseObj = nextObj;
1458 VkBaseLayerObject *nextGpuObj;
1459 PFN_vkGetDeviceProcAddr nextGPA = icd->GetDeviceProcAddr;
1460 VkBaseLayerObject *wrappedGpus;
1461 /*
1462 * Figure out how many actual layers will need to be wrapped.
1463 */
1464 for (uint32_t i = 0; i < dev->enabled_device_extensions.count; i++) {
1465 struct loader_extension_property *ext_prop = &dev->enabled_device_extensions.list[i];
1466 if (ext_prop->alias) {
1467 ext_prop = ext_prop->alias;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001468 }
Jon Ashburn94e70492015-06-10 10:13:10 -06001469 if (ext_prop->origin != VK_EXTENSION_ORIGIN_LAYER) {
1470 continue;
Jon Ashburn27cd5842015-05-12 17:26:48 -06001471 }
Jon Ashburn94e70492015-06-10 10:13:10 -06001472 loader_add_to_ext_list(&dev->activated_layer_list, 1, ext_prop);
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06001473 }
Jon Ashburn94e70492015-06-10 10:13:10 -06001474
1475 if (!dev->activated_layer_list.count)
1476 return 0;
1477
1478 wrappedGpus = malloc(sizeof (VkBaseLayerObject) * dev->activated_layer_list.count);
1479 if (!wrappedGpus) {
1480 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to malloc Gpu objects for layer");
1481 return 0;
1482 }
1483 for (int32_t i = dev->activated_layer_list.count - 1; i >= 0; i--) {
1484
1485 struct loader_extension_property *ext_prop = &dev->activated_layer_list.list[i];
1486 loader_platform_dl_handle lib_handle;
1487
1488 assert(ext_prop->origin == VK_EXTENSION_ORIGIN_LAYER);
1489
1490 nextGpuObj = (wrappedGpus + i);
1491 nextGpuObj->pGPA = nextGPA;
1492 nextGpuObj->baseObject = baseObj;
1493 nextGpuObj->nextObject = nextObj;
1494 nextObj = (VkObject) nextGpuObj;
1495
1496 char funcStr[256];
1497 snprintf(funcStr, 256, "%sGetDeviceProcAddr", ext_prop->info.name);
1498 lib_handle = loader_add_layer_lib("device", ext_prop);
1499 if ((nextGPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, funcStr)) == NULL)
1500 nextGPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetDeviceProcAddr");
1501 if (!nextGPA) {
1502 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to find vkGetDeviceProcAddr in layer %s", ext_prop->info.name);
1503 continue;
1504 }
1505
1506 loader_log(VK_DBG_REPORT_INFO_BIT, 0,
1507 "Insert device layer library %s for extension: %s",
1508 ext_prop->lib_name, ext_prop->info.name);
1509
1510 }
1511
1512 loader_init_device_dispatch_table(&dev->loader_dispatch, nextGPA,
1513 (VkPhysicalDevice) nextObj, (VkPhysicalDevice) baseObj);
1514 free(wrappedGpus);
1515
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001516 return dev->activated_layer_list.count;
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06001517}
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001518
Jon Ashburn27cd5842015-05-12 17:26:48 -06001519VkResult loader_CreateInstance(
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001520 const VkInstanceCreateInfo* pCreateInfo,
1521 VkInstance* pInstance)
Jon Ashburn1beab2d2015-01-26 14:51:40 -07001522{
Jon Ashburneed0c002015-05-21 17:42:17 -06001523 struct loader_instance *ptr_instance = *(struct loader_instance **) pInstance;
Jon Ashburn46888392015-01-29 15:45:51 -07001524 struct loader_scanned_icds *scanned_icds;
1525 struct loader_icd *icd;
Jon Ashburn27cd5842015-05-12 17:26:48 -06001526 VkResult res;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07001527
Jon Ashburn46888392015-01-29 15:45:51 -07001528 scanned_icds = loader.scanned_icd_list;
1529 while (scanned_icds) {
1530 icd = loader_icd_add(ptr_instance, scanned_icds);
1531 if (icd) {
Jon Ashburnb317fad2015-04-04 14:52:07 -06001532 res = scanned_icds->CreateInstance(pCreateInfo,
Jon Ashburn3da71f22015-05-14 12:43:38 -06001533 &(icd->instance));
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001534 if (res != VK_SUCCESS)
Jon Ashburn46888392015-01-29 15:45:51 -07001535 {
1536 ptr_instance->icds = ptr_instance->icds->next;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001537 loader_icd_destroy(ptr_instance, icd);
Jon Ashburn3da71f22015-05-14 12:43:38 -06001538 icd->instance = VK_NULL_HANDLE;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001539 loader_log(VK_DBG_REPORT_WARN_BIT, 0,
Jon Ashburn46888392015-01-29 15:45:51 -07001540 "ICD ignored: failed to CreateInstance on device");
Jon Ashburn3da71f22015-05-14 12:43:38 -06001541 } else
1542 {
1543 loader_icd_init_entrys(icd, scanned_icds);
Jon Ashburn46888392015-01-29 15:45:51 -07001544 }
1545 }
1546 scanned_icds = scanned_icds->next;
1547 }
Jon Ashburn1beab2d2015-01-26 14:51:40 -07001548
Ian Elliotteb450762015-02-05 15:19:15 -07001549 if (ptr_instance->icds == NULL) {
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001550 return VK_ERROR_INCOMPATIBLE_DRIVER;
Ian Elliotteb450762015-02-05 15:19:15 -07001551 }
Jon Ashburn46888392015-01-29 15:45:51 -07001552
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001553 return res;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07001554}
1555
Jon Ashburn27cd5842015-05-12 17:26:48 -06001556VkResult loader_DestroyInstance(
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -06001557 VkInstance instance)
Jon Ashburn1beab2d2015-01-26 14:51:40 -07001558{
Courtney Goeltzenleuchterdeceded2015-06-08 15:04:02 -06001559 struct loader_instance *ptr_instance = loader_instance(instance);
Jon Ashburn3da71f22015-05-14 12:43:38 -06001560 struct loader_icd *icds = ptr_instance->icds;
Jon Ashburna6fd2612015-06-16 14:43:19 -06001561 struct loader_icd *next_icd;
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -06001562 VkResult res;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07001563
1564 // Remove this instance from the list of instances:
1565 struct loader_instance *prev = NULL;
1566 struct loader_instance *next = loader.instances;
1567 while (next != NULL) {
1568 if (next == ptr_instance) {
1569 // Remove this instance from the list:
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001570 free(ptr_instance->app_extension_props);
Jon Ashburn1beab2d2015-01-26 14:51:40 -07001571 if (prev)
1572 prev->next = next->next;
Jon Ashburnc5c49602015-02-03 09:26:59 -07001573 else
1574 loader.instances = next->next;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07001575 break;
1576 }
1577 prev = next;
1578 next = next->next;
1579 }
1580 if (next == NULL) {
1581 // This must be an invalid instance handle or empty list
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001582 return VK_ERROR_INVALID_HANDLE;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07001583 }
1584
Jon Ashburn3da71f22015-05-14 12:43:38 -06001585 while (icds) {
1586 if (icds->instance) {
1587 res = icds->DestroyInstance(icds->instance);
Tony Barbourf20f87b2015-04-22 09:02:32 -06001588 if (res != VK_SUCCESS)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001589 loader_log(VK_DBG_REPORT_WARN_BIT, 0,
Tony Barbourf20f87b2015-04-22 09:02:32 -06001590 "ICD ignored: failed to DestroyInstance on device");
1591 }
Jon Ashburna6fd2612015-06-16 14:43:19 -06001592 next_icd = icds->next;
Jon Ashburn3da71f22015-05-14 12:43:38 -06001593 icds->instance = VK_NULL_HANDLE;
Jon Ashburna6fd2612015-06-16 14:43:19 -06001594 loader_icd_destroy(ptr_instance, icds);
1595
1596 icds = next_icd;
Jon Ashburn46888392015-01-29 15:45:51 -07001597 }
1598
Jon Ashburn1beab2d2015-01-26 14:51:40 -07001599
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06001600 return VK_SUCCESS;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07001601}
1602
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001603VkResult loader_init_physical_device_info(
1604 struct loader_instance *ptr_instance)
1605{
1606 struct loader_icd *icd;
1607 uint32_t n, count = 0;
1608 VkResult res = VK_ERROR_UNKNOWN;
1609
1610 icd = ptr_instance->icds;
1611 while (icd) {
1612 res = icd->EnumeratePhysicalDevices(icd->instance, &n, NULL);
1613 if (res != VK_SUCCESS)
1614 return res;
1615 icd->gpu_count = n;
1616 count += n;
1617 icd = icd->next;
1618 }
1619
1620 ptr_instance->total_gpu_count = count;
1621
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001622 icd = ptr_instance->icds;
1623 while (icd) {
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001624
1625 n = icd->gpu_count;
Jon Ashburn128f9422015-05-28 19:16:58 -06001626 icd->gpus = (VkPhysicalDevice *) malloc(n * sizeof(VkPhysicalDevice));
1627 if (!icd->gpus) {
1628 /* TODO: Add cleanup code here */
1629 return VK_ERROR_OUT_OF_HOST_MEMORY;
1630 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001631 res = icd->EnumeratePhysicalDevices(
1632 icd->instance,
1633 &n,
Jon Ashburn128f9422015-05-28 19:16:58 -06001634 icd->gpus);
1635 if ((res == VK_SUCCESS) && (n == icd->gpu_count)) {
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001636
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001637 for (unsigned int i = 0; i < n; i++) {
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001638
Jon Ashburn128f9422015-05-28 19:16:58 -06001639 loader_init_dispatch(icd->gpus[i], ptr_instance->disp);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001640
1641 if (!loader_init_ext_list(&icd->device_extension_cache[i])) {
1642 /* TODO: Add cleanup code here */
1643 res = VK_ERROR_OUT_OF_HOST_MEMORY;
1644 }
Tony Barbour59a47322015-06-24 16:06:58 -06001645 if (res == VK_SUCCESS && icd->GetPhysicalDeviceExtensionProperties && icd->GetPhysicalDeviceExtensionCount) {
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001646 uint32_t extension_count;
1647
Tony Barbour59a47322015-06-24 16:06:58 -06001648 res = icd->GetPhysicalDeviceExtensionCount(icd->gpus[i], &extension_count);
1649 if (res == VK_SUCCESS) {
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001650 struct loader_extension_property ext_props;
1651
1652 /* Gather all the ICD extensions */
1653 for (uint32_t extension_id = 0; extension_id < extension_count; extension_id++) {
Tony Barbour59a47322015-06-24 16:06:58 -06001654 res = icd->GetPhysicalDeviceExtensionProperties(icd->gpus[i],
1655 extension_id, &ext_props.info);
1656 if (res == VK_SUCCESS) {
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001657 ext_props.origin = VK_EXTENSION_ORIGIN_ICD;
1658 ext_props.lib_name = icd->scanned_icds->lib_name;
Jon Ashburn953bb3c2015-06-10 16:11:42 -06001659 ext_props.get_proc_addr = icd->GetDeviceProcAddr;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001660 loader_add_to_ext_list(&icd->device_extension_cache[i], 1, &ext_props);
1661 }
1662 }
1663
1664 // Traverse layers list adding non-duplicate extensions to the list
1665 for (uint32_t l = 0; l < loader.scanned_layer_count; l++) {
Jon Ashburn953bb3c2015-06-10 16:11:42 -06001666 loader_get_physical_device_layer_extensions(ptr_instance, icd->gpus[i], l, &icd->device_extension_cache[i]);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001667 }
1668 }
1669 }
1670
1671 if (res != VK_SUCCESS) {
1672 /* clean up any extension lists previously created before this request failed */
1673 for (uint32_t j = 0; j < i; j++) {
1674 loader_destroy_ext_list(&icd->device_extension_cache[i]);
1675 }
1676 return res;
1677 }
1678 }
1679
1680 count += n;
1681 }
1682
1683 icd = icd->next;
1684 }
1685
1686 return VK_SUCCESS;
1687}
1688
Jon Ashburn27cd5842015-05-12 17:26:48 -06001689VkResult loader_EnumeratePhysicalDevices(
Courtney Goeltzenleuchter5e41f1d2015-04-20 12:48:54 -06001690 VkInstance instance,
1691 uint32_t* pPhysicalDeviceCount,
1692 VkPhysicalDevice* pPhysicalDevices)
Jon Ashburn1beab2d2015-01-26 14:51:40 -07001693{
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001694 uint32_t index = 0;
Jon Ashburn4c392fb2015-01-28 19:57:09 -07001695 struct loader_instance *ptr_instance = (struct loader_instance *) instance;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001696 struct loader_icd *icd = ptr_instance->icds;
Jon Ashburn4c392fb2015-01-28 19:57:09 -07001697
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001698 if (ptr_instance->total_gpu_count == 0) {
1699 loader_init_physical_device_info(ptr_instance);
Jon Ashburn4c392fb2015-01-28 19:57:09 -07001700 }
1701
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001702 *pPhysicalDeviceCount = ptr_instance->total_gpu_count;
1703 if (!pPhysicalDevices) {
1704 return VK_SUCCESS;
1705 }
Jon Ashburn4c392fb2015-01-28 19:57:09 -07001706
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001707 while (icd) {
1708 assert((index + icd->gpu_count) <= *pPhysicalDeviceCount);
Jon Ashburn128f9422015-05-28 19:16:58 -06001709 memcpy(&pPhysicalDevices[index], icd->gpus, icd->gpu_count * sizeof(VkPhysicalDevice));
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001710 index += icd->gpu_count;
1711 icd = icd->next;
1712 }
1713
1714 return VK_SUCCESS;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07001715}
1716
Tony Barbour59a47322015-06-24 16:06:58 -06001717VkResult loader_GetPhysicalDeviceProperties(
Jon Ashburn3da71f22015-05-14 12:43:38 -06001718 VkPhysicalDevice gpu,
Tony Barbour59a47322015-06-24 16:06:58 -06001719 VkPhysicalDeviceProperties* pProperties)
Jon Ashburn3da71f22015-05-14 12:43:38 -06001720{
1721 uint32_t gpu_index;
Jon Ashburn128f9422015-05-28 19:16:58 -06001722 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
Jon Ashburn3da71f22015-05-14 12:43:38 -06001723 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
1724
Tony Barbour59a47322015-06-24 16:06:58 -06001725 if (icd->GetPhysicalDeviceProperties)
1726 res = icd->GetPhysicalDeviceProperties(gpu, pProperties);
1727
1728 return res;
1729}
1730
1731VkResult loader_GetPhysicalDevicePerformance(
1732 VkPhysicalDevice gpu,
1733 VkPhysicalDevicePerformance* pPerformance)
1734{
1735 uint32_t gpu_index;
1736 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
1737 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
1738
1739 if (icd->GetPhysicalDevicePerformance)
1740 res = icd->GetPhysicalDevicePerformance(gpu, pPerformance);
1741
1742 return res;
1743}
1744
1745VkResult loader_GetPhysicalDeviceQueueCount(
1746 VkPhysicalDevice gpu,
1747 uint32_t* pCount)
1748{
1749 uint32_t gpu_index;
1750 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
1751 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
1752
1753 if (icd->GetPhysicalDeviceQueueCount)
1754 res = icd->GetPhysicalDeviceQueueCount(gpu, pCount);
1755
1756 return res;
1757}
1758
1759VkResult loader_GetPhysicalDeviceQueueProperties (
1760 VkPhysicalDevice gpu,
1761 uint32_t count,
1762 VkPhysicalDeviceQueueProperties * pProperties)
1763{
1764 uint32_t gpu_index;
1765 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
1766 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
1767
1768 if (icd->GetPhysicalDeviceQueueProperties)
1769 res = icd->GetPhysicalDeviceQueueProperties(gpu, count, pProperties);
1770
1771 return res;
1772}
1773
1774VkResult loader_GetPhysicalDeviceMemoryProperties (
1775 VkPhysicalDevice gpu,
1776 VkPhysicalDeviceMemoryProperties* pProperties)
1777{
1778 uint32_t gpu_index;
1779 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
1780 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
1781
1782 if (icd->GetPhysicalDeviceMemoryProperties)
1783 res = icd->GetPhysicalDeviceMemoryProperties(gpu, pProperties);
Jon Ashburn3da71f22015-05-14 12:43:38 -06001784
1785 return res;
1786}
1787
Chris Forbesbc0bb772015-06-21 22:55:02 +12001788VkResult loader_GetPhysicalDeviceFeatures(
1789 VkPhysicalDevice physicalDevice,
1790 VkPhysicalDeviceFeatures* pFeatures)
1791{
1792 uint32_t gpu_index;
1793 struct loader_icd *icd = loader_get_icd(physicalDevice, &gpu_index);
1794 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
1795
1796 if (icd->GetPhysicalDeviceFeatures)
1797 res = icd->GetPhysicalDeviceFeatures(physicalDevice, pFeatures);
1798
1799 return res;
1800}
1801
1802VkResult loader_GetPhysicalDeviceFormatInfo(
1803 VkPhysicalDevice physicalDevice,
1804 VkFormat format,
1805 VkFormatProperties* pFormatInfo)
1806{
1807 uint32_t gpu_index;
1808 struct loader_icd *icd = loader_get_icd(physicalDevice, &gpu_index);
1809 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
1810
1811 if (icd->GetPhysicalDeviceFormatInfo)
1812 res = icd->GetPhysicalDeviceFormatInfo(physicalDevice, format, pFormatInfo);
1813
1814 return res;
1815}
1816
1817VkResult loader_GetPhysicalDeviceLimits(
1818 VkPhysicalDevice physicalDevice,
1819 VkPhysicalDeviceLimits* pLimits)
1820{
1821 uint32_t gpu_index;
1822 struct loader_icd *icd = loader_get_icd(physicalDevice, &gpu_index);
1823 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
1824
1825 if (icd->GetPhysicalDeviceLimits)
1826 res = icd->GetPhysicalDeviceLimits(physicalDevice, pLimits);
1827
1828 return res;
1829}
1830
Jon Ashburn95a77ba2015-05-15 15:09:35 -06001831VkResult loader_CreateDevice(
1832 VkPhysicalDevice gpu,
1833 const VkDeviceCreateInfo* pCreateInfo,
1834 VkDevice* pDevice)
1835{
1836 uint32_t gpu_index;
Jon Ashburn128f9422015-05-28 19:16:58 -06001837 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001838 struct loader_device *dev;
Jon Ashburn95a77ba2015-05-15 15:09:35 -06001839 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
Jon Ashburn95a77ba2015-05-15 15:09:35 -06001840
Jon Ashburn95a77ba2015-05-15 15:09:35 -06001841 if (icd->CreateDevice) {
1842 res = icd->CreateDevice(gpu, pCreateInfo, pDevice);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001843 if (res != VK_SUCCESS) {
1844 return res;
Jon Ashburn95a77ba2015-05-15 15:09:35 -06001845 }
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001846 dev = loader_add_logical_device(*pDevice, &icd->logical_device_list);
David Pinedoa0a8a242015-06-24 15:29:18 -06001847 if (dev == NULL) {
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001848 return VK_ERROR_OUT_OF_HOST_MEMORY;
David Pinedoa0a8a242015-06-24 15:29:18 -06001849 }
Jon Ashburnd6a5b672015-06-08 16:38:48 -06001850 PFN_vkGetDeviceProcAddr get_proc_addr = icd->GetDeviceProcAddr;
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001851 loader_init_device_dispatch_table(&dev->loader_dispatch, get_proc_addr,
1852 icd->gpus[gpu_index], icd->gpus[gpu_index]);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001853
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001854 loader_init_dispatch(*pDevice, &dev->loader_dispatch);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001855
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001856 dev->app_extension_count = pCreateInfo->extensionCount;
1857 dev->app_extension_props = (VkExtensionProperties *) malloc(sizeof(VkExtensionProperties) * pCreateInfo->extensionCount);
1858 if (dev->app_extension_props == NULL && (dev->app_extension_count > 0)) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001859 return VK_ERROR_OUT_OF_HOST_MEMORY;
1860 }
1861
1862 /* Make local copy of extension list */
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001863 if (dev->app_extension_count > 0 && dev->app_extension_props != NULL) {
1864 memcpy(dev->app_extension_props, pCreateInfo->pEnabledExtensions, sizeof(VkExtensionProperties) * pCreateInfo->extensionCount);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001865 }
1866
Courtney Goeltzenleuchteree3b16a2015-06-01 14:12:42 -06001867 /*
1868 * Put together the complete list of extensions to enable
1869 * This includes extensions requested via environment variables.
1870 */
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001871 loader_enable_device_layers(dev);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001872
Courtney Goeltzenleuchteree3b16a2015-06-01 14:12:42 -06001873 /*
1874 * Load the libraries needed by the extensions on the
Jon Ashburn953bb3c2015-06-10 16:11:42 -06001875 * enabled extension list. This will build the device chain
1876 * terminating with the selected device.
Courtney Goeltzenleuchteree3b16a2015-06-01 14:12:42 -06001877 */
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001878 loader_activate_device_layers(*pDevice, dev, icd,
1879 dev->app_extension_count,
1880 dev->app_extension_props);
Jon Ashburn95a77ba2015-05-15 15:09:35 -06001881 }
1882
1883 return res;
1884}
1885
Courtney Goeltzenleuchter9ec39ac2015-06-22 17:45:21 -06001886static void * VKAPI loader_GetInstanceProcAddr(VkInstance instance, const char * pName)
Jon Ashburnb0fbe912015-05-06 10:15:07 -06001887{
Jon Ashburn07daee72015-05-21 18:13:33 -06001888 if (instance == VK_NULL_HANDLE)
1889 return NULL;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001890
Jon Ashburn07daee72015-05-21 18:13:33 -06001891 void *addr;
1892 /* get entrypoint addresses that are global (in the loader)*/
1893 addr = globalGetProcAddr(pName);
1894 if (addr)
1895 return addr;
Jon Ashburnb0fbe912015-05-06 10:15:07 -06001896
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001897 struct loader_instance *ptr_instance = (struct loader_instance *) instance;
1898
Jon Ashburn922c8f62015-06-18 09:05:37 -06001899 /* return any extension global entrypoints */
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001900 addr = debug_report_instance_gpa(ptr_instance, pName);
1901 if (addr) {
1902 return addr;
1903 }
1904
Jon Ashburn922c8f62015-06-18 09:05:37 -06001905 /* TODO Remove this once WSI has no loader special code */
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001906 addr = wsi_lunarg_GetInstanceProcAddr(instance, pName);
David Pinedoa0a8a242015-06-24 15:29:18 -06001907 if (addr) {
Jon Ashburn922c8f62015-06-18 09:05:37 -06001908 return addr;
David Pinedoa0a8a242015-06-24 15:29:18 -06001909 }
Jon Ashburn07daee72015-05-21 18:13:33 -06001910
1911 /* return the instance dispatch table entrypoint for extensions */
1912 const VkLayerInstanceDispatchTable *disp_table = * (VkLayerInstanceDispatchTable **) instance;
1913 if (disp_table == NULL)
1914 return NULL;
1915
1916 addr = loader_lookup_instance_dispatch_table(disp_table, pName);
1917 if (addr)
1918 return addr;
Jon Ashburnb0fbe912015-05-06 10:15:07 -06001919
1920 return NULL;
1921}
1922
Courtney Goeltzenleuchter9ec39ac2015-06-22 17:45:21 -06001923LOADER_EXPORT void * VKAPI vkGetInstanceProcAddr(VkInstance instance, const char * pName)
1924{
1925 return loader_GetInstanceProcAddr(instance, pName);
1926}
1927
1928static void * VKAPI loader_GetDeviceProcAddr(VkDevice device, const char * pName)
Jon Ashburn1beab2d2015-01-26 14:51:40 -07001929{
Jon Ashburn8d1b0b52015-05-18 13:20:15 -06001930 if (device == VK_NULL_HANDLE) {
1931 return NULL;
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001932 }
Jon Ashburn3d526cb2015-04-13 18:10:06 -06001933
Chia-I Wuf46b81a2015-01-04 11:12:47 +08001934 void *addr;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001935
Jon Ashburn3d526cb2015-04-13 18:10:06 -06001936 /* for entrypoints that loader must handle (ie non-dispatchable or create object)
1937 make sure the loader entrypoint is returned */
1938 addr = loader_non_passthrough_gpa(pName);
Ian Elliotte19c9152015-04-15 12:53:19 -06001939 if (addr) {
Jon Ashburn3d526cb2015-04-13 18:10:06 -06001940 return addr;
Ian Elliotte19c9152015-04-15 12:53:19 -06001941 }
Jon Ashburn3d526cb2015-04-13 18:10:06 -06001942
Jon Ashburn07daee72015-05-21 18:13:33 -06001943 /* return any extension device entrypoints the loader knows about */
Jon Ashburn922c8f62015-06-18 09:05:37 -06001944 /* TODO once WSI has no loader special code remove this */
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001945 addr = wsi_lunarg_GetDeviceProcAddr(device, pName);
David Pinedoa0a8a242015-06-24 15:29:18 -06001946 if (addr) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001947 return addr;
David Pinedoa0a8a242015-06-24 15:29:18 -06001948 }
Jon Ashburn07daee72015-05-21 18:13:33 -06001949
Jon Ashburn3d526cb2015-04-13 18:10:06 -06001950 /* return the dispatch table entrypoint for the fastest case */
Jon Ashburn8d1b0b52015-05-18 13:20:15 -06001951 const VkLayerDispatchTable *disp_table = * (VkLayerDispatchTable **) device;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001952 if (disp_table == NULL)
1953 return NULL;
1954
Jon Ashburn27cd5842015-05-12 17:26:48 -06001955 addr = loader_lookup_device_dispatch_table(disp_table, pName);
Chia-I Wuf46b81a2015-01-04 11:12:47 +08001956 if (addr)
1957 return addr;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001958 else {
Jon Ashburn8d1b0b52015-05-18 13:20:15 -06001959 if (disp_table->GetDeviceProcAddr == NULL)
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001960 return NULL;
Jon Ashburn8d1b0b52015-05-18 13:20:15 -06001961 return disp_table->GetDeviceProcAddr(device, pName);
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001962 }
1963}
1964
Courtney Goeltzenleuchter9ec39ac2015-06-22 17:45:21 -06001965LOADER_EXPORT void * VKAPI vkGetDeviceProcAddr(VkDevice device, const char * pName)
1966{
1967 return loader_GetDeviceProcAddr(device, pName);
1968}
1969
Tony Barbour59a47322015-06-24 16:06:58 -06001970LOADER_EXPORT VkResult VKAPI vkGetGlobalExtensionCount(
1971 uint32_t* pCount)
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07001972{
Tony Barbour59a47322015-06-24 16:06:58 -06001973 /* Scan/discover all ICD libraries in a single-threaded manner */
1974 loader_platform_thread_once(&once_icd, loader_icd_scan);
1975
1976 /* get layer libraries in a single-threaded manner */
1977 loader_platform_thread_once(&once_layer, layer_lib_scan);
1978
1979 /* merge any duplicate extensions */
1980 loader_platform_thread_once(&once_exts, loader_coalesce_extensions);
1981
1982 loader_platform_thread_lock_mutex(&loader_lock);
1983 *pCount = loader.global_extensions.count;
1984 loader_platform_thread_unlock_mutex(&loader_lock);
1985 return VK_SUCCESS;
1986}
1987
1988LOADER_EXPORT VkResult VKAPI vkGetGlobalExtensionProperties(
1989 uint32_t extensionIndex,
1990 VkExtensionProperties* pProperties)
1991{
Jon Ashburn6301a0f2015-05-29 13:15:39 -06001992
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001993 /* Scan/discover all ICD libraries in a single-threaded manner */
1994 loader_platform_thread_once(&once_icd, loader_icd_scan);
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07001995
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001996 /* get layer libraries in a single-threaded manner */
1997 loader_platform_thread_once(&once_layer, layer_lib_scan);
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07001998
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001999 /* merge any duplicate extensions */
2000 loader_platform_thread_once(&once_exts, loader_coalesce_extensions);
2001
Tony Barbour59a47322015-06-24 16:06:58 -06002002 if (extensionIndex >= loader.global_extensions.count)
2003 return VK_ERROR_INVALID_VALUE;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06002004
Jon Ashburn6301a0f2015-05-29 13:15:39 -06002005 loader_platform_thread_lock_mutex(&loader_lock);
Tony Barbour59a47322015-06-24 16:06:58 -06002006 memcpy(pProperties,
2007 &loader.global_extensions.list[extensionIndex],
2008 sizeof(VkExtensionProperties));
2009
Jon Ashburn6301a0f2015-05-29 13:15:39 -06002010 loader_platform_thread_unlock_mutex(&loader_lock);
Tony Barbour59a47322015-06-24 16:06:58 -06002011 return VK_SUCCESS;
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07002012}
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002013
Tony Barbour59a47322015-06-24 16:06:58 -06002014VkResult loader_GetPhysicalDeviceExtensionCount(
Jon Ashburn95a77ba2015-05-15 15:09:35 -06002015 VkPhysicalDevice gpu,
Tony Barbour59a47322015-06-24 16:06:58 -06002016 uint32_t* pCount)
Jon Ashburn95a77ba2015-05-15 15:09:35 -06002017{
2018 uint32_t gpu_index;
Tony Barbour59a47322015-06-24 16:06:58 -06002019 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
2020 *pCount = icd->device_extension_cache[gpu_index].count;
2021
2022 return VK_SUCCESS;
2023}
2024
2025VkResult loader_GetPhysicalDeviceExtensionProperties(
2026 VkPhysicalDevice gpu,
2027 uint32_t extensionIndex,
2028 VkExtensionProperties* pProperties)
2029{
2030 uint32_t gpu_index;
Jon Ashburn128f9422015-05-28 19:16:58 -06002031 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07002032
Tony Barbour59a47322015-06-24 16:06:58 -06002033 if (extensionIndex >= icd->device_extension_cache[gpu_index].count)
2034 return VK_ERROR_INVALID_VALUE;
Jon Ashburn95a77ba2015-05-15 15:09:35 -06002035
Tony Barbour59a47322015-06-24 16:06:58 -06002036 memcpy( pProperties,
2037 &icd->device_extension_cache[gpu_index].list[extensionIndex],
2038 sizeof(VkExtensionProperties));
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002039
2040 return VK_SUCCESS;
Jon Ashburn95a77ba2015-05-15 15:09:35 -06002041}