blob: 44c7d6674c8a03c5ea9f9029a3caed22199b0641 [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 bool loader_init_ext_list(
65 const struct loader_instance *inst,
66 struct loader_extension_list *ext_info);
Courtney Goeltzenleuchter9a4f38c2015-06-22 17:45:21 -060067
Courtney Goeltzenleuchter8b253f92015-06-08 15:11:18 -060068enum loader_debug {
Courtney Goeltzenleuchter1d4c50f2015-07-08 18:41:08 -060069 LOADER_INFO_BIT = 0x01,
70 LOADER_WARN_BIT = 0x02,
71 LOADER_PERF_BIT = 0x04,
72 LOADER_ERROR_BIT = 0x08,
73 LOADER_DEBUG_BIT = 0x10,
Courtney Goeltzenleuchter8b253f92015-06-08 15:11:18 -060074};
75
76uint32_t g_loader_debug = 0;
77uint32_t g_loader_log_msgs = 0;
78
Jon Ashburnb40f2562015-05-29 13:15:39 -060079//thread safety lock for accessing global data structures such as "loader"
80// all entrypoints on the instance chain need to be locked except GPA
Jon Ashburnffd5d672015-06-29 11:25:34 -060081// additionally CreateDevice and DestroyDevice needs to be locked
Jon Ashburnb40f2562015-05-29 13:15:39 -060082loader_platform_thread_mutex loader_lock;
Jon Ashburnd02fc2c2015-09-22 13:11:00 -060083loader_platform_thread_mutex loader_json_lock;
Jon Ashburnb40f2562015-05-29 13:15:39 -060084
Ian Elliott1d73e662015-07-06 14:36:13 -060085// This table contains the loader's instance dispatch table, which contains
86// default functions if no instance layers are activated. This contains
87// pointers to "terminator functions".
Jon Ashburnb40f2562015-05-29 13:15:39 -060088const VkLayerInstanceDispatchTable instance_disp = {
Jon Ashburn8aa75cb2015-09-28 16:15:00 -060089 .GetInstanceProcAddr = vkGetInstanceProcAddr,
Jon Ashburnfce93d92015-05-12 17:26:48 -060090 .CreateInstance = loader_CreateInstance,
91 .DestroyInstance = loader_DestroyInstance,
92 .EnumeratePhysicalDevices = loader_EnumeratePhysicalDevices,
Chris Forbesd7576302015-06-21 22:55:02 +120093 .GetPhysicalDeviceFeatures = loader_GetPhysicalDeviceFeatures,
Courtney Goeltzenleuchter4da96aa2015-07-12 12:52:09 -060094 .GetPhysicalDeviceFormatProperties = loader_GetPhysicalDeviceFormatProperties,
Jon Ashburn4e189562015-07-23 18:49:07 -060095 .GetPhysicalDeviceImageFormatProperties = loader_GetPhysicalDeviceImageFormatProperties,
Tony Barbour426b9052015-06-24 16:06:58 -060096 .GetPhysicalDeviceProperties = loader_GetPhysicalDeviceProperties,
Cody Northropef72e2a2015-08-03 17:04:53 -060097 .GetPhysicalDeviceQueueFamilyProperties = loader_GetPhysicalDeviceQueueFamilyProperties,
Tony Barbour426b9052015-06-24 16:06:58 -060098 .GetPhysicalDeviceMemoryProperties = loader_GetPhysicalDeviceMemoryProperties,
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -060099 .EnumerateDeviceExtensionProperties = loader_EnumerateDeviceExtensionProperties,
100 .EnumerateDeviceLayerProperties = loader_EnumerateDeviceLayerProperties,
Mark Lobodzinski83d4e6a2015-07-03 15:58:09 -0600101 .GetPhysicalDeviceSparseImageFormatProperties = loader_GetPhysicalDeviceSparseImageFormatProperties,
Ian Elliott338dedb2015-08-21 15:09:33 -0600102 .GetPhysicalDeviceSurfaceSupportKHR = loader_GetPhysicalDeviceSurfaceSupportKHR,
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600103 .DbgCreateMsgCallback = loader_DbgCreateMsgCallback,
104 .DbgDestroyMsgCallback = loader_DbgDestroyMsgCallback,
Jon Ashburnfce93d92015-05-12 17:26:48 -0600105};
106
Jon Ashburn754f1992015-08-18 18:04:47 -0600107LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_init);
Ian Elliott81ac44c2015-01-13 17:52:38 -0700108
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600109void* loader_heap_alloc(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600110 const struct loader_instance *instance,
111 size_t size,
112 VkSystemAllocType alloc_type)
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600113{
114 if (instance && instance->alloc_callbacks.pfnAlloc) {
115 /* TODO: What should default alignment be? 1, 4, 8, other? */
116 return instance->alloc_callbacks.pfnAlloc(instance->alloc_callbacks.pUserData, size, 4, alloc_type);
117 }
118 return malloc(size);
119}
120
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600121void loader_heap_free(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600122 const struct loader_instance *instance,
123 void *pMem)
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600124{
Mike Stroyana73e50c2015-10-01 15:23:48 -0600125 if (pMem == NULL) return;
Jon Ashburncfe4e682015-08-14 12:51:47 -0600126 if (instance && instance->alloc_callbacks.pfnFree) {
Courtney Goeltzenleuchtere9005172015-07-10 17:39:59 -0600127 instance->alloc_callbacks.pfnFree(instance->alloc_callbacks.pUserData, pMem);
Jon Ashburnfab6ee22015-08-13 08:28:48 -0600128 return;
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600129 }
Courtney Goeltzenleuchtere9005172015-07-10 17:39:59 -0600130 free(pMem);
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600131}
132
Jon Ashburne5e60df2015-08-27 15:23:52 -0600133void* loader_heap_realloc(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600134 const struct loader_instance *instance,
Jon Ashburne5e60df2015-08-27 15:23:52 -0600135 void *pMem,
136 size_t orig_size,
137 size_t size,
138 VkSystemAllocType alloc_type)
139{
140 if (pMem == NULL || orig_size == 0)
141 return loader_heap_alloc(instance, size, alloc_type);
142 if (size == 0) {
143 loader_heap_free(instance, pMem);
144 return NULL;
145 }
146 if (instance && instance->alloc_callbacks.pfnAlloc) {
147 if (size <= orig_size) {
148 memset(((uint8_t *)pMem) + size, 0, orig_size - size);
149 return pMem;
150 }
151 void *new_ptr = instance->alloc_callbacks.pfnAlloc(instance->alloc_callbacks.pUserData, size, 4, alloc_type);
152 if (!new_ptr)
153 return NULL;
154 memcpy(new_ptr, pMem, orig_size);
155 instance->alloc_callbacks.pfnFree(instance->alloc_callbacks.pUserData, pMem);
Jon Ashburn37984152015-10-21 16:09:27 -0600156 return new_ptr;
Jon Ashburne5e60df2015-08-27 15:23:52 -0600157 }
158 return realloc(pMem, size);
159}
160
Jon Ashburn413d6582015-08-28 15:19:27 -0600161void *loader_tls_heap_alloc(size_t size)
162{
163 return loader_heap_alloc(tls_instance, size, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
164}
165
166void loader_tls_heap_free(void *pMem)
167{
Jon Ashburnf1e68102015-10-07 09:23:40 -0600168 loader_heap_free(tls_instance, pMem);
Jon Ashburn413d6582015-08-28 15:19:27 -0600169}
170
Jon Ashburnee33ae72015-06-30 14:46:22 -0700171static void loader_log(VkFlags msg_type, int32_t msg_code,
172 const char *format, ...)
173{
Jon Ashburn2b779162015-07-31 15:47:59 -0600174 char msg[512];
Jon Ashburnee33ae72015-06-30 14:46:22 -0700175 va_list ap;
176 int ret;
177
178 if (!(msg_type & g_loader_log_msgs)) {
179 return;
180 }
181
182 va_start(ap, format);
183 ret = vsnprintf(msg, sizeof(msg), format, ap);
184 if ((ret >= (int) sizeof(msg)) || ret < 0) {
185 msg[sizeof(msg)-1] = '\0';
186 }
187 va_end(ap);
188
Ian Elliott225188f2015-02-17 10:33:47 -0700189#if defined(WIN32)
Jon Ashburnee33ae72015-06-30 14:46:22 -0700190 OutputDebugString(msg);
mschott632564c2015-07-22 14:11:29 +0200191 OutputDebugString("\n");
Jon Ashburnee33ae72015-06-30 14:46:22 -0700192#endif
193 fputs(msg, stderr);
194 fputc('\n', stderr);
195}
196
197#if defined(WIN32)
Tony Barbour76096e62015-07-29 14:26:21 -0600198static char *loader_get_next_path(char *path);
Jon Ashburnee33ae72015-06-30 14:46:22 -0700199/**
200* Find the list of registry files (names within a key) in key "location".
201*
202* This function looks in the registry (hive = DEFAULT_VK_REGISTRY_HIVE) key as given in "location"
203* for a list or name/values which are added to a returned list (function return value).
204* The DWORD values within the key must be 0 or they are skipped.
Jon Ashburne58f1a32015-08-28 13:38:21 -0600205* Function return is a string with a ';' separated list of filenames.
Jon Ashburnee33ae72015-06-30 14:46:22 -0700206* Function return is NULL if no valid name/value pairs are found in the key,
207* or the key is not found.
208*
209* \returns
210* A string list of filenames as pointer.
211* When done using the returned string list, pointer should be freed.
212*/
Jon Ashburne58f1a32015-08-28 13:38:21 -0600213static char *loader_get_registry_files(const struct loader_instance *inst, char *location)
Jon Ashburnee33ae72015-06-30 14:46:22 -0700214{
215 LONG rtn_value;
216 HKEY hive, key;
217 DWORD access_flags = KEY_QUERY_VALUE;
218 char name[2048];
219 char *out = NULL;
Tony Barbour76096e62015-07-29 14:26:21 -0600220 char *loc = location;
221 char *next;
Jon Ashburnee33ae72015-06-30 14:46:22 -0700222 DWORD idx = 0;
223 DWORD name_size = sizeof(name);
224 DWORD value;
225 DWORD total_size = 4096;
226 DWORD value_size = sizeof(value);
Tony Barbour76096e62015-07-29 14:26:21 -0600227
228 while(*loc)
229 {
230 next = loader_get_next_path(loc);
231 hive = DEFAULT_VK_REGISTRY_HIVE;
232 rtn_value = RegOpenKeyEx(hive, loc, 0, access_flags, &key);
233 if (rtn_value != ERROR_SUCCESS) {
234 // We didn't find the key. Try the 32-bit hive (where we've seen the
235 // key end up on some people's systems):
236 access_flags |= KEY_WOW64_32KEY;
237 rtn_value = RegOpenKeyEx(hive, loc, 0, access_flags, &key);
238 if (rtn_value != ERROR_SUCCESS) {
239 // We still couldn't find the key, so give up:
240 loc = next;
241 continue;
Jon Ashburnee33ae72015-06-30 14:46:22 -0700242 }
Jon Ashburnee33ae72015-06-30 14:46:22 -0700243 }
Tony Barbour76096e62015-07-29 14:26:21 -0600244
Jon Ashburne58f1a32015-08-28 13:38:21 -0600245 while ((rtn_value = RegEnumValue(key, idx++, name, &name_size, NULL, NULL, (LPBYTE) &value, &value_size)) == ERROR_SUCCESS) {
Tony Barbour76096e62015-07-29 14:26:21 -0600246 if (value_size == sizeof(value) && value == 0) {
247 if (out == NULL) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600248 out = loader_heap_alloc(inst, total_size, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Tony Barbour76096e62015-07-29 14:26:21 -0600249 out[0] = '\0';
250 }
251 else if (strlen(out) + name_size + 1 > total_size) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600252 out = loader_heap_realloc(inst, out, total_size, total_size * 2, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Tony Barbour76096e62015-07-29 14:26:21 -0600253 total_size *= 2;
254 }
255 if (out == NULL) {
256 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory, failed loader_get_registry_files");
257 return NULL;
258 }
259 if (strlen(out) == 0)
260 snprintf(out, name_size + 1, "%s", name);
261 else
262 snprintf(out + strlen(out), name_size + 2, "%c%s", PATH_SEPERATOR, name);
263 }
264 name_size = 2048;
265 }
266 loc = next;
Jon Ashburnee33ae72015-06-30 14:46:22 -0700267 }
Tony Barbour76096e62015-07-29 14:26:21 -0600268
Jon Ashburnee33ae72015-06-30 14:46:22 -0700269 return out;
270}
271
Ian Elliott225188f2015-02-17 10:33:47 -0700272#endif // WIN32
273
Jon Ashburn4b7f35f2015-08-03 09:08:46 -0600274/**
275 * Given string of three part form "maj.min.pat" convert to a vulkan version
276 * number.
277 */
278static uint32_t loader_make_version(const char *vers_str)
279{
Jon Ashburnb8605fe2015-09-18 12:53:16 -0600280 uint32_t vers = 0, major=0, minor=0, patch=0;
Jon Ashburn4b7f35f2015-08-03 09:08:46 -0600281 char *minor_str= NULL;
282 char *patch_str = NULL;
283 char *cstr;
284 char *str;
285
286 if (!vers_str)
287 return vers;
288 cstr = loader_stack_alloc(strlen(vers_str) + 1);
289 strcpy(cstr, vers_str);
290 while ((str = strchr(cstr, '.')) != NULL) {
291 if (minor_str == NULL) {
292 minor_str = str + 1;
293 *str = '\0';
294 major = atoi(cstr);
295 }
296 else if (patch_str == NULL) {
297 patch_str = str + 1;
298 *str = '\0';
299 minor = atoi(minor_str);
300 }
301 else {
302 return vers;
303 }
304 cstr = str + 1;
305 }
306 patch = atoi(patch_str);
307
308 return VK_MAKE_VERSION(major, minor, patch);
309
310}
311
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600312bool compare_vk_extension_properties(const VkExtensionProperties *op1, const VkExtensionProperties *op2)
313{
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600314 return strcmp(op1->extName, op2->extName) == 0 ? true : false;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600315}
316
Jon Ashburn1b111de2015-07-06 15:40:35 -0600317/**
Jon Ashburn60378412015-07-02 12:59:25 -0600318 * Search the given ext_array for an extension
319 * matching the given vk_ext_prop
320 */
321bool has_vk_extension_property_array(
322 const VkExtensionProperties *vk_ext_prop,
323 const uint32_t count,
324 const VkExtensionProperties *ext_array)
325{
326 for (uint32_t i = 0; i < count; i++) {
327 if (compare_vk_extension_properties(vk_ext_prop, &ext_array[i]))
328 return true;
329 }
330 return false;
331}
332
Jon Ashburn1b111de2015-07-06 15:40:35 -0600333/**
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600334 * Search the given ext_list for an extension
335 * matching the given vk_ext_prop
336 */
337bool has_vk_extension_property(
338 const VkExtensionProperties *vk_ext_prop,
339 const struct loader_extension_list *ext_list)
340{
341 for (uint32_t i = 0; i < ext_list->count; i++) {
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600342 if (compare_vk_extension_properties(&ext_list->list[i], vk_ext_prop))
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600343 return true;
344 }
345 return false;
346}
347
Jon Ashburn0bf6a182015-07-16 17:19:31 -0600348static inline bool loader_is_layer_type_device(const enum layer_type type) {
349 if ((type & VK_LAYER_TYPE_DEVICE_EXPLICIT) ||
350 (type & VK_LAYER_TYPE_DEVICE_IMPLICIT))
351 return true;
352 return false;
353}
354
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600355/*
Jon Ashburn1b111de2015-07-06 15:40:35 -0600356 * Search the given layer list for a layer matching the given layer name
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600357 */
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600358static struct loader_layer_properties *loader_get_layer_property(
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600359 const char *name,
360 const struct loader_layer_list *layer_list)
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600361{
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600362 for (uint32_t i = 0; i < layer_list->count; i++) {
363 const VkLayerProperties *item = &layer_list->list[i].info;
364 if (strcmp(name, item->layerName) == 0)
365 return &layer_list->list[i];
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600366 }
367 return NULL;
368}
369
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600370/**
371 * Get the next unused layer property in the list. Init the property to zero.
372 */
373static struct loader_layer_properties *loader_get_next_layer_property(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600374 const struct loader_instance *inst,
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600375 struct loader_layer_list *layer_list)
376{
377 if (layer_list->capacity == 0) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600378 layer_list->list = loader_heap_alloc(inst,
379 sizeof(struct loader_layer_properties) * 64,
380 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600381 if (layer_list->list == NULL) {
382 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't add any layer properties to list");
383 return NULL;
384 }
385 memset(layer_list->list, 0, sizeof(struct loader_layer_properties) * 64);
386 layer_list->capacity = sizeof(struct loader_layer_properties) * 64;
387 }
388
389 // ensure enough room to add an entry
390 if ((layer_list->count + 1) * sizeof (struct loader_layer_properties)
391 > layer_list->capacity) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600392 layer_list->list = loader_heap_realloc(inst, layer_list->list,
393 layer_list->capacity,
394 layer_list->capacity * 2,
395 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600396 if (layer_list->list == NULL) {
397 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
398 "realloc failed for layer list");
399 }
400 layer_list->capacity *= 2;
401 }
402
403 layer_list->count++;
404 return &(layer_list->list[layer_list->count - 1]);
405}
406
407/**
408 * Remove all layer properties entrys from the list
409 */
Jon Ashburne58f1a32015-08-28 13:38:21 -0600410void loader_delete_layer_properties(
411 const struct loader_instance *inst,
412 struct loader_layer_list *layer_list)
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600413{
414 uint32_t i;
415
Jon Ashburn182b8302015-08-11 14:49:54 -0600416 if (!layer_list)
417 return;
418
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600419 for (i = 0; i < layer_list->count; i++) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600420 loader_destroy_ext_list(inst, &layer_list->list[i].instance_extension_list);
421 loader_destroy_ext_list(inst, &layer_list->list[i].device_extension_list);
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600422 }
423 layer_list->count = 0;
424
Jon Ashburn182b8302015-08-11 14:49:54 -0600425 if (layer_list->capacity > 0) {
426 layer_list->capacity = 0;
Jon Ashburne58f1a32015-08-28 13:38:21 -0600427 loader_heap_free(inst, layer_list->list);
Jon Ashburn182b8302015-08-11 14:49:54 -0600428 }
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600429
430}
431
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600432static void loader_add_global_extensions(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600433 const struct loader_instance *inst,
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -0600434 const PFN_vkEnumerateInstanceExtensionProperties fp_get_props,
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600435 const char *lib_name,
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600436 struct loader_extension_list *ext_list)
437{
438 uint32_t i, count;
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600439 VkExtensionProperties *ext_props;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600440 VkResult res;
441
Courtney Goeltzenleuchteraa9faab2015-07-06 22:28:18 -0600442 if (!fp_get_props) {
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -0600443 /* No EnumerateInstanceExtensionProperties defined */
Courtney Goeltzenleuchteraa9faab2015-07-06 22:28:18 -0600444 return;
445 }
446
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600447 res = fp_get_props(NULL, &count, NULL);
Jon Ashburneb2728b2015-04-10 14:33:07 -0600448 if (res != VK_SUCCESS) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600449 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Error getting global extension count from %s", lib_name);
Jon Ashburneb2728b2015-04-10 14:33:07 -0600450 return;
451 }
Jon Ashburn60699262015-06-10 16:11:42 -0600452
Courtney Goeltzenleuchteraa9faab2015-07-06 22:28:18 -0600453 if (count == 0) {
454 /* No ExtensionProperties to report */
455 return;
456 }
457
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600458 ext_props = loader_stack_alloc(count * sizeof(VkExtensionProperties));
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600459
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600460 res = fp_get_props(NULL, &count, ext_props);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600461 if (res != VK_SUCCESS) {
462 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Error getting global extensions from %s", lib_name);
463 return;
464 }
Tony Barbour426b9052015-06-24 16:06:58 -0600465
Jon Ashburneb2728b2015-04-10 14:33:07 -0600466 for (i = 0; i < count; i++) {
Courtney Goeltzenleuchter73a21d32015-07-12 13:20:05 -0600467 char spec_version[64];
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600468
469 snprintf(spec_version, sizeof(spec_version), "%d.%d.%d",
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600470 VK_MAJOR(ext_props[i].specVersion),
471 VK_MINOR(ext_props[i].specVersion),
472 VK_PATCH(ext_props[i].specVersion));
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600473 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Courtney Goeltzenleuchter73a21d32015-07-12 13:20:05 -0600474 "Global Extension: %s (%s) version %s",
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600475 ext_props[i].extName, lib_name, spec_version);
Jon Ashburne58f1a32015-08-28 13:38:21 -0600476 loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600477 }
478
479 return;
480}
481
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600482static void loader_add_physical_device_extensions(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600483 const struct loader_instance *inst,
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -0600484 PFN_vkEnumerateDeviceExtensionProperties get_phys_dev_ext_props,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600485 VkPhysicalDevice physical_device,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600486 const char *lib_name,
487 struct loader_extension_list *ext_list)
488{
489 uint32_t i, count;
490 VkResult res;
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600491 VkExtensionProperties *ext_props;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600492
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600493 if (!get_phys_dev_ext_props) {
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -0600494 /* No EnumerateDeviceExtensionProperties defined */
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600495 return;
496 }
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600497
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600498 res = get_phys_dev_ext_props(physical_device, NULL, &count, NULL);
499 if (res == VK_SUCCESS && count > 0) {
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600500 ext_props = loader_stack_alloc(count * sizeof(VkExtensionProperties));
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600501
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600502 res = get_phys_dev_ext_props(physical_device, NULL, &count, ext_props);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600503 for (i = 0; i < count; i++) {
Courtney Goeltzenleuchter73a21d32015-07-12 13:20:05 -0600504 char spec_version[64];
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600505
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600506 snprintf(spec_version, sizeof(spec_version), "%d.%d.%d",
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600507 VK_MAJOR(ext_props[i].specVersion),
508 VK_MINOR(ext_props[i].specVersion),
509 VK_PATCH(ext_props[i].specVersion));
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600510 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Courtney Goeltzenleuchter73a21d32015-07-12 13:20:05 -0600511 "PhysicalDevice Extension: %s (%s) version %s",
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600512 ext_props[i].extName, lib_name, spec_version);
Jon Ashburne58f1a32015-08-28 13:38:21 -0600513 loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
Jon Ashburn60699262015-06-10 16:11:42 -0600514 }
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600515 } else {
Jon Ashburn0b728052015-08-04 10:22:33 -0600516 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 -0600517 }
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600518
Jon Ashburneb2728b2015-04-10 14:33:07 -0600519 return;
520}
521
Jon Ashburne58f1a32015-08-28 13:38:21 -0600522static bool loader_init_ext_list(const struct loader_instance *inst,
523 struct loader_extension_list *ext_info)
Jon Ashburneb2728b2015-04-10 14:33:07 -0600524{
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600525 ext_info->capacity = 32 * sizeof(VkExtensionProperties);
Jon Ashburne58f1a32015-08-28 13:38:21 -0600526 ext_info->list = loader_heap_alloc(inst, ext_info->capacity, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600527 if (ext_info->list == NULL) {
528 return false;
529 }
530 memset(ext_info->list, 0, ext_info->capacity);
531 ext_info->count = 0;
532 return true;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600533}
534
Jon Ashburne58f1a32015-08-28 13:38:21 -0600535void loader_destroy_ext_list(const struct loader_instance *inst,
536 struct loader_extension_list *ext_info)
Jon Ashburneb2728b2015-04-10 14:33:07 -0600537{
Jon Ashburne58f1a32015-08-28 13:38:21 -0600538 loader_heap_free(inst, ext_info->list);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600539 ext_info->count = 0;
540 ext_info->capacity = 0;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600541}
Jon Ashburneb2728b2015-04-10 14:33:07 -0600542
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600543/*
544 * Append non-duplicate extension properties defined in props
545 * to the given ext_list.
546 */
547void loader_add_to_ext_list(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600548 const struct loader_instance *inst,
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600549 struct loader_extension_list *ext_list,
550 uint32_t prop_list_count,
551 const VkExtensionProperties *props)
552{
553 uint32_t i;
554 const VkExtensionProperties *cur_ext;
555
556 if (ext_list->list == NULL || ext_list->capacity == 0) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600557 loader_init_ext_list(inst, ext_list);
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600558 }
559
560 if (ext_list->list == NULL)
561 return;
562
563 for (i = 0; i < prop_list_count; i++) {
564 cur_ext = &props[i];
565
566 // look for duplicates
567 if (has_vk_extension_property(cur_ext, ext_list)) {
568 continue;
569 }
570
571 // add to list at end
572 // check for enough capacity
573 if (ext_list->count * sizeof(VkExtensionProperties)
574 >= ext_list->capacity) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600575
576 ext_list->list = loader_heap_realloc(inst,
577 ext_list->list,
578 ext_list->capacity,
579 ext_list->capacity * 2,
580 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600581 // double capacity
582 ext_list->capacity *= 2;
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600583 }
584
585 memcpy(&ext_list->list[ext_list->count], cur_ext, sizeof(VkExtensionProperties));
586 ext_list->count++;
587 }
588}
589
Jon Ashburn60378412015-07-02 12:59:25 -0600590/**
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600591 * Search the given search_list for any layers in the props list.
592 * Add these to the output layer_list. Don't add duplicates to the output layer_list.
Jon Ashburn60378412015-07-02 12:59:25 -0600593 */
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -0600594static VkResult loader_add_layer_names_to_list(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600595 const struct loader_instance *inst,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600596 struct loader_layer_list *output_list,
597 uint32_t name_count,
598 const char * const *names,
599 const struct loader_layer_list *search_list)
Jon Ashburneb2728b2015-04-10 14:33:07 -0600600{
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600601 struct loader_layer_properties *layer_prop;
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -0600602 VkResult err = VK_SUCCESS;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600603
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600604 for (uint32_t i = 0; i < name_count; i++) {
605 const char *search_target = names[i];
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600606 layer_prop = loader_get_layer_property(search_target, search_list);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600607 if (!layer_prop) {
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -0600608 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Unable to find layer %s", search_target);
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -0600609 err = VK_ERROR_LAYER_NOT_PRESENT;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600610 continue;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600611 }
612
Jon Ashburne58f1a32015-08-28 13:38:21 -0600613 loader_add_to_layer_list(inst, output_list, 1, layer_prop);
Jon Ashburneb2728b2015-04-10 14:33:07 -0600614 }
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -0600615
616 return err;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600617}
618
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600619
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600620/*
621 * Manage lists of VkLayerProperties
622 */
Jon Ashburne58f1a32015-08-28 13:38:21 -0600623static bool loader_init_layer_list(const struct loader_instance *inst,
624 struct loader_layer_list *list)
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600625{
626 list->capacity = 32 * sizeof(struct loader_layer_properties);
Jon Ashburne58f1a32015-08-28 13:38:21 -0600627 list->list = loader_heap_alloc(inst, list->capacity, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600628 if (list->list == NULL) {
629 return false;
630 }
631 memset(list->list, 0, list->capacity);
632 list->count = 0;
633 return true;
634}
635
Jon Ashburne58f1a32015-08-28 13:38:21 -0600636void loader_destroy_layer_list(const struct loader_instance *inst,
637 struct loader_layer_list *layer_list)
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600638{
Jon Ashburne58f1a32015-08-28 13:38:21 -0600639 loader_heap_free(inst, layer_list->list);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600640 layer_list->count = 0;
641 layer_list->capacity = 0;
642}
643
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600644/*
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600645 * Manage list of layer libraries (loader_lib_info)
646 */
Jon Ashburne58f1a32015-08-28 13:38:21 -0600647static bool loader_init_layer_library_list(const struct loader_instance *inst,
648 struct loader_layer_library_list *list)
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600649{
650 list->capacity = 32 * sizeof(struct loader_lib_info);
Jon Ashburne58f1a32015-08-28 13:38:21 -0600651 list->list = loader_heap_alloc(inst, list->capacity, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600652 if (list->list == NULL) {
653 return false;
654 }
655 memset(list->list, 0, list->capacity);
656 list->count = 0;
657 return true;
658}
659
Jon Ashburne58f1a32015-08-28 13:38:21 -0600660void loader_destroy_layer_library_list(const struct loader_instance *inst,
661 struct loader_layer_library_list *list)
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600662{
663 for (uint32_t i = 0; i < list->count; i++) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600664 loader_heap_free(inst, list->list[i].lib_name);
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600665 }
Jon Ashburne58f1a32015-08-28 13:38:21 -0600666 loader_heap_free(inst, list->list);
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600667 list->count = 0;
668 list->capacity = 0;
669}
670
671void loader_add_to_layer_library_list(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600672 const struct loader_instance *inst,
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600673 struct loader_layer_library_list *list,
674 uint32_t item_count,
675 const struct loader_lib_info *new_items)
676{
677 uint32_t i;
678 struct loader_lib_info *item;
679
680 if (list->list == NULL || list->capacity == 0) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600681 loader_init_layer_library_list(inst, list);
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600682 }
683
684 if (list->list == NULL)
685 return;
686
687 for (i = 0; i < item_count; i++) {
688 item = (struct loader_lib_info *) &new_items[i];
689
690 // look for duplicates
691 for (uint32_t j = 0; j < list->count; j++) {
692 if (strcmp(list->list[i].lib_name, new_items->lib_name) == 0) {
693 continue;
694 }
695 }
696
697 // add to list at end
698 // check for enough capacity
699 if (list->count * sizeof(struct loader_lib_info)
700 >= list->capacity) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600701
702 list->list = loader_heap_realloc(inst,
703 list->list,
704 list->capacity,
705 list->capacity * 2,
706 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600707 // double capacity
708 list->capacity *= 2;
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600709 }
710
711 memcpy(&list->list[list->count], item, sizeof(struct loader_lib_info));
712 list->count++;
713 }
714}
715
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600716
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600717/*
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600718 * Search the given layer list for a list
719 * matching the given VkLayerProperties
720 */
721bool has_vk_layer_property(
722 const VkLayerProperties *vk_layer_prop,
723 const struct loader_layer_list *list)
724{
725 for (uint32_t i = 0; i < list->count; i++) {
726 if (strcmp(vk_layer_prop->layerName, list->list[i].info.layerName) == 0)
727 return true;
728 }
729 return false;
730}
731
732/*
733 * Search the given layer list for a layer
734 * matching the given name
735 */
736bool has_layer_name(
737 const char *name,
738 const struct loader_layer_list *list)
739{
740 for (uint32_t i = 0; i < list->count; i++) {
741 if (strcmp(name, list->list[i].info.layerName) == 0)
742 return true;
743 }
744 return false;
745}
746
747/*
748 * Append non-duplicate layer properties defined in prop_list
749 * to the given layer_info list
750 */
751void loader_add_to_layer_list(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600752 const struct loader_instance *inst,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600753 struct loader_layer_list *list,
754 uint32_t prop_list_count,
755 const struct loader_layer_properties *props)
756{
757 uint32_t i;
758 struct loader_layer_properties *layer;
759
760 if (list->list == NULL || list->capacity == 0) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600761 loader_init_layer_list(inst, list);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600762 }
763
764 if (list->list == NULL)
765 return;
766
767 for (i = 0; i < prop_list_count; i++) {
768 layer = (struct loader_layer_properties *) &props[i];
769
770 // look for duplicates
771 if (has_vk_layer_property(&layer->info, list)) {
772 continue;
773 }
774
775 // add to list at end
776 // check for enough capacity
777 if (list->count * sizeof(struct loader_layer_properties)
778 >= list->capacity) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600779
780 list->list = loader_heap_realloc(inst,
781 list->list,
782 list->capacity,
783 list->capacity * 2,
784 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600785 // double capacity
786 list->capacity *= 2;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600787 }
788
789 memcpy(&list->list[list->count], layer, sizeof(struct loader_layer_properties));
790 list->count++;
791 }
792}
793
Jon Ashburnf2ddb732015-07-07 10:27:45 -0600794/**
795 * Search the search_list for any layer with a name
796 * that matches the given name and a type that matches the given type
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600797 * Add all matching layers to the found_list
Jon Ashburnf2ddb732015-07-07 10:27:45 -0600798 * Do not add if found loader_layer_properties is already
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600799 * on the found_list.
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600800 */
Jon Ashburn60378412015-07-02 12:59:25 -0600801static void loader_find_layer_name_add_list(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600802 const struct loader_instance *inst,
Jon Ashburn60378412015-07-02 12:59:25 -0600803 const char *name,
Jon Ashburnf2ddb732015-07-07 10:27:45 -0600804 const enum layer_type type,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600805 const struct loader_layer_list *search_list,
806 struct loader_layer_list *found_list)
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600807{
Jon Ashburn87c8fe92015-10-05 09:03:21 -0600808 bool found = false;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600809 for (uint32_t i = 0; i < search_list->count; i++) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600810 struct loader_layer_properties *layer_prop = &search_list->list[i];
Jon Ashburnf2ddb732015-07-07 10:27:45 -0600811 if (0 == strcmp(layer_prop->info.layerName, name) &&
812 (layer_prop->type & type)) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600813 /* Found a layer with the same name, add to found_list */
Jon Ashburne58f1a32015-08-28 13:38:21 -0600814 loader_add_to_layer_list(inst, found_list, 1, layer_prop);
Jon Ashburn87c8fe92015-10-05 09:03:21 -0600815 found = true;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600816 }
817 }
Jon Ashburn87c8fe92015-10-05 09:03:21 -0600818 if (!found) {
819 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Warning, couldn't find layer name %s to activate", name);
820 }
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600821}
822
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600823static VkExtensionProperties *get_extension_property(
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -0600824 const char *name,
825 const struct loader_extension_list *list)
Jon Ashburn42e41032015-04-14 09:15:32 -0600826{
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -0600827 for (uint32_t i = 0; i < list->count; i++) {
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600828 if (strcmp(name, list->list[i].extName) == 0)
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -0600829 return &list->list[i];
Jon Ashburn42e41032015-04-14 09:15:32 -0600830 }
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -0600831 return NULL;
Jon Ashburn42e41032015-04-14 09:15:32 -0600832}
833
Jon Ashburn60378412015-07-02 12:59:25 -0600834/*
835 * For global exenstions implemented within the loader (i.e. DEBUG_REPORT
836 * the extension must provide two entry points for the loader to use:
837 * - "trampoline" entry point - this is the address returned by GetProcAddr
838 * and will always do what's necessary to support a global call.
839 * - "terminator" function - this function will be put at the end of the
840 * instance chain and will contain the necessary logica to call / process
841 * the extension for the appropriate ICDs that are available.
842 * There is no generic mechanism for including these functions, the references
843 * must be placed into the appropriate loader entry points.
844 * GetInstanceProcAddr: call extension GetInstanceProcAddr to check for GetProcAddr requests
845 * loader_coalesce_extensions(void) - add extension records to the list of global
846 * extension available to the app.
847 * instance_disp - add function pointer for terminator function to this array.
848 * The extension itself should be in a separate file that will be
849 * linked directly with the loader.
850 */
Jon Ashburnc1d1eb72015-08-14 11:57:54 -0600851
Jon Ashburn754f1992015-08-18 18:04:47 -0600852void loader_get_icd_loader_instance_extensions(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600853 const struct loader_instance *inst,
Jon Ashburn754f1992015-08-18 18:04:47 -0600854 struct loader_icd_libs *icd_libs,
855 struct loader_extension_list *inst_exts)
Jon Ashburneb2728b2015-04-10 14:33:07 -0600856{
Jon Ashburn85f98072015-08-14 14:49:22 -0600857 struct loader_extension_list icd_exts;
Jon Ashburnc1d1eb72015-08-14 11:57:54 -0600858 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, "Build ICD instance extension list");
Jon Ashburneb2728b2015-04-10 14:33:07 -0600859 // traverse scanned icd list adding non-duplicate extensions to the list
Jon Ashburn754f1992015-08-18 18:04:47 -0600860 for (uint32_t i = 0; i < icd_libs->count; i++) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600861 loader_init_ext_list(inst, &icd_exts);
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -0600862 loader_add_global_extensions(inst, icd_libs->list[i].EnumerateInstanceExtensionProperties,
Jon Ashburn754f1992015-08-18 18:04:47 -0600863 icd_libs->list[i].lib_name,
Jon Ashburn85f98072015-08-14 14:49:22 -0600864 &icd_exts);
Jon Ashburne58f1a32015-08-28 13:38:21 -0600865 loader_add_to_ext_list(inst, inst_exts,
Jon Ashburn85f98072015-08-14 14:49:22 -0600866 icd_exts.count,
867 icd_exts.list);
Jon Ashburne58f1a32015-08-28 13:38:21 -0600868 loader_destroy_ext_list(inst, &icd_exts);
Jon Ashburneb2728b2015-04-10 14:33:07 -0600869 };
870
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600871 // Traverse loader's extensions, adding non-duplicate extensions to the list
Jon Ashburne58f1a32015-08-28 13:38:21 -0600872 wsi_swapchain_add_instance_extensions(inst, inst_exts);
873 debug_report_add_instance_extensions(inst, inst_exts);
Jon Ashburneb2728b2015-04-10 14:33:07 -0600874}
875
Jon Ashburne58f1a32015-08-28 13:38:21 -0600876struct loader_icd *loader_get_icd_and_device(const VkDevice device,
877 struct loader_device **found_dev)
Jon Ashburncb5a5ac2015-06-10 10:06:06 -0600878{
879 *found_dev = NULL;
880 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
881 for (struct loader_icd *icd = inst->icds; icd; icd = icd->next) {
882 for (struct loader_device *dev = icd->logical_device_list; dev; dev = dev->next)
Jon Ashburn0c5eea22015-09-30 12:56:42 -0600883 /* Value comparison of device prevents object wrapping by layers */
884 if (loader_get_dispatch(dev->device) == loader_get_dispatch(device)) {
Jon Ashburncb5a5ac2015-06-10 10:06:06 -0600885 *found_dev = dev;
886 return icd;
887 }
888 }
889 }
890 return NULL;
891}
892
Jon Ashburne58f1a32015-08-28 13:38:21 -0600893static void loader_destroy_logical_device(const struct loader_instance *inst,
894 struct loader_device *dev)
Jon Ashburncb5a5ac2015-06-10 10:06:06 -0600895{
Jon Ashburne58f1a32015-08-28 13:38:21 -0600896 loader_heap_free(inst, dev->app_extension_props);
Jon Ashburncb5a5ac2015-06-10 10:06:06 -0600897 if (dev->activated_layer_list.count)
Jon Ashburne58f1a32015-08-28 13:38:21 -0600898 loader_destroy_layer_list(inst, &dev->activated_layer_list);
899 loader_heap_free(inst, dev);
Jon Ashburncb5a5ac2015-06-10 10:06:06 -0600900}
901
Jon Ashburne58f1a32015-08-28 13:38:21 -0600902static struct loader_device *loader_add_logical_device(
903 const struct loader_instance *inst,
904 const VkDevice dev,
905 struct loader_device **device_list)
Jon Ashburncb5a5ac2015-06-10 10:06:06 -0600906{
907 struct loader_device *new_dev;
908
Jon Ashburne58f1a32015-08-28 13:38:21 -0600909 new_dev = loader_heap_alloc(inst, sizeof(struct loader_device), VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburncb5a5ac2015-06-10 10:06:06 -0600910 if (!new_dev) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600911 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc struct laoder-device");
Jon Ashburncb5a5ac2015-06-10 10:06:06 -0600912 return NULL;
913 }
914
915 memset(new_dev, 0, sizeof(struct loader_device));
916
917 new_dev->next = *device_list;
918 new_dev->device = dev;
919 *device_list = new_dev;
920 return new_dev;
921}
922
Jon Ashburne58f1a32015-08-28 13:38:21 -0600923void loader_remove_logical_device(
924 const struct loader_instance *inst,
925 VkDevice device)
Jon Ashburncb5a5ac2015-06-10 10:06:06 -0600926{
927 struct loader_device *found_dev, *dev, *prev_dev;
928 struct loader_icd *icd;
929 icd = loader_get_icd_and_device(device, &found_dev);
930
931 if (!icd || !found_dev)
932 return;
933
934 prev_dev = NULL;
935 dev = icd->logical_device_list;
936 while (dev && dev != found_dev) {
937 prev_dev = dev;
938 dev = dev->next;
939 }
940
941 if (prev_dev)
942 prev_dev->next = found_dev->next;
943 else
944 icd->logical_device_list = found_dev->next;
Jon Ashburne58f1a32015-08-28 13:38:21 -0600945 loader_destroy_logical_device(inst, found_dev);
Jon Ashburncb5a5ac2015-06-10 10:06:06 -0600946}
947
948
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600949static void loader_icd_destroy(
950 struct loader_instance *ptr_inst,
951 struct loader_icd *icd)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800952{
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600953 ptr_inst->total_icd_count--;
Jon Ashburne58f1a32015-08-28 13:38:21 -0600954 loader_heap_free(ptr_inst, icd->gpus);
Courtney Goeltzenleuchter6b70e362015-06-14 19:57:15 -0600955 for (struct loader_device *dev = icd->logical_device_list; dev; ) {
956 struct loader_device *next_dev = dev->next;
Jon Ashburne58f1a32015-08-28 13:38:21 -0600957 loader_destroy_logical_device(ptr_inst, dev);
Courtney Goeltzenleuchter6b70e362015-06-14 19:57:15 -0600958 dev = next_dev;
959 }
Jon Ashburncb5a5ac2015-06-10 10:06:06 -0600960
Jon Ashburne58f1a32015-08-28 13:38:21 -0600961 loader_heap_free(ptr_inst, icd);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800962}
963
Jon Ashburne58f1a32015-08-28 13:38:21 -0600964static struct loader_icd * loader_icd_create(const struct loader_instance *inst)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800965{
966 struct loader_icd *icd;
967
Jon Ashburne58f1a32015-08-28 13:38:21 -0600968 icd = loader_heap_alloc(inst, sizeof(*icd), VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800969 if (!icd)
970 return NULL;
971
Courtney Goeltzenleuchter6f928162014-10-28 10:29:27 -0600972 memset(icd, 0, sizeof(*icd));
973
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800974 return icd;
975}
976
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600977static struct loader_icd *loader_icd_add(
978 struct loader_instance *ptr_inst,
Jon Ashburne9ca8fa2015-08-20 16:35:30 -0600979 const struct loader_scanned_icds *icd_lib)
Chia-I Wu894a1172014-08-04 11:18:20 +0800980{
981 struct loader_icd *icd;
982
Jon Ashburne58f1a32015-08-28 13:38:21 -0600983 icd = loader_icd_create(ptr_inst);
Chia-I Wu894a1172014-08-04 11:18:20 +0800984 if (!icd)
985 return NULL;
986
Jon Ashburne9ca8fa2015-08-20 16:35:30 -0600987 icd->this_icd_lib = icd_lib;
988 icd->this_instance = ptr_inst;
989
Chia-I Wu894a1172014-08-04 11:18:20 +0800990 /* prepend to the list */
Jon Ashburn3336df82015-01-29 15:45:51 -0700991 icd->next = ptr_inst->icds;
992 ptr_inst->icds = icd;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600993 ptr_inst->total_icd_count++;
Chia-I Wu894a1172014-08-04 11:18:20 +0800994
995 return icd;
996}
997
Jon Ashburne58f1a32015-08-28 13:38:21 -0600998void loader_scanned_icd_clear(
999 const struct loader_instance *inst,
1000 struct loader_icd_libs *icd_libs)
Jon Ashburn754f1992015-08-18 18:04:47 -06001001{
1002 if (icd_libs->capacity == 0)
1003 return;
1004 for (uint32_t i = 0; i < icd_libs->count; i++) {
1005 loader_platform_close_library(icd_libs->list[i].handle);
Jon Ashburne58f1a32015-08-28 13:38:21 -06001006 loader_heap_free(inst, icd_libs->list[i].lib_name);
Jon Ashburn754f1992015-08-18 18:04:47 -06001007 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06001008 loader_heap_free(inst, icd_libs->list);
Jon Ashburn754f1992015-08-18 18:04:47 -06001009 icd_libs->capacity = 0;
1010 icd_libs->count = 0;
1011 icd_libs->list = NULL;
1012}
1013
Jon Ashburne58f1a32015-08-28 13:38:21 -06001014static void loader_scanned_icd_init(const struct loader_instance *inst,
1015 struct loader_icd_libs *icd_libs)
Jon Ashburn754f1992015-08-18 18:04:47 -06001016{
Jon Ashburne58f1a32015-08-28 13:38:21 -06001017 loader_scanned_icd_clear(inst, icd_libs);
Jon Ashburn754f1992015-08-18 18:04:47 -06001018 icd_libs->capacity = 8 * sizeof(struct loader_scanned_icds);
Jon Ashburne58f1a32015-08-28 13:38:21 -06001019 icd_libs->list = loader_heap_alloc(inst, icd_libs->capacity, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburn754f1992015-08-18 18:04:47 -06001020
1021}
1022
1023static void loader_scanned_icd_add(
Jon Ashburne58f1a32015-08-28 13:38:21 -06001024 const struct loader_instance *inst,
Jon Ashburn754f1992015-08-18 18:04:47 -06001025 struct loader_icd_libs *icd_libs,
1026 const char *filename)
Jon Ashburn14275da2015-01-28 11:01:35 -07001027{
Ian Elliott81ac44c2015-01-13 17:52:38 -07001028 loader_platform_dl_handle handle;
Tony Barbourde4124d2015-07-03 10:33:54 -06001029 PFN_vkCreateInstance fp_create_inst;
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -06001030 PFN_vkEnumerateInstanceExtensionProperties fp_get_global_ext_props;
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001031 PFN_vkGetInstanceProcAddr fp_get_proc_addr;
Jon Ashburn14275da2015-01-28 11:01:35 -07001032 struct loader_scanned_icds *new_node;
1033
Jon Ashburn754f1992015-08-18 18:04:47 -06001034 /* TODO implement ref counting of libraries, for now this function leaves
1035 libraries open and the scanned_icd_clear closes them */
Ian Elliott81ac44c2015-01-13 17:52:38 -07001036 // Used to call: dlopen(filename, RTLD_LAZY);
1037 handle = loader_platform_open_library(filename);
Jon Ashburn14275da2015-01-28 11:01:35 -07001038 if (!handle) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001039 loader_log(VK_DBG_REPORT_WARN_BIT, 0, loader_platform_open_library_error(filename));
Jon Ashburn14275da2015-01-28 11:01:35 -07001040 return;
1041 }
1042
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001043#define LOOKUP_LD(func_ptr, func) do { \
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -06001044 func_ptr = (PFN_vk ##func) loader_platform_get_proc_address(handle, "vk" #func); \
Jon Ashburn14275da2015-01-28 11:01:35 -07001045 if (!func_ptr) { \
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001046 loader_log(VK_DBG_REPORT_WARN_BIT, 0, loader_platform_get_proc_address_error("vk" #func)); \
Jon Ashburn14275da2015-01-28 11:01:35 -07001047 return; \
1048 } \
1049} while (0)
1050
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001051 LOOKUP_LD(fp_get_proc_addr, GetInstanceProcAddr);
1052 LOOKUP_LD(fp_create_inst, CreateInstance);
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -06001053 LOOKUP_LD(fp_get_global_ext_props, EnumerateInstanceExtensionProperties);
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001054
1055#undef LOOKUP_LD
Jon Ashburn14275da2015-01-28 11:01:35 -07001056
Jon Ashburn754f1992015-08-18 18:04:47 -06001057 // check for enough capacity
1058 if ((icd_libs->count * sizeof(struct loader_scanned_icds)) >= icd_libs->capacity) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06001059
1060 icd_libs->list = loader_heap_realloc(inst,
1061 icd_libs->list,
1062 icd_libs->capacity,
1063 icd_libs->capacity * 2,
1064 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburn754f1992015-08-18 18:04:47 -06001065 // double capacity
1066 icd_libs->capacity *= 2;
Jon Ashburn14275da2015-01-28 11:01:35 -07001067 }
Jon Ashburn754f1992015-08-18 18:04:47 -06001068 new_node = &(icd_libs->list[icd_libs->count]);
Jon Ashburn14275da2015-01-28 11:01:35 -07001069
1070 new_node->handle = handle;
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001071 new_node->GetInstanceProcAddr = fp_get_proc_addr;
Jon Ashburn3336df82015-01-29 15:45:51 -07001072 new_node->CreateInstance = fp_create_inst;
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -06001073 new_node->EnumerateInstanceExtensionProperties = fp_get_global_ext_props;
Jon Ashburn14275da2015-01-28 11:01:35 -07001074
Jon Ashburne58f1a32015-08-28 13:38:21 -06001075 new_node->lib_name = (char *) loader_heap_alloc(inst,
1076 strlen(filename) + 1,
1077 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001078 if (!new_node->lib_name) {
1079 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Out of memory can't add icd");
1080 return;
1081 }
1082 strcpy(new_node->lib_name, filename);
Jon Ashburn754f1992015-08-18 18:04:47 -06001083 icd_libs->count++;
Jon Ashburneb2728b2015-04-10 14:33:07 -06001084}
Ian Elliott81ac44c2015-01-13 17:52:38 -07001085
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001086static bool loader_icd_init_entrys(struct loader_icd *icd,
1087 VkInstance inst,
1088 const PFN_vkGetInstanceProcAddr fp_gipa)
Jon Ashburn0dd356d2015-05-14 12:43:38 -06001089{
1090 /* initialize entrypoint function pointers */
1091
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001092 #define LOOKUP_GIPA(func, required) do { \
1093 icd->func = (PFN_vk ##func) fp_gipa(inst, "vk" #func); \
1094 if (!icd->func && required) { \
1095 loader_log(VK_DBG_REPORT_WARN_BIT, 0, \
1096 loader_platform_get_proc_address_error("vk" #func)); \
1097 return false; \
1098 } \
Jon Ashburn0dd356d2015-05-14 12:43:38 -06001099 } while (0)
1100
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001101 LOOKUP_GIPA(GetDeviceProcAddr, true);
1102 LOOKUP_GIPA(DestroyInstance, true);
1103 LOOKUP_GIPA(EnumeratePhysicalDevices, true);
1104 LOOKUP_GIPA(GetPhysicalDeviceFeatures, true);
1105 LOOKUP_GIPA(GetPhysicalDeviceFormatProperties, true);
Jon Ashburn4e189562015-07-23 18:49:07 -06001106 LOOKUP_GIPA(GetPhysicalDeviceImageFormatProperties, true);
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001107 LOOKUP_GIPA(CreateDevice, true);
1108 LOOKUP_GIPA(GetPhysicalDeviceProperties, true);
1109 LOOKUP_GIPA(GetPhysicalDeviceMemoryProperties, true);
Cody Northropef72e2a2015-08-03 17:04:53 -06001110 LOOKUP_GIPA(GetPhysicalDeviceQueueFamilyProperties, true);
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -06001111 LOOKUP_GIPA(EnumerateDeviceExtensionProperties, true);
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001112 LOOKUP_GIPA(GetPhysicalDeviceSparseImageFormatProperties, true);
1113 LOOKUP_GIPA(DbgCreateMsgCallback, false);
1114 LOOKUP_GIPA(DbgDestroyMsgCallback, false);
Ian Elliott338dedb2015-08-21 15:09:33 -06001115 LOOKUP_GIPA(GetPhysicalDeviceSurfaceSupportKHR, false);
Jon Ashburn0dd356d2015-05-14 12:43:38 -06001116
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001117#undef LOOKUP_GIPA
Ian Elliott1d73e662015-07-06 14:36:13 -06001118
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001119 return true;
Jon Ashburn0dd356d2015-05-14 12:43:38 -06001120}
1121
Courtney Goeltzenleuchter8b253f92015-06-08 15:11:18 -06001122static void loader_debug_init(void)
1123{
1124 const char *env;
1125
1126 if (g_loader_debug > 0)
1127 return;
1128
1129 g_loader_debug = 0;
1130
1131 /* parse comma-separated debug options */
Courtney Goeltzenleuchter893f2872015-07-29 09:08:22 -06001132 env = getenv("VK_LOADER_DEBUG");
Courtney Goeltzenleuchter8b253f92015-06-08 15:11:18 -06001133 while (env) {
1134 const char *p = strchr(env, ',');
1135 size_t len;
1136
1137 if (p)
1138 len = p - env;
1139 else
1140 len = strlen(env);
1141
1142 if (len > 0) {
1143 if (strncmp(env, "warn", len) == 0) {
1144 g_loader_debug |= LOADER_WARN_BIT;
1145 g_loader_log_msgs |= VK_DBG_REPORT_WARN_BIT;
1146 } else if (strncmp(env, "info", len) == 0) {
1147 g_loader_debug |= LOADER_INFO_BIT;
1148 g_loader_log_msgs |= VK_DBG_REPORT_INFO_BIT;
1149 } else if (strncmp(env, "perf", len) == 0) {
1150 g_loader_debug |= LOADER_PERF_BIT;
1151 g_loader_log_msgs |= VK_DBG_REPORT_PERF_WARN_BIT;
1152 } else if (strncmp(env, "error", len) == 0) {
1153 g_loader_debug |= LOADER_ERROR_BIT;
1154 g_loader_log_msgs |= VK_DBG_REPORT_ERROR_BIT;
1155 } else if (strncmp(env, "debug", len) == 0) {
1156 g_loader_debug |= LOADER_DEBUG_BIT;
1157 g_loader_log_msgs |= VK_DBG_REPORT_DEBUG_BIT;
1158 }
1159 }
1160
1161 if (!p)
1162 break;
1163
1164 env = p + 1;
1165 }
1166}
1167
Jon Ashburn754f1992015-08-18 18:04:47 -06001168void loader_initialize(void)
1169{
Jon Ashburnd02fc2c2015-09-22 13:11:00 -06001170 // initialize mutexs
Jon Ashburn754f1992015-08-18 18:04:47 -06001171 loader_platform_thread_create_mutex(&loader_lock);
Jon Ashburnd02fc2c2015-09-22 13:11:00 -06001172 loader_platform_thread_create_mutex(&loader_json_lock);
Jon Ashburn754f1992015-08-18 18:04:47 -06001173
1174 // initialize logging
1175 loader_debug_init();
Jon Ashburn413d6582015-08-28 15:19:27 -06001176
1177 // initial cJSON to use alloc callbacks
1178 cJSON_Hooks alloc_fns = {
1179 .malloc_fn = loader_tls_heap_alloc,
1180 .free_fn = loader_tls_heap_free,
1181 };
1182 cJSON_InitHooks(&alloc_fns);
Jon Ashburn754f1992015-08-18 18:04:47 -06001183}
1184
Jon Ashburnffd5d672015-06-29 11:25:34 -06001185struct loader_manifest_files {
1186 uint32_t count;
1187 char **filename_list;
1188};
1189
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06001190/**
Jon Ashburnffd5d672015-06-29 11:25:34 -06001191 * Get next file or dirname given a string list or registry key path
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06001192 *
1193 * \returns
Jon Ashburnffd5d672015-06-29 11:25:34 -06001194 * A pointer to first char in the next path.
1195 * The next path (or NULL) in the list is returned in next_path.
1196 * Note: input string is modified in some cases. PASS IN A COPY!
1197 */
Jon Ashburnffd5d672015-06-29 11:25:34 -06001198static char *loader_get_next_path(char *path)
1199{
1200 uint32_t len;
1201 char *next;
1202
1203 if (path == NULL)
1204 return NULL;
1205 next = strchr(path, PATH_SEPERATOR);
1206 if (next == NULL) {
1207 len = (uint32_t) strlen(path);
1208 next = path + len;
1209 }
1210 else {
1211 *next = '\0';
1212 next++;
1213 }
1214
1215 return next;
1216}
1217
1218/**
Jon Ashburn38144502015-07-07 15:06:25 -06001219 * Given a path which is absolute or relative. Expand the path if relative otherwise
1220 * leave the path unmodified if absolute. The path which is relative from is
1221 * given in rel_base and should include trailing directory seperator '/'
1222 *
1223 * \returns
1224 * A string in out_fullpath of the full absolute path
1225 * Side effect is that dir string maybe modified.
1226 */
1227static void loader_expand_path(const char *path,
1228 const char *rel_base,
1229 size_t out_size,
1230 char *out_fullpath)
1231{
1232 if (loader_platform_is_path_absolute(path)) {
1233 strncpy(out_fullpath, path, out_size);
1234 out_fullpath[out_size - 1] = '\0';
1235 }
1236 else {
1237 // convert relative to absolute path based on rel_base
1238 size_t len = strlen(path);
1239 strncpy(out_fullpath, rel_base, out_size);
1240 out_fullpath[out_size - 1] = '\0';
1241 assert(out_size >= strlen(out_fullpath) + len + 1);
1242 strncat(out_fullpath, path, len);
1243 }
1244}
1245
1246/**
Jon Ashburnffd5d672015-06-29 11:25:34 -06001247 * Given a filename (file) and a list of paths (dir), try to find an existing
1248 * file in the paths. If filename already is a path then no
1249 * searching in the given paths.
1250 *
1251 * \returns
1252 * A string in out_fullpath of either the full path or file.
1253 * Side effect is that dir string maybe modified.
1254 */
1255static void loader_get_fullpath(const char *file,
1256 char *dir,
1257 size_t out_size,
1258 char *out_fullpath)
1259{
1260 char *next_dir;
1261 if (strchr(file,DIRECTORY_SYMBOL) == NULL) {
1262 //find file exists with prepending given path
1263 while (*dir) {
1264 next_dir = loader_get_next_path(dir);
1265 snprintf(out_fullpath, out_size, "%s%c%s",
1266 dir, DIRECTORY_SYMBOL, file);
1267 if (loader_platform_file_exists(out_fullpath)) {
1268 return;
1269 }
1270 dir = next_dir;
1271 }
1272 }
1273 snprintf(out_fullpath, out_size, "%s", file);
1274}
1275
1276/**
1277 * Read a JSON file into a buffer.
1278 *
1279 * \returns
1280 * A pointer to a cJSON object representing the JSON parse tree.
1281 * This returned buffer should be freed by caller.
1282 */
1283static cJSON *loader_get_json(const char *filename)
1284{
1285 FILE *file;
1286 char *json_buf;
1287 cJSON *json;
1288 uint64_t len;
1289 file = fopen(filename,"rb");
Jon Ashburna01fb3e2015-08-27 08:30:50 -06001290 if (!file) {
1291 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Couldn't open JSON file %s", filename);
1292 return NULL;
1293 }
Jon Ashburnffd5d672015-06-29 11:25:34 -06001294 fseek(file, 0, SEEK_END);
1295 len = ftell(file);
1296 fseek(file, 0, SEEK_SET);
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -06001297 json_buf = (char*) loader_stack_alloc(len+1);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001298 if (json_buf == NULL) {
1299 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get JSON file");
1300 fclose(file);
1301 return NULL;
1302 }
1303 if (fread(json_buf, sizeof(char), len, file) != len) {
1304 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "fread failed can't get JSON file");
1305 fclose(file);
1306 return NULL;
1307 }
1308 fclose(file);
1309 json_buf[len] = '\0';
1310
1311 //parse text from file
1312 json = cJSON_Parse(json_buf);
1313 if (json == NULL)
1314 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Can't parse JSON file %s", filename);
1315 return json;
1316}
1317
1318/**
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06001319 * Do a deep copy of the loader_layer_properties structure.
1320 */
1321static void loader_copy_layer_properties(
Jon Ashburne58f1a32015-08-28 13:38:21 -06001322 const struct loader_instance *inst,
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06001323 struct loader_layer_properties *dst,
1324 struct loader_layer_properties *src)
1325{
1326 memcpy(dst, src, sizeof (*src));
Jon Ashburne58f1a32015-08-28 13:38:21 -06001327 dst->instance_extension_list.list = loader_heap_alloc(
1328 inst,
1329 sizeof(VkExtensionProperties) *
1330 src->instance_extension_list.count,
1331 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
1332 dst->instance_extension_list.capacity = sizeof(VkExtensionProperties) *
1333 src->instance_extension_list.count;
1334 memcpy(dst->instance_extension_list.list, src->instance_extension_list.list,
1335 dst->instance_extension_list.capacity);
1336 dst->device_extension_list.list = loader_heap_alloc(
1337 inst,
1338 sizeof(VkExtensionProperties) *
1339 src->device_extension_list.count,
1340 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
1341 dst->device_extension_list.capacity = sizeof(VkExtensionProperties) *
1342 src->device_extension_list.count;
1343 memcpy(dst->device_extension_list.list, src->device_extension_list.list,
1344 dst->device_extension_list.capacity);
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06001345}
1346
1347/**
Jon Ashburn1b111de2015-07-06 15:40:35 -06001348 * Given a cJSON struct (json) of the top level JSON object from layer manifest
1349 * file, add entry to the layer_list.
Jon Ashburn8e4fab42015-08-03 17:19:30 -06001350 * Fill out the layer_properties in this list entry from the input cJSON object.
Jon Ashburn1b111de2015-07-06 15:40:35 -06001351 *
1352 * \returns
1353 * void
1354 * layer_list has a new entry and initialized accordingly.
1355 * If the json input object does not have all the required fields no entry
1356 * is added to the list.
1357 */
Jon Ashburne58f1a32015-08-28 13:38:21 -06001358static void loader_add_layer_properties(const struct loader_instance *inst,
1359 struct loader_layer_list *layer_instance_list,
Jon Ashburn0bf6a182015-07-16 17:19:31 -06001360 struct loader_layer_list *layer_device_list,
Jon Ashburn1b111de2015-07-06 15:40:35 -06001361 cJSON *json,
1362 bool is_implicit,
1363 char *filename)
1364{
1365 /* Fields in layer manifest file that are required:
1366 * (required) “file_format_version”
1367 * following are required in the "layer" object:
1368 * (required) "name"
1369 * (required) "type"
1370 * (required) “library_path”
1371 * (required) “abi_versions”
1372 * (required) “implementation_version”
1373 * (required) “description”
1374 * (required for implicit layers) “disable_environment”
1375 *
1376 * First get all required items and if any missing abort
1377 */
1378
1379 cJSON *item, *layer_node, *ext_item;
1380 char *temp;
1381 char *name, *type, *library_path, *abi_versions;
1382 char *implementation_version, *description;
1383 cJSON *disable_environment;
1384 int i;
Jon Ashburnc4748dc2015-08-04 11:14:18 -06001385 VkExtensionProperties ext_prop;
Jon Ashburn1b111de2015-07-06 15:40:35 -06001386 item = cJSON_GetObjectItem(json, "file_format_version");
1387 if (item == NULL) {
1388 return;
1389 }
1390 char *file_vers = cJSON_PrintUnformatted(item);
1391 loader_log(VK_DBG_REPORT_INFO_BIT, 0, "Found manifest file %s, version %s",
1392 filename, file_vers);
1393 if (strcmp(file_vers, "\"0.9.0\"") != 0)
Jon Ashburn8e4fab42015-08-03 17:19:30 -06001394 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 -06001395 loader_tls_heap_free(file_vers);
Jon Ashburn1b111de2015-07-06 15:40:35 -06001396
Jon Ashburn1b111de2015-07-06 15:40:35 -06001397 layer_node = cJSON_GetObjectItem(json, "layer");
1398 if (layer_node == NULL) {
1399 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"layer\" object in manifest JSON file, skipping");
1400 return;
1401 }
Jon Ashburn082569b2015-08-12 16:39:32 -06001402
1403 // loop through all "layer" objects in the file
1404 do {
Jon Ashburn1b111de2015-07-06 15:40:35 -06001405#define GET_JSON_OBJECT(node, var) { \
1406 var = cJSON_GetObjectItem(node, #var); \
Jon Ashburn082569b2015-08-12 16:39:32 -06001407 if (var == NULL) { \
1408 layer_node = layer_node->next; \
1409 continue; \
1410 } \
Jon Ashburn1b111de2015-07-06 15:40:35 -06001411 }
1412#define GET_JSON_ITEM(node, var) { \
1413 item = cJSON_GetObjectItem(node, #var); \
Jon Ashburn082569b2015-08-12 16:39:32 -06001414 if (item == NULL) { \
1415 layer_node = layer_node->next; \
1416 continue; \
1417 } \
Jon Ashburn1b111de2015-07-06 15:40:35 -06001418 temp = cJSON_Print(item); \
1419 temp[strlen(temp) - 1] = '\0'; \
Jon Ashburn0b728052015-08-04 10:22:33 -06001420 var = loader_stack_alloc(strlen(temp) + 1); \
Jon Ashburn1b111de2015-07-06 15:40:35 -06001421 strcpy(var, &temp[1]); \
Jon Ashburn413d6582015-08-28 15:19:27 -06001422 loader_tls_heap_free(temp); \
Jon Ashburn1b111de2015-07-06 15:40:35 -06001423 }
Jon Ashburn082569b2015-08-12 16:39:32 -06001424 GET_JSON_ITEM(layer_node, name)
1425 GET_JSON_ITEM(layer_node, type)
1426 GET_JSON_ITEM(layer_node, library_path)
1427 GET_JSON_ITEM(layer_node, abi_versions)
1428 GET_JSON_ITEM(layer_node, implementation_version)
1429 GET_JSON_ITEM(layer_node, description)
1430 if (is_implicit) {
1431 GET_JSON_OBJECT(layer_node, disable_environment)
1432 }
Jon Ashburn1b111de2015-07-06 15:40:35 -06001433#undef GET_JSON_ITEM
1434#undef GET_JSON_OBJECT
1435
Jon Ashburn082569b2015-08-12 16:39:32 -06001436 // add list entry
Jon Ashburnb8605fe2015-09-18 12:53:16 -06001437 struct loader_layer_properties *props=NULL;
Jon Ashburn082569b2015-08-12 16:39:32 -06001438 if (!strcmp(type, "DEVICE")) {
1439 if (layer_device_list == NULL) {
1440 layer_node = layer_node->next;
1441 continue;
1442 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06001443 props = loader_get_next_layer_property(inst, layer_device_list);
Jon Ashburn082569b2015-08-12 16:39:32 -06001444 props->type = (is_implicit) ? VK_LAYER_TYPE_DEVICE_IMPLICIT : VK_LAYER_TYPE_DEVICE_EXPLICIT;
1445 }
1446 if (!strcmp(type, "INSTANCE")) {
1447 if (layer_instance_list == NULL) {
1448 layer_node = layer_node->next;
1449 continue;
1450 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06001451 props = loader_get_next_layer_property(inst, layer_instance_list);
Jon Ashburn082569b2015-08-12 16:39:32 -06001452 props->type = (is_implicit) ? VK_LAYER_TYPE_INSTANCE_IMPLICIT : VK_LAYER_TYPE_INSTANCE_EXPLICIT;
1453 }
1454 if (!strcmp(type, "GLOBAL")) {
1455 if (layer_instance_list != NULL)
Jon Ashburne58f1a32015-08-28 13:38:21 -06001456 props = loader_get_next_layer_property(inst, layer_instance_list);
Jon Ashburn082569b2015-08-12 16:39:32 -06001457 else if (layer_device_list != NULL)
Jon Ashburne58f1a32015-08-28 13:38:21 -06001458 props = loader_get_next_layer_property(inst, layer_device_list);
Jon Ashburn082569b2015-08-12 16:39:32 -06001459 else {
1460 layer_node = layer_node->next;
1461 continue;
1462 }
1463 props->type = (is_implicit) ? VK_LAYER_TYPE_GLOBAL_IMPLICIT : VK_LAYER_TYPE_GLOBAL_EXPLICIT;
1464 }
Jon Ashburn0bf6a182015-07-16 17:19:31 -06001465
Jon Ashburnb8605fe2015-09-18 12:53:16 -06001466 if (props == NULL) {
1467 layer_node = layer_node->next;
1468 continue;
1469 }
1470
Jon Ashburn082569b2015-08-12 16:39:32 -06001471 strncpy(props->info.layerName, name, sizeof (props->info.layerName));
1472 props->info.layerName[sizeof (props->info.layerName) - 1] = '\0';
Jon Ashburn38144502015-07-07 15:06:25 -06001473
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06001474 char *fullpath = props->lib_name;
Jon Ashburn082569b2015-08-12 16:39:32 -06001475 char *rel_base;
1476 if (strchr(library_path, DIRECTORY_SYMBOL) == NULL) {
1477 // a filename which is assumed in the system directory
1478 char *def_path = loader_stack_alloc(strlen(DEFAULT_VK_LAYERS_PATH) + 1);
1479 strcpy(def_path, DEFAULT_VK_LAYERS_PATH);
1480 loader_get_fullpath(library_path, def_path, MAX_STRING_SIZE, fullpath);
1481 } else {
1482 // a relative or absolute path
1483 char *name_copy = loader_stack_alloc(strlen(filename) + 2);
1484 size_t len;
1485 strcpy(name_copy, filename);
1486 rel_base = loader_platform_dirname(name_copy);
1487 len = strlen(rel_base);
1488 rel_base[len] = DIRECTORY_SYMBOL;
1489 rel_base[len + 1] = '\0';
1490 loader_expand_path(library_path, rel_base, MAX_STRING_SIZE, fullpath);
1491 }
Jon Ashburn082569b2015-08-12 16:39:32 -06001492 props->info.specVersion = loader_make_version(abi_versions);
1493 props->info.implVersion = loader_make_version(implementation_version);
1494 strncpy((char *) props->info.description, description, sizeof (props->info.description));
1495 props->info.description[sizeof (props->info.description) - 1] = '\0';
1496 if (is_implicit) {
1497 strncpy(props->disable_env_var.name, disable_environment->child->string, sizeof (props->disable_env_var.name));
1498 props->disable_env_var.name[sizeof (props->disable_env_var.name) - 1] = '\0';
1499 strncpy(props->disable_env_var.value, disable_environment->child->valuestring, sizeof (props->disable_env_var.value));
1500 props->disable_env_var.value[sizeof (props->disable_env_var.value) - 1] = '\0';
1501 }
Jon Ashburn1b111de2015-07-06 15:40:35 -06001502
Jon Ashburn082569b2015-08-12 16:39:32 -06001503 /**
1504 * Now get all optional items and objects and put in list:
1505 * functions
1506 * instance_extensions
1507 * device_extensions
1508 * enable_environment (implicit layers only)
1509 */
Jon Ashburn1b111de2015-07-06 15:40:35 -06001510#define GET_JSON_OBJECT(node, var) { \
1511 var = cJSON_GetObjectItem(node, #var); \
1512 }
1513#define GET_JSON_ITEM(node, var) { \
1514 item = cJSON_GetObjectItem(node, #var); \
Jon Ashburn2db08042015-09-09 11:29:24 -06001515 if (item != NULL) { \
Jon Ashburn1b111de2015-07-06 15:40:35 -06001516 temp = cJSON_Print(item); \
Jon Ashburn2db08042015-09-09 11:29:24 -06001517 temp[strlen(temp) - 1] = '\0'; \
1518 var = loader_stack_alloc(strlen(temp) + 1);\
1519 strcpy(var, &temp[1]); \
1520 loader_tls_heap_free(temp); \
1521 } \
Jon Ashburn1b111de2015-07-06 15:40:35 -06001522 }
1523
Jon Ashburn082569b2015-08-12 16:39:32 -06001524 cJSON *instance_extensions, *device_extensions, *functions, *enable_environment;
Jon Ashburnb8605fe2015-09-18 12:53:16 -06001525 char *vkGetInstanceProcAddr = NULL, *vkGetDeviceProcAddr = NULL, *version=NULL;
Jon Ashburn082569b2015-08-12 16:39:32 -06001526 GET_JSON_OBJECT(layer_node, functions)
1527 if (functions != NULL) {
1528 GET_JSON_ITEM(functions, vkGetInstanceProcAddr)
1529 GET_JSON_ITEM(functions, vkGetDeviceProcAddr)
Jon Ashburn2db08042015-09-09 11:29:24 -06001530 if (vkGetInstanceProcAddr != NULL)
1531 strncpy(props->functions.str_gipa, vkGetInstanceProcAddr, sizeof (props->functions.str_gipa));
Jon Ashburn082569b2015-08-12 16:39:32 -06001532 props->functions.str_gipa[sizeof (props->functions.str_gipa) - 1] = '\0';
Jon Ashburn2db08042015-09-09 11:29:24 -06001533 if (vkGetDeviceProcAddr != NULL)
1534 strncpy(props->functions.str_gdpa, vkGetDeviceProcAddr, sizeof (props->functions.str_gdpa));
Jon Ashburn082569b2015-08-12 16:39:32 -06001535 props->functions.str_gdpa[sizeof (props->functions.str_gdpa) - 1] = '\0';
Jon Ashburn1b111de2015-07-06 15:40:35 -06001536 }
Jon Ashburn082569b2015-08-12 16:39:32 -06001537 GET_JSON_OBJECT(layer_node, instance_extensions)
1538 if (instance_extensions != NULL) {
1539 int count = cJSON_GetArraySize(instance_extensions);
1540 for (i = 0; i < count; i++) {
1541 ext_item = cJSON_GetArrayItem(instance_extensions, i);
1542 GET_JSON_ITEM(ext_item, name)
1543 GET_JSON_ITEM(ext_item, version)
1544 strncpy(ext_prop.extName, name, sizeof (ext_prop.extName));
1545 ext_prop.extName[sizeof (ext_prop.extName) - 1] = '\0';
1546 ext_prop.specVersion = loader_make_version(version);
Jon Ashburne58f1a32015-08-28 13:38:21 -06001547 loader_add_to_ext_list(inst, &props->instance_extension_list, 1, &ext_prop);
Jon Ashburn082569b2015-08-12 16:39:32 -06001548 }
Jon Ashburn1b111de2015-07-06 15:40:35 -06001549 }
Jon Ashburn082569b2015-08-12 16:39:32 -06001550 GET_JSON_OBJECT(layer_node, device_extensions)
1551 if (device_extensions != NULL) {
1552 int count = cJSON_GetArraySize(device_extensions);
1553 for (i = 0; i < count; i++) {
1554 ext_item = cJSON_GetArrayItem(device_extensions, i);
1555 GET_JSON_ITEM(ext_item, name);
1556 GET_JSON_ITEM(ext_item, version);
1557 strncpy(ext_prop.extName, name, sizeof (ext_prop.extName));
1558 ext_prop.extName[sizeof (ext_prop.extName) - 1] = '\0';
1559 ext_prop.specVersion = loader_make_version(version);
Jon Ashburne58f1a32015-08-28 13:38:21 -06001560 loader_add_to_ext_list(inst, &props->device_extension_list, 1, &ext_prop);
Jon Ashburn082569b2015-08-12 16:39:32 -06001561 }
1562 }
1563 if (is_implicit) {
1564 GET_JSON_OBJECT(layer_node, enable_environment)
1565 strncpy(props->enable_env_var.name, enable_environment->child->string, sizeof (props->enable_env_var.name));
1566 props->enable_env_var.name[sizeof (props->enable_env_var.name) - 1] = '\0';
1567 strncpy(props->enable_env_var.value, enable_environment->child->valuestring, sizeof (props->enable_env_var.value));
1568 props->enable_env_var.value[sizeof (props->enable_env_var.value) - 1] = '\0';
1569 }
Jon Ashburn1b111de2015-07-06 15:40:35 -06001570#undef GET_JSON_ITEM
1571#undef GET_JSON_OBJECT
Jon Ashburn082569b2015-08-12 16:39:32 -06001572 // for global layers need to add them to both device and instance list
1573 if (!strcmp(type, "GLOBAL")) {
1574 struct loader_layer_properties *dev_props;
1575 if (layer_instance_list == NULL || layer_device_list == NULL) {
1576 layer_node = layer_node->next;
1577 continue;
1578 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06001579 dev_props = loader_get_next_layer_property(inst, layer_device_list);
Jon Ashburn082569b2015-08-12 16:39:32 -06001580 //copy into device layer list
Jon Ashburne58f1a32015-08-28 13:38:21 -06001581 loader_copy_layer_properties(inst, dev_props, props);
Jon Ashburn082569b2015-08-12 16:39:32 -06001582 }
1583 layer_node = layer_node->next;
1584 } while (layer_node != NULL);
1585 return;
Jon Ashburn1b111de2015-07-06 15:40:35 -06001586}
1587
1588/**
Jon Ashburnffd5d672015-06-29 11:25:34 -06001589 * Find the Vulkan library manifest files.
1590 *
1591 * This function scans the location or env_override directories/files
1592 * for a list of JSON manifest files. If env_override is non-NULL
1593 * and has a valid value. Then the location is ignored. Otherwise
1594 * location is used to look for manifest files. The location
1595 * is interpreted as Registry path on Windows and a directory path(s)
1596 * on Linux.
1597 *
1598 * \returns
1599 * A string list of manifest files to be opened in out_files param.
1600 * List has a pointer to string for each manifest filename.
1601 * When done using the list in out_files, pointers should be freed.
Jon Ashburnee33ae72015-06-30 14:46:22 -07001602 * Location or override string lists can be either files or directories as follows:
1603 * | location | override
1604 * --------------------------------
1605 * Win ICD | files | files
1606 * Win Layer | files | dirs
1607 * Linux ICD | dirs | files
1608 * Linux Layer| dirs | dirs
Jon Ashburnffd5d672015-06-29 11:25:34 -06001609 */
Jon Ashburne58f1a32015-08-28 13:38:21 -06001610static void loader_get_manifest_files(const struct loader_instance *inst,
1611 const char *env_override,
Jon Ashburnee33ae72015-06-30 14:46:22 -07001612 bool is_layer,
1613 const char *location,
1614 struct loader_manifest_files *out_files)
Jon Ashburnffd5d672015-06-29 11:25:34 -06001615{
1616 char *override = NULL;
1617 char *loc;
1618 char *file, *next_file, *name;
1619 size_t alloced_count = 64;
1620 char full_path[2048];
1621 DIR *sysdir = NULL;
Jon Ashburnee33ae72015-06-30 14:46:22 -07001622 bool list_is_dirs = false;
Jon Ashburnffd5d672015-06-29 11:25:34 -06001623 struct dirent *dent;
1624
1625 out_files->count = 0;
1626 out_files->filename_list = NULL;
1627
Jon Ashburnffd5d672015-06-29 11:25:34 -06001628 if (env_override != NULL && (override = getenv(env_override))) {
1629#if defined(__linux__)
1630 if (geteuid() != getuid()) {
Jon Ashburnee33ae72015-06-30 14:46:22 -07001631 /* Don't allow setuid apps to use the env var: */
Jon Ashburnffd5d672015-06-29 11:25:34 -06001632 override = NULL;
1633 }
1634#endif
1635 }
1636
1637 if (location == NULL) {
1638 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
Jon Ashburnee33ae72015-06-30 14:46:22 -07001639 "Can't get manifest files with NULL location, env_override=%s",
1640 env_override);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001641 return;
1642 }
1643
Jon Ashburnee33ae72015-06-30 14:46:22 -07001644#if defined(__linux__)
1645 list_is_dirs = (override == NULL || is_layer) ? true : false;
1646#else //WIN32
1647 list_is_dirs = (is_layer && override != NULL) ? true : false;
1648#endif
Jon Ashburnffd5d672015-06-29 11:25:34 -06001649 // Make a copy of the input we are using so it is not modified
Jon Ashburnee33ae72015-06-30 14:46:22 -07001650 // Also handle getting the location(s) from registry on Windows
1651 if (override == NULL) {
Jon Ashburncdc9f0a2015-07-31 10:11:24 -06001652 loc = loader_stack_alloc(strlen(location) + 1);
Jon Ashburnee33ae72015-06-30 14:46:22 -07001653 if (loc == NULL) {
1654 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files");
1655 return;
1656 }
1657 strcpy(loc, location);
Jon Ashburnc1381ed2015-07-31 09:33:21 -06001658#if defined (_WIN32)
Jon Ashburn6fb9a532015-08-28 14:58:46 -07001659 loc = loader_get_registry_files(inst, loc);
Jon Ashburnc1381ed2015-07-31 09:33:21 -06001660 if (loc == NULL) {
1661 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Registry lookup failed can't get manifest files");
1662 return;
1663 }
Jon Ashburnee33ae72015-06-30 14:46:22 -07001664#endif
Jon Ashburnffd5d672015-06-29 11:25:34 -06001665 }
Jon Ashburnee33ae72015-06-30 14:46:22 -07001666 else {
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -06001667 loc = loader_stack_alloc(strlen(override) + 1);
Jon Ashburnee33ae72015-06-30 14:46:22 -07001668 if (loc == NULL) {
1669 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files");
1670 return;
1671 }
1672 strcpy(loc, override);
1673 }
Jon Ashburnffd5d672015-06-29 11:25:34 -06001674
Liam Middlebrookf2a6ec42015-07-23 18:32:20 -07001675 // Print out the paths being searched if debugging is enabled
Jon Ashburn6ff63e42015-07-31 09:41:31 -06001676 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 -07001677
Jon Ashburnffd5d672015-06-29 11:25:34 -06001678 file = loc;
1679 while (*file) {
1680 next_file = loader_get_next_path(file);
Jon Ashburnee33ae72015-06-30 14:46:22 -07001681 if (list_is_dirs) {
Jon Ashburnffd5d672015-06-29 11:25:34 -06001682 sysdir = opendir(file);
1683 name = NULL;
1684 if (sysdir) {
1685 dent = readdir(sysdir);
1686 if (dent == NULL)
1687 break;
1688 name = &(dent->d_name[0]);
1689 loader_get_fullpath(name, file, sizeof(full_path), full_path);
1690 name = full_path;
1691 }
1692 }
1693 else {
Jon Ashburnee33ae72015-06-30 14:46:22 -07001694#if defined(__linux__)
1695 // only Linux has relative paths
Jon Ashburnffd5d672015-06-29 11:25:34 -06001696 char *dir;
1697 // make a copy of location so it isn't modified
Jason Ekstrand35fa1a12015-10-10 08:33:37 -07001698 dir = loader_stack_alloc(strlen(loc) + 1);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001699 if (dir == NULL) {
1700 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files");
1701 return;
1702 }
Jason Ekstrand35fa1a12015-10-10 08:33:37 -07001703 strcpy(dir, loc);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001704
1705 loader_get_fullpath(file, dir, sizeof(full_path), full_path);
1706
1707 name = full_path;
Jon Ashburnee33ae72015-06-30 14:46:22 -07001708#else // WIN32
1709 name = file;
1710#endif
Jon Ashburnffd5d672015-06-29 11:25:34 -06001711 }
1712 while (name) {
1713 /* Look for files ending with ".json" suffix */
1714 uint32_t nlen = (uint32_t) strlen(name);
1715 const char *suf = name + nlen - 5;
1716 if ((nlen > 5) && !strncmp(suf, ".json", 5)) {
1717 if (out_files->count == 0) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06001718 out_files->filename_list = loader_heap_alloc(inst,
1719 alloced_count * sizeof(char *),
1720 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001721 }
1722 else if (out_files->count == alloced_count) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06001723 out_files->filename_list = loader_heap_realloc(inst,
1724 out_files->filename_list,
1725 alloced_count * sizeof(char *),
1726 alloced_count * sizeof(char *) * 2,
1727 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001728 alloced_count *= 2;
1729 }
1730 if (out_files->filename_list == NULL) {
1731 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't alloc manifest file list");
1732 return;
1733 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06001734 out_files->filename_list[out_files->count] = loader_heap_alloc(
1735 inst,
1736 strlen(name) + 1,
1737 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001738 if (out_files->filename_list[out_files->count] == NULL) {
1739 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files");
1740 return;
1741 }
1742 strcpy(out_files->filename_list[out_files->count], name);
1743 out_files->count++;
Jon Ashburnc5662f62015-07-02 10:08:47 -06001744 } else if (!list_is_dirs) {
1745 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 -06001746 }
Jon Ashburnee33ae72015-06-30 14:46:22 -07001747 if (list_is_dirs) {
Jon Ashburnffd5d672015-06-29 11:25:34 -06001748 dent = readdir(sysdir);
1749 if (dent == NULL)
1750 break;
1751 name = &(dent->d_name[0]);
1752 loader_get_fullpath(name, file, sizeof(full_path), full_path);
1753 name = full_path;
1754 }
1755 else {
1756 break;
1757 }
1758 }
1759 if (sysdir)
1760 closedir(sysdir);
1761 file = next_file;
1762 }
1763 return;
1764}
1765
Jon Ashburn754f1992015-08-18 18:04:47 -06001766void loader_init_icd_lib_list()
1767{
1768
1769}
1770
1771void loader_destroy_icd_lib_list()
1772{
1773
1774}
Jon Ashburnffd5d672015-06-29 11:25:34 -06001775/**
1776 * Try to find the Vulkan ICD driver(s).
1777 *
1778 * This function scans the default system loader path(s) or path
1779 * specified by the \c VK_ICD_FILENAMES environment variable in
1780 * order to find loadable VK ICDs manifest files. From these
1781 * manifest files it finds the ICD libraries.
1782 *
1783 * \returns
Jon Ashburn754f1992015-08-18 18:04:47 -06001784 * a list of icds that were discovered
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06001785 */
Jon Ashburne58f1a32015-08-28 13:38:21 -06001786void loader_icd_scan(
1787 const struct loader_instance *inst,
1788 struct loader_icd_libs *icds)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001789{
Jon Ashburnffd5d672015-06-29 11:25:34 -06001790 char *file_str;
1791 struct loader_manifest_files manifest_files;
1792
Jon Ashburne58f1a32015-08-28 13:38:21 -06001793 loader_scanned_icd_init(inst, icds);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001794 // Get a list of manifest files for ICDs
Jon Ashburne58f1a32015-08-28 13:38:21 -06001795 loader_get_manifest_files(inst, "VK_ICD_FILENAMES", false,
1796 DEFAULT_VK_DRIVERS_INFO, &manifest_files);
Jon Ashburn1b111de2015-07-06 15:40:35 -06001797 if (manifest_files.count == 0)
1798 return;
Jon Ashburnd02fc2c2015-09-22 13:11:00 -06001799 loader_platform_thread_lock_mutex(&loader_json_lock);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001800 for (uint32_t i = 0; i < manifest_files.count; i++) {
1801 file_str = manifest_files.filename_list[i];
1802 if (file_str == NULL)
1803 continue;
1804
Jon Ashburn1b111de2015-07-06 15:40:35 -06001805 cJSON *json;
Jon Ashburnffd5d672015-06-29 11:25:34 -06001806 json = loader_get_json(file_str);
Jon Ashburna01fb3e2015-08-27 08:30:50 -06001807 if (!json)
1808 continue;
Jon Ashburn1b111de2015-07-06 15:40:35 -06001809 cJSON *item;
1810 item = cJSON_GetObjectItem(json, "file_format_version");
Jon Ashburnd02fc2c2015-09-22 13:11:00 -06001811 if (item == NULL) {
1812 loader_platform_thread_unlock_mutex(&loader_json_lock);
Jon Ashburn1b111de2015-07-06 15:40:35 -06001813 return;
Jon Ashburnd02fc2c2015-09-22 13:11:00 -06001814 }
Jon Ashburn1b111de2015-07-06 15:40:35 -06001815 char *file_vers = cJSON_Print(item);
1816 loader_log(VK_DBG_REPORT_INFO_BIT, 0, "Found manifest file %s, version %s",
1817 file_str, file_vers);
1818 if (strcmp(file_vers, "\"1.0.0\"") != 0)
1819 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 -06001820 loader_tls_heap_free(file_vers);
Jon Ashburn1b111de2015-07-06 15:40:35 -06001821 item = cJSON_GetObjectItem(json, "ICD");
1822 if (item != NULL) {
1823 item = cJSON_GetObjectItem(item, "library_path");
1824 if (item != NULL) {
Jon Ashburn10442c12015-08-25 16:48:24 -06001825 char *temp= cJSON_Print(item);
1826 if (!temp || strlen(temp) == 0) {
1827 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 -06001828 loader_tls_heap_free(temp);
Jon Ashburne58f1a32015-08-28 13:38:21 -06001829 loader_heap_free(inst, file_str);
Jon Ashburn10442c12015-08-25 16:48:24 -06001830 cJSON_Delete(json);
1831 continue;
Jon Ashburnffd5d672015-06-29 11:25:34 -06001832 }
Jon Ashburn10442c12015-08-25 16:48:24 -06001833 //strip out extra quotes
1834 temp[strlen(temp) - 1] = '\0';
1835 char *library_path = loader_stack_alloc(strlen(temp) + 1);
1836 strcpy(library_path, &temp[1]);
Jon Ashburn413d6582015-08-28 15:19:27 -06001837 loader_tls_heap_free(temp);
Jon Ashburn10442c12015-08-25 16:48:24 -06001838 if (!library_path || strlen(library_path) == 0) {
1839 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 -06001840 loader_heap_free(inst, file_str);
Jon Ashburn10442c12015-08-25 16:48:24 -06001841 cJSON_Delete(json);
1842 continue;
1843 }
1844 char *fullpath;
Courtney Goeltzenleuchtera2f21d02015-10-07 09:00:34 -06001845 size_t path_len;
Jon Ashburn10442c12015-08-25 16:48:24 -06001846 char *rel_base;
1847 // Print out the paths being searched if debugging is enabled
1848 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, "Searching for ICD drivers named %s default dir %s\n", library_path, DEFAULT_VK_DRIVERS_PATH);
1849 if (strchr(library_path, DIRECTORY_SYMBOL) == NULL) {
1850 // a filename which is assumed in the system directory
1851 char *def_path = loader_stack_alloc(strlen(DEFAULT_VK_DRIVERS_PATH) + 1);
1852 strcpy(def_path, DEFAULT_VK_DRIVERS_PATH);
1853 path_len = strlen(DEFAULT_VK_DRIVERS_PATH) + strlen(library_path) + 2;
1854 fullpath = loader_stack_alloc(path_len);
1855#if defined(__linux__)
1856 loader_get_fullpath(library_path, def_path, path_len, fullpath);
1857#else // WIN32
1858 strncpy(fullpath, library_path, sizeof (fullpath));
1859 fullpath[sizeof (fullpath) - 1] = '\0';
1860#endif
1861 } else {
1862 // a relative or absolute path
1863 char *name_copy = loader_stack_alloc(strlen(file_str) + 2);
1864 size_t len;
1865 strcpy(name_copy, file_str);
1866 rel_base = loader_platform_dirname(name_copy);
1867 len = strlen(rel_base);
1868 rel_base[len] = DIRECTORY_SYMBOL;
1869 rel_base[len + 1] = '\0';
1870 path_len = strlen(rel_base) + strlen(library_path) + 2;
1871 fullpath = loader_stack_alloc(path_len);
1872 loader_expand_path(library_path, rel_base, path_len, fullpath);
1873 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06001874 loader_scanned_icd_add(inst, icds, fullpath);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001875 }
Jon Ashburn10442c12015-08-25 16:48:24 -06001876
Jon Ashburnffd5d672015-06-29 11:25:34 -06001877 }
1878 else
1879 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"ICD\" object in ICD JSON file %s, skipping", file_str);
1880
Jon Ashburne58f1a32015-08-28 13:38:21 -06001881 loader_heap_free(inst, file_str);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001882 cJSON_Delete(json);
1883 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06001884 loader_heap_free(inst, manifest_files.filename_list);
Jon Ashburnd02fc2c2015-09-22 13:11:00 -06001885 loader_platform_thread_unlock_mutex(&loader_json_lock);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001886}
1887
Jon Ashburnd43f9b62014-10-14 19:15:22 -06001888
Jon Ashburne58f1a32015-08-28 13:38:21 -06001889void loader_layer_scan(
1890 const struct loader_instance *inst,
1891 struct loader_layer_list *instance_layers,
1892 struct loader_layer_list *device_layers)
Jon Ashburnd43f9b62014-10-14 19:15:22 -06001893{
Jon Ashburn1b111de2015-07-06 15:40:35 -06001894 char *file_str;
1895 struct loader_manifest_files manifest_files;
1896 cJSON *json;
1897 uint32_t i;
Jon Ashburnd43f9b62014-10-14 19:15:22 -06001898
Jon Ashburn1b111de2015-07-06 15:40:35 -06001899 // Get a list of manifest files for layers
Jon Ashburne58f1a32015-08-28 13:38:21 -06001900 loader_get_manifest_files(inst, LAYERS_PATH_ENV, true, DEFAULT_VK_LAYERS_INFO,
Jon Ashburn1b111de2015-07-06 15:40:35 -06001901 &manifest_files);
1902 if (manifest_files.count == 0)
Courtney Goeltzenleuchterbce445a2014-12-01 09:29:42 -07001903 return;
Jon Ashburn0dcd6192015-06-04 15:30:58 -06001904
Jon Ashburn8e4fab42015-08-03 17:19:30 -06001905#if 0 //TODO
Jon Ashburn1b111de2015-07-06 15:40:35 -06001906 /**
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -06001907 * We need a list of the layer libraries, not just a list of
1908 * the layer properties (a layer library could expose more than
1909 * one layer property). This list of scanned layers would be
1910 * used to check for global and physicaldevice layer properties.
1911 */
1912 if (!loader_init_layer_library_list(&loader.scanned_layer_libraries)) {
1913 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
Jon Ashburne58f1a32015-08-28 13:38:21 -06001914 "Alloc for layer list failed: %s line: %d", __FILE__, __LINE__);
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -06001915 return;
Jon Ashburn68a63922015-07-02 09:40:15 -06001916 }
Jon Ashburn1b111de2015-07-06 15:40:35 -06001917#endif
Jon Ashburnd43f9b62014-10-14 19:15:22 -06001918
Jon Ashburn8e4fab42015-08-03 17:19:30 -06001919 /* cleanup any previously scanned libraries */
Jon Ashburne58f1a32015-08-28 13:38:21 -06001920 loader_delete_layer_properties(inst, instance_layers);
1921 loader_delete_layer_properties(inst, device_layers);
Jon Ashburn0bf6a182015-07-16 17:19:31 -06001922
Jon Ashburnd02fc2c2015-09-22 13:11:00 -06001923 loader_platform_thread_lock_mutex(&loader_json_lock);
Jon Ashburn1b111de2015-07-06 15:40:35 -06001924 for (i = 0; i < manifest_files.count; i++) {
1925 file_str = manifest_files.filename_list[i];
1926 if (file_str == NULL)
1927 continue;
Courtney Goeltzenleuchteraa685052015-06-01 14:49:17 -06001928
Jon Ashburn1b111de2015-07-06 15:40:35 -06001929 // parse file into JSON struct
1930 json = loader_get_json(file_str);
1931 if (!json) {
1932 continue;
1933 }
Jon Ashburn8e4fab42015-08-03 17:19:30 -06001934
Jon Ashburn1b111de2015-07-06 15:40:35 -06001935 //TODO pass in implicit versus explicit bool
Jon Ashburn0bf6a182015-07-16 17:19:31 -06001936 //TODO error if device layers expose instance_extensions
1937 //TODO error if instance layers expose device extensions
Jon Ashburne58f1a32015-08-28 13:38:21 -06001938 loader_add_layer_properties(inst,
1939 instance_layers,
Jon Ashburn182b8302015-08-11 14:49:54 -06001940 device_layers,
Jon Ashburn0bf6a182015-07-16 17:19:31 -06001941 json,
1942 false,
1943 file_str);
1944
Jon Ashburne58f1a32015-08-28 13:38:21 -06001945 loader_heap_free(inst, file_str);
Jon Ashburn1b111de2015-07-06 15:40:35 -06001946 cJSON_Delete(json);
1947 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06001948 loader_heap_free(inst, manifest_files.filename_list);
Jon Ashburnd02fc2c2015-09-22 13:11:00 -06001949 loader_platform_thread_unlock_mutex(&loader_json_lock);
Jon Ashburnd43f9b62014-10-14 19:15:22 -06001950}
1951
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -06001952static PFN_vkVoidFunction VKAPI loader_gpa_instance_internal(VkInstance inst, const char * pName)
Jon Ashburnfce93d92015-05-12 17:26:48 -06001953{
1954 // inst is not wrapped
1955 if (inst == VK_NULL_HANDLE) {
1956 return NULL;
1957 }
1958 VkLayerInstanceDispatchTable* disp_table = * (VkLayerInstanceDispatchTable **) inst;
1959 void *addr;
1960
Jon Ashburn4f2575f2015-05-28 16:25:02 -06001961 if (!strcmp(pName, "vkGetInstanceProcAddr"))
1962 return (void *) loader_gpa_instance_internal;
1963
Jon Ashburnfce93d92015-05-12 17:26:48 -06001964 if (disp_table == NULL)
1965 return NULL;
1966
1967 addr = loader_lookup_instance_dispatch_table(disp_table, pName);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001968 if (addr) {
Jon Ashburnfce93d92015-05-12 17:26:48 -06001969 return addr;
Jon Ashburne18431b2015-04-13 18:10:06 -06001970 }
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001971
1972 if (disp_table->GetInstanceProcAddr == NULL) {
1973 return NULL;
1974 }
1975 return disp_table->GetInstanceProcAddr(inst, pName);
Jon Ashburne18431b2015-04-13 18:10:06 -06001976}
1977
Jon Ashburn0c5eea22015-09-30 12:56:42 -06001978struct loader_instance *loader_get_instance(const VkInstance instance)
1979{
1980 /* look up the loader_instance in our list by comparing dispatch tables, as
1981 * there is no guarantee the instance is still a loader_instance* after any
1982 * layers which wrap the instance object.
1983 */
1984 const VkLayerInstanceDispatchTable *disp;
1985 struct loader_instance *ptr_instance = NULL;
1986 disp = loader_get_instance_dispatch(instance);
1987 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
1988 if (inst->disp == disp) {
1989 ptr_instance = inst;
1990 break;
1991 }
1992 }
1993 return ptr_instance;
1994}
1995
Jon Ashburnd5df54d2015-05-28 19:16:58 -06001996struct loader_icd * loader_get_icd(const VkPhysicalDevice gpu, uint32_t *gpu_index)
Jon Ashburnb55278a2014-10-17 15:09:07 -06001997{
Jon Ashburnd5df54d2015-05-28 19:16:58 -06001998
Tony Barbour9687cb12015-07-14 13:34:05 -06001999 *gpu_index = 0;
Jon Ashburndc67ef52015-01-29 16:44:24 -07002000 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
2001 for (struct loader_icd *icd = inst->icds; icd; icd = icd->next) {
2002 for (uint32_t i = 0; i < icd->gpu_count; i++)
Jon Ashburn0c5eea22015-09-30 12:56:42 -06002003 /* Value comparison of VkPhysicalDevice prevents wrapping, use
2004 * instance device table instead (TODO this aliases GPUs within
2005 * an instance, since they have identical dispatch tables)
2006 */
2007 if (loader_get_instance_dispatch(icd->gpus[i]) == loader_get_instance_dispatch(gpu)) {
Jon Ashburndc67ef52015-01-29 16:44:24 -07002008 *gpu_index = i;
2009 return icd;
2010 }
2011 }
Jon Ashburnb55278a2014-10-17 15:09:07 -06002012 }
2013 return NULL;
2014}
2015
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002016static loader_platform_dl_handle loader_add_layer_lib(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002017 const struct loader_instance *inst,
Jon Ashburn9a9de1f2015-05-27 13:19:22 -06002018 const char *chain_type,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002019 struct loader_layer_properties *layer_prop)
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002020{
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002021 struct loader_lib_info *new_layer_lib_list, *my_lib;
Jon Ashburne58f1a32015-08-28 13:38:21 -06002022 size_t new_alloc_size;
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -06002023 /*
2024 * TODO: We can now track this information in the
2025 * scanned_layer_libraries list.
2026 */
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002027 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) {
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002028 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, layer_prop->lib_name) == 0) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002029 /* Have already loaded this library, just increment ref count */
2030 loader.loaded_layer_lib_list[i].ref_count++;
Courtney Goeltzenleuchter926f39e2015-06-14 11:59:07 -06002031 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002032 "%s Chain: Increment layer reference count for layer library %s",
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002033 chain_type, layer_prop->lib_name);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002034 return loader.loaded_layer_lib_list[i].lib_handle;
2035 }
2036 }
2037
2038 /* Haven't seen this library so load it */
Jon Ashburne58f1a32015-08-28 13:38:21 -06002039 new_alloc_size = 0;
2040 if (loader.loaded_layer_lib_capacity == 0)
2041 new_alloc_size = 8 * sizeof(struct loader_lib_info);
2042 else if (loader.loaded_layer_lib_capacity <= loader.loaded_layer_lib_count *
2043 sizeof(struct loader_lib_info))
2044 new_alloc_size = loader.loaded_layer_lib_capacity * 2;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002045
Jon Ashburne58f1a32015-08-28 13:38:21 -06002046 if (new_alloc_size) {
2047 new_layer_lib_list = loader_heap_realloc(
2048 inst, loader.loaded_layer_lib_list,
2049 loader.loaded_layer_lib_capacity,
2050 new_alloc_size,
2051 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
2052 if (!new_layer_lib_list) {
2053 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "loader: realloc failed in loader_add_layer_lib");
2054 return NULL;
2055 }
2056 loader.loaded_layer_lib_capacity = new_alloc_size;
2057 } else
2058 new_layer_lib_list = loader.loaded_layer_lib_list;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002059 my_lib = &new_layer_lib_list[loader.loaded_layer_lib_count];
2060
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002061 strncpy(my_lib->lib_name, layer_prop->lib_name, sizeof(my_lib->lib_name));
2062 my_lib->lib_name[sizeof(my_lib->lib_name) - 1] = '\0';
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002063 my_lib->ref_count = 0;
2064 my_lib->lib_handle = NULL;
2065
2066 if ((my_lib->lib_handle = loader_platform_open_library(my_lib->lib_name)) == NULL) {
2067 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
2068 loader_platform_open_library_error(my_lib->lib_name));
2069 return NULL;
2070 } else {
Courtney Goeltzenleuchter926f39e2015-06-14 11:59:07 -06002071 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002072 "Chain: %s: Loading layer library %s",
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002073 chain_type, layer_prop->lib_name);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002074 }
2075 loader.loaded_layer_lib_count++;
2076 loader.loaded_layer_lib_list = new_layer_lib_list;
2077 my_lib->ref_count++;
2078
2079 return my_lib->lib_handle;
2080}
2081
2082static void loader_remove_layer_lib(
2083 struct loader_instance *inst,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002084 struct loader_layer_properties *layer_prop)
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002085{
2086 uint32_t idx;
Tony Barbour9687cb12015-07-14 13:34:05 -06002087 struct loader_lib_info *new_layer_lib_list, *my_lib = NULL;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002088
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002089 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) {
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002090 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, layer_prop->lib_name) == 0) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002091 /* found matching library */
2092 idx = i;
2093 my_lib = &loader.loaded_layer_lib_list[i];
2094 break;
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002095 }
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002096 }
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002097
Tony Barbour9687cb12015-07-14 13:34:05 -06002098 if (my_lib) {
2099 my_lib->ref_count--;
2100 if (my_lib->ref_count > 0) {
2101 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002102 "Decrement reference count for layer library %s", layer_prop->lib_name);
Tony Barbour9687cb12015-07-14 13:34:05 -06002103 return;
2104 }
Courtney Goeltzenleuchter0199e952015-02-27 15:19:33 -07002105 }
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002106 loader_platform_close_library(my_lib->lib_handle);
Courtney Goeltzenleuchter926f39e2015-06-14 11:59:07 -06002107 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002108 "Unloading layer library %s", layer_prop->lib_name);
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002109
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002110 /* Need to remove unused library from list */
Jon Ashburne58f1a32015-08-28 13:38:21 -06002111 new_layer_lib_list = loader_heap_alloc(inst,
2112 loader.loaded_layer_lib_capacity,
2113 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002114 if (!new_layer_lib_list) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06002115 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "loader: heap alloc failed loader_remove_layer_library");
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002116 return;
2117 }
2118
2119 if (idx > 0) {
2120 /* Copy records before idx */
2121 memcpy(new_layer_lib_list, &loader.loaded_layer_lib_list[0],
2122 sizeof(struct loader_lib_info) * idx);
2123 }
2124 if (idx < (loader.loaded_layer_lib_count - 1)) {
2125 /* Copy records after idx */
2126 memcpy(&new_layer_lib_list[idx], &loader.loaded_layer_lib_list[idx+1],
2127 sizeof(struct loader_lib_info) * (loader.loaded_layer_lib_count - idx - 1));
2128 }
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002129
Jon Ashburne58f1a32015-08-28 13:38:21 -06002130 loader_heap_free(inst, loader.loaded_layer_lib_list);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002131 loader.loaded_layer_lib_count--;
2132 loader.loaded_layer_lib_list = new_layer_lib_list;
Jon Ashburnead95c52014-11-18 09:06:04 -07002133}
2134
Jon Ashburn1b111de2015-07-06 15:40:35 -06002135
2136/**
2137 * Go through the search_list and find any layers which match type. If layer
2138 * type match is found in then add it to ext_list.
2139 */
2140//TODO need to handle implict layer enable env var and disable env var
Jon Ashburn535bd002015-07-02 16:10:32 -06002141static void loader_add_layer_implicit(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002142 const struct loader_instance *inst,
Jon Ashburn535bd002015-07-02 16:10:32 -06002143 const enum layer_type type,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002144 struct loader_layer_list *list,
Jon Ashburn182b8302015-08-11 14:49:54 -06002145 const struct loader_layer_list *search_list)
Jon Ashburn535bd002015-07-02 16:10:32 -06002146{
2147 uint32_t i;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002148 for (i = 0; i < search_list->count; i++) {
2149 const struct loader_layer_properties *prop = &search_list->list[i];
Jon Ashburn535bd002015-07-02 16:10:32 -06002150 if (prop->type & type) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002151 /* Found an layer with the same type, add to layer_list */
Jon Ashburne58f1a32015-08-28 13:38:21 -06002152 loader_add_to_layer_list(inst, list, 1, prop);
Jon Ashburn535bd002015-07-02 16:10:32 -06002153 }
2154 }
2155
2156}
2157
2158/**
2159 * Get the layer name(s) from the env_name environment variable. If layer
Jon Ashburnf2ddb732015-07-07 10:27:45 -06002160 * is found in search_list then add it to layer_list. But only add it to
2161 * layer_list if type matches.
Jon Ashburn535bd002015-07-02 16:10:32 -06002162 */
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002163static void loader_add_layer_env(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002164 const struct loader_instance *inst,
Jon Ashburnf2ddb732015-07-07 10:27:45 -06002165 const enum layer_type type,
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002166 const char *env_name,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002167 struct loader_layer_list *layer_list,
2168 const struct loader_layer_list *search_list)
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002169{
Ian Elliott225188f2015-02-17 10:33:47 -07002170 char *layerEnv;
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002171 char *next, *name;
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002172
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002173 layerEnv = getenv(env_name);
Ian Elliott225188f2015-02-17 10:33:47 -07002174 if (layerEnv == NULL) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002175 return;
Ian Elliott225188f2015-02-17 10:33:47 -07002176 }
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -06002177 name = loader_stack_alloc(strlen(layerEnv) + 1);
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002178 if (name == NULL) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002179 return;
Ian Elliott225188f2015-02-17 10:33:47 -07002180 }
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002181 strcpy(name, layerEnv);
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002182
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002183 while (name && *name ) {
2184 next = loader_get_next_path(name);
Jon Ashburne58f1a32015-08-28 13:38:21 -06002185 loader_find_layer_name_add_list(inst, name, type, search_list, layer_list);
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002186 name = next;
Courtney Goeltzenleuchter0199e952015-02-27 15:19:33 -07002187 }
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002188
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002189 return;
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002190}
2191
Courtney Goeltzenleuchter3d8dc1f2015-06-08 15:09:22 -06002192void loader_deactivate_instance_layers(struct loader_instance *instance)
Jon Ashburn183dfd02014-10-22 18:13:16 -06002193{
Jon Ashburn60378412015-07-02 12:59:25 -06002194 if (!instance->activated_layer_list.count) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002195 return;
2196 }
Jon Ashburn183dfd02014-10-22 18:13:16 -06002197
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002198 /* Create instance chain of enabled layers */
Courtney Goeltzenleuchter3d8dc1f2015-06-08 15:09:22 -06002199 for (uint32_t i = 0; i < instance->activated_layer_list.count; i++) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002200 struct loader_layer_properties *layer_prop = &instance->activated_layer_list.list[i];
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002201
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002202 loader_remove_layer_lib(instance, layer_prop);
Jon Ashburn183dfd02014-10-22 18:13:16 -06002203 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06002204 loader_destroy_layer_list(instance, &instance->activated_layer_list);
Jon Ashburn183dfd02014-10-22 18:13:16 -06002205}
2206
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002207VkResult loader_enable_instance_layers(
Jon Ashburn182b8302015-08-11 14:49:54 -06002208 struct loader_instance *inst,
2209 const VkInstanceCreateInfo *pCreateInfo,
2210 const struct loader_layer_list *instance_layers)
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002211{
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002212 VkResult err;
2213
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -06002214 assert(inst && "Cannot have null instance");
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002215
Jon Ashburne58f1a32015-08-28 13:38:21 -06002216 if (!loader_init_layer_list(inst, &inst->activated_layer_list)) {
2217 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc Instance activated layer list");
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002218 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburn60378412015-07-02 12:59:25 -06002219 }
2220
Jon Ashburn535bd002015-07-02 16:10:32 -06002221 /* Add any implicit layers first */
2222 loader_add_layer_implicit(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002223 inst,
Jon Ashburn535bd002015-07-02 16:10:32 -06002224 VK_LAYER_TYPE_INSTANCE_IMPLICIT,
2225 &inst->activated_layer_list,
Jon Ashburn182b8302015-08-11 14:49:54 -06002226 instance_layers);
Jon Ashburn535bd002015-07-02 16:10:32 -06002227
Jon Ashburn1b111de2015-07-06 15:40:35 -06002228 /* Add any layers specified via environment variable next */
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002229 loader_add_layer_env(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002230 inst,
Jon Ashburnf2ddb732015-07-07 10:27:45 -06002231 VK_LAYER_TYPE_INSTANCE_EXPLICIT,
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002232 "VK_INSTANCE_LAYERS",
2233 &inst->activated_layer_list,
Jon Ashburn182b8302015-08-11 14:49:54 -06002234 instance_layers);
Jon Ashburn60378412015-07-02 12:59:25 -06002235
2236 /* Add layers specified by the application */
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002237 err = loader_add_layer_names_to_list(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002238 inst,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002239 &inst->activated_layer_list,
2240 pCreateInfo->layerCount,
2241 pCreateInfo->ppEnabledLayerNames,
Jon Ashburn182b8302015-08-11 14:49:54 -06002242 instance_layers);
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002243
2244 return err;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002245}
2246
Jon Ashburnfce93d92015-05-12 17:26:48 -06002247uint32_t loader_activate_instance_layers(struct loader_instance *inst)
2248{
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002249 uint32_t layer_idx;
Jon Ashburnd5df54d2015-05-28 19:16:58 -06002250 VkBaseLayerObject *wrappedInstance;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002251
David Pinedo0fab78b2015-06-24 15:29:18 -06002252 if (inst == NULL) {
Jon Ashburnfce93d92015-05-12 17:26:48 -06002253 return 0;
David Pinedo0fab78b2015-06-24 15:29:18 -06002254 }
Jon Ashburnfce93d92015-05-12 17:26:48 -06002255
2256 // NOTE inst is unwrapped at this point in time
Tony Barbourde4124d2015-07-03 10:33:54 -06002257 void* baseObj = (void*) inst;
2258 void* nextObj = (void*) inst;
Jon Ashburnfce93d92015-05-12 17:26:48 -06002259 VkBaseLayerObject *nextInstObj;
2260 PFN_vkGetInstanceProcAddr nextGPA = loader_gpa_instance_internal;
2261
Jon Ashburn60378412015-07-02 12:59:25 -06002262 if (!inst->activated_layer_list.count) {
Courtney Goeltzenleuchter33243142015-08-07 09:53:18 -06002263 loader_init_instance_core_dispatch_table(inst->disp, nextGPA, (VkInstance) nextObj, (VkInstance) baseObj);
Jon Ashburnfce93d92015-05-12 17:26:48 -06002264 return 0;
2265 }
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002266
Courtney Goeltzenleuchter0248b992015-07-06 09:04:55 -06002267 wrappedInstance = loader_stack_alloc(sizeof(VkBaseLayerObject)
Jon Ashburn60378412015-07-02 12:59:25 -06002268 * inst->activated_layer_list.count);
Jon Ashburnd5df54d2015-05-28 19:16:58 -06002269 if (!wrappedInstance) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06002270 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc Instance objects for layer");
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002271 return 0;
2272 }
2273
2274 /* Create instance chain of enabled layers */
Jon Ashburn60378412015-07-02 12:59:25 -06002275 layer_idx = inst->activated_layer_list.count - 1;
Courtney Goeltzenleuchterf4b430e2015-06-07 17:28:17 -06002276 for (int32_t i = inst->activated_layer_list.count - 1; i >= 0; i--) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002277 struct loader_layer_properties *layer_prop = &inst->activated_layer_list.list[i];
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002278 loader_platform_dl_handle lib_handle;
2279
Jon Ashburn60378412015-07-02 12:59:25 -06002280 /*
Courtney Goeltzenleuchterc27292a2015-06-01 14:12:42 -06002281 * Note: An extension's Get*ProcAddr should not return a function pointer for
2282 * any extension entry points until the extension has been enabled.
2283 * To do this requires a different behavior from Get*ProcAddr functions implemented
2284 * in layers.
2285 * The very first call to a layer will be it's Get*ProcAddr function requesting
Tobin Ehlis84492ee2015-10-06 09:09:24 -06002286 * the layer's vkGet*ProcAddr. The layer should initialize its internal dispatch table
Courtney Goeltzenleuchterc27292a2015-06-01 14:12:42 -06002287 * with the wrapped object given (either Instance or Device) and return the layer's
2288 * Get*ProcAddr function. The layer should also use this opportunity to record the
2289 * baseObject so that it can find the correct local dispatch table on future calls.
2290 * Subsequent calls to Get*ProcAddr, CreateInstance, CreateDevice
2291 * will not use a wrapped object and must look up their local dispatch table from
2292 * the given baseObject.
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002293 */
Jon Ashburnd5df54d2015-05-28 19:16:58 -06002294 nextInstObj = (wrappedInstance + layer_idx);
Tony Barbourde4124d2015-07-03 10:33:54 -06002295 nextInstObj->pGPA = (PFN_vkGPA) nextGPA;
Jon Ashburnfce93d92015-05-12 17:26:48 -06002296 nextInstObj->baseObject = baseObj;
2297 nextInstObj->nextObject = nextObj;
Tony Barbourde4124d2015-07-03 10:33:54 -06002298 nextObj = (void*) nextInstObj;
Jon Ashburnfce93d92015-05-12 17:26:48 -06002299
Jon Ashburne58f1a32015-08-28 13:38:21 -06002300 lib_handle = loader_add_layer_lib(inst, "instance", layer_prop);
Jon Ashburn2db08042015-09-09 11:29:24 -06002301 if ((nextGPA = layer_prop->functions.get_instance_proc_addr) == NULL) {
2302 if (layer_prop->functions.str_gipa == NULL || strlen(layer_prop->functions.str_gipa) == 0) {
2303 nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetInstanceProcAddr");
2304 layer_prop->functions.get_instance_proc_addr = nextGPA;
2305 } else
2306 nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gipa);
2307 if (!nextGPA) {
2308 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 -06002309
Jon Ashburn2db08042015-09-09 11:29:24 -06002310 /* TODO: Should we return nextObj, nextGPA to previous? or decrement layer_list count*/
2311 continue;
2312 }
Jon Ashburnfce93d92015-05-12 17:26:48 -06002313 }
2314
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002315 loader_log(VK_DBG_REPORT_INFO_BIT, 0,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002316 "Insert instance layer %s (%s)",
2317 layer_prop->info.layerName,
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002318 layer_prop->lib_name);
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002319
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002320 layer_idx--;
Jon Ashburnfce93d92015-05-12 17:26:48 -06002321 }
2322
Jon Ashburn4f2575f2015-05-28 16:25:02 -06002323 loader_init_instance_core_dispatch_table(inst->disp, nextGPA, (VkInstance) nextObj, (VkInstance) baseObj);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002324
Jon Ashburn60378412015-07-02 12:59:25 -06002325 return inst->activated_layer_list.count;
Jon Ashburnfce93d92015-05-12 17:26:48 -06002326}
2327
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002328void loader_activate_instance_layer_extensions(struct loader_instance *inst)
2329{
2330
2331 loader_init_instance_extension_dispatch_table(inst->disp,
2332 inst->disp->GetInstanceProcAddr,
Jon Ashburnd5df54d2015-05-28 19:16:58 -06002333 (VkInstance) inst);
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002334}
2335
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002336static VkResult loader_enable_device_layers(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002337 const struct loader_instance *inst,
Jon Ashburn182b8302015-08-11 14:49:54 -06002338 struct loader_icd *icd,
2339 struct loader_device *dev,
2340 const VkDeviceCreateInfo *pCreateInfo,
2341 const struct loader_layer_list *device_layers)
2342
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002343{
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002344 VkResult err;
2345
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -06002346 assert(dev && "Cannot have null device");
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002347
Jon Ashburn60378412015-07-02 12:59:25 -06002348 if (dev->activated_layer_list.list == NULL || dev->activated_layer_list.capacity == 0) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06002349 loader_init_layer_list(inst, &dev->activated_layer_list);
Jon Ashburn60378412015-07-02 12:59:25 -06002350 }
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002351
Jon Ashburn60378412015-07-02 12:59:25 -06002352 if (dev->activated_layer_list.list == NULL) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06002353 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc device activated layer list");
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002354 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburn60378412015-07-02 12:59:25 -06002355 }
2356
Jon Ashburn535bd002015-07-02 16:10:32 -06002357 /* Add any implicit layers first */
2358 loader_add_layer_implicit(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002359 inst,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002360 VK_LAYER_TYPE_DEVICE_IMPLICIT,
2361 &dev->activated_layer_list,
Jon Ashburn182b8302015-08-11 14:49:54 -06002362 device_layers);
Jon Ashburn535bd002015-07-02 16:10:32 -06002363
2364 /* Add any layers specified via environment variable next */
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002365 loader_add_layer_env(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002366 inst,
Jon Ashburnf2ddb732015-07-07 10:27:45 -06002367 VK_LAYER_TYPE_DEVICE_EXPLICIT,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002368 "VK_DEVICE_LAYERS",
2369 &dev->activated_layer_list,
Jon Ashburn182b8302015-08-11 14:49:54 -06002370 device_layers);
Jon Ashburn60378412015-07-02 12:59:25 -06002371
2372 /* Add layers specified by the application */
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002373 err = loader_add_layer_names_to_list(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002374 inst,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002375 &dev->activated_layer_list,
2376 pCreateInfo->layerCount,
2377 pCreateInfo->ppEnabledLayerNames,
Jon Ashburn182b8302015-08-11 14:49:54 -06002378 device_layers);
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002379
2380 return err;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002381}
2382
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002383/*
Jon Ashburnc1d1eb72015-08-14 11:57:54 -06002384 * This function terminates the device chain for CreateDevice.
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002385 * CreateDevice is a special case and so the loader call's
2386 * the ICD's CreateDevice before creating the chain. Since
2387 * we can't call CreateDevice twice we must terminate the
2388 * device chain with something else.
2389 */
Dan Ginsburgf99e4102015-07-23 13:15:00 -04002390static VkResult VKAPI scratch_vkCreateDevice(
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002391 VkPhysicalDevice gpu,
2392 const VkDeviceCreateInfo *pCreateInfo,
2393 VkDevice *pDevice)
2394{
2395 return VK_SUCCESS;
2396}
2397
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -06002398static PFN_vkVoidFunction VKAPI loader_GetDeviceChainProcAddr(VkDevice device, const char * name)
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002399{
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002400 if (!strcmp(name, "vkGetDeviceProcAddr"))
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -06002401 return (PFN_vkVoidFunction) loader_GetDeviceChainProcAddr;
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002402 if (!strcmp(name, "vkCreateDevice"))
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -06002403 return (PFN_vkVoidFunction) scratch_vkCreateDevice;
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002404
Courtney Goeltzenleuchtere76db422015-06-29 16:09:23 -06002405 struct loader_device *found_dev;
2406 struct loader_icd *icd = loader_get_icd_and_device(device, &found_dev);
2407 return icd->GetDeviceProcAddr(device, name);
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002408}
2409
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06002410static uint32_t loader_activate_device_layers(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002411 const struct loader_instance *inst,
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002412 struct loader_device *dev,
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -06002413 VkDevice device)
Jon Ashburn183dfd02014-10-22 18:13:16 -06002414{
David Pinedo0fab78b2015-06-24 15:29:18 -06002415 if (!dev) {
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06002416 return 0;
David Pinedo0fab78b2015-06-24 15:29:18 -06002417 }
Jon Ashburn612539f2015-06-10 10:13:10 -06002418
Jon Ashburn183dfd02014-10-22 18:13:16 -06002419 /* activate any layer libraries */
Tony Barbourde4124d2015-07-03 10:33:54 -06002420 void* nextObj = (void*) device;
2421 void* baseObj = nextObj;
Jon Ashburn612539f2015-06-10 10:13:10 -06002422 VkBaseLayerObject *nextGpuObj;
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002423 PFN_vkGetDeviceProcAddr nextGPA = loader_GetDeviceChainProcAddr;
Jon Ashburn612539f2015-06-10 10:13:10 -06002424 VkBaseLayerObject *wrappedGpus;
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002425
Courtney Goeltzenleuchter33243142015-08-07 09:53:18 -06002426 if (!dev->activated_layer_list.count) {
2427 loader_init_device_dispatch_table(&dev->loader_dispatch, nextGPA,
2428 (VkDevice) nextObj, (VkDevice) baseObj);
Jon Ashburn612539f2015-06-10 10:13:10 -06002429 return 0;
Courtney Goeltzenleuchter33243142015-08-07 09:53:18 -06002430 }
Jon Ashburn612539f2015-06-10 10:13:10 -06002431
Jon Ashburne58f1a32015-08-28 13:38:21 -06002432 wrappedGpus = loader_heap_alloc(inst,
2433 sizeof (VkBaseLayerObject) * dev->activated_layer_list.count,
2434 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburn612539f2015-06-10 10:13:10 -06002435 if (!wrappedGpus) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06002436 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc Gpu objects for layer");
Jon Ashburn612539f2015-06-10 10:13:10 -06002437 return 0;
2438 }
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002439
Jon Ashburn612539f2015-06-10 10:13:10 -06002440 for (int32_t i = dev->activated_layer_list.count - 1; i >= 0; i--) {
2441
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002442 struct loader_layer_properties *layer_prop = &dev->activated_layer_list.list[i];
Jon Ashburn612539f2015-06-10 10:13:10 -06002443 loader_platform_dl_handle lib_handle;
2444
Jon Ashburn612539f2015-06-10 10:13:10 -06002445 nextGpuObj = (wrappedGpus + i);
Tony Barbourde4124d2015-07-03 10:33:54 -06002446 nextGpuObj->pGPA = (PFN_vkGPA)nextGPA;
Jon Ashburn612539f2015-06-10 10:13:10 -06002447 nextGpuObj->baseObject = baseObj;
2448 nextGpuObj->nextObject = nextObj;
Tony Barbourde4124d2015-07-03 10:33:54 -06002449 nextObj = (void*) nextGpuObj;
Jon Ashburn612539f2015-06-10 10:13:10 -06002450
Jon Ashburne58f1a32015-08-28 13:38:21 -06002451 lib_handle = loader_add_layer_lib(inst, "device", layer_prop);
Jon Ashburn2db08042015-09-09 11:29:24 -06002452 if ((nextGPA = layer_prop->functions.get_device_proc_addr) == NULL) {
2453 if (layer_prop->functions.str_gdpa == NULL || strlen(layer_prop->functions.str_gdpa) == 0) {
2454 nextGPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetDeviceProcAddr");
2455 layer_prop->functions.get_device_proc_addr = nextGPA;
2456 } else
2457 nextGPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gdpa);
2458 if (!nextGPA) {
2459 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to find vkGetDeviceProcAddr in layer %s", layer_prop->lib_name);
2460 continue;
2461 }
Jon Ashburn612539f2015-06-10 10:13:10 -06002462 }
2463
2464 loader_log(VK_DBG_REPORT_INFO_BIT, 0,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002465 "Insert device layer library %s (%s)",
2466 layer_prop->info.layerName,
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002467 layer_prop->lib_name);
Jon Ashburn612539f2015-06-10 10:13:10 -06002468
2469 }
2470
2471 loader_init_device_dispatch_table(&dev->loader_dispatch, nextGPA,
Tony Barbourde4124d2015-07-03 10:33:54 -06002472 (VkDevice) nextObj, (VkDevice) baseObj);
Jon Ashburne58f1a32015-08-28 13:38:21 -06002473 loader_heap_free(inst, wrappedGpus);
Jon Ashburn612539f2015-06-10 10:13:10 -06002474
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06002475 return dev->activated_layer_list.count;
Jon Ashburn183dfd02014-10-22 18:13:16 -06002476}
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002477
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002478VkResult loader_validate_layers(
2479 const uint32_t layer_count,
2480 const char * const *ppEnabledLayerNames,
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002481 const struct loader_layer_list *list)
Courtney Goeltzenleuchter5d9f29b2015-07-06 17:45:08 -06002482{
2483 struct loader_layer_properties *prop;
2484
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002485 for (uint32_t i = 0; i < layer_count; i++) {
Jon Ashburn8e4fab42015-08-03 17:19:30 -06002486 prop = loader_get_layer_property(ppEnabledLayerNames[i],
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002487 list);
Courtney Goeltzenleuchter5d9f29b2015-07-06 17:45:08 -06002488 if (!prop) {
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -06002489 return VK_ERROR_LAYER_NOT_PRESENT;
Courtney Goeltzenleuchter5d9f29b2015-07-06 17:45:08 -06002490 }
2491 }
2492
2493 return VK_SUCCESS;
2494}
2495
2496VkResult loader_validate_instance_extensions(
Jon Ashburnc1d1eb72015-08-14 11:57:54 -06002497 const struct loader_extension_list *icd_exts,
Jon Ashburn182b8302015-08-11 14:49:54 -06002498 const struct loader_layer_list *instance_layer,
2499 const VkInstanceCreateInfo *pCreateInfo)
Courtney Goeltzenleuchter5d9f29b2015-07-06 17:45:08 -06002500{
Jon Ashburnc4748dc2015-08-04 11:14:18 -06002501 VkExtensionProperties *extension_prop;
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002502 struct loader_layer_properties *layer_prop;
2503
2504 for (uint32_t i = 0; i < pCreateInfo->extensionCount; i++) {
2505 extension_prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
Jon Ashburnc1d1eb72015-08-14 11:57:54 -06002506 icd_exts);
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002507
2508 if (extension_prop) {
2509 continue;
2510 }
2511
2512 extension_prop = NULL;
2513
2514 /* Not in global list, search layer extension lists */
2515 for (uint32_t j = 0; j < pCreateInfo->layerCount; j++) {
Jon Ashburn8e4fab42015-08-03 17:19:30 -06002516 layer_prop = loader_get_layer_property(pCreateInfo->ppEnabledLayerNames[i],
Jon Ashburn182b8302015-08-11 14:49:54 -06002517 instance_layer);
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002518 if (!layer_prop) {
Courtney Goeltzenleuchter91371ff2015-07-06 20:46:50 -06002519 /* Should NOT get here, loader_validate_layers
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002520 * should have already filtered this case out.
2521 */
2522 continue;
2523 }
2524
2525 extension_prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
2526 &layer_prop->instance_extension_list);
2527 if (extension_prop) {
2528 /* Found the extension in one of the layers enabled by the app. */
2529 break;
2530 }
2531 }
2532
2533 if (!extension_prop) {
2534 /* Didn't find extension name in any of the global layers, error out */
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -06002535 return VK_ERROR_EXTENSION_NOT_PRESENT;
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002536 }
2537 }
2538 return VK_SUCCESS;
2539}
2540
2541VkResult loader_validate_device_extensions(
Jon Ashburn182b8302015-08-11 14:49:54 -06002542 struct loader_icd *icd,
2543 uint32_t gpu_index,
2544 const struct loader_layer_list *device_layer,
2545 const VkDeviceCreateInfo *pCreateInfo)
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002546{
Jon Ashburnc4748dc2015-08-04 11:14:18 -06002547 VkExtensionProperties *extension_prop;
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002548 struct loader_layer_properties *layer_prop;
2549
2550 for (uint32_t i = 0; i < pCreateInfo->extensionCount; i++) {
2551 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i];
2552 extension_prop = get_extension_property(extension_name,
Courtney Goeltzenleuchterd2775f72015-07-08 21:13:16 -06002553 &icd->device_extension_cache[gpu_index]);
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002554
2555 if (extension_prop) {
2556 continue;
2557 }
2558
2559 /* Not in global list, search layer extension lists */
2560 for (uint32_t j = 0; j < pCreateInfo->layerCount; j++) {
2561 const char *layer_name = pCreateInfo->ppEnabledLayerNames[j];
Jon Ashburn8e4fab42015-08-03 17:19:30 -06002562 layer_prop = loader_get_layer_property(layer_name,
Jon Ashburn182b8302015-08-11 14:49:54 -06002563 device_layer);
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002564
2565 if (!layer_prop) {
2566 /* Should NOT get here, loader_validate_instance_layers
2567 * should have already filtered this case out.
2568 */
2569 continue;
2570 }
2571
2572 extension_prop = get_extension_property(extension_name,
2573 &layer_prop->device_extension_list);
2574 if (extension_prop) {
2575 /* Found the extension in one of the layers enabled by the app. */
2576 break;
2577 }
2578 }
2579
2580 if (!extension_prop) {
2581 /* Didn't find extension name in any of the device layers, error out */
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -06002582 return VK_ERROR_EXTENSION_NOT_PRESENT;
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002583 }
2584 }
Courtney Goeltzenleuchter5d9f29b2015-07-06 17:45:08 -06002585 return VK_SUCCESS;
2586}
2587
Dan Ginsburgf99e4102015-07-23 13:15:00 -04002588VkResult VKAPI loader_CreateInstance(
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002589 const VkInstanceCreateInfo* pCreateInfo,
2590 VkInstance* pInstance)
Jon Ashburn349508d2015-01-26 14:51:40 -07002591{
Jon Ashburna179dcf2015-05-21 17:42:17 -06002592 struct loader_instance *ptr_instance = *(struct loader_instance **) pInstance;
Jon Ashburn3336df82015-01-29 15:45:51 -07002593 struct loader_icd *icd;
Jon Ashburnc4748dc2015-08-04 11:14:18 -06002594 VkExtensionProperties *prop;
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06002595 char **filtered_extension_names = NULL;
2596 VkInstanceCreateInfo icd_create_info;
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002597 VkResult res = VK_SUCCESS;
Jon Ashburnce7e3d92015-07-16 10:17:29 -06002598 bool success;
Jon Ashburn349508d2015-01-26 14:51:40 -07002599
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06002600 icd_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
2601 icd_create_info.layerCount = 0;
2602 icd_create_info.ppEnabledLayerNames = NULL;
2603 icd_create_info.pAllocCb = pCreateInfo->pAllocCb;
2604 icd_create_info.pAppInfo = pCreateInfo->pAppInfo;
2605 icd_create_info.pNext = pCreateInfo->pNext;
2606
2607 /*
2608 * NOTE: Need to filter the extensions to only those
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002609 * supported by the ICD.
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06002610 * No ICD will advertise support for layers. An ICD
2611 * library could support a layer, but it would be
2612 * independent of the actual ICD, just in the same library.
2613 */
2614 filtered_extension_names = loader_stack_alloc(pCreateInfo->extensionCount * sizeof(char *));
2615 if (!filtered_extension_names) {
2616 return VK_ERROR_OUT_OF_HOST_MEMORY;
2617 }
2618 icd_create_info.ppEnabledExtensionNames = (const char * const *) filtered_extension_names;
2619
Jon Ashburn754f1992015-08-18 18:04:47 -06002620 for (uint32_t i = 0; i < ptr_instance->icd_libs.count; i++) {
2621 icd = loader_icd_add(ptr_instance, &ptr_instance->icd_libs.list[i]);
Jon Ashburn3336df82015-01-29 15:45:51 -07002622 if (icd) {
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06002623 icd_create_info.extensionCount = 0;
2624 for (uint32_t i = 0; i < pCreateInfo->extensionCount; i++) {
2625 prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
Jon Ashburn85f98072015-08-14 14:49:22 -06002626 &ptr_instance->ext_list);
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06002627 if (prop) {
2628 filtered_extension_names[icd_create_info.extensionCount] = (char *) pCreateInfo->ppEnabledExtensionNames[i];
2629 icd_create_info.extensionCount++;
2630 }
2631 }
2632
Jon Ashburn754f1992015-08-18 18:04:47 -06002633 res = ptr_instance->icd_libs.list[i].CreateInstance(&icd_create_info,
Jon Ashburn0dd356d2015-05-14 12:43:38 -06002634 &(icd->instance));
Jon Ashburnce7e3d92015-07-16 10:17:29 -06002635 success = loader_icd_init_entrys(
2636 icd,
2637 icd->instance,
Jon Ashburn754f1992015-08-18 18:04:47 -06002638 ptr_instance->icd_libs.list[i].GetInstanceProcAddr);
Jon Ashburnce7e3d92015-07-16 10:17:29 -06002639
2640 if (res != VK_SUCCESS || !success)
Jon Ashburn3336df82015-01-29 15:45:51 -07002641 {
2642 ptr_instance->icds = ptr_instance->icds->next;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002643 loader_icd_destroy(ptr_instance, icd);
Jon Ashburn0dd356d2015-05-14 12:43:38 -06002644 icd->instance = VK_NULL_HANDLE;
Jon Ashburnce7e3d92015-07-16 10:17:29 -06002645 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
2646 "ICD ignored: failed to CreateInstance and find entrypoints with ICD");
Jon Ashburn3336df82015-01-29 15:45:51 -07002647 }
2648 }
Jon Ashburn3336df82015-01-29 15:45:51 -07002649 }
Jon Ashburn349508d2015-01-26 14:51:40 -07002650
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002651 /*
2652 * If no ICDs were added to instance list and res is unchanged
2653 * from it's initial value, the loader was unable to find
2654 * a suitable ICD.
2655 */
Ian Elliott617fdec2015-02-05 15:19:15 -07002656 if (ptr_instance->icds == NULL) {
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002657 if (res == VK_SUCCESS) {
2658 return VK_ERROR_INCOMPATIBLE_DRIVER;
2659 } else {
2660 return res;
2661 }
Ian Elliott617fdec2015-02-05 15:19:15 -07002662 }
Jon Ashburn3336df82015-01-29 15:45:51 -07002663
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002664 return VK_SUCCESS;
Jon Ashburn349508d2015-01-26 14:51:40 -07002665}
2666
Mark Lobodzinski67b42b72015-09-07 13:59:43 -06002667void VKAPI loader_DestroyInstance(
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -06002668 VkInstance instance)
Jon Ashburn349508d2015-01-26 14:51:40 -07002669{
Courtney Goeltzenleuchter8afefb52015-06-08 15:04:02 -06002670 struct loader_instance *ptr_instance = loader_instance(instance);
Jon Ashburn0dd356d2015-05-14 12:43:38 -06002671 struct loader_icd *icds = ptr_instance->icds;
Jon Ashburn16a16d62015-06-16 14:43:19 -06002672 struct loader_icd *next_icd;
Jon Ashburn349508d2015-01-26 14:51:40 -07002673
2674 // Remove this instance from the list of instances:
2675 struct loader_instance *prev = NULL;
2676 struct loader_instance *next = loader.instances;
2677 while (next != NULL) {
2678 if (next == ptr_instance) {
2679 // Remove this instance from the list:
2680 if (prev)
2681 prev->next = next->next;
Jon Ashburn2cabd252015-02-03 09:26:59 -07002682 else
2683 loader.instances = next->next;
Jon Ashburn349508d2015-01-26 14:51:40 -07002684 break;
2685 }
2686 prev = next;
2687 next = next->next;
2688 }
Jon Ashburn349508d2015-01-26 14:51:40 -07002689
Jon Ashburn0dd356d2015-05-14 12:43:38 -06002690 while (icds) {
2691 if (icds->instance) {
Mark Lobodzinski67b42b72015-09-07 13:59:43 -06002692 icds->DestroyInstance(icds->instance);
Tony Barbour22a30862015-04-22 09:02:32 -06002693 }
Jon Ashburn16a16d62015-06-16 14:43:19 -06002694 next_icd = icds->next;
Jon Ashburn0dd356d2015-05-14 12:43:38 -06002695 icds->instance = VK_NULL_HANDLE;
Jon Ashburn16a16d62015-06-16 14:43:19 -06002696 loader_icd_destroy(ptr_instance, icds);
2697
2698 icds = next_icd;
Jon Ashburn3336df82015-01-29 15:45:51 -07002699 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06002700 loader_delete_layer_properties(ptr_instance, &ptr_instance->device_layer_list);
2701 loader_delete_layer_properties(ptr_instance, &ptr_instance->instance_layer_list);
2702 loader_scanned_icd_clear(ptr_instance, &ptr_instance->icd_libs);
2703 loader_destroy_ext_list(ptr_instance, &ptr_instance->ext_list);
Jon Ashburn349508d2015-01-26 14:51:40 -07002704}
2705
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002706VkResult loader_init_physical_device_info(
2707 struct loader_instance *ptr_instance)
2708{
2709 struct loader_icd *icd;
2710 uint32_t n, count = 0;
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -06002711 VkResult res;
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002712
2713 icd = ptr_instance->icds;
2714 while (icd) {
2715 res = icd->EnumeratePhysicalDevices(icd->instance, &n, NULL);
2716 if (res != VK_SUCCESS)
2717 return res;
2718 icd->gpu_count = n;
2719 count += n;
2720 icd = icd->next;
2721 }
2722
2723 ptr_instance->total_gpu_count = count;
2724
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002725 icd = ptr_instance->icds;
2726 while (icd) {
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002727
2728 n = icd->gpu_count;
Jon Ashburne58f1a32015-08-28 13:38:21 -06002729 icd->gpus = (VkPhysicalDevice *) loader_heap_alloc(
2730 ptr_instance,
2731 n * sizeof(VkPhysicalDevice),
2732 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburnd5df54d2015-05-28 19:16:58 -06002733 if (!icd->gpus) {
2734 /* TODO: Add cleanup code here */
2735 return VK_ERROR_OUT_OF_HOST_MEMORY;
2736 }
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002737 res = icd->EnumeratePhysicalDevices(
2738 icd->instance,
2739 &n,
Jon Ashburnd5df54d2015-05-28 19:16:58 -06002740 icd->gpus);
2741 if ((res == VK_SUCCESS) && (n == icd->gpu_count)) {
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002742
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002743 for (unsigned int i = 0; i < n; i++) {
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002744
Jon Ashburnd5df54d2015-05-28 19:16:58 -06002745 loader_init_dispatch(icd->gpus[i], ptr_instance->disp);
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002746
Jon Ashburne58f1a32015-08-28 13:38:21 -06002747 if (!loader_init_ext_list(ptr_instance, &icd->device_extension_cache[i])) {
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002748 /* TODO: Add cleanup code here */
2749 res = VK_ERROR_OUT_OF_HOST_MEMORY;
2750 }
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002751 if (res == VK_SUCCESS) {
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002752
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002753 loader_add_physical_device_extensions(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002754 ptr_instance,
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -06002755 icd->EnumerateDeviceExtensionProperties,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002756 icd->gpus[0],
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002757 icd->this_icd_lib->lib_name,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002758 &icd->device_extension_cache[i]);
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002759
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002760 }
2761
2762 if (res != VK_SUCCESS) {
2763 /* clean up any extension lists previously created before this request failed */
2764 for (uint32_t j = 0; j < i; j++) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06002765 loader_destroy_ext_list(
2766 ptr_instance,
2767 &icd->device_extension_cache[i]);
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002768 }
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002769
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002770 return res;
2771 }
2772 }
2773
2774 count += n;
2775 }
2776
2777 icd = icd->next;
2778 }
2779
2780 return VK_SUCCESS;
2781}
2782
Dan Ginsburgf99e4102015-07-23 13:15:00 -04002783VkResult VKAPI loader_EnumeratePhysicalDevices(
Courtney Goeltzenleuchter9f530cb2015-04-20 12:48:54 -06002784 VkInstance instance,
2785 uint32_t* pPhysicalDeviceCount,
2786 VkPhysicalDevice* pPhysicalDevices)
Jon Ashburn349508d2015-01-26 14:51:40 -07002787{
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002788 uint32_t index = 0;
Jon Ashburnb048a9b2015-01-28 19:57:09 -07002789 struct loader_instance *ptr_instance = (struct loader_instance *) instance;
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002790 struct loader_icd *icd = ptr_instance->icds;
Jon Ashburnb048a9b2015-01-28 19:57:09 -07002791
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002792 if (ptr_instance->total_gpu_count == 0) {
2793 loader_init_physical_device_info(ptr_instance);
Jon Ashburnb048a9b2015-01-28 19:57:09 -07002794 }
2795
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002796 *pPhysicalDeviceCount = ptr_instance->total_gpu_count;
2797 if (!pPhysicalDevices) {
2798 return VK_SUCCESS;
2799 }
Jon Ashburnb048a9b2015-01-28 19:57:09 -07002800
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002801 while (icd) {
2802 assert((index + icd->gpu_count) <= *pPhysicalDeviceCount);
Jon Ashburnd5df54d2015-05-28 19:16:58 -06002803 memcpy(&pPhysicalDevices[index], icd->gpus, icd->gpu_count * sizeof(VkPhysicalDevice));
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002804 index += icd->gpu_count;
2805 icd = icd->next;
2806 }
2807
2808 return VK_SUCCESS;
Jon Ashburn349508d2015-01-26 14:51:40 -07002809}
2810
Courtney Goeltzenleuchter01d2ae12015-10-20 16:40:38 -06002811void VKAPI loader_GetPhysicalDeviceProperties(
Jon Ashburn0dd356d2015-05-14 12:43:38 -06002812 VkPhysicalDevice gpu,
Tony Barbour426b9052015-06-24 16:06:58 -06002813 VkPhysicalDeviceProperties* pProperties)
Jon Ashburn0dd356d2015-05-14 12:43:38 -06002814{
2815 uint32_t gpu_index;
Jon Ashburnd5df54d2015-05-28 19:16:58 -06002816 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
Jon Ashburn0dd356d2015-05-14 12:43:38 -06002817
Tony Barbour426b9052015-06-24 16:06:58 -06002818 if (icd->GetPhysicalDeviceProperties)
Courtney Goeltzenleuchter01d2ae12015-10-20 16:40:38 -06002819 icd->GetPhysicalDeviceProperties(gpu, pProperties);
Tony Barbour426b9052015-06-24 16:06:58 -06002820}
2821
Courtney Goeltzenleuchter01d2ae12015-10-20 16:40:38 -06002822void VKAPI loader_GetPhysicalDeviceQueueFamilyProperties (
Tony Barbour426b9052015-06-24 16:06:58 -06002823 VkPhysicalDevice gpu,
Cody Northropef72e2a2015-08-03 17:04:53 -06002824 uint32_t* pCount,
2825 VkQueueFamilyProperties* pProperties)
Tony Barbour426b9052015-06-24 16:06:58 -06002826{
2827 uint32_t gpu_index;
2828 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
Tony Barbour426b9052015-06-24 16:06:58 -06002829
Cody Northropef72e2a2015-08-03 17:04:53 -06002830 if (icd->GetPhysicalDeviceQueueFamilyProperties)
Courtney Goeltzenleuchter01d2ae12015-10-20 16:40:38 -06002831 icd->GetPhysicalDeviceQueueFamilyProperties(gpu, pCount, pProperties);
Tony Barbour426b9052015-06-24 16:06:58 -06002832}
2833
Courtney Goeltzenleuchter01d2ae12015-10-20 16:40:38 -06002834void VKAPI loader_GetPhysicalDeviceMemoryProperties (
Tony Barbour426b9052015-06-24 16:06:58 -06002835 VkPhysicalDevice gpu,
2836 VkPhysicalDeviceMemoryProperties* pProperties)
2837{
2838 uint32_t gpu_index;
2839 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
Tony Barbour426b9052015-06-24 16:06:58 -06002840
2841 if (icd->GetPhysicalDeviceMemoryProperties)
Courtney Goeltzenleuchter01d2ae12015-10-20 16:40:38 -06002842 icd->GetPhysicalDeviceMemoryProperties(gpu, pProperties);
Jon Ashburn0dd356d2015-05-14 12:43:38 -06002843}
2844
Courtney Goeltzenleuchter01d2ae12015-10-20 16:40:38 -06002845void VKAPI loader_GetPhysicalDeviceFeatures(
Chris Forbesd7576302015-06-21 22:55:02 +12002846 VkPhysicalDevice physicalDevice,
2847 VkPhysicalDeviceFeatures* pFeatures)
2848{
2849 uint32_t gpu_index;
2850 struct loader_icd *icd = loader_get_icd(physicalDevice, &gpu_index);
Chris Forbesd7576302015-06-21 22:55:02 +12002851
2852 if (icd->GetPhysicalDeviceFeatures)
Courtney Goeltzenleuchter01d2ae12015-10-20 16:40:38 -06002853 icd->GetPhysicalDeviceFeatures(physicalDevice, pFeatures);
Chris Forbesd7576302015-06-21 22:55:02 +12002854}
2855
Courtney Goeltzenleuchter01d2ae12015-10-20 16:40:38 -06002856void VKAPI loader_GetPhysicalDeviceFormatProperties(
Chris Forbesd7576302015-06-21 22:55:02 +12002857 VkPhysicalDevice physicalDevice,
2858 VkFormat format,
2859 VkFormatProperties* pFormatInfo)
2860{
2861 uint32_t gpu_index;
2862 struct loader_icd *icd = loader_get_icd(physicalDevice, &gpu_index);
Chris Forbesd7576302015-06-21 22:55:02 +12002863
Courtney Goeltzenleuchter4da96aa2015-07-12 12:52:09 -06002864 if (icd->GetPhysicalDeviceFormatProperties)
Courtney Goeltzenleuchter01d2ae12015-10-20 16:40:38 -06002865 icd->GetPhysicalDeviceFormatProperties(physicalDevice, format, pFormatInfo);
Chris Forbesd7576302015-06-21 22:55:02 +12002866}
2867
Courtney Goeltzenleuchter01d2ae12015-10-20 16:40:38 -06002868void VKAPI loader_GetPhysicalDeviceImageFormatProperties(
Jon Ashburn4e189562015-07-23 18:49:07 -06002869 VkPhysicalDevice physicalDevice,
2870 VkFormat format,
2871 VkImageType type,
2872 VkImageTiling tiling,
2873 VkImageUsageFlags usage,
Courtney Goeltzenleuchter83c95f82015-09-10 13:44:12 -06002874 VkImageCreateFlags flags,
Jon Ashburn4e189562015-07-23 18:49:07 -06002875 VkImageFormatProperties* pImageFormatProperties)
2876{
2877 uint32_t gpu_index;
2878 struct loader_icd *icd = loader_get_icd(physicalDevice, &gpu_index);
Jon Ashburn4e189562015-07-23 18:49:07 -06002879
2880 if (icd->GetPhysicalDeviceImageFormatProperties)
Courtney Goeltzenleuchter01d2ae12015-10-20 16:40:38 -06002881 icd->GetPhysicalDeviceImageFormatProperties(physicalDevice, format,
Courtney Goeltzenleuchter83c95f82015-09-10 13:44:12 -06002882 type, tiling, usage, flags, pImageFormatProperties);
Jon Ashburn4e189562015-07-23 18:49:07 -06002883}
2884
Courtney Goeltzenleuchter01d2ae12015-10-20 16:40:38 -06002885void VKAPI loader_GetPhysicalDeviceSparseImageFormatProperties(
Mark Lobodzinski83d4e6a2015-07-03 15:58:09 -06002886 VkPhysicalDevice physicalDevice,
2887 VkFormat format,
2888 VkImageType type,
2889 uint32_t samples,
2890 VkImageUsageFlags usage,
2891 VkImageTiling tiling,
2892 uint32_t* pNumProperties,
2893 VkSparseImageFormatProperties* pProperties)
2894{
2895 uint32_t gpu_index;
2896 struct loader_icd *icd = loader_get_icd(physicalDevice, &gpu_index);
Mark Lobodzinski83d4e6a2015-07-03 15:58:09 -06002897
2898 if (icd->GetPhysicalDeviceSparseImageFormatProperties)
Courtney Goeltzenleuchter01d2ae12015-10-20 16:40:38 -06002899 icd->GetPhysicalDeviceSparseImageFormatProperties(physicalDevice, format, type, samples, usage, tiling, pNumProperties, pProperties);
Mark Lobodzinski83d4e6a2015-07-03 15:58:09 -06002900}
2901
Dan Ginsburgf99e4102015-07-23 13:15:00 -04002902VkResult VKAPI loader_CreateDevice(
Jon Ashburn2666e2f2015-05-15 15:09:35 -06002903 VkPhysicalDevice gpu,
2904 const VkDeviceCreateInfo* pCreateInfo,
2905 VkDevice* pDevice)
2906{
2907 uint32_t gpu_index;
Jon Ashburnd5df54d2015-05-28 19:16:58 -06002908 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06002909 struct loader_device *dev;
Jon Ashburn6853e7e2015-10-26 16:54:51 -06002910 const struct loader_instance *inst;
Courtney Goeltzenleuchter91371ff2015-07-06 20:46:50 -06002911 VkDeviceCreateInfo device_create_info;
2912 char **filtered_extension_names = NULL;
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002913 VkResult res;
Jon Ashburn2666e2f2015-05-15 15:09:35 -06002914
Courtney Goeltzenleuchterdfd53f52015-10-15 16:58:44 -06002915 assert(pCreateInfo->requestedQueueCount >= 1);
Mark Lobodzinski5ea338c2015-09-17 15:17:34 -06002916
Jon Ashburn6853e7e2015-10-26 16:54:51 -06002917 if (!icd)
2918 return VK_ERROR_INITIALIZATION_FAILED;
2919
2920 inst = icd->this_instance;
2921
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002922 if (!icd->CreateDevice) {
2923 return VK_ERROR_INITIALIZATION_FAILED;
Jon Ashburn2666e2f2015-05-15 15:09:35 -06002924 }
2925
Jon Ashburn182b8302015-08-11 14:49:54 -06002926 /* validate any app enabled layers are available */
2927 if (pCreateInfo->layerCount > 0) {
2928 res = loader_validate_layers(pCreateInfo->layerCount,
2929 pCreateInfo->ppEnabledLayerNames,
Jon Ashburne58f1a32015-08-28 13:38:21 -06002930 &inst->device_layer_list);
Jon Ashburn182b8302015-08-11 14:49:54 -06002931 if (res != VK_SUCCESS) {
2932 return res;
2933 }
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002934 }
2935
Jon Ashburne58f1a32015-08-28 13:38:21 -06002936 res = loader_validate_device_extensions(icd, gpu_index, &inst->device_layer_list, pCreateInfo);
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002937 if (res != VK_SUCCESS) {
2938 return res;
2939 }
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002940
Courtney Goeltzenleuchter91371ff2015-07-06 20:46:50 -06002941 /*
2942 * NOTE: Need to filter the extensions to only those
2943 * supported by the ICD.
2944 * No ICD will advertise support for layers. An ICD
2945 * library could support a layer, but it would be
2946 * independent of the actual ICD, just in the same library.
2947 */
2948 filtered_extension_names = loader_stack_alloc(pCreateInfo->extensionCount * sizeof(char *));
2949 if (!filtered_extension_names) {
2950 return VK_ERROR_OUT_OF_HOST_MEMORY;
2951 }
2952
2953 /* Copy user's data */
2954 memcpy(&device_create_info, pCreateInfo, sizeof(VkDeviceCreateInfo));
2955
2956 /* ICD's do not use layers */
2957 device_create_info.layerCount = 0;
2958 device_create_info.ppEnabledLayerNames = NULL;
2959
2960 device_create_info.extensionCount = 0;
2961 device_create_info.ppEnabledExtensionNames = (const char * const *) filtered_extension_names;
2962
2963 for (uint32_t i = 0; i < pCreateInfo->extensionCount; i++) {
2964 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i];
Jon Ashburnc4748dc2015-08-04 11:14:18 -06002965 VkExtensionProperties *prop = get_extension_property(extension_name,
Courtney Goeltzenleuchter91371ff2015-07-06 20:46:50 -06002966 &icd->device_extension_cache[gpu_index]);
2967 if (prop) {
2968 filtered_extension_names[device_create_info.extensionCount] = (char *) extension_name;
2969 device_create_info.extensionCount++;
2970 }
2971 }
2972
Jon Ashburn0c5eea22015-09-30 12:56:42 -06002973 // since gpu object maybe wrapped by a layer need to get unwrapped version
2974 // we haven't yet called down the chain for the layer to unwrap the object
2975 res = icd->CreateDevice(icd->gpus[gpu_index], pCreateInfo, pDevice);
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002976 if (res != VK_SUCCESS) {
2977 return res;
2978 }
2979
Jon Ashburne58f1a32015-08-28 13:38:21 -06002980 dev = loader_add_logical_device(inst, *pDevice, &icd->logical_device_list);
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002981 if (dev == NULL) {
2982 return VK_ERROR_OUT_OF_HOST_MEMORY;
2983 }
2984 PFN_vkGetDeviceProcAddr get_proc_addr = icd->GetDeviceProcAddr;
2985 loader_init_device_dispatch_table(&dev->loader_dispatch, get_proc_addr,
Courtney Goeltzenleuchter08f54e72015-07-16 10:36:57 -06002986 *pDevice, *pDevice);
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002987
2988 dev->loader_dispatch.CreateDevice = scratch_vkCreateDevice;
2989 loader_init_dispatch(*pDevice, &dev->loader_dispatch);
2990
Jon Ashburn182b8302015-08-11 14:49:54 -06002991 /* activate any layers on device chain which terminates with device*/
Jon Ashburne58f1a32015-08-28 13:38:21 -06002992 res = loader_enable_device_layers(inst, icd, dev, pCreateInfo, &inst->device_layer_list);
Jon Ashburn182b8302015-08-11 14:49:54 -06002993 if (res != VK_SUCCESS) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06002994 loader_destroy_logical_device(inst, dev);
Jon Ashburn182b8302015-08-11 14:49:54 -06002995 return res;
2996 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06002997 loader_activate_device_layers(inst, dev, *pDevice);
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002998
2999 res = dev->loader_dispatch.CreateDevice(gpu, pCreateInfo, pDevice);
3000
3001 dev->loader_dispatch.CreateDevice = icd->CreateDevice;
3002
Jon Ashburn2666e2f2015-05-15 15:09:35 -06003003 return res;
3004}
3005
Jon Ashburn8aa75cb2015-09-28 16:15:00 -06003006/**
3007 * Get an instance level or global level entry point address.
3008 * @param instance
3009 * @param pName
3010 * @return
3011 * If instance == NULL returns a global level entrypoint for all core entry points
3012 * If instance is valid returns a instance relative entry point for instance level
3013 * entry points both core and extensions.
3014 * Instance relative means call down the instance chain. Global means trampoline entry points.
3015 */
3016LOADER_EXPORT PFN_vkVoidFunction VKAPI vkGetInstanceProcAddr(VkInstance instance, const char * pName)
Jon Ashburn53c16772015-05-06 10:15:07 -06003017{
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06003018
Jon Ashburncedc15f2015-05-21 18:13:33 -06003019 void *addr;
Jon Ashburn53c16772015-05-06 10:15:07 -06003020
Jon Ashburn8aa75cb2015-09-28 16:15:00 -06003021 if (instance == VK_NULL_HANDLE) {
Jon Ashburn05b4ec62015-10-01 12:03:17 -06003022 /* get entrypoint addresses that are global (in the loader),
3023 doesn't include any instance extensions since they may not be enabled yet*/
Jon Ashburn0c5eea22015-09-30 12:56:42 -06003024
Jon Ashburn8aa75cb2015-09-28 16:15:00 -06003025 addr = globalGetProcAddr(pName);
Jon Ashburn8aa75cb2015-09-28 16:15:00 -06003026
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06003027 return addr;
3028 }
3029
Jon Ashburn05b4ec62015-10-01 12:03:17 -06003030
Jon Ashburn8aa75cb2015-09-28 16:15:00 -06003031 /* return any instance entrypoints that must resolve to loader code */
3032 addr = loader_non_passthrough_gipa(pName);
David Pinedo0fab78b2015-06-24 15:29:18 -06003033 if (addr) {
Jon Ashburn4ebc0962015-06-18 09:05:37 -06003034 return addr;
David Pinedo0fab78b2015-06-24 15:29:18 -06003035 }
Jon Ashburncedc15f2015-05-21 18:13:33 -06003036
Jon Ashburn05b4ec62015-10-01 12:03:17 -06003037 /* debug_report is a special case; need to return loader trampoline entrypoints
3038 * unless the extension is not enabled; also need to handle debug_report
3039 * utility functions */
Jon Ashburn0c5eea22015-09-30 12:56:42 -06003040 struct loader_instance *ptr_instance = loader_get_instance(instance);
Jon Ashburn05b4ec62015-10-01 12:03:17 -06003041 if (debug_report_instance_gpa(ptr_instance, pName, &addr)) {
3042 return addr;
3043 }
3044
3045 /* return the instance dispatch table entrypoint for core and extensions */
Jon Ashburncedc15f2015-05-21 18:13:33 -06003046 const VkLayerInstanceDispatchTable *disp_table = * (VkLayerInstanceDispatchTable **) instance;
3047 if (disp_table == NULL)
3048 return NULL;
3049
3050 addr = loader_lookup_instance_dispatch_table(disp_table, pName);
3051 if (addr)
3052 return addr;
Jon Ashburn53c16772015-05-06 10:15:07 -06003053
Jon Ashburn8aa75cb2015-09-28 16:15:00 -06003054 // NOTE: any instance extensions must be known to loader and resolved
3055 // in the above call to loader_lookup_instance_dispatch_table())
Jon Ashburn53c16772015-05-06 10:15:07 -06003056 return NULL;
3057}
3058
Jon Ashburn8aa75cb2015-09-28 16:15:00 -06003059/**
3060 * Get a device level or global level entry point address.
3061 * @param device
3062 * @param pName
3063 * @return
3064 * If device == NULL, returns a global level entrypoint for all core entry points
3065 * If device is valid, returns a device relative entry point for device level
3066 * entry points both core and extensions.
3067 * Device relative means call down the device chain. Global means trampoline entry points.
3068 */
3069LOADER_EXPORT PFN_vkVoidFunction VKAPI vkGetDeviceProcAddr(VkDevice device, const char * pName)
Courtney Goeltzenleuchter9a4f38c2015-06-22 17:45:21 -06003070{
Jon Ashburn8aa75cb2015-09-28 16:15:00 -06003071 void *addr;
Courtney Goeltzenleuchter9a4f38c2015-06-22 17:45:21 -06003072
Jon Ashburn1245cec2015-05-18 13:20:15 -06003073 if (device == VK_NULL_HANDLE) {
Jon Ashburn8aa75cb2015-09-28 16:15:00 -06003074 /* get entrypoint addresses that are global (in the loader)*/
3075 addr = globalGetProcAddr(pName);
3076 return addr;
Ian Elliott81ac44c2015-01-13 17:52:38 -07003077 }
Jon Ashburne18431b2015-04-13 18:10:06 -06003078
Jon Ashburnd43f9b62014-10-14 19:15:22 -06003079
Jon Ashburne18431b2015-04-13 18:10:06 -06003080 /* for entrypoints that loader must handle (ie non-dispatchable or create object)
3081 make sure the loader entrypoint is returned */
Jon Ashburn8aa75cb2015-09-28 16:15:00 -06003082 addr = loader_non_passthrough_gdpa(pName);
Ian Elliottfdf00b62015-04-15 12:53:19 -06003083 if (addr) {
Jon Ashburne18431b2015-04-13 18:10:06 -06003084 return addr;
Ian Elliottfdf00b62015-04-15 12:53:19 -06003085 }
Jon Ashburne18431b2015-04-13 18:10:06 -06003086
3087 /* return the dispatch table entrypoint for the fastest case */
Jon Ashburn1245cec2015-05-18 13:20:15 -06003088 const VkLayerDispatchTable *disp_table = * (VkLayerDispatchTable **) device;
Jon Ashburnd43f9b62014-10-14 19:15:22 -06003089 if (disp_table == NULL)
3090 return NULL;
3091
Jon Ashburnfce93d92015-05-12 17:26:48 -06003092 addr = loader_lookup_device_dispatch_table(disp_table, pName);
Chia-I Wu38e5a2c2015-01-04 11:12:47 +08003093 if (addr)
3094 return addr;
Jon Ashburnd43f9b62014-10-14 19:15:22 -06003095 else {
Jon Ashburn1245cec2015-05-18 13:20:15 -06003096 if (disp_table->GetDeviceProcAddr == NULL)
Jon Ashburnd43f9b62014-10-14 19:15:22 -06003097 return NULL;
Jon Ashburn1245cec2015-05-18 13:20:15 -06003098 return disp_table->GetDeviceProcAddr(device, pName);
Jon Ashburnd43f9b62014-10-14 19:15:22 -06003099 }
3100}
3101
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -06003102LOADER_EXPORT VkResult VKAPI vkEnumerateInstanceExtensionProperties(
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003103 const char* pLayerName,
3104 uint32_t* pCount,
3105 VkExtensionProperties* pProperties)
3106{
Jon Ashburnb8605fe2015-09-18 12:53:16 -06003107 struct loader_extension_list *global_ext_list=NULL;
Jon Ashburn182b8302015-08-11 14:49:54 -06003108 struct loader_layer_list instance_layers;
Jon Ashburnc1d1eb72015-08-14 11:57:54 -06003109 struct loader_extension_list icd_extensions;
Jon Ashburn754f1992015-08-18 18:04:47 -06003110 struct loader_icd_libs icd_libs;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003111 uint32_t copy_size;
3112
Jon Ashburn413d6582015-08-28 15:19:27 -06003113 tls_instance = NULL;
Jon Ashburnc1d1eb72015-08-14 11:57:54 -06003114 memset(&icd_extensions, 0, sizeof(icd_extensions));
Mike Stroyana73e50c2015-10-01 15:23:48 -06003115 memset(&instance_layers, 0, sizeof(instance_layers));
Jon Ashburn754f1992015-08-18 18:04:47 -06003116 loader_platform_thread_once(&once_init, loader_initialize);
Jon Ashburnc1d1eb72015-08-14 11:57:54 -06003117
Jon Ashburn182b8302015-08-11 14:49:54 -06003118 /* get layer libraries if needed */
3119 if (pLayerName && strlen(pLayerName) != 0) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06003120 loader_layer_scan(NULL, &instance_layers, NULL);
Jon Ashburn182b8302015-08-11 14:49:54 -06003121 for (uint32_t i = 0; i < instance_layers.count; i++) {
3122 struct loader_layer_properties *props = &instance_layers.list[i];
3123 if (strcmp(props->info.layerName, pLayerName) == 0) {
3124 global_ext_list = &props->instance_extension_list;
3125 }
3126 }
3127 }
3128 else {
Jon Ashburn754f1992015-08-18 18:04:47 -06003129 /* Scan/discover all ICD libraries */
3130 memset(&icd_libs, 0 , sizeof(struct loader_icd_libs));
Jon Ashburne58f1a32015-08-28 13:38:21 -06003131 loader_icd_scan(NULL, &icd_libs);
Jon Ashburnc1d1eb72015-08-14 11:57:54 -06003132 /* get extensions from all ICD's, merge so no duplicates */
Jon Ashburne58f1a32015-08-28 13:38:21 -06003133 loader_get_icd_loader_instance_extensions(NULL, &icd_libs, &icd_extensions);
3134 loader_scanned_icd_clear(NULL, &icd_libs);
Jon Ashburnc1d1eb72015-08-14 11:57:54 -06003135 global_ext_list = &icd_extensions;
Jon Ashburn182b8302015-08-11 14:49:54 -06003136 }
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003137
Jon Ashburn182b8302015-08-11 14:49:54 -06003138 if (global_ext_list == NULL) {
Mike Stroyana73e50c2015-10-01 15:23:48 -06003139 loader_destroy_layer_list(NULL, &instance_layers);
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -06003140 return VK_ERROR_LAYER_NOT_PRESENT;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003141 }
3142
3143 if (pProperties == NULL) {
Mike Stroyana73e50c2015-10-01 15:23:48 -06003144 *pCount = global_ext_list->count;
3145 loader_destroy_layer_list(NULL, &instance_layers);
Jon Ashburne58f1a32015-08-28 13:38:21 -06003146 loader_destroy_ext_list(NULL, &icd_extensions);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003147 return VK_SUCCESS;
3148 }
3149
Jon Ashburn182b8302015-08-11 14:49:54 -06003150 copy_size = *pCount < global_ext_list->count ? *pCount : global_ext_list->count;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003151 for (uint32_t i = 0; i < copy_size; i++) {
3152 memcpy(&pProperties[i],
Jon Ashburn182b8302015-08-11 14:49:54 -06003153 &global_ext_list->list[i],
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003154 sizeof(VkExtensionProperties));
3155 }
3156 *pCount = copy_size;
Jon Ashburne58f1a32015-08-28 13:38:21 -06003157 loader_destroy_ext_list(NULL, &icd_extensions);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003158
Jon Ashburn182b8302015-08-11 14:49:54 -06003159 if (copy_size < global_ext_list->count) {
Mike Stroyana73e50c2015-10-01 15:23:48 -06003160 loader_destroy_layer_list(NULL, &instance_layers);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003161 return VK_INCOMPLETE;
3162 }
3163
Mike Stroyana73e50c2015-10-01 15:23:48 -06003164 loader_destroy_layer_list(NULL, &instance_layers);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003165 return VK_SUCCESS;
3166}
3167
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -06003168LOADER_EXPORT VkResult VKAPI vkEnumerateInstanceLayerProperties(
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003169 uint32_t* pCount,
3170 VkLayerProperties* pProperties)
Tony Barbour426b9052015-06-24 16:06:58 -06003171{
Jon Ashburnb40f2562015-05-29 13:15:39 -06003172
Jon Ashburn182b8302015-08-11 14:49:54 -06003173 struct loader_layer_list instance_layer_list;
Jon Ashburn413d6582015-08-28 15:19:27 -06003174 tls_instance = NULL;
Jon Ashburn182b8302015-08-11 14:49:54 -06003175
Jon Ashburn754f1992015-08-18 18:04:47 -06003176 loader_platform_thread_once(&once_init, loader_initialize);
Courtney Goeltzenleuchter0199e952015-02-27 15:19:33 -07003177
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003178 uint32_t copy_size;
Jon Ashburneb2728b2015-04-10 14:33:07 -06003179
Jon Ashburn182b8302015-08-11 14:49:54 -06003180 /* get layer libraries */
3181 memset(&instance_layer_list, 0, sizeof(instance_layer_list));
Jon Ashburne58f1a32015-08-28 13:38:21 -06003182 loader_layer_scan(NULL, &instance_layer_list, NULL);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003183
3184 if (pProperties == NULL) {
Jon Ashburn182b8302015-08-11 14:49:54 -06003185 *pCount = instance_layer_list.count;
Jon Ashburne58f1a32015-08-28 13:38:21 -06003186 loader_destroy_layer_list(NULL, &instance_layer_list);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003187 return VK_SUCCESS;
3188 }
3189
Jon Ashburn182b8302015-08-11 14:49:54 -06003190 copy_size = (*pCount < instance_layer_list.count) ? *pCount : instance_layer_list.count;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003191 for (uint32_t i = 0; i < copy_size; i++) {
Jon Ashburn182b8302015-08-11 14:49:54 -06003192 memcpy(&pProperties[i], &instance_layer_list.list[i].info, sizeof(VkLayerProperties));
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003193 }
3194 *pCount = copy_size;
Jon Ashburne58f1a32015-08-28 13:38:21 -06003195 loader_destroy_layer_list(NULL, &instance_layer_list);
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003196
Jon Ashburn182b8302015-08-11 14:49:54 -06003197 if (copy_size < instance_layer_list.count) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003198 return VK_INCOMPLETE;
3199 }
Tony Barbour426b9052015-06-24 16:06:58 -06003200
3201 return VK_SUCCESS;
3202}
3203
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -06003204VkResult VKAPI loader_EnumerateDeviceExtensionProperties(
Tony Barbour426b9052015-06-24 16:06:58 -06003205 VkPhysicalDevice gpu,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003206 const char* pLayerName,
3207 uint32_t* pCount,
Tony Barbour426b9052015-06-24 16:06:58 -06003208 VkExtensionProperties* pProperties)
3209{
3210 uint32_t gpu_index;
Jon Ashburnd5df54d2015-05-28 19:16:58 -06003211 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003212 uint32_t copy_size;
Courtney Goeltzenleuchter0199e952015-02-27 15:19:33 -07003213
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003214 uint32_t count;
Jon Ashburnb8605fe2015-09-18 12:53:16 -06003215 struct loader_extension_list *dev_ext_list=NULL;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003216
Jon Ashburn182b8302015-08-11 14:49:54 -06003217 /* get layer libraries if needed */
3218 if (pLayerName && strlen(pLayerName) != 0) {
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06003219 for (uint32_t i = 0; i < icd->this_instance->device_layer_list.count; i++) {
3220 struct loader_layer_properties *props = &icd->this_instance->device_layer_list.list[i];
Jon Ashburn182b8302015-08-11 14:49:54 -06003221 if (strcmp(props->info.layerName, pLayerName) == 0) {
3222 dev_ext_list = &props->device_extension_list;
3223 }
3224 }
3225 }
3226 else {
3227 dev_ext_list = &icd->device_extension_cache[gpu_index];
3228 }
3229
Jon Ashburnb8605fe2015-09-18 12:53:16 -06003230 count = (dev_ext_list == NULL) ? 0: dev_ext_list->count;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003231 if (pProperties == NULL) {
3232 *pCount = count;
3233 return VK_SUCCESS;
3234 }
3235
3236 copy_size = *pCount < count ? *pCount : count;
3237 for (uint32_t i = 0; i < copy_size; i++) {
3238 memcpy(&pProperties[i],
Jon Ashburn182b8302015-08-11 14:49:54 -06003239 &dev_ext_list->list[i],
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003240 sizeof(VkExtensionProperties));
3241 }
3242 *pCount = copy_size;
3243
3244 if (copy_size < count) {
3245 return VK_INCOMPLETE;
3246 }
3247
3248 return VK_SUCCESS;
3249}
3250
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -06003251VkResult VKAPI loader_EnumerateDeviceLayerProperties(
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003252 VkPhysicalDevice gpu,
3253 uint32_t* pCount,
3254 VkLayerProperties* pProperties)
3255{
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003256 uint32_t copy_size;
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06003257 uint32_t gpu_index;
3258 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003259
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06003260 uint32_t count = icd->this_instance->device_layer_list.count;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003261
3262 if (pProperties == NULL) {
3263 *pCount = count;
3264 return VK_SUCCESS;
3265 }
3266
Jon Ashburn182b8302015-08-11 14:49:54 -06003267 copy_size = (*pCount < count) ? *pCount : count;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003268 for (uint32_t i = 0; i < copy_size; i++) {
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06003269 memcpy(&pProperties[i], &(icd->this_instance->device_layer_list.list[i].info), sizeof(VkLayerProperties));
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003270 }
3271 *pCount = copy_size;
3272
3273 if (copy_size < count) {
3274 return VK_INCOMPLETE;
3275 }
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003276
3277 return VK_SUCCESS;
Jon Ashburn2666e2f2015-05-15 15:09:35 -06003278}