blob: 96b0120248daa1ad3a9c24559373c6f14490de8a [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 Ashburnfce93d92015-05-12 17:26:48 -060045#include "gpa_helper.h"
46#include "table_ops.h"
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -060047#include "debug_report.h"
Tobin Ehlis2d1d9702015-07-03 09:42:57 -060048#include "vk_icd.h"
Jon Ashburnffd5d672015-06-29 11:25:34 -060049#include "cJSON.h"
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080050
Courtney Goeltzenleuchter71cd74d2015-06-01 14:09:34 -060051static loader_platform_dl_handle loader_add_layer_lib(
Jon Ashburne58f1a32015-08-28 13:38:21 -060052 const struct loader_instance *inst,
Courtney Goeltzenleuchter71cd74d2015-06-01 14:09:34 -060053 const char *chain_type,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -060054 struct loader_layer_properties *layer_prop);
Courtney Goeltzenleuchter71cd74d2015-06-01 14:09:34 -060055
56static void loader_remove_layer_lib(
57 struct loader_instance *inst,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -060058 struct loader_layer_properties *layer_prop);
Courtney Goeltzenleuchter71cd74d2015-06-01 14:09:34 -060059
Jon Ashburnfce93d92015-05-12 17:26:48 -060060struct loader_struct loader = {0};
Jon Ashburn413d6582015-08-28 15:19:27 -060061// TLS for instance for alloc/free callbacks
62THREAD_LOCAL_DECL struct loader_instance *tls_instance;
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080063
Jon Ashburne58f1a32015-08-28 13:38:21 -060064static PFN_vkVoidFunction VKAPI loader_GetInstanceProcAddr(
65 VkInstance instance,
66 const char * pName);
67static bool loader_init_ext_list(
68 const struct loader_instance *inst,
69 struct loader_extension_list *ext_info);
Courtney Goeltzenleuchter9a4f38c2015-06-22 17:45:21 -060070
Courtney Goeltzenleuchter8b253f92015-06-08 15:11:18 -060071enum loader_debug {
Courtney Goeltzenleuchter1d4c50f2015-07-08 18:41:08 -060072 LOADER_INFO_BIT = 0x01,
73 LOADER_WARN_BIT = 0x02,
74 LOADER_PERF_BIT = 0x04,
75 LOADER_ERROR_BIT = 0x08,
76 LOADER_DEBUG_BIT = 0x10,
Courtney Goeltzenleuchter8b253f92015-06-08 15:11:18 -060077};
78
79uint32_t g_loader_debug = 0;
80uint32_t g_loader_log_msgs = 0;
81
Jon Ashburnb40f2562015-05-29 13:15:39 -060082//thread safety lock for accessing global data structures such as "loader"
83// all entrypoints on the instance chain need to be locked except GPA
Jon Ashburnffd5d672015-06-29 11:25:34 -060084// additionally CreateDevice and DestroyDevice needs to be locked
Jon Ashburnb40f2562015-05-29 13:15:39 -060085loader_platform_thread_mutex loader_lock;
Jon Ashburnd02fc2c2015-09-22 13:11:00 -060086loader_platform_thread_mutex loader_json_lock;
Jon Ashburnb40f2562015-05-29 13:15:39 -060087
Ian Elliott1d73e662015-07-06 14:36:13 -060088// This table contains the loader's instance dispatch table, which contains
89// default functions if no instance layers are activated. This contains
90// pointers to "terminator functions".
Jon Ashburnb40f2562015-05-29 13:15:39 -060091const VkLayerInstanceDispatchTable instance_disp = {
Courtney Goeltzenleuchter9a4f38c2015-06-22 17:45:21 -060092 .GetInstanceProcAddr = loader_GetInstanceProcAddr,
Jon Ashburnfce93d92015-05-12 17:26:48 -060093 .CreateInstance = loader_CreateInstance,
94 .DestroyInstance = loader_DestroyInstance,
95 .EnumeratePhysicalDevices = loader_EnumeratePhysicalDevices,
Chris Forbesd7576302015-06-21 22:55:02 +120096 .GetPhysicalDeviceFeatures = loader_GetPhysicalDeviceFeatures,
Courtney Goeltzenleuchter4da96aa2015-07-12 12:52:09 -060097 .GetPhysicalDeviceFormatProperties = loader_GetPhysicalDeviceFormatProperties,
Jon Ashburn4e189562015-07-23 18:49:07 -060098 .GetPhysicalDeviceImageFormatProperties = loader_GetPhysicalDeviceImageFormatProperties,
Tony Barbour426b9052015-06-24 16:06:58 -060099 .GetPhysicalDeviceProperties = loader_GetPhysicalDeviceProperties,
Cody Northropef72e2a2015-08-03 17:04:53 -0600100 .GetPhysicalDeviceQueueFamilyProperties = loader_GetPhysicalDeviceQueueFamilyProperties,
Tony Barbour426b9052015-06-24 16:06:58 -0600101 .GetPhysicalDeviceMemoryProperties = loader_GetPhysicalDeviceMemoryProperties,
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -0600102 .EnumerateDeviceExtensionProperties = loader_EnumerateDeviceExtensionProperties,
103 .EnumerateDeviceLayerProperties = loader_EnumerateDeviceLayerProperties,
Mark Lobodzinski83d4e6a2015-07-03 15:58:09 -0600104 .GetPhysicalDeviceSparseImageFormatProperties = loader_GetPhysicalDeviceSparseImageFormatProperties,
Ian Elliott338dedb2015-08-21 15:09:33 -0600105 .GetPhysicalDeviceSurfaceSupportKHR = loader_GetPhysicalDeviceSurfaceSupportKHR,
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600106 .DbgCreateMsgCallback = loader_DbgCreateMsgCallback,
107 .DbgDestroyMsgCallback = loader_DbgDestroyMsgCallback,
Jon Ashburnfce93d92015-05-12 17:26:48 -0600108};
109
Jon Ashburn754f1992015-08-18 18:04:47 -0600110LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_init);
Ian Elliott81ac44c2015-01-13 17:52:38 -0700111
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600112void* loader_heap_alloc(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600113 const struct loader_instance *instance,
114 size_t size,
115 VkSystemAllocType alloc_type)
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600116{
117 if (instance && instance->alloc_callbacks.pfnAlloc) {
118 /* TODO: What should default alignment be? 1, 4, 8, other? */
119 return instance->alloc_callbacks.pfnAlloc(instance->alloc_callbacks.pUserData, size, 4, alloc_type);
120 }
121 return malloc(size);
122}
123
124void* loader_aligned_heap_alloc(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600125 const struct loader_instance *instance,
126 size_t size,
127 size_t alignment,
128 VkSystemAllocType alloc_type)
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600129{
Jon Ashburncfe4e682015-08-14 12:51:47 -0600130 if (instance && instance->alloc_callbacks.pfnAlloc) {
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600131 return instance->alloc_callbacks.pfnAlloc(instance->alloc_callbacks.pUserData, size, alignment, alloc_type);
132 }
Cody Northrop62ac1c52015-07-08 16:48:37 -0600133#if defined(_WIN32)
134 return _aligned_malloc(alignment, size);
135#else
136 return aligned_alloc(alignment, size);
137#endif
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600138}
139
140void loader_heap_free(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600141 const struct loader_instance *instance,
142 void *pMem)
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600143{
Jon Ashburncfe4e682015-08-14 12:51:47 -0600144 if (instance && instance->alloc_callbacks.pfnFree) {
Courtney Goeltzenleuchtere9005172015-07-10 17:39:59 -0600145 instance->alloc_callbacks.pfnFree(instance->alloc_callbacks.pUserData, pMem);
Jon Ashburnfab6ee22015-08-13 08:28:48 -0600146 return;
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600147 }
Courtney Goeltzenleuchtere9005172015-07-10 17:39:59 -0600148 free(pMem);
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600149}
150
Jon Ashburne5e60df2015-08-27 15:23:52 -0600151void* loader_heap_realloc(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600152 const struct loader_instance *instance,
Jon Ashburne5e60df2015-08-27 15:23:52 -0600153 void *pMem,
154 size_t orig_size,
155 size_t size,
156 VkSystemAllocType alloc_type)
157{
158 if (pMem == NULL || orig_size == 0)
159 return loader_heap_alloc(instance, size, alloc_type);
160 if (size == 0) {
161 loader_heap_free(instance, pMem);
162 return NULL;
163 }
164 if (instance && instance->alloc_callbacks.pfnAlloc) {
165 if (size <= orig_size) {
166 memset(((uint8_t *)pMem) + size, 0, orig_size - size);
167 return pMem;
168 }
169 void *new_ptr = instance->alloc_callbacks.pfnAlloc(instance->alloc_callbacks.pUserData, size, 4, alloc_type);
170 if (!new_ptr)
171 return NULL;
172 memcpy(new_ptr, pMem, orig_size);
173 instance->alloc_callbacks.pfnFree(instance->alloc_callbacks.pUserData, pMem);
174 }
175 return realloc(pMem, size);
176}
177
Jon Ashburn413d6582015-08-28 15:19:27 -0600178void *loader_tls_heap_alloc(size_t size)
179{
180 return loader_heap_alloc(tls_instance, size, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
181}
182
183void loader_tls_heap_free(void *pMem)
184{
185 return loader_heap_free(tls_instance, pMem);
186}
187
Jon Ashburnee33ae72015-06-30 14:46:22 -0700188static void loader_log(VkFlags msg_type, int32_t msg_code,
189 const char *format, ...)
190{
Jon Ashburn2b779162015-07-31 15:47:59 -0600191 char msg[512];
Jon Ashburnee33ae72015-06-30 14:46:22 -0700192 va_list ap;
193 int ret;
194
195 if (!(msg_type & g_loader_log_msgs)) {
196 return;
197 }
198
199 va_start(ap, format);
200 ret = vsnprintf(msg, sizeof(msg), format, ap);
201 if ((ret >= (int) sizeof(msg)) || ret < 0) {
202 msg[sizeof(msg)-1] = '\0';
203 }
204 va_end(ap);
205
Ian Elliott225188f2015-02-17 10:33:47 -0700206#if defined(WIN32)
Jon Ashburnee33ae72015-06-30 14:46:22 -0700207 OutputDebugString(msg);
mschott632564c2015-07-22 14:11:29 +0200208 OutputDebugString("\n");
Jon Ashburnee33ae72015-06-30 14:46:22 -0700209#endif
210 fputs(msg, stderr);
211 fputc('\n', stderr);
212}
213
214#if defined(WIN32)
Tony Barbour76096e62015-07-29 14:26:21 -0600215static char *loader_get_next_path(char *path);
Jon Ashburnee33ae72015-06-30 14:46:22 -0700216/**
217* Find the list of registry files (names within a key) in key "location".
218*
219* This function looks in the registry (hive = DEFAULT_VK_REGISTRY_HIVE) key as given in "location"
220* for a list or name/values which are added to a returned list (function return value).
221* The DWORD values within the key must be 0 or they are skipped.
Jon Ashburne58f1a32015-08-28 13:38:21 -0600222* Function return is a string with a ';' separated list of filenames.
Jon Ashburnee33ae72015-06-30 14:46:22 -0700223* Function return is NULL if no valid name/value pairs are found in the key,
224* or the key is not found.
225*
226* \returns
227* A string list of filenames as pointer.
228* When done using the returned string list, pointer should be freed.
229*/
Jon Ashburne58f1a32015-08-28 13:38:21 -0600230static char *loader_get_registry_files(const struct loader_instance *inst, char *location)
Jon Ashburnee33ae72015-06-30 14:46:22 -0700231{
232 LONG rtn_value;
233 HKEY hive, key;
234 DWORD access_flags = KEY_QUERY_VALUE;
235 char name[2048];
236 char *out = NULL;
Tony Barbour76096e62015-07-29 14:26:21 -0600237 char *loc = location;
238 char *next;
Jon Ashburnee33ae72015-06-30 14:46:22 -0700239 DWORD idx = 0;
240 DWORD name_size = sizeof(name);
241 DWORD value;
242 DWORD total_size = 4096;
243 DWORD value_size = sizeof(value);
Tony Barbour76096e62015-07-29 14:26:21 -0600244
245 while(*loc)
246 {
247 next = loader_get_next_path(loc);
248 hive = DEFAULT_VK_REGISTRY_HIVE;
249 rtn_value = RegOpenKeyEx(hive, loc, 0, access_flags, &key);
250 if (rtn_value != ERROR_SUCCESS) {
251 // We didn't find the key. Try the 32-bit hive (where we've seen the
252 // key end up on some people's systems):
253 access_flags |= KEY_WOW64_32KEY;
254 rtn_value = RegOpenKeyEx(hive, loc, 0, access_flags, &key);
255 if (rtn_value != ERROR_SUCCESS) {
256 // We still couldn't find the key, so give up:
257 loc = next;
258 continue;
Jon Ashburnee33ae72015-06-30 14:46:22 -0700259 }
Jon Ashburnee33ae72015-06-30 14:46:22 -0700260 }
Tony Barbour76096e62015-07-29 14:26:21 -0600261
Jon Ashburne58f1a32015-08-28 13:38:21 -0600262 while ((rtn_value = RegEnumValue(key, idx++, name, &name_size, NULL, NULL, (LPBYTE) &value, &value_size)) == ERROR_SUCCESS) {
Tony Barbour76096e62015-07-29 14:26:21 -0600263 if (value_size == sizeof(value) && value == 0) {
264 if (out == NULL) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600265 out = loader_heap_alloc(inst, total_size, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Tony Barbour76096e62015-07-29 14:26:21 -0600266 out[0] = '\0';
267 }
268 else if (strlen(out) + name_size + 1 > total_size) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600269 out = loader_heap_realloc(inst, out, total_size, total_size * 2, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Tony Barbour76096e62015-07-29 14:26:21 -0600270 total_size *= 2;
271 }
272 if (out == NULL) {
273 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory, failed loader_get_registry_files");
274 return NULL;
275 }
276 if (strlen(out) == 0)
277 snprintf(out, name_size + 1, "%s", name);
278 else
279 snprintf(out + strlen(out), name_size + 2, "%c%s", PATH_SEPERATOR, name);
280 }
281 name_size = 2048;
282 }
283 loc = next;
Jon Ashburnee33ae72015-06-30 14:46:22 -0700284 }
Tony Barbour76096e62015-07-29 14:26:21 -0600285
Jon Ashburnee33ae72015-06-30 14:46:22 -0700286 return out;
287}
288
Ian Elliott225188f2015-02-17 10:33:47 -0700289#endif // WIN32
290
Jon Ashburn4b7f35f2015-08-03 09:08:46 -0600291/**
292 * Given string of three part form "maj.min.pat" convert to a vulkan version
293 * number.
294 */
295static uint32_t loader_make_version(const char *vers_str)
296{
Jon Ashburnb8605fe2015-09-18 12:53:16 -0600297 uint32_t vers = 0, major=0, minor=0, patch=0;
Jon Ashburn4b7f35f2015-08-03 09:08:46 -0600298 char *minor_str= NULL;
299 char *patch_str = NULL;
300 char *cstr;
301 char *str;
302
303 if (!vers_str)
304 return vers;
305 cstr = loader_stack_alloc(strlen(vers_str) + 1);
306 strcpy(cstr, vers_str);
307 while ((str = strchr(cstr, '.')) != NULL) {
308 if (minor_str == NULL) {
309 minor_str = str + 1;
310 *str = '\0';
311 major = atoi(cstr);
312 }
313 else if (patch_str == NULL) {
314 patch_str = str + 1;
315 *str = '\0';
316 minor = atoi(minor_str);
317 }
318 else {
319 return vers;
320 }
321 cstr = str + 1;
322 }
323 patch = atoi(patch_str);
324
325 return VK_MAKE_VERSION(major, minor, patch);
326
327}
328
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600329bool compare_vk_extension_properties(const VkExtensionProperties *op1, const VkExtensionProperties *op2)
330{
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600331 return strcmp(op1->extName, op2->extName) == 0 ? true : false;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600332}
333
Jon Ashburn1b111de2015-07-06 15:40:35 -0600334/**
Jon Ashburn60378412015-07-02 12:59:25 -0600335 * Search the given ext_array for an extension
336 * matching the given vk_ext_prop
337 */
338bool has_vk_extension_property_array(
339 const VkExtensionProperties *vk_ext_prop,
340 const uint32_t count,
341 const VkExtensionProperties *ext_array)
342{
343 for (uint32_t i = 0; i < count; i++) {
344 if (compare_vk_extension_properties(vk_ext_prop, &ext_array[i]))
345 return true;
346 }
347 return false;
348}
349
Jon Ashburn1b111de2015-07-06 15:40:35 -0600350/**
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600351 * Search the given ext_list for an extension
352 * matching the given vk_ext_prop
353 */
354bool has_vk_extension_property(
355 const VkExtensionProperties *vk_ext_prop,
356 const struct loader_extension_list *ext_list)
357{
358 for (uint32_t i = 0; i < ext_list->count; i++) {
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600359 if (compare_vk_extension_properties(&ext_list->list[i], vk_ext_prop))
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600360 return true;
361 }
362 return false;
363}
364
Jon Ashburn0bf6a182015-07-16 17:19:31 -0600365static inline bool loader_is_layer_type_device(const enum layer_type type) {
366 if ((type & VK_LAYER_TYPE_DEVICE_EXPLICIT) ||
367 (type & VK_LAYER_TYPE_DEVICE_IMPLICIT))
368 return true;
369 return false;
370}
371
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600372/*
Jon Ashburn1b111de2015-07-06 15:40:35 -0600373 * Search the given layer list for a layer matching the given layer name
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600374 */
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600375static struct loader_layer_properties *loader_get_layer_property(
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600376 const char *name,
377 const struct loader_layer_list *layer_list)
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600378{
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600379 for (uint32_t i = 0; i < layer_list->count; i++) {
380 const VkLayerProperties *item = &layer_list->list[i].info;
381 if (strcmp(name, item->layerName) == 0)
382 return &layer_list->list[i];
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600383 }
384 return NULL;
385}
386
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600387/**
388 * Get the next unused layer property in the list. Init the property to zero.
389 */
390static struct loader_layer_properties *loader_get_next_layer_property(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600391 const struct loader_instance *inst,
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600392 struct loader_layer_list *layer_list)
393{
394 if (layer_list->capacity == 0) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600395 layer_list->list = loader_heap_alloc(inst,
396 sizeof(struct loader_layer_properties) * 64,
397 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600398 if (layer_list->list == NULL) {
399 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't add any layer properties to list");
400 return NULL;
401 }
402 memset(layer_list->list, 0, sizeof(struct loader_layer_properties) * 64);
403 layer_list->capacity = sizeof(struct loader_layer_properties) * 64;
404 }
405
406 // ensure enough room to add an entry
407 if ((layer_list->count + 1) * sizeof (struct loader_layer_properties)
408 > layer_list->capacity) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600409 layer_list->list = loader_heap_realloc(inst, layer_list->list,
410 layer_list->capacity,
411 layer_list->capacity * 2,
412 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600413 if (layer_list->list == NULL) {
414 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
415 "realloc failed for layer list");
416 }
417 layer_list->capacity *= 2;
418 }
419
420 layer_list->count++;
421 return &(layer_list->list[layer_list->count - 1]);
422}
423
424/**
425 * Remove all layer properties entrys from the list
426 */
Jon Ashburne58f1a32015-08-28 13:38:21 -0600427void loader_delete_layer_properties(
428 const struct loader_instance *inst,
429 struct loader_layer_list *layer_list)
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600430{
431 uint32_t i;
432
Jon Ashburn182b8302015-08-11 14:49:54 -0600433 if (!layer_list)
434 return;
435
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600436 for (i = 0; i < layer_list->count; i++) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600437 loader_destroy_ext_list(inst, &layer_list->list[i].instance_extension_list);
438 loader_destroy_ext_list(inst, &layer_list->list[i].device_extension_list);
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600439 }
440 layer_list->count = 0;
441
Jon Ashburn182b8302015-08-11 14:49:54 -0600442 if (layer_list->capacity > 0) {
443 layer_list->capacity = 0;
Jon Ashburne58f1a32015-08-28 13:38:21 -0600444 loader_heap_free(inst, layer_list->list);
Jon Ashburn182b8302015-08-11 14:49:54 -0600445 }
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600446
447}
448
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600449static void loader_add_global_extensions(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600450 const struct loader_instance *inst,
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -0600451 const PFN_vkEnumerateInstanceExtensionProperties fp_get_props,
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600452 const char *lib_name,
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600453 struct loader_extension_list *ext_list)
454{
455 uint32_t i, count;
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600456 VkExtensionProperties *ext_props;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600457 VkResult res;
458
Courtney Goeltzenleuchteraa9faab2015-07-06 22:28:18 -0600459 if (!fp_get_props) {
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -0600460 /* No EnumerateInstanceExtensionProperties defined */
Courtney Goeltzenleuchteraa9faab2015-07-06 22:28:18 -0600461 return;
462 }
463
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600464 res = fp_get_props(NULL, &count, NULL);
Jon Ashburneb2728b2015-04-10 14:33:07 -0600465 if (res != VK_SUCCESS) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600466 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Error getting global extension count from %s", lib_name);
Jon Ashburneb2728b2015-04-10 14:33:07 -0600467 return;
468 }
Jon Ashburn60699262015-06-10 16:11:42 -0600469
Courtney Goeltzenleuchteraa9faab2015-07-06 22:28:18 -0600470 if (count == 0) {
471 /* No ExtensionProperties to report */
472 return;
473 }
474
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600475 ext_props = loader_stack_alloc(count * sizeof(VkExtensionProperties));
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600476
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600477 res = fp_get_props(NULL, &count, ext_props);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600478 if (res != VK_SUCCESS) {
479 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Error getting global extensions from %s", lib_name);
480 return;
481 }
Tony Barbour426b9052015-06-24 16:06:58 -0600482
Jon Ashburneb2728b2015-04-10 14:33:07 -0600483 for (i = 0; i < count; i++) {
Courtney Goeltzenleuchter73a21d32015-07-12 13:20:05 -0600484 char spec_version[64];
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600485
486 snprintf(spec_version, sizeof(spec_version), "%d.%d.%d",
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600487 VK_MAJOR(ext_props[i].specVersion),
488 VK_MINOR(ext_props[i].specVersion),
489 VK_PATCH(ext_props[i].specVersion));
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600490 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Courtney Goeltzenleuchter73a21d32015-07-12 13:20:05 -0600491 "Global Extension: %s (%s) version %s",
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600492 ext_props[i].extName, lib_name, spec_version);
Jon Ashburne58f1a32015-08-28 13:38:21 -0600493 loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600494 }
495
496 return;
497}
498
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600499static void loader_add_physical_device_extensions(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600500 const struct loader_instance *inst,
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -0600501 PFN_vkEnumerateDeviceExtensionProperties get_phys_dev_ext_props,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600502 VkPhysicalDevice physical_device,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600503 const char *lib_name,
504 struct loader_extension_list *ext_list)
505{
506 uint32_t i, count;
507 VkResult res;
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600508 VkExtensionProperties *ext_props;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600509
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600510 if (!get_phys_dev_ext_props) {
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -0600511 /* No EnumerateDeviceExtensionProperties defined */
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600512 return;
513 }
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600514
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600515 res = get_phys_dev_ext_props(physical_device, NULL, &count, NULL);
516 if (res == VK_SUCCESS && count > 0) {
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600517 ext_props = loader_stack_alloc(count * sizeof(VkExtensionProperties));
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600518
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600519 res = get_phys_dev_ext_props(physical_device, NULL, &count, ext_props);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600520 for (i = 0; i < count; i++) {
Courtney Goeltzenleuchter73a21d32015-07-12 13:20:05 -0600521 char spec_version[64];
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600522
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600523 snprintf(spec_version, sizeof(spec_version), "%d.%d.%d",
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600524 VK_MAJOR(ext_props[i].specVersion),
525 VK_MINOR(ext_props[i].specVersion),
526 VK_PATCH(ext_props[i].specVersion));
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600527 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Courtney Goeltzenleuchter73a21d32015-07-12 13:20:05 -0600528 "PhysicalDevice Extension: %s (%s) version %s",
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600529 ext_props[i].extName, lib_name, spec_version);
Jon Ashburne58f1a32015-08-28 13:38:21 -0600530 loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
Jon Ashburn60699262015-06-10 16:11:42 -0600531 }
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600532 } else {
Jon Ashburn0b728052015-08-04 10:22:33 -0600533 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Error getting physical device extension info count from library %s", lib_name);
Jon Ashburneb2728b2015-04-10 14:33:07 -0600534 }
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600535
Jon Ashburneb2728b2015-04-10 14:33:07 -0600536 return;
537}
538
Jon Ashburne58f1a32015-08-28 13:38:21 -0600539static bool loader_init_ext_list(const struct loader_instance *inst,
540 struct loader_extension_list *ext_info)
Jon Ashburneb2728b2015-04-10 14:33:07 -0600541{
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600542 ext_info->capacity = 32 * sizeof(VkExtensionProperties);
Jon Ashburne58f1a32015-08-28 13:38:21 -0600543 ext_info->list = loader_heap_alloc(inst, ext_info->capacity, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600544 if (ext_info->list == NULL) {
545 return false;
546 }
547 memset(ext_info->list, 0, ext_info->capacity);
548 ext_info->count = 0;
549 return true;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600550}
551
Jon Ashburne58f1a32015-08-28 13:38:21 -0600552void loader_destroy_ext_list(const struct loader_instance *inst,
553 struct loader_extension_list *ext_info)
Jon Ashburneb2728b2015-04-10 14:33:07 -0600554{
Jon Ashburne58f1a32015-08-28 13:38:21 -0600555 loader_heap_free(inst, ext_info->list);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600556 ext_info->count = 0;
557 ext_info->capacity = 0;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600558}
Jon Ashburneb2728b2015-04-10 14:33:07 -0600559
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600560/*
561 * Append non-duplicate extension properties defined in props
562 * to the given ext_list.
563 */
564void loader_add_to_ext_list(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600565 const struct loader_instance *inst,
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600566 struct loader_extension_list *ext_list,
567 uint32_t prop_list_count,
568 const VkExtensionProperties *props)
569{
570 uint32_t i;
571 const VkExtensionProperties *cur_ext;
572
573 if (ext_list->list == NULL || ext_list->capacity == 0) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600574 loader_init_ext_list(inst, ext_list);
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600575 }
576
577 if (ext_list->list == NULL)
578 return;
579
580 for (i = 0; i < prop_list_count; i++) {
581 cur_ext = &props[i];
582
583 // look for duplicates
584 if (has_vk_extension_property(cur_ext, ext_list)) {
585 continue;
586 }
587
588 // add to list at end
589 // check for enough capacity
590 if (ext_list->count * sizeof(VkExtensionProperties)
591 >= ext_list->capacity) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600592
593 ext_list->list = loader_heap_realloc(inst,
594 ext_list->list,
595 ext_list->capacity,
596 ext_list->capacity * 2,
597 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600598 // double capacity
599 ext_list->capacity *= 2;
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600600 }
601
602 memcpy(&ext_list->list[ext_list->count], cur_ext, sizeof(VkExtensionProperties));
603 ext_list->count++;
604 }
605}
606
Jon Ashburn60378412015-07-02 12:59:25 -0600607/**
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600608 * Search the given search_list for any layers in the props list.
609 * Add these to the output layer_list. Don't add duplicates to the output layer_list.
Jon Ashburn60378412015-07-02 12:59:25 -0600610 */
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -0600611static VkResult loader_add_layer_names_to_list(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600612 const struct loader_instance *inst,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600613 struct loader_layer_list *output_list,
614 uint32_t name_count,
615 const char * const *names,
616 const struct loader_layer_list *search_list)
Jon Ashburneb2728b2015-04-10 14:33:07 -0600617{
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600618 struct loader_layer_properties *layer_prop;
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -0600619 VkResult err = VK_SUCCESS;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600620
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600621 for (uint32_t i = 0; i < name_count; i++) {
622 const char *search_target = names[i];
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600623 layer_prop = loader_get_layer_property(search_target, search_list);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600624 if (!layer_prop) {
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -0600625 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Unable to find layer %s", search_target);
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -0600626 err = VK_ERROR_LAYER_NOT_PRESENT;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600627 continue;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600628 }
629
Jon Ashburne58f1a32015-08-28 13:38:21 -0600630 loader_add_to_layer_list(inst, output_list, 1, layer_prop);
Jon Ashburneb2728b2015-04-10 14:33:07 -0600631 }
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -0600632
633 return err;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600634}
635
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600636
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600637/*
638 * Manage lists of VkLayerProperties
639 */
Jon Ashburne58f1a32015-08-28 13:38:21 -0600640static bool loader_init_layer_list(const struct loader_instance *inst,
641 struct loader_layer_list *list)
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600642{
643 list->capacity = 32 * sizeof(struct loader_layer_properties);
Jon Ashburne58f1a32015-08-28 13:38:21 -0600644 list->list = loader_heap_alloc(inst, list->capacity, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600645 if (list->list == NULL) {
646 return false;
647 }
648 memset(list->list, 0, list->capacity);
649 list->count = 0;
650 return true;
651}
652
Jon Ashburne58f1a32015-08-28 13:38:21 -0600653void loader_destroy_layer_list(const struct loader_instance *inst,
654 struct loader_layer_list *layer_list)
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600655{
Jon Ashburne58f1a32015-08-28 13:38:21 -0600656 loader_heap_free(inst, layer_list->list);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600657 layer_list->count = 0;
658 layer_list->capacity = 0;
659}
660
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600661/*
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600662 * Manage list of layer libraries (loader_lib_info)
663 */
Jon Ashburne58f1a32015-08-28 13:38:21 -0600664static bool loader_init_layer_library_list(const struct loader_instance *inst,
665 struct loader_layer_library_list *list)
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600666{
667 list->capacity = 32 * sizeof(struct loader_lib_info);
Jon Ashburne58f1a32015-08-28 13:38:21 -0600668 list->list = loader_heap_alloc(inst, list->capacity, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600669 if (list->list == NULL) {
670 return false;
671 }
672 memset(list->list, 0, list->capacity);
673 list->count = 0;
674 return true;
675}
676
Jon Ashburne58f1a32015-08-28 13:38:21 -0600677void loader_destroy_layer_library_list(const struct loader_instance *inst,
678 struct loader_layer_library_list *list)
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600679{
680 for (uint32_t i = 0; i < list->count; i++) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600681 loader_heap_free(inst, list->list[i].lib_name);
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600682 }
Jon Ashburne58f1a32015-08-28 13:38:21 -0600683 loader_heap_free(inst, list->list);
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600684 list->count = 0;
685 list->capacity = 0;
686}
687
688void loader_add_to_layer_library_list(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600689 const struct loader_instance *inst,
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600690 struct loader_layer_library_list *list,
691 uint32_t item_count,
692 const struct loader_lib_info *new_items)
693{
694 uint32_t i;
695 struct loader_lib_info *item;
696
697 if (list->list == NULL || list->capacity == 0) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600698 loader_init_layer_library_list(inst, list);
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600699 }
700
701 if (list->list == NULL)
702 return;
703
704 for (i = 0; i < item_count; i++) {
705 item = (struct loader_lib_info *) &new_items[i];
706
707 // look for duplicates
708 for (uint32_t j = 0; j < list->count; j++) {
709 if (strcmp(list->list[i].lib_name, new_items->lib_name) == 0) {
710 continue;
711 }
712 }
713
714 // add to list at end
715 // check for enough capacity
716 if (list->count * sizeof(struct loader_lib_info)
717 >= list->capacity) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600718
719 list->list = loader_heap_realloc(inst,
720 list->list,
721 list->capacity,
722 list->capacity * 2,
723 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600724 // double capacity
725 list->capacity *= 2;
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600726 }
727
728 memcpy(&list->list[list->count], item, sizeof(struct loader_lib_info));
729 list->count++;
730 }
731}
732
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600733
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600734/*
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600735 * Search the given layer list for a list
736 * matching the given VkLayerProperties
737 */
738bool has_vk_layer_property(
739 const VkLayerProperties *vk_layer_prop,
740 const struct loader_layer_list *list)
741{
742 for (uint32_t i = 0; i < list->count; i++) {
743 if (strcmp(vk_layer_prop->layerName, list->list[i].info.layerName) == 0)
744 return true;
745 }
746 return false;
747}
748
749/*
750 * Search the given layer list for a layer
751 * matching the given name
752 */
753bool has_layer_name(
754 const char *name,
755 const struct loader_layer_list *list)
756{
757 for (uint32_t i = 0; i < list->count; i++) {
758 if (strcmp(name, list->list[i].info.layerName) == 0)
759 return true;
760 }
761 return false;
762}
763
764/*
765 * Append non-duplicate layer properties defined in prop_list
766 * to the given layer_info list
767 */
768void loader_add_to_layer_list(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600769 const struct loader_instance *inst,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600770 struct loader_layer_list *list,
771 uint32_t prop_list_count,
772 const struct loader_layer_properties *props)
773{
774 uint32_t i;
775 struct loader_layer_properties *layer;
776
777 if (list->list == NULL || list->capacity == 0) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600778 loader_init_layer_list(inst, list);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600779 }
780
781 if (list->list == NULL)
782 return;
783
784 for (i = 0; i < prop_list_count; i++) {
785 layer = (struct loader_layer_properties *) &props[i];
786
787 // look for duplicates
788 if (has_vk_layer_property(&layer->info, list)) {
789 continue;
790 }
791
792 // add to list at end
793 // check for enough capacity
794 if (list->count * sizeof(struct loader_layer_properties)
795 >= list->capacity) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600796
797 list->list = loader_heap_realloc(inst,
798 list->list,
799 list->capacity,
800 list->capacity * 2,
801 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600802 // double capacity
803 list->capacity *= 2;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600804 }
805
806 memcpy(&list->list[list->count], layer, sizeof(struct loader_layer_properties));
807 list->count++;
808 }
809}
810
Jon Ashburnf2ddb732015-07-07 10:27:45 -0600811/**
812 * Search the search_list for any layer with a name
813 * that matches the given name and a type that matches the given type
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600814 * Add all matching layers to the found_list
Jon Ashburnf2ddb732015-07-07 10:27:45 -0600815 * Do not add if found loader_layer_properties is already
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600816 * on the found_list.
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600817 */
Jon Ashburn60378412015-07-02 12:59:25 -0600818static void loader_find_layer_name_add_list(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600819 const struct loader_instance *inst,
Jon Ashburn60378412015-07-02 12:59:25 -0600820 const char *name,
Jon Ashburnf2ddb732015-07-07 10:27:45 -0600821 const enum layer_type type,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600822 const struct loader_layer_list *search_list,
823 struct loader_layer_list *found_list)
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600824{
825 for (uint32_t i = 0; i < search_list->count; i++) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600826 struct loader_layer_properties *layer_prop = &search_list->list[i];
Jon Ashburnf2ddb732015-07-07 10:27:45 -0600827 if (0 == strcmp(layer_prop->info.layerName, name) &&
828 (layer_prop->type & type)) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600829 /* Found a layer with the same name, add to found_list */
Jon Ashburne58f1a32015-08-28 13:38:21 -0600830 loader_add_to_layer_list(inst, found_list, 1, layer_prop);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600831 }
832 }
833}
834
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600835static VkExtensionProperties *get_extension_property(
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -0600836 const char *name,
837 const struct loader_extension_list *list)
Jon Ashburn42e41032015-04-14 09:15:32 -0600838{
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -0600839 for (uint32_t i = 0; i < list->count; i++) {
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600840 if (strcmp(name, list->list[i].extName) == 0)
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -0600841 return &list->list[i];
Jon Ashburn42e41032015-04-14 09:15:32 -0600842 }
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -0600843 return NULL;
Jon Ashburn42e41032015-04-14 09:15:32 -0600844}
845
Jon Ashburn60378412015-07-02 12:59:25 -0600846/*
847 * For global exenstions implemented within the loader (i.e. DEBUG_REPORT
848 * the extension must provide two entry points for the loader to use:
849 * - "trampoline" entry point - this is the address returned by GetProcAddr
850 * and will always do what's necessary to support a global call.
851 * - "terminator" function - this function will be put at the end of the
852 * instance chain and will contain the necessary logica to call / process
853 * the extension for the appropriate ICDs that are available.
854 * There is no generic mechanism for including these functions, the references
855 * must be placed into the appropriate loader entry points.
856 * GetInstanceProcAddr: call extension GetInstanceProcAddr to check for GetProcAddr requests
857 * loader_coalesce_extensions(void) - add extension records to the list of global
858 * extension available to the app.
859 * instance_disp - add function pointer for terminator function to this array.
860 * The extension itself should be in a separate file that will be
861 * linked directly with the loader.
862 */
Jon Ashburnc1d1eb72015-08-14 11:57:54 -0600863
Jon Ashburn754f1992015-08-18 18:04:47 -0600864void loader_get_icd_loader_instance_extensions(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600865 const struct loader_instance *inst,
Jon Ashburn754f1992015-08-18 18:04:47 -0600866 struct loader_icd_libs *icd_libs,
867 struct loader_extension_list *inst_exts)
Jon Ashburneb2728b2015-04-10 14:33:07 -0600868{
Jon Ashburn85f98072015-08-14 14:49:22 -0600869 struct loader_extension_list icd_exts;
Jon Ashburnc1d1eb72015-08-14 11:57:54 -0600870 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, "Build ICD instance extension list");
Jon Ashburneb2728b2015-04-10 14:33:07 -0600871 // traverse scanned icd list adding non-duplicate extensions to the list
Jon Ashburn754f1992015-08-18 18:04:47 -0600872 for (uint32_t i = 0; i < icd_libs->count; i++) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600873 loader_init_ext_list(inst, &icd_exts);
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -0600874 loader_add_global_extensions(inst, icd_libs->list[i].EnumerateInstanceExtensionProperties,
Jon Ashburn754f1992015-08-18 18:04:47 -0600875 icd_libs->list[i].lib_name,
Jon Ashburn85f98072015-08-14 14:49:22 -0600876 &icd_exts);
Jon Ashburne58f1a32015-08-28 13:38:21 -0600877 loader_add_to_ext_list(inst, inst_exts,
Jon Ashburn85f98072015-08-14 14:49:22 -0600878 icd_exts.count,
879 icd_exts.list);
Jon Ashburne58f1a32015-08-28 13:38:21 -0600880 loader_destroy_ext_list(inst, &icd_exts);
Jon Ashburneb2728b2015-04-10 14:33:07 -0600881 };
882
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600883 // Traverse loader's extensions, adding non-duplicate extensions to the list
Jon Ashburne58f1a32015-08-28 13:38:21 -0600884 wsi_swapchain_add_instance_extensions(inst, inst_exts);
885 debug_report_add_instance_extensions(inst, inst_exts);
Jon Ashburneb2728b2015-04-10 14:33:07 -0600886}
887
Jon Ashburne58f1a32015-08-28 13:38:21 -0600888struct loader_icd *loader_get_icd_and_device(const VkDevice device,
889 struct loader_device **found_dev)
Jon Ashburncb5a5ac2015-06-10 10:06:06 -0600890{
891 *found_dev = NULL;
892 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
893 for (struct loader_icd *icd = inst->icds; icd; icd = icd->next) {
894 for (struct loader_device *dev = icd->logical_device_list; dev; dev = dev->next)
895 if (dev->device == device) {
896 *found_dev = dev;
897 return icd;
898 }
899 }
900 }
901 return NULL;
902}
903
Jon Ashburne58f1a32015-08-28 13:38:21 -0600904static void loader_destroy_logical_device(const struct loader_instance *inst,
905 struct loader_device *dev)
Jon Ashburncb5a5ac2015-06-10 10:06:06 -0600906{
Jon Ashburne58f1a32015-08-28 13:38:21 -0600907 loader_heap_free(inst, dev->app_extension_props);
Jon Ashburncb5a5ac2015-06-10 10:06:06 -0600908 if (dev->activated_layer_list.count)
Jon Ashburne58f1a32015-08-28 13:38:21 -0600909 loader_destroy_layer_list(inst, &dev->activated_layer_list);
910 loader_heap_free(inst, dev);
Jon Ashburncb5a5ac2015-06-10 10:06:06 -0600911}
912
Jon Ashburne58f1a32015-08-28 13:38:21 -0600913static struct loader_device *loader_add_logical_device(
914 const struct loader_instance *inst,
915 const VkDevice dev,
916 struct loader_device **device_list)
Jon Ashburncb5a5ac2015-06-10 10:06:06 -0600917{
918 struct loader_device *new_dev;
919
Jon Ashburne58f1a32015-08-28 13:38:21 -0600920 new_dev = loader_heap_alloc(inst, sizeof(struct loader_device), VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburncb5a5ac2015-06-10 10:06:06 -0600921 if (!new_dev) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600922 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc struct laoder-device");
Jon Ashburncb5a5ac2015-06-10 10:06:06 -0600923 return NULL;
924 }
925
926 memset(new_dev, 0, sizeof(struct loader_device));
927
928 new_dev->next = *device_list;
929 new_dev->device = dev;
930 *device_list = new_dev;
931 return new_dev;
932}
933
Jon Ashburne58f1a32015-08-28 13:38:21 -0600934void loader_remove_logical_device(
935 const struct loader_instance *inst,
936 VkDevice device)
Jon Ashburncb5a5ac2015-06-10 10:06:06 -0600937{
938 struct loader_device *found_dev, *dev, *prev_dev;
939 struct loader_icd *icd;
940 icd = loader_get_icd_and_device(device, &found_dev);
941
942 if (!icd || !found_dev)
943 return;
944
945 prev_dev = NULL;
946 dev = icd->logical_device_list;
947 while (dev && dev != found_dev) {
948 prev_dev = dev;
949 dev = dev->next;
950 }
951
952 if (prev_dev)
953 prev_dev->next = found_dev->next;
954 else
955 icd->logical_device_list = found_dev->next;
Jon Ashburne58f1a32015-08-28 13:38:21 -0600956 loader_destroy_logical_device(inst, found_dev);
Jon Ashburncb5a5ac2015-06-10 10:06:06 -0600957}
958
959
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600960static void loader_icd_destroy(
961 struct loader_instance *ptr_inst,
962 struct loader_icd *icd)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800963{
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600964 ptr_inst->total_icd_count--;
Jon Ashburne58f1a32015-08-28 13:38:21 -0600965 loader_heap_free(ptr_inst, icd->gpus);
Courtney Goeltzenleuchter6b70e362015-06-14 19:57:15 -0600966 for (struct loader_device *dev = icd->logical_device_list; dev; ) {
967 struct loader_device *next_dev = dev->next;
Jon Ashburne58f1a32015-08-28 13:38:21 -0600968 loader_destroy_logical_device(ptr_inst, dev);
Courtney Goeltzenleuchter6b70e362015-06-14 19:57:15 -0600969 dev = next_dev;
970 }
Jon Ashburncb5a5ac2015-06-10 10:06:06 -0600971
Jon Ashburne58f1a32015-08-28 13:38:21 -0600972 loader_heap_free(ptr_inst, icd);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800973}
974
Jon Ashburne58f1a32015-08-28 13:38:21 -0600975static struct loader_icd * loader_icd_create(const struct loader_instance *inst)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800976{
977 struct loader_icd *icd;
978
Jon Ashburne58f1a32015-08-28 13:38:21 -0600979 icd = loader_heap_alloc(inst, sizeof(*icd), VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800980 if (!icd)
981 return NULL;
982
Courtney Goeltzenleuchter6f928162014-10-28 10:29:27 -0600983 memset(icd, 0, sizeof(*icd));
984
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800985 return icd;
986}
987
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600988static struct loader_icd *loader_icd_add(
989 struct loader_instance *ptr_inst,
Jon Ashburne9ca8fa2015-08-20 16:35:30 -0600990 const struct loader_scanned_icds *icd_lib)
Chia-I Wu894a1172014-08-04 11:18:20 +0800991{
992 struct loader_icd *icd;
993
Jon Ashburne58f1a32015-08-28 13:38:21 -0600994 icd = loader_icd_create(ptr_inst);
Chia-I Wu894a1172014-08-04 11:18:20 +0800995 if (!icd)
996 return NULL;
997
Jon Ashburne9ca8fa2015-08-20 16:35:30 -0600998 icd->this_icd_lib = icd_lib;
999 icd->this_instance = ptr_inst;
1000
Chia-I Wu894a1172014-08-04 11:18:20 +08001001 /* prepend to the list */
Jon Ashburn3336df82015-01-29 15:45:51 -07001002 icd->next = ptr_inst->icds;
1003 ptr_inst->icds = icd;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001004 ptr_inst->total_icd_count++;
Chia-I Wu894a1172014-08-04 11:18:20 +08001005
1006 return icd;
1007}
1008
Jon Ashburne58f1a32015-08-28 13:38:21 -06001009void loader_scanned_icd_clear(
1010 const struct loader_instance *inst,
1011 struct loader_icd_libs *icd_libs)
Jon Ashburn754f1992015-08-18 18:04:47 -06001012{
1013 if (icd_libs->capacity == 0)
1014 return;
1015 for (uint32_t i = 0; i < icd_libs->count; i++) {
1016 loader_platform_close_library(icd_libs->list[i].handle);
Jon Ashburne58f1a32015-08-28 13:38:21 -06001017 loader_heap_free(inst, icd_libs->list[i].lib_name);
Jon Ashburn754f1992015-08-18 18:04:47 -06001018 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06001019 loader_heap_free(inst, icd_libs->list);
Jon Ashburn754f1992015-08-18 18:04:47 -06001020 icd_libs->capacity = 0;
1021 icd_libs->count = 0;
1022 icd_libs->list = NULL;
1023}
1024
Jon Ashburne58f1a32015-08-28 13:38:21 -06001025static void loader_scanned_icd_init(const struct loader_instance *inst,
1026 struct loader_icd_libs *icd_libs)
Jon Ashburn754f1992015-08-18 18:04:47 -06001027{
Jon Ashburne58f1a32015-08-28 13:38:21 -06001028 loader_scanned_icd_clear(inst, icd_libs);
Jon Ashburn754f1992015-08-18 18:04:47 -06001029 icd_libs->capacity = 8 * sizeof(struct loader_scanned_icds);
Jon Ashburne58f1a32015-08-28 13:38:21 -06001030 icd_libs->list = loader_heap_alloc(inst, icd_libs->capacity, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburn754f1992015-08-18 18:04:47 -06001031
1032}
1033
1034static void loader_scanned_icd_add(
Jon Ashburne58f1a32015-08-28 13:38:21 -06001035 const struct loader_instance *inst,
Jon Ashburn754f1992015-08-18 18:04:47 -06001036 struct loader_icd_libs *icd_libs,
1037 const char *filename)
Jon Ashburn14275da2015-01-28 11:01:35 -07001038{
Ian Elliott81ac44c2015-01-13 17:52:38 -07001039 loader_platform_dl_handle handle;
Tony Barbourde4124d2015-07-03 10:33:54 -06001040 PFN_vkCreateInstance fp_create_inst;
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -06001041 PFN_vkEnumerateInstanceExtensionProperties fp_get_global_ext_props;
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001042 PFN_vkGetInstanceProcAddr fp_get_proc_addr;
Jon Ashburn14275da2015-01-28 11:01:35 -07001043 struct loader_scanned_icds *new_node;
1044
Jon Ashburn754f1992015-08-18 18:04:47 -06001045 /* TODO implement ref counting of libraries, for now this function leaves
1046 libraries open and the scanned_icd_clear closes them */
Ian Elliott81ac44c2015-01-13 17:52:38 -07001047 // Used to call: dlopen(filename, RTLD_LAZY);
1048 handle = loader_platform_open_library(filename);
Jon Ashburn14275da2015-01-28 11:01:35 -07001049 if (!handle) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001050 loader_log(VK_DBG_REPORT_WARN_BIT, 0, loader_platform_open_library_error(filename));
Jon Ashburn14275da2015-01-28 11:01:35 -07001051 return;
1052 }
1053
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001054#define LOOKUP_LD(func_ptr, func) do { \
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -06001055 func_ptr = (PFN_vk ##func) loader_platform_get_proc_address(handle, "vk" #func); \
Jon Ashburn14275da2015-01-28 11:01:35 -07001056 if (!func_ptr) { \
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001057 loader_log(VK_DBG_REPORT_WARN_BIT, 0, loader_platform_get_proc_address_error("vk" #func)); \
Jon Ashburn14275da2015-01-28 11:01:35 -07001058 return; \
1059 } \
1060} while (0)
1061
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001062 LOOKUP_LD(fp_get_proc_addr, GetInstanceProcAddr);
1063 LOOKUP_LD(fp_create_inst, CreateInstance);
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -06001064 LOOKUP_LD(fp_get_global_ext_props, EnumerateInstanceExtensionProperties);
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001065
1066#undef LOOKUP_LD
Jon Ashburn14275da2015-01-28 11:01:35 -07001067
Jon Ashburn754f1992015-08-18 18:04:47 -06001068 // check for enough capacity
1069 if ((icd_libs->count * sizeof(struct loader_scanned_icds)) >= icd_libs->capacity) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06001070
1071 icd_libs->list = loader_heap_realloc(inst,
1072 icd_libs->list,
1073 icd_libs->capacity,
1074 icd_libs->capacity * 2,
1075 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburn754f1992015-08-18 18:04:47 -06001076 // double capacity
1077 icd_libs->capacity *= 2;
Jon Ashburn14275da2015-01-28 11:01:35 -07001078 }
Jon Ashburn754f1992015-08-18 18:04:47 -06001079 new_node = &(icd_libs->list[icd_libs->count]);
Jon Ashburn14275da2015-01-28 11:01:35 -07001080
1081 new_node->handle = handle;
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001082 new_node->GetInstanceProcAddr = fp_get_proc_addr;
Jon Ashburn3336df82015-01-29 15:45:51 -07001083 new_node->CreateInstance = fp_create_inst;
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -06001084 new_node->EnumerateInstanceExtensionProperties = fp_get_global_ext_props;
Jon Ashburn14275da2015-01-28 11:01:35 -07001085
Jon Ashburne58f1a32015-08-28 13:38:21 -06001086 new_node->lib_name = (char *) loader_heap_alloc(inst,
1087 strlen(filename) + 1,
1088 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001089 if (!new_node->lib_name) {
1090 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Out of memory can't add icd");
1091 return;
1092 }
1093 strcpy(new_node->lib_name, filename);
Jon Ashburn754f1992015-08-18 18:04:47 -06001094 icd_libs->count++;
Jon Ashburneb2728b2015-04-10 14:33:07 -06001095}
Ian Elliott81ac44c2015-01-13 17:52:38 -07001096
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001097static bool loader_icd_init_entrys(struct loader_icd *icd,
1098 VkInstance inst,
1099 const PFN_vkGetInstanceProcAddr fp_gipa)
Jon Ashburn0dd356d2015-05-14 12:43:38 -06001100{
1101 /* initialize entrypoint function pointers */
1102
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001103 #define LOOKUP_GIPA(func, required) do { \
1104 icd->func = (PFN_vk ##func) fp_gipa(inst, "vk" #func); \
1105 if (!icd->func && required) { \
1106 loader_log(VK_DBG_REPORT_WARN_BIT, 0, \
1107 loader_platform_get_proc_address_error("vk" #func)); \
1108 return false; \
1109 } \
Jon Ashburn0dd356d2015-05-14 12:43:38 -06001110 } while (0)
1111
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001112 LOOKUP_GIPA(GetDeviceProcAddr, true);
1113 LOOKUP_GIPA(DestroyInstance, true);
1114 LOOKUP_GIPA(EnumeratePhysicalDevices, true);
1115 LOOKUP_GIPA(GetPhysicalDeviceFeatures, true);
1116 LOOKUP_GIPA(GetPhysicalDeviceFormatProperties, true);
Jon Ashburn4e189562015-07-23 18:49:07 -06001117 LOOKUP_GIPA(GetPhysicalDeviceImageFormatProperties, true);
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001118 LOOKUP_GIPA(CreateDevice, true);
1119 LOOKUP_GIPA(GetPhysicalDeviceProperties, true);
1120 LOOKUP_GIPA(GetPhysicalDeviceMemoryProperties, true);
Cody Northropef72e2a2015-08-03 17:04:53 -06001121 LOOKUP_GIPA(GetPhysicalDeviceQueueFamilyProperties, true);
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -06001122 LOOKUP_GIPA(EnumerateDeviceExtensionProperties, true);
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001123 LOOKUP_GIPA(GetPhysicalDeviceSparseImageFormatProperties, true);
1124 LOOKUP_GIPA(DbgCreateMsgCallback, false);
1125 LOOKUP_GIPA(DbgDestroyMsgCallback, false);
Ian Elliott338dedb2015-08-21 15:09:33 -06001126 LOOKUP_GIPA(GetPhysicalDeviceSurfaceSupportKHR, false);
Jon Ashburn0dd356d2015-05-14 12:43:38 -06001127
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001128#undef LOOKUP_GIPA
Ian Elliott1d73e662015-07-06 14:36:13 -06001129
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001130 return true;
Jon Ashburn0dd356d2015-05-14 12:43:38 -06001131}
1132
Courtney Goeltzenleuchter8b253f92015-06-08 15:11:18 -06001133static void loader_debug_init(void)
1134{
1135 const char *env;
1136
1137 if (g_loader_debug > 0)
1138 return;
1139
1140 g_loader_debug = 0;
1141
1142 /* parse comma-separated debug options */
Courtney Goeltzenleuchter893f2872015-07-29 09:08:22 -06001143 env = getenv("VK_LOADER_DEBUG");
Courtney Goeltzenleuchter8b253f92015-06-08 15:11:18 -06001144 while (env) {
1145 const char *p = strchr(env, ',');
1146 size_t len;
1147
1148 if (p)
1149 len = p - env;
1150 else
1151 len = strlen(env);
1152
1153 if (len > 0) {
1154 if (strncmp(env, "warn", len) == 0) {
1155 g_loader_debug |= LOADER_WARN_BIT;
1156 g_loader_log_msgs |= VK_DBG_REPORT_WARN_BIT;
1157 } else if (strncmp(env, "info", len) == 0) {
1158 g_loader_debug |= LOADER_INFO_BIT;
1159 g_loader_log_msgs |= VK_DBG_REPORT_INFO_BIT;
1160 } else if (strncmp(env, "perf", len) == 0) {
1161 g_loader_debug |= LOADER_PERF_BIT;
1162 g_loader_log_msgs |= VK_DBG_REPORT_PERF_WARN_BIT;
1163 } else if (strncmp(env, "error", len) == 0) {
1164 g_loader_debug |= LOADER_ERROR_BIT;
1165 g_loader_log_msgs |= VK_DBG_REPORT_ERROR_BIT;
1166 } else if (strncmp(env, "debug", len) == 0) {
1167 g_loader_debug |= LOADER_DEBUG_BIT;
1168 g_loader_log_msgs |= VK_DBG_REPORT_DEBUG_BIT;
1169 }
1170 }
1171
1172 if (!p)
1173 break;
1174
1175 env = p + 1;
1176 }
1177}
1178
Jon Ashburn754f1992015-08-18 18:04:47 -06001179void loader_initialize(void)
1180{
Jon Ashburnd02fc2c2015-09-22 13:11:00 -06001181 // initialize mutexs
Jon Ashburn754f1992015-08-18 18:04:47 -06001182 loader_platform_thread_create_mutex(&loader_lock);
Jon Ashburnd02fc2c2015-09-22 13:11:00 -06001183 loader_platform_thread_create_mutex(&loader_json_lock);
Jon Ashburn754f1992015-08-18 18:04:47 -06001184
1185 // initialize logging
1186 loader_debug_init();
Jon Ashburn413d6582015-08-28 15:19:27 -06001187
1188 // initial cJSON to use alloc callbacks
1189 cJSON_Hooks alloc_fns = {
1190 .malloc_fn = loader_tls_heap_alloc,
1191 .free_fn = loader_tls_heap_free,
1192 };
1193 cJSON_InitHooks(&alloc_fns);
Jon Ashburn754f1992015-08-18 18:04:47 -06001194}
1195
Jon Ashburnffd5d672015-06-29 11:25:34 -06001196struct loader_manifest_files {
1197 uint32_t count;
1198 char **filename_list;
1199};
1200
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06001201/**
Jon Ashburnffd5d672015-06-29 11:25:34 -06001202 * Get next file or dirname given a string list or registry key path
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06001203 *
1204 * \returns
Jon Ashburnffd5d672015-06-29 11:25:34 -06001205 * A pointer to first char in the next path.
1206 * The next path (or NULL) in the list is returned in next_path.
1207 * Note: input string is modified in some cases. PASS IN A COPY!
1208 */
Jon Ashburnffd5d672015-06-29 11:25:34 -06001209static char *loader_get_next_path(char *path)
1210{
1211 uint32_t len;
1212 char *next;
1213
1214 if (path == NULL)
1215 return NULL;
1216 next = strchr(path, PATH_SEPERATOR);
1217 if (next == NULL) {
1218 len = (uint32_t) strlen(path);
1219 next = path + len;
1220 }
1221 else {
1222 *next = '\0';
1223 next++;
1224 }
1225
1226 return next;
1227}
1228
1229/**
Jon Ashburn38144502015-07-07 15:06:25 -06001230 * Given a path which is absolute or relative. Expand the path if relative otherwise
1231 * leave the path unmodified if absolute. The path which is relative from is
1232 * given in rel_base and should include trailing directory seperator '/'
1233 *
1234 * \returns
1235 * A string in out_fullpath of the full absolute path
1236 * Side effect is that dir string maybe modified.
1237 */
1238static void loader_expand_path(const char *path,
1239 const char *rel_base,
1240 size_t out_size,
1241 char *out_fullpath)
1242{
1243 if (loader_platform_is_path_absolute(path)) {
1244 strncpy(out_fullpath, path, out_size);
1245 out_fullpath[out_size - 1] = '\0';
1246 }
1247 else {
1248 // convert relative to absolute path based on rel_base
1249 size_t len = strlen(path);
1250 strncpy(out_fullpath, rel_base, out_size);
1251 out_fullpath[out_size - 1] = '\0';
1252 assert(out_size >= strlen(out_fullpath) + len + 1);
1253 strncat(out_fullpath, path, len);
1254 }
1255}
1256
1257/**
Jon Ashburnffd5d672015-06-29 11:25:34 -06001258 * Given a filename (file) and a list of paths (dir), try to find an existing
1259 * file in the paths. If filename already is a path then no
1260 * searching in the given paths.
1261 *
1262 * \returns
1263 * A string in out_fullpath of either the full path or file.
1264 * Side effect is that dir string maybe modified.
1265 */
1266static void loader_get_fullpath(const char *file,
1267 char *dir,
1268 size_t out_size,
1269 char *out_fullpath)
1270{
1271 char *next_dir;
1272 if (strchr(file,DIRECTORY_SYMBOL) == NULL) {
1273 //find file exists with prepending given path
1274 while (*dir) {
1275 next_dir = loader_get_next_path(dir);
1276 snprintf(out_fullpath, out_size, "%s%c%s",
1277 dir, DIRECTORY_SYMBOL, file);
1278 if (loader_platform_file_exists(out_fullpath)) {
1279 return;
1280 }
1281 dir = next_dir;
1282 }
1283 }
1284 snprintf(out_fullpath, out_size, "%s", file);
1285}
1286
1287/**
1288 * Read a JSON file into a buffer.
1289 *
1290 * \returns
1291 * A pointer to a cJSON object representing the JSON parse tree.
1292 * This returned buffer should be freed by caller.
1293 */
1294static cJSON *loader_get_json(const char *filename)
1295{
1296 FILE *file;
1297 char *json_buf;
1298 cJSON *json;
1299 uint64_t len;
1300 file = fopen(filename,"rb");
Jon Ashburna01fb3e2015-08-27 08:30:50 -06001301 if (!file) {
1302 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Couldn't open JSON file %s", filename);
1303 return NULL;
1304 }
Jon Ashburnffd5d672015-06-29 11:25:34 -06001305 fseek(file, 0, SEEK_END);
1306 len = ftell(file);
1307 fseek(file, 0, SEEK_SET);
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -06001308 json_buf = (char*) loader_stack_alloc(len+1);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001309 if (json_buf == NULL) {
1310 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get JSON file");
1311 fclose(file);
1312 return NULL;
1313 }
1314 if (fread(json_buf, sizeof(char), len, file) != len) {
1315 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "fread failed can't get JSON file");
1316 fclose(file);
1317 return NULL;
1318 }
1319 fclose(file);
1320 json_buf[len] = '\0';
1321
1322 //parse text from file
1323 json = cJSON_Parse(json_buf);
1324 if (json == NULL)
1325 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Can't parse JSON file %s", filename);
1326 return json;
1327}
1328
1329/**
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06001330 * Do a deep copy of the loader_layer_properties structure.
1331 */
1332static void loader_copy_layer_properties(
Jon Ashburne58f1a32015-08-28 13:38:21 -06001333 const struct loader_instance *inst,
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06001334 struct loader_layer_properties *dst,
1335 struct loader_layer_properties *src)
1336{
1337 memcpy(dst, src, sizeof (*src));
Jon Ashburne58f1a32015-08-28 13:38:21 -06001338 dst->instance_extension_list.list = loader_heap_alloc(
1339 inst,
1340 sizeof(VkExtensionProperties) *
1341 src->instance_extension_list.count,
1342 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
1343 dst->instance_extension_list.capacity = sizeof(VkExtensionProperties) *
1344 src->instance_extension_list.count;
1345 memcpy(dst->instance_extension_list.list, src->instance_extension_list.list,
1346 dst->instance_extension_list.capacity);
1347 dst->device_extension_list.list = loader_heap_alloc(
1348 inst,
1349 sizeof(VkExtensionProperties) *
1350 src->device_extension_list.count,
1351 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
1352 dst->device_extension_list.capacity = sizeof(VkExtensionProperties) *
1353 src->device_extension_list.count;
1354 memcpy(dst->device_extension_list.list, src->device_extension_list.list,
1355 dst->device_extension_list.capacity);
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06001356}
1357
1358/**
Jon Ashburn1b111de2015-07-06 15:40:35 -06001359 * Given a cJSON struct (json) of the top level JSON object from layer manifest
1360 * file, add entry to the layer_list.
Jon Ashburn8e4fab42015-08-03 17:19:30 -06001361 * Fill out the layer_properties in this list entry from the input cJSON object.
Jon Ashburn1b111de2015-07-06 15:40:35 -06001362 *
1363 * \returns
1364 * void
1365 * layer_list has a new entry and initialized accordingly.
1366 * If the json input object does not have all the required fields no entry
1367 * is added to the list.
1368 */
Jon Ashburne58f1a32015-08-28 13:38:21 -06001369static void loader_add_layer_properties(const struct loader_instance *inst,
1370 struct loader_layer_list *layer_instance_list,
Jon Ashburn0bf6a182015-07-16 17:19:31 -06001371 struct loader_layer_list *layer_device_list,
Jon Ashburn1b111de2015-07-06 15:40:35 -06001372 cJSON *json,
1373 bool is_implicit,
1374 char *filename)
1375{
1376 /* Fields in layer manifest file that are required:
1377 * (required) “file_format_version”
1378 * following are required in the "layer" object:
1379 * (required) "name"
1380 * (required) "type"
1381 * (required) “library_path”
1382 * (required) “abi_versions”
1383 * (required) “implementation_version”
1384 * (required) “description”
1385 * (required for implicit layers) “disable_environment”
1386 *
1387 * First get all required items and if any missing abort
1388 */
1389
1390 cJSON *item, *layer_node, *ext_item;
1391 char *temp;
1392 char *name, *type, *library_path, *abi_versions;
1393 char *implementation_version, *description;
1394 cJSON *disable_environment;
1395 int i;
Jon Ashburnc4748dc2015-08-04 11:14:18 -06001396 VkExtensionProperties ext_prop;
Jon Ashburn1b111de2015-07-06 15:40:35 -06001397 item = cJSON_GetObjectItem(json, "file_format_version");
1398 if (item == NULL) {
1399 return;
1400 }
1401 char *file_vers = cJSON_PrintUnformatted(item);
1402 loader_log(VK_DBG_REPORT_INFO_BIT, 0, "Found manifest file %s, version %s",
1403 filename, file_vers);
1404 if (strcmp(file_vers, "\"0.9.0\"") != 0)
Jon Ashburn8e4fab42015-08-03 17:19:30 -06001405 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Unexpected manifest file version (expected 0.9.0), may cause errors");
Jon Ashburn413d6582015-08-28 15:19:27 -06001406 loader_tls_heap_free(file_vers);
Jon Ashburn1b111de2015-07-06 15:40:35 -06001407
Jon Ashburn1b111de2015-07-06 15:40:35 -06001408 layer_node = cJSON_GetObjectItem(json, "layer");
1409 if (layer_node == NULL) {
1410 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"layer\" object in manifest JSON file, skipping");
1411 return;
1412 }
Jon Ashburn082569b2015-08-12 16:39:32 -06001413
1414 // loop through all "layer" objects in the file
1415 do {
Jon Ashburn1b111de2015-07-06 15:40:35 -06001416#define GET_JSON_OBJECT(node, var) { \
1417 var = cJSON_GetObjectItem(node, #var); \
Jon Ashburn082569b2015-08-12 16:39:32 -06001418 if (var == NULL) { \
1419 layer_node = layer_node->next; \
1420 continue; \
1421 } \
Jon Ashburn1b111de2015-07-06 15:40:35 -06001422 }
1423#define GET_JSON_ITEM(node, var) { \
1424 item = cJSON_GetObjectItem(node, #var); \
Jon Ashburn082569b2015-08-12 16:39:32 -06001425 if (item == NULL) { \
1426 layer_node = layer_node->next; \
1427 continue; \
1428 } \
Jon Ashburn1b111de2015-07-06 15:40:35 -06001429 temp = cJSON_Print(item); \
1430 temp[strlen(temp) - 1] = '\0'; \
Jon Ashburn0b728052015-08-04 10:22:33 -06001431 var = loader_stack_alloc(strlen(temp) + 1); \
Jon Ashburn1b111de2015-07-06 15:40:35 -06001432 strcpy(var, &temp[1]); \
Jon Ashburn413d6582015-08-28 15:19:27 -06001433 loader_tls_heap_free(temp); \
Jon Ashburn1b111de2015-07-06 15:40:35 -06001434 }
Jon Ashburn082569b2015-08-12 16:39:32 -06001435 GET_JSON_ITEM(layer_node, name)
1436 GET_JSON_ITEM(layer_node, type)
1437 GET_JSON_ITEM(layer_node, library_path)
1438 GET_JSON_ITEM(layer_node, abi_versions)
1439 GET_JSON_ITEM(layer_node, implementation_version)
1440 GET_JSON_ITEM(layer_node, description)
1441 if (is_implicit) {
1442 GET_JSON_OBJECT(layer_node, disable_environment)
1443 }
Jon Ashburn1b111de2015-07-06 15:40:35 -06001444#undef GET_JSON_ITEM
1445#undef GET_JSON_OBJECT
1446
Jon Ashburn082569b2015-08-12 16:39:32 -06001447 // add list entry
Jon Ashburnb8605fe2015-09-18 12:53:16 -06001448 struct loader_layer_properties *props=NULL;
Jon Ashburn082569b2015-08-12 16:39:32 -06001449 if (!strcmp(type, "DEVICE")) {
1450 if (layer_device_list == NULL) {
1451 layer_node = layer_node->next;
1452 continue;
1453 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06001454 props = loader_get_next_layer_property(inst, layer_device_list);
Jon Ashburn082569b2015-08-12 16:39:32 -06001455 props->type = (is_implicit) ? VK_LAYER_TYPE_DEVICE_IMPLICIT : VK_LAYER_TYPE_DEVICE_EXPLICIT;
1456 }
1457 if (!strcmp(type, "INSTANCE")) {
1458 if (layer_instance_list == NULL) {
1459 layer_node = layer_node->next;
1460 continue;
1461 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06001462 props = loader_get_next_layer_property(inst, layer_instance_list);
Jon Ashburn082569b2015-08-12 16:39:32 -06001463 props->type = (is_implicit) ? VK_LAYER_TYPE_INSTANCE_IMPLICIT : VK_LAYER_TYPE_INSTANCE_EXPLICIT;
1464 }
1465 if (!strcmp(type, "GLOBAL")) {
1466 if (layer_instance_list != NULL)
Jon Ashburne58f1a32015-08-28 13:38:21 -06001467 props = loader_get_next_layer_property(inst, layer_instance_list);
Jon Ashburn082569b2015-08-12 16:39:32 -06001468 else if (layer_device_list != NULL)
Jon Ashburne58f1a32015-08-28 13:38:21 -06001469 props = loader_get_next_layer_property(inst, layer_device_list);
Jon Ashburn082569b2015-08-12 16:39:32 -06001470 else {
1471 layer_node = layer_node->next;
1472 continue;
1473 }
1474 props->type = (is_implicit) ? VK_LAYER_TYPE_GLOBAL_IMPLICIT : VK_LAYER_TYPE_GLOBAL_EXPLICIT;
1475 }
Jon Ashburn0bf6a182015-07-16 17:19:31 -06001476
Jon Ashburnb8605fe2015-09-18 12:53:16 -06001477 if (props == NULL) {
1478 layer_node = layer_node->next;
1479 continue;
1480 }
1481
Jon Ashburn082569b2015-08-12 16:39:32 -06001482 strncpy(props->info.layerName, name, sizeof (props->info.layerName));
1483 props->info.layerName[sizeof (props->info.layerName) - 1] = '\0';
Jon Ashburn38144502015-07-07 15:06:25 -06001484
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06001485 char *fullpath = props->lib_name;
Jon Ashburn082569b2015-08-12 16:39:32 -06001486 char *rel_base;
1487 if (strchr(library_path, DIRECTORY_SYMBOL) == NULL) {
1488 // a filename which is assumed in the system directory
1489 char *def_path = loader_stack_alloc(strlen(DEFAULT_VK_LAYERS_PATH) + 1);
1490 strcpy(def_path, DEFAULT_VK_LAYERS_PATH);
1491 loader_get_fullpath(library_path, def_path, MAX_STRING_SIZE, fullpath);
1492 } else {
1493 // a relative or absolute path
1494 char *name_copy = loader_stack_alloc(strlen(filename) + 2);
1495 size_t len;
1496 strcpy(name_copy, filename);
1497 rel_base = loader_platform_dirname(name_copy);
1498 len = strlen(rel_base);
1499 rel_base[len] = DIRECTORY_SYMBOL;
1500 rel_base[len + 1] = '\0';
1501 loader_expand_path(library_path, rel_base, MAX_STRING_SIZE, fullpath);
1502 }
Jon Ashburn082569b2015-08-12 16:39:32 -06001503 props->info.specVersion = loader_make_version(abi_versions);
1504 props->info.implVersion = loader_make_version(implementation_version);
1505 strncpy((char *) props->info.description, description, sizeof (props->info.description));
1506 props->info.description[sizeof (props->info.description) - 1] = '\0';
1507 if (is_implicit) {
1508 strncpy(props->disable_env_var.name, disable_environment->child->string, sizeof (props->disable_env_var.name));
1509 props->disable_env_var.name[sizeof (props->disable_env_var.name) - 1] = '\0';
1510 strncpy(props->disable_env_var.value, disable_environment->child->valuestring, sizeof (props->disable_env_var.value));
1511 props->disable_env_var.value[sizeof (props->disable_env_var.value) - 1] = '\0';
1512 }
Jon Ashburn1b111de2015-07-06 15:40:35 -06001513
Jon Ashburn082569b2015-08-12 16:39:32 -06001514 /**
1515 * Now get all optional items and objects and put in list:
1516 * functions
1517 * instance_extensions
1518 * device_extensions
1519 * enable_environment (implicit layers only)
1520 */
Jon Ashburn1b111de2015-07-06 15:40:35 -06001521#define GET_JSON_OBJECT(node, var) { \
1522 var = cJSON_GetObjectItem(node, #var); \
1523 }
1524#define GET_JSON_ITEM(node, var) { \
1525 item = cJSON_GetObjectItem(node, #var); \
Jon Ashburn2db08042015-09-09 11:29:24 -06001526 if (item != NULL) { \
Jon Ashburn1b111de2015-07-06 15:40:35 -06001527 temp = cJSON_Print(item); \
Jon Ashburn2db08042015-09-09 11:29:24 -06001528 temp[strlen(temp) - 1] = '\0'; \
1529 var = loader_stack_alloc(strlen(temp) + 1);\
1530 strcpy(var, &temp[1]); \
1531 loader_tls_heap_free(temp); \
1532 } \
Jon Ashburn1b111de2015-07-06 15:40:35 -06001533 }
1534
Jon Ashburn082569b2015-08-12 16:39:32 -06001535 cJSON *instance_extensions, *device_extensions, *functions, *enable_environment;
Jon Ashburnb8605fe2015-09-18 12:53:16 -06001536 char *vkGetInstanceProcAddr = NULL, *vkGetDeviceProcAddr = NULL, *version=NULL;
Jon Ashburn082569b2015-08-12 16:39:32 -06001537 GET_JSON_OBJECT(layer_node, functions)
1538 if (functions != NULL) {
1539 GET_JSON_ITEM(functions, vkGetInstanceProcAddr)
1540 GET_JSON_ITEM(functions, vkGetDeviceProcAddr)
Jon Ashburn2db08042015-09-09 11:29:24 -06001541 if (vkGetInstanceProcAddr != NULL)
1542 strncpy(props->functions.str_gipa, vkGetInstanceProcAddr, sizeof (props->functions.str_gipa));
Jon Ashburn082569b2015-08-12 16:39:32 -06001543 props->functions.str_gipa[sizeof (props->functions.str_gipa) - 1] = '\0';
Jon Ashburn2db08042015-09-09 11:29:24 -06001544 if (vkGetDeviceProcAddr != NULL)
1545 strncpy(props->functions.str_gdpa, vkGetDeviceProcAddr, sizeof (props->functions.str_gdpa));
Jon Ashburn082569b2015-08-12 16:39:32 -06001546 props->functions.str_gdpa[sizeof (props->functions.str_gdpa) - 1] = '\0';
Jon Ashburn1b111de2015-07-06 15:40:35 -06001547 }
Jon Ashburn082569b2015-08-12 16:39:32 -06001548 GET_JSON_OBJECT(layer_node, instance_extensions)
1549 if (instance_extensions != NULL) {
1550 int count = cJSON_GetArraySize(instance_extensions);
1551 for (i = 0; i < count; i++) {
1552 ext_item = cJSON_GetArrayItem(instance_extensions, i);
1553 GET_JSON_ITEM(ext_item, name)
1554 GET_JSON_ITEM(ext_item, version)
1555 strncpy(ext_prop.extName, name, sizeof (ext_prop.extName));
1556 ext_prop.extName[sizeof (ext_prop.extName) - 1] = '\0';
1557 ext_prop.specVersion = loader_make_version(version);
Jon Ashburne58f1a32015-08-28 13:38:21 -06001558 loader_add_to_ext_list(inst, &props->instance_extension_list, 1, &ext_prop);
Jon Ashburn082569b2015-08-12 16:39:32 -06001559 }
Jon Ashburn1b111de2015-07-06 15:40:35 -06001560 }
Jon Ashburn082569b2015-08-12 16:39:32 -06001561 GET_JSON_OBJECT(layer_node, device_extensions)
1562 if (device_extensions != NULL) {
1563 int count = cJSON_GetArraySize(device_extensions);
1564 for (i = 0; i < count; i++) {
1565 ext_item = cJSON_GetArrayItem(device_extensions, i);
1566 GET_JSON_ITEM(ext_item, name);
1567 GET_JSON_ITEM(ext_item, version);
1568 strncpy(ext_prop.extName, name, sizeof (ext_prop.extName));
1569 ext_prop.extName[sizeof (ext_prop.extName) - 1] = '\0';
1570 ext_prop.specVersion = loader_make_version(version);
Jon Ashburne58f1a32015-08-28 13:38:21 -06001571 loader_add_to_ext_list(inst, &props->device_extension_list, 1, &ext_prop);
Jon Ashburn082569b2015-08-12 16:39:32 -06001572 }
1573 }
1574 if (is_implicit) {
1575 GET_JSON_OBJECT(layer_node, enable_environment)
1576 strncpy(props->enable_env_var.name, enable_environment->child->string, sizeof (props->enable_env_var.name));
1577 props->enable_env_var.name[sizeof (props->enable_env_var.name) - 1] = '\0';
1578 strncpy(props->enable_env_var.value, enable_environment->child->valuestring, sizeof (props->enable_env_var.value));
1579 props->enable_env_var.value[sizeof (props->enable_env_var.value) - 1] = '\0';
1580 }
Jon Ashburn1b111de2015-07-06 15:40:35 -06001581#undef GET_JSON_ITEM
1582#undef GET_JSON_OBJECT
Jon Ashburn082569b2015-08-12 16:39:32 -06001583 // for global layers need to add them to both device and instance list
1584 if (!strcmp(type, "GLOBAL")) {
1585 struct loader_layer_properties *dev_props;
1586 if (layer_instance_list == NULL || layer_device_list == NULL) {
1587 layer_node = layer_node->next;
1588 continue;
1589 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06001590 dev_props = loader_get_next_layer_property(inst, layer_device_list);
Jon Ashburn082569b2015-08-12 16:39:32 -06001591 //copy into device layer list
Jon Ashburne58f1a32015-08-28 13:38:21 -06001592 loader_copy_layer_properties(inst, dev_props, props);
Jon Ashburn082569b2015-08-12 16:39:32 -06001593 }
1594 layer_node = layer_node->next;
1595 } while (layer_node != NULL);
1596 return;
Jon Ashburn1b111de2015-07-06 15:40:35 -06001597}
1598
1599/**
Jon Ashburnffd5d672015-06-29 11:25:34 -06001600 * Find the Vulkan library manifest files.
1601 *
1602 * This function scans the location or env_override directories/files
1603 * for a list of JSON manifest files. If env_override is non-NULL
1604 * and has a valid value. Then the location is ignored. Otherwise
1605 * location is used to look for manifest files. The location
1606 * is interpreted as Registry path on Windows and a directory path(s)
1607 * on Linux.
1608 *
1609 * \returns
1610 * A string list of manifest files to be opened in out_files param.
1611 * List has a pointer to string for each manifest filename.
1612 * When done using the list in out_files, pointers should be freed.
Jon Ashburnee33ae72015-06-30 14:46:22 -07001613 * Location or override string lists can be either files or directories as follows:
1614 * | location | override
1615 * --------------------------------
1616 * Win ICD | files | files
1617 * Win Layer | files | dirs
1618 * Linux ICD | dirs | files
1619 * Linux Layer| dirs | dirs
Jon Ashburnffd5d672015-06-29 11:25:34 -06001620 */
Jon Ashburne58f1a32015-08-28 13:38:21 -06001621static void loader_get_manifest_files(const struct loader_instance *inst,
1622 const char *env_override,
Jon Ashburnee33ae72015-06-30 14:46:22 -07001623 bool is_layer,
1624 const char *location,
1625 struct loader_manifest_files *out_files)
Jon Ashburnffd5d672015-06-29 11:25:34 -06001626{
1627 char *override = NULL;
1628 char *loc;
1629 char *file, *next_file, *name;
1630 size_t alloced_count = 64;
1631 char full_path[2048];
1632 DIR *sysdir = NULL;
Jon Ashburnee33ae72015-06-30 14:46:22 -07001633 bool list_is_dirs = false;
Jon Ashburnffd5d672015-06-29 11:25:34 -06001634 struct dirent *dent;
1635
1636 out_files->count = 0;
1637 out_files->filename_list = NULL;
1638
Jon Ashburnffd5d672015-06-29 11:25:34 -06001639 if (env_override != NULL && (override = getenv(env_override))) {
1640#if defined(__linux__)
1641 if (geteuid() != getuid()) {
Jon Ashburnee33ae72015-06-30 14:46:22 -07001642 /* Don't allow setuid apps to use the env var: */
Jon Ashburnffd5d672015-06-29 11:25:34 -06001643 override = NULL;
1644 }
1645#endif
1646 }
1647
1648 if (location == NULL) {
1649 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
Jon Ashburnee33ae72015-06-30 14:46:22 -07001650 "Can't get manifest files with NULL location, env_override=%s",
1651 env_override);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001652 return;
1653 }
1654
Jon Ashburnee33ae72015-06-30 14:46:22 -07001655#if defined(__linux__)
1656 list_is_dirs = (override == NULL || is_layer) ? true : false;
1657#else //WIN32
1658 list_is_dirs = (is_layer && override != NULL) ? true : false;
1659#endif
Jon Ashburnffd5d672015-06-29 11:25:34 -06001660 // Make a copy of the input we are using so it is not modified
Jon Ashburnee33ae72015-06-30 14:46:22 -07001661 // Also handle getting the location(s) from registry on Windows
1662 if (override == NULL) {
Jon Ashburncdc9f0a2015-07-31 10:11:24 -06001663 loc = loader_stack_alloc(strlen(location) + 1);
Jon Ashburnee33ae72015-06-30 14:46:22 -07001664 if (loc == NULL) {
1665 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files");
1666 return;
1667 }
1668 strcpy(loc, location);
Jon Ashburnc1381ed2015-07-31 09:33:21 -06001669#if defined (_WIN32)
Jon Ashburn6fb9a532015-08-28 14:58:46 -07001670 loc = loader_get_registry_files(inst, loc);
Jon Ashburnc1381ed2015-07-31 09:33:21 -06001671 if (loc == NULL) {
1672 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Registry lookup failed can't get manifest files");
1673 return;
1674 }
Jon Ashburnee33ae72015-06-30 14:46:22 -07001675#endif
Jon Ashburnffd5d672015-06-29 11:25:34 -06001676 }
Jon Ashburnee33ae72015-06-30 14:46:22 -07001677 else {
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -06001678 loc = loader_stack_alloc(strlen(override) + 1);
Jon Ashburnee33ae72015-06-30 14:46:22 -07001679 if (loc == NULL) {
1680 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files");
1681 return;
1682 }
1683 strcpy(loc, override);
1684 }
Jon Ashburnffd5d672015-06-29 11:25:34 -06001685
Liam Middlebrookf2a6ec42015-07-23 18:32:20 -07001686 // Print out the paths being searched if debugging is enabled
Jon Ashburn6ff63e42015-07-31 09:41:31 -06001687 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, "Searching the following paths for manifest files: %s\n", loc);
Liam Middlebrookf2a6ec42015-07-23 18:32:20 -07001688
Jon Ashburnffd5d672015-06-29 11:25:34 -06001689 file = loc;
1690 while (*file) {
1691 next_file = loader_get_next_path(file);
Jon Ashburnee33ae72015-06-30 14:46:22 -07001692 if (list_is_dirs) {
Jon Ashburnffd5d672015-06-29 11:25:34 -06001693 sysdir = opendir(file);
1694 name = NULL;
1695 if (sysdir) {
1696 dent = readdir(sysdir);
1697 if (dent == NULL)
1698 break;
1699 name = &(dent->d_name[0]);
1700 loader_get_fullpath(name, file, sizeof(full_path), full_path);
1701 name = full_path;
1702 }
1703 }
1704 else {
Jon Ashburnee33ae72015-06-30 14:46:22 -07001705#if defined(__linux__)
1706 // only Linux has relative paths
Jon Ashburnffd5d672015-06-29 11:25:34 -06001707 char *dir;
1708 // make a copy of location so it isn't modified
Jon Ashburne5c48722015-08-27 13:06:58 -06001709 dir = loader_stack_alloc(strlen(location) + 1);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001710 if (dir == NULL) {
1711 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files");
1712 return;
1713 }
1714 strcpy(dir, location);
1715
1716 loader_get_fullpath(file, dir, sizeof(full_path), full_path);
1717
1718 name = full_path;
Jon Ashburnee33ae72015-06-30 14:46:22 -07001719#else // WIN32
1720 name = file;
1721#endif
Jon Ashburnffd5d672015-06-29 11:25:34 -06001722 }
1723 while (name) {
1724 /* Look for files ending with ".json" suffix */
1725 uint32_t nlen = (uint32_t) strlen(name);
1726 const char *suf = name + nlen - 5;
1727 if ((nlen > 5) && !strncmp(suf, ".json", 5)) {
1728 if (out_files->count == 0) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06001729 out_files->filename_list = loader_heap_alloc(inst,
1730 alloced_count * sizeof(char *),
1731 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001732 }
1733 else if (out_files->count == alloced_count) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06001734 out_files->filename_list = loader_heap_realloc(inst,
1735 out_files->filename_list,
1736 alloced_count * sizeof(char *),
1737 alloced_count * sizeof(char *) * 2,
1738 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001739 alloced_count *= 2;
1740 }
1741 if (out_files->filename_list == NULL) {
1742 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't alloc manifest file list");
1743 return;
1744 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06001745 out_files->filename_list[out_files->count] = loader_heap_alloc(
1746 inst,
1747 strlen(name) + 1,
1748 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001749 if (out_files->filename_list[out_files->count] == NULL) {
1750 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files");
1751 return;
1752 }
1753 strcpy(out_files->filename_list[out_files->count], name);
1754 out_files->count++;
Jon Ashburnc5662f62015-07-02 10:08:47 -06001755 } else if (!list_is_dirs) {
1756 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 -06001757 }
Jon Ashburnee33ae72015-06-30 14:46:22 -07001758 if (list_is_dirs) {
Jon Ashburnffd5d672015-06-29 11:25:34 -06001759 dent = readdir(sysdir);
1760 if (dent == NULL)
1761 break;
1762 name = &(dent->d_name[0]);
1763 loader_get_fullpath(name, file, sizeof(full_path), full_path);
1764 name = full_path;
1765 }
1766 else {
1767 break;
1768 }
1769 }
1770 if (sysdir)
1771 closedir(sysdir);
1772 file = next_file;
1773 }
1774 return;
1775}
1776
Jon Ashburn754f1992015-08-18 18:04:47 -06001777void loader_init_icd_lib_list()
1778{
1779
1780}
1781
1782void loader_destroy_icd_lib_list()
1783{
1784
1785}
Jon Ashburnffd5d672015-06-29 11:25:34 -06001786/**
1787 * Try to find the Vulkan ICD driver(s).
1788 *
1789 * This function scans the default system loader path(s) or path
1790 * specified by the \c VK_ICD_FILENAMES environment variable in
1791 * order to find loadable VK ICDs manifest files. From these
1792 * manifest files it finds the ICD libraries.
1793 *
1794 * \returns
Jon Ashburn754f1992015-08-18 18:04:47 -06001795 * a list of icds that were discovered
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06001796 */
Jon Ashburne58f1a32015-08-28 13:38:21 -06001797void loader_icd_scan(
1798 const struct loader_instance *inst,
1799 struct loader_icd_libs *icds)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001800{
Jon Ashburnffd5d672015-06-29 11:25:34 -06001801 char *file_str;
1802 struct loader_manifest_files manifest_files;
1803
Jon Ashburne58f1a32015-08-28 13:38:21 -06001804 loader_scanned_icd_init(inst, icds);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001805 // Get a list of manifest files for ICDs
Jon Ashburne58f1a32015-08-28 13:38:21 -06001806 loader_get_manifest_files(inst, "VK_ICD_FILENAMES", false,
1807 DEFAULT_VK_DRIVERS_INFO, &manifest_files);
Jon Ashburn1b111de2015-07-06 15:40:35 -06001808 if (manifest_files.count == 0)
1809 return;
Jon Ashburnd02fc2c2015-09-22 13:11:00 -06001810 loader_platform_thread_lock_mutex(&loader_json_lock);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001811 for (uint32_t i = 0; i < manifest_files.count; i++) {
1812 file_str = manifest_files.filename_list[i];
1813 if (file_str == NULL)
1814 continue;
1815
Jon Ashburn1b111de2015-07-06 15:40:35 -06001816 cJSON *json;
Jon Ashburnffd5d672015-06-29 11:25:34 -06001817 json = loader_get_json(file_str);
Jon Ashburna01fb3e2015-08-27 08:30:50 -06001818 if (!json)
1819 continue;
Jon Ashburn1b111de2015-07-06 15:40:35 -06001820 cJSON *item;
1821 item = cJSON_GetObjectItem(json, "file_format_version");
Jon Ashburnd02fc2c2015-09-22 13:11:00 -06001822 if (item == NULL) {
1823 loader_platform_thread_unlock_mutex(&loader_json_lock);
Jon Ashburn1b111de2015-07-06 15:40:35 -06001824 return;
Jon Ashburnd02fc2c2015-09-22 13:11:00 -06001825 }
Jon Ashburn1b111de2015-07-06 15:40:35 -06001826 char *file_vers = cJSON_Print(item);
1827 loader_log(VK_DBG_REPORT_INFO_BIT, 0, "Found manifest file %s, version %s",
1828 file_str, file_vers);
1829 if (strcmp(file_vers, "\"1.0.0\"") != 0)
1830 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Unexpected manifest file version (expected 1.0.0), may cause errors");
Jon Ashburn413d6582015-08-28 15:19:27 -06001831 loader_tls_heap_free(file_vers);
Jon Ashburn1b111de2015-07-06 15:40:35 -06001832 item = cJSON_GetObjectItem(json, "ICD");
1833 if (item != NULL) {
1834 item = cJSON_GetObjectItem(item, "library_path");
1835 if (item != NULL) {
Jon Ashburn10442c12015-08-25 16:48:24 -06001836 char *temp= cJSON_Print(item);
1837 if (!temp || strlen(temp) == 0) {
1838 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"library_path\" in ICD JSON file %s, skipping", file_str);
Jon Ashburn413d6582015-08-28 15:19:27 -06001839 loader_tls_heap_free(temp);
Jon Ashburne58f1a32015-08-28 13:38:21 -06001840 loader_heap_free(inst, file_str);
Jon Ashburn10442c12015-08-25 16:48:24 -06001841 cJSON_Delete(json);
1842 continue;
Jon Ashburnffd5d672015-06-29 11:25:34 -06001843 }
Jon Ashburn10442c12015-08-25 16:48:24 -06001844 //strip out extra quotes
1845 temp[strlen(temp) - 1] = '\0';
1846 char *library_path = loader_stack_alloc(strlen(temp) + 1);
1847 strcpy(library_path, &temp[1]);
Jon Ashburn413d6582015-08-28 15:19:27 -06001848 loader_tls_heap_free(temp);
Jon Ashburn10442c12015-08-25 16:48:24 -06001849 if (!library_path || strlen(library_path) == 0) {
1850 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"library_path\" in ICD JSON file %s, skipping", file_str);
Jon Ashburne58f1a32015-08-28 13:38:21 -06001851 loader_heap_free(inst, file_str);
Jon Ashburn10442c12015-08-25 16:48:24 -06001852 cJSON_Delete(json);
1853 continue;
1854 }
1855 char *fullpath;
1856 uint32_t path_len;
1857 char *rel_base;
1858 // Print out the paths being searched if debugging is enabled
1859 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, "Searching for ICD drivers named %s default dir %s\n", library_path, DEFAULT_VK_DRIVERS_PATH);
1860 if (strchr(library_path, DIRECTORY_SYMBOL) == NULL) {
1861 // a filename which is assumed in the system directory
1862 char *def_path = loader_stack_alloc(strlen(DEFAULT_VK_DRIVERS_PATH) + 1);
1863 strcpy(def_path, DEFAULT_VK_DRIVERS_PATH);
1864 path_len = strlen(DEFAULT_VK_DRIVERS_PATH) + strlen(library_path) + 2;
1865 fullpath = loader_stack_alloc(path_len);
1866#if defined(__linux__)
1867 loader_get_fullpath(library_path, def_path, path_len, fullpath);
1868#else // WIN32
1869 strncpy(fullpath, library_path, sizeof (fullpath));
1870 fullpath[sizeof (fullpath) - 1] = '\0';
1871#endif
1872 } else {
1873 // a relative or absolute path
1874 char *name_copy = loader_stack_alloc(strlen(file_str) + 2);
1875 size_t len;
1876 strcpy(name_copy, file_str);
1877 rel_base = loader_platform_dirname(name_copy);
1878 len = strlen(rel_base);
1879 rel_base[len] = DIRECTORY_SYMBOL;
1880 rel_base[len + 1] = '\0';
1881 path_len = strlen(rel_base) + strlen(library_path) + 2;
1882 fullpath = loader_stack_alloc(path_len);
1883 loader_expand_path(library_path, rel_base, path_len, fullpath);
1884 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06001885 loader_scanned_icd_add(inst, icds, fullpath);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001886 }
Jon Ashburn10442c12015-08-25 16:48:24 -06001887
Jon Ashburnffd5d672015-06-29 11:25:34 -06001888 }
1889 else
1890 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"ICD\" object in ICD JSON file %s, skipping", file_str);
1891
Jon Ashburne58f1a32015-08-28 13:38:21 -06001892 loader_heap_free(inst, file_str);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001893 cJSON_Delete(json);
1894 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06001895 loader_heap_free(inst, manifest_files.filename_list);
Jon Ashburnd02fc2c2015-09-22 13:11:00 -06001896 loader_platform_thread_unlock_mutex(&loader_json_lock);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001897}
1898
Jon Ashburnd43f9b62014-10-14 19:15:22 -06001899
Jon Ashburne58f1a32015-08-28 13:38:21 -06001900void loader_layer_scan(
1901 const struct loader_instance *inst,
1902 struct loader_layer_list *instance_layers,
1903 struct loader_layer_list *device_layers)
Jon Ashburnd43f9b62014-10-14 19:15:22 -06001904{
Jon Ashburn1b111de2015-07-06 15:40:35 -06001905 char *file_str;
1906 struct loader_manifest_files manifest_files;
1907 cJSON *json;
1908 uint32_t i;
Jon Ashburnd43f9b62014-10-14 19:15:22 -06001909
Jon Ashburn1b111de2015-07-06 15:40:35 -06001910 // Get a list of manifest files for layers
Jon Ashburne58f1a32015-08-28 13:38:21 -06001911 loader_get_manifest_files(inst, LAYERS_PATH_ENV, true, DEFAULT_VK_LAYERS_INFO,
Jon Ashburn1b111de2015-07-06 15:40:35 -06001912 &manifest_files);
1913 if (manifest_files.count == 0)
Courtney Goeltzenleuchterbce445a2014-12-01 09:29:42 -07001914 return;
Jon Ashburn0dcd6192015-06-04 15:30:58 -06001915
Jon Ashburn8e4fab42015-08-03 17:19:30 -06001916#if 0 //TODO
Jon Ashburn1b111de2015-07-06 15:40:35 -06001917 /**
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -06001918 * We need a list of the layer libraries, not just a list of
1919 * the layer properties (a layer library could expose more than
1920 * one layer property). This list of scanned layers would be
1921 * used to check for global and physicaldevice layer properties.
1922 */
1923 if (!loader_init_layer_library_list(&loader.scanned_layer_libraries)) {
1924 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
Jon Ashburne58f1a32015-08-28 13:38:21 -06001925 "Alloc for layer list failed: %s line: %d", __FILE__, __LINE__);
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -06001926 return;
Jon Ashburn68a63922015-07-02 09:40:15 -06001927 }
Jon Ashburn1b111de2015-07-06 15:40:35 -06001928#endif
Jon Ashburnd43f9b62014-10-14 19:15:22 -06001929
Jon Ashburn8e4fab42015-08-03 17:19:30 -06001930 /* cleanup any previously scanned libraries */
Jon Ashburne58f1a32015-08-28 13:38:21 -06001931 loader_delete_layer_properties(inst, instance_layers);
1932 loader_delete_layer_properties(inst, device_layers);
Jon Ashburn0bf6a182015-07-16 17:19:31 -06001933
Jon Ashburnd02fc2c2015-09-22 13:11:00 -06001934 loader_platform_thread_lock_mutex(&loader_json_lock);
Jon Ashburn1b111de2015-07-06 15:40:35 -06001935 for (i = 0; i < manifest_files.count; i++) {
1936 file_str = manifest_files.filename_list[i];
1937 if (file_str == NULL)
1938 continue;
Courtney Goeltzenleuchteraa685052015-06-01 14:49:17 -06001939
Jon Ashburn1b111de2015-07-06 15:40:35 -06001940 // parse file into JSON struct
1941 json = loader_get_json(file_str);
1942 if (!json) {
1943 continue;
1944 }
Jon Ashburn8e4fab42015-08-03 17:19:30 -06001945
Jon Ashburn1b111de2015-07-06 15:40:35 -06001946 //TODO pass in implicit versus explicit bool
Jon Ashburn0bf6a182015-07-16 17:19:31 -06001947 //TODO error if device layers expose instance_extensions
1948 //TODO error if instance layers expose device extensions
Jon Ashburne58f1a32015-08-28 13:38:21 -06001949 loader_add_layer_properties(inst,
1950 instance_layers,
Jon Ashburn182b8302015-08-11 14:49:54 -06001951 device_layers,
Jon Ashburn0bf6a182015-07-16 17:19:31 -06001952 json,
1953 false,
1954 file_str);
1955
Jon Ashburne58f1a32015-08-28 13:38:21 -06001956 loader_heap_free(inst, file_str);
Jon Ashburn1b111de2015-07-06 15:40:35 -06001957 cJSON_Delete(json);
1958 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06001959 loader_heap_free(inst, manifest_files.filename_list);
Jon Ashburnd02fc2c2015-09-22 13:11:00 -06001960 loader_platform_thread_unlock_mutex(&loader_json_lock);
Jon Ashburnd43f9b62014-10-14 19:15:22 -06001961}
1962
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -06001963static PFN_vkVoidFunction VKAPI loader_gpa_instance_internal(VkInstance inst, const char * pName)
Jon Ashburnfce93d92015-05-12 17:26:48 -06001964{
1965 // inst is not wrapped
1966 if (inst == VK_NULL_HANDLE) {
1967 return NULL;
1968 }
1969 VkLayerInstanceDispatchTable* disp_table = * (VkLayerInstanceDispatchTable **) inst;
1970 void *addr;
1971
Jon Ashburn4f2575f2015-05-28 16:25:02 -06001972 if (!strcmp(pName, "vkGetInstanceProcAddr"))
1973 return (void *) loader_gpa_instance_internal;
1974
Jon Ashburnfce93d92015-05-12 17:26:48 -06001975 if (disp_table == NULL)
1976 return NULL;
1977
1978 addr = loader_lookup_instance_dispatch_table(disp_table, pName);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001979 if (addr) {
Jon Ashburnfce93d92015-05-12 17:26:48 -06001980 return addr;
Jon Ashburne18431b2015-04-13 18:10:06 -06001981 }
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001982
1983 if (disp_table->GetInstanceProcAddr == NULL) {
1984 return NULL;
1985 }
1986 return disp_table->GetInstanceProcAddr(inst, pName);
Jon Ashburne18431b2015-04-13 18:10:06 -06001987}
1988
Jon Ashburnd5df54d2015-05-28 19:16:58 -06001989struct loader_icd * loader_get_icd(const VkPhysicalDevice gpu, uint32_t *gpu_index)
Jon Ashburnb55278a2014-10-17 15:09:07 -06001990{
Jon Ashburnd5df54d2015-05-28 19:16:58 -06001991
Tony Barbour9687cb12015-07-14 13:34:05 -06001992 *gpu_index = 0;
Jon Ashburndc67ef52015-01-29 16:44:24 -07001993 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
1994 for (struct loader_icd *icd = inst->icds; icd; icd = icd->next) {
1995 for (uint32_t i = 0; i < icd->gpu_count; i++)
Jon Ashburnd5df54d2015-05-28 19:16:58 -06001996 if (icd->gpus[i] == gpu) {
Jon Ashburndc67ef52015-01-29 16:44:24 -07001997 *gpu_index = i;
1998 return icd;
1999 }
2000 }
Jon Ashburnb55278a2014-10-17 15:09:07 -06002001 }
2002 return NULL;
2003}
2004
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002005static loader_platform_dl_handle loader_add_layer_lib(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002006 const struct loader_instance *inst,
Jon Ashburn9a9de1f2015-05-27 13:19:22 -06002007 const char *chain_type,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002008 struct loader_layer_properties *layer_prop)
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002009{
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002010 struct loader_lib_info *new_layer_lib_list, *my_lib;
Jon Ashburne58f1a32015-08-28 13:38:21 -06002011 size_t new_alloc_size;
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -06002012 /*
2013 * TODO: We can now track this information in the
2014 * scanned_layer_libraries list.
2015 */
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002016 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) {
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002017 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, layer_prop->lib_name) == 0) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002018 /* Have already loaded this library, just increment ref count */
2019 loader.loaded_layer_lib_list[i].ref_count++;
Courtney Goeltzenleuchter926f39e2015-06-14 11:59:07 -06002020 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002021 "%s Chain: Increment layer reference count for layer library %s",
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002022 chain_type, layer_prop->lib_name);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002023 return loader.loaded_layer_lib_list[i].lib_handle;
2024 }
2025 }
2026
2027 /* Haven't seen this library so load it */
Jon Ashburne58f1a32015-08-28 13:38:21 -06002028 new_alloc_size = 0;
2029 if (loader.loaded_layer_lib_capacity == 0)
2030 new_alloc_size = 8 * sizeof(struct loader_lib_info);
2031 else if (loader.loaded_layer_lib_capacity <= loader.loaded_layer_lib_count *
2032 sizeof(struct loader_lib_info))
2033 new_alloc_size = loader.loaded_layer_lib_capacity * 2;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002034
Jon Ashburne58f1a32015-08-28 13:38:21 -06002035 if (new_alloc_size) {
2036 new_layer_lib_list = loader_heap_realloc(
2037 inst, loader.loaded_layer_lib_list,
2038 loader.loaded_layer_lib_capacity,
2039 new_alloc_size,
2040 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
2041 if (!new_layer_lib_list) {
2042 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "loader: realloc failed in loader_add_layer_lib");
2043 return NULL;
2044 }
2045 loader.loaded_layer_lib_capacity = new_alloc_size;
2046 } else
2047 new_layer_lib_list = loader.loaded_layer_lib_list;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002048 my_lib = &new_layer_lib_list[loader.loaded_layer_lib_count];
2049
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002050 strncpy(my_lib->lib_name, layer_prop->lib_name, sizeof(my_lib->lib_name));
2051 my_lib->lib_name[sizeof(my_lib->lib_name) - 1] = '\0';
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002052 my_lib->ref_count = 0;
2053 my_lib->lib_handle = NULL;
2054
2055 if ((my_lib->lib_handle = loader_platform_open_library(my_lib->lib_name)) == NULL) {
2056 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
2057 loader_platform_open_library_error(my_lib->lib_name));
2058 return NULL;
2059 } else {
Courtney Goeltzenleuchter926f39e2015-06-14 11:59:07 -06002060 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002061 "Chain: %s: Loading layer library %s",
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002062 chain_type, layer_prop->lib_name);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002063 }
2064 loader.loaded_layer_lib_count++;
2065 loader.loaded_layer_lib_list = new_layer_lib_list;
2066 my_lib->ref_count++;
2067
2068 return my_lib->lib_handle;
2069}
2070
2071static void loader_remove_layer_lib(
2072 struct loader_instance *inst,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002073 struct loader_layer_properties *layer_prop)
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002074{
2075 uint32_t idx;
Tony Barbour9687cb12015-07-14 13:34:05 -06002076 struct loader_lib_info *new_layer_lib_list, *my_lib = NULL;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002077
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002078 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) {
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002079 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, layer_prop->lib_name) == 0) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002080 /* found matching library */
2081 idx = i;
2082 my_lib = &loader.loaded_layer_lib_list[i];
2083 break;
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002084 }
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002085 }
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002086
Tony Barbour9687cb12015-07-14 13:34:05 -06002087 if (my_lib) {
2088 my_lib->ref_count--;
2089 if (my_lib->ref_count > 0) {
2090 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002091 "Decrement reference count for layer library %s", layer_prop->lib_name);
Tony Barbour9687cb12015-07-14 13:34:05 -06002092 return;
2093 }
Courtney Goeltzenleuchter0199e952015-02-27 15:19:33 -07002094 }
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002095 loader_platform_close_library(my_lib->lib_handle);
Courtney Goeltzenleuchter926f39e2015-06-14 11:59:07 -06002096 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002097 "Unloading layer library %s", layer_prop->lib_name);
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002098
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002099 /* Need to remove unused library from list */
Jon Ashburne58f1a32015-08-28 13:38:21 -06002100 new_layer_lib_list = loader_heap_alloc(inst,
2101 loader.loaded_layer_lib_capacity,
2102 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002103 if (!new_layer_lib_list) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06002104 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "loader: heap alloc failed loader_remove_layer_library");
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002105 return;
2106 }
2107
2108 if (idx > 0) {
2109 /* Copy records before idx */
2110 memcpy(new_layer_lib_list, &loader.loaded_layer_lib_list[0],
2111 sizeof(struct loader_lib_info) * idx);
2112 }
2113 if (idx < (loader.loaded_layer_lib_count - 1)) {
2114 /* Copy records after idx */
2115 memcpy(&new_layer_lib_list[idx], &loader.loaded_layer_lib_list[idx+1],
2116 sizeof(struct loader_lib_info) * (loader.loaded_layer_lib_count - idx - 1));
2117 }
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002118
Jon Ashburne58f1a32015-08-28 13:38:21 -06002119 loader_heap_free(inst, loader.loaded_layer_lib_list);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002120 loader.loaded_layer_lib_count--;
2121 loader.loaded_layer_lib_list = new_layer_lib_list;
Jon Ashburnead95c52014-11-18 09:06:04 -07002122}
2123
Jon Ashburn1b111de2015-07-06 15:40:35 -06002124
2125/**
2126 * Go through the search_list and find any layers which match type. If layer
2127 * type match is found in then add it to ext_list.
2128 */
2129//TODO need to handle implict layer enable env var and disable env var
Jon Ashburn535bd002015-07-02 16:10:32 -06002130static void loader_add_layer_implicit(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002131 const struct loader_instance *inst,
Jon Ashburn535bd002015-07-02 16:10:32 -06002132 const enum layer_type type,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002133 struct loader_layer_list *list,
Jon Ashburn182b8302015-08-11 14:49:54 -06002134 const struct loader_layer_list *search_list)
Jon Ashburn535bd002015-07-02 16:10:32 -06002135{
2136 uint32_t i;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002137 for (i = 0; i < search_list->count; i++) {
2138 const struct loader_layer_properties *prop = &search_list->list[i];
Jon Ashburn535bd002015-07-02 16:10:32 -06002139 if (prop->type & type) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002140 /* Found an layer with the same type, add to layer_list */
Jon Ashburne58f1a32015-08-28 13:38:21 -06002141 loader_add_to_layer_list(inst, list, 1, prop);
Jon Ashburn535bd002015-07-02 16:10:32 -06002142 }
2143 }
2144
2145}
2146
2147/**
2148 * Get the layer name(s) from the env_name environment variable. If layer
Jon Ashburnf2ddb732015-07-07 10:27:45 -06002149 * is found in search_list then add it to layer_list. But only add it to
2150 * layer_list if type matches.
Jon Ashburn535bd002015-07-02 16:10:32 -06002151 */
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002152static void loader_add_layer_env(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002153 const struct loader_instance *inst,
Jon Ashburnf2ddb732015-07-07 10:27:45 -06002154 const enum layer_type type,
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002155 const char *env_name,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002156 struct loader_layer_list *layer_list,
2157 const struct loader_layer_list *search_list)
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002158{
Ian Elliott225188f2015-02-17 10:33:47 -07002159 char *layerEnv;
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002160 char *next, *name;
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002161
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002162 layerEnv = getenv(env_name);
Ian Elliott225188f2015-02-17 10:33:47 -07002163 if (layerEnv == NULL) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002164 return;
Ian Elliott225188f2015-02-17 10:33:47 -07002165 }
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -06002166 name = loader_stack_alloc(strlen(layerEnv) + 1);
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002167 if (name == NULL) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002168 return;
Ian Elliott225188f2015-02-17 10:33:47 -07002169 }
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002170 strcpy(name, layerEnv);
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002171
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002172 while (name && *name ) {
2173 next = loader_get_next_path(name);
Jon Ashburne58f1a32015-08-28 13:38:21 -06002174 loader_find_layer_name_add_list(inst, name, type, search_list, layer_list);
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002175 name = next;
Courtney Goeltzenleuchter0199e952015-02-27 15:19:33 -07002176 }
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002177
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002178 return;
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002179}
2180
Courtney Goeltzenleuchter3d8dc1f2015-06-08 15:09:22 -06002181void loader_deactivate_instance_layers(struct loader_instance *instance)
Jon Ashburn183dfd02014-10-22 18:13:16 -06002182{
Jon Ashburn60378412015-07-02 12:59:25 -06002183 if (!instance->activated_layer_list.count) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002184 return;
2185 }
Jon Ashburn183dfd02014-10-22 18:13:16 -06002186
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002187 /* Create instance chain of enabled layers */
Courtney Goeltzenleuchter3d8dc1f2015-06-08 15:09:22 -06002188 for (uint32_t i = 0; i < instance->activated_layer_list.count; i++) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002189 struct loader_layer_properties *layer_prop = &instance->activated_layer_list.list[i];
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002190
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002191 loader_remove_layer_lib(instance, layer_prop);
Jon Ashburn183dfd02014-10-22 18:13:16 -06002192 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06002193 loader_destroy_layer_list(instance, &instance->activated_layer_list);
Jon Ashburn183dfd02014-10-22 18:13:16 -06002194}
2195
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002196VkResult loader_enable_instance_layers(
Jon Ashburn182b8302015-08-11 14:49:54 -06002197 struct loader_instance *inst,
2198 const VkInstanceCreateInfo *pCreateInfo,
2199 const struct loader_layer_list *instance_layers)
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002200{
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002201 VkResult err;
2202
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -06002203 assert(inst && "Cannot have null instance");
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002204
Jon Ashburne58f1a32015-08-28 13:38:21 -06002205 if (!loader_init_layer_list(inst, &inst->activated_layer_list)) {
2206 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc Instance activated layer list");
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002207 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburn60378412015-07-02 12:59:25 -06002208 }
2209
Jon Ashburn535bd002015-07-02 16:10:32 -06002210 /* Add any implicit layers first */
2211 loader_add_layer_implicit(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002212 inst,
Jon Ashburn535bd002015-07-02 16:10:32 -06002213 VK_LAYER_TYPE_INSTANCE_IMPLICIT,
2214 &inst->activated_layer_list,
Jon Ashburn182b8302015-08-11 14:49:54 -06002215 instance_layers);
Jon Ashburn535bd002015-07-02 16:10:32 -06002216
Jon Ashburn1b111de2015-07-06 15:40:35 -06002217 /* Add any layers specified via environment variable next */
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002218 loader_add_layer_env(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002219 inst,
Jon Ashburnf2ddb732015-07-07 10:27:45 -06002220 VK_LAYER_TYPE_INSTANCE_EXPLICIT,
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002221 "VK_INSTANCE_LAYERS",
2222 &inst->activated_layer_list,
Jon Ashburn182b8302015-08-11 14:49:54 -06002223 instance_layers);
Jon Ashburn60378412015-07-02 12:59:25 -06002224
2225 /* Add layers specified by the application */
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002226 err = loader_add_layer_names_to_list(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002227 inst,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002228 &inst->activated_layer_list,
2229 pCreateInfo->layerCount,
2230 pCreateInfo->ppEnabledLayerNames,
Jon Ashburn182b8302015-08-11 14:49:54 -06002231 instance_layers);
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002232
2233 return err;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002234}
2235
Jon Ashburnfce93d92015-05-12 17:26:48 -06002236uint32_t loader_activate_instance_layers(struct loader_instance *inst)
2237{
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002238 uint32_t layer_idx;
Jon Ashburnd5df54d2015-05-28 19:16:58 -06002239 VkBaseLayerObject *wrappedInstance;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002240
David Pinedo0fab78b2015-06-24 15:29:18 -06002241 if (inst == NULL) {
Jon Ashburnfce93d92015-05-12 17:26:48 -06002242 return 0;
David Pinedo0fab78b2015-06-24 15:29:18 -06002243 }
Jon Ashburnfce93d92015-05-12 17:26:48 -06002244
2245 // NOTE inst is unwrapped at this point in time
Tony Barbourde4124d2015-07-03 10:33:54 -06002246 void* baseObj = (void*) inst;
2247 void* nextObj = (void*) inst;
Jon Ashburnfce93d92015-05-12 17:26:48 -06002248 VkBaseLayerObject *nextInstObj;
2249 PFN_vkGetInstanceProcAddr nextGPA = loader_gpa_instance_internal;
2250
Jon Ashburn60378412015-07-02 12:59:25 -06002251 if (!inst->activated_layer_list.count) {
Courtney Goeltzenleuchter33243142015-08-07 09:53:18 -06002252 loader_init_instance_core_dispatch_table(inst->disp, nextGPA, (VkInstance) nextObj, (VkInstance) baseObj);
Jon Ashburnfce93d92015-05-12 17:26:48 -06002253 return 0;
2254 }
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002255
Courtney Goeltzenleuchter0248b992015-07-06 09:04:55 -06002256 wrappedInstance = loader_stack_alloc(sizeof(VkBaseLayerObject)
Jon Ashburn60378412015-07-02 12:59:25 -06002257 * inst->activated_layer_list.count);
Jon Ashburnd5df54d2015-05-28 19:16:58 -06002258 if (!wrappedInstance) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06002259 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc Instance objects for layer");
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002260 return 0;
2261 }
2262
2263 /* Create instance chain of enabled layers */
Jon Ashburn60378412015-07-02 12:59:25 -06002264 layer_idx = inst->activated_layer_list.count - 1;
Courtney Goeltzenleuchterf4b430e2015-06-07 17:28:17 -06002265 for (int32_t i = inst->activated_layer_list.count - 1; i >= 0; i--) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002266 struct loader_layer_properties *layer_prop = &inst->activated_layer_list.list[i];
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002267 loader_platform_dl_handle lib_handle;
2268
Jon Ashburn60378412015-07-02 12:59:25 -06002269 /*
Courtney Goeltzenleuchterc27292a2015-06-01 14:12:42 -06002270 * Note: An extension's Get*ProcAddr should not return a function pointer for
2271 * any extension entry points until the extension has been enabled.
2272 * To do this requires a different behavior from Get*ProcAddr functions implemented
2273 * in layers.
2274 * The very first call to a layer will be it's Get*ProcAddr function requesting
2275 * the layer's vkGet*ProcAddr. The layer should intialize it's internal dispatch table
2276 * with the wrapped object given (either Instance or Device) and return the layer's
2277 * Get*ProcAddr function. The layer should also use this opportunity to record the
2278 * baseObject so that it can find the correct local dispatch table on future calls.
2279 * Subsequent calls to Get*ProcAddr, CreateInstance, CreateDevice
2280 * will not use a wrapped object and must look up their local dispatch table from
2281 * the given baseObject.
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002282 */
Jon Ashburnd5df54d2015-05-28 19:16:58 -06002283 nextInstObj = (wrappedInstance + layer_idx);
Tony Barbourde4124d2015-07-03 10:33:54 -06002284 nextInstObj->pGPA = (PFN_vkGPA) nextGPA;
Jon Ashburnfce93d92015-05-12 17:26:48 -06002285 nextInstObj->baseObject = baseObj;
2286 nextInstObj->nextObject = nextObj;
Tony Barbourde4124d2015-07-03 10:33:54 -06002287 nextObj = (void*) nextInstObj;
Jon Ashburnfce93d92015-05-12 17:26:48 -06002288
Jon Ashburne58f1a32015-08-28 13:38:21 -06002289 lib_handle = loader_add_layer_lib(inst, "instance", layer_prop);
Jon Ashburn2db08042015-09-09 11:29:24 -06002290 if ((nextGPA = layer_prop->functions.get_instance_proc_addr) == NULL) {
2291 if (layer_prop->functions.str_gipa == NULL || strlen(layer_prop->functions.str_gipa) == 0) {
2292 nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetInstanceProcAddr");
2293 layer_prop->functions.get_instance_proc_addr = nextGPA;
2294 } else
2295 nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gipa);
2296 if (!nextGPA) {
2297 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to find vkGetInstanceProcAddr in layer %s", layer_prop->lib_name);
Courtney Goeltzenleuchteraa685052015-06-01 14:49:17 -06002298
Jon Ashburn2db08042015-09-09 11:29:24 -06002299 /* TODO: Should we return nextObj, nextGPA to previous? or decrement layer_list count*/
2300 continue;
2301 }
Jon Ashburnfce93d92015-05-12 17:26:48 -06002302 }
2303
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002304 loader_log(VK_DBG_REPORT_INFO_BIT, 0,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002305 "Insert instance layer %s (%s)",
2306 layer_prop->info.layerName,
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002307 layer_prop->lib_name);
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002308
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002309 layer_idx--;
Jon Ashburnfce93d92015-05-12 17:26:48 -06002310 }
2311
Jon Ashburn4f2575f2015-05-28 16:25:02 -06002312 loader_init_instance_core_dispatch_table(inst->disp, nextGPA, (VkInstance) nextObj, (VkInstance) baseObj);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002313
Jon Ashburn60378412015-07-02 12:59:25 -06002314 return inst->activated_layer_list.count;
Jon Ashburnfce93d92015-05-12 17:26:48 -06002315}
2316
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002317void loader_activate_instance_layer_extensions(struct loader_instance *inst)
2318{
2319
2320 loader_init_instance_extension_dispatch_table(inst->disp,
2321 inst->disp->GetInstanceProcAddr,
Jon Ashburnd5df54d2015-05-28 19:16:58 -06002322 (VkInstance) inst);
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002323}
2324
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002325static VkResult loader_enable_device_layers(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002326 const struct loader_instance *inst,
Jon Ashburn182b8302015-08-11 14:49:54 -06002327 struct loader_icd *icd,
2328 struct loader_device *dev,
2329 const VkDeviceCreateInfo *pCreateInfo,
2330 const struct loader_layer_list *device_layers)
2331
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002332{
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002333 VkResult err;
2334
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -06002335 assert(dev && "Cannot have null device");
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002336
Jon Ashburn60378412015-07-02 12:59:25 -06002337 if (dev->activated_layer_list.list == NULL || dev->activated_layer_list.capacity == 0) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06002338 loader_init_layer_list(inst, &dev->activated_layer_list);
Jon Ashburn60378412015-07-02 12:59:25 -06002339 }
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002340
Jon Ashburn60378412015-07-02 12:59:25 -06002341 if (dev->activated_layer_list.list == NULL) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06002342 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc device activated layer list");
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002343 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburn60378412015-07-02 12:59:25 -06002344 }
2345
Jon Ashburn535bd002015-07-02 16:10:32 -06002346 /* Add any implicit layers first */
2347 loader_add_layer_implicit(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002348 inst,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002349 VK_LAYER_TYPE_DEVICE_IMPLICIT,
2350 &dev->activated_layer_list,
Jon Ashburn182b8302015-08-11 14:49:54 -06002351 device_layers);
Jon Ashburn535bd002015-07-02 16:10:32 -06002352
2353 /* Add any layers specified via environment variable next */
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002354 loader_add_layer_env(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002355 inst,
Jon Ashburnf2ddb732015-07-07 10:27:45 -06002356 VK_LAYER_TYPE_DEVICE_EXPLICIT,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002357 "VK_DEVICE_LAYERS",
2358 &dev->activated_layer_list,
Jon Ashburn182b8302015-08-11 14:49:54 -06002359 device_layers);
Jon Ashburn60378412015-07-02 12:59:25 -06002360
2361 /* Add layers specified by the application */
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002362 err = loader_add_layer_names_to_list(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002363 inst,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002364 &dev->activated_layer_list,
2365 pCreateInfo->layerCount,
2366 pCreateInfo->ppEnabledLayerNames,
Jon Ashburn182b8302015-08-11 14:49:54 -06002367 device_layers);
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002368
2369 return err;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002370}
2371
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002372/*
Jon Ashburnc1d1eb72015-08-14 11:57:54 -06002373 * This function terminates the device chain for CreateDevice.
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002374 * CreateDevice is a special case and so the loader call's
2375 * the ICD's CreateDevice before creating the chain. Since
2376 * we can't call CreateDevice twice we must terminate the
2377 * device chain with something else.
2378 */
Dan Ginsburgf99e4102015-07-23 13:15:00 -04002379static VkResult VKAPI scratch_vkCreateDevice(
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002380 VkPhysicalDevice gpu,
2381 const VkDeviceCreateInfo *pCreateInfo,
2382 VkDevice *pDevice)
2383{
2384 return VK_SUCCESS;
2385}
2386
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -06002387static PFN_vkVoidFunction VKAPI loader_GetDeviceChainProcAddr(VkDevice device, const char * name)
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002388{
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002389 if (!strcmp(name, "vkGetDeviceProcAddr"))
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -06002390 return (PFN_vkVoidFunction) loader_GetDeviceChainProcAddr;
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002391 if (!strcmp(name, "vkCreateDevice"))
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -06002392 return (PFN_vkVoidFunction) scratch_vkCreateDevice;
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002393
Courtney Goeltzenleuchtere76db422015-06-29 16:09:23 -06002394 struct loader_device *found_dev;
2395 struct loader_icd *icd = loader_get_icd_and_device(device, &found_dev);
2396 return icd->GetDeviceProcAddr(device, name);
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002397}
2398
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06002399static uint32_t loader_activate_device_layers(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002400 const struct loader_instance *inst,
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002401 struct loader_device *dev,
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -06002402 VkDevice device)
Jon Ashburn183dfd02014-10-22 18:13:16 -06002403{
David Pinedo0fab78b2015-06-24 15:29:18 -06002404 if (!dev) {
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06002405 return 0;
David Pinedo0fab78b2015-06-24 15:29:18 -06002406 }
Jon Ashburn612539f2015-06-10 10:13:10 -06002407
Jon Ashburn183dfd02014-10-22 18:13:16 -06002408 /* activate any layer libraries */
Tony Barbourde4124d2015-07-03 10:33:54 -06002409 void* nextObj = (void*) device;
2410 void* baseObj = nextObj;
Jon Ashburn612539f2015-06-10 10:13:10 -06002411 VkBaseLayerObject *nextGpuObj;
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002412 PFN_vkGetDeviceProcAddr nextGPA = loader_GetDeviceChainProcAddr;
Jon Ashburn612539f2015-06-10 10:13:10 -06002413 VkBaseLayerObject *wrappedGpus;
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002414
Courtney Goeltzenleuchter33243142015-08-07 09:53:18 -06002415 if (!dev->activated_layer_list.count) {
2416 loader_init_device_dispatch_table(&dev->loader_dispatch, nextGPA,
2417 (VkDevice) nextObj, (VkDevice) baseObj);
Jon Ashburn612539f2015-06-10 10:13:10 -06002418 return 0;
Courtney Goeltzenleuchter33243142015-08-07 09:53:18 -06002419 }
Jon Ashburn612539f2015-06-10 10:13:10 -06002420
Jon Ashburne58f1a32015-08-28 13:38:21 -06002421 wrappedGpus = loader_heap_alloc(inst,
2422 sizeof (VkBaseLayerObject) * dev->activated_layer_list.count,
2423 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburn612539f2015-06-10 10:13:10 -06002424 if (!wrappedGpus) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06002425 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc Gpu objects for layer");
Jon Ashburn612539f2015-06-10 10:13:10 -06002426 return 0;
2427 }
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002428
Jon Ashburn612539f2015-06-10 10:13:10 -06002429 for (int32_t i = dev->activated_layer_list.count - 1; i >= 0; i--) {
2430
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002431 struct loader_layer_properties *layer_prop = &dev->activated_layer_list.list[i];
Jon Ashburn612539f2015-06-10 10:13:10 -06002432 loader_platform_dl_handle lib_handle;
2433
Jon Ashburn612539f2015-06-10 10:13:10 -06002434 nextGpuObj = (wrappedGpus + i);
Tony Barbourde4124d2015-07-03 10:33:54 -06002435 nextGpuObj->pGPA = (PFN_vkGPA)nextGPA;
Jon Ashburn612539f2015-06-10 10:13:10 -06002436 nextGpuObj->baseObject = baseObj;
2437 nextGpuObj->nextObject = nextObj;
Tony Barbourde4124d2015-07-03 10:33:54 -06002438 nextObj = (void*) nextGpuObj;
Jon Ashburn612539f2015-06-10 10:13:10 -06002439
Jon Ashburne58f1a32015-08-28 13:38:21 -06002440 lib_handle = loader_add_layer_lib(inst, "device", layer_prop);
Jon Ashburn2db08042015-09-09 11:29:24 -06002441 if ((nextGPA = layer_prop->functions.get_device_proc_addr) == NULL) {
2442 if (layer_prop->functions.str_gdpa == NULL || strlen(layer_prop->functions.str_gdpa) == 0) {
2443 nextGPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetDeviceProcAddr");
2444 layer_prop->functions.get_device_proc_addr = nextGPA;
2445 } else
2446 nextGPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gdpa);
2447 if (!nextGPA) {
2448 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to find vkGetDeviceProcAddr in layer %s", layer_prop->lib_name);
2449 continue;
2450 }
Jon Ashburn612539f2015-06-10 10:13:10 -06002451 }
2452
2453 loader_log(VK_DBG_REPORT_INFO_BIT, 0,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002454 "Insert device layer library %s (%s)",
2455 layer_prop->info.layerName,
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002456 layer_prop->lib_name);
Jon Ashburn612539f2015-06-10 10:13:10 -06002457
2458 }
2459
2460 loader_init_device_dispatch_table(&dev->loader_dispatch, nextGPA,
Tony Barbourde4124d2015-07-03 10:33:54 -06002461 (VkDevice) nextObj, (VkDevice) baseObj);
Jon Ashburne58f1a32015-08-28 13:38:21 -06002462 loader_heap_free(inst, wrappedGpus);
Jon Ashburn612539f2015-06-10 10:13:10 -06002463
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06002464 return dev->activated_layer_list.count;
Jon Ashburn183dfd02014-10-22 18:13:16 -06002465}
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002466
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002467VkResult loader_validate_layers(
2468 const uint32_t layer_count,
2469 const char * const *ppEnabledLayerNames,
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002470 const struct loader_layer_list *list)
Courtney Goeltzenleuchter5d9f29b2015-07-06 17:45:08 -06002471{
2472 struct loader_layer_properties *prop;
2473
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002474 for (uint32_t i = 0; i < layer_count; i++) {
Jon Ashburn8e4fab42015-08-03 17:19:30 -06002475 prop = loader_get_layer_property(ppEnabledLayerNames[i],
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002476 list);
Courtney Goeltzenleuchter5d9f29b2015-07-06 17:45:08 -06002477 if (!prop) {
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -06002478 return VK_ERROR_LAYER_NOT_PRESENT;
Courtney Goeltzenleuchter5d9f29b2015-07-06 17:45:08 -06002479 }
2480 }
2481
2482 return VK_SUCCESS;
2483}
2484
2485VkResult loader_validate_instance_extensions(
Jon Ashburnc1d1eb72015-08-14 11:57:54 -06002486 const struct loader_extension_list *icd_exts,
Jon Ashburn182b8302015-08-11 14:49:54 -06002487 const struct loader_layer_list *instance_layer,
2488 const VkInstanceCreateInfo *pCreateInfo)
Courtney Goeltzenleuchter5d9f29b2015-07-06 17:45:08 -06002489{
Jon Ashburnc4748dc2015-08-04 11:14:18 -06002490 VkExtensionProperties *extension_prop;
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002491 struct loader_layer_properties *layer_prop;
2492
2493 for (uint32_t i = 0; i < pCreateInfo->extensionCount; i++) {
2494 extension_prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
Jon Ashburnc1d1eb72015-08-14 11:57:54 -06002495 icd_exts);
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002496
2497 if (extension_prop) {
2498 continue;
2499 }
2500
2501 extension_prop = NULL;
2502
2503 /* Not in global list, search layer extension lists */
2504 for (uint32_t j = 0; j < pCreateInfo->layerCount; j++) {
Jon Ashburn8e4fab42015-08-03 17:19:30 -06002505 layer_prop = loader_get_layer_property(pCreateInfo->ppEnabledLayerNames[i],
Jon Ashburn182b8302015-08-11 14:49:54 -06002506 instance_layer);
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002507 if (!layer_prop) {
Courtney Goeltzenleuchter91371ff2015-07-06 20:46:50 -06002508 /* Should NOT get here, loader_validate_layers
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002509 * should have already filtered this case out.
2510 */
2511 continue;
2512 }
2513
2514 extension_prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
2515 &layer_prop->instance_extension_list);
2516 if (extension_prop) {
2517 /* Found the extension in one of the layers enabled by the app. */
2518 break;
2519 }
2520 }
2521
2522 if (!extension_prop) {
2523 /* Didn't find extension name in any of the global layers, error out */
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -06002524 return VK_ERROR_EXTENSION_NOT_PRESENT;
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002525 }
2526 }
2527 return VK_SUCCESS;
2528}
2529
2530VkResult loader_validate_device_extensions(
Jon Ashburn182b8302015-08-11 14:49:54 -06002531 struct loader_icd *icd,
2532 uint32_t gpu_index,
2533 const struct loader_layer_list *device_layer,
2534 const VkDeviceCreateInfo *pCreateInfo)
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002535{
Jon Ashburnc4748dc2015-08-04 11:14:18 -06002536 VkExtensionProperties *extension_prop;
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002537 struct loader_layer_properties *layer_prop;
2538
2539 for (uint32_t i = 0; i < pCreateInfo->extensionCount; i++) {
2540 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i];
2541 extension_prop = get_extension_property(extension_name,
Courtney Goeltzenleuchterd2775f72015-07-08 21:13:16 -06002542 &icd->device_extension_cache[gpu_index]);
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002543
2544 if (extension_prop) {
2545 continue;
2546 }
2547
2548 /* Not in global list, search layer extension lists */
2549 for (uint32_t j = 0; j < pCreateInfo->layerCount; j++) {
2550 const char *layer_name = pCreateInfo->ppEnabledLayerNames[j];
Jon Ashburn8e4fab42015-08-03 17:19:30 -06002551 layer_prop = loader_get_layer_property(layer_name,
Jon Ashburn182b8302015-08-11 14:49:54 -06002552 device_layer);
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002553
2554 if (!layer_prop) {
2555 /* Should NOT get here, loader_validate_instance_layers
2556 * should have already filtered this case out.
2557 */
2558 continue;
2559 }
2560
2561 extension_prop = get_extension_property(extension_name,
2562 &layer_prop->device_extension_list);
2563 if (extension_prop) {
2564 /* Found the extension in one of the layers enabled by the app. */
2565 break;
2566 }
2567 }
2568
2569 if (!extension_prop) {
2570 /* Didn't find extension name in any of the device layers, error out */
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -06002571 return VK_ERROR_EXTENSION_NOT_PRESENT;
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002572 }
2573 }
Courtney Goeltzenleuchter5d9f29b2015-07-06 17:45:08 -06002574 return VK_SUCCESS;
2575}
2576
Dan Ginsburgf99e4102015-07-23 13:15:00 -04002577VkResult VKAPI loader_CreateInstance(
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002578 const VkInstanceCreateInfo* pCreateInfo,
2579 VkInstance* pInstance)
Jon Ashburn349508d2015-01-26 14:51:40 -07002580{
Jon Ashburna179dcf2015-05-21 17:42:17 -06002581 struct loader_instance *ptr_instance = *(struct loader_instance **) pInstance;
Jon Ashburn3336df82015-01-29 15:45:51 -07002582 struct loader_icd *icd;
Jon Ashburnc4748dc2015-08-04 11:14:18 -06002583 VkExtensionProperties *prop;
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06002584 char **filtered_extension_names = NULL;
2585 VkInstanceCreateInfo icd_create_info;
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002586 VkResult res = VK_SUCCESS;
Jon Ashburnce7e3d92015-07-16 10:17:29 -06002587 bool success;
Jon Ashburn349508d2015-01-26 14:51:40 -07002588
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06002589 icd_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
2590 icd_create_info.layerCount = 0;
2591 icd_create_info.ppEnabledLayerNames = NULL;
2592 icd_create_info.pAllocCb = pCreateInfo->pAllocCb;
2593 icd_create_info.pAppInfo = pCreateInfo->pAppInfo;
2594 icd_create_info.pNext = pCreateInfo->pNext;
2595
2596 /*
2597 * NOTE: Need to filter the extensions to only those
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002598 * supported by the ICD.
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06002599 * No ICD will advertise support for layers. An ICD
2600 * library could support a layer, but it would be
2601 * independent of the actual ICD, just in the same library.
2602 */
2603 filtered_extension_names = loader_stack_alloc(pCreateInfo->extensionCount * sizeof(char *));
2604 if (!filtered_extension_names) {
2605 return VK_ERROR_OUT_OF_HOST_MEMORY;
2606 }
2607 icd_create_info.ppEnabledExtensionNames = (const char * const *) filtered_extension_names;
2608
Jon Ashburn754f1992015-08-18 18:04:47 -06002609 for (uint32_t i = 0; i < ptr_instance->icd_libs.count; i++) {
2610 icd = loader_icd_add(ptr_instance, &ptr_instance->icd_libs.list[i]);
Jon Ashburn3336df82015-01-29 15:45:51 -07002611 if (icd) {
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06002612 icd_create_info.extensionCount = 0;
2613 for (uint32_t i = 0; i < pCreateInfo->extensionCount; i++) {
2614 prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
Jon Ashburn85f98072015-08-14 14:49:22 -06002615 &ptr_instance->ext_list);
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06002616 if (prop) {
2617 filtered_extension_names[icd_create_info.extensionCount] = (char *) pCreateInfo->ppEnabledExtensionNames[i];
2618 icd_create_info.extensionCount++;
2619 }
2620 }
2621
Jon Ashburn754f1992015-08-18 18:04:47 -06002622 res = ptr_instance->icd_libs.list[i].CreateInstance(&icd_create_info,
Jon Ashburn0dd356d2015-05-14 12:43:38 -06002623 &(icd->instance));
Jon Ashburnce7e3d92015-07-16 10:17:29 -06002624 success = loader_icd_init_entrys(
2625 icd,
2626 icd->instance,
Jon Ashburn754f1992015-08-18 18:04:47 -06002627 ptr_instance->icd_libs.list[i].GetInstanceProcAddr);
Jon Ashburnce7e3d92015-07-16 10:17:29 -06002628
2629 if (res != VK_SUCCESS || !success)
Jon Ashburn3336df82015-01-29 15:45:51 -07002630 {
2631 ptr_instance->icds = ptr_instance->icds->next;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002632 loader_icd_destroy(ptr_instance, icd);
Jon Ashburn0dd356d2015-05-14 12:43:38 -06002633 icd->instance = VK_NULL_HANDLE;
Jon Ashburnce7e3d92015-07-16 10:17:29 -06002634 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
2635 "ICD ignored: failed to CreateInstance and find entrypoints with ICD");
Jon Ashburn3336df82015-01-29 15:45:51 -07002636 }
2637 }
Jon Ashburn3336df82015-01-29 15:45:51 -07002638 }
Jon Ashburn349508d2015-01-26 14:51:40 -07002639
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002640 /*
2641 * If no ICDs were added to instance list and res is unchanged
2642 * from it's initial value, the loader was unable to find
2643 * a suitable ICD.
2644 */
Ian Elliott617fdec2015-02-05 15:19:15 -07002645 if (ptr_instance->icds == NULL) {
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002646 if (res == VK_SUCCESS) {
2647 return VK_ERROR_INCOMPATIBLE_DRIVER;
2648 } else {
2649 return res;
2650 }
Ian Elliott617fdec2015-02-05 15:19:15 -07002651 }
Jon Ashburn3336df82015-01-29 15:45:51 -07002652
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002653 return VK_SUCCESS;
Jon Ashburn349508d2015-01-26 14:51:40 -07002654}
2655
Mark Lobodzinski67b42b72015-09-07 13:59:43 -06002656void VKAPI loader_DestroyInstance(
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -06002657 VkInstance instance)
Jon Ashburn349508d2015-01-26 14:51:40 -07002658{
Courtney Goeltzenleuchter8afefb52015-06-08 15:04:02 -06002659 struct loader_instance *ptr_instance = loader_instance(instance);
Jon Ashburn0dd356d2015-05-14 12:43:38 -06002660 struct loader_icd *icds = ptr_instance->icds;
Jon Ashburn16a16d62015-06-16 14:43:19 -06002661 struct loader_icd *next_icd;
Jon Ashburn349508d2015-01-26 14:51:40 -07002662
2663 // Remove this instance from the list of instances:
2664 struct loader_instance *prev = NULL;
2665 struct loader_instance *next = loader.instances;
2666 while (next != NULL) {
2667 if (next == ptr_instance) {
2668 // Remove this instance from the list:
2669 if (prev)
2670 prev->next = next->next;
Jon Ashburn2cabd252015-02-03 09:26:59 -07002671 else
2672 loader.instances = next->next;
Jon Ashburn349508d2015-01-26 14:51:40 -07002673 break;
2674 }
2675 prev = next;
2676 next = next->next;
2677 }
Courtney Goeltzenleuchtera54b76a2015-09-04 13:39:59 -06002678 /* TODOVV: Move this test to validation layer */
2679// if (next == NULL) {
2680// // This must be an invalid instance handle or empty list
2681// return VK_ERROR_INVALID_HANDLE;
2682// }
Jon Ashburn349508d2015-01-26 14:51:40 -07002683
Jon Ashburn0dd356d2015-05-14 12:43:38 -06002684 while (icds) {
2685 if (icds->instance) {
Mark Lobodzinski67b42b72015-09-07 13:59:43 -06002686 icds->DestroyInstance(icds->instance);
2687 /* TODOVV: Move this test to validation layer */
2688 //if (res != VK_SUCCESS)
2689 // loader_log(VK_DBG_REPORT_WARN_BIT, 0,
2690 // "ICD ignored: failed to DestroyInstance on device");
Tony Barbour22a30862015-04-22 09:02:32 -06002691 }
Jon Ashburn16a16d62015-06-16 14:43:19 -06002692 next_icd = icds->next;
Jon Ashburn0dd356d2015-05-14 12:43:38 -06002693 icds->instance = VK_NULL_HANDLE;
Jon Ashburn16a16d62015-06-16 14:43:19 -06002694 loader_icd_destroy(ptr_instance, icds);
2695
2696 icds = next_icd;
Jon Ashburn3336df82015-01-29 15:45:51 -07002697 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06002698 loader_delete_layer_properties(ptr_instance, &ptr_instance->device_layer_list);
2699 loader_delete_layer_properties(ptr_instance, &ptr_instance->instance_layer_list);
2700 loader_scanned_icd_clear(ptr_instance, &ptr_instance->icd_libs);
2701 loader_destroy_ext_list(ptr_instance, &ptr_instance->ext_list);
Jon Ashburn349508d2015-01-26 14:51:40 -07002702}
2703
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002704VkResult loader_init_physical_device_info(
2705 struct loader_instance *ptr_instance)
2706{
2707 struct loader_icd *icd;
2708 uint32_t n, count = 0;
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -06002709 VkResult res;
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002710
2711 icd = ptr_instance->icds;
2712 while (icd) {
2713 res = icd->EnumeratePhysicalDevices(icd->instance, &n, NULL);
2714 if (res != VK_SUCCESS)
2715 return res;
2716 icd->gpu_count = n;
2717 count += n;
2718 icd = icd->next;
2719 }
2720
2721 ptr_instance->total_gpu_count = count;
2722
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002723 icd = ptr_instance->icds;
2724 while (icd) {
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002725
2726 n = icd->gpu_count;
Jon Ashburne58f1a32015-08-28 13:38:21 -06002727 icd->gpus = (VkPhysicalDevice *) loader_heap_alloc(
2728 ptr_instance,
2729 n * sizeof(VkPhysicalDevice),
2730 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburnd5df54d2015-05-28 19:16:58 -06002731 if (!icd->gpus) {
2732 /* TODO: Add cleanup code here */
2733 return VK_ERROR_OUT_OF_HOST_MEMORY;
2734 }
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002735 res = icd->EnumeratePhysicalDevices(
2736 icd->instance,
2737 &n,
Jon Ashburnd5df54d2015-05-28 19:16:58 -06002738 icd->gpus);
2739 if ((res == VK_SUCCESS) && (n == icd->gpu_count)) {
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002740
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002741 for (unsigned int i = 0; i < n; i++) {
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002742
Jon Ashburnd5df54d2015-05-28 19:16:58 -06002743 loader_init_dispatch(icd->gpus[i], ptr_instance->disp);
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002744
Jon Ashburne58f1a32015-08-28 13:38:21 -06002745 if (!loader_init_ext_list(ptr_instance, &icd->device_extension_cache[i])) {
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002746 /* TODO: Add cleanup code here */
2747 res = VK_ERROR_OUT_OF_HOST_MEMORY;
2748 }
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002749 if (res == VK_SUCCESS) {
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002750
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002751 loader_add_physical_device_extensions(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002752 ptr_instance,
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -06002753 icd->EnumerateDeviceExtensionProperties,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002754 icd->gpus[0],
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002755 icd->this_icd_lib->lib_name,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002756 &icd->device_extension_cache[i]);
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002757
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002758 }
2759
2760 if (res != VK_SUCCESS) {
2761 /* clean up any extension lists previously created before this request failed */
2762 for (uint32_t j = 0; j < i; j++) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06002763 loader_destroy_ext_list(
2764 ptr_instance,
2765 &icd->device_extension_cache[i]);
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002766 }
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002767
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002768 return res;
2769 }
2770 }
2771
2772 count += n;
2773 }
2774
2775 icd = icd->next;
2776 }
2777
2778 return VK_SUCCESS;
2779}
2780
Dan Ginsburgf99e4102015-07-23 13:15:00 -04002781VkResult VKAPI loader_EnumeratePhysicalDevices(
Courtney Goeltzenleuchter9f530cb2015-04-20 12:48:54 -06002782 VkInstance instance,
2783 uint32_t* pPhysicalDeviceCount,
2784 VkPhysicalDevice* pPhysicalDevices)
Jon Ashburn349508d2015-01-26 14:51:40 -07002785{
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002786 uint32_t index = 0;
Jon Ashburnb048a9b2015-01-28 19:57:09 -07002787 struct loader_instance *ptr_instance = (struct loader_instance *) instance;
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002788 struct loader_icd *icd = ptr_instance->icds;
Jon Ashburnb048a9b2015-01-28 19:57:09 -07002789
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002790 if (ptr_instance->total_gpu_count == 0) {
2791 loader_init_physical_device_info(ptr_instance);
Jon Ashburnb048a9b2015-01-28 19:57:09 -07002792 }
2793
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002794 *pPhysicalDeviceCount = ptr_instance->total_gpu_count;
2795 if (!pPhysicalDevices) {
2796 return VK_SUCCESS;
2797 }
Jon Ashburnb048a9b2015-01-28 19:57:09 -07002798
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002799 while (icd) {
2800 assert((index + icd->gpu_count) <= *pPhysicalDeviceCount);
Jon Ashburnd5df54d2015-05-28 19:16:58 -06002801 memcpy(&pPhysicalDevices[index], icd->gpus, icd->gpu_count * sizeof(VkPhysicalDevice));
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002802 index += icd->gpu_count;
2803 icd = icd->next;
2804 }
2805
2806 return VK_SUCCESS;
Jon Ashburn349508d2015-01-26 14:51:40 -07002807}
2808
Dan Ginsburgf99e4102015-07-23 13:15:00 -04002809VkResult VKAPI loader_GetPhysicalDeviceProperties(
Jon Ashburn0dd356d2015-05-14 12:43:38 -06002810 VkPhysicalDevice gpu,
Tony Barbour426b9052015-06-24 16:06:58 -06002811 VkPhysicalDeviceProperties* pProperties)
Jon Ashburn0dd356d2015-05-14 12:43:38 -06002812{
2813 uint32_t gpu_index;
Jon Ashburnd5df54d2015-05-28 19:16:58 -06002814 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
Jon Ashburn0dd356d2015-05-14 12:43:38 -06002815 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2816
Tony Barbour426b9052015-06-24 16:06:58 -06002817 if (icd->GetPhysicalDeviceProperties)
2818 res = icd->GetPhysicalDeviceProperties(gpu, pProperties);
2819
2820 return res;
2821}
2822
Cody Northropef72e2a2015-08-03 17:04:53 -06002823VkResult VKAPI loader_GetPhysicalDeviceQueueFamilyProperties (
Tony Barbour426b9052015-06-24 16:06:58 -06002824 VkPhysicalDevice gpu,
Cody Northropef72e2a2015-08-03 17:04:53 -06002825 uint32_t* pCount,
2826 VkQueueFamilyProperties* pProperties)
Tony Barbour426b9052015-06-24 16:06:58 -06002827{
2828 uint32_t gpu_index;
2829 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
2830 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2831
Cody Northropef72e2a2015-08-03 17:04:53 -06002832 if (icd->GetPhysicalDeviceQueueFamilyProperties)
2833 res = icd->GetPhysicalDeviceQueueFamilyProperties(gpu, pCount, pProperties);
Tony Barbour426b9052015-06-24 16:06:58 -06002834
2835 return res;
2836}
2837
Dan Ginsburgf99e4102015-07-23 13:15:00 -04002838VkResult VKAPI loader_GetPhysicalDeviceMemoryProperties (
Tony Barbour426b9052015-06-24 16:06:58 -06002839 VkPhysicalDevice gpu,
2840 VkPhysicalDeviceMemoryProperties* pProperties)
2841{
2842 uint32_t gpu_index;
2843 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
2844 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2845
2846 if (icd->GetPhysicalDeviceMemoryProperties)
2847 res = icd->GetPhysicalDeviceMemoryProperties(gpu, pProperties);
Jon Ashburn0dd356d2015-05-14 12:43:38 -06002848
2849 return res;
2850}
2851
Dan Ginsburgf99e4102015-07-23 13:15:00 -04002852VkResult VKAPI loader_GetPhysicalDeviceFeatures(
Chris Forbesd7576302015-06-21 22:55:02 +12002853 VkPhysicalDevice physicalDevice,
2854 VkPhysicalDeviceFeatures* pFeatures)
2855{
2856 uint32_t gpu_index;
2857 struct loader_icd *icd = loader_get_icd(physicalDevice, &gpu_index);
2858 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2859
2860 if (icd->GetPhysicalDeviceFeatures)
2861 res = icd->GetPhysicalDeviceFeatures(physicalDevice, pFeatures);
2862
2863 return res;
2864}
2865
Dan Ginsburgf99e4102015-07-23 13:15:00 -04002866VkResult VKAPI loader_GetPhysicalDeviceFormatProperties(
Chris Forbesd7576302015-06-21 22:55:02 +12002867 VkPhysicalDevice physicalDevice,
2868 VkFormat format,
2869 VkFormatProperties* pFormatInfo)
2870{
2871 uint32_t gpu_index;
2872 struct loader_icd *icd = loader_get_icd(physicalDevice, &gpu_index);
2873 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2874
Courtney Goeltzenleuchter4da96aa2015-07-12 12:52:09 -06002875 if (icd->GetPhysicalDeviceFormatProperties)
2876 res = icd->GetPhysicalDeviceFormatProperties(physicalDevice, format, pFormatInfo);
Chris Forbesd7576302015-06-21 22:55:02 +12002877
2878 return res;
2879}
2880
Jon Ashburn4e189562015-07-23 18:49:07 -06002881VkResult VKAPI loader_GetPhysicalDeviceImageFormatProperties(
2882 VkPhysicalDevice physicalDevice,
2883 VkFormat format,
2884 VkImageType type,
2885 VkImageTiling tiling,
2886 VkImageUsageFlags usage,
Courtney Goeltzenleuchter83c95f82015-09-10 13:44:12 -06002887 VkImageCreateFlags flags,
Jon Ashburn4e189562015-07-23 18:49:07 -06002888 VkImageFormatProperties* pImageFormatProperties)
2889{
2890 uint32_t gpu_index;
2891 struct loader_icd *icd = loader_get_icd(physicalDevice, &gpu_index);
2892 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2893
2894 if (icd->GetPhysicalDeviceImageFormatProperties)
2895 res = icd->GetPhysicalDeviceImageFormatProperties(physicalDevice, format,
Courtney Goeltzenleuchter83c95f82015-09-10 13:44:12 -06002896 type, tiling, usage, flags, pImageFormatProperties);
Jon Ashburn4e189562015-07-23 18:49:07 -06002897
2898 return res;
2899}
2900
Dan Ginsburgf99e4102015-07-23 13:15:00 -04002901VkResult VKAPI loader_GetPhysicalDeviceSparseImageFormatProperties(
Mark Lobodzinski83d4e6a2015-07-03 15:58:09 -06002902 VkPhysicalDevice physicalDevice,
2903 VkFormat format,
2904 VkImageType type,
2905 uint32_t samples,
2906 VkImageUsageFlags usage,
2907 VkImageTiling tiling,
2908 uint32_t* pNumProperties,
2909 VkSparseImageFormatProperties* pProperties)
2910{
2911 uint32_t gpu_index;
2912 struct loader_icd *icd = loader_get_icd(physicalDevice, &gpu_index);
2913 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2914
2915 if (icd->GetPhysicalDeviceSparseImageFormatProperties)
2916 res = icd->GetPhysicalDeviceSparseImageFormatProperties(physicalDevice, format, type, samples, usage, tiling, pNumProperties, pProperties);
2917
2918 return res;
2919}
2920
Dan Ginsburgf99e4102015-07-23 13:15:00 -04002921VkResult VKAPI loader_CreateDevice(
Jon Ashburn2666e2f2015-05-15 15:09:35 -06002922 VkPhysicalDevice gpu,
2923 const VkDeviceCreateInfo* pCreateInfo,
2924 VkDevice* pDevice)
2925{
2926 uint32_t gpu_index;
Jon Ashburnd5df54d2015-05-28 19:16:58 -06002927 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06002928 struct loader_device *dev;
Jon Ashburne58f1a32015-08-28 13:38:21 -06002929 const struct loader_instance *inst = icd->this_instance;
Courtney Goeltzenleuchter91371ff2015-07-06 20:46:50 -06002930 VkDeviceCreateInfo device_create_info;
2931 char **filtered_extension_names = NULL;
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002932 VkResult res;
Jon Ashburn2666e2f2015-05-15 15:09:35 -06002933
Mark Lobodzinski5ea338c2015-09-17 15:17:34 -06002934 assert(pCreateInfo->queueRecordCount >= 1);
2935
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002936 if (!icd->CreateDevice) {
2937 return VK_ERROR_INITIALIZATION_FAILED;
Jon Ashburn2666e2f2015-05-15 15:09:35 -06002938 }
2939
Jon Ashburn182b8302015-08-11 14:49:54 -06002940 /* validate any app enabled layers are available */
2941 if (pCreateInfo->layerCount > 0) {
2942 res = loader_validate_layers(pCreateInfo->layerCount,
2943 pCreateInfo->ppEnabledLayerNames,
Jon Ashburne58f1a32015-08-28 13:38:21 -06002944 &inst->device_layer_list);
Jon Ashburn182b8302015-08-11 14:49:54 -06002945 if (res != VK_SUCCESS) {
2946 return res;
2947 }
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002948 }
2949
Jon Ashburne58f1a32015-08-28 13:38:21 -06002950 res = loader_validate_device_extensions(icd, gpu_index, &inst->device_layer_list, pCreateInfo);
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002951 if (res != VK_SUCCESS) {
2952 return res;
2953 }
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002954
Courtney Goeltzenleuchter91371ff2015-07-06 20:46:50 -06002955 /*
2956 * NOTE: Need to filter the extensions to only those
2957 * supported by the ICD.
2958 * No ICD will advertise support for layers. An ICD
2959 * library could support a layer, but it would be
2960 * independent of the actual ICD, just in the same library.
2961 */
2962 filtered_extension_names = loader_stack_alloc(pCreateInfo->extensionCount * sizeof(char *));
2963 if (!filtered_extension_names) {
2964 return VK_ERROR_OUT_OF_HOST_MEMORY;
2965 }
2966
2967 /* Copy user's data */
2968 memcpy(&device_create_info, pCreateInfo, sizeof(VkDeviceCreateInfo));
2969
2970 /* ICD's do not use layers */
2971 device_create_info.layerCount = 0;
2972 device_create_info.ppEnabledLayerNames = NULL;
2973
2974 device_create_info.extensionCount = 0;
2975 device_create_info.ppEnabledExtensionNames = (const char * const *) filtered_extension_names;
2976
2977 for (uint32_t i = 0; i < pCreateInfo->extensionCount; i++) {
2978 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i];
Jon Ashburnc4748dc2015-08-04 11:14:18 -06002979 VkExtensionProperties *prop = get_extension_property(extension_name,
Courtney Goeltzenleuchter91371ff2015-07-06 20:46:50 -06002980 &icd->device_extension_cache[gpu_index]);
2981 if (prop) {
2982 filtered_extension_names[device_create_info.extensionCount] = (char *) extension_name;
2983 device_create_info.extensionCount++;
2984 }
2985 }
2986
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002987 res = icd->CreateDevice(gpu, pCreateInfo, pDevice);
2988 if (res != VK_SUCCESS) {
2989 return res;
2990 }
2991
Jon Ashburne58f1a32015-08-28 13:38:21 -06002992 dev = loader_add_logical_device(inst, *pDevice, &icd->logical_device_list);
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002993 if (dev == NULL) {
2994 return VK_ERROR_OUT_OF_HOST_MEMORY;
2995 }
2996 PFN_vkGetDeviceProcAddr get_proc_addr = icd->GetDeviceProcAddr;
2997 loader_init_device_dispatch_table(&dev->loader_dispatch, get_proc_addr,
Courtney Goeltzenleuchter08f54e72015-07-16 10:36:57 -06002998 *pDevice, *pDevice);
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002999
3000 dev->loader_dispatch.CreateDevice = scratch_vkCreateDevice;
3001 loader_init_dispatch(*pDevice, &dev->loader_dispatch);
3002
Jon Ashburn182b8302015-08-11 14:49:54 -06003003 /* activate any layers on device chain which terminates with device*/
Jon Ashburne58f1a32015-08-28 13:38:21 -06003004 res = loader_enable_device_layers(inst, icd, dev, pCreateInfo, &inst->device_layer_list);
Jon Ashburn182b8302015-08-11 14:49:54 -06003005 if (res != VK_SUCCESS) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06003006 loader_destroy_logical_device(inst, dev);
Jon Ashburn182b8302015-08-11 14:49:54 -06003007 return res;
3008 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06003009 loader_activate_device_layers(inst, dev, *pDevice);
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06003010
3011 res = dev->loader_dispatch.CreateDevice(gpu, pCreateInfo, pDevice);
3012
3013 dev->loader_dispatch.CreateDevice = icd->CreateDevice;
3014
Jon Ashburn2666e2f2015-05-15 15:09:35 -06003015 return res;
3016}
3017
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -06003018static PFN_vkVoidFunction VKAPI loader_GetInstanceProcAddr(VkInstance instance, const char * pName)
Jon Ashburn53c16772015-05-06 10:15:07 -06003019{
Jon Ashburncedc15f2015-05-21 18:13:33 -06003020 if (instance == VK_NULL_HANDLE)
3021 return NULL;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06003022
Jon Ashburncedc15f2015-05-21 18:13:33 -06003023 void *addr;
3024 /* get entrypoint addresses that are global (in the loader)*/
3025 addr = globalGetProcAddr(pName);
3026 if (addr)
3027 return addr;
Jon Ashburn53c16772015-05-06 10:15:07 -06003028
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06003029 struct loader_instance *ptr_instance = (struct loader_instance *) instance;
3030
Jon Ashburn4ebc0962015-06-18 09:05:37 -06003031 /* return any extension global entrypoints */
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06003032 addr = debug_report_instance_gpa(ptr_instance, pName);
3033 if (addr) {
3034 return addr;
3035 }
3036
Ian Elliott1d73e662015-07-06 14:36:13 -06003037 addr = wsi_swapchain_GetInstanceProcAddr(ptr_instance, pName);
David Pinedo0fab78b2015-06-24 15:29:18 -06003038 if (addr) {
Jon Ashburn4ebc0962015-06-18 09:05:37 -06003039 return addr;
David Pinedo0fab78b2015-06-24 15:29:18 -06003040 }
Jon Ashburncedc15f2015-05-21 18:13:33 -06003041
3042 /* return the instance dispatch table entrypoint for extensions */
3043 const VkLayerInstanceDispatchTable *disp_table = * (VkLayerInstanceDispatchTable **) instance;
3044 if (disp_table == NULL)
3045 return NULL;
3046
3047 addr = loader_lookup_instance_dispatch_table(disp_table, pName);
3048 if (addr)
3049 return addr;
Jon Ashburn53c16772015-05-06 10:15:07 -06003050
3051 return NULL;
3052}
3053
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -06003054LOADER_EXPORT PFN_vkVoidFunction VKAPI vkGetInstanceProcAddr(VkInstance instance, const char * pName)
Courtney Goeltzenleuchter9a4f38c2015-06-22 17:45:21 -06003055{
3056 return loader_GetInstanceProcAddr(instance, pName);
3057}
3058
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -06003059static PFN_vkVoidFunction VKAPI loader_GetDeviceProcAddr(VkDevice device, const char * pName)
Jon Ashburn349508d2015-01-26 14:51:40 -07003060{
Jon Ashburn1245cec2015-05-18 13:20:15 -06003061 if (device == VK_NULL_HANDLE) {
3062 return NULL;
Ian Elliott81ac44c2015-01-13 17:52:38 -07003063 }
Jon Ashburne18431b2015-04-13 18:10:06 -06003064
Chia-I Wu38e5a2c2015-01-04 11:12:47 +08003065 void *addr;
Jon Ashburnd43f9b62014-10-14 19:15:22 -06003066
Jon Ashburne18431b2015-04-13 18:10:06 -06003067 /* for entrypoints that loader must handle (ie non-dispatchable or create object)
3068 make sure the loader entrypoint is returned */
3069 addr = loader_non_passthrough_gpa(pName);
Ian Elliottfdf00b62015-04-15 12:53:19 -06003070 if (addr) {
Jon Ashburne18431b2015-04-13 18:10:06 -06003071 return addr;
Ian Elliottfdf00b62015-04-15 12:53:19 -06003072 }
Jon Ashburne18431b2015-04-13 18:10:06 -06003073
3074 /* return the dispatch table entrypoint for the fastest case */
Jon Ashburn1245cec2015-05-18 13:20:15 -06003075 const VkLayerDispatchTable *disp_table = * (VkLayerDispatchTable **) device;
Jon Ashburnd43f9b62014-10-14 19:15:22 -06003076 if (disp_table == NULL)
3077 return NULL;
3078
Jon Ashburnfce93d92015-05-12 17:26:48 -06003079 addr = loader_lookup_device_dispatch_table(disp_table, pName);
Chia-I Wu38e5a2c2015-01-04 11:12:47 +08003080 if (addr)
3081 return addr;
Jon Ashburnd43f9b62014-10-14 19:15:22 -06003082 else {
Jon Ashburn1245cec2015-05-18 13:20:15 -06003083 if (disp_table->GetDeviceProcAddr == NULL)
Jon Ashburnd43f9b62014-10-14 19:15:22 -06003084 return NULL;
Jon Ashburn1245cec2015-05-18 13:20:15 -06003085 return disp_table->GetDeviceProcAddr(device, pName);
Jon Ashburnd43f9b62014-10-14 19:15:22 -06003086 }
3087}
3088
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -06003089LOADER_EXPORT PFN_vkVoidFunction VKAPI vkGetDeviceProcAddr(VkDevice device, const char * pName)
Courtney Goeltzenleuchter9a4f38c2015-06-22 17:45:21 -06003090{
3091 return loader_GetDeviceProcAddr(device, pName);
3092}
3093
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -06003094LOADER_EXPORT VkResult VKAPI vkEnumerateInstanceExtensionProperties(
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003095 const char* pLayerName,
3096 uint32_t* pCount,
3097 VkExtensionProperties* pProperties)
3098{
Jon Ashburnb8605fe2015-09-18 12:53:16 -06003099 struct loader_extension_list *global_ext_list=NULL;
Jon Ashburn182b8302015-08-11 14:49:54 -06003100 struct loader_layer_list instance_layers;
Jon Ashburnc1d1eb72015-08-14 11:57:54 -06003101 struct loader_extension_list icd_extensions;
Jon Ashburn754f1992015-08-18 18:04:47 -06003102 struct loader_icd_libs icd_libs;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003103 uint32_t copy_size;
3104
Jon Ashburn413d6582015-08-28 15:19:27 -06003105 tls_instance = NULL;
Jon Ashburnc1d1eb72015-08-14 11:57:54 -06003106 memset(&icd_extensions, 0, sizeof(icd_extensions));
Jon Ashburn754f1992015-08-18 18:04:47 -06003107 loader_platform_thread_once(&once_init, loader_initialize);
Jon Ashburnc1d1eb72015-08-14 11:57:54 -06003108
Jon Ashburn182b8302015-08-11 14:49:54 -06003109 /* get layer libraries if needed */
3110 if (pLayerName && strlen(pLayerName) != 0) {
3111 memset(&instance_layers, 0, sizeof(instance_layers));
Jon Ashburne58f1a32015-08-28 13:38:21 -06003112 loader_layer_scan(NULL, &instance_layers, NULL);
Jon Ashburn182b8302015-08-11 14:49:54 -06003113 for (uint32_t i = 0; i < instance_layers.count; i++) {
3114 struct loader_layer_properties *props = &instance_layers.list[i];
3115 if (strcmp(props->info.layerName, pLayerName) == 0) {
3116 global_ext_list = &props->instance_extension_list;
3117 }
3118 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06003119 loader_destroy_layer_list(NULL, &instance_layers);
Jon Ashburn182b8302015-08-11 14:49:54 -06003120 }
3121 else {
Jon Ashburn754f1992015-08-18 18:04:47 -06003122 /* Scan/discover all ICD libraries */
3123 memset(&icd_libs, 0 , sizeof(struct loader_icd_libs));
Jon Ashburne58f1a32015-08-28 13:38:21 -06003124 loader_icd_scan(NULL, &icd_libs);
Jon Ashburnc1d1eb72015-08-14 11:57:54 -06003125 /* get extensions from all ICD's, merge so no duplicates */
Jon Ashburne58f1a32015-08-28 13:38:21 -06003126 loader_get_icd_loader_instance_extensions(NULL, &icd_libs, &icd_extensions);
3127 loader_scanned_icd_clear(NULL, &icd_libs);
Jon Ashburnc1d1eb72015-08-14 11:57:54 -06003128 global_ext_list = &icd_extensions;
Jon Ashburn182b8302015-08-11 14:49:54 -06003129 }
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003130
Jon Ashburn182b8302015-08-11 14:49:54 -06003131 if (global_ext_list == NULL) {
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -06003132 return VK_ERROR_LAYER_NOT_PRESENT;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003133 }
3134
3135 if (pProperties == NULL) {
Jon Ashburn182b8302015-08-11 14:49:54 -06003136 *pCount = global_ext_list->count;
Jon Ashburne58f1a32015-08-28 13:38:21 -06003137 loader_destroy_ext_list(NULL, &icd_extensions);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003138 return VK_SUCCESS;
3139 }
3140
Jon Ashburn182b8302015-08-11 14:49:54 -06003141 copy_size = *pCount < global_ext_list->count ? *pCount : global_ext_list->count;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003142 for (uint32_t i = 0; i < copy_size; i++) {
3143 memcpy(&pProperties[i],
Jon Ashburn182b8302015-08-11 14:49:54 -06003144 &global_ext_list->list[i],
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003145 sizeof(VkExtensionProperties));
3146 }
3147 *pCount = copy_size;
Jon Ashburne58f1a32015-08-28 13:38:21 -06003148 loader_destroy_ext_list(NULL, &icd_extensions);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003149
Jon Ashburn182b8302015-08-11 14:49:54 -06003150 if (copy_size < global_ext_list->count) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003151 return VK_INCOMPLETE;
3152 }
3153
3154 return VK_SUCCESS;
3155}
3156
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -06003157LOADER_EXPORT VkResult VKAPI vkEnumerateInstanceLayerProperties(
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003158 uint32_t* pCount,
3159 VkLayerProperties* pProperties)
Tony Barbour426b9052015-06-24 16:06:58 -06003160{
Jon Ashburnb40f2562015-05-29 13:15:39 -06003161
Jon Ashburn182b8302015-08-11 14:49:54 -06003162 struct loader_layer_list instance_layer_list;
Jon Ashburn413d6582015-08-28 15:19:27 -06003163 tls_instance = NULL;
Jon Ashburn182b8302015-08-11 14:49:54 -06003164
Jon Ashburn754f1992015-08-18 18:04:47 -06003165 loader_platform_thread_once(&once_init, loader_initialize);
Courtney Goeltzenleuchter0199e952015-02-27 15:19:33 -07003166
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003167 uint32_t copy_size;
Jon Ashburneb2728b2015-04-10 14:33:07 -06003168
Jon Ashburn182b8302015-08-11 14:49:54 -06003169 /* get layer libraries */
3170 memset(&instance_layer_list, 0, sizeof(instance_layer_list));
Jon Ashburne58f1a32015-08-28 13:38:21 -06003171 loader_layer_scan(NULL, &instance_layer_list, NULL);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003172
3173 if (pProperties == NULL) {
Jon Ashburn182b8302015-08-11 14:49:54 -06003174 *pCount = instance_layer_list.count;
Jon Ashburne58f1a32015-08-28 13:38:21 -06003175 loader_destroy_layer_list(NULL, &instance_layer_list);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003176 return VK_SUCCESS;
3177 }
3178
Jon Ashburn182b8302015-08-11 14:49:54 -06003179 copy_size = (*pCount < instance_layer_list.count) ? *pCount : instance_layer_list.count;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003180 for (uint32_t i = 0; i < copy_size; i++) {
Jon Ashburn182b8302015-08-11 14:49:54 -06003181 memcpy(&pProperties[i], &instance_layer_list.list[i].info, sizeof(VkLayerProperties));
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003182 }
3183 *pCount = copy_size;
Jon Ashburne58f1a32015-08-28 13:38:21 -06003184 loader_destroy_layer_list(NULL, &instance_layer_list);
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003185
Jon Ashburn182b8302015-08-11 14:49:54 -06003186 if (copy_size < instance_layer_list.count) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003187 return VK_INCOMPLETE;
3188 }
Tony Barbour426b9052015-06-24 16:06:58 -06003189
3190 return VK_SUCCESS;
3191}
3192
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -06003193VkResult VKAPI loader_EnumerateDeviceExtensionProperties(
Tony Barbour426b9052015-06-24 16:06:58 -06003194 VkPhysicalDevice gpu,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003195 const char* pLayerName,
3196 uint32_t* pCount,
Tony Barbour426b9052015-06-24 16:06:58 -06003197 VkExtensionProperties* pProperties)
3198{
3199 uint32_t gpu_index;
Jon Ashburnd5df54d2015-05-28 19:16:58 -06003200 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003201 uint32_t copy_size;
Courtney Goeltzenleuchter0199e952015-02-27 15:19:33 -07003202
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003203 uint32_t count;
Jon Ashburnb8605fe2015-09-18 12:53:16 -06003204 struct loader_extension_list *dev_ext_list=NULL;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003205
Jon Ashburn182b8302015-08-11 14:49:54 -06003206 /* get layer libraries if needed */
3207 if (pLayerName && strlen(pLayerName) != 0) {
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06003208 for (uint32_t i = 0; i < icd->this_instance->device_layer_list.count; i++) {
3209 struct loader_layer_properties *props = &icd->this_instance->device_layer_list.list[i];
Jon Ashburn182b8302015-08-11 14:49:54 -06003210 if (strcmp(props->info.layerName, pLayerName) == 0) {
3211 dev_ext_list = &props->device_extension_list;
3212 }
3213 }
3214 }
3215 else {
3216 dev_ext_list = &icd->device_extension_cache[gpu_index];
3217 }
3218
Jon Ashburnb8605fe2015-09-18 12:53:16 -06003219 count = (dev_ext_list == NULL) ? 0: dev_ext_list->count;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003220 if (pProperties == NULL) {
3221 *pCount = count;
3222 return VK_SUCCESS;
3223 }
3224
3225 copy_size = *pCount < count ? *pCount : count;
3226 for (uint32_t i = 0; i < copy_size; i++) {
3227 memcpy(&pProperties[i],
Jon Ashburn182b8302015-08-11 14:49:54 -06003228 &dev_ext_list->list[i],
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003229 sizeof(VkExtensionProperties));
3230 }
3231 *pCount = copy_size;
3232
3233 if (copy_size < count) {
3234 return VK_INCOMPLETE;
3235 }
3236
3237 return VK_SUCCESS;
3238}
3239
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -06003240VkResult VKAPI loader_EnumerateDeviceLayerProperties(
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003241 VkPhysicalDevice gpu,
3242 uint32_t* pCount,
3243 VkLayerProperties* pProperties)
3244{
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003245 uint32_t copy_size;
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06003246 uint32_t gpu_index;
3247 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003248
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06003249 uint32_t count = icd->this_instance->device_layer_list.count;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003250
3251 if (pProperties == NULL) {
3252 *pCount = count;
3253 return VK_SUCCESS;
3254 }
3255
Jon Ashburn182b8302015-08-11 14:49:54 -06003256 copy_size = (*pCount < count) ? *pCount : count;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003257 for (uint32_t i = 0; i < copy_size; i++) {
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06003258 memcpy(&pProperties[i], &(icd->this_instance->device_layer_list.list[i].info), sizeof(VkLayerProperties));
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003259 }
3260 *pCount = copy_size;
3261
3262 if (copy_size < count) {
3263 return VK_INCOMPLETE;
3264 }
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003265
3266 return VK_SUCCESS;
Jon Ashburn2666e2f2015-05-15 15:09:35 -06003267}