blob: 12e2fe0fe6a82d75f9fa4894a683c850d2362b43 [file] [log] [blame]
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001/*
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06002 * Vulkan
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08003 *
4 * Copyright (C) 2014 LunarG, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
Chia-I Wu44e42362014-09-02 08:32:09 +080023 *
24 * Authors:
25 * Chia-I Wu <olv@lunarg.com>
Jon Ashburn406a0fe2014-11-14 09:52:42 -070026 * Jon Ashburn <jon@lunarg.com>
Chia-I Wu44e42362014-09-02 08:32:09 +080027 * Courtney Goeltzenleuchter <courtney@lunarg.com>
Ian Elliott76005132015-03-31 15:32:41 -060028 * Ian Elliott <ian@lunarg.com>
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080029 */
Jon Ashburn183dfd02014-10-22 18:13:16 -060030#define _GNU_SOURCE
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080031#include <stdio.h>
32#include <stdlib.h>
33#include <stdarg.h>
34#include <stdbool.h>
35#include <string.h>
36
Chia-I Wu894a1172014-08-04 11:18:20 +080037#include <sys/types.h>
Ian Elliott81ac44c2015-01-13 17:52:38 -070038#if defined(WIN32)
39#include "dirent_on_windows.h"
40#else // WIN32
Chia-I Wu894a1172014-08-04 11:18:20 +080041#include <dirent.h>
Ian Elliott81ac44c2015-01-13 17:52:38 -070042#endif // WIN32
Tobin Ehlis7a51d902015-07-03 10:34:49 -060043#include "vk_loader_platform.h"
Chia-I Wu468e3c32014-08-04 08:03:57 +080044#include "loader.h"
Jon Ashburncedc15f2015-05-21 18:13:33 -060045#include "wsi_lunarg.h"
Jon Ashburnfce93d92015-05-12 17:26:48 -060046#include "gpa_helper.h"
47#include "table_ops.h"
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -060048#include "debug_report.h"
Tobin Ehlis2d1d9702015-07-03 09:42:57 -060049#include "vk_icd.h"
Jon Ashburnffd5d672015-06-29 11:25:34 -060050#include "cJSON.h"
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080051
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -060052void loader_add_to_ext_list(
53 struct loader_extension_list *ext_list,
54 uint32_t prop_list_count,
55 const struct loader_extension_property *prop_list);
56
Courtney Goeltzenleuchter71cd74d2015-06-01 14:09:34 -060057static loader_platform_dl_handle loader_add_layer_lib(
58 const char *chain_type,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -060059 struct loader_layer_properties *layer_prop);
Courtney Goeltzenleuchter71cd74d2015-06-01 14:09:34 -060060
61static void loader_remove_layer_lib(
62 struct loader_instance *inst,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -060063 struct loader_layer_properties *layer_prop);
Courtney Goeltzenleuchter71cd74d2015-06-01 14:09:34 -060064
Jon Ashburnfce93d92015-05-12 17:26:48 -060065struct loader_struct loader = {0};
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080066
Courtney Goeltzenleuchter9a4f38c2015-06-22 17:45:21 -060067static void * VKAPI loader_GetInstanceProcAddr(VkInstance instance, const char * pName);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -060068static bool loader_init_ext_list(struct loader_extension_list *ext_info);
Courtney Goeltzenleuchter9a4f38c2015-06-22 17:45:21 -060069
Courtney Goeltzenleuchter8b253f92015-06-08 15:11:18 -060070enum loader_debug {
Courtney Goeltzenleuchter1d4c50f2015-07-08 18:41:08 -060071 LOADER_INFO_BIT = 0x01,
72 LOADER_WARN_BIT = 0x02,
73 LOADER_PERF_BIT = 0x04,
74 LOADER_ERROR_BIT = 0x08,
75 LOADER_DEBUG_BIT = 0x10,
Courtney Goeltzenleuchter8b253f92015-06-08 15:11:18 -060076};
77
78uint32_t g_loader_debug = 0;
79uint32_t g_loader_log_msgs = 0;
80
Jon Ashburnb40f2562015-05-29 13:15:39 -060081//thread safety lock for accessing global data structures such as "loader"
82// all entrypoints on the instance chain need to be locked except GPA
Jon Ashburnffd5d672015-06-29 11:25:34 -060083// additionally CreateDevice and DestroyDevice needs to be locked
Jon Ashburnb40f2562015-05-29 13:15:39 -060084loader_platform_thread_mutex loader_lock;
85
86const VkLayerInstanceDispatchTable instance_disp = {
Courtney Goeltzenleuchter9a4f38c2015-06-22 17:45:21 -060087 .GetInstanceProcAddr = loader_GetInstanceProcAddr,
Jon Ashburnfce93d92015-05-12 17:26:48 -060088 .CreateInstance = loader_CreateInstance,
89 .DestroyInstance = loader_DestroyInstance,
90 .EnumeratePhysicalDevices = loader_EnumeratePhysicalDevices,
Chris Forbesd7576302015-06-21 22:55:02 +120091 .GetPhysicalDeviceFeatures = loader_GetPhysicalDeviceFeatures,
Courtney Goeltzenleuchter4da96aa2015-07-12 12:52:09 -060092 .GetPhysicalDeviceFormatProperties = loader_GetPhysicalDeviceFormatProperties,
Chris Forbesd7576302015-06-21 22:55:02 +120093 .GetPhysicalDeviceLimits = loader_GetPhysicalDeviceLimits,
Tony Barbour426b9052015-06-24 16:06:58 -060094 .GetPhysicalDeviceProperties = loader_GetPhysicalDeviceProperties,
Tony Barbour426b9052015-06-24 16:06:58 -060095 .GetPhysicalDeviceQueueCount = loader_GetPhysicalDeviceQueueCount,
96 .GetPhysicalDeviceQueueProperties = loader_GetPhysicalDeviceQueueProperties,
97 .GetPhysicalDeviceMemoryProperties = loader_GetPhysicalDeviceMemoryProperties,
Tony Barbour426b9052015-06-24 16:06:58 -060098 .GetPhysicalDeviceExtensionProperties = loader_GetPhysicalDeviceExtensionProperties,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -060099 .GetPhysicalDeviceLayerProperties = loader_GetPhysicalDeviceLayerProperties,
Mark Lobodzinski83d4e6a2015-07-03 15:58:09 -0600100 .GetPhysicalDeviceSparseImageFormatProperties = loader_GetPhysicalDeviceSparseImageFormatProperties,
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600101 .DbgCreateMsgCallback = loader_DbgCreateMsgCallback,
102 .DbgDestroyMsgCallback = loader_DbgDestroyMsgCallback,
Jon Ashburnfce93d92015-05-12 17:26:48 -0600103};
104
105LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_icd);
106LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_layer);
107LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_exts);
Ian Elliott81ac44c2015-01-13 17:52:38 -0700108
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600109void* loader_heap_alloc(
110 struct loader_instance *instance,
111 size_t size,
112 VkSystemAllocType alloc_type)
113{
114 if (instance && instance->alloc_callbacks.pfnAlloc) {
115 /* TODO: What should default alignment be? 1, 4, 8, other? */
116 return instance->alloc_callbacks.pfnAlloc(instance->alloc_callbacks.pUserData, size, 4, alloc_type);
117 }
118 return malloc(size);
119}
120
121void* loader_aligned_heap_alloc(
122 struct loader_instance *instance,
123 size_t size,
124 size_t alignment,
125 VkSystemAllocType alloc_type)
126{
127 if (!instance && instance->alloc_callbacks.pfnAlloc) {
128 return instance->alloc_callbacks.pfnAlloc(instance->alloc_callbacks.pUserData, size, alignment, alloc_type);
129 }
Cody Northrop62ac1c52015-07-08 16:48:37 -0600130#if defined(_WIN32)
131 return _aligned_malloc(alignment, size);
132#else
133 return aligned_alloc(alignment, size);
134#endif
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600135}
136
137void loader_heap_free(
138 struct loader_instance *instance,
139 void *pMem)
140{
141 if (!instance && instance->alloc_callbacks.pfnFree) {
Courtney Goeltzenleuchtere9005172015-07-10 17:39:59 -0600142 instance->alloc_callbacks.pfnFree(instance->alloc_callbacks.pUserData, pMem);
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600143 }
Courtney Goeltzenleuchtere9005172015-07-10 17:39:59 -0600144 free(pMem);
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600145}
146
Jon Ashburnee33ae72015-06-30 14:46:22 -0700147static void loader_log(VkFlags msg_type, int32_t msg_code,
148 const char *format, ...)
149{
150 char msg[256];
151 va_list ap;
152 int ret;
153
154 if (!(msg_type & g_loader_log_msgs)) {
155 return;
156 }
157
158 va_start(ap, format);
159 ret = vsnprintf(msg, sizeof(msg), format, ap);
160 if ((ret >= (int) sizeof(msg)) || ret < 0) {
161 msg[sizeof(msg)-1] = '\0';
162 }
163 va_end(ap);
164
Ian Elliott225188f2015-02-17 10:33:47 -0700165#if defined(WIN32)
Jon Ashburnee33ae72015-06-30 14:46:22 -0700166 OutputDebugString(msg);
167#endif
168 fputs(msg, stderr);
169 fputc('\n', stderr);
170}
171
172#if defined(WIN32)
173/**
174* Find the list of registry files (names within a key) in key "location".
175*
176* This function looks in the registry (hive = DEFAULT_VK_REGISTRY_HIVE) key as given in "location"
177* for a list or name/values which are added to a returned list (function return value).
178* The DWORD values within the key must be 0 or they are skipped.
179* Function return is a string with a ';' seperated list of filenames.
180* Function return is NULL if no valid name/value pairs are found in the key,
181* or the key is not found.
182*
183* \returns
184* A string list of filenames as pointer.
185* When done using the returned string list, pointer should be freed.
186*/
187static char *loader_get_registry_files(const char *location)
188{
189 LONG rtn_value;
190 HKEY hive, key;
191 DWORD access_flags = KEY_QUERY_VALUE;
192 char name[2048];
193 char *out = NULL;
194
195 hive = DEFAULT_VK_REGISTRY_HIVE;
196 rtn_value = RegOpenKeyEx(hive, location, 0, access_flags, &key);
197 if (rtn_value != ERROR_SUCCESS) {
198 // We didn't find the key. Try the 32-bit hive (where we've seen the
199 // key end up on some people's systems):
200 access_flags |= KEY_WOW64_32KEY;
201 rtn_value = RegOpenKeyEx(hive, location, 0, access_flags, &key);
202 if (rtn_value != ERROR_SUCCESS) {
203 // We still couldn't find the key, so give up:
204 return NULL;
205 }
206 }
207
208 DWORD idx = 0;
209 DWORD name_size = sizeof(name);
210 DWORD value;
211 DWORD total_size = 4096;
212 DWORD value_size = sizeof(value);
213 while((rtn_value = RegEnumValue(key, idx++, name, &name_size, NULL, NULL, (LPBYTE) &value, &value_size)) == ERROR_SUCCESS) {
214 if (value_size == sizeof(value) && value == 0) {
215 if (out == NULL) {
216 out = malloc(total_size);
217 out[0] = '\0';
218 }
219 else if (strlen(out) + name_size + 1 > total_size) {
220 out = realloc(out, total_size * 2);
221 total_size *= 2;
222 }
223 if (out == NULL) {
224 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory, failed loader_get_registry_files");
225 return NULL;
226 }
227 if (strlen(out) == 0)
228 snprintf(out, name_size + 1, "%s", name);
229 else
230 snprintf(out + strlen(out), name_size + 1, "%c%s", PATH_SEPERATOR, name);
231 }
232 }
233 return out;
234}
235
Ian Elliott225188f2015-02-17 10:33:47 -0700236#endif // WIN32
237
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600238bool compare_vk_extension_properties(const VkExtensionProperties *op1, const VkExtensionProperties *op2)
239{
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600240 return strcmp(op1->extName, op2->extName) == 0 ? true : false;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600241}
242
Jon Ashburn1b111de2015-07-06 15:40:35 -0600243/**
Jon Ashburn60378412015-07-02 12:59:25 -0600244 * Search the given ext_array for an extension
245 * matching the given vk_ext_prop
246 */
247bool has_vk_extension_property_array(
248 const VkExtensionProperties *vk_ext_prop,
249 const uint32_t count,
250 const VkExtensionProperties *ext_array)
251{
252 for (uint32_t i = 0; i < count; i++) {
253 if (compare_vk_extension_properties(vk_ext_prop, &ext_array[i]))
254 return true;
255 }
256 return false;
257}
258
Jon Ashburn1b111de2015-07-06 15:40:35 -0600259/**
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600260 * Search the given ext_list for an extension
261 * matching the given vk_ext_prop
262 */
263bool has_vk_extension_property(
264 const VkExtensionProperties *vk_ext_prop,
265 const struct loader_extension_list *ext_list)
266{
267 for (uint32_t i = 0; i < ext_list->count; i++) {
268 if (compare_vk_extension_properties(&ext_list->list[i].info, vk_ext_prop))
269 return true;
270 }
271 return false;
272}
273
274/*
Jon Ashburn1b111de2015-07-06 15:40:35 -0600275 * Search the given layer list for a layer matching the given layer name
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600276 */
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600277static struct loader_layer_properties *get_layer_property(
278 const char *name,
279 const struct loader_layer_list *layer_list)
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600280{
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600281 for (uint32_t i = 0; i < layer_list->count; i++) {
282 const VkLayerProperties *item = &layer_list->list[i].info;
283 if (strcmp(name, item->layerName) == 0)
284 return &layer_list->list[i];
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600285 }
286 return NULL;
287}
288
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600289static void loader_add_global_extensions(
Tony Barbour426b9052015-06-24 16:06:58 -0600290 const PFN_vkGetGlobalExtensionProperties fp_get_props,
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600291 const char *lib_name,
Jon Ashburn60699262015-06-10 16:11:42 -0600292 const loader_platform_dl_handle lib_handle,
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600293 const enum extension_origin origin,
294 struct loader_extension_list *ext_list)
295{
296 uint32_t i, count;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600297 struct loader_extension_property ext_props;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600298 VkExtensionProperties *extension_properties;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600299 VkResult res;
300
Courtney Goeltzenleuchteraa9faab2015-07-06 22:28:18 -0600301 if (!fp_get_props) {
302 /* No GetGlobalExtensionProperties defined */
303 return;
304 }
305
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600306 res = fp_get_props(NULL, &count, NULL);
Jon Ashburneb2728b2015-04-10 14:33:07 -0600307 if (res != VK_SUCCESS) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600308 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Error getting global extension count from %s", lib_name);
Jon Ashburneb2728b2015-04-10 14:33:07 -0600309 return;
310 }
Jon Ashburn60699262015-06-10 16:11:42 -0600311
Courtney Goeltzenleuchteraa9faab2015-07-06 22:28:18 -0600312 if (count == 0) {
313 /* No ExtensionProperties to report */
314 return;
315 }
316
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600317 extension_properties = loader_stack_alloc(count * sizeof(VkExtensionProperties));
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600318
319 res = fp_get_props(NULL, &count, extension_properties);
320 if (res != VK_SUCCESS) {
321 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Error getting global extensions from %s", lib_name);
322 return;
323 }
Tony Barbour426b9052015-06-24 16:06:58 -0600324
Jon Ashburneb2728b2015-04-10 14:33:07 -0600325 for (i = 0; i < count; i++) {
Courtney Goeltzenleuchterf4b430e2015-06-07 17:28:17 -0600326 memset(&ext_props, 0, sizeof(ext_props));
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600327 memcpy(&ext_props.info, &extension_properties[i], sizeof(VkExtensionProperties));
328 //TODO eventually get this from the layer config file
329 ext_props.origin = origin;
330 ext_props.lib_name = lib_name;
Jon Ashburn60699262015-06-10 16:11:42 -0600331
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600332 char spec_version[64], version[64];
333
334 snprintf(spec_version, sizeof(spec_version), "%d.%d.%d",
335 VK_MAJOR(ext_props.info.specVersion),
336 VK_MINOR(ext_props.info.specVersion),
337 VK_PATCH(ext_props.info.specVersion));
338 snprintf(version, sizeof(version), "%d.%d.%d",
339 VK_MAJOR(ext_props.info.version),
340 VK_MINOR(ext_props.info.version),
341 VK_PATCH(ext_props.info.version));
342
343 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
344 "Global Extension: %s (%s) version %s, Vulkan version %s",
345 ext_props.info.extName, lib_name, version, spec_version);
346 loader_add_to_ext_list(ext_list, 1, &ext_props);
347 }
348
349 return;
350}
351
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600352static void loader_add_physical_device_extensions(
353 PFN_vkGetPhysicalDeviceExtensionProperties get_phys_dev_ext_props,
354 VkPhysicalDevice physical_device,
355 const enum extension_origin origin,
356 const char *lib_name,
357 struct loader_extension_list *ext_list)
358{
359 uint32_t i, count;
360 VkResult res;
361 struct loader_extension_property ext_props;
362 VkExtensionProperties *extension_properties;
363
364 memset(&ext_props, 0, sizeof(ext_props));
365 ext_props.origin = origin;
366 ext_props.lib_name = lib_name;
367
368 if (get_phys_dev_ext_props) {
369 res = get_phys_dev_ext_props(physical_device, NULL, &count, NULL);
370 if (res == VK_SUCCESS && count > 0) {
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600371
372 extension_properties = loader_stack_alloc(count * sizeof(VkExtensionProperties));
373
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600374 res = get_phys_dev_ext_props(physical_device, NULL, &count, extension_properties);
375 for (i = 0; i < count; i++) {
376 char spec_version[64], version[64];
377
378 memcpy(&ext_props.info, &extension_properties[i], sizeof(VkExtensionProperties));
379
380 snprintf(spec_version, sizeof(spec_version), "%d.%d.%d",
381 VK_MAJOR(ext_props.info.specVersion),
382 VK_MINOR(ext_props.info.specVersion),
383 VK_PATCH(ext_props.info.specVersion));
384 snprintf(version, sizeof(version), "%d.%d.%d",
385 VK_MAJOR(ext_props.info.version),
386 VK_MINOR(ext_props.info.version),
387 VK_PATCH(ext_props.info.version));
388
389 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
390 "PhysicalDevice Extension: %s (%s) version %s, Vulkan version %s",
391 ext_props.info.extName, lib_name, version, spec_version);
392 loader_add_to_ext_list(ext_list, 1, &ext_props);
Jon Ashburn60699262015-06-10 16:11:42 -0600393 }
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600394 } else {
395 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Error getting physical device extension info count from Layer %s", ext_props.lib_name);
Jon Ashburneb2728b2015-04-10 14:33:07 -0600396 }
Jon Ashburneb2728b2015-04-10 14:33:07 -0600397 }
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600398
Jon Ashburneb2728b2015-04-10 14:33:07 -0600399 return;
400}
401
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600402static void loader_add_physical_device_layer_properties(
403 struct loader_icd *icd,
404 char *lib_name,
405 const loader_platform_dl_handle lib_handle)
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -0600406{
407 uint32_t i, count;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600408 VkLayerProperties *layer_properties;
409 PFN_vkGetPhysicalDeviceExtensionProperties fp_get_ext_props;
410 PFN_vkGetPhysicalDeviceLayerProperties fp_get_layer_props;
411 VkPhysicalDevice gpu = icd->gpus[0];
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -0600412 VkResult res;
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -0600413
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600414 fp_get_ext_props = loader_platform_get_proc_address(lib_handle, "vkGetPhysicalDeviceExtensionProperties");
415 if (!fp_get_ext_props) {
416 loader_log(VK_DBG_REPORT_INFO_BIT, 0,
417 "Couldn't dlsym vkGetPhysicalDeviceExtensionProperties from library %s",
418 lib_name);
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -0600419 }
420
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600421 fp_get_layer_props = loader_platform_get_proc_address(lib_handle, "vkGetPhysicalDeviceLayerProperties");
422 if (!fp_get_layer_props) {
423 loader_log(VK_DBG_REPORT_INFO_BIT, 0,
424 "Couldn't dlsym vkGetPhysicalDeviceLayerProperties from library %s",
425 lib_name);
426 return;
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -0600427 }
428
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600429 /*
430 * NOTE: We assume that all GPUs of an ICD support the same PhysicalDevice
431 * layers and extensions. Thus only ask for info about the first gpu.
432 */
433 res = fp_get_layer_props(gpu, &count, NULL);
434 if (res != VK_SUCCESS) {
435 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Error getting PhysicalDevice layer count from %s", lib_name);
436 return;
437 }
438
439 if (count == 0) {
440 return;
441 }
442
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600443 layer_properties = loader_stack_alloc(count * sizeof(VkLayerProperties));
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600444
445 res = fp_get_layer_props(gpu, &count, layer_properties);
446 if (res != VK_SUCCESS) {
447 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Error getting %d PhysicalDevice layer properties from %s",
448 count, lib_name);
449 return;
450 }
451
Jon Ashburn1b111de2015-07-06 15:40:35 -0600452 //TODO get layer properties from manifest file
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600453 for (i = 0; i < count; i++) {
454 struct loader_layer_properties layer;
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600455
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600456 memset(&layer, 0, sizeof(struct loader_layer_properties));
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600457
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600458 layer.lib_info.lib_name = lib_name;
459 memcpy(&layer.info, &layer_properties[i], sizeof(VkLayerProperties));
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600460
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600461 loader_init_ext_list(&layer.instance_extension_list);
462 loader_init_ext_list(&layer.device_extension_list);
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600463
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600464 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, "Collecting PhysicalDevice extensions for layer %s (%s)",
465 layer.info.layerName, layer.info.description);
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600466
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600467 loader_add_physical_device_extensions(
468 fp_get_ext_props,
469 icd->gpus[i],
470 VK_EXTENSION_ORIGIN_LAYER,
471 lib_name,
472 &layer.device_extension_list);
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600473
474 loader_add_to_layer_list(&icd->layer_properties_cache, 1, &layer);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600475 }
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -0600476 return;
477}
478
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600479static bool loader_init_ext_list(struct loader_extension_list *ext_info)
Jon Ashburneb2728b2015-04-10 14:33:07 -0600480{
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600481 ext_info->capacity = 32 * sizeof(struct loader_extension_property);
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600482 /* TODO: Need to use loader_stack_alloc or loader_heap_alloc */
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600483 ext_info->list = malloc(ext_info->capacity);
484 if (ext_info->list == NULL) {
485 return false;
486 }
487 memset(ext_info->list, 0, ext_info->capacity);
488 ext_info->count = 0;
489 return true;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600490}
491
Courtney Goeltzenleuchter3d8dc1f2015-06-08 15:09:22 -0600492void loader_destroy_ext_list(struct loader_extension_list *ext_info)
Jon Ashburneb2728b2015-04-10 14:33:07 -0600493{
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600494 free(ext_info->list);
495 ext_info->count = 0;
496 ext_info->capacity = 0;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600497}
Jon Ashburneb2728b2015-04-10 14:33:07 -0600498
Jon Ashburn60378412015-07-02 12:59:25 -0600499/**
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600500 * Search the given search_list for any layers in the props list.
501 * Add these to the output layer_list. Don't add duplicates to the output layer_list.
Jon Ashburn60378412015-07-02 12:59:25 -0600502 */
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -0600503static VkResult loader_add_layer_names_to_list(
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600504 struct loader_layer_list *output_list,
505 uint32_t name_count,
506 const char * const *names,
507 const struct loader_layer_list *search_list)
Jon Ashburneb2728b2015-04-10 14:33:07 -0600508{
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600509 struct loader_layer_properties *layer_prop;
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -0600510 VkResult err = VK_SUCCESS;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600511
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600512 for (uint32_t i = 0; i < name_count; i++) {
513 const char *search_target = names[i];
514 layer_prop = get_layer_property(search_target, search_list);
515 if (!layer_prop) {
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -0600516 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Unable to find layer %s", search_target);
517 err = VK_ERROR_INVALID_LAYER;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600518 continue;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600519 }
520
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600521 loader_add_to_layer_list(output_list, 1, layer_prop);
Jon Ashburneb2728b2015-04-10 14:33:07 -0600522 }
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -0600523
524 return err;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600525}
526
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600527/*
Jon Ashburn1b111de2015-07-06 15:40:35 -0600528 * Append non-duplicate extension properties defined in props
529 * to the given ext_list.
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600530 */
531void loader_add_to_ext_list(
532 struct loader_extension_list *ext_list,
533 uint32_t prop_list_count,
534 const struct loader_extension_property *props)
535{
536 uint32_t i;
537 struct loader_extension_property *cur_ext;
538
539 if (ext_list->list == NULL || ext_list->capacity == 0) {
540 loader_init_ext_list(ext_list);
541 }
542
543 if (ext_list->list == NULL)
544 return;
545
546 for (i = 0; i < prop_list_count; i++) {
547 cur_ext = (struct loader_extension_property *) &props[i];
548
549 // look for duplicates
550 if (has_vk_extension_property(&cur_ext->info, ext_list)) {
551 continue;
552 }
553
554 // add to list at end
555 // check for enough capacity
556 if (ext_list->count * sizeof(struct loader_extension_property)
557 >= ext_list->capacity) {
558 // double capacity
559 ext_list->capacity *= 2;
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600560 /* TODO: Need to use loader_stack_alloc or loader_heap_alloc */
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600561 ext_list->list = realloc(ext_list->list, ext_list->capacity);
562 }
Courtney Goeltzenleuchterf4b430e2015-06-07 17:28:17 -0600563
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600564 memcpy(&ext_list->list[ext_list->count], cur_ext, sizeof(struct loader_extension_property));
565 ext_list->count++;
566 }
567}
568
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600569/*
570 * Manage lists of VkLayerProperties
571 */
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600572static bool loader_init_layer_list(struct loader_layer_list *list)
573{
574 list->capacity = 32 * sizeof(struct loader_layer_properties);
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600575 /* TODO: Need to use loader_stack_alloc or loader_heap_alloc */
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600576 list->list = malloc(list->capacity);
577 if (list->list == NULL) {
578 return false;
579 }
580 memset(list->list, 0, list->capacity);
581 list->count = 0;
582 return true;
583}
584
585void loader_destroy_layer_list(struct loader_layer_list *layer_list)
586{
587 free(layer_list->list);
588 layer_list->count = 0;
589 layer_list->capacity = 0;
590}
591
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600592/*
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600593 * Manage list of layer libraries (loader_lib_info)
594 */
595static bool loader_init_layer_library_list(struct loader_layer_library_list *list)
596{
597 list->capacity = 32 * sizeof(struct loader_lib_info);
598 /* TODO: Need to use loader_stack_alloc or loader_heap_alloc */
599 list->list = malloc(list->capacity);
600 if (list->list == NULL) {
601 return false;
602 }
603 memset(list->list, 0, list->capacity);
604 list->count = 0;
605 return true;
606}
607
608void loader_destroy_layer_library_list(struct loader_layer_library_list *list)
609{
610 for (uint32_t i = 0; i < list->count; i++) {
611 free(list->list[i].lib_name);
612 }
613 free(list->list);
614 list->count = 0;
615 list->capacity = 0;
616}
617
618void loader_add_to_layer_library_list(
619 struct loader_layer_library_list *list,
620 uint32_t item_count,
621 const struct loader_lib_info *new_items)
622{
623 uint32_t i;
624 struct loader_lib_info *item;
625
626 if (list->list == NULL || list->capacity == 0) {
627 loader_init_layer_library_list(list);
628 }
629
630 if (list->list == NULL)
631 return;
632
633 for (i = 0; i < item_count; i++) {
634 item = (struct loader_lib_info *) &new_items[i];
635
636 // look for duplicates
637 for (uint32_t j = 0; j < list->count; j++) {
638 if (strcmp(list->list[i].lib_name, new_items->lib_name) == 0) {
639 continue;
640 }
641 }
642
643 // add to list at end
644 // check for enough capacity
645 if (list->count * sizeof(struct loader_lib_info)
646 >= list->capacity) {
647 // double capacity
648 list->capacity *= 2;
649 /* TODO: Need to use loader_stack_alloc or loader_heap_alloc */
650 list->list = realloc(list->list, list->capacity);
651 }
652
653 memcpy(&list->list[list->count], item, sizeof(struct loader_lib_info));
654 list->count++;
655 }
656}
657
Jon Ashburn1b111de2015-07-06 15:40:35 -0600658#if 0
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600659/*
660 * Add's library indicated by lib_name to list if it
661 * implements vkGetGlobalLayerProperties or
662 * vkGetPhysicalDeviceLayerProperties.
663 */
664static void loader_add_layer_library(
665 struct loader_instance *instance,
666 const char *lib_name,
667 const loader_platform_dl_handle lib_handle,
668 struct loader_layer_library_list *list)
669{
670 struct loader_lib_info *library_info;
671 PFN_vkGetPhysicalDeviceLayerProperties fp_get_phydev_props;
672 PFN_vkGetGlobalLayerProperties fp_get_layer_props;
673
674 fp_get_layer_props = loader_platform_get_proc_address(lib_handle, "vkGetGlobalLayerProperties");
675 fp_get_phydev_props = loader_platform_get_proc_address(lib_handle, "vkGetPhysicalDeviceLayerProperties");
676
677 if (!fp_get_layer_props && !fp_get_phydev_props)
678 return;
679
680 /*
681 * Allocate enough space for the library name to
682 * immediately follow the loader_lib_info structure
683 */
684 library_info = loader_heap_alloc(instance, sizeof(struct loader_lib_info) + strlen(lib_name) + 1, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
685 if (!library_info) {
686 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
687 "Malloc for layer library list failed: %s line: %d", __FILE__, __LINE__);
688 return;
689 }
690 memset(library_info, 0, sizeof(struct loader_lib_info));
691 library_info->lib_name = (char *) &library_info[1];
692 strcpy(library_info->lib_name, lib_name);
693
694 loader_add_to_layer_library_list(list, 1, library_info);
695}
Jon Ashburn1b111de2015-07-06 15:40:35 -0600696#endif
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600697/*
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600698 * Search the given layer list for a list
699 * matching the given VkLayerProperties
700 */
701bool has_vk_layer_property(
702 const VkLayerProperties *vk_layer_prop,
703 const struct loader_layer_list *list)
704{
705 for (uint32_t i = 0; i < list->count; i++) {
706 if (strcmp(vk_layer_prop->layerName, list->list[i].info.layerName) == 0)
707 return true;
708 }
709 return false;
710}
711
712/*
713 * Search the given layer list for a layer
714 * matching the given name
715 */
716bool has_layer_name(
717 const char *name,
718 const struct loader_layer_list *list)
719{
720 for (uint32_t i = 0; i < list->count; i++) {
721 if (strcmp(name, list->list[i].info.layerName) == 0)
722 return true;
723 }
724 return false;
725}
726
727/*
728 * Append non-duplicate layer properties defined in prop_list
729 * to the given layer_info list
730 */
731void loader_add_to_layer_list(
732 struct loader_layer_list *list,
733 uint32_t prop_list_count,
734 const struct loader_layer_properties *props)
735{
736 uint32_t i;
737 struct loader_layer_properties *layer;
738
739 if (list->list == NULL || list->capacity == 0) {
740 loader_init_layer_list(list);
741 }
742
743 if (list->list == NULL)
744 return;
745
746 for (i = 0; i < prop_list_count; i++) {
747 layer = (struct loader_layer_properties *) &props[i];
748
749 // look for duplicates
750 if (has_vk_layer_property(&layer->info, list)) {
751 continue;
752 }
753
754 // add to list at end
755 // check for enough capacity
756 if (list->count * sizeof(struct loader_layer_properties)
757 >= list->capacity) {
758 // double capacity
759 list->capacity *= 2;
760 list->list = realloc(list->list, list->capacity);
761 }
762
763 memcpy(&list->list[list->count], layer, sizeof(struct loader_layer_properties));
764 list->count++;
765 }
766}
767
Jon Ashburnf2ddb732015-07-07 10:27:45 -0600768/**
769 * Search the search_list for any layer with a name
770 * that matches the given name and a type that matches the given type
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600771 * Add all matching layers to the found_list
Jon Ashburnf2ddb732015-07-07 10:27:45 -0600772 * Do not add if found loader_layer_properties is already
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600773 * on the found_list.
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600774 */
Jon Ashburn60378412015-07-02 12:59:25 -0600775static void loader_find_layer_name_add_list(
776 const char *name,
Jon Ashburnf2ddb732015-07-07 10:27:45 -0600777 const enum layer_type type,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600778 const struct loader_layer_list *search_list,
779 struct loader_layer_list *found_list)
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600780{
781 for (uint32_t i = 0; i < search_list->count; i++) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600782 struct loader_layer_properties *layer_prop = &search_list->list[i];
Jon Ashburnf2ddb732015-07-07 10:27:45 -0600783 if (0 == strcmp(layer_prop->info.layerName, name) &&
784 (layer_prop->type & type)) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600785 /* Found a layer with the same name, add to found_list */
786 loader_add_to_layer_list(found_list, 1, layer_prop);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600787 }
788 }
789}
790
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -0600791static struct loader_extension_property *get_extension_property(
792 const char *name,
793 const struct loader_extension_list *list)
Jon Ashburn42e41032015-04-14 09:15:32 -0600794{
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -0600795 for (uint32_t i = 0; i < list->count; i++) {
796 const VkExtensionProperties *item = &list->list[i].info;
797 if (strcmp(name, item->extName) == 0)
798 return &list->list[i];
Jon Ashburn42e41032015-04-14 09:15:32 -0600799 }
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -0600800 return NULL;
Jon Ashburn42e41032015-04-14 09:15:32 -0600801}
802
Jon Ashburn60378412015-07-02 12:59:25 -0600803/*
804 * For global exenstions implemented within the loader (i.e. DEBUG_REPORT
805 * the extension must provide two entry points for the loader to use:
806 * - "trampoline" entry point - this is the address returned by GetProcAddr
807 * and will always do what's necessary to support a global call.
808 * - "terminator" function - this function will be put at the end of the
809 * instance chain and will contain the necessary logica to call / process
810 * the extension for the appropriate ICDs that are available.
811 * There is no generic mechanism for including these functions, the references
812 * must be placed into the appropriate loader entry points.
813 * GetInstanceProcAddr: call extension GetInstanceProcAddr to check for GetProcAddr requests
814 * loader_coalesce_extensions(void) - add extension records to the list of global
815 * extension available to the app.
816 * instance_disp - add function pointer for terminator function to this array.
817 * The extension itself should be in a separate file that will be
818 * linked directly with the loader.
819 */
Jon Ashburnfce93d92015-05-12 17:26:48 -0600820void loader_coalesce_extensions(void)
Jon Ashburneb2728b2015-04-10 14:33:07 -0600821{
Jon Ashburneb2728b2015-04-10 14:33:07 -0600822 struct loader_scanned_icds *icd_list = loader.scanned_icd_list;
823
824 // traverse scanned icd list adding non-duplicate extensions to the list
825 while (icd_list != NULL) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600826 loader_add_to_ext_list(&loader.global_extensions,
827 icd_list->global_extension_list.count,
828 icd_list->global_extension_list.list);
Jon Ashburneb2728b2015-04-10 14:33:07 -0600829 icd_list = icd_list->next;
830 };
831
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600832 // Traverse loader's extensions, adding non-duplicate extensions to the list
833 debug_report_add_instance_extensions(&loader.global_extensions);
Jon Ashburneb2728b2015-04-10 14:33:07 -0600834}
835
Jon Ashburncb5a5ac2015-06-10 10:06:06 -0600836static struct loader_icd *loader_get_icd_and_device(const VkDevice device,
837 struct loader_device **found_dev)
838{
839 *found_dev = NULL;
840 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
841 for (struct loader_icd *icd = inst->icds; icd; icd = icd->next) {
842 for (struct loader_device *dev = icd->logical_device_list; dev; dev = dev->next)
843 if (dev->device == device) {
844 *found_dev = dev;
845 return icd;
846 }
847 }
848 }
849 return NULL;
850}
851
852static void loader_destroy_logical_device(struct loader_device *dev)
853{
854 free(dev->app_extension_props);
Jon Ashburncb5a5ac2015-06-10 10:06:06 -0600855 if (dev->activated_layer_list.count)
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600856 loader_destroy_layer_list(&dev->activated_layer_list);
Jon Ashburncb5a5ac2015-06-10 10:06:06 -0600857 free(dev);
858}
859
860static struct loader_device *loader_add_logical_device(const VkDevice dev, struct loader_device **device_list)
861{
862 struct loader_device *new_dev;
863
864 new_dev = malloc(sizeof(struct loader_device));
865 if (!new_dev) {
866 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to malloc struct laoder-device");
867 return NULL;
868 }
869
870 memset(new_dev, 0, sizeof(struct loader_device));
871
872 new_dev->next = *device_list;
873 new_dev->device = dev;
874 *device_list = new_dev;
875 return new_dev;
876}
877
878void loader_remove_logical_device(VkDevice device)
879{
880 struct loader_device *found_dev, *dev, *prev_dev;
881 struct loader_icd *icd;
882 icd = loader_get_icd_and_device(device, &found_dev);
883
884 if (!icd || !found_dev)
885 return;
886
887 prev_dev = NULL;
888 dev = icd->logical_device_list;
889 while (dev && dev != found_dev) {
890 prev_dev = dev;
891 dev = dev->next;
892 }
893
894 if (prev_dev)
895 prev_dev->next = found_dev->next;
896 else
897 icd->logical_device_list = found_dev->next;
898 loader_destroy_logical_device(found_dev);
899}
900
901
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600902static void loader_icd_destroy(
903 struct loader_instance *ptr_inst,
904 struct loader_icd *icd)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800905{
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600906 ptr_inst->total_icd_count--;
Jon Ashburnd5df54d2015-05-28 19:16:58 -0600907 free(icd->gpus);
Courtney Goeltzenleuchter6b70e362015-06-14 19:57:15 -0600908 for (struct loader_device *dev = icd->logical_device_list; dev; ) {
909 struct loader_device *next_dev = dev->next;
Jon Ashburncb5a5ac2015-06-10 10:06:06 -0600910 loader_destroy_logical_device(dev);
Courtney Goeltzenleuchter6b70e362015-06-14 19:57:15 -0600911 dev = next_dev;
912 }
Jon Ashburncb5a5ac2015-06-10 10:06:06 -0600913
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800914 free(icd);
915}
916
Jon Ashburneb2728b2015-04-10 14:33:07 -0600917static struct loader_icd * loader_icd_create(const struct loader_scanned_icds *scanned)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800918{
919 struct loader_icd *icd;
920
921 icd = malloc(sizeof(*icd));
922 if (!icd)
923 return NULL;
924
Courtney Goeltzenleuchter6f928162014-10-28 10:29:27 -0600925 memset(icd, 0, sizeof(*icd));
926
Jon Ashburn14275da2015-01-28 11:01:35 -0700927 icd->scanned_icds = scanned;
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800928
929 return icd;
930}
931
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600932static struct loader_icd *loader_icd_add(
933 struct loader_instance *ptr_inst,
934 const struct loader_scanned_icds *scanned)
Chia-I Wu894a1172014-08-04 11:18:20 +0800935{
936 struct loader_icd *icd;
937
Jon Ashburn14275da2015-01-28 11:01:35 -0700938 icd = loader_icd_create(scanned);
Chia-I Wu894a1172014-08-04 11:18:20 +0800939 if (!icd)
940 return NULL;
941
Chia-I Wu894a1172014-08-04 11:18:20 +0800942 /* prepend to the list */
Jon Ashburn3336df82015-01-29 15:45:51 -0700943 icd->next = ptr_inst->icds;
944 ptr_inst->icds = icd;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600945 ptr_inst->total_icd_count++;
Chia-I Wu894a1172014-08-04 11:18:20 +0800946
947 return icd;
948}
949
Jon Ashburn14275da2015-01-28 11:01:35 -0700950static void loader_scanned_icd_add(const char *filename)
951{
Ian Elliott81ac44c2015-01-13 17:52:38 -0700952 loader_platform_dl_handle handle;
Tony Barbourde4124d2015-07-03 10:33:54 -0600953 PFN_vkCreateInstance fp_create_inst;
954 PFN_vkGetGlobalExtensionProperties fp_get_global_ext_props;
955 PFN_vkGetPhysicalDeviceExtensionProperties fp_get_device_ext_props;
956 PFN_vkGetDeviceProcAddr fp_get_proc_addr;
Jon Ashburn14275da2015-01-28 11:01:35 -0700957 struct loader_scanned_icds *new_node;
958
Ian Elliott81ac44c2015-01-13 17:52:38 -0700959 // Used to call: dlopen(filename, RTLD_LAZY);
960 handle = loader_platform_open_library(filename);
Jon Ashburn14275da2015-01-28 11:01:35 -0700961 if (!handle) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600962 loader_log(VK_DBG_REPORT_WARN_BIT, 0, loader_platform_open_library_error(filename));
Jon Ashburn14275da2015-01-28 11:01:35 -0700963 return;
964 }
965
966#define LOOKUP(func_ptr, func) do { \
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600967 func_ptr = (PFN_vk ##func) loader_platform_get_proc_address(handle, "vk" #func); \
Jon Ashburn14275da2015-01-28 11:01:35 -0700968 if (!func_ptr) { \
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600969 loader_log(VK_DBG_REPORT_WARN_BIT, 0, loader_platform_get_proc_address_error("vk" #func)); \
Jon Ashburn14275da2015-01-28 11:01:35 -0700970 return; \
971 } \
972} while (0)
973
Jon Ashburn3336df82015-01-29 15:45:51 -0700974 LOOKUP(fp_create_inst, CreateInstance);
Tony Barbour426b9052015-06-24 16:06:58 -0600975 LOOKUP(fp_get_global_ext_props, GetGlobalExtensionProperties);
Tony Barbour426b9052015-06-24 16:06:58 -0600976 LOOKUP(fp_get_device_ext_props, GetPhysicalDeviceExtensionProperties);
Jon Ashburn60699262015-06-10 16:11:42 -0600977 LOOKUP(fp_get_proc_addr, GetDeviceProcAddr);
Jon Ashburn14275da2015-01-28 11:01:35 -0700978#undef LOOKUP
979
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600980 new_node = (struct loader_scanned_icds *) malloc(sizeof(struct loader_scanned_icds)
981 + strlen(filename) + 1);
Jon Ashburn14275da2015-01-28 11:01:35 -0700982 if (!new_node) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600983 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Out of memory can't add icd");
Jon Ashburn14275da2015-01-28 11:01:35 -0700984 return;
985 }
986
987 new_node->handle = handle;
Jon Ashburn3336df82015-01-29 15:45:51 -0700988 new_node->CreateInstance = fp_create_inst;
Tony Barbour426b9052015-06-24 16:06:58 -0600989 new_node->GetGlobalExtensionProperties = fp_get_global_ext_props;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600990 loader_init_ext_list(&new_node->global_extension_list);
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -0600991 loader_init_ext_list(&new_node->device_extension_list);
Jon Ashburn14275da2015-01-28 11:01:35 -0700992 new_node->next = loader.scanned_icd_list;
Jon Ashburn14275da2015-01-28 11:01:35 -0700993
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600994 new_node->lib_name = (char *) (new_node + 1);
995 if (!new_node->lib_name) {
996 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Out of memory can't add icd");
997 return;
998 }
999 strcpy(new_node->lib_name, filename);
1000
Jon Ashburneb2728b2015-04-10 14:33:07 -06001001 loader.scanned_icd_list = new_node;
1002
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06001003 loader_add_global_extensions(
Tony Barbour426b9052015-06-24 16:06:58 -06001004 (PFN_vkGetGlobalExtensionProperties) fp_get_global_ext_props,
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001005 new_node->lib_name,
Jon Ashburn60699262015-06-10 16:11:42 -06001006 handle,
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001007 VK_EXTENSION_ORIGIN_ICD,
1008 &new_node->global_extension_list);
Jon Ashburneb2728b2015-04-10 14:33:07 -06001009}
Ian Elliott81ac44c2015-01-13 17:52:38 -07001010
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06001011static struct loader_extension_list *loader_global_extensions(const char *pLayerName)
1012{
1013 if (pLayerName == NULL || (strlen(pLayerName) == 0)) {
1014 return &loader.global_extensions;
1015 }
1016
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -06001017 /* Find and return global extension list for given layer */
Jon Ashburn1b111de2015-07-06 15:40:35 -06001018 for (uint32_t i = 0; i < loader.scanned_layers.count; i++) {
1019 struct loader_layer_properties *work_layer = &loader.scanned_layers.list[i];
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06001020 if (strcmp(work_layer->info.layerName, pLayerName) == 0) {
1021 return &work_layer->instance_extension_list;
1022 }
1023 }
1024
1025 return NULL;
1026}
1027
Jon Ashburn1b111de2015-07-06 15:40:35 -06001028static struct loader_layer_list *loader_scanned_layers()
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06001029{
Jon Ashburn1b111de2015-07-06 15:40:35 -06001030 return &loader.scanned_layers;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06001031}
1032
1033static void loader_physical_device_layers(
1034 struct loader_icd *icd,
1035 uint32_t *count,
1036 struct loader_layer_list **list)
1037{
1038 *count = icd->layer_properties_cache.count;
1039 *list = &icd->layer_properties_cache;
1040}
1041
1042static void loader_physical_device_extensions(
1043 struct loader_icd *icd,
1044 uint32_t gpu_idx,
1045 const char *layer_name,
1046 uint32_t *count,
1047 struct loader_extension_list **list)
1048{
1049 if (layer_name == NULL || (strlen(layer_name) == 0)) {
1050 *count = icd->device_extension_cache[gpu_idx].count;
1051 *list = &icd->device_extension_cache[gpu_idx];
1052 return;
1053 }
1054 for (uint32_t i = 0; i < icd->layer_properties_cache.count; i++) {
1055 if (strcmp(layer_name, icd->layer_properties_cache.list[i].info.layerName) == 0) {
1056 *count = icd->layer_properties_cache.list[i].device_extension_list.count;
1057 *list = &icd->layer_properties_cache.list[i].device_extension_list;
Courtney Goeltzenleuchtercbb941b2015-07-10 10:11:50 -06001058 break;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06001059 }
1060 }
1061}
1062
Jon Ashburn0dd356d2015-05-14 12:43:38 -06001063static void loader_icd_init_entrys(struct loader_icd *icd,
1064 struct loader_scanned_icds *scanned_icds)
1065{
1066 /* initialize entrypoint function pointers */
1067
1068 #define LOOKUP(func) do { \
1069 icd->func = (PFN_vk ##func) loader_platform_get_proc_address(scanned_icds->handle, "vk" #func); \
1070 if (!icd->func) { \
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001071 loader_log(VK_DBG_REPORT_WARN_BIT, 0, loader_platform_get_proc_address_error("vk" #func)); \
Jon Ashburn0dd356d2015-05-14 12:43:38 -06001072 return; \
1073 } \
1074 } while (0)
1075
Jon Ashburn1245cec2015-05-18 13:20:15 -06001076 /* could change this to use GetInstanceProcAddr in driver instead of dlsym */
1077 LOOKUP(GetDeviceProcAddr);
Jon Ashburn0dd356d2015-05-14 12:43:38 -06001078 LOOKUP(DestroyInstance);
1079 LOOKUP(EnumeratePhysicalDevices);
Chris Forbesd7576302015-06-21 22:55:02 +12001080 LOOKUP(GetPhysicalDeviceFeatures);
Courtney Goeltzenleuchter4da96aa2015-07-12 12:52:09 -06001081 LOOKUP(GetPhysicalDeviceFormatProperties);
Chris Forbesd7576302015-06-21 22:55:02 +12001082 LOOKUP(GetPhysicalDeviceLimits);
Jon Ashburn0dd356d2015-05-14 12:43:38 -06001083 LOOKUP(CreateDevice);
Tony Barbour426b9052015-06-24 16:06:58 -06001084 LOOKUP(GetPhysicalDeviceProperties);
1085 LOOKUP(GetPhysicalDeviceMemoryProperties);
Tony Barbour426b9052015-06-24 16:06:58 -06001086 LOOKUP(GetPhysicalDeviceQueueCount);
1087 LOOKUP(GetPhysicalDeviceQueueProperties);
1088 LOOKUP(GetPhysicalDeviceExtensionProperties);
Mark Lobodzinski83d4e6a2015-07-03 15:58:09 -06001089 LOOKUP(GetPhysicalDeviceSparseImageFormatProperties);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001090 LOOKUP(DbgCreateMsgCallback);
1091 LOOKUP(DbgDestroyMsgCallback);
Jon Ashburn0dd356d2015-05-14 12:43:38 -06001092#undef LOOKUP
1093
1094 return;
1095}
1096
Courtney Goeltzenleuchter8b253f92015-06-08 15:11:18 -06001097static void loader_debug_init(void)
1098{
1099 const char *env;
1100
1101 if (g_loader_debug > 0)
1102 return;
1103
1104 g_loader_debug = 0;
1105
1106 /* parse comma-separated debug options */
1107 env = getenv("LOADER_DEBUG");
1108 while (env) {
1109 const char *p = strchr(env, ',');
1110 size_t len;
1111
1112 if (p)
1113 len = p - env;
1114 else
1115 len = strlen(env);
1116
1117 if (len > 0) {
1118 if (strncmp(env, "warn", len) == 0) {
1119 g_loader_debug |= LOADER_WARN_BIT;
1120 g_loader_log_msgs |= VK_DBG_REPORT_WARN_BIT;
1121 } else if (strncmp(env, "info", len) == 0) {
1122 g_loader_debug |= LOADER_INFO_BIT;
1123 g_loader_log_msgs |= VK_DBG_REPORT_INFO_BIT;
1124 } else if (strncmp(env, "perf", len) == 0) {
1125 g_loader_debug |= LOADER_PERF_BIT;
1126 g_loader_log_msgs |= VK_DBG_REPORT_PERF_WARN_BIT;
1127 } else if (strncmp(env, "error", len) == 0) {
1128 g_loader_debug |= LOADER_ERROR_BIT;
1129 g_loader_log_msgs |= VK_DBG_REPORT_ERROR_BIT;
1130 } else if (strncmp(env, "debug", len) == 0) {
1131 g_loader_debug |= LOADER_DEBUG_BIT;
1132 g_loader_log_msgs |= VK_DBG_REPORT_DEBUG_BIT;
1133 }
1134 }
1135
1136 if (!p)
1137 break;
1138
1139 env = p + 1;
1140 }
1141}
1142
Jon Ashburnffd5d672015-06-29 11:25:34 -06001143struct loader_manifest_files {
1144 uint32_t count;
1145 char **filename_list;
1146};
1147
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06001148/**
Jon Ashburnffd5d672015-06-29 11:25:34 -06001149 * Get next file or dirname given a string list or registry key path
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06001150 *
1151 * \returns
Jon Ashburnffd5d672015-06-29 11:25:34 -06001152 * A pointer to first char in the next path.
1153 * The next path (or NULL) in the list is returned in next_path.
1154 * Note: input string is modified in some cases. PASS IN A COPY!
1155 */
Jon Ashburnffd5d672015-06-29 11:25:34 -06001156static char *loader_get_next_path(char *path)
1157{
1158 uint32_t len;
1159 char *next;
1160
1161 if (path == NULL)
1162 return NULL;
1163 next = strchr(path, PATH_SEPERATOR);
1164 if (next == NULL) {
1165 len = (uint32_t) strlen(path);
1166 next = path + len;
1167 }
1168 else {
1169 *next = '\0';
1170 next++;
1171 }
1172
1173 return next;
1174}
1175
1176/**
Jon Ashburn38144502015-07-07 15:06:25 -06001177 * Given a path which is absolute or relative. Expand the path if relative otherwise
1178 * leave the path unmodified if absolute. The path which is relative from is
1179 * given in rel_base and should include trailing directory seperator '/'
1180 *
1181 * \returns
1182 * A string in out_fullpath of the full absolute path
1183 * Side effect is that dir string maybe modified.
1184 */
1185static void loader_expand_path(const char *path,
1186 const char *rel_base,
1187 size_t out_size,
1188 char *out_fullpath)
1189{
1190 if (loader_platform_is_path_absolute(path)) {
1191 strncpy(out_fullpath, path, out_size);
1192 out_fullpath[out_size - 1] = '\0';
1193 }
1194 else {
1195 // convert relative to absolute path based on rel_base
1196 size_t len = strlen(path);
1197 strncpy(out_fullpath, rel_base, out_size);
1198 out_fullpath[out_size - 1] = '\0';
1199 assert(out_size >= strlen(out_fullpath) + len + 1);
1200 strncat(out_fullpath, path, len);
1201 }
1202}
1203
1204/**
Jon Ashburnffd5d672015-06-29 11:25:34 -06001205 * Given a filename (file) and a list of paths (dir), try to find an existing
1206 * file in the paths. If filename already is a path then no
1207 * searching in the given paths.
1208 *
1209 * \returns
1210 * A string in out_fullpath of either the full path or file.
1211 * Side effect is that dir string maybe modified.
1212 */
1213static void loader_get_fullpath(const char *file,
1214 char *dir,
1215 size_t out_size,
1216 char *out_fullpath)
1217{
1218 char *next_dir;
1219 if (strchr(file,DIRECTORY_SYMBOL) == NULL) {
1220 //find file exists with prepending given path
1221 while (*dir) {
1222 next_dir = loader_get_next_path(dir);
1223 snprintf(out_fullpath, out_size, "%s%c%s",
1224 dir, DIRECTORY_SYMBOL, file);
1225 if (loader_platform_file_exists(out_fullpath)) {
1226 return;
1227 }
1228 dir = next_dir;
1229 }
1230 }
1231 snprintf(out_fullpath, out_size, "%s", file);
1232}
1233
1234/**
1235 * Read a JSON file into a buffer.
1236 *
1237 * \returns
1238 * A pointer to a cJSON object representing the JSON parse tree.
1239 * This returned buffer should be freed by caller.
1240 */
1241static cJSON *loader_get_json(const char *filename)
1242{
1243 FILE *file;
1244 char *json_buf;
1245 cJSON *json;
1246 uint64_t len;
1247 file = fopen(filename,"rb");
1248 fseek(file, 0, SEEK_END);
1249 len = ftell(file);
1250 fseek(file, 0, SEEK_SET);
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -06001251 json_buf = (char*) loader_stack_alloc(len+1);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001252 if (json_buf == NULL) {
1253 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get JSON file");
1254 fclose(file);
1255 return NULL;
1256 }
1257 if (fread(json_buf, sizeof(char), len, file) != len) {
1258 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "fread failed can't get JSON file");
1259 fclose(file);
1260 return NULL;
1261 }
1262 fclose(file);
1263 json_buf[len] = '\0';
1264
1265 //parse text from file
1266 json = cJSON_Parse(json_buf);
1267 if (json == NULL)
1268 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Can't parse JSON file %s", filename);
1269 return json;
1270}
1271
1272/**
Jon Ashburn1b111de2015-07-06 15:40:35 -06001273 * Given a cJSON struct (json) of the top level JSON object from layer manifest
1274 * file, add entry to the layer_list.
1275 * Fill out the layer_properties in this list entry from the input cHJSON object.
1276 *
1277 * \returns
1278 * void
1279 * layer_list has a new entry and initialized accordingly.
1280 * If the json input object does not have all the required fields no entry
1281 * is added to the list.
1282 */
1283static void loader_add_layer_properties(struct loader_layer_list *layer_list,
1284 cJSON *json,
1285 bool is_implicit,
1286 char *filename)
1287{
1288 /* Fields in layer manifest file that are required:
1289 * (required) “file_format_version”
1290 * following are required in the "layer" object:
1291 * (required) "name"
1292 * (required) "type"
1293 * (required) “library_path”
1294 * (required) “abi_versions”
1295 * (required) “implementation_version”
1296 * (required) “description”
1297 * (required for implicit layers) “disable_environment”
1298 *
1299 * First get all required items and if any missing abort
1300 */
1301
1302 cJSON *item, *layer_node, *ext_item;
1303 char *temp;
1304 char *name, *type, *library_path, *abi_versions;
1305 char *implementation_version, *description;
1306 cJSON *disable_environment;
1307 int i;
1308 struct loader_extension_property ext_prop;
1309 item = cJSON_GetObjectItem(json, "file_format_version");
1310 if (item == NULL) {
1311 return;
1312 }
1313 char *file_vers = cJSON_PrintUnformatted(item);
1314 loader_log(VK_DBG_REPORT_INFO_BIT, 0, "Found manifest file %s, version %s",
1315 filename, file_vers);
1316 if (strcmp(file_vers, "\"0.9.0\"") != 0)
1317 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Unexpected manifest file version (expected 1.0.0), may cause errors");
1318 free(file_vers);
1319
1320 //TODO handle multiple layer nodes in the file
1321 //TODO handle scanned libraries not one per layer property
1322 layer_node = cJSON_GetObjectItem(json, "layer");
1323 if (layer_node == NULL) {
1324 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"layer\" object in manifest JSON file, skipping");
1325 return;
1326 }
1327#define GET_JSON_OBJECT(node, var) { \
1328 var = cJSON_GetObjectItem(node, #var); \
1329 if (var == NULL) \
1330 return; \
1331 }
1332#define GET_JSON_ITEM(node, var) { \
1333 item = cJSON_GetObjectItem(node, #var); \
1334 if (item == NULL) \
1335 return; \
1336 temp = cJSON_Print(item); \
1337 temp[strlen(temp) - 1] = '\0'; \
1338 var = malloc(strlen(temp) + 1); \
1339 strcpy(var, &temp[1]); \
1340 free(temp); \
1341 }
1342 GET_JSON_ITEM(layer_node, name)
1343 GET_JSON_ITEM(layer_node, type)
1344 GET_JSON_ITEM(layer_node, library_path)
1345 GET_JSON_ITEM(layer_node, abi_versions)
1346 GET_JSON_ITEM(layer_node, implementation_version)
1347 GET_JSON_ITEM(layer_node, description)
1348 if (is_implicit) {
1349 GET_JSON_OBJECT(layer_node, disable_environment)
1350 }
1351#undef GET_JSON_ITEM
1352#undef GET_JSON_OBJECT
1353
1354 // add list entry
1355 assert((layer_list->count + 1) * sizeof(struct loader_layer_properties) <= layer_list->capacity);
1356 struct loader_layer_properties *props = &(layer_list->list[layer_list->count]);
Jon Ashburn38144502015-07-07 15:06:25 -06001357 strncpy(props->info.layerName, name, sizeof(props->info.layerName));
1358 props->info.layerName[sizeof(props->info.layerName) - 1] = '\0';
Jon Ashburn1b111de2015-07-06 15:40:35 -06001359 free(name);
Jon Ashburn38144502015-07-07 15:06:25 -06001360
Jon Ashburnf2ddb732015-07-07 10:27:45 -06001361 if (!strcmp(type, "DEVICE"))
Jon Ashburn1b111de2015-07-06 15:40:35 -06001362 props->type = (is_implicit) ? VK_LAYER_TYPE_DEVICE_IMPLICIT : VK_LAYER_TYPE_DEVICE_EXPLICIT;
Jon Ashburnf2ddb732015-07-07 10:27:45 -06001363 if (!strcmp(type, "INSTANCE"))
Jon Ashburn1b111de2015-07-06 15:40:35 -06001364 props->type = (is_implicit) ? VK_LAYER_TYPE_INSTANCE_IMPLICIT : VK_LAYER_TYPE_INSTANCE_EXPLICIT;
Jon Ashburnf2ddb732015-07-07 10:27:45 -06001365 if (!strcmp(type, "GLOBAL"))
Jon Ashburn1b111de2015-07-06 15:40:35 -06001366 props->type = (is_implicit) ? VK_LAYER_TYPE_GLOBAL_IMPLICIT : VK_LAYER_TYPE_GLOBAL_EXPLICIT;
1367 free(type);
Jon Ashburn38144502015-07-07 15:06:25 -06001368
1369 char *fullpath = malloc(2048);
1370 char *rel_base;
1371 if (strchr(library_path, DIRECTORY_SYMBOL) == NULL) {
1372 // a filename which is assumed in the system directory
Jon Ashburnd9a9d1a2015-07-09 14:06:55 -06001373 char *def_path = loader_stack_alloc(strlen(DEFAULT_VK_LAYERS_PATH) + 1);
1374 strcpy(def_path, DEFAULT_VK_LAYERS_PATH);
1375 loader_get_fullpath(library_path, def_path, 2048, fullpath);
Jon Ashburn38144502015-07-07 15:06:25 -06001376 }
1377 else {
1378 // a relative or absolute path
1379 char *name_copy = loader_stack_alloc(strlen(filename) + 2);
1380 size_t len;
1381 strcpy(name_copy, filename);
1382 rel_base = loader_platform_dirname(name_copy);
1383 len = strlen(rel_base);
1384 rel_base[len] = DIRECTORY_SYMBOL;
1385 rel_base[len + 1] = '\0';
1386 loader_expand_path(library_path, rel_base, 2048, fullpath);
1387 }
1388 props->lib_info.lib_name = fullpath;
1389 free(library_path);
1390 //TODO merge the info with the versions and convert string to int
Jon Ashburn1b111de2015-07-06 15:40:35 -06001391 props->abi_version = abi_versions;
1392 props->impl_version = implementation_version;
Jon Ashburn38144502015-07-07 15:06:25 -06001393 strncpy(props->info.description, description, sizeof(props->info.description));
1394 props->info.description[sizeof(props->info.description) - 1] = '\0';
Jon Ashburn1b111de2015-07-06 15:40:35 -06001395 free(description);
1396 if (is_implicit) {
1397 props->disable_env_var.name = disable_environment->child->string;
1398 props->disable_env_var.value = disable_environment->child->valuestring;
1399 }
1400 layer_list->count++;
1401
1402 /**
1403 * Now get all optional items and objects and put in list:
1404 * functions
1405 * instance_extensions
1406 * device_extensions
1407 * enable_environment (implicit layers only)
1408 */
1409#define GET_JSON_OBJECT(node, var) { \
1410 var = cJSON_GetObjectItem(node, #var); \
1411 }
1412#define GET_JSON_ITEM(node, var) { \
1413 item = cJSON_GetObjectItem(node, #var); \
1414 if (item != NULL) \
1415 temp = cJSON_Print(item); \
1416 temp[strlen(temp) - 1] = '\0'; \
1417 var = malloc(strlen(temp) + 1); \
1418 strcpy(var, &temp[1]); \
1419 free(temp); \
1420 }
1421
1422 cJSON *instance_extensions, *device_extensions, *functions, *enable_environment;
1423 char *vkGetInstanceProcAddr, *vkGetDeviceProcAddr, *version;
1424 GET_JSON_OBJECT(layer_node, functions)
1425 if (functions != NULL) {
1426 GET_JSON_ITEM(functions, vkGetInstanceProcAddr)
1427 GET_JSON_ITEM(functions, vkGetDeviceProcAddr)
1428 props->functions.str_gipa = vkGetInstanceProcAddr;
1429 props->functions.str_gdpa = vkGetDeviceProcAddr;
1430 }
1431 GET_JSON_OBJECT(layer_node, instance_extensions)
1432 if (instance_extensions != NULL) {
1433 int count = cJSON_GetArraySize(instance_extensions);
1434 for (i = 0; i < count; i++) {
1435 ext_item = cJSON_GetArrayItem(instance_extensions, i);
1436 GET_JSON_ITEM(ext_item, name)
1437 GET_JSON_ITEM(ext_item, version)
1438 ext_prop.origin = VK_EXTENSION_ORIGIN_LAYER;
1439 ext_prop.lib_name = library_path;
1440 strcpy(ext_prop.info.extName, name);
1441 //TODO convert from string to int ext_prop.info.version = version;
1442 loader_add_to_ext_list(&props->instance_extension_list, 1, &ext_prop);
1443 }
1444 }
1445 GET_JSON_OBJECT(layer_node, device_extensions)
1446 if (device_extensions != NULL) {
1447 int count = cJSON_GetArraySize(device_extensions);
1448 for (i = 0; i < count; i++) {
1449 ext_item = cJSON_GetArrayItem(device_extensions, i);
1450 GET_JSON_ITEM(ext_item, name);
1451 GET_JSON_ITEM(ext_item, version);
1452 ext_prop.origin = VK_EXTENSION_ORIGIN_LAYER;
1453 ext_prop.lib_name = library_path;
1454 strcpy(ext_prop.info.extName, name);
1455 //TODO convert from string to int ext_prop.info.version = version;
1456 loader_add_to_ext_list(&props->device_extension_list, 1, &ext_prop);
1457 }
1458 }
1459 if (is_implicit) {
1460 GET_JSON_OBJECT(layer_node, enable_environment)
1461 props->enable_env_var.name = enable_environment->child->string;
1462 props->enable_env_var.value = enable_environment->child->valuestring;
1463 }
1464#undef GET_JSON_ITEM
1465#undef GET_JSON_OBJECT
1466
1467}
1468
1469/**
Jon Ashburnffd5d672015-06-29 11:25:34 -06001470 * Find the Vulkan library manifest files.
1471 *
1472 * This function scans the location or env_override directories/files
1473 * for a list of JSON manifest files. If env_override is non-NULL
1474 * and has a valid value. Then the location is ignored. Otherwise
1475 * location is used to look for manifest files. The location
1476 * is interpreted as Registry path on Windows and a directory path(s)
1477 * on Linux.
1478 *
1479 * \returns
1480 * A string list of manifest files to be opened in out_files param.
1481 * List has a pointer to string for each manifest filename.
1482 * When done using the list in out_files, pointers should be freed.
Jon Ashburnee33ae72015-06-30 14:46:22 -07001483 * Location or override string lists can be either files or directories as follows:
1484 * | location | override
1485 * --------------------------------
1486 * Win ICD | files | files
1487 * Win Layer | files | dirs
1488 * Linux ICD | dirs | files
1489 * Linux Layer| dirs | dirs
Jon Ashburnffd5d672015-06-29 11:25:34 -06001490 */
1491static void loader_get_manifest_files(const char *env_override,
Jon Ashburnee33ae72015-06-30 14:46:22 -07001492 bool is_layer,
1493 const char *location,
1494 struct loader_manifest_files *out_files)
Jon Ashburnffd5d672015-06-29 11:25:34 -06001495{
1496 char *override = NULL;
1497 char *loc;
1498 char *file, *next_file, *name;
1499 size_t alloced_count = 64;
1500 char full_path[2048];
1501 DIR *sysdir = NULL;
Jon Ashburnee33ae72015-06-30 14:46:22 -07001502 bool list_is_dirs = false;
Jon Ashburnffd5d672015-06-29 11:25:34 -06001503 struct dirent *dent;
1504
1505 out_files->count = 0;
1506 out_files->filename_list = NULL;
1507
Jon Ashburnffd5d672015-06-29 11:25:34 -06001508 if (env_override != NULL && (override = getenv(env_override))) {
1509#if defined(__linux__)
1510 if (geteuid() != getuid()) {
Jon Ashburnee33ae72015-06-30 14:46:22 -07001511 /* Don't allow setuid apps to use the env var: */
Jon Ashburnffd5d672015-06-29 11:25:34 -06001512 override = NULL;
1513 }
1514#endif
1515 }
1516
1517 if (location == NULL) {
1518 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
Jon Ashburnee33ae72015-06-30 14:46:22 -07001519 "Can't get manifest files with NULL location, env_override=%s",
1520 env_override);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001521 return;
1522 }
1523
Jon Ashburnee33ae72015-06-30 14:46:22 -07001524#if defined(__linux__)
1525 list_is_dirs = (override == NULL || is_layer) ? true : false;
1526#else //WIN32
1527 list_is_dirs = (is_layer && override != NULL) ? true : false;
1528#endif
Jon Ashburnffd5d672015-06-29 11:25:34 -06001529 // Make a copy of the input we are using so it is not modified
Jon Ashburnee33ae72015-06-30 14:46:22 -07001530 // Also handle getting the location(s) from registry on Windows
1531 if (override == NULL) {
1532#if defined (_WIN32)
1533 loc = loader_get_registry_files(location);
1534 if (loc == NULL) {
1535 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Registry lookup failed can't get manifest files");
1536 return;
1537 }
1538#else
Jon Ashburnffd5d672015-06-29 11:25:34 -06001539 loc = alloca(strlen(location) + 1);
Jon Ashburnee33ae72015-06-30 14:46:22 -07001540 if (loc == NULL) {
1541 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files");
1542 return;
1543 }
1544 strcpy(loc, location);
1545#endif
Jon Ashburnffd5d672015-06-29 11:25:34 -06001546 }
Jon Ashburnee33ae72015-06-30 14:46:22 -07001547 else {
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -06001548 loc = loader_stack_alloc(strlen(override) + 1);
Jon Ashburnee33ae72015-06-30 14:46:22 -07001549 if (loc == NULL) {
1550 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files");
1551 return;
1552 }
1553 strcpy(loc, override);
1554 }
Jon Ashburnffd5d672015-06-29 11:25:34 -06001555
1556 file = loc;
1557 while (*file) {
1558 next_file = loader_get_next_path(file);
Jon Ashburnee33ae72015-06-30 14:46:22 -07001559 if (list_is_dirs) {
Jon Ashburnffd5d672015-06-29 11:25:34 -06001560 sysdir = opendir(file);
1561 name = NULL;
1562 if (sysdir) {
1563 dent = readdir(sysdir);
1564 if (dent == NULL)
1565 break;
1566 name = &(dent->d_name[0]);
1567 loader_get_fullpath(name, file, sizeof(full_path), full_path);
1568 name = full_path;
1569 }
1570 }
1571 else {
Jon Ashburnee33ae72015-06-30 14:46:22 -07001572#if defined(__linux__)
1573 // only Linux has relative paths
Jon Ashburnffd5d672015-06-29 11:25:34 -06001574 char *dir;
1575 // make a copy of location so it isn't modified
1576 dir = alloca(strlen(location) + 1);
1577 if (dir == NULL) {
1578 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files");
1579 return;
1580 }
1581 strcpy(dir, location);
1582
1583 loader_get_fullpath(file, dir, sizeof(full_path), full_path);
1584
1585 name = full_path;
Jon Ashburnee33ae72015-06-30 14:46:22 -07001586#else // WIN32
1587 name = file;
1588#endif
Jon Ashburnffd5d672015-06-29 11:25:34 -06001589 }
1590 while (name) {
1591 /* Look for files ending with ".json" suffix */
1592 uint32_t nlen = (uint32_t) strlen(name);
1593 const char *suf = name + nlen - 5;
1594 if ((nlen > 5) && !strncmp(suf, ".json", 5)) {
1595 if (out_files->count == 0) {
1596 out_files->filename_list = malloc(alloced_count * sizeof(char *));
1597 }
1598 else if (out_files->count == alloced_count) {
1599 out_files->filename_list = realloc(out_files->filename_list,
1600 alloced_count * sizeof(char *) * 2);
1601 alloced_count *= 2;
1602 }
1603 if (out_files->filename_list == NULL) {
1604 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't alloc manifest file list");
1605 return;
1606 }
1607 out_files->filename_list[out_files->count] = malloc(strlen(name) + 1);
1608 if (out_files->filename_list[out_files->count] == NULL) {
1609 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files");
1610 return;
1611 }
1612 strcpy(out_files->filename_list[out_files->count], name);
1613 out_files->count++;
Jon Ashburnc5662f62015-07-02 10:08:47 -06001614 } else if (!list_is_dirs) {
1615 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Skipping manifest file %s, file name must end in .json", name);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001616 }
Jon Ashburnee33ae72015-06-30 14:46:22 -07001617 if (list_is_dirs) {
Jon Ashburnffd5d672015-06-29 11:25:34 -06001618 dent = readdir(sysdir);
1619 if (dent == NULL)
1620 break;
1621 name = &(dent->d_name[0]);
1622 loader_get_fullpath(name, file, sizeof(full_path), full_path);
1623 name = full_path;
1624 }
1625 else {
1626 break;
1627 }
1628 }
1629 if (sysdir)
1630 closedir(sysdir);
1631 file = next_file;
1632 }
1633 return;
1634}
1635
1636/**
1637 * Try to find the Vulkan ICD driver(s).
1638 *
1639 * This function scans the default system loader path(s) or path
1640 * specified by the \c VK_ICD_FILENAMES environment variable in
1641 * order to find loadable VK ICDs manifest files. From these
1642 * manifest files it finds the ICD libraries.
1643 *
1644 * \returns
Jon Ashburn622ca2f2015-06-30 16:44:28 -06001645 * void
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06001646 */
Jon Ashburnfce93d92015-05-12 17:26:48 -06001647void loader_icd_scan(void)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001648{
Jon Ashburnffd5d672015-06-29 11:25:34 -06001649 char *file_str;
1650 struct loader_manifest_files manifest_files;
1651
Jon Ashburnb40f2562015-05-29 13:15:39 -06001652
1653 // convenient place to initialize a mutex
1654 loader_platform_thread_create_mutex(&loader_lock);
1655
Jon Ashburnffd5d672015-06-29 11:25:34 -06001656 // convenient place to initialize logging
Courtney Goeltzenleuchter8b253f92015-06-08 15:11:18 -06001657 loader_debug_init();
1658
Jon Ashburnffd5d672015-06-29 11:25:34 -06001659 // Get a list of manifest files for ICDs
1660 loader_get_manifest_files("VK_ICD_FILENAMES", false, DEFAULT_VK_DRIVERS_INFO,
1661 &manifest_files);
Jon Ashburn1b111de2015-07-06 15:40:35 -06001662 if (manifest_files.count == 0)
1663 return;
Jon Ashburnffd5d672015-06-29 11:25:34 -06001664 for (uint32_t i = 0; i < manifest_files.count; i++) {
1665 file_str = manifest_files.filename_list[i];
1666 if (file_str == NULL)
1667 continue;
1668
Jon Ashburn1b111de2015-07-06 15:40:35 -06001669 cJSON *json;
Jon Ashburnffd5d672015-06-29 11:25:34 -06001670 json = loader_get_json(file_str);
Jon Ashburn1b111de2015-07-06 15:40:35 -06001671 cJSON *item;
1672 item = cJSON_GetObjectItem(json, "file_format_version");
1673 if (item == NULL)
1674 return;
1675 char *file_vers = cJSON_Print(item);
1676 loader_log(VK_DBG_REPORT_INFO_BIT, 0, "Found manifest file %s, version %s",
1677 file_str, file_vers);
1678 if (strcmp(file_vers, "\"1.0.0\"") != 0)
1679 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Unexpected manifest file version (expected 1.0.0), may cause errors");
1680 free(file_vers);
1681 item = cJSON_GetObjectItem(json, "ICD");
1682 if (item != NULL) {
1683 item = cJSON_GetObjectItem(item, "library_path");
1684 if (item != NULL) {
1685 char *icd_filename = cJSON_PrintUnformatted(item);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001686 char *icd_file = icd_filename;
1687 if (icd_filename != NULL) {
Jon Ashburnffd5d672015-06-29 11:25:34 -06001688 char def_dir[] = DEFAULT_VK_DRIVERS_PATH;
1689 char *dir = def_dir;
1690 // strip off extra quotes
1691 if (icd_filename[strlen(icd_filename) - 1] == '"')
1692 icd_filename[strlen(icd_filename) - 1] = '\0';
1693 if (icd_filename[0] == '"')
1694 icd_filename++;
Jon Ashburnee33ae72015-06-30 14:46:22 -07001695#if defined(__linux__)
1696 char full_path[2048];
Jon Ashburnffd5d672015-06-29 11:25:34 -06001697 loader_get_fullpath(icd_filename, dir, sizeof(full_path), full_path);
1698 loader_scanned_icd_add(full_path);
Jon Ashburnee33ae72015-06-30 14:46:22 -07001699#else // WIN32
1700 loader_scanned_icd_add(icd_filename);
1701#endif
Jon Ashburnffd5d672015-06-29 11:25:34 -06001702 free(icd_file);
1703 }
1704 }
1705 else
1706 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"library_path\" in ICD JSON file %s, skipping", file_str);
1707 }
1708 else
1709 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"ICD\" object in ICD JSON file %s, skipping", file_str);
1710
1711 free(file_str);
1712 cJSON_Delete(json);
1713 }
1714 free(manifest_files.filename_list);
1715
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001716}
1717
Jon Ashburnd43f9b62014-10-14 19:15:22 -06001718
Jon Ashburn68a63922015-07-02 09:40:15 -06001719void loader_layer_scan(void)
Jon Ashburnd43f9b62014-10-14 19:15:22 -06001720{
Jon Ashburn1b111de2015-07-06 15:40:35 -06001721 char *file_str;
1722 struct loader_manifest_files manifest_files;
1723 cJSON *json;
1724 uint32_t i;
Jon Ashburnd43f9b62014-10-14 19:15:22 -06001725
Jon Ashburn1b111de2015-07-06 15:40:35 -06001726 // Get a list of manifest files for layers
1727 loader_get_manifest_files(LAYERS_PATH_ENV, true, DEFAULT_VK_LAYERS_INFO,
1728 &manifest_files);
1729 if (manifest_files.count == 0)
Courtney Goeltzenleuchterbce445a2014-12-01 09:29:42 -07001730 return;
Jon Ashburn0dcd6192015-06-04 15:30:58 -06001731
Jon Ashburn1b111de2015-07-06 15:40:35 -06001732#if 0
1733 /**
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -06001734 * We need a list of the layer libraries, not just a list of
1735 * the layer properties (a layer library could expose more than
1736 * one layer property). This list of scanned layers would be
1737 * used to check for global and physicaldevice layer properties.
1738 */
1739 if (!loader_init_layer_library_list(&loader.scanned_layer_libraries)) {
1740 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
1741 "Malloc for layer list failed: %s line: %d", __FILE__, __LINE__);
1742 return;
Jon Ashburn68a63922015-07-02 09:40:15 -06001743 }
Jon Ashburn1b111de2015-07-06 15:40:35 -06001744#endif
Jon Ashburnd43f9b62014-10-14 19:15:22 -06001745
Jon Ashburn1b111de2015-07-06 15:40:35 -06001746 // TODO use global_layer add and delete functions instead
1747 if (loader.scanned_layers.capacity == 0) {
1748 loader.scanned_layers.list = malloc(sizeof(struct loader_layer_properties) * 64);
1749 if (loader.scanned_layers.list == NULL) {
1750 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can'add any layer properties to list");
1751 return;
Jon Ashburneb2728b2015-04-10 14:33:07 -06001752 }
Jon Ashburn1b111de2015-07-06 15:40:35 -06001753 memset(loader.scanned_layers.list, 0, sizeof(struct loader_layer_properties) * 64);
1754 loader.scanned_layers.capacity = sizeof(struct loader_layer_properties) * 64;
1755 }
1756 else {
1757 /* cleanup any previously scanned libraries */
1758 //TODO make sure everything is cleaned up properly
1759 for (i = 0; i < loader.scanned_layers.count; i++) {
1760 if (loader.scanned_layers.list[i].lib_info.lib_name != NULL)
1761 free(loader.scanned_layers.list[i].lib_info.lib_name);
1762 loader_destroy_ext_list(&loader.scanned_layers.list[i].instance_extension_list);
1763 loader_destroy_ext_list(&loader.scanned_layers.list[i].device_extension_list);
1764 loader.scanned_layers.list[i].lib_info.lib_name = NULL;
Jon Ashburneb2728b2015-04-10 14:33:07 -06001765 }
Jon Ashburn1b111de2015-07-06 15:40:35 -06001766 loader.scanned_layers.count = 0;
1767 }
Jon Ashburnd43f9b62014-10-14 19:15:22 -06001768
Jon Ashburn1b111de2015-07-06 15:40:35 -06001769 for (i = 0; i < manifest_files.count; i++) {
1770 file_str = manifest_files.filename_list[i];
1771 if (file_str == NULL)
1772 continue;
Courtney Goeltzenleuchteraa685052015-06-01 14:49:17 -06001773
Jon Ashburn1b111de2015-07-06 15:40:35 -06001774 // parse file into JSON struct
1775 json = loader_get_json(file_str);
1776 if (!json) {
1777 continue;
1778 }
1779 // ensure enough room to add an entry
1780 if ((loader.scanned_layers.count + 1) * sizeof (struct loader_layer_properties)
1781 > loader.scanned_layers.capacity) {
1782 loader.scanned_layers.list = realloc(loader.scanned_layers.list,
1783 loader.scanned_layers.capacity * 2);
1784 if (loader.scanned_layers.list == NULL) {
1785 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
1786 "realloc failed for scanned layers");
1787 break;
1788 }
1789 loader.scanned_layers.capacity *= 2;
1790 }
1791 //TODO pass in implicit versus explicit bool
1792 loader_add_layer_properties(&loader.scanned_layers, json, false, file_str);
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -06001793
Jon Ashburn1b111de2015-07-06 15:40:35 -06001794 free(file_str);
1795 cJSON_Delete(json);
1796 }
1797 free(manifest_files.filename_list);
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06001798
Jon Ashburnd43f9b62014-10-14 19:15:22 -06001799}
1800
Jon Ashburnfce93d92015-05-12 17:26:48 -06001801static void* VKAPI loader_gpa_instance_internal(VkInstance inst, const char * pName)
1802{
1803 // inst is not wrapped
1804 if (inst == VK_NULL_HANDLE) {
1805 return NULL;
1806 }
1807 VkLayerInstanceDispatchTable* disp_table = * (VkLayerInstanceDispatchTable **) inst;
1808 void *addr;
1809
Jon Ashburn4f2575f2015-05-28 16:25:02 -06001810 if (!strcmp(pName, "vkGetInstanceProcAddr"))
1811 return (void *) loader_gpa_instance_internal;
1812
Jon Ashburnfce93d92015-05-12 17:26:48 -06001813 if (disp_table == NULL)
1814 return NULL;
1815
1816 addr = loader_lookup_instance_dispatch_table(disp_table, pName);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001817 if (addr) {
Jon Ashburnfce93d92015-05-12 17:26:48 -06001818 return addr;
Jon Ashburne18431b2015-04-13 18:10:06 -06001819 }
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001820
1821 if (disp_table->GetInstanceProcAddr == NULL) {
1822 return NULL;
1823 }
1824 return disp_table->GetInstanceProcAddr(inst, pName);
Jon Ashburne18431b2015-04-13 18:10:06 -06001825}
1826
Jon Ashburnd5df54d2015-05-28 19:16:58 -06001827struct loader_icd * loader_get_icd(const VkPhysicalDevice gpu, uint32_t *gpu_index)
Jon Ashburnb55278a2014-10-17 15:09:07 -06001828{
Jon Ashburnd5df54d2015-05-28 19:16:58 -06001829
Jon Ashburndc67ef52015-01-29 16:44:24 -07001830 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
1831 for (struct loader_icd *icd = inst->icds; icd; icd = icd->next) {
1832 for (uint32_t i = 0; i < icd->gpu_count; i++)
Jon Ashburnd5df54d2015-05-28 19:16:58 -06001833 if (icd->gpus[i] == gpu) {
Jon Ashburndc67ef52015-01-29 16:44:24 -07001834 *gpu_index = i;
1835 return icd;
1836 }
1837 }
Jon Ashburnb55278a2014-10-17 15:09:07 -06001838 }
1839 return NULL;
1840}
1841
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001842static loader_platform_dl_handle loader_add_layer_lib(
Jon Ashburn9a9de1f2015-05-27 13:19:22 -06001843 const char *chain_type,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06001844 struct loader_layer_properties *layer_prop)
Jon Ashburnd43f9b62014-10-14 19:15:22 -06001845{
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001846 struct loader_lib_info *new_layer_lib_list, *my_lib;
1847
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -06001848 /*
1849 * TODO: We can now track this information in the
1850 * scanned_layer_libraries list.
1851 */
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001852 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06001853 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, layer_prop->lib_info.lib_name) == 0) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001854 /* Have already loaded this library, just increment ref count */
1855 loader.loaded_layer_lib_list[i].ref_count++;
Courtney Goeltzenleuchter926f39e2015-06-14 11:59:07 -06001856 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06001857 "%s Chain: Increment layer reference count for layer library %s",
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06001858 chain_type, layer_prop->lib_info.lib_name);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001859 return loader.loaded_layer_lib_list[i].lib_handle;
1860 }
1861 }
1862
1863 /* Haven't seen this library so load it */
1864 new_layer_lib_list = realloc(loader.loaded_layer_lib_list,
1865 (loader.loaded_layer_lib_count + 1) * sizeof(struct loader_lib_info));
1866 if (!new_layer_lib_list) {
1867 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "loader: malloc failed");
1868 return NULL;
1869 }
1870
1871 my_lib = &new_layer_lib_list[loader.loaded_layer_lib_count];
1872
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06001873 /* NOTE: We require that the layer property be immutable */
1874 my_lib->lib_name = (char *) layer_prop->lib_info.lib_name;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001875 my_lib->ref_count = 0;
1876 my_lib->lib_handle = NULL;
1877
1878 if ((my_lib->lib_handle = loader_platform_open_library(my_lib->lib_name)) == NULL) {
1879 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
1880 loader_platform_open_library_error(my_lib->lib_name));
1881 return NULL;
1882 } else {
Courtney Goeltzenleuchter926f39e2015-06-14 11:59:07 -06001883 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06001884 "Chain: %s: Loading layer library %s",
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06001885 chain_type, layer_prop->lib_info.lib_name);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001886 }
1887 loader.loaded_layer_lib_count++;
1888 loader.loaded_layer_lib_list = new_layer_lib_list;
1889 my_lib->ref_count++;
1890
1891 return my_lib->lib_handle;
1892}
1893
1894static void loader_remove_layer_lib(
1895 struct loader_instance *inst,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06001896 struct loader_layer_properties *layer_prop)
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001897{
1898 uint32_t idx;
1899 struct loader_lib_info *new_layer_lib_list, *my_lib;
1900
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001901 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06001902 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, layer_prop->lib_info.lib_name) == 0) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001903 /* found matching library */
1904 idx = i;
1905 my_lib = &loader.loaded_layer_lib_list[i];
1906 break;
Jon Ashburnd43f9b62014-10-14 19:15:22 -06001907 }
Jon Ashburnd43f9b62014-10-14 19:15:22 -06001908 }
Jon Ashburnd43f9b62014-10-14 19:15:22 -06001909
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001910 my_lib->ref_count--;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001911 if (my_lib->ref_count > 0) {
Courtney Goeltzenleuchter926f39e2015-06-14 11:59:07 -06001912 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06001913 "Decrement reference count for layer library %s", layer_prop->lib_info.lib_name);
Jon Ashburnfce93d92015-05-12 17:26:48 -06001914 return;
Courtney Goeltzenleuchter0199e952015-02-27 15:19:33 -07001915 }
Jon Ashburn4d3b7522015-04-14 14:14:48 -06001916
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06001917 loader_platform_close_library(my_lib->lib_handle);
Courtney Goeltzenleuchter926f39e2015-06-14 11:59:07 -06001918 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06001919 "Unloading layer library %s", layer_prop->lib_info.lib_name);
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06001920
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001921 /* Need to remove unused library from list */
1922 new_layer_lib_list = malloc((loader.loaded_layer_lib_count - 1) * sizeof(struct loader_lib_info));
1923 if (!new_layer_lib_list) {
1924 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "loader: malloc failed");
1925 return;
1926 }
1927
1928 if (idx > 0) {
1929 /* Copy records before idx */
1930 memcpy(new_layer_lib_list, &loader.loaded_layer_lib_list[0],
1931 sizeof(struct loader_lib_info) * idx);
1932 }
1933 if (idx < (loader.loaded_layer_lib_count - 1)) {
1934 /* Copy records after idx */
1935 memcpy(&new_layer_lib_list[idx], &loader.loaded_layer_lib_list[idx+1],
1936 sizeof(struct loader_lib_info) * (loader.loaded_layer_lib_count - idx - 1));
1937 }
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06001938
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001939 free(loader.loaded_layer_lib_list);
1940 loader.loaded_layer_lib_count--;
1941 loader.loaded_layer_lib_list = new_layer_lib_list;
Jon Ashburnead95c52014-11-18 09:06:04 -07001942}
1943
Jon Ashburn1b111de2015-07-06 15:40:35 -06001944
1945/**
1946 * Go through the search_list and find any layers which match type. If layer
1947 * type match is found in then add it to ext_list.
1948 */
1949//TODO need to handle implict layer enable env var and disable env var
Jon Ashburn535bd002015-07-02 16:10:32 -06001950static void loader_add_layer_implicit(
1951 const enum layer_type type,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06001952 struct loader_layer_list *list,
1953 struct loader_layer_list *search_list)
Jon Ashburn535bd002015-07-02 16:10:32 -06001954{
1955 uint32_t i;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06001956 for (i = 0; i < search_list->count; i++) {
1957 const struct loader_layer_properties *prop = &search_list->list[i];
Jon Ashburn535bd002015-07-02 16:10:32 -06001958 if (prop->type & type) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06001959 /* Found an layer with the same type, add to layer_list */
1960 loader_add_to_layer_list(list, 1, prop);
Jon Ashburn535bd002015-07-02 16:10:32 -06001961 }
1962 }
1963
1964}
1965
1966/**
1967 * Get the layer name(s) from the env_name environment variable. If layer
Jon Ashburnf2ddb732015-07-07 10:27:45 -06001968 * is found in search_list then add it to layer_list. But only add it to
1969 * layer_list if type matches.
Jon Ashburn535bd002015-07-02 16:10:32 -06001970 */
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001971static void loader_add_layer_env(
Jon Ashburnf2ddb732015-07-07 10:27:45 -06001972 const enum layer_type type,
Jon Ashburna2e6efe2015-07-02 14:10:53 -06001973 const char *env_name,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06001974 struct loader_layer_list *layer_list,
1975 const struct loader_layer_list *search_list)
Jon Ashburnd43f9b62014-10-14 19:15:22 -06001976{
Ian Elliott225188f2015-02-17 10:33:47 -07001977 char *layerEnv;
Jon Ashburna2e6efe2015-07-02 14:10:53 -06001978 char *next, *name;
Jon Ashburnd43f9b62014-10-14 19:15:22 -06001979
Jon Ashburna2e6efe2015-07-02 14:10:53 -06001980 layerEnv = getenv(env_name);
Ian Elliott225188f2015-02-17 10:33:47 -07001981 if (layerEnv == NULL) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001982 return;
Ian Elliott225188f2015-02-17 10:33:47 -07001983 }
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -06001984 name = loader_stack_alloc(strlen(layerEnv) + 1);
Jon Ashburna2e6efe2015-07-02 14:10:53 -06001985 if (name == NULL) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001986 return;
Ian Elliott225188f2015-02-17 10:33:47 -07001987 }
Jon Ashburna2e6efe2015-07-02 14:10:53 -06001988 strcpy(name, layerEnv);
Jon Ashburnd43f9b62014-10-14 19:15:22 -06001989
Jon Ashburna2e6efe2015-07-02 14:10:53 -06001990 while (name && *name ) {
1991 next = loader_get_next_path(name);
Jon Ashburnf2ddb732015-07-07 10:27:45 -06001992 loader_find_layer_name_add_list(name, type, search_list, layer_list);
Jon Ashburna2e6efe2015-07-02 14:10:53 -06001993 name = next;
Courtney Goeltzenleuchter0199e952015-02-27 15:19:33 -07001994 }
Jon Ashburnd43f9b62014-10-14 19:15:22 -06001995
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001996 return;
Jon Ashburnd43f9b62014-10-14 19:15:22 -06001997}
1998
Courtney Goeltzenleuchter3d8dc1f2015-06-08 15:09:22 -06001999void loader_deactivate_instance_layers(struct loader_instance *instance)
Jon Ashburn183dfd02014-10-22 18:13:16 -06002000{
Jon Ashburn60378412015-07-02 12:59:25 -06002001 if (!instance->activated_layer_list.count) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002002 return;
2003 }
Jon Ashburn183dfd02014-10-22 18:13:16 -06002004
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002005 /* Create instance chain of enabled layers */
Courtney Goeltzenleuchter3d8dc1f2015-06-08 15:09:22 -06002006 for (uint32_t i = 0; i < instance->activated_layer_list.count; i++) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002007 struct loader_layer_properties *layer_prop = &instance->activated_layer_list.list[i];
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002008
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002009 loader_remove_layer_lib(instance, layer_prop);
Jon Ashburn183dfd02014-10-22 18:13:16 -06002010 }
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002011 loader_destroy_layer_list(&instance->activated_layer_list);
Jon Ashburn183dfd02014-10-22 18:13:16 -06002012}
2013
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002014VkResult loader_enable_instance_layers(
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002015 struct loader_instance *inst,
2016 const VkInstanceCreateInfo *pCreateInfo)
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002017{
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002018 VkResult err;
2019
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002020 if (inst == NULL)
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002021 return VK_ERROR_UNKNOWN;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002022
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002023 if (!loader_init_layer_list(&inst->activated_layer_list)) {
Jon Ashburn60378412015-07-02 12:59:25 -06002024 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to malloc Instance activated layer list");
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002025 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburn60378412015-07-02 12:59:25 -06002026 }
2027
Jon Ashburn535bd002015-07-02 16:10:32 -06002028 /* Add any implicit layers first */
2029 loader_add_layer_implicit(
2030 VK_LAYER_TYPE_INSTANCE_IMPLICIT,
2031 &inst->activated_layer_list,
Jon Ashburn1b111de2015-07-06 15:40:35 -06002032 &loader.scanned_layers);
Jon Ashburn535bd002015-07-02 16:10:32 -06002033
Jon Ashburn1b111de2015-07-06 15:40:35 -06002034 /* Add any layers specified via environment variable next */
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002035 loader_add_layer_env(
Jon Ashburnf2ddb732015-07-07 10:27:45 -06002036 VK_LAYER_TYPE_INSTANCE_EXPLICIT,
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002037 "VK_INSTANCE_LAYERS",
2038 &inst->activated_layer_list,
Jon Ashburn1b111de2015-07-06 15:40:35 -06002039 &loader.scanned_layers);
Jon Ashburn60378412015-07-02 12:59:25 -06002040
2041 /* Add layers specified by the application */
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002042 err = loader_add_layer_names_to_list(
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002043 &inst->activated_layer_list,
2044 pCreateInfo->layerCount,
2045 pCreateInfo->ppEnabledLayerNames,
Jon Ashburn1b111de2015-07-06 15:40:35 -06002046 &loader.scanned_layers);
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002047
2048 return err;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002049}
2050
Jon Ashburnfce93d92015-05-12 17:26:48 -06002051uint32_t loader_activate_instance_layers(struct loader_instance *inst)
2052{
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002053 uint32_t layer_idx;
Jon Ashburnd5df54d2015-05-28 19:16:58 -06002054 VkBaseLayerObject *wrappedInstance;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002055
David Pinedo0fab78b2015-06-24 15:29:18 -06002056 if (inst == NULL) {
Jon Ashburnfce93d92015-05-12 17:26:48 -06002057 return 0;
David Pinedo0fab78b2015-06-24 15:29:18 -06002058 }
Jon Ashburnfce93d92015-05-12 17:26:48 -06002059
2060 // NOTE inst is unwrapped at this point in time
Tony Barbourde4124d2015-07-03 10:33:54 -06002061 void* baseObj = (void*) inst;
2062 void* nextObj = (void*) inst;
Jon Ashburnfce93d92015-05-12 17:26:48 -06002063 VkBaseLayerObject *nextInstObj;
2064 PFN_vkGetInstanceProcAddr nextGPA = loader_gpa_instance_internal;
2065
Jon Ashburn60378412015-07-02 12:59:25 -06002066 if (!inst->activated_layer_list.count) {
Jon Ashburnfce93d92015-05-12 17:26:48 -06002067 return 0;
2068 }
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002069
Courtney Goeltzenleuchter0248b992015-07-06 09:04:55 -06002070 wrappedInstance = loader_stack_alloc(sizeof(VkBaseLayerObject)
Jon Ashburn60378412015-07-02 12:59:25 -06002071 * inst->activated_layer_list.count);
Jon Ashburnd5df54d2015-05-28 19:16:58 -06002072 if (!wrappedInstance) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002073 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to malloc Instance objects for layer");
2074 return 0;
2075 }
2076
2077 /* Create instance chain of enabled layers */
Jon Ashburn60378412015-07-02 12:59:25 -06002078 layer_idx = inst->activated_layer_list.count - 1;
Courtney Goeltzenleuchterf4b430e2015-06-07 17:28:17 -06002079 for (int32_t i = inst->activated_layer_list.count - 1; i >= 0; i--) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002080 struct loader_layer_properties *layer_prop = &inst->activated_layer_list.list[i];
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002081 loader_platform_dl_handle lib_handle;
2082
Jon Ashburn60378412015-07-02 12:59:25 -06002083 /*
Courtney Goeltzenleuchterc27292a2015-06-01 14:12:42 -06002084 * Note: An extension's Get*ProcAddr should not return a function pointer for
2085 * any extension entry points until the extension has been enabled.
2086 * To do this requires a different behavior from Get*ProcAddr functions implemented
2087 * in layers.
2088 * The very first call to a layer will be it's Get*ProcAddr function requesting
2089 * the layer's vkGet*ProcAddr. The layer should intialize it's internal dispatch table
2090 * with the wrapped object given (either Instance or Device) and return the layer's
2091 * Get*ProcAddr function. The layer should also use this opportunity to record the
2092 * baseObject so that it can find the correct local dispatch table on future calls.
2093 * Subsequent calls to Get*ProcAddr, CreateInstance, CreateDevice
2094 * will not use a wrapped object and must look up their local dispatch table from
2095 * the given baseObject.
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002096 */
Jon Ashburnd5df54d2015-05-28 19:16:58 -06002097 nextInstObj = (wrappedInstance + layer_idx);
Tony Barbourde4124d2015-07-03 10:33:54 -06002098 nextInstObj->pGPA = (PFN_vkGPA) nextGPA;
Jon Ashburnfce93d92015-05-12 17:26:48 -06002099 nextInstObj->baseObject = baseObj;
2100 nextInstObj->nextObject = nextObj;
Tony Barbourde4124d2015-07-03 10:33:54 -06002101 nextObj = (void*) nextInstObj;
Jon Ashburnfce93d92015-05-12 17:26:48 -06002102
2103 char funcStr[256];
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002104 snprintf(funcStr, 256, "%sGetInstanceProcAddr", layer_prop->info.layerName);
2105 lib_handle = loader_add_layer_lib("instance", layer_prop);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002106 if ((nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, funcStr)) == NULL)
2107 nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetInstanceProcAddr");
Jon Ashburnfce93d92015-05-12 17:26:48 -06002108 if (!nextGPA) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002109 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to find vkGetInstanceProcAddr in layer %s", layer_prop->lib_info.lib_name);
Courtney Goeltzenleuchteraa685052015-06-01 14:49:17 -06002110
2111 /* TODO: Should we return nextObj, nextGPA to previous? */
Jon Ashburnfce93d92015-05-12 17:26:48 -06002112 continue;
2113 }
2114
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002115 loader_log(VK_DBG_REPORT_INFO_BIT, 0,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002116 "Insert instance layer %s (%s)",
2117 layer_prop->info.layerName,
2118 layer_prop->lib_info.lib_name);
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002119
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002120 layer_idx--;
Jon Ashburnfce93d92015-05-12 17:26:48 -06002121 }
2122
Jon Ashburn4f2575f2015-05-28 16:25:02 -06002123 loader_init_instance_core_dispatch_table(inst->disp, nextGPA, (VkInstance) nextObj, (VkInstance) baseObj);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002124
Jon Ashburn60378412015-07-02 12:59:25 -06002125 return inst->activated_layer_list.count;
Jon Ashburnfce93d92015-05-12 17:26:48 -06002126}
2127
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002128void loader_activate_instance_layer_extensions(struct loader_instance *inst)
2129{
2130
2131 loader_init_instance_extension_dispatch_table(inst->disp,
2132 inst->disp->GetInstanceProcAddr,
Jon Ashburnd5df54d2015-05-28 19:16:58 -06002133 (VkInstance) inst);
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002134}
2135
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002136static VkResult loader_enable_device_layers(
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -06002137 struct loader_icd *icd,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002138 struct loader_device *dev,
2139 const VkDeviceCreateInfo *pCreateInfo)
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002140{
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002141 VkResult err;
2142
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06002143 if (dev == NULL)
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002144 return VK_ERROR_UNKNOWN;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002145
Jon Ashburn60378412015-07-02 12:59:25 -06002146 if (dev->activated_layer_list.list == NULL || dev->activated_layer_list.capacity == 0) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002147 loader_init_layer_list(&dev->activated_layer_list);
Jon Ashburn60378412015-07-02 12:59:25 -06002148 }
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002149
Jon Ashburn60378412015-07-02 12:59:25 -06002150 if (dev->activated_layer_list.list == NULL) {
2151 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to malloc device activated layer list");
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002152 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburn60378412015-07-02 12:59:25 -06002153 }
2154
Jon Ashburn535bd002015-07-02 16:10:32 -06002155 /* Add any implicit layers first */
2156 loader_add_layer_implicit(
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002157 VK_LAYER_TYPE_DEVICE_IMPLICIT,
2158 &dev->activated_layer_list,
Jon Ashburnf2ddb732015-07-07 10:27:45 -06002159 &loader.scanned_layers);
Jon Ashburn535bd002015-07-02 16:10:32 -06002160
2161 /* Add any layers specified via environment variable next */
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002162 loader_add_layer_env(
Jon Ashburnf2ddb732015-07-07 10:27:45 -06002163 VK_LAYER_TYPE_DEVICE_EXPLICIT,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002164 "VK_DEVICE_LAYERS",
2165 &dev->activated_layer_list,
Jon Ashburnf2ddb732015-07-07 10:27:45 -06002166 &loader.scanned_layers);
Jon Ashburn60378412015-07-02 12:59:25 -06002167
2168 /* Add layers specified by the application */
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002169 err = loader_add_layer_names_to_list(
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002170 &dev->activated_layer_list,
2171 pCreateInfo->layerCount,
2172 pCreateInfo->ppEnabledLayerNames,
Jon Ashburnf2ddb732015-07-07 10:27:45 -06002173 &loader.scanned_layers);
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002174
2175 return err;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002176}
2177
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002178/*
2179 * This function terminates the device chain fro CreateDevice.
2180 * CreateDevice is a special case and so the loader call's
2181 * the ICD's CreateDevice before creating the chain. Since
2182 * we can't call CreateDevice twice we must terminate the
2183 * device chain with something else.
2184 */
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002185static VkResult scratch_vkCreateDevice(
2186 VkPhysicalDevice gpu,
2187 const VkDeviceCreateInfo *pCreateInfo,
2188 VkDevice *pDevice)
2189{
2190 return VK_SUCCESS;
2191}
2192
2193static void * VKAPI loader_GetDeviceChainProcAddr(VkDevice device, const char * name)
2194{
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002195 if (!strcmp(name, "vkGetDeviceProcAddr"))
2196 return (void *) loader_GetDeviceChainProcAddr;
2197 if (!strcmp(name, "vkCreateDevice"))
2198 return (void *) scratch_vkCreateDevice;
2199
Courtney Goeltzenleuchtere76db422015-06-29 16:09:23 -06002200 struct loader_device *found_dev;
2201 struct loader_icd *icd = loader_get_icd_and_device(device, &found_dev);
2202 return icd->GetDeviceProcAddr(device, name);
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002203}
2204
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06002205static uint32_t loader_activate_device_layers(
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -06002206 struct loader_icd *icd,
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002207 struct loader_device *dev,
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -06002208 VkDevice device)
Jon Ashburn183dfd02014-10-22 18:13:16 -06002209{
Jon Ashburn183dfd02014-10-22 18:13:16 -06002210 if (!icd)
2211 return 0;
Jon Ashburn183dfd02014-10-22 18:13:16 -06002212
David Pinedo0fab78b2015-06-24 15:29:18 -06002213 if (!dev) {
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06002214 return 0;
David Pinedo0fab78b2015-06-24 15:29:18 -06002215 }
Jon Ashburn612539f2015-06-10 10:13:10 -06002216
Jon Ashburn183dfd02014-10-22 18:13:16 -06002217 /* activate any layer libraries */
Tony Barbourde4124d2015-07-03 10:33:54 -06002218 void* nextObj = (void*) device;
2219 void* baseObj = nextObj;
Jon Ashburn612539f2015-06-10 10:13:10 -06002220 VkBaseLayerObject *nextGpuObj;
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002221 PFN_vkGetDeviceProcAddr nextGPA = loader_GetDeviceChainProcAddr;
Jon Ashburn612539f2015-06-10 10:13:10 -06002222 VkBaseLayerObject *wrappedGpus;
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002223
Jon Ashburn612539f2015-06-10 10:13:10 -06002224 if (!dev->activated_layer_list.count)
2225 return 0;
2226
2227 wrappedGpus = malloc(sizeof (VkBaseLayerObject) * dev->activated_layer_list.count);
2228 if (!wrappedGpus) {
2229 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to malloc Gpu objects for layer");
2230 return 0;
2231 }
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002232
Jon Ashburn612539f2015-06-10 10:13:10 -06002233 for (int32_t i = dev->activated_layer_list.count - 1; i >= 0; i--) {
2234
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002235 struct loader_layer_properties *layer_prop = &dev->activated_layer_list.list[i];
Jon Ashburn612539f2015-06-10 10:13:10 -06002236 loader_platform_dl_handle lib_handle;
2237
Jon Ashburn612539f2015-06-10 10:13:10 -06002238 nextGpuObj = (wrappedGpus + i);
Tony Barbourde4124d2015-07-03 10:33:54 -06002239 nextGpuObj->pGPA = (PFN_vkGPA)nextGPA;
Jon Ashburn612539f2015-06-10 10:13:10 -06002240 nextGpuObj->baseObject = baseObj;
2241 nextGpuObj->nextObject = nextObj;
Tony Barbourde4124d2015-07-03 10:33:54 -06002242 nextObj = (void*) nextGpuObj;
Jon Ashburn612539f2015-06-10 10:13:10 -06002243
2244 char funcStr[256];
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002245 snprintf(funcStr, 256, "%sGetDeviceProcAddr", layer_prop->info.layerName);
2246 lib_handle = loader_add_layer_lib("device", layer_prop);
Jon Ashburn612539f2015-06-10 10:13:10 -06002247 if ((nextGPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, funcStr)) == NULL)
2248 nextGPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetDeviceProcAddr");
2249 if (!nextGPA) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002250 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to find vkGetDeviceProcAddr in layer %s", layer_prop->info.layerName);
Jon Ashburn612539f2015-06-10 10:13:10 -06002251 continue;
2252 }
2253
2254 loader_log(VK_DBG_REPORT_INFO_BIT, 0,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002255 "Insert device layer library %s (%s)",
2256 layer_prop->info.layerName,
2257 layer_prop->lib_info.lib_name);
Jon Ashburn612539f2015-06-10 10:13:10 -06002258
2259 }
2260
2261 loader_init_device_dispatch_table(&dev->loader_dispatch, nextGPA,
Tony Barbourde4124d2015-07-03 10:33:54 -06002262 (VkDevice) nextObj, (VkDevice) baseObj);
Jon Ashburn612539f2015-06-10 10:13:10 -06002263 free(wrappedGpus);
2264
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06002265 return dev->activated_layer_list.count;
Jon Ashburn183dfd02014-10-22 18:13:16 -06002266}
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002267
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002268VkResult loader_validate_layers(
2269 const uint32_t layer_count,
2270 const char * const *ppEnabledLayerNames,
2271 struct loader_layer_list *list)
Courtney Goeltzenleuchter5d9f29b2015-07-06 17:45:08 -06002272{
2273 struct loader_layer_properties *prop;
2274
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002275 for (uint32_t i = 0; i < layer_count; i++) {
2276 prop = get_layer_property(ppEnabledLayerNames[i],
2277 list);
Courtney Goeltzenleuchter5d9f29b2015-07-06 17:45:08 -06002278 if (!prop) {
2279 return VK_ERROR_INVALID_LAYER;
2280 }
2281 }
2282
2283 return VK_SUCCESS;
2284}
2285
2286VkResult loader_validate_instance_extensions(
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002287 const VkInstanceCreateInfo *pCreateInfo)
Courtney Goeltzenleuchter5d9f29b2015-07-06 17:45:08 -06002288{
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002289 struct loader_extension_property *extension_prop;
2290 struct loader_layer_properties *layer_prop;
2291
2292 for (uint32_t i = 0; i < pCreateInfo->extensionCount; i++) {
2293 extension_prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
2294 &loader.global_extensions);
2295
2296 if (extension_prop) {
2297 continue;
2298 }
2299
2300 extension_prop = NULL;
2301
2302 /* Not in global list, search layer extension lists */
2303 for (uint32_t j = 0; j < pCreateInfo->layerCount; j++) {
2304 layer_prop = get_layer_property(pCreateInfo->ppEnabledLayerNames[i],
Jon Ashburn1b111de2015-07-06 15:40:35 -06002305 &loader.scanned_layers);
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002306
2307 if (!layer_prop) {
Courtney Goeltzenleuchter91371ff2015-07-06 20:46:50 -06002308 /* Should NOT get here, loader_validate_layers
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002309 * should have already filtered this case out.
2310 */
2311 continue;
2312 }
2313
2314 extension_prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
2315 &layer_prop->instance_extension_list);
2316 if (extension_prop) {
2317 /* Found the extension in one of the layers enabled by the app. */
2318 break;
2319 }
2320 }
2321
2322 if (!extension_prop) {
2323 /* Didn't find extension name in any of the global layers, error out */
2324 return VK_ERROR_INVALID_EXTENSION;
2325 }
2326 }
2327 return VK_SUCCESS;
2328}
2329
2330VkResult loader_validate_device_extensions(
2331 struct loader_icd *icd,
Cody Northropf02f9f82015-07-09 18:08:05 -06002332 uint32_t gpu_index,
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002333 const VkDeviceCreateInfo *pCreateInfo)
2334{
2335 struct loader_extension_property *extension_prop;
2336 struct loader_layer_properties *layer_prop;
2337
2338 for (uint32_t i = 0; i < pCreateInfo->extensionCount; i++) {
2339 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i];
2340 extension_prop = get_extension_property(extension_name,
Courtney Goeltzenleuchterd2775f72015-07-08 21:13:16 -06002341 &icd->device_extension_cache[gpu_index]);
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002342
2343 if (extension_prop) {
2344 continue;
2345 }
2346
2347 /* Not in global list, search layer extension lists */
2348 for (uint32_t j = 0; j < pCreateInfo->layerCount; j++) {
2349 const char *layer_name = pCreateInfo->ppEnabledLayerNames[j];
2350 layer_prop = get_layer_property(layer_name,
2351 &icd->layer_properties_cache);
2352
2353 if (!layer_prop) {
2354 /* Should NOT get here, loader_validate_instance_layers
2355 * should have already filtered this case out.
2356 */
2357 continue;
2358 }
2359
2360 extension_prop = get_extension_property(extension_name,
2361 &layer_prop->device_extension_list);
2362 if (extension_prop) {
2363 /* Found the extension in one of the layers enabled by the app. */
2364 break;
2365 }
2366 }
2367
2368 if (!extension_prop) {
2369 /* Didn't find extension name in any of the device layers, error out */
2370 return VK_ERROR_INVALID_EXTENSION;
2371 }
2372 }
Courtney Goeltzenleuchter5d9f29b2015-07-06 17:45:08 -06002373 return VK_SUCCESS;
2374}
2375
Jon Ashburnfce93d92015-05-12 17:26:48 -06002376VkResult loader_CreateInstance(
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002377 const VkInstanceCreateInfo* pCreateInfo,
2378 VkInstance* pInstance)
Jon Ashburn349508d2015-01-26 14:51:40 -07002379{
Jon Ashburna179dcf2015-05-21 17:42:17 -06002380 struct loader_instance *ptr_instance = *(struct loader_instance **) pInstance;
Jon Ashburn3336df82015-01-29 15:45:51 -07002381 struct loader_scanned_icds *scanned_icds;
2382 struct loader_icd *icd;
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06002383 struct loader_extension_property *prop;
2384 char **filtered_extension_names = NULL;
2385 VkInstanceCreateInfo icd_create_info;
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002386 VkResult res = VK_SUCCESS;
Jon Ashburn349508d2015-01-26 14:51:40 -07002387
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06002388 icd_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
2389 icd_create_info.layerCount = 0;
2390 icd_create_info.ppEnabledLayerNames = NULL;
2391 icd_create_info.pAllocCb = pCreateInfo->pAllocCb;
2392 icd_create_info.pAppInfo = pCreateInfo->pAppInfo;
2393 icd_create_info.pNext = pCreateInfo->pNext;
2394
2395 /*
2396 * NOTE: Need to filter the extensions to only those
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002397 * supported by the ICD.
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06002398 * No ICD will advertise support for layers. An ICD
2399 * library could support a layer, but it would be
2400 * independent of the actual ICD, just in the same library.
2401 */
2402 filtered_extension_names = loader_stack_alloc(pCreateInfo->extensionCount * sizeof(char *));
2403 if (!filtered_extension_names) {
2404 return VK_ERROR_OUT_OF_HOST_MEMORY;
2405 }
2406 icd_create_info.ppEnabledExtensionNames = (const char * const *) filtered_extension_names;
2407
Jon Ashburn3336df82015-01-29 15:45:51 -07002408 scanned_icds = loader.scanned_icd_list;
2409 while (scanned_icds) {
2410 icd = loader_icd_add(ptr_instance, scanned_icds);
2411 if (icd) {
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06002412
2413 icd_create_info.extensionCount = 0;
2414 for (uint32_t i = 0; i < pCreateInfo->extensionCount; i++) {
2415 prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
2416 &scanned_icds->global_extension_list);
2417 if (prop) {
2418 filtered_extension_names[icd_create_info.extensionCount] = (char *) pCreateInfo->ppEnabledExtensionNames[i];
2419 icd_create_info.extensionCount++;
2420 }
2421 }
2422
2423 res = scanned_icds->CreateInstance(&icd_create_info,
Jon Ashburn0dd356d2015-05-14 12:43:38 -06002424 &(icd->instance));
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06002425 if (res != VK_SUCCESS)
Jon Ashburn3336df82015-01-29 15:45:51 -07002426 {
2427 ptr_instance->icds = ptr_instance->icds->next;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002428 loader_icd_destroy(ptr_instance, icd);
Jon Ashburn0dd356d2015-05-14 12:43:38 -06002429 icd->instance = VK_NULL_HANDLE;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002430 loader_log(VK_DBG_REPORT_WARN_BIT, 0,
Jon Ashburn3336df82015-01-29 15:45:51 -07002431 "ICD ignored: failed to CreateInstance on device");
Jon Ashburn0dd356d2015-05-14 12:43:38 -06002432 } else
2433 {
2434 loader_icd_init_entrys(icd, scanned_icds);
Jon Ashburn3336df82015-01-29 15:45:51 -07002435 }
2436 }
2437 scanned_icds = scanned_icds->next;
2438 }
Jon Ashburn349508d2015-01-26 14:51:40 -07002439
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002440 /*
2441 * If no ICDs were added to instance list and res is unchanged
2442 * from it's initial value, the loader was unable to find
2443 * a suitable ICD.
2444 */
Ian Elliott617fdec2015-02-05 15:19:15 -07002445 if (ptr_instance->icds == NULL) {
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002446 if (res == VK_SUCCESS) {
2447 return VK_ERROR_INCOMPATIBLE_DRIVER;
2448 } else {
2449 return res;
2450 }
Ian Elliott617fdec2015-02-05 15:19:15 -07002451 }
Jon Ashburn3336df82015-01-29 15:45:51 -07002452
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002453 return VK_SUCCESS;
Jon Ashburn349508d2015-01-26 14:51:40 -07002454}
2455
Jon Ashburnfce93d92015-05-12 17:26:48 -06002456VkResult loader_DestroyInstance(
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -06002457 VkInstance instance)
Jon Ashburn349508d2015-01-26 14:51:40 -07002458{
Courtney Goeltzenleuchter8afefb52015-06-08 15:04:02 -06002459 struct loader_instance *ptr_instance = loader_instance(instance);
Jon Ashburn0dd356d2015-05-14 12:43:38 -06002460 struct loader_icd *icds = ptr_instance->icds;
Jon Ashburn16a16d62015-06-16 14:43:19 -06002461 struct loader_icd *next_icd;
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -06002462 VkResult res;
Jon Ashburn349508d2015-01-26 14:51:40 -07002463
2464 // Remove this instance from the list of instances:
2465 struct loader_instance *prev = NULL;
2466 struct loader_instance *next = loader.instances;
2467 while (next != NULL) {
2468 if (next == ptr_instance) {
2469 // Remove this instance from the list:
2470 if (prev)
2471 prev->next = next->next;
Jon Ashburn2cabd252015-02-03 09:26:59 -07002472 else
2473 loader.instances = next->next;
Jon Ashburn349508d2015-01-26 14:51:40 -07002474 break;
2475 }
2476 prev = next;
2477 next = next->next;
2478 }
2479 if (next == NULL) {
2480 // This must be an invalid instance handle or empty list
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06002481 return VK_ERROR_INVALID_HANDLE;
Jon Ashburn349508d2015-01-26 14:51:40 -07002482 }
2483
Jon Ashburn0dd356d2015-05-14 12:43:38 -06002484 while (icds) {
2485 if (icds->instance) {
2486 res = icds->DestroyInstance(icds->instance);
Tony Barbour22a30862015-04-22 09:02:32 -06002487 if (res != VK_SUCCESS)
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002488 loader_log(VK_DBG_REPORT_WARN_BIT, 0,
Tony Barbour22a30862015-04-22 09:02:32 -06002489 "ICD ignored: failed to DestroyInstance on device");
2490 }
Jon Ashburn16a16d62015-06-16 14:43:19 -06002491 next_icd = icds->next;
Jon Ashburn0dd356d2015-05-14 12:43:38 -06002492 icds->instance = VK_NULL_HANDLE;
Jon Ashburn16a16d62015-06-16 14:43:19 -06002493 loader_icd_destroy(ptr_instance, icds);
2494
2495 icds = next_icd;
Jon Ashburn3336df82015-01-29 15:45:51 -07002496 }
2497
Jon Ashburn349508d2015-01-26 14:51:40 -07002498
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06002499 return VK_SUCCESS;
Jon Ashburn349508d2015-01-26 14:51:40 -07002500}
2501
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002502VkResult loader_init_physical_device_info(
2503 struct loader_instance *ptr_instance)
2504{
2505 struct loader_icd *icd;
2506 uint32_t n, count = 0;
2507 VkResult res = VK_ERROR_UNKNOWN;
2508
2509 icd = ptr_instance->icds;
2510 while (icd) {
2511 res = icd->EnumeratePhysicalDevices(icd->instance, &n, NULL);
2512 if (res != VK_SUCCESS)
2513 return res;
2514 icd->gpu_count = n;
2515 count += n;
2516 icd = icd->next;
2517 }
2518
2519 ptr_instance->total_gpu_count = count;
2520
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002521 icd = ptr_instance->icds;
2522 while (icd) {
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002523
2524 n = icd->gpu_count;
Jon Ashburnd5df54d2015-05-28 19:16:58 -06002525 icd->gpus = (VkPhysicalDevice *) malloc(n * sizeof(VkPhysicalDevice));
2526 if (!icd->gpus) {
2527 /* TODO: Add cleanup code here */
2528 return VK_ERROR_OUT_OF_HOST_MEMORY;
2529 }
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002530 res = icd->EnumeratePhysicalDevices(
2531 icd->instance,
2532 &n,
Jon Ashburnd5df54d2015-05-28 19:16:58 -06002533 icd->gpus);
2534 if ((res == VK_SUCCESS) && (n == icd->gpu_count)) {
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002535
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002536 for (unsigned int i = 0; i < n; i++) {
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002537
Jon Ashburnd5df54d2015-05-28 19:16:58 -06002538 loader_init_dispatch(icd->gpus[i], ptr_instance->disp);
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002539
2540 if (!loader_init_ext_list(&icd->device_extension_cache[i])) {
2541 /* TODO: Add cleanup code here */
2542 res = VK_ERROR_OUT_OF_HOST_MEMORY;
2543 }
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002544 if (res == VK_SUCCESS) {
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002545
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002546 loader_add_physical_device_extensions(
2547 icd->GetPhysicalDeviceExtensionProperties,
2548 icd->gpus[0],
2549 VK_EXTENSION_ORIGIN_ICD,
2550 icd->scanned_icds->lib_name,
2551 &icd->device_extension_cache[i]);
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002552
Jon Ashburn1b111de2015-07-06 15:40:35 -06002553 for (uint32_t l = 0; l < loader.scanned_layers.count; l++) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002554 loader_platform_dl_handle lib_handle;
Jon Ashburn1b111de2015-07-06 15:40:35 -06002555 char *lib_name = loader.scanned_layers.list[l].lib_info.lib_name;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002556
2557 lib_handle = loader_platform_open_library(lib_name);
2558 if (lib_handle == NULL) {
2559 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, "open library failed: %s", lib_name);
2560 continue;
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002561 }
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002562 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
2563 "library: %s", lib_name);
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002564
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002565 loader_add_physical_device_layer_properties(
2566 icd, lib_name, lib_handle);
2567
2568 loader_platform_close_library(lib_handle);
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002569 }
2570 }
2571
2572 if (res != VK_SUCCESS) {
2573 /* clean up any extension lists previously created before this request failed */
2574 for (uint32_t j = 0; j < i; j++) {
2575 loader_destroy_ext_list(&icd->device_extension_cache[i]);
2576 }
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002577
2578 loader_destroy_layer_list(&icd->layer_properties_cache);
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002579 return res;
2580 }
2581 }
2582
2583 count += n;
2584 }
2585
2586 icd = icd->next;
2587 }
2588
2589 return VK_SUCCESS;
2590}
2591
Jon Ashburnfce93d92015-05-12 17:26:48 -06002592VkResult loader_EnumeratePhysicalDevices(
Courtney Goeltzenleuchter9f530cb2015-04-20 12:48:54 -06002593 VkInstance instance,
2594 uint32_t* pPhysicalDeviceCount,
2595 VkPhysicalDevice* pPhysicalDevices)
Jon Ashburn349508d2015-01-26 14:51:40 -07002596{
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002597 uint32_t index = 0;
Jon Ashburnb048a9b2015-01-28 19:57:09 -07002598 struct loader_instance *ptr_instance = (struct loader_instance *) instance;
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002599 struct loader_icd *icd = ptr_instance->icds;
Jon Ashburnb048a9b2015-01-28 19:57:09 -07002600
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002601 if (ptr_instance->total_gpu_count == 0) {
2602 loader_init_physical_device_info(ptr_instance);
Jon Ashburnb048a9b2015-01-28 19:57:09 -07002603 }
2604
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002605 *pPhysicalDeviceCount = ptr_instance->total_gpu_count;
2606 if (!pPhysicalDevices) {
2607 return VK_SUCCESS;
2608 }
Jon Ashburnb048a9b2015-01-28 19:57:09 -07002609
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002610 while (icd) {
2611 assert((index + icd->gpu_count) <= *pPhysicalDeviceCount);
Jon Ashburnd5df54d2015-05-28 19:16:58 -06002612 memcpy(&pPhysicalDevices[index], icd->gpus, icd->gpu_count * sizeof(VkPhysicalDevice));
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002613 index += icd->gpu_count;
2614 icd = icd->next;
2615 }
2616
2617 return VK_SUCCESS;
Jon Ashburn349508d2015-01-26 14:51:40 -07002618}
2619
Tony Barbour426b9052015-06-24 16:06:58 -06002620VkResult loader_GetPhysicalDeviceProperties(
Jon Ashburn0dd356d2015-05-14 12:43:38 -06002621 VkPhysicalDevice gpu,
Tony Barbour426b9052015-06-24 16:06:58 -06002622 VkPhysicalDeviceProperties* pProperties)
Jon Ashburn0dd356d2015-05-14 12:43:38 -06002623{
2624 uint32_t gpu_index;
Jon Ashburnd5df54d2015-05-28 19:16:58 -06002625 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
Jon Ashburn0dd356d2015-05-14 12:43:38 -06002626 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2627
Tony Barbour426b9052015-06-24 16:06:58 -06002628 if (icd->GetPhysicalDeviceProperties)
2629 res = icd->GetPhysicalDeviceProperties(gpu, pProperties);
2630
2631 return res;
2632}
2633
Tony Barbour426b9052015-06-24 16:06:58 -06002634VkResult loader_GetPhysicalDeviceQueueCount(
2635 VkPhysicalDevice gpu,
2636 uint32_t* pCount)
2637{
2638 uint32_t gpu_index;
2639 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
2640 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2641
2642 if (icd->GetPhysicalDeviceQueueCount)
2643 res = icd->GetPhysicalDeviceQueueCount(gpu, pCount);
2644
2645 return res;
2646}
2647
2648VkResult loader_GetPhysicalDeviceQueueProperties (
2649 VkPhysicalDevice gpu,
2650 uint32_t count,
2651 VkPhysicalDeviceQueueProperties * pProperties)
2652{
2653 uint32_t gpu_index;
2654 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
2655 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2656
2657 if (icd->GetPhysicalDeviceQueueProperties)
2658 res = icd->GetPhysicalDeviceQueueProperties(gpu, count, pProperties);
2659
2660 return res;
2661}
2662
2663VkResult loader_GetPhysicalDeviceMemoryProperties (
2664 VkPhysicalDevice gpu,
2665 VkPhysicalDeviceMemoryProperties* pProperties)
2666{
2667 uint32_t gpu_index;
2668 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
2669 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2670
2671 if (icd->GetPhysicalDeviceMemoryProperties)
2672 res = icd->GetPhysicalDeviceMemoryProperties(gpu, pProperties);
Jon Ashburn0dd356d2015-05-14 12:43:38 -06002673
2674 return res;
2675}
2676
Chris Forbesd7576302015-06-21 22:55:02 +12002677VkResult loader_GetPhysicalDeviceFeatures(
2678 VkPhysicalDevice physicalDevice,
2679 VkPhysicalDeviceFeatures* pFeatures)
2680{
2681 uint32_t gpu_index;
2682 struct loader_icd *icd = loader_get_icd(physicalDevice, &gpu_index);
2683 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2684
2685 if (icd->GetPhysicalDeviceFeatures)
2686 res = icd->GetPhysicalDeviceFeatures(physicalDevice, pFeatures);
2687
2688 return res;
2689}
2690
Courtney Goeltzenleuchter4da96aa2015-07-12 12:52:09 -06002691VkResult loader_GetPhysicalDeviceFormatProperties(
Chris Forbesd7576302015-06-21 22:55:02 +12002692 VkPhysicalDevice physicalDevice,
2693 VkFormat format,
2694 VkFormatProperties* pFormatInfo)
2695{
2696 uint32_t gpu_index;
2697 struct loader_icd *icd = loader_get_icd(physicalDevice, &gpu_index);
2698 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2699
Courtney Goeltzenleuchter4da96aa2015-07-12 12:52:09 -06002700 if (icd->GetPhysicalDeviceFormatProperties)
2701 res = icd->GetPhysicalDeviceFormatProperties(physicalDevice, format, pFormatInfo);
Chris Forbesd7576302015-06-21 22:55:02 +12002702
2703 return res;
2704}
2705
2706VkResult loader_GetPhysicalDeviceLimits(
2707 VkPhysicalDevice physicalDevice,
2708 VkPhysicalDeviceLimits* pLimits)
2709{
2710 uint32_t gpu_index;
2711 struct loader_icd *icd = loader_get_icd(physicalDevice, &gpu_index);
2712 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2713
2714 if (icd->GetPhysicalDeviceLimits)
2715 res = icd->GetPhysicalDeviceLimits(physicalDevice, pLimits);
2716
2717 return res;
2718}
2719
Mark Lobodzinski83d4e6a2015-07-03 15:58:09 -06002720VkResult loader_GetPhysicalDeviceSparseImageFormatProperties(
2721 VkPhysicalDevice physicalDevice,
2722 VkFormat format,
2723 VkImageType type,
2724 uint32_t samples,
2725 VkImageUsageFlags usage,
2726 VkImageTiling tiling,
2727 uint32_t* pNumProperties,
2728 VkSparseImageFormatProperties* pProperties)
2729{
2730 uint32_t gpu_index;
2731 struct loader_icd *icd = loader_get_icd(physicalDevice, &gpu_index);
2732 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2733
2734 if (icd->GetPhysicalDeviceSparseImageFormatProperties)
2735 res = icd->GetPhysicalDeviceSparseImageFormatProperties(physicalDevice, format, type, samples, usage, tiling, pNumProperties, pProperties);
2736
2737 return res;
2738}
2739
Jon Ashburn2666e2f2015-05-15 15:09:35 -06002740VkResult loader_CreateDevice(
2741 VkPhysicalDevice gpu,
2742 const VkDeviceCreateInfo* pCreateInfo,
2743 VkDevice* pDevice)
2744{
2745 uint32_t gpu_index;
Jon Ashburnd5df54d2015-05-28 19:16:58 -06002746 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06002747 struct loader_device *dev;
Courtney Goeltzenleuchter91371ff2015-07-06 20:46:50 -06002748 VkDeviceCreateInfo device_create_info;
2749 char **filtered_extension_names = NULL;
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002750 VkResult res;
Jon Ashburn2666e2f2015-05-15 15:09:35 -06002751
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002752 if (!icd->CreateDevice) {
2753 return VK_ERROR_INITIALIZATION_FAILED;
Jon Ashburn2666e2f2015-05-15 15:09:35 -06002754 }
2755
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002756 res = loader_validate_layers(pCreateInfo->layerCount,
2757 pCreateInfo->ppEnabledLayerNames,
2758 &icd->layer_properties_cache);
2759 if (res != VK_SUCCESS) {
2760 return res;
2761 }
2762
Courtney Goeltzenleuchterd2775f72015-07-08 21:13:16 -06002763 res = loader_validate_device_extensions(icd, gpu_index, pCreateInfo);
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002764 if (res != VK_SUCCESS) {
2765 return res;
2766 }
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002767
Courtney Goeltzenleuchter91371ff2015-07-06 20:46:50 -06002768 /*
2769 * NOTE: Need to filter the extensions to only those
2770 * supported by the ICD.
2771 * No ICD will advertise support for layers. An ICD
2772 * library could support a layer, but it would be
2773 * independent of the actual ICD, just in the same library.
2774 */
2775 filtered_extension_names = loader_stack_alloc(pCreateInfo->extensionCount * sizeof(char *));
2776 if (!filtered_extension_names) {
2777 return VK_ERROR_OUT_OF_HOST_MEMORY;
2778 }
2779
2780 /* Copy user's data */
2781 memcpy(&device_create_info, pCreateInfo, sizeof(VkDeviceCreateInfo));
2782
2783 /* ICD's do not use layers */
2784 device_create_info.layerCount = 0;
2785 device_create_info.ppEnabledLayerNames = NULL;
2786
2787 device_create_info.extensionCount = 0;
2788 device_create_info.ppEnabledExtensionNames = (const char * const *) filtered_extension_names;
2789
2790 for (uint32_t i = 0; i < pCreateInfo->extensionCount; i++) {
2791 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i];
2792 struct loader_extension_property *prop = get_extension_property(extension_name,
2793 &icd->device_extension_cache[gpu_index]);
2794 if (prop) {
2795 filtered_extension_names[device_create_info.extensionCount] = (char *) extension_name;
2796 device_create_info.extensionCount++;
2797 }
2798 }
2799
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002800 res = icd->CreateDevice(gpu, pCreateInfo, pDevice);
2801 if (res != VK_SUCCESS) {
2802 return res;
2803 }
2804
2805 dev = loader_add_logical_device(*pDevice, &icd->logical_device_list);
2806 if (dev == NULL) {
2807 return VK_ERROR_OUT_OF_HOST_MEMORY;
2808 }
2809 PFN_vkGetDeviceProcAddr get_proc_addr = icd->GetDeviceProcAddr;
2810 loader_init_device_dispatch_table(&dev->loader_dispatch, get_proc_addr,
Tony Barbourde4124d2015-07-03 10:33:54 -06002811 (VkDevice) icd->gpus[gpu_index], (VkDevice) icd->gpus[gpu_index]);
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002812
2813 dev->loader_dispatch.CreateDevice = scratch_vkCreateDevice;
2814 loader_init_dispatch(*pDevice, &dev->loader_dispatch);
2815
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002816 /*
2817 * Put together the complete list of extensions to enable
2818 * This includes extensions requested via environment variables.
2819 */
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -06002820 loader_enable_device_layers(icd, dev, pCreateInfo);
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002821
2822 /*
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002823 * Load the libraries and build the device chain
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002824 * terminating with the selected device.
2825 */
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -06002826 loader_activate_device_layers(icd, dev, *pDevice);
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002827
2828 res = dev->loader_dispatch.CreateDevice(gpu, pCreateInfo, pDevice);
2829
2830 dev->loader_dispatch.CreateDevice = icd->CreateDevice;
2831
Jon Ashburn2666e2f2015-05-15 15:09:35 -06002832 return res;
2833}
2834
Courtney Goeltzenleuchter9a4f38c2015-06-22 17:45:21 -06002835static void * VKAPI loader_GetInstanceProcAddr(VkInstance instance, const char * pName)
Jon Ashburn53c16772015-05-06 10:15:07 -06002836{
Jon Ashburncedc15f2015-05-21 18:13:33 -06002837 if (instance == VK_NULL_HANDLE)
2838 return NULL;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002839
Jon Ashburncedc15f2015-05-21 18:13:33 -06002840 void *addr;
2841 /* get entrypoint addresses that are global (in the loader)*/
2842 addr = globalGetProcAddr(pName);
2843 if (addr)
2844 return addr;
Jon Ashburn53c16772015-05-06 10:15:07 -06002845
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002846 struct loader_instance *ptr_instance = (struct loader_instance *) instance;
2847
Jon Ashburn4ebc0962015-06-18 09:05:37 -06002848 /* return any extension global entrypoints */
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002849 addr = debug_report_instance_gpa(ptr_instance, pName);
2850 if (addr) {
2851 return addr;
2852 }
2853
Jon Ashburn4ebc0962015-06-18 09:05:37 -06002854 /* TODO Remove this once WSI has no loader special code */
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002855 addr = wsi_lunarg_GetInstanceProcAddr(instance, pName);
David Pinedo0fab78b2015-06-24 15:29:18 -06002856 if (addr) {
Jon Ashburn4ebc0962015-06-18 09:05:37 -06002857 return addr;
David Pinedo0fab78b2015-06-24 15:29:18 -06002858 }
Jon Ashburncedc15f2015-05-21 18:13:33 -06002859
2860 /* return the instance dispatch table entrypoint for extensions */
2861 const VkLayerInstanceDispatchTable *disp_table = * (VkLayerInstanceDispatchTable **) instance;
2862 if (disp_table == NULL)
2863 return NULL;
2864
2865 addr = loader_lookup_instance_dispatch_table(disp_table, pName);
2866 if (addr)
2867 return addr;
Jon Ashburn53c16772015-05-06 10:15:07 -06002868
2869 return NULL;
2870}
2871
Courtney Goeltzenleuchter9a4f38c2015-06-22 17:45:21 -06002872LOADER_EXPORT void * VKAPI vkGetInstanceProcAddr(VkInstance instance, const char * pName)
2873{
2874 return loader_GetInstanceProcAddr(instance, pName);
2875}
2876
2877static void * VKAPI loader_GetDeviceProcAddr(VkDevice device, const char * pName)
Jon Ashburn349508d2015-01-26 14:51:40 -07002878{
Jon Ashburn1245cec2015-05-18 13:20:15 -06002879 if (device == VK_NULL_HANDLE) {
2880 return NULL;
Ian Elliott81ac44c2015-01-13 17:52:38 -07002881 }
Jon Ashburne18431b2015-04-13 18:10:06 -06002882
Chia-I Wu38e5a2c2015-01-04 11:12:47 +08002883 void *addr;
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002884
Jon Ashburne18431b2015-04-13 18:10:06 -06002885 /* for entrypoints that loader must handle (ie non-dispatchable or create object)
2886 make sure the loader entrypoint is returned */
2887 addr = loader_non_passthrough_gpa(pName);
Ian Elliottfdf00b62015-04-15 12:53:19 -06002888 if (addr) {
Jon Ashburne18431b2015-04-13 18:10:06 -06002889 return addr;
Ian Elliottfdf00b62015-04-15 12:53:19 -06002890 }
Jon Ashburne18431b2015-04-13 18:10:06 -06002891
Jon Ashburncedc15f2015-05-21 18:13:33 -06002892 /* return any extension device entrypoints the loader knows about */
Jon Ashburn4ebc0962015-06-18 09:05:37 -06002893 /* TODO once WSI has no loader special code remove this */
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002894 addr = wsi_lunarg_GetDeviceProcAddr(device, pName);
David Pinedo0fab78b2015-06-24 15:29:18 -06002895 if (addr) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002896 return addr;
David Pinedo0fab78b2015-06-24 15:29:18 -06002897 }
Jon Ashburncedc15f2015-05-21 18:13:33 -06002898
Jon Ashburne18431b2015-04-13 18:10:06 -06002899 /* return the dispatch table entrypoint for the fastest case */
Jon Ashburn1245cec2015-05-18 13:20:15 -06002900 const VkLayerDispatchTable *disp_table = * (VkLayerDispatchTable **) device;
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002901 if (disp_table == NULL)
2902 return NULL;
2903
Jon Ashburnfce93d92015-05-12 17:26:48 -06002904 addr = loader_lookup_device_dispatch_table(disp_table, pName);
Chia-I Wu38e5a2c2015-01-04 11:12:47 +08002905 if (addr)
2906 return addr;
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002907 else {
Jon Ashburn1245cec2015-05-18 13:20:15 -06002908 if (disp_table->GetDeviceProcAddr == NULL)
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002909 return NULL;
Jon Ashburn1245cec2015-05-18 13:20:15 -06002910 return disp_table->GetDeviceProcAddr(device, pName);
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002911 }
2912}
2913
Courtney Goeltzenleuchter9a4f38c2015-06-22 17:45:21 -06002914LOADER_EXPORT void * VKAPI vkGetDeviceProcAddr(VkDevice device, const char * pName)
2915{
2916 return loader_GetDeviceProcAddr(device, pName);
2917}
2918
Tony Barbour426b9052015-06-24 16:06:58 -06002919LOADER_EXPORT VkResult VKAPI vkGetGlobalExtensionProperties(
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002920 const char* pLayerName,
2921 uint32_t* pCount,
2922 VkExtensionProperties* pProperties)
2923{
2924 struct loader_extension_list *global_extension_list;
2925
2926 /* Scan/discover all ICD libraries in a single-threaded manner */
2927 loader_platform_thread_once(&once_icd, loader_icd_scan);
2928
2929 /* get layer libraries in a single-threaded manner */
2930 loader_platform_thread_once(&once_layer, loader_layer_scan);
2931
2932 /* merge any duplicate extensions */
2933 loader_platform_thread_once(&once_exts, loader_coalesce_extensions);
2934
2935 uint32_t copy_size;
2936
2937 if (pCount == NULL) {
2938 return VK_ERROR_INVALID_POINTER;
2939 }
2940
2941 loader_platform_thread_lock_mutex(&loader_lock);
2942
2943 global_extension_list = loader_global_extensions(pLayerName);
2944 if (global_extension_list == NULL) {
2945 loader_platform_thread_unlock_mutex(&loader_lock);
2946 return VK_ERROR_INVALID_LAYER;
2947 }
2948
2949 if (pProperties == NULL) {
2950 *pCount = global_extension_list->count;
2951 loader_platform_thread_unlock_mutex(&loader_lock);
2952 return VK_SUCCESS;
2953 }
2954
2955 copy_size = *pCount < global_extension_list->count ? *pCount : global_extension_list->count;
2956 for (uint32_t i = 0; i < copy_size; i++) {
2957 memcpy(&pProperties[i],
2958 &global_extension_list->list[i].info,
2959 sizeof(VkExtensionProperties));
2960 }
2961 *pCount = copy_size;
2962
2963 loader_platform_thread_unlock_mutex(&loader_lock);
2964
2965 if (copy_size < global_extension_list->count) {
2966 return VK_INCOMPLETE;
2967 }
2968
2969 return VK_SUCCESS;
2970}
2971
2972LOADER_EXPORT VkResult VKAPI vkGetGlobalLayerProperties(
2973 uint32_t* pCount,
2974 VkLayerProperties* pProperties)
Tony Barbour426b9052015-06-24 16:06:58 -06002975{
Jon Ashburnb40f2562015-05-29 13:15:39 -06002976
Jon Ashburneb2728b2015-04-10 14:33:07 -06002977 /* Scan/discover all ICD libraries in a single-threaded manner */
2978 loader_platform_thread_once(&once_icd, loader_icd_scan);
Courtney Goeltzenleuchter0199e952015-02-27 15:19:33 -07002979
Jon Ashburneb2728b2015-04-10 14:33:07 -06002980 /* get layer libraries in a single-threaded manner */
Jon Ashburn68a63922015-07-02 09:40:15 -06002981 loader_platform_thread_once(&once_layer, loader_layer_scan);
Courtney Goeltzenleuchter0199e952015-02-27 15:19:33 -07002982
Jon Ashburneb2728b2015-04-10 14:33:07 -06002983 /* merge any duplicate extensions */
2984 loader_platform_thread_once(&once_exts, loader_coalesce_extensions);
2985
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002986 uint32_t copy_size;
Jon Ashburneb2728b2015-04-10 14:33:07 -06002987
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002988 if (pCount == NULL) {
2989 return VK_ERROR_INVALID_POINTER;
2990 }
2991
2992 /* TODO: do we still need to lock */
Jon Ashburnb40f2562015-05-29 13:15:39 -06002993 loader_platform_thread_lock_mutex(&loader_lock);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002994
2995 struct loader_layer_list *layer_list;
Jon Ashburn1b111de2015-07-06 15:40:35 -06002996 layer_list = loader_scanned_layers();
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002997
2998 if (pProperties == NULL) {
2999 *pCount = layer_list->count;
3000 loader_platform_thread_unlock_mutex(&loader_lock);
3001 return VK_SUCCESS;
3002 }
3003
3004 copy_size = *pCount < layer_list->count ? *pCount : layer_list->count;
3005 for (uint32_t i = 0; i < copy_size; i++) {
3006 memcpy(&pProperties[i], &layer_list->list[i].info, sizeof(VkLayerProperties));
3007 }
3008 *pCount = copy_size;
Tony Barbour426b9052015-06-24 16:06:58 -06003009
Jon Ashburnb40f2562015-05-29 13:15:39 -06003010 loader_platform_thread_unlock_mutex(&loader_lock);
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003011
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003012 if (copy_size < layer_list->count) {
3013 return VK_INCOMPLETE;
3014 }
Tony Barbour426b9052015-06-24 16:06:58 -06003015
3016 return VK_SUCCESS;
3017}
3018
3019VkResult loader_GetPhysicalDeviceExtensionProperties(
3020 VkPhysicalDevice gpu,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003021 const char* pLayerName,
3022 uint32_t* pCount,
Tony Barbour426b9052015-06-24 16:06:58 -06003023 VkExtensionProperties* pProperties)
3024{
3025 uint32_t gpu_index;
Jon Ashburnd5df54d2015-05-28 19:16:58 -06003026 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003027 uint32_t copy_size;
Courtney Goeltzenleuchter0199e952015-02-27 15:19:33 -07003028
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003029 if (pCount == NULL) {
3030 return VK_ERROR_INVALID_POINTER;
3031 }
Jon Ashburn2666e2f2015-05-15 15:09:35 -06003032
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003033 uint32_t count;
3034 struct loader_extension_list *list;
3035 loader_physical_device_extensions(icd, gpu_index, pLayerName, &count, &list);
3036
3037 if (pProperties == NULL) {
3038 *pCount = count;
3039 return VK_SUCCESS;
3040 }
3041
3042 copy_size = *pCount < count ? *pCount : count;
3043 for (uint32_t i = 0; i < copy_size; i++) {
3044 memcpy(&pProperties[i],
3045 &list->list[i].info,
3046 sizeof(VkExtensionProperties));
3047 }
3048 *pCount = copy_size;
3049
3050 if (copy_size < count) {
3051 return VK_INCOMPLETE;
3052 }
3053
3054 return VK_SUCCESS;
3055}
3056
3057VkResult loader_GetPhysicalDeviceLayerProperties(
3058 VkPhysicalDevice gpu,
3059 uint32_t* pCount,
3060 VkLayerProperties* pProperties)
3061{
3062 uint32_t gpu_index;
3063 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
3064 uint32_t copy_size;
3065
3066 if (pCount == NULL) {
3067 return VK_ERROR_INVALID_POINTER;
3068 }
3069
3070 uint32_t count;
3071 struct loader_layer_list *layer_list;
3072 loader_physical_device_layers(icd, &count, &layer_list);
3073
3074 if (pProperties == NULL) {
3075 *pCount = count;
3076 return VK_SUCCESS;
3077 }
3078
3079 copy_size = *pCount < count ? *pCount : count;
3080 for (uint32_t i = 0; i < copy_size; i++) {
3081 memcpy(&pProperties[i],
3082 &layer_list->list[i].info,
3083 sizeof(VkLayerProperties));
3084 }
3085 *pCount = copy_size;
3086
3087 if (copy_size < count) {
3088 return VK_INCOMPLETE;
3089 }
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003090
3091 return VK_SUCCESS;
Jon Ashburn2666e2f2015-05-15 15:09:35 -06003092}