blob: 9b9455cbebfd1c854a1d07e0a0d760f1c5cd4c14 [file] [log] [blame]
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001/*
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06002 * Vulkan
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08003 *
4 * Copyright (C) 2014 LunarG, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
Chia-I Wu701f3f62014-09-02 08:32:09 +080023 *
24 * Authors:
25 * Chia-I Wu <olv@lunarg.com>
Jon Ashburn01e2d662014-11-14 09:52:42 -070026 * Jon Ashburn <jon@lunarg.com>
Chia-I Wu701f3f62014-09-02 08:32:09 +080027 * Courtney Goeltzenleuchter <courtney@lunarg.com>
Ian Elliott5aa4ea22015-03-31 15:32:41 -060028 * Ian Elliott <ian@lunarg.com>
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080029 */
Jon Ashburn6b4d70c2014-10-22 18:13:16 -060030#define _GNU_SOURCE
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080031#include <stdio.h>
32#include <stdlib.h>
33#include <stdarg.h>
34#include <stdbool.h>
35#include <string.h>
36
Chia-I Wu13a61a52014-08-04 11:18:20 +080037#include <sys/types.h>
Ian Elliott2d4ab1e2015-01-13 17:52:38 -070038#if defined(WIN32)
39#include "dirent_on_windows.h"
40#else // WIN32
Chia-I Wu13a61a52014-08-04 11:18:20 +080041#include <dirent.h>
Ian Elliott2d4ab1e2015-01-13 17:52:38 -070042#endif // WIN32
Tobin Ehlisb835d1b2015-07-03 10:34:49 -060043#include "vk_loader_platform.h"
Chia-I Wu19300602014-08-04 08:03:57 +080044#include "loader.h"
Jon Ashburn27cd5842015-05-12 17:26:48 -060045#include "gpa_helper.h"
46#include "table_ops.h"
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -060047#include "debug_report.h"
Tobin Ehlis0c6f9ee2015-07-03 09:42:57 -060048#include "vk_icd.h"
Jon Ashburn2077e382015-06-29 11:25:34 -060049#include "cJSON.h"
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080050
Courtney Goeltzenleuchtered488302015-06-01 14:09:34 -060051static loader_platform_dl_handle loader_add_layer_lib(
Jon Ashburne39a4f82015-08-28 13:38:21 -060052 const struct loader_instance *inst,
Courtney Goeltzenleuchtered488302015-06-01 14:09:34 -060053 const char *chain_type,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -060054 struct loader_layer_properties *layer_prop);
Courtney Goeltzenleuchtered488302015-06-01 14:09:34 -060055
56static void loader_remove_layer_lib(
57 struct loader_instance *inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -060058 struct loader_layer_properties *layer_prop);
Courtney Goeltzenleuchtered488302015-06-01 14:09:34 -060059
Jon Ashburn27cd5842015-05-12 17:26:48 -060060struct loader_struct loader = {0};
Jon Ashburn87d6aa92015-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 Ashburne39a4f82015-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 Goeltzenleuchter9ec39ac2015-06-22 17:45:21 -060067
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -060068enum loader_debug {
Courtney Goeltzenleuchterf3387652015-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 Goeltzenleuchter880a2a72015-06-08 15:11:18 -060074};
75
76uint32_t g_loader_debug = 0;
77uint32_t g_loader_log_msgs = 0;
78
Jon Ashburn6301a0f2015-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 Ashburn2077e382015-06-29 11:25:34 -060081// additionally CreateDevice and DestroyDevice needs to be locked
Jon Ashburn6301a0f2015-05-29 13:15:39 -060082loader_platform_thread_mutex loader_lock;
Jon Ashburn6461ef22015-09-22 13:11:00 -060083loader_platform_thread_mutex loader_json_lock;
Jon Ashburn6301a0f2015-05-29 13:15:39 -060084
Ian Elliottd3ef02f2015-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 Ashburn6301a0f2015-05-29 13:15:39 -060088const VkLayerInstanceDispatchTable instance_disp = {
Jon Ashburn69e9ea22015-09-28 16:15:00 -060089 .GetInstanceProcAddr = vkGetInstanceProcAddr,
Jon Ashburn27cd5842015-05-12 17:26:48 -060090 .CreateInstance = loader_CreateInstance,
91 .DestroyInstance = loader_DestroyInstance,
92 .EnumeratePhysicalDevices = loader_EnumeratePhysicalDevices,
Chris Forbesbc0bb772015-06-21 22:55:02 +120093 .GetPhysicalDeviceFeatures = loader_GetPhysicalDeviceFeatures,
Courtney Goeltzenleuchter2caec862015-07-12 12:52:09 -060094 .GetPhysicalDeviceFormatProperties = loader_GetPhysicalDeviceFormatProperties,
Jon Ashburn754864f2015-07-23 18:49:07 -060095 .GetPhysicalDeviceImageFormatProperties = loader_GetPhysicalDeviceImageFormatProperties,
Tony Barbour59a47322015-06-24 16:06:58 -060096 .GetPhysicalDeviceProperties = loader_GetPhysicalDeviceProperties,
Cody Northropd0802882015-08-03 17:04:53 -060097 .GetPhysicalDeviceQueueFamilyProperties = loader_GetPhysicalDeviceQueueFamilyProperties,
Tony Barbour59a47322015-06-24 16:06:58 -060098 .GetPhysicalDeviceMemoryProperties = loader_GetPhysicalDeviceMemoryProperties,
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -060099 .EnumerateDeviceExtensionProperties = loader_EnumerateDeviceExtensionProperties,
100 .EnumerateDeviceLayerProperties = loader_EnumerateDeviceLayerProperties,
Mark Lobodzinski16e8bef2015-07-03 15:58:09 -0600101 .GetPhysicalDeviceSparseImageFormatProperties = loader_GetPhysicalDeviceSparseImageFormatProperties,
Ian Elliott7e40db92015-08-21 15:09:33 -0600102 .GetPhysicalDeviceSurfaceSupportKHR = loader_GetPhysicalDeviceSurfaceSupportKHR,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600103 .DbgCreateMsgCallback = loader_DbgCreateMsgCallback,
104 .DbgDestroyMsgCallback = loader_DbgDestroyMsgCallback,
Jon Ashburn27cd5842015-05-12 17:26:48 -0600105};
106
Jon Ashburn8810c5f2015-08-18 18:04:47 -0600107LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_init);
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700108
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600109void* loader_heap_alloc(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600110 const struct loader_instance *instance,
111 size_t size,
112 VkSystemAllocType alloc_type)
Courtney Goeltzenleuchter7f5aafc2015-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
121void* loader_aligned_heap_alloc(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600122 const struct loader_instance *instance,
123 size_t size,
124 size_t alignment,
125 VkSystemAllocType alloc_type)
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600126{
Jon Ashburneacfa3a2015-08-14 12:51:47 -0600127 if (instance && instance->alloc_callbacks.pfnAlloc) {
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600128 return instance->alloc_callbacks.pfnAlloc(instance->alloc_callbacks.pUserData, size, alignment, alloc_type);
129 }
Cody Northrop33fa0412015-07-08 16:48:37 -0600130#if defined(_WIN32)
131 return _aligned_malloc(alignment, size);
132#else
133 return aligned_alloc(alignment, size);
134#endif
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600135}
136
137void loader_heap_free(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600138 const struct loader_instance *instance,
139 void *pMem)
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600140{
Mike Stroyan09c06c72015-10-01 15:23:48 -0600141 if (pMem == NULL) return;
Jon Ashburneacfa3a2015-08-14 12:51:47 -0600142 if (instance && instance->alloc_callbacks.pfnFree) {
Courtney Goeltzenleuchter922e1452015-07-10 17:39:59 -0600143 instance->alloc_callbacks.pfnFree(instance->alloc_callbacks.pUserData, pMem);
Jon Ashburnd2c171b2015-08-13 08:28:48 -0600144 return;
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600145 }
Courtney Goeltzenleuchter922e1452015-07-10 17:39:59 -0600146 free(pMem);
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600147}
148
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600149void* loader_heap_realloc(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600150 const struct loader_instance *instance,
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600151 void *pMem,
152 size_t orig_size,
153 size_t size,
154 VkSystemAllocType alloc_type)
155{
156 if (pMem == NULL || orig_size == 0)
157 return loader_heap_alloc(instance, size, alloc_type);
158 if (size == 0) {
159 loader_heap_free(instance, pMem);
160 return NULL;
161 }
162 if (instance && instance->alloc_callbacks.pfnAlloc) {
163 if (size <= orig_size) {
164 memset(((uint8_t *)pMem) + size, 0, orig_size - size);
165 return pMem;
166 }
167 void *new_ptr = instance->alloc_callbacks.pfnAlloc(instance->alloc_callbacks.pUserData, size, 4, alloc_type);
168 if (!new_ptr)
169 return NULL;
170 memcpy(new_ptr, pMem, orig_size);
171 instance->alloc_callbacks.pfnFree(instance->alloc_callbacks.pUserData, pMem);
172 }
173 return realloc(pMem, size);
174}
175
Jon Ashburn87d6aa92015-08-28 15:19:27 -0600176void *loader_tls_heap_alloc(size_t size)
177{
178 return loader_heap_alloc(tls_instance, size, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
179}
180
181void loader_tls_heap_free(void *pMem)
182{
183 return loader_heap_free(tls_instance, pMem);
184}
185
Jon Ashburnffad94d2015-06-30 14:46:22 -0700186static void loader_log(VkFlags msg_type, int32_t msg_code,
187 const char *format, ...)
188{
Jon Ashburn86723b02015-07-31 15:47:59 -0600189 char msg[512];
Jon Ashburnffad94d2015-06-30 14:46:22 -0700190 va_list ap;
191 int ret;
192
193 if (!(msg_type & g_loader_log_msgs)) {
194 return;
195 }
196
197 va_start(ap, format);
198 ret = vsnprintf(msg, sizeof(msg), format, ap);
199 if ((ret >= (int) sizeof(msg)) || ret < 0) {
200 msg[sizeof(msg)-1] = '\0';
201 }
202 va_end(ap);
203
Ian Elliott4470a302015-02-17 10:33:47 -0700204#if defined(WIN32)
Jon Ashburnffad94d2015-06-30 14:46:22 -0700205 OutputDebugString(msg);
mschottb9cdb782015-07-22 14:11:29 +0200206 OutputDebugString("\n");
Jon Ashburnffad94d2015-06-30 14:46:22 -0700207#endif
208 fputs(msg, stderr);
209 fputc('\n', stderr);
210}
211
212#if defined(WIN32)
Tony Barbourea968902015-07-29 14:26:21 -0600213static char *loader_get_next_path(char *path);
Jon Ashburnffad94d2015-06-30 14:46:22 -0700214/**
215* Find the list of registry files (names within a key) in key "location".
216*
217* This function looks in the registry (hive = DEFAULT_VK_REGISTRY_HIVE) key as given in "location"
218* for a list or name/values which are added to a returned list (function return value).
219* The DWORD values within the key must be 0 or they are skipped.
Jon Ashburne39a4f82015-08-28 13:38:21 -0600220* Function return is a string with a ';' separated list of filenames.
Jon Ashburnffad94d2015-06-30 14:46:22 -0700221* Function return is NULL if no valid name/value pairs are found in the key,
222* or the key is not found.
223*
224* \returns
225* A string list of filenames as pointer.
226* When done using the returned string list, pointer should be freed.
227*/
Jon Ashburne39a4f82015-08-28 13:38:21 -0600228static char *loader_get_registry_files(const struct loader_instance *inst, char *location)
Jon Ashburnffad94d2015-06-30 14:46:22 -0700229{
230 LONG rtn_value;
231 HKEY hive, key;
232 DWORD access_flags = KEY_QUERY_VALUE;
233 char name[2048];
234 char *out = NULL;
Tony Barbourea968902015-07-29 14:26:21 -0600235 char *loc = location;
236 char *next;
Jon Ashburnffad94d2015-06-30 14:46:22 -0700237 DWORD idx = 0;
238 DWORD name_size = sizeof(name);
239 DWORD value;
240 DWORD total_size = 4096;
241 DWORD value_size = sizeof(value);
Tony Barbourea968902015-07-29 14:26:21 -0600242
243 while(*loc)
244 {
245 next = loader_get_next_path(loc);
246 hive = DEFAULT_VK_REGISTRY_HIVE;
247 rtn_value = RegOpenKeyEx(hive, loc, 0, access_flags, &key);
248 if (rtn_value != ERROR_SUCCESS) {
249 // We didn't find the key. Try the 32-bit hive (where we've seen the
250 // key end up on some people's systems):
251 access_flags |= KEY_WOW64_32KEY;
252 rtn_value = RegOpenKeyEx(hive, loc, 0, access_flags, &key);
253 if (rtn_value != ERROR_SUCCESS) {
254 // We still couldn't find the key, so give up:
255 loc = next;
256 continue;
Jon Ashburnffad94d2015-06-30 14:46:22 -0700257 }
Jon Ashburnffad94d2015-06-30 14:46:22 -0700258 }
Tony Barbourea968902015-07-29 14:26:21 -0600259
Jon Ashburne39a4f82015-08-28 13:38:21 -0600260 while ((rtn_value = RegEnumValue(key, idx++, name, &name_size, NULL, NULL, (LPBYTE) &value, &value_size)) == ERROR_SUCCESS) {
Tony Barbourea968902015-07-29 14:26:21 -0600261 if (value_size == sizeof(value) && value == 0) {
262 if (out == NULL) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600263 out = loader_heap_alloc(inst, total_size, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Tony Barbourea968902015-07-29 14:26:21 -0600264 out[0] = '\0';
265 }
266 else if (strlen(out) + name_size + 1 > total_size) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600267 out = loader_heap_realloc(inst, out, total_size, total_size * 2, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Tony Barbourea968902015-07-29 14:26:21 -0600268 total_size *= 2;
269 }
270 if (out == NULL) {
271 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory, failed loader_get_registry_files");
272 return NULL;
273 }
274 if (strlen(out) == 0)
275 snprintf(out, name_size + 1, "%s", name);
276 else
277 snprintf(out + strlen(out), name_size + 2, "%c%s", PATH_SEPERATOR, name);
278 }
279 name_size = 2048;
280 }
281 loc = next;
Jon Ashburnffad94d2015-06-30 14:46:22 -0700282 }
Tony Barbourea968902015-07-29 14:26:21 -0600283
Jon Ashburnffad94d2015-06-30 14:46:22 -0700284 return out;
285}
286
Ian Elliott4470a302015-02-17 10:33:47 -0700287#endif // WIN32
288
Jon Ashburnc7237a72015-08-03 09:08:46 -0600289/**
290 * Given string of three part form "maj.min.pat" convert to a vulkan version
291 * number.
292 */
293static uint32_t loader_make_version(const char *vers_str)
294{
Jon Ashburn432d2762015-09-18 12:53:16 -0600295 uint32_t vers = 0, major=0, minor=0, patch=0;
Jon Ashburnc7237a72015-08-03 09:08:46 -0600296 char *minor_str= NULL;
297 char *patch_str = NULL;
298 char *cstr;
299 char *str;
300
301 if (!vers_str)
302 return vers;
303 cstr = loader_stack_alloc(strlen(vers_str) + 1);
304 strcpy(cstr, vers_str);
305 while ((str = strchr(cstr, '.')) != NULL) {
306 if (minor_str == NULL) {
307 minor_str = str + 1;
308 *str = '\0';
309 major = atoi(cstr);
310 }
311 else if (patch_str == NULL) {
312 patch_str = str + 1;
313 *str = '\0';
314 minor = atoi(minor_str);
315 }
316 else {
317 return vers;
318 }
319 cstr = str + 1;
320 }
321 patch = atoi(patch_str);
322
323 return VK_MAKE_VERSION(major, minor, patch);
324
325}
326
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600327bool compare_vk_extension_properties(const VkExtensionProperties *op1, const VkExtensionProperties *op2)
328{
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600329 return strcmp(op1->extName, op2->extName) == 0 ? true : false;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600330}
331
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -0600332/**
Jon Ashburnbd6c4882015-07-02 12:59:25 -0600333 * Search the given ext_array for an extension
334 * matching the given vk_ext_prop
335 */
336bool has_vk_extension_property_array(
337 const VkExtensionProperties *vk_ext_prop,
338 const uint32_t count,
339 const VkExtensionProperties *ext_array)
340{
341 for (uint32_t i = 0; i < count; i++) {
342 if (compare_vk_extension_properties(vk_ext_prop, &ext_array[i]))
343 return true;
344 }
345 return false;
346}
347
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -0600348/**
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600349 * Search the given ext_list for an extension
350 * matching the given vk_ext_prop
351 */
352bool has_vk_extension_property(
353 const VkExtensionProperties *vk_ext_prop,
354 const struct loader_extension_list *ext_list)
355{
356 for (uint32_t i = 0; i < ext_list->count; i++) {
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600357 if (compare_vk_extension_properties(&ext_list->list[i], vk_ext_prop))
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600358 return true;
359 }
360 return false;
361}
362
Jon Ashburnb2ef1372015-07-16 17:19:31 -0600363static inline bool loader_is_layer_type_device(const enum layer_type type) {
364 if ((type & VK_LAYER_TYPE_DEVICE_EXPLICIT) ||
365 (type & VK_LAYER_TYPE_DEVICE_IMPLICIT))
366 return true;
367 return false;
368}
369
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600370/*
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -0600371 * Search the given layer list for a layer matching the given layer name
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600372 */
Jon Ashburne13ecc92015-08-03 17:19:30 -0600373static struct loader_layer_properties *loader_get_layer_property(
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600374 const char *name,
375 const struct loader_layer_list *layer_list)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600376{
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600377 for (uint32_t i = 0; i < layer_list->count; i++) {
378 const VkLayerProperties *item = &layer_list->list[i].info;
379 if (strcmp(name, item->layerName) == 0)
380 return &layer_list->list[i];
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600381 }
382 return NULL;
383}
384
Jon Ashburne13ecc92015-08-03 17:19:30 -0600385/**
386 * Get the next unused layer property in the list. Init the property to zero.
387 */
388static struct loader_layer_properties *loader_get_next_layer_property(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600389 const struct loader_instance *inst,
Jon Ashburne13ecc92015-08-03 17:19:30 -0600390 struct loader_layer_list *layer_list)
391{
392 if (layer_list->capacity == 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600393 layer_list->list = loader_heap_alloc(inst,
394 sizeof(struct loader_layer_properties) * 64,
395 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburne13ecc92015-08-03 17:19:30 -0600396 if (layer_list->list == NULL) {
397 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't add any layer properties to list");
398 return NULL;
399 }
400 memset(layer_list->list, 0, sizeof(struct loader_layer_properties) * 64);
401 layer_list->capacity = sizeof(struct loader_layer_properties) * 64;
402 }
403
404 // ensure enough room to add an entry
405 if ((layer_list->count + 1) * sizeof (struct loader_layer_properties)
406 > layer_list->capacity) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600407 layer_list->list = loader_heap_realloc(inst, layer_list->list,
408 layer_list->capacity,
409 layer_list->capacity * 2,
410 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburne13ecc92015-08-03 17:19:30 -0600411 if (layer_list->list == NULL) {
412 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
413 "realloc failed for layer list");
414 }
415 layer_list->capacity *= 2;
416 }
417
418 layer_list->count++;
419 return &(layer_list->list[layer_list->count - 1]);
420}
421
422/**
423 * Remove all layer properties entrys from the list
424 */
Jon Ashburne39a4f82015-08-28 13:38:21 -0600425void loader_delete_layer_properties(
426 const struct loader_instance *inst,
427 struct loader_layer_list *layer_list)
Jon Ashburne13ecc92015-08-03 17:19:30 -0600428{
429 uint32_t i;
430
Jon Ashburnb82c1852015-08-11 14:49:54 -0600431 if (!layer_list)
432 return;
433
Jon Ashburne13ecc92015-08-03 17:19:30 -0600434 for (i = 0; i < layer_list->count; i++) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600435 loader_destroy_ext_list(inst, &layer_list->list[i].instance_extension_list);
436 loader_destroy_ext_list(inst, &layer_list->list[i].device_extension_list);
Jon Ashburne13ecc92015-08-03 17:19:30 -0600437 }
438 layer_list->count = 0;
439
Jon Ashburnb82c1852015-08-11 14:49:54 -0600440 if (layer_list->capacity > 0) {
441 layer_list->capacity = 0;
Jon Ashburne39a4f82015-08-28 13:38:21 -0600442 loader_heap_free(inst, layer_list->list);
Jon Ashburnb82c1852015-08-11 14:49:54 -0600443 }
Jon Ashburne13ecc92015-08-03 17:19:30 -0600444
445}
446
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600447static void loader_add_global_extensions(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600448 const struct loader_instance *inst,
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -0600449 const PFN_vkEnumerateInstanceExtensionProperties fp_get_props,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600450 const char *lib_name,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600451 struct loader_extension_list *ext_list)
452{
453 uint32_t i, count;
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600454 VkExtensionProperties *ext_props;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600455 VkResult res;
456
Courtney Goeltzenleuchter5c6cf472015-07-06 22:28:18 -0600457 if (!fp_get_props) {
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -0600458 /* No EnumerateInstanceExtensionProperties defined */
Courtney Goeltzenleuchter5c6cf472015-07-06 22:28:18 -0600459 return;
460 }
461
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600462 res = fp_get_props(NULL, &count, NULL);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600463 if (res != VK_SUCCESS) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600464 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Error getting global extension count from %s", lib_name);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600465 return;
466 }
Jon Ashburn953bb3c2015-06-10 16:11:42 -0600467
Courtney Goeltzenleuchter5c6cf472015-07-06 22:28:18 -0600468 if (count == 0) {
469 /* No ExtensionProperties to report */
470 return;
471 }
472
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600473 ext_props = loader_stack_alloc(count * sizeof(VkExtensionProperties));
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600474
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600475 res = fp_get_props(NULL, &count, ext_props);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600476 if (res != VK_SUCCESS) {
477 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Error getting global extensions from %s", lib_name);
478 return;
479 }
Tony Barbour59a47322015-06-24 16:06:58 -0600480
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600481 for (i = 0; i < count; i++) {
Courtney Goeltzenleuchter53043732015-07-12 13:20:05 -0600482 char spec_version[64];
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600483
484 snprintf(spec_version, sizeof(spec_version), "%d.%d.%d",
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600485 VK_MAJOR(ext_props[i].specVersion),
486 VK_MINOR(ext_props[i].specVersion),
487 VK_PATCH(ext_props[i].specVersion));
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600488 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Courtney Goeltzenleuchter53043732015-07-12 13:20:05 -0600489 "Global Extension: %s (%s) version %s",
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600490 ext_props[i].extName, lib_name, spec_version);
Jon Ashburne39a4f82015-08-28 13:38:21 -0600491 loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600492 }
493
494 return;
495}
496
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600497static void loader_add_physical_device_extensions(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600498 const struct loader_instance *inst,
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -0600499 PFN_vkEnumerateDeviceExtensionProperties get_phys_dev_ext_props,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600500 VkPhysicalDevice physical_device,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600501 const char *lib_name,
502 struct loader_extension_list *ext_list)
503{
504 uint32_t i, count;
505 VkResult res;
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600506 VkExtensionProperties *ext_props;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600507
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600508 if (!get_phys_dev_ext_props) {
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -0600509 /* No EnumerateDeviceExtensionProperties defined */
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600510 return;
511 }
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600512
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600513 res = get_phys_dev_ext_props(physical_device, NULL, &count, NULL);
514 if (res == VK_SUCCESS && count > 0) {
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600515 ext_props = loader_stack_alloc(count * sizeof(VkExtensionProperties));
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600516
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600517 res = get_phys_dev_ext_props(physical_device, NULL, &count, ext_props);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600518 for (i = 0; i < count; i++) {
Courtney Goeltzenleuchter53043732015-07-12 13:20:05 -0600519 char spec_version[64];
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600520
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600521 snprintf(spec_version, sizeof(spec_version), "%d.%d.%d",
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600522 VK_MAJOR(ext_props[i].specVersion),
523 VK_MINOR(ext_props[i].specVersion),
524 VK_PATCH(ext_props[i].specVersion));
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600525 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Courtney Goeltzenleuchter53043732015-07-12 13:20:05 -0600526 "PhysicalDevice Extension: %s (%s) version %s",
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600527 ext_props[i].extName, lib_name, spec_version);
Jon Ashburne39a4f82015-08-28 13:38:21 -0600528 loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
Jon Ashburn953bb3c2015-06-10 16:11:42 -0600529 }
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600530 } else {
Jon Ashburnf73e9212015-08-04 10:22:33 -0600531 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Error getting physical device extension info count from library %s", lib_name);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600532 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600533
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600534 return;
535}
536
Jon Ashburne39a4f82015-08-28 13:38:21 -0600537static bool loader_init_ext_list(const struct loader_instance *inst,
538 struct loader_extension_list *ext_info)
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600539{
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600540 ext_info->capacity = 32 * sizeof(VkExtensionProperties);
Jon Ashburne39a4f82015-08-28 13:38:21 -0600541 ext_info->list = loader_heap_alloc(inst, ext_info->capacity, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600542 if (ext_info->list == NULL) {
543 return false;
544 }
545 memset(ext_info->list, 0, ext_info->capacity);
546 ext_info->count = 0;
547 return true;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600548}
549
Jon Ashburne39a4f82015-08-28 13:38:21 -0600550void loader_destroy_ext_list(const struct loader_instance *inst,
551 struct loader_extension_list *ext_info)
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600552{
Jon Ashburne39a4f82015-08-28 13:38:21 -0600553 loader_heap_free(inst, ext_info->list);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600554 ext_info->count = 0;
555 ext_info->capacity = 0;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600556}
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600557
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600558/*
559 * Append non-duplicate extension properties defined in props
560 * to the given ext_list.
561 */
562void loader_add_to_ext_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600563 const struct loader_instance *inst,
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600564 struct loader_extension_list *ext_list,
565 uint32_t prop_list_count,
566 const VkExtensionProperties *props)
567{
568 uint32_t i;
569 const VkExtensionProperties *cur_ext;
570
571 if (ext_list->list == NULL || ext_list->capacity == 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600572 loader_init_ext_list(inst, ext_list);
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600573 }
574
575 if (ext_list->list == NULL)
576 return;
577
578 for (i = 0; i < prop_list_count; i++) {
579 cur_ext = &props[i];
580
581 // look for duplicates
582 if (has_vk_extension_property(cur_ext, ext_list)) {
583 continue;
584 }
585
586 // add to list at end
587 // check for enough capacity
588 if (ext_list->count * sizeof(VkExtensionProperties)
589 >= ext_list->capacity) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600590
591 ext_list->list = loader_heap_realloc(inst,
592 ext_list->list,
593 ext_list->capacity,
594 ext_list->capacity * 2,
595 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600596 // double capacity
597 ext_list->capacity *= 2;
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600598 }
599
600 memcpy(&ext_list->list[ext_list->count], cur_ext, sizeof(VkExtensionProperties));
601 ext_list->count++;
602 }
603}
604
Jon Ashburnbd6c4882015-07-02 12:59:25 -0600605/**
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600606 * Search the given search_list for any layers in the props list.
607 * Add these to the output layer_list. Don't add duplicates to the output layer_list.
Jon Ashburnbd6c4882015-07-02 12:59:25 -0600608 */
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -0600609static VkResult loader_add_layer_names_to_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600610 const struct loader_instance *inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600611 struct loader_layer_list *output_list,
612 uint32_t name_count,
613 const char * const *names,
614 const struct loader_layer_list *search_list)
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600615{
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600616 struct loader_layer_properties *layer_prop;
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -0600617 VkResult err = VK_SUCCESS;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600618
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600619 for (uint32_t i = 0; i < name_count; i++) {
620 const char *search_target = names[i];
Jon Ashburne13ecc92015-08-03 17:19:30 -0600621 layer_prop = loader_get_layer_property(search_target, search_list);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600622 if (!layer_prop) {
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -0600623 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Unable to find layer %s", search_target);
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -0600624 err = VK_ERROR_LAYER_NOT_PRESENT;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600625 continue;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600626 }
627
Jon Ashburne39a4f82015-08-28 13:38:21 -0600628 loader_add_to_layer_list(inst, output_list, 1, layer_prop);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600629 }
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -0600630
631 return err;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600632}
633
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600634
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600635/*
636 * Manage lists of VkLayerProperties
637 */
Jon Ashburne39a4f82015-08-28 13:38:21 -0600638static bool loader_init_layer_list(const struct loader_instance *inst,
639 struct loader_layer_list *list)
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600640{
641 list->capacity = 32 * sizeof(struct loader_layer_properties);
Jon Ashburne39a4f82015-08-28 13:38:21 -0600642 list->list = loader_heap_alloc(inst, list->capacity, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600643 if (list->list == NULL) {
644 return false;
645 }
646 memset(list->list, 0, list->capacity);
647 list->count = 0;
648 return true;
649}
650
Jon Ashburne39a4f82015-08-28 13:38:21 -0600651void loader_destroy_layer_list(const struct loader_instance *inst,
652 struct loader_layer_list *layer_list)
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600653{
Jon Ashburne39a4f82015-08-28 13:38:21 -0600654 loader_heap_free(inst, layer_list->list);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600655 layer_list->count = 0;
656 layer_list->capacity = 0;
657}
658
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600659/*
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600660 * Manage list of layer libraries (loader_lib_info)
661 */
Jon Ashburne39a4f82015-08-28 13:38:21 -0600662static bool loader_init_layer_library_list(const struct loader_instance *inst,
663 struct loader_layer_library_list *list)
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600664{
665 list->capacity = 32 * sizeof(struct loader_lib_info);
Jon Ashburne39a4f82015-08-28 13:38:21 -0600666 list->list = loader_heap_alloc(inst, list->capacity, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600667 if (list->list == NULL) {
668 return false;
669 }
670 memset(list->list, 0, list->capacity);
671 list->count = 0;
672 return true;
673}
674
Jon Ashburne39a4f82015-08-28 13:38:21 -0600675void loader_destroy_layer_library_list(const struct loader_instance *inst,
676 struct loader_layer_library_list *list)
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600677{
678 for (uint32_t i = 0; i < list->count; i++) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600679 loader_heap_free(inst, list->list[i].lib_name);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600680 }
Jon Ashburne39a4f82015-08-28 13:38:21 -0600681 loader_heap_free(inst, list->list);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600682 list->count = 0;
683 list->capacity = 0;
684}
685
686void loader_add_to_layer_library_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600687 const struct loader_instance *inst,
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600688 struct loader_layer_library_list *list,
689 uint32_t item_count,
690 const struct loader_lib_info *new_items)
691{
692 uint32_t i;
693 struct loader_lib_info *item;
694
695 if (list->list == NULL || list->capacity == 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600696 loader_init_layer_library_list(inst, list);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600697 }
698
699 if (list->list == NULL)
700 return;
701
702 for (i = 0; i < item_count; i++) {
703 item = (struct loader_lib_info *) &new_items[i];
704
705 // look for duplicates
706 for (uint32_t j = 0; j < list->count; j++) {
707 if (strcmp(list->list[i].lib_name, new_items->lib_name) == 0) {
708 continue;
709 }
710 }
711
712 // add to list at end
713 // check for enough capacity
714 if (list->count * sizeof(struct loader_lib_info)
715 >= list->capacity) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600716
717 list->list = loader_heap_realloc(inst,
718 list->list,
719 list->capacity,
720 list->capacity * 2,
721 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600722 // double capacity
723 list->capacity *= 2;
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600724 }
725
726 memcpy(&list->list[list->count], item, sizeof(struct loader_lib_info));
727 list->count++;
728 }
729}
730
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600731
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600732/*
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600733 * Search the given layer list for a list
734 * matching the given VkLayerProperties
735 */
736bool has_vk_layer_property(
737 const VkLayerProperties *vk_layer_prop,
738 const struct loader_layer_list *list)
739{
740 for (uint32_t i = 0; i < list->count; i++) {
741 if (strcmp(vk_layer_prop->layerName, list->list[i].info.layerName) == 0)
742 return true;
743 }
744 return false;
745}
746
747/*
748 * Search the given layer list for a layer
749 * matching the given name
750 */
751bool has_layer_name(
752 const char *name,
753 const struct loader_layer_list *list)
754{
755 for (uint32_t i = 0; i < list->count; i++) {
756 if (strcmp(name, list->list[i].info.layerName) == 0)
757 return true;
758 }
759 return false;
760}
761
762/*
763 * Append non-duplicate layer properties defined in prop_list
764 * to the given layer_info list
765 */
766void loader_add_to_layer_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600767 const struct loader_instance *inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600768 struct loader_layer_list *list,
769 uint32_t prop_list_count,
770 const struct loader_layer_properties *props)
771{
772 uint32_t i;
773 struct loader_layer_properties *layer;
774
775 if (list->list == NULL || list->capacity == 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600776 loader_init_layer_list(inst, list);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600777 }
778
779 if (list->list == NULL)
780 return;
781
782 for (i = 0; i < prop_list_count; i++) {
783 layer = (struct loader_layer_properties *) &props[i];
784
785 // look for duplicates
786 if (has_vk_layer_property(&layer->info, list)) {
787 continue;
788 }
789
790 // add to list at end
791 // check for enough capacity
792 if (list->count * sizeof(struct loader_layer_properties)
793 >= list->capacity) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600794
795 list->list = loader_heap_realloc(inst,
796 list->list,
797 list->capacity,
798 list->capacity * 2,
799 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600800 // double capacity
801 list->capacity *= 2;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600802 }
803
804 memcpy(&list->list[list->count], layer, sizeof(struct loader_layer_properties));
805 list->count++;
806 }
807}
808
Jon Ashburnbd332cc2015-07-07 10:27:45 -0600809/**
810 * Search the search_list for any layer with a name
811 * that matches the given name and a type that matches the given type
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600812 * Add all matching layers to the found_list
Jon Ashburnbd332cc2015-07-07 10:27:45 -0600813 * Do not add if found loader_layer_properties is already
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600814 * on the found_list.
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600815 */
Jon Ashburnbd6c4882015-07-02 12:59:25 -0600816static void loader_find_layer_name_add_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600817 const struct loader_instance *inst,
Jon Ashburnbd6c4882015-07-02 12:59:25 -0600818 const char *name,
Jon Ashburnbd332cc2015-07-07 10:27:45 -0600819 const enum layer_type type,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600820 const struct loader_layer_list *search_list,
821 struct loader_layer_list *found_list)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600822{
Jon Ashburn56151d62015-10-05 09:03:21 -0600823 bool found = false;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600824 for (uint32_t i = 0; i < search_list->count; i++) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600825 struct loader_layer_properties *layer_prop = &search_list->list[i];
Jon Ashburnbd332cc2015-07-07 10:27:45 -0600826 if (0 == strcmp(layer_prop->info.layerName, name) &&
827 (layer_prop->type & type)) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600828 /* Found a layer with the same name, add to found_list */
Jon Ashburne39a4f82015-08-28 13:38:21 -0600829 loader_add_to_layer_list(inst, found_list, 1, layer_prop);
Jon Ashburn56151d62015-10-05 09:03:21 -0600830 found = true;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600831 }
832 }
Jon Ashburn56151d62015-10-05 09:03:21 -0600833 if (!found) {
834 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Warning, couldn't find layer name %s to activate", name);
835 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600836}
837
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600838static VkExtensionProperties *get_extension_property(
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -0600839 const char *name,
840 const struct loader_extension_list *list)
Jon Ashburnfc2e38c2015-04-14 09:15:32 -0600841{
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -0600842 for (uint32_t i = 0; i < list->count; i++) {
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600843 if (strcmp(name, list->list[i].extName) == 0)
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -0600844 return &list->list[i];
Jon Ashburnfc2e38c2015-04-14 09:15:32 -0600845 }
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -0600846 return NULL;
Jon Ashburnfc2e38c2015-04-14 09:15:32 -0600847}
848
Jon Ashburnbd6c4882015-07-02 12:59:25 -0600849/*
850 * For global exenstions implemented within the loader (i.e. DEBUG_REPORT
851 * the extension must provide two entry points for the loader to use:
852 * - "trampoline" entry point - this is the address returned by GetProcAddr
853 * and will always do what's necessary to support a global call.
854 * - "terminator" function - this function will be put at the end of the
855 * instance chain and will contain the necessary logica to call / process
856 * the extension for the appropriate ICDs that are available.
857 * There is no generic mechanism for including these functions, the references
858 * must be placed into the appropriate loader entry points.
859 * GetInstanceProcAddr: call extension GetInstanceProcAddr to check for GetProcAddr requests
860 * loader_coalesce_extensions(void) - add extension records to the list of global
861 * extension available to the app.
862 * instance_disp - add function pointer for terminator function to this array.
863 * The extension itself should be in a separate file that will be
864 * linked directly with the loader.
865 */
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -0600866
Jon Ashburn8810c5f2015-08-18 18:04:47 -0600867void loader_get_icd_loader_instance_extensions(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600868 const struct loader_instance *inst,
Jon Ashburn8810c5f2015-08-18 18:04:47 -0600869 struct loader_icd_libs *icd_libs,
870 struct loader_extension_list *inst_exts)
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600871{
Jon Ashburn5c6a46f2015-08-14 14:49:22 -0600872 struct loader_extension_list icd_exts;
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -0600873 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, "Build ICD instance extension list");
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600874 // traverse scanned icd list adding non-duplicate extensions to the list
Jon Ashburn8810c5f2015-08-18 18:04:47 -0600875 for (uint32_t i = 0; i < icd_libs->count; i++) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600876 loader_init_ext_list(inst, &icd_exts);
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -0600877 loader_add_global_extensions(inst, icd_libs->list[i].EnumerateInstanceExtensionProperties,
Jon Ashburn8810c5f2015-08-18 18:04:47 -0600878 icd_libs->list[i].lib_name,
Jon Ashburn5c6a46f2015-08-14 14:49:22 -0600879 &icd_exts);
Jon Ashburne39a4f82015-08-28 13:38:21 -0600880 loader_add_to_ext_list(inst, inst_exts,
Jon Ashburn5c6a46f2015-08-14 14:49:22 -0600881 icd_exts.count,
882 icd_exts.list);
Jon Ashburne39a4f82015-08-28 13:38:21 -0600883 loader_destroy_ext_list(inst, &icd_exts);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600884 };
885
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600886 // Traverse loader's extensions, adding non-duplicate extensions to the list
Jon Ashburne39a4f82015-08-28 13:38:21 -0600887 wsi_swapchain_add_instance_extensions(inst, inst_exts);
888 debug_report_add_instance_extensions(inst, inst_exts);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600889}
890
Jon Ashburne39a4f82015-08-28 13:38:21 -0600891struct loader_icd *loader_get_icd_and_device(const VkDevice device,
892 struct loader_device **found_dev)
Jon Ashburndc6fcad2015-06-10 10:06:06 -0600893{
894 *found_dev = NULL;
895 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
896 for (struct loader_icd *icd = inst->icds; icd; icd = icd->next) {
897 for (struct loader_device *dev = icd->logical_device_list; dev; dev = dev->next)
Jon Ashburne0e64572015-09-30 12:56:42 -0600898 /* Value comparison of device prevents object wrapping by layers */
899 if (loader_get_dispatch(dev->device) == loader_get_dispatch(device)) {
Jon Ashburndc6fcad2015-06-10 10:06:06 -0600900 *found_dev = dev;
901 return icd;
902 }
903 }
904 }
905 return NULL;
906}
907
Jon Ashburne39a4f82015-08-28 13:38:21 -0600908static void loader_destroy_logical_device(const struct loader_instance *inst,
909 struct loader_device *dev)
Jon Ashburndc6fcad2015-06-10 10:06:06 -0600910{
Jon Ashburne39a4f82015-08-28 13:38:21 -0600911 loader_heap_free(inst, dev->app_extension_props);
Jon Ashburndc6fcad2015-06-10 10:06:06 -0600912 if (dev->activated_layer_list.count)
Jon Ashburne39a4f82015-08-28 13:38:21 -0600913 loader_destroy_layer_list(inst, &dev->activated_layer_list);
914 loader_heap_free(inst, dev);
Jon Ashburndc6fcad2015-06-10 10:06:06 -0600915}
916
Jon Ashburne39a4f82015-08-28 13:38:21 -0600917static struct loader_device *loader_add_logical_device(
918 const struct loader_instance *inst,
919 const VkDevice dev,
920 struct loader_device **device_list)
Jon Ashburndc6fcad2015-06-10 10:06:06 -0600921{
922 struct loader_device *new_dev;
923
Jon Ashburne39a4f82015-08-28 13:38:21 -0600924 new_dev = loader_heap_alloc(inst, sizeof(struct loader_device), VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburndc6fcad2015-06-10 10:06:06 -0600925 if (!new_dev) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600926 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc struct laoder-device");
Jon Ashburndc6fcad2015-06-10 10:06:06 -0600927 return NULL;
928 }
929
930 memset(new_dev, 0, sizeof(struct loader_device));
931
932 new_dev->next = *device_list;
933 new_dev->device = dev;
934 *device_list = new_dev;
935 return new_dev;
936}
937
Jon Ashburne39a4f82015-08-28 13:38:21 -0600938void loader_remove_logical_device(
939 const struct loader_instance *inst,
940 VkDevice device)
Jon Ashburndc6fcad2015-06-10 10:06:06 -0600941{
942 struct loader_device *found_dev, *dev, *prev_dev;
943 struct loader_icd *icd;
944 icd = loader_get_icd_and_device(device, &found_dev);
945
946 if (!icd || !found_dev)
947 return;
948
949 prev_dev = NULL;
950 dev = icd->logical_device_list;
951 while (dev && dev != found_dev) {
952 prev_dev = dev;
953 dev = dev->next;
954 }
955
956 if (prev_dev)
957 prev_dev->next = found_dev->next;
958 else
959 icd->logical_device_list = found_dev->next;
Jon Ashburne39a4f82015-08-28 13:38:21 -0600960 loader_destroy_logical_device(inst, found_dev);
Jon Ashburndc6fcad2015-06-10 10:06:06 -0600961}
962
963
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600964static void loader_icd_destroy(
965 struct loader_instance *ptr_inst,
966 struct loader_icd *icd)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800967{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600968 ptr_inst->total_icd_count--;
Jon Ashburne39a4f82015-08-28 13:38:21 -0600969 loader_heap_free(ptr_inst, icd->gpus);
Courtney Goeltzenleuchter1f157ac2015-06-14 19:57:15 -0600970 for (struct loader_device *dev = icd->logical_device_list; dev; ) {
971 struct loader_device *next_dev = dev->next;
Jon Ashburne39a4f82015-08-28 13:38:21 -0600972 loader_destroy_logical_device(ptr_inst, dev);
Courtney Goeltzenleuchter1f157ac2015-06-14 19:57:15 -0600973 dev = next_dev;
974 }
Jon Ashburndc6fcad2015-06-10 10:06:06 -0600975
Jon Ashburne39a4f82015-08-28 13:38:21 -0600976 loader_heap_free(ptr_inst, icd);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800977}
978
Jon Ashburne39a4f82015-08-28 13:38:21 -0600979static struct loader_icd * loader_icd_create(const struct loader_instance *inst)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800980{
981 struct loader_icd *icd;
982
Jon Ashburne39a4f82015-08-28 13:38:21 -0600983 icd = loader_heap_alloc(inst, sizeof(*icd), VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800984 if (!icd)
985 return NULL;
986
Courtney Goeltzenleuchter55001bb2014-10-28 10:29:27 -0600987 memset(icd, 0, sizeof(*icd));
988
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800989 return icd;
990}
991
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600992static struct loader_icd *loader_icd_add(
993 struct loader_instance *ptr_inst,
Jon Ashburn3d002332015-08-20 16:35:30 -0600994 const struct loader_scanned_icds *icd_lib)
Chia-I Wu13a61a52014-08-04 11:18:20 +0800995{
996 struct loader_icd *icd;
997
Jon Ashburne39a4f82015-08-28 13:38:21 -0600998 icd = loader_icd_create(ptr_inst);
Chia-I Wu13a61a52014-08-04 11:18:20 +0800999 if (!icd)
1000 return NULL;
1001
Jon Ashburn3d002332015-08-20 16:35:30 -06001002 icd->this_icd_lib = icd_lib;
1003 icd->this_instance = ptr_inst;
1004
Chia-I Wu13a61a52014-08-04 11:18:20 +08001005 /* prepend to the list */
Jon Ashburn46888392015-01-29 15:45:51 -07001006 icd->next = ptr_inst->icds;
1007 ptr_inst->icds = icd;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001008 ptr_inst->total_icd_count++;
Chia-I Wu13a61a52014-08-04 11:18:20 +08001009
1010 return icd;
1011}
1012
Jon Ashburne39a4f82015-08-28 13:38:21 -06001013void loader_scanned_icd_clear(
1014 const struct loader_instance *inst,
1015 struct loader_icd_libs *icd_libs)
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001016{
1017 if (icd_libs->capacity == 0)
1018 return;
1019 for (uint32_t i = 0; i < icd_libs->count; i++) {
1020 loader_platform_close_library(icd_libs->list[i].handle);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001021 loader_heap_free(inst, icd_libs->list[i].lib_name);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001022 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06001023 loader_heap_free(inst, icd_libs->list);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001024 icd_libs->capacity = 0;
1025 icd_libs->count = 0;
1026 icd_libs->list = NULL;
1027}
1028
Jon Ashburne39a4f82015-08-28 13:38:21 -06001029static void loader_scanned_icd_init(const struct loader_instance *inst,
1030 struct loader_icd_libs *icd_libs)
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001031{
Jon Ashburne39a4f82015-08-28 13:38:21 -06001032 loader_scanned_icd_clear(inst, icd_libs);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001033 icd_libs->capacity = 8 * sizeof(struct loader_scanned_icds);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001034 icd_libs->list = loader_heap_alloc(inst, icd_libs->capacity, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001035
1036}
1037
1038static void loader_scanned_icd_add(
Jon Ashburne39a4f82015-08-28 13:38:21 -06001039 const struct loader_instance *inst,
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001040 struct loader_icd_libs *icd_libs,
1041 const char *filename)
Jon Ashburn46d1f582015-01-28 11:01:35 -07001042{
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001043 loader_platform_dl_handle handle;
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06001044 PFN_vkCreateInstance fp_create_inst;
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06001045 PFN_vkEnumerateInstanceExtensionProperties fp_get_global_ext_props;
Jon Ashburnc624c882015-07-16 10:17:29 -06001046 PFN_vkGetInstanceProcAddr fp_get_proc_addr;
Jon Ashburn46d1f582015-01-28 11:01:35 -07001047 struct loader_scanned_icds *new_node;
1048
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001049 /* TODO implement ref counting of libraries, for now this function leaves
1050 libraries open and the scanned_icd_clear closes them */
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001051 // Used to call: dlopen(filename, RTLD_LAZY);
1052 handle = loader_platform_open_library(filename);
Jon Ashburn46d1f582015-01-28 11:01:35 -07001053 if (!handle) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001054 loader_log(VK_DBG_REPORT_WARN_BIT, 0, loader_platform_open_library_error(filename));
Jon Ashburn46d1f582015-01-28 11:01:35 -07001055 return;
1056 }
1057
Jon Ashburnc624c882015-07-16 10:17:29 -06001058#define LOOKUP_LD(func_ptr, func) do { \
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -06001059 func_ptr = (PFN_vk ##func) loader_platform_get_proc_address(handle, "vk" #func); \
Jon Ashburn46d1f582015-01-28 11:01:35 -07001060 if (!func_ptr) { \
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001061 loader_log(VK_DBG_REPORT_WARN_BIT, 0, loader_platform_get_proc_address_error("vk" #func)); \
Jon Ashburn46d1f582015-01-28 11:01:35 -07001062 return; \
1063 } \
1064} while (0)
1065
Jon Ashburnc624c882015-07-16 10:17:29 -06001066 LOOKUP_LD(fp_get_proc_addr, GetInstanceProcAddr);
1067 LOOKUP_LD(fp_create_inst, CreateInstance);
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06001068 LOOKUP_LD(fp_get_global_ext_props, EnumerateInstanceExtensionProperties);
Jon Ashburnc624c882015-07-16 10:17:29 -06001069
1070#undef LOOKUP_LD
Jon Ashburn46d1f582015-01-28 11:01:35 -07001071
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001072 // check for enough capacity
1073 if ((icd_libs->count * sizeof(struct loader_scanned_icds)) >= icd_libs->capacity) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06001074
1075 icd_libs->list = loader_heap_realloc(inst,
1076 icd_libs->list,
1077 icd_libs->capacity,
1078 icd_libs->capacity * 2,
1079 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001080 // double capacity
1081 icd_libs->capacity *= 2;
Jon Ashburn46d1f582015-01-28 11:01:35 -07001082 }
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001083 new_node = &(icd_libs->list[icd_libs->count]);
Jon Ashburn46d1f582015-01-28 11:01:35 -07001084
1085 new_node->handle = handle;
Jon Ashburnc624c882015-07-16 10:17:29 -06001086 new_node->GetInstanceProcAddr = fp_get_proc_addr;
Jon Ashburn46888392015-01-29 15:45:51 -07001087 new_node->CreateInstance = fp_create_inst;
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06001088 new_node->EnumerateInstanceExtensionProperties = fp_get_global_ext_props;
Jon Ashburn46d1f582015-01-28 11:01:35 -07001089
Jon Ashburne39a4f82015-08-28 13:38:21 -06001090 new_node->lib_name = (char *) loader_heap_alloc(inst,
1091 strlen(filename) + 1,
1092 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001093 if (!new_node->lib_name) {
1094 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Out of memory can't add icd");
1095 return;
1096 }
1097 strcpy(new_node->lib_name, filename);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001098 icd_libs->count++;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001099}
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001100
Jon Ashburnc624c882015-07-16 10:17:29 -06001101static bool loader_icd_init_entrys(struct loader_icd *icd,
1102 VkInstance inst,
1103 const PFN_vkGetInstanceProcAddr fp_gipa)
Jon Ashburn3da71f22015-05-14 12:43:38 -06001104{
1105 /* initialize entrypoint function pointers */
1106
Jon Ashburnc624c882015-07-16 10:17:29 -06001107 #define LOOKUP_GIPA(func, required) do { \
1108 icd->func = (PFN_vk ##func) fp_gipa(inst, "vk" #func); \
1109 if (!icd->func && required) { \
1110 loader_log(VK_DBG_REPORT_WARN_BIT, 0, \
1111 loader_platform_get_proc_address_error("vk" #func)); \
1112 return false; \
1113 } \
Jon Ashburn3da71f22015-05-14 12:43:38 -06001114 } while (0)
1115
Jon Ashburnc624c882015-07-16 10:17:29 -06001116 LOOKUP_GIPA(GetDeviceProcAddr, true);
1117 LOOKUP_GIPA(DestroyInstance, true);
1118 LOOKUP_GIPA(EnumeratePhysicalDevices, true);
1119 LOOKUP_GIPA(GetPhysicalDeviceFeatures, true);
1120 LOOKUP_GIPA(GetPhysicalDeviceFormatProperties, true);
Jon Ashburn754864f2015-07-23 18:49:07 -06001121 LOOKUP_GIPA(GetPhysicalDeviceImageFormatProperties, true);
Jon Ashburnc624c882015-07-16 10:17:29 -06001122 LOOKUP_GIPA(CreateDevice, true);
1123 LOOKUP_GIPA(GetPhysicalDeviceProperties, true);
1124 LOOKUP_GIPA(GetPhysicalDeviceMemoryProperties, true);
Cody Northropd0802882015-08-03 17:04:53 -06001125 LOOKUP_GIPA(GetPhysicalDeviceQueueFamilyProperties, true);
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06001126 LOOKUP_GIPA(EnumerateDeviceExtensionProperties, true);
Jon Ashburnc624c882015-07-16 10:17:29 -06001127 LOOKUP_GIPA(GetPhysicalDeviceSparseImageFormatProperties, true);
1128 LOOKUP_GIPA(DbgCreateMsgCallback, false);
1129 LOOKUP_GIPA(DbgDestroyMsgCallback, false);
Ian Elliott7e40db92015-08-21 15:09:33 -06001130 LOOKUP_GIPA(GetPhysicalDeviceSurfaceSupportKHR, false);
Jon Ashburn3da71f22015-05-14 12:43:38 -06001131
Jon Ashburnc624c882015-07-16 10:17:29 -06001132#undef LOOKUP_GIPA
Ian Elliottd3ef02f2015-07-06 14:36:13 -06001133
Jon Ashburnc624c882015-07-16 10:17:29 -06001134 return true;
Jon Ashburn3da71f22015-05-14 12:43:38 -06001135}
1136
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001137static void loader_debug_init(void)
1138{
1139 const char *env;
1140
1141 if (g_loader_debug > 0)
1142 return;
1143
1144 g_loader_debug = 0;
1145
1146 /* parse comma-separated debug options */
Courtney Goeltzenleuchterfce60db2015-07-29 09:08:22 -06001147 env = getenv("VK_LOADER_DEBUG");
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001148 while (env) {
1149 const char *p = strchr(env, ',');
1150 size_t len;
1151
1152 if (p)
1153 len = p - env;
1154 else
1155 len = strlen(env);
1156
1157 if (len > 0) {
1158 if (strncmp(env, "warn", len) == 0) {
1159 g_loader_debug |= LOADER_WARN_BIT;
1160 g_loader_log_msgs |= VK_DBG_REPORT_WARN_BIT;
1161 } else if (strncmp(env, "info", len) == 0) {
1162 g_loader_debug |= LOADER_INFO_BIT;
1163 g_loader_log_msgs |= VK_DBG_REPORT_INFO_BIT;
1164 } else if (strncmp(env, "perf", len) == 0) {
1165 g_loader_debug |= LOADER_PERF_BIT;
1166 g_loader_log_msgs |= VK_DBG_REPORT_PERF_WARN_BIT;
1167 } else if (strncmp(env, "error", len) == 0) {
1168 g_loader_debug |= LOADER_ERROR_BIT;
1169 g_loader_log_msgs |= VK_DBG_REPORT_ERROR_BIT;
1170 } else if (strncmp(env, "debug", len) == 0) {
1171 g_loader_debug |= LOADER_DEBUG_BIT;
1172 g_loader_log_msgs |= VK_DBG_REPORT_DEBUG_BIT;
1173 }
1174 }
1175
1176 if (!p)
1177 break;
1178
1179 env = p + 1;
1180 }
1181}
1182
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001183void loader_initialize(void)
1184{
Jon Ashburn6461ef22015-09-22 13:11:00 -06001185 // initialize mutexs
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001186 loader_platform_thread_create_mutex(&loader_lock);
Jon Ashburn6461ef22015-09-22 13:11:00 -06001187 loader_platform_thread_create_mutex(&loader_json_lock);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001188
1189 // initialize logging
1190 loader_debug_init();
Jon Ashburn87d6aa92015-08-28 15:19:27 -06001191
1192 // initial cJSON to use alloc callbacks
1193 cJSON_Hooks alloc_fns = {
1194 .malloc_fn = loader_tls_heap_alloc,
1195 .free_fn = loader_tls_heap_free,
1196 };
1197 cJSON_InitHooks(&alloc_fns);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001198}
1199
Jon Ashburn2077e382015-06-29 11:25:34 -06001200struct loader_manifest_files {
1201 uint32_t count;
1202 char **filename_list;
1203};
1204
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06001205/**
Jon Ashburn2077e382015-06-29 11:25:34 -06001206 * Get next file or dirname given a string list or registry key path
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06001207 *
1208 * \returns
Jon Ashburn2077e382015-06-29 11:25:34 -06001209 * A pointer to first char in the next path.
1210 * The next path (or NULL) in the list is returned in next_path.
1211 * Note: input string is modified in some cases. PASS IN A COPY!
1212 */
Jon Ashburn2077e382015-06-29 11:25:34 -06001213static char *loader_get_next_path(char *path)
1214{
1215 uint32_t len;
1216 char *next;
1217
1218 if (path == NULL)
1219 return NULL;
1220 next = strchr(path, PATH_SEPERATOR);
1221 if (next == NULL) {
1222 len = (uint32_t) strlen(path);
1223 next = path + len;
1224 }
1225 else {
1226 *next = '\0';
1227 next++;
1228 }
1229
1230 return next;
1231}
1232
1233/**
Jon Ashburn15315172015-07-07 15:06:25 -06001234 * Given a path which is absolute or relative. Expand the path if relative otherwise
1235 * leave the path unmodified if absolute. The path which is relative from is
1236 * given in rel_base and should include trailing directory seperator '/'
1237 *
1238 * \returns
1239 * A string in out_fullpath of the full absolute path
1240 * Side effect is that dir string maybe modified.
1241 */
1242static void loader_expand_path(const char *path,
1243 const char *rel_base,
1244 size_t out_size,
1245 char *out_fullpath)
1246{
1247 if (loader_platform_is_path_absolute(path)) {
1248 strncpy(out_fullpath, path, out_size);
1249 out_fullpath[out_size - 1] = '\0';
1250 }
1251 else {
1252 // convert relative to absolute path based on rel_base
1253 size_t len = strlen(path);
1254 strncpy(out_fullpath, rel_base, out_size);
1255 out_fullpath[out_size - 1] = '\0';
1256 assert(out_size >= strlen(out_fullpath) + len + 1);
1257 strncat(out_fullpath, path, len);
1258 }
1259}
1260
1261/**
Jon Ashburn2077e382015-06-29 11:25:34 -06001262 * Given a filename (file) and a list of paths (dir), try to find an existing
1263 * file in the paths. If filename already is a path then no
1264 * searching in the given paths.
1265 *
1266 * \returns
1267 * A string in out_fullpath of either the full path or file.
1268 * Side effect is that dir string maybe modified.
1269 */
1270static void loader_get_fullpath(const char *file,
1271 char *dir,
1272 size_t out_size,
1273 char *out_fullpath)
1274{
1275 char *next_dir;
1276 if (strchr(file,DIRECTORY_SYMBOL) == NULL) {
1277 //find file exists with prepending given path
1278 while (*dir) {
1279 next_dir = loader_get_next_path(dir);
1280 snprintf(out_fullpath, out_size, "%s%c%s",
1281 dir, DIRECTORY_SYMBOL, file);
1282 if (loader_platform_file_exists(out_fullpath)) {
1283 return;
1284 }
1285 dir = next_dir;
1286 }
1287 }
1288 snprintf(out_fullpath, out_size, "%s", file);
1289}
1290
1291/**
1292 * Read a JSON file into a buffer.
1293 *
1294 * \returns
1295 * A pointer to a cJSON object representing the JSON parse tree.
1296 * This returned buffer should be freed by caller.
1297 */
1298static cJSON *loader_get_json(const char *filename)
1299{
1300 FILE *file;
1301 char *json_buf;
1302 cJSON *json;
1303 uint64_t len;
1304 file = fopen(filename,"rb");
Jon Ashburnaa4ea472015-08-27 08:30:50 -06001305 if (!file) {
1306 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Couldn't open JSON file %s", filename);
1307 return NULL;
1308 }
Jon Ashburn2077e382015-06-29 11:25:34 -06001309 fseek(file, 0, SEEK_END);
1310 len = ftell(file);
1311 fseek(file, 0, SEEK_SET);
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -06001312 json_buf = (char*) loader_stack_alloc(len+1);
Jon Ashburn2077e382015-06-29 11:25:34 -06001313 if (json_buf == NULL) {
1314 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get JSON file");
1315 fclose(file);
1316 return NULL;
1317 }
1318 if (fread(json_buf, sizeof(char), len, file) != len) {
1319 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "fread failed can't get JSON file");
1320 fclose(file);
1321 return NULL;
1322 }
1323 fclose(file);
1324 json_buf[len] = '\0';
1325
1326 //parse text from file
1327 json = cJSON_Parse(json_buf);
1328 if (json == NULL)
1329 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Can't parse JSON file %s", filename);
1330 return json;
1331}
1332
1333/**
Jon Ashburn3d002332015-08-20 16:35:30 -06001334 * Do a deep copy of the loader_layer_properties structure.
1335 */
1336static void loader_copy_layer_properties(
Jon Ashburne39a4f82015-08-28 13:38:21 -06001337 const struct loader_instance *inst,
Jon Ashburn3d002332015-08-20 16:35:30 -06001338 struct loader_layer_properties *dst,
1339 struct loader_layer_properties *src)
1340{
1341 memcpy(dst, src, sizeof (*src));
Jon Ashburne39a4f82015-08-28 13:38:21 -06001342 dst->instance_extension_list.list = loader_heap_alloc(
1343 inst,
1344 sizeof(VkExtensionProperties) *
1345 src->instance_extension_list.count,
1346 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
1347 dst->instance_extension_list.capacity = sizeof(VkExtensionProperties) *
1348 src->instance_extension_list.count;
1349 memcpy(dst->instance_extension_list.list, src->instance_extension_list.list,
1350 dst->instance_extension_list.capacity);
1351 dst->device_extension_list.list = loader_heap_alloc(
1352 inst,
1353 sizeof(VkExtensionProperties) *
1354 src->device_extension_list.count,
1355 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
1356 dst->device_extension_list.capacity = sizeof(VkExtensionProperties) *
1357 src->device_extension_list.count;
1358 memcpy(dst->device_extension_list.list, src->device_extension_list.list,
1359 dst->device_extension_list.capacity);
Jon Ashburn3d002332015-08-20 16:35:30 -06001360}
1361
1362/**
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001363 * Given a cJSON struct (json) of the top level JSON object from layer manifest
1364 * file, add entry to the layer_list.
Jon Ashburne13ecc92015-08-03 17:19:30 -06001365 * Fill out the layer_properties in this list entry from the input cJSON object.
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001366 *
1367 * \returns
1368 * void
1369 * layer_list has a new entry and initialized accordingly.
1370 * If the json input object does not have all the required fields no entry
1371 * is added to the list.
1372 */
Jon Ashburne39a4f82015-08-28 13:38:21 -06001373static void loader_add_layer_properties(const struct loader_instance *inst,
1374 struct loader_layer_list *layer_instance_list,
Jon Ashburnb2ef1372015-07-16 17:19:31 -06001375 struct loader_layer_list *layer_device_list,
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001376 cJSON *json,
1377 bool is_implicit,
1378 char *filename)
1379{
1380 /* Fields in layer manifest file that are required:
1381 * (required) “file_format_version”
1382 * following are required in the "layer" object:
1383 * (required) "name"
1384 * (required) "type"
1385 * (required) “library_path”
1386 * (required) “abi_versions”
1387 * (required) “implementation_version”
1388 * (required) “description”
1389 * (required for implicit layers) “disable_environment”
1390 *
1391 * First get all required items and if any missing abort
1392 */
1393
1394 cJSON *item, *layer_node, *ext_item;
1395 char *temp;
1396 char *name, *type, *library_path, *abi_versions;
1397 char *implementation_version, *description;
1398 cJSON *disable_environment;
1399 int i;
Jon Ashburn5c042ea2015-08-04 11:14:18 -06001400 VkExtensionProperties ext_prop;
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001401 item = cJSON_GetObjectItem(json, "file_format_version");
1402 if (item == NULL) {
1403 return;
1404 }
1405 char *file_vers = cJSON_PrintUnformatted(item);
1406 loader_log(VK_DBG_REPORT_INFO_BIT, 0, "Found manifest file %s, version %s",
1407 filename, file_vers);
1408 if (strcmp(file_vers, "\"0.9.0\"") != 0)
Jon Ashburne13ecc92015-08-03 17:19:30 -06001409 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Unexpected manifest file version (expected 0.9.0), may cause errors");
Jon Ashburn87d6aa92015-08-28 15:19:27 -06001410 loader_tls_heap_free(file_vers);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001411
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001412 layer_node = cJSON_GetObjectItem(json, "layer");
1413 if (layer_node == NULL) {
1414 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"layer\" object in manifest JSON file, skipping");
1415 return;
1416 }
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001417
1418 // loop through all "layer" objects in the file
1419 do {
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001420#define GET_JSON_OBJECT(node, var) { \
1421 var = cJSON_GetObjectItem(node, #var); \
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001422 if (var == NULL) { \
1423 layer_node = layer_node->next; \
1424 continue; \
1425 } \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001426 }
1427#define GET_JSON_ITEM(node, var) { \
1428 item = cJSON_GetObjectItem(node, #var); \
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001429 if (item == NULL) { \
1430 layer_node = layer_node->next; \
1431 continue; \
1432 } \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001433 temp = cJSON_Print(item); \
1434 temp[strlen(temp) - 1] = '\0'; \
Jon Ashburnf73e9212015-08-04 10:22:33 -06001435 var = loader_stack_alloc(strlen(temp) + 1); \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001436 strcpy(var, &temp[1]); \
Jon Ashburn87d6aa92015-08-28 15:19:27 -06001437 loader_tls_heap_free(temp); \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001438 }
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001439 GET_JSON_ITEM(layer_node, name)
1440 GET_JSON_ITEM(layer_node, type)
1441 GET_JSON_ITEM(layer_node, library_path)
1442 GET_JSON_ITEM(layer_node, abi_versions)
1443 GET_JSON_ITEM(layer_node, implementation_version)
1444 GET_JSON_ITEM(layer_node, description)
1445 if (is_implicit) {
1446 GET_JSON_OBJECT(layer_node, disable_environment)
1447 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001448#undef GET_JSON_ITEM
1449#undef GET_JSON_OBJECT
1450
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001451 // add list entry
Jon Ashburn432d2762015-09-18 12:53:16 -06001452 struct loader_layer_properties *props=NULL;
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001453 if (!strcmp(type, "DEVICE")) {
1454 if (layer_device_list == NULL) {
1455 layer_node = layer_node->next;
1456 continue;
1457 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06001458 props = loader_get_next_layer_property(inst, layer_device_list);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001459 props->type = (is_implicit) ? VK_LAYER_TYPE_DEVICE_IMPLICIT : VK_LAYER_TYPE_DEVICE_EXPLICIT;
1460 }
1461 if (!strcmp(type, "INSTANCE")) {
1462 if (layer_instance_list == NULL) {
1463 layer_node = layer_node->next;
1464 continue;
1465 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06001466 props = loader_get_next_layer_property(inst, layer_instance_list);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001467 props->type = (is_implicit) ? VK_LAYER_TYPE_INSTANCE_IMPLICIT : VK_LAYER_TYPE_INSTANCE_EXPLICIT;
1468 }
1469 if (!strcmp(type, "GLOBAL")) {
1470 if (layer_instance_list != NULL)
Jon Ashburne39a4f82015-08-28 13:38:21 -06001471 props = loader_get_next_layer_property(inst, layer_instance_list);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001472 else if (layer_device_list != NULL)
Jon Ashburne39a4f82015-08-28 13:38:21 -06001473 props = loader_get_next_layer_property(inst, layer_device_list);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001474 else {
1475 layer_node = layer_node->next;
1476 continue;
1477 }
1478 props->type = (is_implicit) ? VK_LAYER_TYPE_GLOBAL_IMPLICIT : VK_LAYER_TYPE_GLOBAL_EXPLICIT;
1479 }
Jon Ashburnb2ef1372015-07-16 17:19:31 -06001480
Jon Ashburn432d2762015-09-18 12:53:16 -06001481 if (props == NULL) {
1482 layer_node = layer_node->next;
1483 continue;
1484 }
1485
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001486 strncpy(props->info.layerName, name, sizeof (props->info.layerName));
1487 props->info.layerName[sizeof (props->info.layerName) - 1] = '\0';
Jon Ashburn15315172015-07-07 15:06:25 -06001488
Jon Ashburn3d002332015-08-20 16:35:30 -06001489 char *fullpath = props->lib_name;
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001490 char *rel_base;
1491 if (strchr(library_path, DIRECTORY_SYMBOL) == NULL) {
1492 // a filename which is assumed in the system directory
1493 char *def_path = loader_stack_alloc(strlen(DEFAULT_VK_LAYERS_PATH) + 1);
1494 strcpy(def_path, DEFAULT_VK_LAYERS_PATH);
1495 loader_get_fullpath(library_path, def_path, MAX_STRING_SIZE, fullpath);
1496 } else {
1497 // a relative or absolute path
1498 char *name_copy = loader_stack_alloc(strlen(filename) + 2);
1499 size_t len;
1500 strcpy(name_copy, filename);
1501 rel_base = loader_platform_dirname(name_copy);
1502 len = strlen(rel_base);
1503 rel_base[len] = DIRECTORY_SYMBOL;
1504 rel_base[len + 1] = '\0';
1505 loader_expand_path(library_path, rel_base, MAX_STRING_SIZE, fullpath);
1506 }
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001507 props->info.specVersion = loader_make_version(abi_versions);
1508 props->info.implVersion = loader_make_version(implementation_version);
1509 strncpy((char *) props->info.description, description, sizeof (props->info.description));
1510 props->info.description[sizeof (props->info.description) - 1] = '\0';
1511 if (is_implicit) {
1512 strncpy(props->disable_env_var.name, disable_environment->child->string, sizeof (props->disable_env_var.name));
1513 props->disable_env_var.name[sizeof (props->disable_env_var.name) - 1] = '\0';
1514 strncpy(props->disable_env_var.value, disable_environment->child->valuestring, sizeof (props->disable_env_var.value));
1515 props->disable_env_var.value[sizeof (props->disable_env_var.value) - 1] = '\0';
1516 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001517
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001518 /**
1519 * Now get all optional items and objects and put in list:
1520 * functions
1521 * instance_extensions
1522 * device_extensions
1523 * enable_environment (implicit layers only)
1524 */
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001525#define GET_JSON_OBJECT(node, var) { \
1526 var = cJSON_GetObjectItem(node, #var); \
1527 }
1528#define GET_JSON_ITEM(node, var) { \
1529 item = cJSON_GetObjectItem(node, #var); \
Jon Ashburn21c21ee2015-09-09 11:29:24 -06001530 if (item != NULL) { \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001531 temp = cJSON_Print(item); \
Jon Ashburn21c21ee2015-09-09 11:29:24 -06001532 temp[strlen(temp) - 1] = '\0'; \
1533 var = loader_stack_alloc(strlen(temp) + 1);\
1534 strcpy(var, &temp[1]); \
1535 loader_tls_heap_free(temp); \
1536 } \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001537 }
1538
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001539 cJSON *instance_extensions, *device_extensions, *functions, *enable_environment;
Jon Ashburn432d2762015-09-18 12:53:16 -06001540 char *vkGetInstanceProcAddr = NULL, *vkGetDeviceProcAddr = NULL, *version=NULL;
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001541 GET_JSON_OBJECT(layer_node, functions)
1542 if (functions != NULL) {
1543 GET_JSON_ITEM(functions, vkGetInstanceProcAddr)
1544 GET_JSON_ITEM(functions, vkGetDeviceProcAddr)
Jon Ashburn21c21ee2015-09-09 11:29:24 -06001545 if (vkGetInstanceProcAddr != NULL)
1546 strncpy(props->functions.str_gipa, vkGetInstanceProcAddr, sizeof (props->functions.str_gipa));
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001547 props->functions.str_gipa[sizeof (props->functions.str_gipa) - 1] = '\0';
Jon Ashburn21c21ee2015-09-09 11:29:24 -06001548 if (vkGetDeviceProcAddr != NULL)
1549 strncpy(props->functions.str_gdpa, vkGetDeviceProcAddr, sizeof (props->functions.str_gdpa));
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001550 props->functions.str_gdpa[sizeof (props->functions.str_gdpa) - 1] = '\0';
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001551 }
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001552 GET_JSON_OBJECT(layer_node, instance_extensions)
1553 if (instance_extensions != NULL) {
1554 int count = cJSON_GetArraySize(instance_extensions);
1555 for (i = 0; i < count; i++) {
1556 ext_item = cJSON_GetArrayItem(instance_extensions, i);
1557 GET_JSON_ITEM(ext_item, name)
1558 GET_JSON_ITEM(ext_item, version)
1559 strncpy(ext_prop.extName, name, sizeof (ext_prop.extName));
1560 ext_prop.extName[sizeof (ext_prop.extName) - 1] = '\0';
1561 ext_prop.specVersion = loader_make_version(version);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001562 loader_add_to_ext_list(inst, &props->instance_extension_list, 1, &ext_prop);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001563 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001564 }
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001565 GET_JSON_OBJECT(layer_node, device_extensions)
1566 if (device_extensions != NULL) {
1567 int count = cJSON_GetArraySize(device_extensions);
1568 for (i = 0; i < count; i++) {
1569 ext_item = cJSON_GetArrayItem(device_extensions, i);
1570 GET_JSON_ITEM(ext_item, name);
1571 GET_JSON_ITEM(ext_item, version);
1572 strncpy(ext_prop.extName, name, sizeof (ext_prop.extName));
1573 ext_prop.extName[sizeof (ext_prop.extName) - 1] = '\0';
1574 ext_prop.specVersion = loader_make_version(version);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001575 loader_add_to_ext_list(inst, &props->device_extension_list, 1, &ext_prop);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001576 }
1577 }
1578 if (is_implicit) {
1579 GET_JSON_OBJECT(layer_node, enable_environment)
1580 strncpy(props->enable_env_var.name, enable_environment->child->string, sizeof (props->enable_env_var.name));
1581 props->enable_env_var.name[sizeof (props->enable_env_var.name) - 1] = '\0';
1582 strncpy(props->enable_env_var.value, enable_environment->child->valuestring, sizeof (props->enable_env_var.value));
1583 props->enable_env_var.value[sizeof (props->enable_env_var.value) - 1] = '\0';
1584 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001585#undef GET_JSON_ITEM
1586#undef GET_JSON_OBJECT
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001587 // for global layers need to add them to both device and instance list
1588 if (!strcmp(type, "GLOBAL")) {
1589 struct loader_layer_properties *dev_props;
1590 if (layer_instance_list == NULL || layer_device_list == NULL) {
1591 layer_node = layer_node->next;
1592 continue;
1593 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06001594 dev_props = loader_get_next_layer_property(inst, layer_device_list);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001595 //copy into device layer list
Jon Ashburne39a4f82015-08-28 13:38:21 -06001596 loader_copy_layer_properties(inst, dev_props, props);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001597 }
1598 layer_node = layer_node->next;
1599 } while (layer_node != NULL);
1600 return;
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001601}
1602
1603/**
Jon Ashburn2077e382015-06-29 11:25:34 -06001604 * Find the Vulkan library manifest files.
1605 *
1606 * This function scans the location or env_override directories/files
1607 * for a list of JSON manifest files. If env_override is non-NULL
1608 * and has a valid value. Then the location is ignored. Otherwise
1609 * location is used to look for manifest files. The location
1610 * is interpreted as Registry path on Windows and a directory path(s)
1611 * on Linux.
1612 *
1613 * \returns
1614 * A string list of manifest files to be opened in out_files param.
1615 * List has a pointer to string for each manifest filename.
1616 * When done using the list in out_files, pointers should be freed.
Jon Ashburnffad94d2015-06-30 14:46:22 -07001617 * Location or override string lists can be either files or directories as follows:
1618 * | location | override
1619 * --------------------------------
1620 * Win ICD | files | files
1621 * Win Layer | files | dirs
1622 * Linux ICD | dirs | files
1623 * Linux Layer| dirs | dirs
Jon Ashburn2077e382015-06-29 11:25:34 -06001624 */
Jon Ashburne39a4f82015-08-28 13:38:21 -06001625static void loader_get_manifest_files(const struct loader_instance *inst,
1626 const char *env_override,
Jon Ashburnffad94d2015-06-30 14:46:22 -07001627 bool is_layer,
1628 const char *location,
1629 struct loader_manifest_files *out_files)
Jon Ashburn2077e382015-06-29 11:25:34 -06001630{
1631 char *override = NULL;
1632 char *loc;
1633 char *file, *next_file, *name;
1634 size_t alloced_count = 64;
1635 char full_path[2048];
1636 DIR *sysdir = NULL;
Jon Ashburnffad94d2015-06-30 14:46:22 -07001637 bool list_is_dirs = false;
Jon Ashburn2077e382015-06-29 11:25:34 -06001638 struct dirent *dent;
1639
1640 out_files->count = 0;
1641 out_files->filename_list = NULL;
1642
Jon Ashburn2077e382015-06-29 11:25:34 -06001643 if (env_override != NULL && (override = getenv(env_override))) {
1644#if defined(__linux__)
1645 if (geteuid() != getuid()) {
Jon Ashburnffad94d2015-06-30 14:46:22 -07001646 /* Don't allow setuid apps to use the env var: */
Jon Ashburn2077e382015-06-29 11:25:34 -06001647 override = NULL;
1648 }
1649#endif
1650 }
1651
1652 if (location == NULL) {
1653 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
Jon Ashburnffad94d2015-06-30 14:46:22 -07001654 "Can't get manifest files with NULL location, env_override=%s",
1655 env_override);
Jon Ashburn2077e382015-06-29 11:25:34 -06001656 return;
1657 }
1658
Jon Ashburnffad94d2015-06-30 14:46:22 -07001659#if defined(__linux__)
1660 list_is_dirs = (override == NULL || is_layer) ? true : false;
1661#else //WIN32
1662 list_is_dirs = (is_layer && override != NULL) ? true : false;
1663#endif
Jon Ashburn2077e382015-06-29 11:25:34 -06001664 // Make a copy of the input we are using so it is not modified
Jon Ashburnffad94d2015-06-30 14:46:22 -07001665 // Also handle getting the location(s) from registry on Windows
1666 if (override == NULL) {
Jon Ashburn3b78e462015-07-31 10:11:24 -06001667 loc = loader_stack_alloc(strlen(location) + 1);
Jon Ashburnffad94d2015-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, location);
Jon Ashburn24265ac2015-07-31 09:33:21 -06001673#if defined (_WIN32)
Jon Ashburn480a50a2015-08-28 14:58:46 -07001674 loc = loader_get_registry_files(inst, loc);
Jon Ashburn24265ac2015-07-31 09:33:21 -06001675 if (loc == NULL) {
1676 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Registry lookup failed can't get manifest files");
1677 return;
1678 }
Jon Ashburnffad94d2015-06-30 14:46:22 -07001679#endif
Jon Ashburn2077e382015-06-29 11:25:34 -06001680 }
Jon Ashburnffad94d2015-06-30 14:46:22 -07001681 else {
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -06001682 loc = loader_stack_alloc(strlen(override) + 1);
Jon Ashburnffad94d2015-06-30 14:46:22 -07001683 if (loc == NULL) {
1684 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files");
1685 return;
1686 }
1687 strcpy(loc, override);
1688 }
Jon Ashburn2077e382015-06-29 11:25:34 -06001689
Liam Middlebrook9b14e892015-07-23 18:32:20 -07001690 // Print out the paths being searched if debugging is enabled
Jon Ashburn46e20d82015-07-31 09:41:31 -06001691 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, "Searching the following paths for manifest files: %s\n", loc);
Liam Middlebrook9b14e892015-07-23 18:32:20 -07001692
Jon Ashburn2077e382015-06-29 11:25:34 -06001693 file = loc;
1694 while (*file) {
1695 next_file = loader_get_next_path(file);
Jon Ashburnffad94d2015-06-30 14:46:22 -07001696 if (list_is_dirs) {
Jon Ashburn2077e382015-06-29 11:25:34 -06001697 sysdir = opendir(file);
1698 name = NULL;
1699 if (sysdir) {
1700 dent = readdir(sysdir);
1701 if (dent == NULL)
1702 break;
1703 name = &(dent->d_name[0]);
1704 loader_get_fullpath(name, file, sizeof(full_path), full_path);
1705 name = full_path;
1706 }
1707 }
1708 else {
Jon Ashburnffad94d2015-06-30 14:46:22 -07001709#if defined(__linux__)
1710 // only Linux has relative paths
Jon Ashburn2077e382015-06-29 11:25:34 -06001711 char *dir;
1712 // make a copy of location so it isn't modified
Jon Ashburn48091a32015-08-27 13:06:58 -06001713 dir = loader_stack_alloc(strlen(location) + 1);
Jon Ashburn2077e382015-06-29 11:25:34 -06001714 if (dir == NULL) {
1715 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files");
1716 return;
1717 }
1718 strcpy(dir, location);
1719
1720 loader_get_fullpath(file, dir, sizeof(full_path), full_path);
1721
1722 name = full_path;
Jon Ashburnffad94d2015-06-30 14:46:22 -07001723#else // WIN32
1724 name = file;
1725#endif
Jon Ashburn2077e382015-06-29 11:25:34 -06001726 }
1727 while (name) {
1728 /* Look for files ending with ".json" suffix */
1729 uint32_t nlen = (uint32_t) strlen(name);
1730 const char *suf = name + nlen - 5;
1731 if ((nlen > 5) && !strncmp(suf, ".json", 5)) {
1732 if (out_files->count == 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06001733 out_files->filename_list = loader_heap_alloc(inst,
1734 alloced_count * sizeof(char *),
1735 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburn2077e382015-06-29 11:25:34 -06001736 }
1737 else if (out_files->count == alloced_count) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06001738 out_files->filename_list = loader_heap_realloc(inst,
1739 out_files->filename_list,
1740 alloced_count * sizeof(char *),
1741 alloced_count * sizeof(char *) * 2,
1742 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburn2077e382015-06-29 11:25:34 -06001743 alloced_count *= 2;
1744 }
1745 if (out_files->filename_list == NULL) {
1746 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't alloc manifest file list");
1747 return;
1748 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06001749 out_files->filename_list[out_files->count] = loader_heap_alloc(
1750 inst,
1751 strlen(name) + 1,
1752 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburn2077e382015-06-29 11:25:34 -06001753 if (out_files->filename_list[out_files->count] == NULL) {
1754 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files");
1755 return;
1756 }
1757 strcpy(out_files->filename_list[out_files->count], name);
1758 out_files->count++;
Jon Ashburnf70f3612015-07-02 10:08:47 -06001759 } else if (!list_is_dirs) {
1760 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Skipping manifest file %s, file name must end in .json", name);
Jon Ashburn2077e382015-06-29 11:25:34 -06001761 }
Jon Ashburnffad94d2015-06-30 14:46:22 -07001762 if (list_is_dirs) {
Jon Ashburn2077e382015-06-29 11:25:34 -06001763 dent = readdir(sysdir);
1764 if (dent == NULL)
1765 break;
1766 name = &(dent->d_name[0]);
1767 loader_get_fullpath(name, file, sizeof(full_path), full_path);
1768 name = full_path;
1769 }
1770 else {
1771 break;
1772 }
1773 }
1774 if (sysdir)
1775 closedir(sysdir);
1776 file = next_file;
1777 }
1778 return;
1779}
1780
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001781void loader_init_icd_lib_list()
1782{
1783
1784}
1785
1786void loader_destroy_icd_lib_list()
1787{
1788
1789}
Jon Ashburn2077e382015-06-29 11:25:34 -06001790/**
1791 * Try to find the Vulkan ICD driver(s).
1792 *
1793 * This function scans the default system loader path(s) or path
1794 * specified by the \c VK_ICD_FILENAMES environment variable in
1795 * order to find loadable VK ICDs manifest files. From these
1796 * manifest files it finds the ICD libraries.
1797 *
1798 * \returns
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001799 * a list of icds that were discovered
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06001800 */
Jon Ashburne39a4f82015-08-28 13:38:21 -06001801void loader_icd_scan(
1802 const struct loader_instance *inst,
1803 struct loader_icd_libs *icds)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001804{
Jon Ashburn2077e382015-06-29 11:25:34 -06001805 char *file_str;
1806 struct loader_manifest_files manifest_files;
1807
Jon Ashburne39a4f82015-08-28 13:38:21 -06001808 loader_scanned_icd_init(inst, icds);
Jon Ashburn2077e382015-06-29 11:25:34 -06001809 // Get a list of manifest files for ICDs
Jon Ashburne39a4f82015-08-28 13:38:21 -06001810 loader_get_manifest_files(inst, "VK_ICD_FILENAMES", false,
1811 DEFAULT_VK_DRIVERS_INFO, &manifest_files);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001812 if (manifest_files.count == 0)
1813 return;
Jon Ashburn6461ef22015-09-22 13:11:00 -06001814 loader_platform_thread_lock_mutex(&loader_json_lock);
Jon Ashburn2077e382015-06-29 11:25:34 -06001815 for (uint32_t i = 0; i < manifest_files.count; i++) {
1816 file_str = manifest_files.filename_list[i];
1817 if (file_str == NULL)
1818 continue;
1819
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001820 cJSON *json;
Jon Ashburn2077e382015-06-29 11:25:34 -06001821 json = loader_get_json(file_str);
Jon Ashburnaa4ea472015-08-27 08:30:50 -06001822 if (!json)
1823 continue;
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001824 cJSON *item;
1825 item = cJSON_GetObjectItem(json, "file_format_version");
Jon Ashburn6461ef22015-09-22 13:11:00 -06001826 if (item == NULL) {
1827 loader_platform_thread_unlock_mutex(&loader_json_lock);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001828 return;
Jon Ashburn6461ef22015-09-22 13:11:00 -06001829 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001830 char *file_vers = cJSON_Print(item);
1831 loader_log(VK_DBG_REPORT_INFO_BIT, 0, "Found manifest file %s, version %s",
1832 file_str, file_vers);
1833 if (strcmp(file_vers, "\"1.0.0\"") != 0)
1834 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Unexpected manifest file version (expected 1.0.0), may cause errors");
Jon Ashburn87d6aa92015-08-28 15:19:27 -06001835 loader_tls_heap_free(file_vers);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001836 item = cJSON_GetObjectItem(json, "ICD");
1837 if (item != NULL) {
1838 item = cJSON_GetObjectItem(item, "library_path");
1839 if (item != NULL) {
Jon Ashburn86251302015-08-25 16:48:24 -06001840 char *temp= cJSON_Print(item);
1841 if (!temp || strlen(temp) == 0) {
1842 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"library_path\" in ICD JSON file %s, skipping", file_str);
Jon Ashburn87d6aa92015-08-28 15:19:27 -06001843 loader_tls_heap_free(temp);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001844 loader_heap_free(inst, file_str);
Jon Ashburn86251302015-08-25 16:48:24 -06001845 cJSON_Delete(json);
1846 continue;
Jon Ashburn2077e382015-06-29 11:25:34 -06001847 }
Jon Ashburn86251302015-08-25 16:48:24 -06001848 //strip out extra quotes
1849 temp[strlen(temp) - 1] = '\0';
1850 char *library_path = loader_stack_alloc(strlen(temp) + 1);
1851 strcpy(library_path, &temp[1]);
Jon Ashburn87d6aa92015-08-28 15:19:27 -06001852 loader_tls_heap_free(temp);
Jon Ashburn86251302015-08-25 16:48:24 -06001853 if (!library_path || strlen(library_path) == 0) {
1854 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"library_path\" in ICD JSON file %s, skipping", file_str);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001855 loader_heap_free(inst, file_str);
Jon Ashburn86251302015-08-25 16:48:24 -06001856 cJSON_Delete(json);
1857 continue;
1858 }
1859 char *fullpath;
1860 uint32_t path_len;
1861 char *rel_base;
1862 // Print out the paths being searched if debugging is enabled
1863 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, "Searching for ICD drivers named %s default dir %s\n", library_path, DEFAULT_VK_DRIVERS_PATH);
1864 if (strchr(library_path, DIRECTORY_SYMBOL) == NULL) {
1865 // a filename which is assumed in the system directory
1866 char *def_path = loader_stack_alloc(strlen(DEFAULT_VK_DRIVERS_PATH) + 1);
1867 strcpy(def_path, DEFAULT_VK_DRIVERS_PATH);
1868 path_len = strlen(DEFAULT_VK_DRIVERS_PATH) + strlen(library_path) + 2;
1869 fullpath = loader_stack_alloc(path_len);
1870#if defined(__linux__)
1871 loader_get_fullpath(library_path, def_path, path_len, fullpath);
1872#else // WIN32
1873 strncpy(fullpath, library_path, sizeof (fullpath));
1874 fullpath[sizeof (fullpath) - 1] = '\0';
1875#endif
1876 } else {
1877 // a relative or absolute path
1878 char *name_copy = loader_stack_alloc(strlen(file_str) + 2);
1879 size_t len;
1880 strcpy(name_copy, file_str);
1881 rel_base = loader_platform_dirname(name_copy);
1882 len = strlen(rel_base);
1883 rel_base[len] = DIRECTORY_SYMBOL;
1884 rel_base[len + 1] = '\0';
1885 path_len = strlen(rel_base) + strlen(library_path) + 2;
1886 fullpath = loader_stack_alloc(path_len);
1887 loader_expand_path(library_path, rel_base, path_len, fullpath);
1888 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06001889 loader_scanned_icd_add(inst, icds, fullpath);
Jon Ashburn2077e382015-06-29 11:25:34 -06001890 }
Jon Ashburn86251302015-08-25 16:48:24 -06001891
Jon Ashburn2077e382015-06-29 11:25:34 -06001892 }
1893 else
1894 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"ICD\" object in ICD JSON file %s, skipping", file_str);
1895
Jon Ashburne39a4f82015-08-28 13:38:21 -06001896 loader_heap_free(inst, file_str);
Jon Ashburn2077e382015-06-29 11:25:34 -06001897 cJSON_Delete(json);
1898 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06001899 loader_heap_free(inst, manifest_files.filename_list);
Jon Ashburn6461ef22015-09-22 13:11:00 -06001900 loader_platform_thread_unlock_mutex(&loader_json_lock);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001901}
1902
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001903
Jon Ashburne39a4f82015-08-28 13:38:21 -06001904void loader_layer_scan(
1905 const struct loader_instance *inst,
1906 struct loader_layer_list *instance_layers,
1907 struct loader_layer_list *device_layers)
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001908{
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001909 char *file_str;
1910 struct loader_manifest_files manifest_files;
1911 cJSON *json;
1912 uint32_t i;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001913
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001914 // Get a list of manifest files for layers
Jon Ashburne39a4f82015-08-28 13:38:21 -06001915 loader_get_manifest_files(inst, LAYERS_PATH_ENV, true, DEFAULT_VK_LAYERS_INFO,
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001916 &manifest_files);
1917 if (manifest_files.count == 0)
Courtney Goeltzenleuchter57985ce2014-12-01 09:29:42 -07001918 return;
Jon Ashburn90c6a0e2015-06-04 15:30:58 -06001919
Jon Ashburne13ecc92015-08-03 17:19:30 -06001920#if 0 //TODO
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001921 /**
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -06001922 * We need a list of the layer libraries, not just a list of
1923 * the layer properties (a layer library could expose more than
1924 * one layer property). This list of scanned layers would be
1925 * used to check for global and physicaldevice layer properties.
1926 */
1927 if (!loader_init_layer_library_list(&loader.scanned_layer_libraries)) {
1928 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
Jon Ashburne39a4f82015-08-28 13:38:21 -06001929 "Alloc for layer list failed: %s line: %d", __FILE__, __LINE__);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -06001930 return;
Jon Ashburn5ef20602015-07-02 09:40:15 -06001931 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001932#endif
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001933
Jon Ashburne13ecc92015-08-03 17:19:30 -06001934 /* cleanup any previously scanned libraries */
Jon Ashburne39a4f82015-08-28 13:38:21 -06001935 loader_delete_layer_properties(inst, instance_layers);
1936 loader_delete_layer_properties(inst, device_layers);
Jon Ashburnb2ef1372015-07-16 17:19:31 -06001937
Jon Ashburn6461ef22015-09-22 13:11:00 -06001938 loader_platform_thread_lock_mutex(&loader_json_lock);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001939 for (i = 0; i < manifest_files.count; i++) {
1940 file_str = manifest_files.filename_list[i];
1941 if (file_str == NULL)
1942 continue;
Courtney Goeltzenleuchtera9e4af42015-06-01 14:49:17 -06001943
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001944 // parse file into JSON struct
1945 json = loader_get_json(file_str);
1946 if (!json) {
1947 continue;
1948 }
Jon Ashburne13ecc92015-08-03 17:19:30 -06001949
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001950 //TODO pass in implicit versus explicit bool
Jon Ashburnb2ef1372015-07-16 17:19:31 -06001951 //TODO error if device layers expose instance_extensions
1952 //TODO error if instance layers expose device extensions
Jon Ashburne39a4f82015-08-28 13:38:21 -06001953 loader_add_layer_properties(inst,
1954 instance_layers,
Jon Ashburnb82c1852015-08-11 14:49:54 -06001955 device_layers,
Jon Ashburnb2ef1372015-07-16 17:19:31 -06001956 json,
1957 false,
1958 file_str);
1959
Jon Ashburne39a4f82015-08-28 13:38:21 -06001960 loader_heap_free(inst, file_str);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001961 cJSON_Delete(json);
1962 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06001963 loader_heap_free(inst, manifest_files.filename_list);
Jon Ashburn6461ef22015-09-22 13:11:00 -06001964 loader_platform_thread_unlock_mutex(&loader_json_lock);
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001965}
1966
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06001967static PFN_vkVoidFunction VKAPI loader_gpa_instance_internal(VkInstance inst, const char * pName)
Jon Ashburn27cd5842015-05-12 17:26:48 -06001968{
1969 // inst is not wrapped
1970 if (inst == VK_NULL_HANDLE) {
1971 return NULL;
1972 }
1973 VkLayerInstanceDispatchTable* disp_table = * (VkLayerInstanceDispatchTable **) inst;
1974 void *addr;
1975
Jon Ashburn8fd08252015-05-28 16:25:02 -06001976 if (!strcmp(pName, "vkGetInstanceProcAddr"))
1977 return (void *) loader_gpa_instance_internal;
1978
Jon Ashburn27cd5842015-05-12 17:26:48 -06001979 if (disp_table == NULL)
1980 return NULL;
1981
1982 addr = loader_lookup_instance_dispatch_table(disp_table, pName);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001983 if (addr) {
Jon Ashburn27cd5842015-05-12 17:26:48 -06001984 return addr;
Jon Ashburn3d526cb2015-04-13 18:10:06 -06001985 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001986
1987 if (disp_table->GetInstanceProcAddr == NULL) {
1988 return NULL;
1989 }
1990 return disp_table->GetInstanceProcAddr(inst, pName);
Jon Ashburn3d526cb2015-04-13 18:10:06 -06001991}
1992
Jon Ashburne0e64572015-09-30 12:56:42 -06001993struct loader_instance *loader_get_instance(const VkInstance instance)
1994{
1995 /* look up the loader_instance in our list by comparing dispatch tables, as
1996 * there is no guarantee the instance is still a loader_instance* after any
1997 * layers which wrap the instance object.
1998 */
1999 const VkLayerInstanceDispatchTable *disp;
2000 struct loader_instance *ptr_instance = NULL;
2001 disp = loader_get_instance_dispatch(instance);
2002 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
2003 if (inst->disp == disp) {
2004 ptr_instance = inst;
2005 break;
2006 }
2007 }
2008 return ptr_instance;
2009}
2010
Jon Ashburn128f9422015-05-28 19:16:58 -06002011struct loader_icd * loader_get_icd(const VkPhysicalDevice gpu, uint32_t *gpu_index)
Jon Ashburn876b1ac2014-10-17 15:09:07 -06002012{
Jon Ashburn128f9422015-05-28 19:16:58 -06002013
Tony Barbourb5d2c942015-07-14 13:34:05 -06002014 *gpu_index = 0;
Jon Ashburn98bd4542015-01-29 16:44:24 -07002015 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
2016 for (struct loader_icd *icd = inst->icds; icd; icd = icd->next) {
2017 for (uint32_t i = 0; i < icd->gpu_count; i++)
Jon Ashburne0e64572015-09-30 12:56:42 -06002018 /* Value comparison of VkPhysicalDevice prevents wrapping, use
2019 * instance device table instead (TODO this aliases GPUs within
2020 * an instance, since they have identical dispatch tables)
2021 */
2022 if (loader_get_instance_dispatch(icd->gpus[i]) == loader_get_instance_dispatch(gpu)) {
Jon Ashburn98bd4542015-01-29 16:44:24 -07002023 *gpu_index = i;
2024 return icd;
2025 }
2026 }
Jon Ashburn876b1ac2014-10-17 15:09:07 -06002027 }
2028 return NULL;
2029}
2030
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002031static loader_platform_dl_handle loader_add_layer_lib(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002032 const struct loader_instance *inst,
Jon Ashburn4f67d742015-05-27 13:19:22 -06002033 const char *chain_type,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002034 struct loader_layer_properties *layer_prop)
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002035{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002036 struct loader_lib_info *new_layer_lib_list, *my_lib;
Jon Ashburne39a4f82015-08-28 13:38:21 -06002037 size_t new_alloc_size;
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -06002038 /*
2039 * TODO: We can now track this information in the
2040 * scanned_layer_libraries list.
2041 */
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002042 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) {
Jon Ashburn3d002332015-08-20 16:35:30 -06002043 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, layer_prop->lib_name) == 0) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002044 /* Have already loaded this library, just increment ref count */
2045 loader.loaded_layer_lib_list[i].ref_count++;
Courtney Goeltzenleuchterca8c81a2015-06-14 11:59:07 -06002046 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002047 "%s Chain: Increment layer reference count for layer library %s",
Jon Ashburn3d002332015-08-20 16:35:30 -06002048 chain_type, layer_prop->lib_name);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002049 return loader.loaded_layer_lib_list[i].lib_handle;
2050 }
2051 }
2052
2053 /* Haven't seen this library so load it */
Jon Ashburne39a4f82015-08-28 13:38:21 -06002054 new_alloc_size = 0;
2055 if (loader.loaded_layer_lib_capacity == 0)
2056 new_alloc_size = 8 * sizeof(struct loader_lib_info);
2057 else if (loader.loaded_layer_lib_capacity <= loader.loaded_layer_lib_count *
2058 sizeof(struct loader_lib_info))
2059 new_alloc_size = loader.loaded_layer_lib_capacity * 2;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002060
Jon Ashburne39a4f82015-08-28 13:38:21 -06002061 if (new_alloc_size) {
2062 new_layer_lib_list = loader_heap_realloc(
2063 inst, loader.loaded_layer_lib_list,
2064 loader.loaded_layer_lib_capacity,
2065 new_alloc_size,
2066 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
2067 if (!new_layer_lib_list) {
2068 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "loader: realloc failed in loader_add_layer_lib");
2069 return NULL;
2070 }
2071 loader.loaded_layer_lib_capacity = new_alloc_size;
2072 } else
2073 new_layer_lib_list = loader.loaded_layer_lib_list;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002074 my_lib = &new_layer_lib_list[loader.loaded_layer_lib_count];
2075
Jon Ashburn3d002332015-08-20 16:35:30 -06002076 strncpy(my_lib->lib_name, layer_prop->lib_name, sizeof(my_lib->lib_name));
2077 my_lib->lib_name[sizeof(my_lib->lib_name) - 1] = '\0';
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002078 my_lib->ref_count = 0;
2079 my_lib->lib_handle = NULL;
2080
2081 if ((my_lib->lib_handle = loader_platform_open_library(my_lib->lib_name)) == NULL) {
2082 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
2083 loader_platform_open_library_error(my_lib->lib_name));
2084 return NULL;
2085 } else {
Courtney Goeltzenleuchterca8c81a2015-06-14 11:59:07 -06002086 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002087 "Chain: %s: Loading layer library %s",
Jon Ashburn3d002332015-08-20 16:35:30 -06002088 chain_type, layer_prop->lib_name);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002089 }
2090 loader.loaded_layer_lib_count++;
2091 loader.loaded_layer_lib_list = new_layer_lib_list;
2092 my_lib->ref_count++;
2093
2094 return my_lib->lib_handle;
2095}
2096
2097static void loader_remove_layer_lib(
2098 struct loader_instance *inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002099 struct loader_layer_properties *layer_prop)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002100{
2101 uint32_t idx;
Tony Barbourb5d2c942015-07-14 13:34:05 -06002102 struct loader_lib_info *new_layer_lib_list, *my_lib = NULL;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002103
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002104 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) {
Jon Ashburn3d002332015-08-20 16:35:30 -06002105 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, layer_prop->lib_name) == 0) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002106 /* found matching library */
2107 idx = i;
2108 my_lib = &loader.loaded_layer_lib_list[i];
2109 break;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002110 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002111 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002112
Tony Barbourb5d2c942015-07-14 13:34:05 -06002113 if (my_lib) {
2114 my_lib->ref_count--;
2115 if (my_lib->ref_count > 0) {
2116 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Jon Ashburn3d002332015-08-20 16:35:30 -06002117 "Decrement reference count for layer library %s", layer_prop->lib_name);
Tony Barbourb5d2c942015-07-14 13:34:05 -06002118 return;
2119 }
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07002120 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002121 loader_platform_close_library(my_lib->lib_handle);
Courtney Goeltzenleuchterca8c81a2015-06-14 11:59:07 -06002122 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Jon Ashburn3d002332015-08-20 16:35:30 -06002123 "Unloading layer library %s", layer_prop->lib_name);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002124
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002125 /* Need to remove unused library from list */
Jon Ashburne39a4f82015-08-28 13:38:21 -06002126 new_layer_lib_list = loader_heap_alloc(inst,
2127 loader.loaded_layer_lib_capacity,
2128 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002129 if (!new_layer_lib_list) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06002130 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "loader: heap alloc failed loader_remove_layer_library");
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002131 return;
2132 }
2133
2134 if (idx > 0) {
2135 /* Copy records before idx */
2136 memcpy(new_layer_lib_list, &loader.loaded_layer_lib_list[0],
2137 sizeof(struct loader_lib_info) * idx);
2138 }
2139 if (idx < (loader.loaded_layer_lib_count - 1)) {
2140 /* Copy records after idx */
2141 memcpy(&new_layer_lib_list[idx], &loader.loaded_layer_lib_list[idx+1],
2142 sizeof(struct loader_lib_info) * (loader.loaded_layer_lib_count - idx - 1));
2143 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002144
Jon Ashburne39a4f82015-08-28 13:38:21 -06002145 loader_heap_free(inst, loader.loaded_layer_lib_list);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002146 loader.loaded_layer_lib_count--;
2147 loader.loaded_layer_lib_list = new_layer_lib_list;
Jon Ashburnb8358052014-11-18 09:06:04 -07002148}
2149
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002150
2151/**
2152 * Go through the search_list and find any layers which match type. If layer
2153 * type match is found in then add it to ext_list.
2154 */
2155//TODO need to handle implict layer enable env var and disable env var
Jon Ashburn0c26e712015-07-02 16:10:32 -06002156static void loader_add_layer_implicit(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002157 const struct loader_instance *inst,
Jon Ashburn0c26e712015-07-02 16:10:32 -06002158 const enum layer_type type,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002159 struct loader_layer_list *list,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002160 const struct loader_layer_list *search_list)
Jon Ashburn0c26e712015-07-02 16:10:32 -06002161{
2162 uint32_t i;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002163 for (i = 0; i < search_list->count; i++) {
2164 const struct loader_layer_properties *prop = &search_list->list[i];
Jon Ashburn0c26e712015-07-02 16:10:32 -06002165 if (prop->type & type) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002166 /* Found an layer with the same type, add to layer_list */
Jon Ashburne39a4f82015-08-28 13:38:21 -06002167 loader_add_to_layer_list(inst, list, 1, prop);
Jon Ashburn0c26e712015-07-02 16:10:32 -06002168 }
2169 }
2170
2171}
2172
2173/**
2174 * Get the layer name(s) from the env_name environment variable. If layer
Jon Ashburnbd332cc2015-07-07 10:27:45 -06002175 * is found in search_list then add it to layer_list. But only add it to
2176 * layer_list if type matches.
Jon Ashburn0c26e712015-07-02 16:10:32 -06002177 */
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002178static void loader_add_layer_env(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002179 const struct loader_instance *inst,
Jon Ashburnbd332cc2015-07-07 10:27:45 -06002180 const enum layer_type type,
Jon Ashburneb6d5682015-07-02 14:10:53 -06002181 const char *env_name,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002182 struct loader_layer_list *layer_list,
2183 const struct loader_layer_list *search_list)
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002184{
Ian Elliott4470a302015-02-17 10:33:47 -07002185 char *layerEnv;
Jon Ashburneb6d5682015-07-02 14:10:53 -06002186 char *next, *name;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002187
Jon Ashburneb6d5682015-07-02 14:10:53 -06002188 layerEnv = getenv(env_name);
Ian Elliott4470a302015-02-17 10:33:47 -07002189 if (layerEnv == NULL) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002190 return;
Ian Elliott4470a302015-02-17 10:33:47 -07002191 }
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -06002192 name = loader_stack_alloc(strlen(layerEnv) + 1);
Jon Ashburneb6d5682015-07-02 14:10:53 -06002193 if (name == NULL) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002194 return;
Ian Elliott4470a302015-02-17 10:33:47 -07002195 }
Jon Ashburneb6d5682015-07-02 14:10:53 -06002196 strcpy(name, layerEnv);
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002197
Jon Ashburneb6d5682015-07-02 14:10:53 -06002198 while (name && *name ) {
2199 next = loader_get_next_path(name);
Jon Ashburne39a4f82015-08-28 13:38:21 -06002200 loader_find_layer_name_add_list(inst, name, type, search_list, layer_list);
Jon Ashburneb6d5682015-07-02 14:10:53 -06002201 name = next;
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07002202 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002203
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002204 return;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002205}
2206
Courtney Goeltzenleuchter7d0023c2015-06-08 15:09:22 -06002207void loader_deactivate_instance_layers(struct loader_instance *instance)
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002208{
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002209 if (!instance->activated_layer_list.count) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002210 return;
2211 }
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002212
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002213 /* Create instance chain of enabled layers */
Courtney Goeltzenleuchter7d0023c2015-06-08 15:09:22 -06002214 for (uint32_t i = 0; i < instance->activated_layer_list.count; i++) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002215 struct loader_layer_properties *layer_prop = &instance->activated_layer_list.list[i];
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002216
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002217 loader_remove_layer_lib(instance, layer_prop);
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002218 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06002219 loader_destroy_layer_list(instance, &instance->activated_layer_list);
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002220}
2221
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002222VkResult loader_enable_instance_layers(
Jon Ashburnb82c1852015-08-11 14:49:54 -06002223 struct loader_instance *inst,
2224 const VkInstanceCreateInfo *pCreateInfo,
2225 const struct loader_layer_list *instance_layers)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002226{
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002227 VkResult err;
2228
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06002229 assert(inst && "Cannot have null instance");
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002230
Jon Ashburne39a4f82015-08-28 13:38:21 -06002231 if (!loader_init_layer_list(inst, &inst->activated_layer_list)) {
2232 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc Instance activated layer list");
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002233 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002234 }
2235
Jon Ashburn0c26e712015-07-02 16:10:32 -06002236 /* Add any implicit layers first */
2237 loader_add_layer_implicit(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002238 inst,
Jon Ashburn0c26e712015-07-02 16:10:32 -06002239 VK_LAYER_TYPE_INSTANCE_IMPLICIT,
2240 &inst->activated_layer_list,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002241 instance_layers);
Jon Ashburn0c26e712015-07-02 16:10:32 -06002242
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002243 /* Add any layers specified via environment variable next */
Jon Ashburneb6d5682015-07-02 14:10:53 -06002244 loader_add_layer_env(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002245 inst,
Jon Ashburnbd332cc2015-07-07 10:27:45 -06002246 VK_LAYER_TYPE_INSTANCE_EXPLICIT,
Jon Ashburneb6d5682015-07-02 14:10:53 -06002247 "VK_INSTANCE_LAYERS",
2248 &inst->activated_layer_list,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002249 instance_layers);
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002250
2251 /* Add layers specified by the application */
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002252 err = loader_add_layer_names_to_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002253 inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002254 &inst->activated_layer_list,
2255 pCreateInfo->layerCount,
2256 pCreateInfo->ppEnabledLayerNames,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002257 instance_layers);
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002258
2259 return err;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002260}
2261
Jon Ashburn27cd5842015-05-12 17:26:48 -06002262uint32_t loader_activate_instance_layers(struct loader_instance *inst)
2263{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002264 uint32_t layer_idx;
Jon Ashburn128f9422015-05-28 19:16:58 -06002265 VkBaseLayerObject *wrappedInstance;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002266
David Pinedoa0a8a242015-06-24 15:29:18 -06002267 if (inst == NULL) {
Jon Ashburn27cd5842015-05-12 17:26:48 -06002268 return 0;
David Pinedoa0a8a242015-06-24 15:29:18 -06002269 }
Jon Ashburn27cd5842015-05-12 17:26:48 -06002270
2271 // NOTE inst is unwrapped at this point in time
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002272 void* baseObj = (void*) inst;
2273 void* nextObj = (void*) inst;
Jon Ashburn27cd5842015-05-12 17:26:48 -06002274 VkBaseLayerObject *nextInstObj;
2275 PFN_vkGetInstanceProcAddr nextGPA = loader_gpa_instance_internal;
2276
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002277 if (!inst->activated_layer_list.count) {
Courtney Goeltzenleuchtered1a8dd2015-08-07 09:53:18 -06002278 loader_init_instance_core_dispatch_table(inst->disp, nextGPA, (VkInstance) nextObj, (VkInstance) baseObj);
Jon Ashburn27cd5842015-05-12 17:26:48 -06002279 return 0;
2280 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002281
Courtney Goeltzenleuchter6f460c52015-07-06 09:04:55 -06002282 wrappedInstance = loader_stack_alloc(sizeof(VkBaseLayerObject)
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002283 * inst->activated_layer_list.count);
Jon Ashburn128f9422015-05-28 19:16:58 -06002284 if (!wrappedInstance) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06002285 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc Instance objects for layer");
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002286 return 0;
2287 }
2288
2289 /* Create instance chain of enabled layers */
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002290 layer_idx = inst->activated_layer_list.count - 1;
Courtney Goeltzenleuchter0f1d8eb2015-06-07 17:28:17 -06002291 for (int32_t i = inst->activated_layer_list.count - 1; i >= 0; i--) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002292 struct loader_layer_properties *layer_prop = &inst->activated_layer_list.list[i];
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002293 loader_platform_dl_handle lib_handle;
2294
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002295 /*
Courtney Goeltzenleuchteree3b16a2015-06-01 14:12:42 -06002296 * Note: An extension's Get*ProcAddr should not return a function pointer for
2297 * any extension entry points until the extension has been enabled.
2298 * To do this requires a different behavior from Get*ProcAddr functions implemented
2299 * in layers.
2300 * The very first call to a layer will be it's Get*ProcAddr function requesting
2301 * the layer's vkGet*ProcAddr. The layer should intialize it's internal dispatch table
2302 * with the wrapped object given (either Instance or Device) and return the layer's
2303 * Get*ProcAddr function. The layer should also use this opportunity to record the
2304 * baseObject so that it can find the correct local dispatch table on future calls.
2305 * Subsequent calls to Get*ProcAddr, CreateInstance, CreateDevice
2306 * will not use a wrapped object and must look up their local dispatch table from
2307 * the given baseObject.
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002308 */
Jon Ashburn128f9422015-05-28 19:16:58 -06002309 nextInstObj = (wrappedInstance + layer_idx);
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002310 nextInstObj->pGPA = (PFN_vkGPA) nextGPA;
Jon Ashburn27cd5842015-05-12 17:26:48 -06002311 nextInstObj->baseObject = baseObj;
2312 nextInstObj->nextObject = nextObj;
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002313 nextObj = (void*) nextInstObj;
Jon Ashburn27cd5842015-05-12 17:26:48 -06002314
Jon Ashburne39a4f82015-08-28 13:38:21 -06002315 lib_handle = loader_add_layer_lib(inst, "instance", layer_prop);
Jon Ashburn21c21ee2015-09-09 11:29:24 -06002316 if ((nextGPA = layer_prop->functions.get_instance_proc_addr) == NULL) {
2317 if (layer_prop->functions.str_gipa == NULL || strlen(layer_prop->functions.str_gipa) == 0) {
2318 nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetInstanceProcAddr");
2319 layer_prop->functions.get_instance_proc_addr = nextGPA;
2320 } else
2321 nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gipa);
2322 if (!nextGPA) {
2323 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to find vkGetInstanceProcAddr in layer %s", layer_prop->lib_name);
Courtney Goeltzenleuchtera9e4af42015-06-01 14:49:17 -06002324
Jon Ashburn21c21ee2015-09-09 11:29:24 -06002325 /* TODO: Should we return nextObj, nextGPA to previous? or decrement layer_list count*/
2326 continue;
2327 }
Jon Ashburn27cd5842015-05-12 17:26:48 -06002328 }
2329
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002330 loader_log(VK_DBG_REPORT_INFO_BIT, 0,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002331 "Insert instance layer %s (%s)",
2332 layer_prop->info.layerName,
Jon Ashburn3d002332015-08-20 16:35:30 -06002333 layer_prop->lib_name);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002334
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002335 layer_idx--;
Jon Ashburn27cd5842015-05-12 17:26:48 -06002336 }
2337
Jon Ashburn8fd08252015-05-28 16:25:02 -06002338 loader_init_instance_core_dispatch_table(inst->disp, nextGPA, (VkInstance) nextObj, (VkInstance) baseObj);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002339
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002340 return inst->activated_layer_list.count;
Jon Ashburn27cd5842015-05-12 17:26:48 -06002341}
2342
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002343void loader_activate_instance_layer_extensions(struct loader_instance *inst)
2344{
2345
2346 loader_init_instance_extension_dispatch_table(inst->disp,
2347 inst->disp->GetInstanceProcAddr,
Jon Ashburn128f9422015-05-28 19:16:58 -06002348 (VkInstance) inst);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002349}
2350
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002351static VkResult loader_enable_device_layers(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002352 const struct loader_instance *inst,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002353 struct loader_icd *icd,
2354 struct loader_device *dev,
2355 const VkDeviceCreateInfo *pCreateInfo,
2356 const struct loader_layer_list *device_layers)
2357
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002358{
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002359 VkResult err;
2360
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06002361 assert(dev && "Cannot have null device");
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002362
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002363 if (dev->activated_layer_list.list == NULL || dev->activated_layer_list.capacity == 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06002364 loader_init_layer_list(inst, &dev->activated_layer_list);
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002365 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002366
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002367 if (dev->activated_layer_list.list == NULL) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06002368 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc device activated layer list");
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002369 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002370 }
2371
Jon Ashburn0c26e712015-07-02 16:10:32 -06002372 /* Add any implicit layers first */
2373 loader_add_layer_implicit(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002374 inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002375 VK_LAYER_TYPE_DEVICE_IMPLICIT,
2376 &dev->activated_layer_list,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002377 device_layers);
Jon Ashburn0c26e712015-07-02 16:10:32 -06002378
2379 /* Add any layers specified via environment variable next */
Jon Ashburneb6d5682015-07-02 14:10:53 -06002380 loader_add_layer_env(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002381 inst,
Jon Ashburnbd332cc2015-07-07 10:27:45 -06002382 VK_LAYER_TYPE_DEVICE_EXPLICIT,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002383 "VK_DEVICE_LAYERS",
2384 &dev->activated_layer_list,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002385 device_layers);
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002386
2387 /* Add layers specified by the application */
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002388 err = loader_add_layer_names_to_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002389 inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002390 &dev->activated_layer_list,
2391 pCreateInfo->layerCount,
2392 pCreateInfo->ppEnabledLayerNames,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002393 device_layers);
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002394
2395 return err;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002396}
2397
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002398/*
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06002399 * This function terminates the device chain for CreateDevice.
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002400 * CreateDevice is a special case and so the loader call's
2401 * the ICD's CreateDevice before creating the chain. Since
2402 * we can't call CreateDevice twice we must terminate the
2403 * device chain with something else.
2404 */
Dan Ginsburg78556e82015-07-23 13:15:00 -04002405static VkResult VKAPI scratch_vkCreateDevice(
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002406 VkPhysicalDevice gpu,
2407 const VkDeviceCreateInfo *pCreateInfo,
2408 VkDevice *pDevice)
2409{
2410 return VK_SUCCESS;
2411}
2412
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06002413static PFN_vkVoidFunction VKAPI loader_GetDeviceChainProcAddr(VkDevice device, const char * name)
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002414{
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002415 if (!strcmp(name, "vkGetDeviceProcAddr"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06002416 return (PFN_vkVoidFunction) loader_GetDeviceChainProcAddr;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002417 if (!strcmp(name, "vkCreateDevice"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06002418 return (PFN_vkVoidFunction) scratch_vkCreateDevice;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002419
Courtney Goeltzenleuchter3e029d12015-06-29 16:09:23 -06002420 struct loader_device *found_dev;
2421 struct loader_icd *icd = loader_get_icd_and_device(device, &found_dev);
2422 return icd->GetDeviceProcAddr(device, name);
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002423}
2424
Jon Ashburndc6fcad2015-06-10 10:06:06 -06002425static uint32_t loader_activate_device_layers(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002426 const struct loader_instance *inst,
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002427 struct loader_device *dev,
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -06002428 VkDevice device)
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002429{
David Pinedoa0a8a242015-06-24 15:29:18 -06002430 if (!dev) {
Jon Ashburndc6fcad2015-06-10 10:06:06 -06002431 return 0;
David Pinedoa0a8a242015-06-24 15:29:18 -06002432 }
Jon Ashburn94e70492015-06-10 10:13:10 -06002433
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002434 /* activate any layer libraries */
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002435 void* nextObj = (void*) device;
2436 void* baseObj = nextObj;
Jon Ashburn94e70492015-06-10 10:13:10 -06002437 VkBaseLayerObject *nextGpuObj;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002438 PFN_vkGetDeviceProcAddr nextGPA = loader_GetDeviceChainProcAddr;
Jon Ashburn94e70492015-06-10 10:13:10 -06002439 VkBaseLayerObject *wrappedGpus;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002440
Courtney Goeltzenleuchtered1a8dd2015-08-07 09:53:18 -06002441 if (!dev->activated_layer_list.count) {
2442 loader_init_device_dispatch_table(&dev->loader_dispatch, nextGPA,
2443 (VkDevice) nextObj, (VkDevice) baseObj);
Jon Ashburn94e70492015-06-10 10:13:10 -06002444 return 0;
Courtney Goeltzenleuchtered1a8dd2015-08-07 09:53:18 -06002445 }
Jon Ashburn94e70492015-06-10 10:13:10 -06002446
Jon Ashburne39a4f82015-08-28 13:38:21 -06002447 wrappedGpus = loader_heap_alloc(inst,
2448 sizeof (VkBaseLayerObject) * dev->activated_layer_list.count,
2449 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburn94e70492015-06-10 10:13:10 -06002450 if (!wrappedGpus) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06002451 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc Gpu objects for layer");
Jon Ashburn94e70492015-06-10 10:13:10 -06002452 return 0;
2453 }
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002454
Jon Ashburn94e70492015-06-10 10:13:10 -06002455 for (int32_t i = dev->activated_layer_list.count - 1; i >= 0; i--) {
2456
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002457 struct loader_layer_properties *layer_prop = &dev->activated_layer_list.list[i];
Jon Ashburn94e70492015-06-10 10:13:10 -06002458 loader_platform_dl_handle lib_handle;
2459
Jon Ashburn94e70492015-06-10 10:13:10 -06002460 nextGpuObj = (wrappedGpus + i);
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002461 nextGpuObj->pGPA = (PFN_vkGPA)nextGPA;
Jon Ashburn94e70492015-06-10 10:13:10 -06002462 nextGpuObj->baseObject = baseObj;
2463 nextGpuObj->nextObject = nextObj;
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002464 nextObj = (void*) nextGpuObj;
Jon Ashburn94e70492015-06-10 10:13:10 -06002465
Jon Ashburne39a4f82015-08-28 13:38:21 -06002466 lib_handle = loader_add_layer_lib(inst, "device", layer_prop);
Jon Ashburn21c21ee2015-09-09 11:29:24 -06002467 if ((nextGPA = layer_prop->functions.get_device_proc_addr) == NULL) {
2468 if (layer_prop->functions.str_gdpa == NULL || strlen(layer_prop->functions.str_gdpa) == 0) {
2469 nextGPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetDeviceProcAddr");
2470 layer_prop->functions.get_device_proc_addr = nextGPA;
2471 } else
2472 nextGPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gdpa);
2473 if (!nextGPA) {
2474 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to find vkGetDeviceProcAddr in layer %s", layer_prop->lib_name);
2475 continue;
2476 }
Jon Ashburn94e70492015-06-10 10:13:10 -06002477 }
2478
2479 loader_log(VK_DBG_REPORT_INFO_BIT, 0,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002480 "Insert device layer library %s (%s)",
2481 layer_prop->info.layerName,
Jon Ashburn3d002332015-08-20 16:35:30 -06002482 layer_prop->lib_name);
Jon Ashburn94e70492015-06-10 10:13:10 -06002483
2484 }
2485
2486 loader_init_device_dispatch_table(&dev->loader_dispatch, nextGPA,
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002487 (VkDevice) nextObj, (VkDevice) baseObj);
Jon Ashburne39a4f82015-08-28 13:38:21 -06002488 loader_heap_free(inst, wrappedGpus);
Jon Ashburn94e70492015-06-10 10:13:10 -06002489
Jon Ashburndc6fcad2015-06-10 10:06:06 -06002490 return dev->activated_layer_list.count;
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002491}
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002492
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002493VkResult loader_validate_layers(
2494 const uint32_t layer_count,
2495 const char * const *ppEnabledLayerNames,
Jon Ashburn3d002332015-08-20 16:35:30 -06002496 const struct loader_layer_list *list)
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06002497{
2498 struct loader_layer_properties *prop;
2499
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002500 for (uint32_t i = 0; i < layer_count; i++) {
Jon Ashburne13ecc92015-08-03 17:19:30 -06002501 prop = loader_get_layer_property(ppEnabledLayerNames[i],
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002502 list);
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06002503 if (!prop) {
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06002504 return VK_ERROR_LAYER_NOT_PRESENT;
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06002505 }
2506 }
2507
2508 return VK_SUCCESS;
2509}
2510
2511VkResult loader_validate_instance_extensions(
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06002512 const struct loader_extension_list *icd_exts,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002513 const struct loader_layer_list *instance_layer,
2514 const VkInstanceCreateInfo *pCreateInfo)
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06002515{
Jon Ashburn5c042ea2015-08-04 11:14:18 -06002516 VkExtensionProperties *extension_prop;
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002517 struct loader_layer_properties *layer_prop;
2518
2519 for (uint32_t i = 0; i < pCreateInfo->extensionCount; i++) {
2520 extension_prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06002521 icd_exts);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002522
2523 if (extension_prop) {
2524 continue;
2525 }
2526
2527 extension_prop = NULL;
2528
2529 /* Not in global list, search layer extension lists */
2530 for (uint32_t j = 0; j < pCreateInfo->layerCount; j++) {
Jon Ashburne13ecc92015-08-03 17:19:30 -06002531 layer_prop = loader_get_layer_property(pCreateInfo->ppEnabledLayerNames[i],
Jon Ashburnb82c1852015-08-11 14:49:54 -06002532 instance_layer);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002533 if (!layer_prop) {
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06002534 /* Should NOT get here, loader_validate_layers
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002535 * should have already filtered this case out.
2536 */
2537 continue;
2538 }
2539
2540 extension_prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
2541 &layer_prop->instance_extension_list);
2542 if (extension_prop) {
2543 /* Found the extension in one of the layers enabled by the app. */
2544 break;
2545 }
2546 }
2547
2548 if (!extension_prop) {
2549 /* Didn't find extension name in any of the global layers, error out */
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06002550 return VK_ERROR_EXTENSION_NOT_PRESENT;
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002551 }
2552 }
2553 return VK_SUCCESS;
2554}
2555
2556VkResult loader_validate_device_extensions(
Jon Ashburnb82c1852015-08-11 14:49:54 -06002557 struct loader_icd *icd,
2558 uint32_t gpu_index,
2559 const struct loader_layer_list *device_layer,
2560 const VkDeviceCreateInfo *pCreateInfo)
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002561{
Jon Ashburn5c042ea2015-08-04 11:14:18 -06002562 VkExtensionProperties *extension_prop;
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002563 struct loader_layer_properties *layer_prop;
2564
2565 for (uint32_t i = 0; i < pCreateInfo->extensionCount; i++) {
2566 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i];
2567 extension_prop = get_extension_property(extension_name,
Courtney Goeltzenleuchterfedb2a52015-07-08 21:13:16 -06002568 &icd->device_extension_cache[gpu_index]);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002569
2570 if (extension_prop) {
2571 continue;
2572 }
2573
2574 /* Not in global list, search layer extension lists */
2575 for (uint32_t j = 0; j < pCreateInfo->layerCount; j++) {
2576 const char *layer_name = pCreateInfo->ppEnabledLayerNames[j];
Jon Ashburne13ecc92015-08-03 17:19:30 -06002577 layer_prop = loader_get_layer_property(layer_name,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002578 device_layer);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002579
2580 if (!layer_prop) {
2581 /* Should NOT get here, loader_validate_instance_layers
2582 * should have already filtered this case out.
2583 */
2584 continue;
2585 }
2586
2587 extension_prop = get_extension_property(extension_name,
2588 &layer_prop->device_extension_list);
2589 if (extension_prop) {
2590 /* Found the extension in one of the layers enabled by the app. */
2591 break;
2592 }
2593 }
2594
2595 if (!extension_prop) {
2596 /* Didn't find extension name in any of the device layers, error out */
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06002597 return VK_ERROR_EXTENSION_NOT_PRESENT;
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002598 }
2599 }
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06002600 return VK_SUCCESS;
2601}
2602
Dan Ginsburg78556e82015-07-23 13:15:00 -04002603VkResult VKAPI loader_CreateInstance(
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002604 const VkInstanceCreateInfo* pCreateInfo,
2605 VkInstance* pInstance)
Jon Ashburn1beab2d2015-01-26 14:51:40 -07002606{
Jon Ashburneed0c002015-05-21 17:42:17 -06002607 struct loader_instance *ptr_instance = *(struct loader_instance **) pInstance;
Jon Ashburn46888392015-01-29 15:45:51 -07002608 struct loader_icd *icd;
Jon Ashburn5c042ea2015-08-04 11:14:18 -06002609 VkExtensionProperties *prop;
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06002610 char **filtered_extension_names = NULL;
2611 VkInstanceCreateInfo icd_create_info;
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002612 VkResult res = VK_SUCCESS;
Jon Ashburnc624c882015-07-16 10:17:29 -06002613 bool success;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07002614
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06002615 icd_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
2616 icd_create_info.layerCount = 0;
2617 icd_create_info.ppEnabledLayerNames = NULL;
2618 icd_create_info.pAllocCb = pCreateInfo->pAllocCb;
2619 icd_create_info.pAppInfo = pCreateInfo->pAppInfo;
2620 icd_create_info.pNext = pCreateInfo->pNext;
2621
2622 /*
2623 * NOTE: Need to filter the extensions to only those
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002624 * supported by the ICD.
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06002625 * No ICD will advertise support for layers. An ICD
2626 * library could support a layer, but it would be
2627 * independent of the actual ICD, just in the same library.
2628 */
2629 filtered_extension_names = loader_stack_alloc(pCreateInfo->extensionCount * sizeof(char *));
2630 if (!filtered_extension_names) {
2631 return VK_ERROR_OUT_OF_HOST_MEMORY;
2632 }
2633 icd_create_info.ppEnabledExtensionNames = (const char * const *) filtered_extension_names;
2634
Jon Ashburn8810c5f2015-08-18 18:04:47 -06002635 for (uint32_t i = 0; i < ptr_instance->icd_libs.count; i++) {
2636 icd = loader_icd_add(ptr_instance, &ptr_instance->icd_libs.list[i]);
Jon Ashburn46888392015-01-29 15:45:51 -07002637 if (icd) {
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06002638 icd_create_info.extensionCount = 0;
2639 for (uint32_t i = 0; i < pCreateInfo->extensionCount; i++) {
2640 prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
Jon Ashburn5c6a46f2015-08-14 14:49:22 -06002641 &ptr_instance->ext_list);
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06002642 if (prop) {
2643 filtered_extension_names[icd_create_info.extensionCount] = (char *) pCreateInfo->ppEnabledExtensionNames[i];
2644 icd_create_info.extensionCount++;
2645 }
2646 }
2647
Jon Ashburn8810c5f2015-08-18 18:04:47 -06002648 res = ptr_instance->icd_libs.list[i].CreateInstance(&icd_create_info,
Jon Ashburn3da71f22015-05-14 12:43:38 -06002649 &(icd->instance));
Jon Ashburnc624c882015-07-16 10:17:29 -06002650 success = loader_icd_init_entrys(
2651 icd,
2652 icd->instance,
Jon Ashburn8810c5f2015-08-18 18:04:47 -06002653 ptr_instance->icd_libs.list[i].GetInstanceProcAddr);
Jon Ashburnc624c882015-07-16 10:17:29 -06002654
2655 if (res != VK_SUCCESS || !success)
Jon Ashburn46888392015-01-29 15:45:51 -07002656 {
2657 ptr_instance->icds = ptr_instance->icds->next;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002658 loader_icd_destroy(ptr_instance, icd);
Jon Ashburn3da71f22015-05-14 12:43:38 -06002659 icd->instance = VK_NULL_HANDLE;
Jon Ashburnc624c882015-07-16 10:17:29 -06002660 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
2661 "ICD ignored: failed to CreateInstance and find entrypoints with ICD");
Jon Ashburn46888392015-01-29 15:45:51 -07002662 }
2663 }
Jon Ashburn46888392015-01-29 15:45:51 -07002664 }
Jon Ashburn1beab2d2015-01-26 14:51:40 -07002665
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002666 /*
2667 * If no ICDs were added to instance list and res is unchanged
2668 * from it's initial value, the loader was unable to find
2669 * a suitable ICD.
2670 */
Ian Elliotteb450762015-02-05 15:19:15 -07002671 if (ptr_instance->icds == NULL) {
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002672 if (res == VK_SUCCESS) {
2673 return VK_ERROR_INCOMPATIBLE_DRIVER;
2674 } else {
2675 return res;
2676 }
Ian Elliotteb450762015-02-05 15:19:15 -07002677 }
Jon Ashburn46888392015-01-29 15:45:51 -07002678
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002679 return VK_SUCCESS;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07002680}
2681
Mark Lobodzinski2141f652015-09-07 13:59:43 -06002682void VKAPI loader_DestroyInstance(
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -06002683 VkInstance instance)
Jon Ashburn1beab2d2015-01-26 14:51:40 -07002684{
Courtney Goeltzenleuchterdeceded2015-06-08 15:04:02 -06002685 struct loader_instance *ptr_instance = loader_instance(instance);
Jon Ashburn3da71f22015-05-14 12:43:38 -06002686 struct loader_icd *icds = ptr_instance->icds;
Jon Ashburna6fd2612015-06-16 14:43:19 -06002687 struct loader_icd *next_icd;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07002688
2689 // Remove this instance from the list of instances:
2690 struct loader_instance *prev = NULL;
2691 struct loader_instance *next = loader.instances;
2692 while (next != NULL) {
2693 if (next == ptr_instance) {
2694 // Remove this instance from the list:
2695 if (prev)
2696 prev->next = next->next;
Jon Ashburnc5c49602015-02-03 09:26:59 -07002697 else
2698 loader.instances = next->next;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07002699 break;
2700 }
2701 prev = next;
2702 next = next->next;
2703 }
Jon Ashburn1beab2d2015-01-26 14:51:40 -07002704
Jon Ashburn3da71f22015-05-14 12:43:38 -06002705 while (icds) {
2706 if (icds->instance) {
Mark Lobodzinski2141f652015-09-07 13:59:43 -06002707 icds->DestroyInstance(icds->instance);
Tony Barbourf20f87b2015-04-22 09:02:32 -06002708 }
Jon Ashburna6fd2612015-06-16 14:43:19 -06002709 next_icd = icds->next;
Jon Ashburn3da71f22015-05-14 12:43:38 -06002710 icds->instance = VK_NULL_HANDLE;
Jon Ashburna6fd2612015-06-16 14:43:19 -06002711 loader_icd_destroy(ptr_instance, icds);
2712
2713 icds = next_icd;
Jon Ashburn46888392015-01-29 15:45:51 -07002714 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06002715 loader_delete_layer_properties(ptr_instance, &ptr_instance->device_layer_list);
2716 loader_delete_layer_properties(ptr_instance, &ptr_instance->instance_layer_list);
2717 loader_scanned_icd_clear(ptr_instance, &ptr_instance->icd_libs);
2718 loader_destroy_ext_list(ptr_instance, &ptr_instance->ext_list);
Jon Ashburn1beab2d2015-01-26 14:51:40 -07002719}
2720
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002721VkResult loader_init_physical_device_info(
2722 struct loader_instance *ptr_instance)
2723{
2724 struct loader_icd *icd;
2725 uint32_t n, count = 0;
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06002726 VkResult res;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002727
2728 icd = ptr_instance->icds;
2729 while (icd) {
2730 res = icd->EnumeratePhysicalDevices(icd->instance, &n, NULL);
2731 if (res != VK_SUCCESS)
2732 return res;
2733 icd->gpu_count = n;
2734 count += n;
2735 icd = icd->next;
2736 }
2737
2738 ptr_instance->total_gpu_count = count;
2739
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002740 icd = ptr_instance->icds;
2741 while (icd) {
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002742
2743 n = icd->gpu_count;
Jon Ashburne39a4f82015-08-28 13:38:21 -06002744 icd->gpus = (VkPhysicalDevice *) loader_heap_alloc(
2745 ptr_instance,
2746 n * sizeof(VkPhysicalDevice),
2747 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburn128f9422015-05-28 19:16:58 -06002748 if (!icd->gpus) {
2749 /* TODO: Add cleanup code here */
2750 return VK_ERROR_OUT_OF_HOST_MEMORY;
2751 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002752 res = icd->EnumeratePhysicalDevices(
2753 icd->instance,
2754 &n,
Jon Ashburn128f9422015-05-28 19:16:58 -06002755 icd->gpus);
2756 if ((res == VK_SUCCESS) && (n == icd->gpu_count)) {
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002757
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002758 for (unsigned int i = 0; i < n; i++) {
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002759
Jon Ashburn128f9422015-05-28 19:16:58 -06002760 loader_init_dispatch(icd->gpus[i], ptr_instance->disp);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002761
Jon Ashburne39a4f82015-08-28 13:38:21 -06002762 if (!loader_init_ext_list(ptr_instance, &icd->device_extension_cache[i])) {
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002763 /* TODO: Add cleanup code here */
2764 res = VK_ERROR_OUT_OF_HOST_MEMORY;
2765 }
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002766 if (res == VK_SUCCESS) {
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002767
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002768 loader_add_physical_device_extensions(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002769 ptr_instance,
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06002770 icd->EnumerateDeviceExtensionProperties,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002771 icd->gpus[0],
Jon Ashburn3d002332015-08-20 16:35:30 -06002772 icd->this_icd_lib->lib_name,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002773 &icd->device_extension_cache[i]);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002774
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002775 }
2776
2777 if (res != VK_SUCCESS) {
2778 /* clean up any extension lists previously created before this request failed */
2779 for (uint32_t j = 0; j < i; j++) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06002780 loader_destroy_ext_list(
2781 ptr_instance,
2782 &icd->device_extension_cache[i]);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002783 }
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002784
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002785 return res;
2786 }
2787 }
2788
2789 count += n;
2790 }
2791
2792 icd = icd->next;
2793 }
2794
2795 return VK_SUCCESS;
2796}
2797
Dan Ginsburg78556e82015-07-23 13:15:00 -04002798VkResult VKAPI loader_EnumeratePhysicalDevices(
Courtney Goeltzenleuchter5e41f1d2015-04-20 12:48:54 -06002799 VkInstance instance,
2800 uint32_t* pPhysicalDeviceCount,
2801 VkPhysicalDevice* pPhysicalDevices)
Jon Ashburn1beab2d2015-01-26 14:51:40 -07002802{
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002803 uint32_t index = 0;
Jon Ashburn4c392fb2015-01-28 19:57:09 -07002804 struct loader_instance *ptr_instance = (struct loader_instance *) instance;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002805 struct loader_icd *icd = ptr_instance->icds;
Jon Ashburn4c392fb2015-01-28 19:57:09 -07002806
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002807 if (ptr_instance->total_gpu_count == 0) {
2808 loader_init_physical_device_info(ptr_instance);
Jon Ashburn4c392fb2015-01-28 19:57:09 -07002809 }
2810
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002811 *pPhysicalDeviceCount = ptr_instance->total_gpu_count;
2812 if (!pPhysicalDevices) {
2813 return VK_SUCCESS;
2814 }
Jon Ashburn4c392fb2015-01-28 19:57:09 -07002815
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002816 while (icd) {
2817 assert((index + icd->gpu_count) <= *pPhysicalDeviceCount);
Jon Ashburn128f9422015-05-28 19:16:58 -06002818 memcpy(&pPhysicalDevices[index], icd->gpus, icd->gpu_count * sizeof(VkPhysicalDevice));
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002819 index += icd->gpu_count;
2820 icd = icd->next;
2821 }
2822
2823 return VK_SUCCESS;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07002824}
2825
Dan Ginsburg78556e82015-07-23 13:15:00 -04002826VkResult VKAPI loader_GetPhysicalDeviceProperties(
Jon Ashburn3da71f22015-05-14 12:43:38 -06002827 VkPhysicalDevice gpu,
Tony Barbour59a47322015-06-24 16:06:58 -06002828 VkPhysicalDeviceProperties* pProperties)
Jon Ashburn3da71f22015-05-14 12:43:38 -06002829{
2830 uint32_t gpu_index;
Jon Ashburn128f9422015-05-28 19:16:58 -06002831 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
Jon Ashburn3da71f22015-05-14 12:43:38 -06002832 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2833
Tony Barbour59a47322015-06-24 16:06:58 -06002834 if (icd->GetPhysicalDeviceProperties)
2835 res = icd->GetPhysicalDeviceProperties(gpu, pProperties);
2836
2837 return res;
2838}
2839
Cody Northropd0802882015-08-03 17:04:53 -06002840VkResult VKAPI loader_GetPhysicalDeviceQueueFamilyProperties (
Tony Barbour59a47322015-06-24 16:06:58 -06002841 VkPhysicalDevice gpu,
Cody Northropd0802882015-08-03 17:04:53 -06002842 uint32_t* pCount,
2843 VkQueueFamilyProperties* pProperties)
Tony Barbour59a47322015-06-24 16:06:58 -06002844{
2845 uint32_t gpu_index;
2846 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
2847 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2848
Cody Northropd0802882015-08-03 17:04:53 -06002849 if (icd->GetPhysicalDeviceQueueFamilyProperties)
2850 res = icd->GetPhysicalDeviceQueueFamilyProperties(gpu, pCount, pProperties);
Tony Barbour59a47322015-06-24 16:06:58 -06002851
2852 return res;
2853}
2854
Dan Ginsburg78556e82015-07-23 13:15:00 -04002855VkResult VKAPI loader_GetPhysicalDeviceMemoryProperties (
Tony Barbour59a47322015-06-24 16:06:58 -06002856 VkPhysicalDevice gpu,
2857 VkPhysicalDeviceMemoryProperties* pProperties)
2858{
2859 uint32_t gpu_index;
2860 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
2861 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2862
2863 if (icd->GetPhysicalDeviceMemoryProperties)
2864 res = icd->GetPhysicalDeviceMemoryProperties(gpu, pProperties);
Jon Ashburn3da71f22015-05-14 12:43:38 -06002865
2866 return res;
2867}
2868
Dan Ginsburg78556e82015-07-23 13:15:00 -04002869VkResult VKAPI loader_GetPhysicalDeviceFeatures(
Chris Forbesbc0bb772015-06-21 22:55:02 +12002870 VkPhysicalDevice physicalDevice,
2871 VkPhysicalDeviceFeatures* pFeatures)
2872{
2873 uint32_t gpu_index;
2874 struct loader_icd *icd = loader_get_icd(physicalDevice, &gpu_index);
2875 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2876
2877 if (icd->GetPhysicalDeviceFeatures)
2878 res = icd->GetPhysicalDeviceFeatures(physicalDevice, pFeatures);
2879
2880 return res;
2881}
2882
Dan Ginsburg78556e82015-07-23 13:15:00 -04002883VkResult VKAPI loader_GetPhysicalDeviceFormatProperties(
Chris Forbesbc0bb772015-06-21 22:55:02 +12002884 VkPhysicalDevice physicalDevice,
2885 VkFormat format,
2886 VkFormatProperties* pFormatInfo)
2887{
2888 uint32_t gpu_index;
2889 struct loader_icd *icd = loader_get_icd(physicalDevice, &gpu_index);
2890 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2891
Courtney Goeltzenleuchter2caec862015-07-12 12:52:09 -06002892 if (icd->GetPhysicalDeviceFormatProperties)
2893 res = icd->GetPhysicalDeviceFormatProperties(physicalDevice, format, pFormatInfo);
Chris Forbesbc0bb772015-06-21 22:55:02 +12002894
2895 return res;
2896}
2897
Jon Ashburn754864f2015-07-23 18:49:07 -06002898VkResult VKAPI loader_GetPhysicalDeviceImageFormatProperties(
2899 VkPhysicalDevice physicalDevice,
2900 VkFormat format,
2901 VkImageType type,
2902 VkImageTiling tiling,
2903 VkImageUsageFlags usage,
Courtney Goeltzenleuchtera22097a2015-09-10 13:44:12 -06002904 VkImageCreateFlags flags,
Jon Ashburn754864f2015-07-23 18:49:07 -06002905 VkImageFormatProperties* pImageFormatProperties)
2906{
2907 uint32_t gpu_index;
2908 struct loader_icd *icd = loader_get_icd(physicalDevice, &gpu_index);
2909 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2910
2911 if (icd->GetPhysicalDeviceImageFormatProperties)
2912 res = icd->GetPhysicalDeviceImageFormatProperties(physicalDevice, format,
Courtney Goeltzenleuchtera22097a2015-09-10 13:44:12 -06002913 type, tiling, usage, flags, pImageFormatProperties);
Jon Ashburn754864f2015-07-23 18:49:07 -06002914
2915 return res;
2916}
2917
Dan Ginsburg78556e82015-07-23 13:15:00 -04002918VkResult VKAPI loader_GetPhysicalDeviceSparseImageFormatProperties(
Mark Lobodzinski16e8bef2015-07-03 15:58:09 -06002919 VkPhysicalDevice physicalDevice,
2920 VkFormat format,
2921 VkImageType type,
2922 uint32_t samples,
2923 VkImageUsageFlags usage,
2924 VkImageTiling tiling,
2925 uint32_t* pNumProperties,
2926 VkSparseImageFormatProperties* pProperties)
2927{
2928 uint32_t gpu_index;
2929 struct loader_icd *icd = loader_get_icd(physicalDevice, &gpu_index);
2930 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2931
2932 if (icd->GetPhysicalDeviceSparseImageFormatProperties)
2933 res = icd->GetPhysicalDeviceSparseImageFormatProperties(physicalDevice, format, type, samples, usage, tiling, pNumProperties, pProperties);
2934
2935 return res;
2936}
2937
Dan Ginsburg78556e82015-07-23 13:15:00 -04002938VkResult VKAPI loader_CreateDevice(
Jon Ashburn95a77ba2015-05-15 15:09:35 -06002939 VkPhysicalDevice gpu,
2940 const VkDeviceCreateInfo* pCreateInfo,
2941 VkDevice* pDevice)
2942{
2943 uint32_t gpu_index;
Jon Ashburn128f9422015-05-28 19:16:58 -06002944 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
Jon Ashburndc6fcad2015-06-10 10:06:06 -06002945 struct loader_device *dev;
Jon Ashburne39a4f82015-08-28 13:38:21 -06002946 const struct loader_instance *inst = icd->this_instance;
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06002947 VkDeviceCreateInfo device_create_info;
2948 char **filtered_extension_names = NULL;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002949 VkResult res;
Jon Ashburn95a77ba2015-05-15 15:09:35 -06002950
Mark Lobodzinski0c29b922015-09-17 15:17:34 -06002951 assert(pCreateInfo->queueRecordCount >= 1);
2952
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002953 if (!icd->CreateDevice) {
2954 return VK_ERROR_INITIALIZATION_FAILED;
Jon Ashburn95a77ba2015-05-15 15:09:35 -06002955 }
2956
Jon Ashburnb82c1852015-08-11 14:49:54 -06002957 /* validate any app enabled layers are available */
2958 if (pCreateInfo->layerCount > 0) {
2959 res = loader_validate_layers(pCreateInfo->layerCount,
2960 pCreateInfo->ppEnabledLayerNames,
Jon Ashburne39a4f82015-08-28 13:38:21 -06002961 &inst->device_layer_list);
Jon Ashburnb82c1852015-08-11 14:49:54 -06002962 if (res != VK_SUCCESS) {
2963 return res;
2964 }
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002965 }
2966
Jon Ashburne39a4f82015-08-28 13:38:21 -06002967 res = loader_validate_device_extensions(icd, gpu_index, &inst->device_layer_list, pCreateInfo);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002968 if (res != VK_SUCCESS) {
2969 return res;
2970 }
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002971
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06002972 /*
2973 * NOTE: Need to filter the extensions to only those
2974 * supported by the ICD.
2975 * No ICD will advertise support for layers. An ICD
2976 * library could support a layer, but it would be
2977 * independent of the actual ICD, just in the same library.
2978 */
2979 filtered_extension_names = loader_stack_alloc(pCreateInfo->extensionCount * sizeof(char *));
2980 if (!filtered_extension_names) {
2981 return VK_ERROR_OUT_OF_HOST_MEMORY;
2982 }
2983
2984 /* Copy user's data */
2985 memcpy(&device_create_info, pCreateInfo, sizeof(VkDeviceCreateInfo));
2986
2987 /* ICD's do not use layers */
2988 device_create_info.layerCount = 0;
2989 device_create_info.ppEnabledLayerNames = NULL;
2990
2991 device_create_info.extensionCount = 0;
2992 device_create_info.ppEnabledExtensionNames = (const char * const *) filtered_extension_names;
2993
2994 for (uint32_t i = 0; i < pCreateInfo->extensionCount; i++) {
2995 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i];
Jon Ashburn5c042ea2015-08-04 11:14:18 -06002996 VkExtensionProperties *prop = get_extension_property(extension_name,
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06002997 &icd->device_extension_cache[gpu_index]);
2998 if (prop) {
2999 filtered_extension_names[device_create_info.extensionCount] = (char *) extension_name;
3000 device_create_info.extensionCount++;
3001 }
3002 }
3003
Jon Ashburne0e64572015-09-30 12:56:42 -06003004 // since gpu object maybe wrapped by a layer need to get unwrapped version
3005 // we haven't yet called down the chain for the layer to unwrap the object
3006 res = icd->CreateDevice(icd->gpus[gpu_index], pCreateInfo, pDevice);
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003007 if (res != VK_SUCCESS) {
3008 return res;
3009 }
3010
Jon Ashburne39a4f82015-08-28 13:38:21 -06003011 dev = loader_add_logical_device(inst, *pDevice, &icd->logical_device_list);
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003012 if (dev == NULL) {
3013 return VK_ERROR_OUT_OF_HOST_MEMORY;
3014 }
3015 PFN_vkGetDeviceProcAddr get_proc_addr = icd->GetDeviceProcAddr;
3016 loader_init_device_dispatch_table(&dev->loader_dispatch, get_proc_addr,
Courtney Goeltzenleuchtere315d3c2015-07-16 10:36:57 -06003017 *pDevice, *pDevice);
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003018
3019 dev->loader_dispatch.CreateDevice = scratch_vkCreateDevice;
3020 loader_init_dispatch(*pDevice, &dev->loader_dispatch);
3021
Jon Ashburnb82c1852015-08-11 14:49:54 -06003022 /* activate any layers on device chain which terminates with device*/
Jon Ashburne39a4f82015-08-28 13:38:21 -06003023 res = loader_enable_device_layers(inst, icd, dev, pCreateInfo, &inst->device_layer_list);
Jon Ashburnb82c1852015-08-11 14:49:54 -06003024 if (res != VK_SUCCESS) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06003025 loader_destroy_logical_device(inst, dev);
Jon Ashburnb82c1852015-08-11 14:49:54 -06003026 return res;
3027 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06003028 loader_activate_device_layers(inst, dev, *pDevice);
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003029
3030 res = dev->loader_dispatch.CreateDevice(gpu, pCreateInfo, pDevice);
3031
3032 dev->loader_dispatch.CreateDevice = icd->CreateDevice;
3033
Jon Ashburn95a77ba2015-05-15 15:09:35 -06003034 return res;
3035}
3036
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003037/**
3038 * Get an instance level or global level entry point address.
3039 * @param instance
3040 * @param pName
3041 * @return
3042 * If instance == NULL returns a global level entrypoint for all core entry points
3043 * If instance is valid returns a instance relative entry point for instance level
3044 * entry points both core and extensions.
3045 * Instance relative means call down the instance chain. Global means trampoline entry points.
3046 */
3047LOADER_EXPORT PFN_vkVoidFunction VKAPI vkGetInstanceProcAddr(VkInstance instance, const char * pName)
Jon Ashburnb0fbe912015-05-06 10:15:07 -06003048{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003049
Jon Ashburn07daee72015-05-21 18:13:33 -06003050 void *addr;
Jon Ashburnb0fbe912015-05-06 10:15:07 -06003051
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003052 if (instance == VK_NULL_HANDLE) {
Jon Ashburnf7a48db2015-10-01 12:03:17 -06003053 /* get entrypoint addresses that are global (in the loader),
3054 doesn't include any instance extensions since they may not be enabled yet*/
Jon Ashburne0e64572015-09-30 12:56:42 -06003055
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003056 addr = globalGetProcAddr(pName);
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003057
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003058 return addr;
3059 }
3060
Jon Ashburnf7a48db2015-10-01 12:03:17 -06003061
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003062 /* return any instance entrypoints that must resolve to loader code */
3063 addr = loader_non_passthrough_gipa(pName);
David Pinedoa0a8a242015-06-24 15:29:18 -06003064 if (addr) {
Jon Ashburn922c8f62015-06-18 09:05:37 -06003065 return addr;
David Pinedoa0a8a242015-06-24 15:29:18 -06003066 }
Jon Ashburn07daee72015-05-21 18:13:33 -06003067
Jon Ashburnf7a48db2015-10-01 12:03:17 -06003068 /* debug_report is a special case; need to return loader trampoline entrypoints
3069 * unless the extension is not enabled; also need to handle debug_report
3070 * utility functions */
Jon Ashburne0e64572015-09-30 12:56:42 -06003071 struct loader_instance *ptr_instance = loader_get_instance(instance);
Jon Ashburnf7a48db2015-10-01 12:03:17 -06003072 if (debug_report_instance_gpa(ptr_instance, pName, &addr)) {
3073 return addr;
3074 }
3075
3076 /* return the instance dispatch table entrypoint for core and extensions */
Jon Ashburn07daee72015-05-21 18:13:33 -06003077 const VkLayerInstanceDispatchTable *disp_table = * (VkLayerInstanceDispatchTable **) instance;
3078 if (disp_table == NULL)
3079 return NULL;
3080
3081 addr = loader_lookup_instance_dispatch_table(disp_table, pName);
3082 if (addr)
3083 return addr;
Jon Ashburnb0fbe912015-05-06 10:15:07 -06003084
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003085 // NOTE: any instance extensions must be known to loader and resolved
3086 // in the above call to loader_lookup_instance_dispatch_table())
Jon Ashburnb0fbe912015-05-06 10:15:07 -06003087 return NULL;
3088}
3089
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003090/**
3091 * Get a device level or global level entry point address.
3092 * @param device
3093 * @param pName
3094 * @return
3095 * If device == NULL, returns a global level entrypoint for all core entry points
3096 * If device is valid, returns a device relative entry point for device level
3097 * entry points both core and extensions.
3098 * Device relative means call down the device chain. Global means trampoline entry points.
3099 */
3100LOADER_EXPORT PFN_vkVoidFunction VKAPI vkGetDeviceProcAddr(VkDevice device, const char * pName)
Courtney Goeltzenleuchter9ec39ac2015-06-22 17:45:21 -06003101{
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003102 void *addr;
Courtney Goeltzenleuchter9ec39ac2015-06-22 17:45:21 -06003103
Jon Ashburn8d1b0b52015-05-18 13:20:15 -06003104 if (device == VK_NULL_HANDLE) {
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003105 /* get entrypoint addresses that are global (in the loader)*/
3106 addr = globalGetProcAddr(pName);
3107 return addr;
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07003108 }
Jon Ashburn3d526cb2015-04-13 18:10:06 -06003109
Jon Ashburnd38bfb12014-10-14 19:15:22 -06003110
Jon Ashburn3d526cb2015-04-13 18:10:06 -06003111 /* for entrypoints that loader must handle (ie non-dispatchable or create object)
3112 make sure the loader entrypoint is returned */
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003113 addr = loader_non_passthrough_gdpa(pName);
Ian Elliotte19c9152015-04-15 12:53:19 -06003114 if (addr) {
Jon Ashburn3d526cb2015-04-13 18:10:06 -06003115 return addr;
Ian Elliotte19c9152015-04-15 12:53:19 -06003116 }
Jon Ashburn3d526cb2015-04-13 18:10:06 -06003117
3118 /* return the dispatch table entrypoint for the fastest case */
Jon Ashburn8d1b0b52015-05-18 13:20:15 -06003119 const VkLayerDispatchTable *disp_table = * (VkLayerDispatchTable **) device;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06003120 if (disp_table == NULL)
3121 return NULL;
3122
Jon Ashburn27cd5842015-05-12 17:26:48 -06003123 addr = loader_lookup_device_dispatch_table(disp_table, pName);
Chia-I Wuf46b81a2015-01-04 11:12:47 +08003124 if (addr)
3125 return addr;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06003126 else {
Jon Ashburn8d1b0b52015-05-18 13:20:15 -06003127 if (disp_table->GetDeviceProcAddr == NULL)
Jon Ashburnd38bfb12014-10-14 19:15:22 -06003128 return NULL;
Jon Ashburn8d1b0b52015-05-18 13:20:15 -06003129 return disp_table->GetDeviceProcAddr(device, pName);
Jon Ashburnd38bfb12014-10-14 19:15:22 -06003130 }
3131}
3132
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06003133LOADER_EXPORT VkResult VKAPI vkEnumerateInstanceExtensionProperties(
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003134 const char* pLayerName,
3135 uint32_t* pCount,
3136 VkExtensionProperties* pProperties)
3137{
Jon Ashburn432d2762015-09-18 12:53:16 -06003138 struct loader_extension_list *global_ext_list=NULL;
Jon Ashburnb82c1852015-08-11 14:49:54 -06003139 struct loader_layer_list instance_layers;
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003140 struct loader_extension_list icd_extensions;
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003141 struct loader_icd_libs icd_libs;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003142 uint32_t copy_size;
3143
Jon Ashburn87d6aa92015-08-28 15:19:27 -06003144 tls_instance = NULL;
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003145 memset(&icd_extensions, 0, sizeof(icd_extensions));
Mike Stroyan09c06c72015-10-01 15:23:48 -06003146 memset(&instance_layers, 0, sizeof(instance_layers));
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003147 loader_platform_thread_once(&once_init, loader_initialize);
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003148
Jon Ashburnb82c1852015-08-11 14:49:54 -06003149 /* get layer libraries if needed */
3150 if (pLayerName && strlen(pLayerName) != 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06003151 loader_layer_scan(NULL, &instance_layers, NULL);
Jon Ashburnb82c1852015-08-11 14:49:54 -06003152 for (uint32_t i = 0; i < instance_layers.count; i++) {
3153 struct loader_layer_properties *props = &instance_layers.list[i];
3154 if (strcmp(props->info.layerName, pLayerName) == 0) {
3155 global_ext_list = &props->instance_extension_list;
3156 }
3157 }
3158 }
3159 else {
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003160 /* Scan/discover all ICD libraries */
3161 memset(&icd_libs, 0 , sizeof(struct loader_icd_libs));
Jon Ashburne39a4f82015-08-28 13:38:21 -06003162 loader_icd_scan(NULL, &icd_libs);
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003163 /* get extensions from all ICD's, merge so no duplicates */
Jon Ashburne39a4f82015-08-28 13:38:21 -06003164 loader_get_icd_loader_instance_extensions(NULL, &icd_libs, &icd_extensions);
3165 loader_scanned_icd_clear(NULL, &icd_libs);
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003166 global_ext_list = &icd_extensions;
Jon Ashburnb82c1852015-08-11 14:49:54 -06003167 }
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003168
Jon Ashburnb82c1852015-08-11 14:49:54 -06003169 if (global_ext_list == NULL) {
Mike Stroyan09c06c72015-10-01 15:23:48 -06003170 loader_destroy_layer_list(NULL, &instance_layers);
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06003171 return VK_ERROR_LAYER_NOT_PRESENT;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003172 }
3173
3174 if (pProperties == NULL) {
Mike Stroyan09c06c72015-10-01 15:23:48 -06003175 *pCount = global_ext_list->count;
3176 loader_destroy_layer_list(NULL, &instance_layers);
Jon Ashburne39a4f82015-08-28 13:38:21 -06003177 loader_destroy_ext_list(NULL, &icd_extensions);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003178 return VK_SUCCESS;
3179 }
3180
Jon Ashburnb82c1852015-08-11 14:49:54 -06003181 copy_size = *pCount < global_ext_list->count ? *pCount : global_ext_list->count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003182 for (uint32_t i = 0; i < copy_size; i++) {
3183 memcpy(&pProperties[i],
Jon Ashburnb82c1852015-08-11 14:49:54 -06003184 &global_ext_list->list[i],
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003185 sizeof(VkExtensionProperties));
3186 }
3187 *pCount = copy_size;
Jon Ashburne39a4f82015-08-28 13:38:21 -06003188 loader_destroy_ext_list(NULL, &icd_extensions);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003189
Jon Ashburnb82c1852015-08-11 14:49:54 -06003190 if (copy_size < global_ext_list->count) {
Mike Stroyan09c06c72015-10-01 15:23:48 -06003191 loader_destroy_layer_list(NULL, &instance_layers);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003192 return VK_INCOMPLETE;
3193 }
3194
Mike Stroyan09c06c72015-10-01 15:23:48 -06003195 loader_destroy_layer_list(NULL, &instance_layers);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003196 return VK_SUCCESS;
3197}
3198
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06003199LOADER_EXPORT VkResult VKAPI vkEnumerateInstanceLayerProperties(
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003200 uint32_t* pCount,
3201 VkLayerProperties* pProperties)
Tony Barbour59a47322015-06-24 16:06:58 -06003202{
Jon Ashburn6301a0f2015-05-29 13:15:39 -06003203
Jon Ashburnb82c1852015-08-11 14:49:54 -06003204 struct loader_layer_list instance_layer_list;
Jon Ashburn87d6aa92015-08-28 15:19:27 -06003205 tls_instance = NULL;
Jon Ashburnb82c1852015-08-11 14:49:54 -06003206
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003207 loader_platform_thread_once(&once_init, loader_initialize);
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07003208
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003209 uint32_t copy_size;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06003210
Jon Ashburnb82c1852015-08-11 14:49:54 -06003211 /* get layer libraries */
3212 memset(&instance_layer_list, 0, sizeof(instance_layer_list));
Jon Ashburne39a4f82015-08-28 13:38:21 -06003213 loader_layer_scan(NULL, &instance_layer_list, NULL);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003214
3215 if (pProperties == NULL) {
Jon Ashburnb82c1852015-08-11 14:49:54 -06003216 *pCount = instance_layer_list.count;
Jon Ashburne39a4f82015-08-28 13:38:21 -06003217 loader_destroy_layer_list(NULL, &instance_layer_list);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003218 return VK_SUCCESS;
3219 }
3220
Jon Ashburnb82c1852015-08-11 14:49:54 -06003221 copy_size = (*pCount < instance_layer_list.count) ? *pCount : instance_layer_list.count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003222 for (uint32_t i = 0; i < copy_size; i++) {
Jon Ashburnb82c1852015-08-11 14:49:54 -06003223 memcpy(&pProperties[i], &instance_layer_list.list[i].info, sizeof(VkLayerProperties));
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003224 }
3225 *pCount = copy_size;
Jon Ashburne39a4f82015-08-28 13:38:21 -06003226 loader_destroy_layer_list(NULL, &instance_layer_list);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003227
Jon Ashburnb82c1852015-08-11 14:49:54 -06003228 if (copy_size < instance_layer_list.count) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003229 return VK_INCOMPLETE;
3230 }
Tony Barbour59a47322015-06-24 16:06:58 -06003231
3232 return VK_SUCCESS;
3233}
3234
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06003235VkResult VKAPI loader_EnumerateDeviceExtensionProperties(
Tony Barbour59a47322015-06-24 16:06:58 -06003236 VkPhysicalDevice gpu,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003237 const char* pLayerName,
3238 uint32_t* pCount,
Tony Barbour59a47322015-06-24 16:06:58 -06003239 VkExtensionProperties* pProperties)
3240{
3241 uint32_t gpu_index;
Jon Ashburn128f9422015-05-28 19:16:58 -06003242 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003243 uint32_t copy_size;
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07003244
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003245 uint32_t count;
Jon Ashburn432d2762015-09-18 12:53:16 -06003246 struct loader_extension_list *dev_ext_list=NULL;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003247
Jon Ashburnb82c1852015-08-11 14:49:54 -06003248 /* get layer libraries if needed */
3249 if (pLayerName && strlen(pLayerName) != 0) {
Jon Ashburn3d002332015-08-20 16:35:30 -06003250 for (uint32_t i = 0; i < icd->this_instance->device_layer_list.count; i++) {
3251 struct loader_layer_properties *props = &icd->this_instance->device_layer_list.list[i];
Jon Ashburnb82c1852015-08-11 14:49:54 -06003252 if (strcmp(props->info.layerName, pLayerName) == 0) {
3253 dev_ext_list = &props->device_extension_list;
3254 }
3255 }
3256 }
3257 else {
3258 dev_ext_list = &icd->device_extension_cache[gpu_index];
3259 }
3260
Jon Ashburn432d2762015-09-18 12:53:16 -06003261 count = (dev_ext_list == NULL) ? 0: dev_ext_list->count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003262 if (pProperties == NULL) {
3263 *pCount = count;
3264 return VK_SUCCESS;
3265 }
3266
3267 copy_size = *pCount < count ? *pCount : count;
3268 for (uint32_t i = 0; i < copy_size; i++) {
3269 memcpy(&pProperties[i],
Jon Ashburnb82c1852015-08-11 14:49:54 -06003270 &dev_ext_list->list[i],
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003271 sizeof(VkExtensionProperties));
3272 }
3273 *pCount = copy_size;
3274
3275 if (copy_size < count) {
3276 return VK_INCOMPLETE;
3277 }
3278
3279 return VK_SUCCESS;
3280}
3281
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06003282VkResult VKAPI loader_EnumerateDeviceLayerProperties(
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003283 VkPhysicalDevice gpu,
3284 uint32_t* pCount,
3285 VkLayerProperties* pProperties)
3286{
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003287 uint32_t copy_size;
Jon Ashburn3d002332015-08-20 16:35:30 -06003288 uint32_t gpu_index;
3289 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003290
Jon Ashburn3d002332015-08-20 16:35:30 -06003291 uint32_t count = icd->this_instance->device_layer_list.count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003292
3293 if (pProperties == NULL) {
3294 *pCount = count;
3295 return VK_SUCCESS;
3296 }
3297
Jon Ashburnb82c1852015-08-11 14:49:54 -06003298 copy_size = (*pCount < count) ? *pCount : count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003299 for (uint32_t i = 0; i < copy_size; i++) {
Jon Ashburn3d002332015-08-20 16:35:30 -06003300 memcpy(&pProperties[i], &(icd->this_instance->device_layer_list.list[i].info), sizeof(VkLayerProperties));
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003301 }
3302 *pCount = copy_size;
3303
3304 if (copy_size < count) {
3305 return VK_INCOMPLETE;
3306 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003307
3308 return VK_SUCCESS;
Jon Ashburn95a77ba2015-05-15 15:09:35 -06003309}