blob: 80a628db165ce22c3fbbc458a95088b7528a8b91 [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
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600121void loader_heap_free(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600122 const struct loader_instance *instance,
123 void *pMem)
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600124{
Mike Stroyan09c06c72015-10-01 15:23:48 -0600125 if (pMem == NULL) return;
Jon Ashburneacfa3a2015-08-14 12:51:47 -0600126 if (instance && instance->alloc_callbacks.pfnFree) {
Courtney Goeltzenleuchter922e1452015-07-10 17:39:59 -0600127 instance->alloc_callbacks.pfnFree(instance->alloc_callbacks.pUserData, pMem);
Jon Ashburnd2c171b2015-08-13 08:28:48 -0600128 return;
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600129 }
Courtney Goeltzenleuchter922e1452015-07-10 17:39:59 -0600130 free(pMem);
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600131}
132
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600133void* loader_heap_realloc(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600134 const struct loader_instance *instance,
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600135 void *pMem,
136 size_t orig_size,
137 size_t size,
138 VkSystemAllocType alloc_type)
139{
140 if (pMem == NULL || orig_size == 0)
141 return loader_heap_alloc(instance, size, alloc_type);
142 if (size == 0) {
143 loader_heap_free(instance, pMem);
144 return NULL;
145 }
146 if (instance && instance->alloc_callbacks.pfnAlloc) {
147 if (size <= orig_size) {
148 memset(((uint8_t *)pMem) + size, 0, orig_size - size);
149 return pMem;
150 }
151 void *new_ptr = instance->alloc_callbacks.pfnAlloc(instance->alloc_callbacks.pUserData, size, 4, alloc_type);
152 if (!new_ptr)
153 return NULL;
154 memcpy(new_ptr, pMem, orig_size);
155 instance->alloc_callbacks.pfnFree(instance->alloc_callbacks.pUserData, pMem);
156 }
157 return realloc(pMem, size);
158}
159
Jon Ashburn87d6aa92015-08-28 15:19:27 -0600160void *loader_tls_heap_alloc(size_t size)
161{
162 return loader_heap_alloc(tls_instance, size, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
163}
164
165void loader_tls_heap_free(void *pMem)
166{
Jon Ashburn557efa72015-10-07 09:23:40 -0600167 loader_heap_free(tls_instance, pMem);
Jon Ashburn87d6aa92015-08-28 15:19:27 -0600168}
169
Jon Ashburnffad94d2015-06-30 14:46:22 -0700170static void loader_log(VkFlags msg_type, int32_t msg_code,
171 const char *format, ...)
172{
Jon Ashburn86723b02015-07-31 15:47:59 -0600173 char msg[512];
Jon Ashburnffad94d2015-06-30 14:46:22 -0700174 va_list ap;
175 int ret;
176
177 if (!(msg_type & g_loader_log_msgs)) {
178 return;
179 }
180
181 va_start(ap, format);
182 ret = vsnprintf(msg, sizeof(msg), format, ap);
183 if ((ret >= (int) sizeof(msg)) || ret < 0) {
184 msg[sizeof(msg)-1] = '\0';
185 }
186 va_end(ap);
187
Ian Elliott4470a302015-02-17 10:33:47 -0700188#if defined(WIN32)
Jon Ashburnffad94d2015-06-30 14:46:22 -0700189 OutputDebugString(msg);
mschottb9cdb782015-07-22 14:11:29 +0200190 OutputDebugString("\n");
Jon Ashburnffad94d2015-06-30 14:46:22 -0700191#endif
192 fputs(msg, stderr);
193 fputc('\n', stderr);
194}
195
196#if defined(WIN32)
Tony Barbourea968902015-07-29 14:26:21 -0600197static char *loader_get_next_path(char *path);
Jon Ashburnffad94d2015-06-30 14:46:22 -0700198/**
199* Find the list of registry files (names within a key) in key "location".
200*
201* This function looks in the registry (hive = DEFAULT_VK_REGISTRY_HIVE) key as given in "location"
202* for a list or name/values which are added to a returned list (function return value).
203* The DWORD values within the key must be 0 or they are skipped.
Jon Ashburne39a4f82015-08-28 13:38:21 -0600204* Function return is a string with a ';' separated list of filenames.
Jon Ashburnffad94d2015-06-30 14:46:22 -0700205* Function return is NULL if no valid name/value pairs are found in the key,
206* or the key is not found.
207*
208* \returns
209* A string list of filenames as pointer.
210* When done using the returned string list, pointer should be freed.
211*/
Jon Ashburne39a4f82015-08-28 13:38:21 -0600212static char *loader_get_registry_files(const struct loader_instance *inst, char *location)
Jon Ashburnffad94d2015-06-30 14:46:22 -0700213{
214 LONG rtn_value;
215 HKEY hive, key;
216 DWORD access_flags = KEY_QUERY_VALUE;
217 char name[2048];
218 char *out = NULL;
Tony Barbourea968902015-07-29 14:26:21 -0600219 char *loc = location;
220 char *next;
Jon Ashburnffad94d2015-06-30 14:46:22 -0700221 DWORD idx = 0;
222 DWORD name_size = sizeof(name);
223 DWORD value;
224 DWORD total_size = 4096;
225 DWORD value_size = sizeof(value);
Tony Barbourea968902015-07-29 14:26:21 -0600226
227 while(*loc)
228 {
229 next = loader_get_next_path(loc);
230 hive = DEFAULT_VK_REGISTRY_HIVE;
231 rtn_value = RegOpenKeyEx(hive, loc, 0, access_flags, &key);
232 if (rtn_value != ERROR_SUCCESS) {
233 // We didn't find the key. Try the 32-bit hive (where we've seen the
234 // key end up on some people's systems):
235 access_flags |= KEY_WOW64_32KEY;
236 rtn_value = RegOpenKeyEx(hive, loc, 0, access_flags, &key);
237 if (rtn_value != ERROR_SUCCESS) {
238 // We still couldn't find the key, so give up:
239 loc = next;
240 continue;
Jon Ashburnffad94d2015-06-30 14:46:22 -0700241 }
Jon Ashburnffad94d2015-06-30 14:46:22 -0700242 }
Tony Barbourea968902015-07-29 14:26:21 -0600243
Jon Ashburne39a4f82015-08-28 13:38:21 -0600244 while ((rtn_value = RegEnumValue(key, idx++, name, &name_size, NULL, NULL, (LPBYTE) &value, &value_size)) == ERROR_SUCCESS) {
Tony Barbourea968902015-07-29 14:26:21 -0600245 if (value_size == sizeof(value) && value == 0) {
246 if (out == NULL) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600247 out = loader_heap_alloc(inst, total_size, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Tony Barbourea968902015-07-29 14:26:21 -0600248 out[0] = '\0';
249 }
250 else if (strlen(out) + name_size + 1 > total_size) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600251 out = loader_heap_realloc(inst, out, total_size, total_size * 2, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Tony Barbourea968902015-07-29 14:26:21 -0600252 total_size *= 2;
253 }
254 if (out == NULL) {
255 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory, failed loader_get_registry_files");
256 return NULL;
257 }
258 if (strlen(out) == 0)
259 snprintf(out, name_size + 1, "%s", name);
260 else
261 snprintf(out + strlen(out), name_size + 2, "%c%s", PATH_SEPERATOR, name);
262 }
263 name_size = 2048;
264 }
265 loc = next;
Jon Ashburnffad94d2015-06-30 14:46:22 -0700266 }
Tony Barbourea968902015-07-29 14:26:21 -0600267
Jon Ashburnffad94d2015-06-30 14:46:22 -0700268 return out;
269}
270
Ian Elliott4470a302015-02-17 10:33:47 -0700271#endif // WIN32
272
Jon Ashburnc7237a72015-08-03 09:08:46 -0600273/**
274 * Given string of three part form "maj.min.pat" convert to a vulkan version
275 * number.
276 */
277static uint32_t loader_make_version(const char *vers_str)
278{
Jon Ashburn432d2762015-09-18 12:53:16 -0600279 uint32_t vers = 0, major=0, minor=0, patch=0;
Jon Ashburnc7237a72015-08-03 09:08:46 -0600280 char *minor_str= NULL;
281 char *patch_str = NULL;
282 char *cstr;
283 char *str;
284
285 if (!vers_str)
286 return vers;
287 cstr = loader_stack_alloc(strlen(vers_str) + 1);
288 strcpy(cstr, vers_str);
289 while ((str = strchr(cstr, '.')) != NULL) {
290 if (minor_str == NULL) {
291 minor_str = str + 1;
292 *str = '\0';
293 major = atoi(cstr);
294 }
295 else if (patch_str == NULL) {
296 patch_str = str + 1;
297 *str = '\0';
298 minor = atoi(minor_str);
299 }
300 else {
301 return vers;
302 }
303 cstr = str + 1;
304 }
305 patch = atoi(patch_str);
306
307 return VK_MAKE_VERSION(major, minor, patch);
308
309}
310
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600311bool compare_vk_extension_properties(const VkExtensionProperties *op1, const VkExtensionProperties *op2)
312{
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600313 return strcmp(op1->extName, op2->extName) == 0 ? true : false;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600314}
315
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -0600316/**
Jon Ashburnbd6c4882015-07-02 12:59:25 -0600317 * Search the given ext_array for an extension
318 * matching the given vk_ext_prop
319 */
320bool has_vk_extension_property_array(
321 const VkExtensionProperties *vk_ext_prop,
322 const uint32_t count,
323 const VkExtensionProperties *ext_array)
324{
325 for (uint32_t i = 0; i < count; i++) {
326 if (compare_vk_extension_properties(vk_ext_prop, &ext_array[i]))
327 return true;
328 }
329 return false;
330}
331
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -0600332/**
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600333 * Search the given ext_list for an extension
334 * matching the given vk_ext_prop
335 */
336bool has_vk_extension_property(
337 const VkExtensionProperties *vk_ext_prop,
338 const struct loader_extension_list *ext_list)
339{
340 for (uint32_t i = 0; i < ext_list->count; i++) {
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600341 if (compare_vk_extension_properties(&ext_list->list[i], vk_ext_prop))
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600342 return true;
343 }
344 return false;
345}
346
Jon Ashburnb2ef1372015-07-16 17:19:31 -0600347static inline bool loader_is_layer_type_device(const enum layer_type type) {
348 if ((type & VK_LAYER_TYPE_DEVICE_EXPLICIT) ||
349 (type & VK_LAYER_TYPE_DEVICE_IMPLICIT))
350 return true;
351 return false;
352}
353
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600354/*
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -0600355 * Search the given layer list for a layer matching the given layer name
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600356 */
Jon Ashburne13ecc92015-08-03 17:19:30 -0600357static struct loader_layer_properties *loader_get_layer_property(
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600358 const char *name,
359 const struct loader_layer_list *layer_list)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600360{
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600361 for (uint32_t i = 0; i < layer_list->count; i++) {
362 const VkLayerProperties *item = &layer_list->list[i].info;
363 if (strcmp(name, item->layerName) == 0)
364 return &layer_list->list[i];
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600365 }
366 return NULL;
367}
368
Jon Ashburne13ecc92015-08-03 17:19:30 -0600369/**
370 * Get the next unused layer property in the list. Init the property to zero.
371 */
372static struct loader_layer_properties *loader_get_next_layer_property(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600373 const struct loader_instance *inst,
Jon Ashburne13ecc92015-08-03 17:19:30 -0600374 struct loader_layer_list *layer_list)
375{
376 if (layer_list->capacity == 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600377 layer_list->list = loader_heap_alloc(inst,
378 sizeof(struct loader_layer_properties) * 64,
379 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburne13ecc92015-08-03 17:19:30 -0600380 if (layer_list->list == NULL) {
381 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't add any layer properties to list");
382 return NULL;
383 }
384 memset(layer_list->list, 0, sizeof(struct loader_layer_properties) * 64);
385 layer_list->capacity = sizeof(struct loader_layer_properties) * 64;
386 }
387
388 // ensure enough room to add an entry
389 if ((layer_list->count + 1) * sizeof (struct loader_layer_properties)
390 > layer_list->capacity) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600391 layer_list->list = loader_heap_realloc(inst, layer_list->list,
392 layer_list->capacity,
393 layer_list->capacity * 2,
394 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburne13ecc92015-08-03 17:19:30 -0600395 if (layer_list->list == NULL) {
396 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
397 "realloc failed for layer list");
398 }
399 layer_list->capacity *= 2;
400 }
401
402 layer_list->count++;
403 return &(layer_list->list[layer_list->count - 1]);
404}
405
406/**
407 * Remove all layer properties entrys from the list
408 */
Jon Ashburne39a4f82015-08-28 13:38:21 -0600409void loader_delete_layer_properties(
410 const struct loader_instance *inst,
411 struct loader_layer_list *layer_list)
Jon Ashburne13ecc92015-08-03 17:19:30 -0600412{
413 uint32_t i;
414
Jon Ashburnb82c1852015-08-11 14:49:54 -0600415 if (!layer_list)
416 return;
417
Jon Ashburne13ecc92015-08-03 17:19:30 -0600418 for (i = 0; i < layer_list->count; i++) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600419 loader_destroy_ext_list(inst, &layer_list->list[i].instance_extension_list);
420 loader_destroy_ext_list(inst, &layer_list->list[i].device_extension_list);
Jon Ashburne13ecc92015-08-03 17:19:30 -0600421 }
422 layer_list->count = 0;
423
Jon Ashburnb82c1852015-08-11 14:49:54 -0600424 if (layer_list->capacity > 0) {
425 layer_list->capacity = 0;
Jon Ashburne39a4f82015-08-28 13:38:21 -0600426 loader_heap_free(inst, layer_list->list);
Jon Ashburnb82c1852015-08-11 14:49:54 -0600427 }
Jon Ashburne13ecc92015-08-03 17:19:30 -0600428
429}
430
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600431static void loader_add_global_extensions(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600432 const struct loader_instance *inst,
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -0600433 const PFN_vkEnumerateInstanceExtensionProperties fp_get_props,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600434 const char *lib_name,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600435 struct loader_extension_list *ext_list)
436{
437 uint32_t i, count;
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600438 VkExtensionProperties *ext_props;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600439 VkResult res;
440
Courtney Goeltzenleuchter5c6cf472015-07-06 22:28:18 -0600441 if (!fp_get_props) {
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -0600442 /* No EnumerateInstanceExtensionProperties defined */
Courtney Goeltzenleuchter5c6cf472015-07-06 22:28:18 -0600443 return;
444 }
445
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600446 res = fp_get_props(NULL, &count, NULL);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600447 if (res != VK_SUCCESS) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600448 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Error getting global extension count from %s", lib_name);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600449 return;
450 }
Jon Ashburn953bb3c2015-06-10 16:11:42 -0600451
Courtney Goeltzenleuchter5c6cf472015-07-06 22:28:18 -0600452 if (count == 0) {
453 /* No ExtensionProperties to report */
454 return;
455 }
456
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600457 ext_props = loader_stack_alloc(count * sizeof(VkExtensionProperties));
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600458
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600459 res = fp_get_props(NULL, &count, ext_props);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600460 if (res != VK_SUCCESS) {
461 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Error getting global extensions from %s", lib_name);
462 return;
463 }
Tony Barbour59a47322015-06-24 16:06:58 -0600464
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600465 for (i = 0; i < count; i++) {
Courtney Goeltzenleuchter53043732015-07-12 13:20:05 -0600466 char spec_version[64];
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600467
468 snprintf(spec_version, sizeof(spec_version), "%d.%d.%d",
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600469 VK_MAJOR(ext_props[i].specVersion),
470 VK_MINOR(ext_props[i].specVersion),
471 VK_PATCH(ext_props[i].specVersion));
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600472 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Courtney Goeltzenleuchter53043732015-07-12 13:20:05 -0600473 "Global Extension: %s (%s) version %s",
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600474 ext_props[i].extName, lib_name, spec_version);
Jon Ashburne39a4f82015-08-28 13:38:21 -0600475 loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600476 }
477
478 return;
479}
480
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600481static void loader_add_physical_device_extensions(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600482 const struct loader_instance *inst,
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -0600483 PFN_vkEnumerateDeviceExtensionProperties get_phys_dev_ext_props,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600484 VkPhysicalDevice physical_device,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600485 const char *lib_name,
486 struct loader_extension_list *ext_list)
487{
488 uint32_t i, count;
489 VkResult res;
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600490 VkExtensionProperties *ext_props;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600491
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600492 if (!get_phys_dev_ext_props) {
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -0600493 /* No EnumerateDeviceExtensionProperties defined */
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600494 return;
495 }
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600496
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600497 res = get_phys_dev_ext_props(physical_device, NULL, &count, NULL);
498 if (res == VK_SUCCESS && count > 0) {
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600499 ext_props = loader_stack_alloc(count * sizeof(VkExtensionProperties));
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600500
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600501 res = get_phys_dev_ext_props(physical_device, NULL, &count, ext_props);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600502 for (i = 0; i < count; i++) {
Courtney Goeltzenleuchter53043732015-07-12 13:20:05 -0600503 char spec_version[64];
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600504
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600505 snprintf(spec_version, sizeof(spec_version), "%d.%d.%d",
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600506 VK_MAJOR(ext_props[i].specVersion),
507 VK_MINOR(ext_props[i].specVersion),
508 VK_PATCH(ext_props[i].specVersion));
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600509 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Courtney Goeltzenleuchter53043732015-07-12 13:20:05 -0600510 "PhysicalDevice Extension: %s (%s) version %s",
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600511 ext_props[i].extName, lib_name, spec_version);
Jon Ashburne39a4f82015-08-28 13:38:21 -0600512 loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
Jon Ashburn953bb3c2015-06-10 16:11:42 -0600513 }
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600514 } else {
Jon Ashburnf73e9212015-08-04 10:22:33 -0600515 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 -0600516 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600517
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600518 return;
519}
520
Jon Ashburne39a4f82015-08-28 13:38:21 -0600521static bool loader_init_ext_list(const struct loader_instance *inst,
522 struct loader_extension_list *ext_info)
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600523{
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600524 ext_info->capacity = 32 * sizeof(VkExtensionProperties);
Jon Ashburne39a4f82015-08-28 13:38:21 -0600525 ext_info->list = loader_heap_alloc(inst, ext_info->capacity, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600526 if (ext_info->list == NULL) {
527 return false;
528 }
529 memset(ext_info->list, 0, ext_info->capacity);
530 ext_info->count = 0;
531 return true;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600532}
533
Jon Ashburne39a4f82015-08-28 13:38:21 -0600534void loader_destroy_ext_list(const struct loader_instance *inst,
535 struct loader_extension_list *ext_info)
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600536{
Jon Ashburne39a4f82015-08-28 13:38:21 -0600537 loader_heap_free(inst, ext_info->list);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600538 ext_info->count = 0;
539 ext_info->capacity = 0;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600540}
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600541
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600542/*
543 * Append non-duplicate extension properties defined in props
544 * to the given ext_list.
545 */
546void loader_add_to_ext_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600547 const struct loader_instance *inst,
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600548 struct loader_extension_list *ext_list,
549 uint32_t prop_list_count,
550 const VkExtensionProperties *props)
551{
552 uint32_t i;
553 const VkExtensionProperties *cur_ext;
554
555 if (ext_list->list == NULL || ext_list->capacity == 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600556 loader_init_ext_list(inst, ext_list);
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600557 }
558
559 if (ext_list->list == NULL)
560 return;
561
562 for (i = 0; i < prop_list_count; i++) {
563 cur_ext = &props[i];
564
565 // look for duplicates
566 if (has_vk_extension_property(cur_ext, ext_list)) {
567 continue;
568 }
569
570 // add to list at end
571 // check for enough capacity
572 if (ext_list->count * sizeof(VkExtensionProperties)
573 >= ext_list->capacity) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600574
575 ext_list->list = loader_heap_realloc(inst,
576 ext_list->list,
577 ext_list->capacity,
578 ext_list->capacity * 2,
579 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600580 // double capacity
581 ext_list->capacity *= 2;
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600582 }
583
584 memcpy(&ext_list->list[ext_list->count], cur_ext, sizeof(VkExtensionProperties));
585 ext_list->count++;
586 }
587}
588
Jon Ashburnbd6c4882015-07-02 12:59:25 -0600589/**
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600590 * Search the given search_list for any layers in the props list.
591 * Add these to the output layer_list. Don't add duplicates to the output layer_list.
Jon Ashburnbd6c4882015-07-02 12:59:25 -0600592 */
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -0600593static VkResult loader_add_layer_names_to_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600594 const struct loader_instance *inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600595 struct loader_layer_list *output_list,
596 uint32_t name_count,
597 const char * const *names,
598 const struct loader_layer_list *search_list)
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600599{
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600600 struct loader_layer_properties *layer_prop;
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -0600601 VkResult err = VK_SUCCESS;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600602
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600603 for (uint32_t i = 0; i < name_count; i++) {
604 const char *search_target = names[i];
Jon Ashburne13ecc92015-08-03 17:19:30 -0600605 layer_prop = loader_get_layer_property(search_target, search_list);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600606 if (!layer_prop) {
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -0600607 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Unable to find layer %s", search_target);
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -0600608 err = VK_ERROR_LAYER_NOT_PRESENT;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600609 continue;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600610 }
611
Jon Ashburne39a4f82015-08-28 13:38:21 -0600612 loader_add_to_layer_list(inst, output_list, 1, layer_prop);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600613 }
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -0600614
615 return err;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600616}
617
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600618
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600619/*
620 * Manage lists of VkLayerProperties
621 */
Jon Ashburne39a4f82015-08-28 13:38:21 -0600622static bool loader_init_layer_list(const struct loader_instance *inst,
623 struct loader_layer_list *list)
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600624{
625 list->capacity = 32 * sizeof(struct loader_layer_properties);
Jon Ashburne39a4f82015-08-28 13:38:21 -0600626 list->list = loader_heap_alloc(inst, list->capacity, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600627 if (list->list == NULL) {
628 return false;
629 }
630 memset(list->list, 0, list->capacity);
631 list->count = 0;
632 return true;
633}
634
Jon Ashburne39a4f82015-08-28 13:38:21 -0600635void loader_destroy_layer_list(const struct loader_instance *inst,
636 struct loader_layer_list *layer_list)
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600637{
Jon Ashburne39a4f82015-08-28 13:38:21 -0600638 loader_heap_free(inst, layer_list->list);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600639 layer_list->count = 0;
640 layer_list->capacity = 0;
641}
642
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600643/*
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600644 * Manage list of layer libraries (loader_lib_info)
645 */
Jon Ashburne39a4f82015-08-28 13:38:21 -0600646static bool loader_init_layer_library_list(const struct loader_instance *inst,
647 struct loader_layer_library_list *list)
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600648{
649 list->capacity = 32 * sizeof(struct loader_lib_info);
Jon Ashburne39a4f82015-08-28 13:38:21 -0600650 list->list = loader_heap_alloc(inst, list->capacity, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600651 if (list->list == NULL) {
652 return false;
653 }
654 memset(list->list, 0, list->capacity);
655 list->count = 0;
656 return true;
657}
658
Jon Ashburne39a4f82015-08-28 13:38:21 -0600659void loader_destroy_layer_library_list(const struct loader_instance *inst,
660 struct loader_layer_library_list *list)
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600661{
662 for (uint32_t i = 0; i < list->count; i++) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600663 loader_heap_free(inst, list->list[i].lib_name);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600664 }
Jon Ashburne39a4f82015-08-28 13:38:21 -0600665 loader_heap_free(inst, list->list);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600666 list->count = 0;
667 list->capacity = 0;
668}
669
670void loader_add_to_layer_library_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600671 const struct loader_instance *inst,
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600672 struct loader_layer_library_list *list,
673 uint32_t item_count,
674 const struct loader_lib_info *new_items)
675{
676 uint32_t i;
677 struct loader_lib_info *item;
678
679 if (list->list == NULL || list->capacity == 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600680 loader_init_layer_library_list(inst, list);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600681 }
682
683 if (list->list == NULL)
684 return;
685
686 for (i = 0; i < item_count; i++) {
687 item = (struct loader_lib_info *) &new_items[i];
688
689 // look for duplicates
690 for (uint32_t j = 0; j < list->count; j++) {
691 if (strcmp(list->list[i].lib_name, new_items->lib_name) == 0) {
692 continue;
693 }
694 }
695
696 // add to list at end
697 // check for enough capacity
698 if (list->count * sizeof(struct loader_lib_info)
699 >= list->capacity) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600700
701 list->list = loader_heap_realloc(inst,
702 list->list,
703 list->capacity,
704 list->capacity * 2,
705 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600706 // double capacity
707 list->capacity *= 2;
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600708 }
709
710 memcpy(&list->list[list->count], item, sizeof(struct loader_lib_info));
711 list->count++;
712 }
713}
714
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600715
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600716/*
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600717 * Search the given layer list for a list
718 * matching the given VkLayerProperties
719 */
720bool has_vk_layer_property(
721 const VkLayerProperties *vk_layer_prop,
722 const struct loader_layer_list *list)
723{
724 for (uint32_t i = 0; i < list->count; i++) {
725 if (strcmp(vk_layer_prop->layerName, list->list[i].info.layerName) == 0)
726 return true;
727 }
728 return false;
729}
730
731/*
732 * Search the given layer list for a layer
733 * matching the given name
734 */
735bool has_layer_name(
736 const char *name,
737 const struct loader_layer_list *list)
738{
739 for (uint32_t i = 0; i < list->count; i++) {
740 if (strcmp(name, list->list[i].info.layerName) == 0)
741 return true;
742 }
743 return false;
744}
745
746/*
747 * Append non-duplicate layer properties defined in prop_list
748 * to the given layer_info list
749 */
750void loader_add_to_layer_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600751 const struct loader_instance *inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600752 struct loader_layer_list *list,
753 uint32_t prop_list_count,
754 const struct loader_layer_properties *props)
755{
756 uint32_t i;
757 struct loader_layer_properties *layer;
758
759 if (list->list == NULL || list->capacity == 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600760 loader_init_layer_list(inst, list);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600761 }
762
763 if (list->list == NULL)
764 return;
765
766 for (i = 0; i < prop_list_count; i++) {
767 layer = (struct loader_layer_properties *) &props[i];
768
769 // look for duplicates
770 if (has_vk_layer_property(&layer->info, list)) {
771 continue;
772 }
773
774 // add to list at end
775 // check for enough capacity
776 if (list->count * sizeof(struct loader_layer_properties)
777 >= list->capacity) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600778
779 list->list = loader_heap_realloc(inst,
780 list->list,
781 list->capacity,
782 list->capacity * 2,
783 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600784 // double capacity
785 list->capacity *= 2;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600786 }
787
788 memcpy(&list->list[list->count], layer, sizeof(struct loader_layer_properties));
789 list->count++;
790 }
791}
792
Jon Ashburnbd332cc2015-07-07 10:27:45 -0600793/**
794 * Search the search_list for any layer with a name
795 * that matches the given name and a type that matches the given type
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600796 * Add all matching layers to the found_list
Jon Ashburnbd332cc2015-07-07 10:27:45 -0600797 * Do not add if found loader_layer_properties is already
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600798 * on the found_list.
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600799 */
Jon Ashburnbd6c4882015-07-02 12:59:25 -0600800static void loader_find_layer_name_add_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600801 const struct loader_instance *inst,
Jon Ashburnbd6c4882015-07-02 12:59:25 -0600802 const char *name,
Jon Ashburnbd332cc2015-07-07 10:27:45 -0600803 const enum layer_type type,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600804 const struct loader_layer_list *search_list,
805 struct loader_layer_list *found_list)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600806{
Jon Ashburn56151d62015-10-05 09:03:21 -0600807 bool found = false;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600808 for (uint32_t i = 0; i < search_list->count; i++) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600809 struct loader_layer_properties *layer_prop = &search_list->list[i];
Jon Ashburnbd332cc2015-07-07 10:27:45 -0600810 if (0 == strcmp(layer_prop->info.layerName, name) &&
811 (layer_prop->type & type)) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600812 /* Found a layer with the same name, add to found_list */
Jon Ashburne39a4f82015-08-28 13:38:21 -0600813 loader_add_to_layer_list(inst, found_list, 1, layer_prop);
Jon Ashburn56151d62015-10-05 09:03:21 -0600814 found = true;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600815 }
816 }
Jon Ashburn56151d62015-10-05 09:03:21 -0600817 if (!found) {
818 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Warning, couldn't find layer name %s to activate", name);
819 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600820}
821
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600822static VkExtensionProperties *get_extension_property(
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -0600823 const char *name,
824 const struct loader_extension_list *list)
Jon Ashburnfc2e38c2015-04-14 09:15:32 -0600825{
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -0600826 for (uint32_t i = 0; i < list->count; i++) {
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600827 if (strcmp(name, list->list[i].extName) == 0)
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -0600828 return &list->list[i];
Jon Ashburnfc2e38c2015-04-14 09:15:32 -0600829 }
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -0600830 return NULL;
Jon Ashburnfc2e38c2015-04-14 09:15:32 -0600831}
832
Jon Ashburnbd6c4882015-07-02 12:59:25 -0600833/*
834 * For global exenstions implemented within the loader (i.e. DEBUG_REPORT
835 * the extension must provide two entry points for the loader to use:
836 * - "trampoline" entry point - this is the address returned by GetProcAddr
837 * and will always do what's necessary to support a global call.
838 * - "terminator" function - this function will be put at the end of the
839 * instance chain and will contain the necessary logica to call / process
840 * the extension for the appropriate ICDs that are available.
841 * There is no generic mechanism for including these functions, the references
842 * must be placed into the appropriate loader entry points.
843 * GetInstanceProcAddr: call extension GetInstanceProcAddr to check for GetProcAddr requests
844 * loader_coalesce_extensions(void) - add extension records to the list of global
845 * extension available to the app.
846 * instance_disp - add function pointer for terminator function to this array.
847 * The extension itself should be in a separate file that will be
848 * linked directly with the loader.
849 */
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -0600850
Jon Ashburn8810c5f2015-08-18 18:04:47 -0600851void loader_get_icd_loader_instance_extensions(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600852 const struct loader_instance *inst,
Jon Ashburn8810c5f2015-08-18 18:04:47 -0600853 struct loader_icd_libs *icd_libs,
854 struct loader_extension_list *inst_exts)
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600855{
Jon Ashburn5c6a46f2015-08-14 14:49:22 -0600856 struct loader_extension_list icd_exts;
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -0600857 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, "Build ICD instance extension list");
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600858 // traverse scanned icd list adding non-duplicate extensions to the list
Jon Ashburn8810c5f2015-08-18 18:04:47 -0600859 for (uint32_t i = 0; i < icd_libs->count; i++) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600860 loader_init_ext_list(inst, &icd_exts);
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -0600861 loader_add_global_extensions(inst, icd_libs->list[i].EnumerateInstanceExtensionProperties,
Jon Ashburn8810c5f2015-08-18 18:04:47 -0600862 icd_libs->list[i].lib_name,
Jon Ashburn5c6a46f2015-08-14 14:49:22 -0600863 &icd_exts);
Jon Ashburne39a4f82015-08-28 13:38:21 -0600864 loader_add_to_ext_list(inst, inst_exts,
Jon Ashburn5c6a46f2015-08-14 14:49:22 -0600865 icd_exts.count,
866 icd_exts.list);
Jon Ashburne39a4f82015-08-28 13:38:21 -0600867 loader_destroy_ext_list(inst, &icd_exts);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600868 };
869
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600870 // Traverse loader's extensions, adding non-duplicate extensions to the list
Jon Ashburne39a4f82015-08-28 13:38:21 -0600871 wsi_swapchain_add_instance_extensions(inst, inst_exts);
872 debug_report_add_instance_extensions(inst, inst_exts);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600873}
874
Jon Ashburne39a4f82015-08-28 13:38:21 -0600875struct loader_icd *loader_get_icd_and_device(const VkDevice device,
876 struct loader_device **found_dev)
Jon Ashburndc6fcad2015-06-10 10:06:06 -0600877{
878 *found_dev = NULL;
879 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
880 for (struct loader_icd *icd = inst->icds; icd; icd = icd->next) {
881 for (struct loader_device *dev = icd->logical_device_list; dev; dev = dev->next)
Jon Ashburne0e64572015-09-30 12:56:42 -0600882 /* Value comparison of device prevents object wrapping by layers */
883 if (loader_get_dispatch(dev->device) == loader_get_dispatch(device)) {
Jon Ashburndc6fcad2015-06-10 10:06:06 -0600884 *found_dev = dev;
885 return icd;
886 }
887 }
888 }
889 return NULL;
890}
891
Jon Ashburne39a4f82015-08-28 13:38:21 -0600892static void loader_destroy_logical_device(const struct loader_instance *inst,
893 struct loader_device *dev)
Jon Ashburndc6fcad2015-06-10 10:06:06 -0600894{
Jon Ashburne39a4f82015-08-28 13:38:21 -0600895 loader_heap_free(inst, dev->app_extension_props);
Jon Ashburndc6fcad2015-06-10 10:06:06 -0600896 if (dev->activated_layer_list.count)
Jon Ashburne39a4f82015-08-28 13:38:21 -0600897 loader_destroy_layer_list(inst, &dev->activated_layer_list);
898 loader_heap_free(inst, dev);
Jon Ashburndc6fcad2015-06-10 10:06:06 -0600899}
900
Jon Ashburne39a4f82015-08-28 13:38:21 -0600901static struct loader_device *loader_add_logical_device(
902 const struct loader_instance *inst,
903 const VkDevice dev,
904 struct loader_device **device_list)
Jon Ashburndc6fcad2015-06-10 10:06:06 -0600905{
906 struct loader_device *new_dev;
907
Jon Ashburne39a4f82015-08-28 13:38:21 -0600908 new_dev = loader_heap_alloc(inst, sizeof(struct loader_device), VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburndc6fcad2015-06-10 10:06:06 -0600909 if (!new_dev) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600910 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc struct laoder-device");
Jon Ashburndc6fcad2015-06-10 10:06:06 -0600911 return NULL;
912 }
913
914 memset(new_dev, 0, sizeof(struct loader_device));
915
916 new_dev->next = *device_list;
917 new_dev->device = dev;
918 *device_list = new_dev;
919 return new_dev;
920}
921
Jon Ashburne39a4f82015-08-28 13:38:21 -0600922void loader_remove_logical_device(
923 const struct loader_instance *inst,
924 VkDevice device)
Jon Ashburndc6fcad2015-06-10 10:06:06 -0600925{
926 struct loader_device *found_dev, *dev, *prev_dev;
927 struct loader_icd *icd;
928 icd = loader_get_icd_and_device(device, &found_dev);
929
930 if (!icd || !found_dev)
931 return;
932
933 prev_dev = NULL;
934 dev = icd->logical_device_list;
935 while (dev && dev != found_dev) {
936 prev_dev = dev;
937 dev = dev->next;
938 }
939
940 if (prev_dev)
941 prev_dev->next = found_dev->next;
942 else
943 icd->logical_device_list = found_dev->next;
Jon Ashburne39a4f82015-08-28 13:38:21 -0600944 loader_destroy_logical_device(inst, found_dev);
Jon Ashburndc6fcad2015-06-10 10:06:06 -0600945}
946
947
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600948static void loader_icd_destroy(
949 struct loader_instance *ptr_inst,
950 struct loader_icd *icd)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800951{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600952 ptr_inst->total_icd_count--;
Jon Ashburne39a4f82015-08-28 13:38:21 -0600953 loader_heap_free(ptr_inst, icd->gpus);
Courtney Goeltzenleuchter1f157ac2015-06-14 19:57:15 -0600954 for (struct loader_device *dev = icd->logical_device_list; dev; ) {
955 struct loader_device *next_dev = dev->next;
Jon Ashburne39a4f82015-08-28 13:38:21 -0600956 loader_destroy_logical_device(ptr_inst, dev);
Courtney Goeltzenleuchter1f157ac2015-06-14 19:57:15 -0600957 dev = next_dev;
958 }
Jon Ashburndc6fcad2015-06-10 10:06:06 -0600959
Jon Ashburne39a4f82015-08-28 13:38:21 -0600960 loader_heap_free(ptr_inst, icd);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800961}
962
Jon Ashburne39a4f82015-08-28 13:38:21 -0600963static struct loader_icd * loader_icd_create(const struct loader_instance *inst)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800964{
965 struct loader_icd *icd;
966
Jon Ashburne39a4f82015-08-28 13:38:21 -0600967 icd = loader_heap_alloc(inst, sizeof(*icd), VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800968 if (!icd)
969 return NULL;
970
Courtney Goeltzenleuchter55001bb2014-10-28 10:29:27 -0600971 memset(icd, 0, sizeof(*icd));
972
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800973 return icd;
974}
975
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600976static struct loader_icd *loader_icd_add(
977 struct loader_instance *ptr_inst,
Jon Ashburn3d002332015-08-20 16:35:30 -0600978 const struct loader_scanned_icds *icd_lib)
Chia-I Wu13a61a52014-08-04 11:18:20 +0800979{
980 struct loader_icd *icd;
981
Jon Ashburne39a4f82015-08-28 13:38:21 -0600982 icd = loader_icd_create(ptr_inst);
Chia-I Wu13a61a52014-08-04 11:18:20 +0800983 if (!icd)
984 return NULL;
985
Jon Ashburn3d002332015-08-20 16:35:30 -0600986 icd->this_icd_lib = icd_lib;
987 icd->this_instance = ptr_inst;
988
Chia-I Wu13a61a52014-08-04 11:18:20 +0800989 /* prepend to the list */
Jon Ashburn46888392015-01-29 15:45:51 -0700990 icd->next = ptr_inst->icds;
991 ptr_inst->icds = icd;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600992 ptr_inst->total_icd_count++;
Chia-I Wu13a61a52014-08-04 11:18:20 +0800993
994 return icd;
995}
996
Jon Ashburne39a4f82015-08-28 13:38:21 -0600997void loader_scanned_icd_clear(
998 const struct loader_instance *inst,
999 struct loader_icd_libs *icd_libs)
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001000{
1001 if (icd_libs->capacity == 0)
1002 return;
1003 for (uint32_t i = 0; i < icd_libs->count; i++) {
1004 loader_platform_close_library(icd_libs->list[i].handle);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001005 loader_heap_free(inst, icd_libs->list[i].lib_name);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001006 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06001007 loader_heap_free(inst, icd_libs->list);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001008 icd_libs->capacity = 0;
1009 icd_libs->count = 0;
1010 icd_libs->list = NULL;
1011}
1012
Jon Ashburne39a4f82015-08-28 13:38:21 -06001013static void loader_scanned_icd_init(const struct loader_instance *inst,
1014 struct loader_icd_libs *icd_libs)
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001015{
Jon Ashburne39a4f82015-08-28 13:38:21 -06001016 loader_scanned_icd_clear(inst, icd_libs);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001017 icd_libs->capacity = 8 * sizeof(struct loader_scanned_icds);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001018 icd_libs->list = loader_heap_alloc(inst, icd_libs->capacity, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001019
1020}
1021
1022static void loader_scanned_icd_add(
Jon Ashburne39a4f82015-08-28 13:38:21 -06001023 const struct loader_instance *inst,
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001024 struct loader_icd_libs *icd_libs,
1025 const char *filename)
Jon Ashburn46d1f582015-01-28 11:01:35 -07001026{
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001027 loader_platform_dl_handle handle;
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06001028 PFN_vkCreateInstance fp_create_inst;
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06001029 PFN_vkEnumerateInstanceExtensionProperties fp_get_global_ext_props;
Jon Ashburnc624c882015-07-16 10:17:29 -06001030 PFN_vkGetInstanceProcAddr fp_get_proc_addr;
Jon Ashburn46d1f582015-01-28 11:01:35 -07001031 struct loader_scanned_icds *new_node;
1032
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001033 /* TODO implement ref counting of libraries, for now this function leaves
1034 libraries open and the scanned_icd_clear closes them */
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001035 // Used to call: dlopen(filename, RTLD_LAZY);
1036 handle = loader_platform_open_library(filename);
Jon Ashburn46d1f582015-01-28 11:01:35 -07001037 if (!handle) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001038 loader_log(VK_DBG_REPORT_WARN_BIT, 0, loader_platform_open_library_error(filename));
Jon Ashburn46d1f582015-01-28 11:01:35 -07001039 return;
1040 }
1041
Jon Ashburnc624c882015-07-16 10:17:29 -06001042#define LOOKUP_LD(func_ptr, func) do { \
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -06001043 func_ptr = (PFN_vk ##func) loader_platform_get_proc_address(handle, "vk" #func); \
Jon Ashburn46d1f582015-01-28 11:01:35 -07001044 if (!func_ptr) { \
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001045 loader_log(VK_DBG_REPORT_WARN_BIT, 0, loader_platform_get_proc_address_error("vk" #func)); \
Jon Ashburn46d1f582015-01-28 11:01:35 -07001046 return; \
1047 } \
1048} while (0)
1049
Jon Ashburnc624c882015-07-16 10:17:29 -06001050 LOOKUP_LD(fp_get_proc_addr, GetInstanceProcAddr);
1051 LOOKUP_LD(fp_create_inst, CreateInstance);
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06001052 LOOKUP_LD(fp_get_global_ext_props, EnumerateInstanceExtensionProperties);
Jon Ashburnc624c882015-07-16 10:17:29 -06001053
1054#undef LOOKUP_LD
Jon Ashburn46d1f582015-01-28 11:01:35 -07001055
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001056 // check for enough capacity
1057 if ((icd_libs->count * sizeof(struct loader_scanned_icds)) >= icd_libs->capacity) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06001058
1059 icd_libs->list = loader_heap_realloc(inst,
1060 icd_libs->list,
1061 icd_libs->capacity,
1062 icd_libs->capacity * 2,
1063 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001064 // double capacity
1065 icd_libs->capacity *= 2;
Jon Ashburn46d1f582015-01-28 11:01:35 -07001066 }
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001067 new_node = &(icd_libs->list[icd_libs->count]);
Jon Ashburn46d1f582015-01-28 11:01:35 -07001068
1069 new_node->handle = handle;
Jon Ashburnc624c882015-07-16 10:17:29 -06001070 new_node->GetInstanceProcAddr = fp_get_proc_addr;
Jon Ashburn46888392015-01-29 15:45:51 -07001071 new_node->CreateInstance = fp_create_inst;
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06001072 new_node->EnumerateInstanceExtensionProperties = fp_get_global_ext_props;
Jon Ashburn46d1f582015-01-28 11:01:35 -07001073
Jon Ashburne39a4f82015-08-28 13:38:21 -06001074 new_node->lib_name = (char *) loader_heap_alloc(inst,
1075 strlen(filename) + 1,
1076 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001077 if (!new_node->lib_name) {
1078 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Out of memory can't add icd");
1079 return;
1080 }
1081 strcpy(new_node->lib_name, filename);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001082 icd_libs->count++;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001083}
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001084
Jon Ashburnc624c882015-07-16 10:17:29 -06001085static bool loader_icd_init_entrys(struct loader_icd *icd,
1086 VkInstance inst,
1087 const PFN_vkGetInstanceProcAddr fp_gipa)
Jon Ashburn3da71f22015-05-14 12:43:38 -06001088{
1089 /* initialize entrypoint function pointers */
1090
Jon Ashburnc624c882015-07-16 10:17:29 -06001091 #define LOOKUP_GIPA(func, required) do { \
1092 icd->func = (PFN_vk ##func) fp_gipa(inst, "vk" #func); \
1093 if (!icd->func && required) { \
1094 loader_log(VK_DBG_REPORT_WARN_BIT, 0, \
1095 loader_platform_get_proc_address_error("vk" #func)); \
1096 return false; \
1097 } \
Jon Ashburn3da71f22015-05-14 12:43:38 -06001098 } while (0)
1099
Jon Ashburnc624c882015-07-16 10:17:29 -06001100 LOOKUP_GIPA(GetDeviceProcAddr, true);
1101 LOOKUP_GIPA(DestroyInstance, true);
1102 LOOKUP_GIPA(EnumeratePhysicalDevices, true);
1103 LOOKUP_GIPA(GetPhysicalDeviceFeatures, true);
1104 LOOKUP_GIPA(GetPhysicalDeviceFormatProperties, true);
Jon Ashburn754864f2015-07-23 18:49:07 -06001105 LOOKUP_GIPA(GetPhysicalDeviceImageFormatProperties, true);
Jon Ashburnc624c882015-07-16 10:17:29 -06001106 LOOKUP_GIPA(CreateDevice, true);
1107 LOOKUP_GIPA(GetPhysicalDeviceProperties, true);
1108 LOOKUP_GIPA(GetPhysicalDeviceMemoryProperties, true);
Cody Northropd0802882015-08-03 17:04:53 -06001109 LOOKUP_GIPA(GetPhysicalDeviceQueueFamilyProperties, true);
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06001110 LOOKUP_GIPA(EnumerateDeviceExtensionProperties, true);
Jon Ashburnc624c882015-07-16 10:17:29 -06001111 LOOKUP_GIPA(GetPhysicalDeviceSparseImageFormatProperties, true);
1112 LOOKUP_GIPA(DbgCreateMsgCallback, false);
1113 LOOKUP_GIPA(DbgDestroyMsgCallback, false);
Ian Elliott7e40db92015-08-21 15:09:33 -06001114 LOOKUP_GIPA(GetPhysicalDeviceSurfaceSupportKHR, false);
Jon Ashburn3da71f22015-05-14 12:43:38 -06001115
Jon Ashburnc624c882015-07-16 10:17:29 -06001116#undef LOOKUP_GIPA
Ian Elliottd3ef02f2015-07-06 14:36:13 -06001117
Jon Ashburnc624c882015-07-16 10:17:29 -06001118 return true;
Jon Ashburn3da71f22015-05-14 12:43:38 -06001119}
1120
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001121static void loader_debug_init(void)
1122{
1123 const char *env;
1124
1125 if (g_loader_debug > 0)
1126 return;
1127
1128 g_loader_debug = 0;
1129
1130 /* parse comma-separated debug options */
Courtney Goeltzenleuchterfce60db2015-07-29 09:08:22 -06001131 env = getenv("VK_LOADER_DEBUG");
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001132 while (env) {
1133 const char *p = strchr(env, ',');
1134 size_t len;
1135
1136 if (p)
1137 len = p - env;
1138 else
1139 len = strlen(env);
1140
1141 if (len > 0) {
1142 if (strncmp(env, "warn", len) == 0) {
1143 g_loader_debug |= LOADER_WARN_BIT;
1144 g_loader_log_msgs |= VK_DBG_REPORT_WARN_BIT;
1145 } else if (strncmp(env, "info", len) == 0) {
1146 g_loader_debug |= LOADER_INFO_BIT;
1147 g_loader_log_msgs |= VK_DBG_REPORT_INFO_BIT;
1148 } else if (strncmp(env, "perf", len) == 0) {
1149 g_loader_debug |= LOADER_PERF_BIT;
1150 g_loader_log_msgs |= VK_DBG_REPORT_PERF_WARN_BIT;
1151 } else if (strncmp(env, "error", len) == 0) {
1152 g_loader_debug |= LOADER_ERROR_BIT;
1153 g_loader_log_msgs |= VK_DBG_REPORT_ERROR_BIT;
1154 } else if (strncmp(env, "debug", len) == 0) {
1155 g_loader_debug |= LOADER_DEBUG_BIT;
1156 g_loader_log_msgs |= VK_DBG_REPORT_DEBUG_BIT;
1157 }
1158 }
1159
1160 if (!p)
1161 break;
1162
1163 env = p + 1;
1164 }
1165}
1166
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001167void loader_initialize(void)
1168{
Jon Ashburn6461ef22015-09-22 13:11:00 -06001169 // initialize mutexs
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001170 loader_platform_thread_create_mutex(&loader_lock);
Jon Ashburn6461ef22015-09-22 13:11:00 -06001171 loader_platform_thread_create_mutex(&loader_json_lock);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001172
1173 // initialize logging
1174 loader_debug_init();
Jon Ashburn87d6aa92015-08-28 15:19:27 -06001175
1176 // initial cJSON to use alloc callbacks
1177 cJSON_Hooks alloc_fns = {
1178 .malloc_fn = loader_tls_heap_alloc,
1179 .free_fn = loader_tls_heap_free,
1180 };
1181 cJSON_InitHooks(&alloc_fns);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001182}
1183
Jon Ashburn2077e382015-06-29 11:25:34 -06001184struct loader_manifest_files {
1185 uint32_t count;
1186 char **filename_list;
1187};
1188
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06001189/**
Jon Ashburn2077e382015-06-29 11:25:34 -06001190 * Get next file or dirname given a string list or registry key path
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06001191 *
1192 * \returns
Jon Ashburn2077e382015-06-29 11:25:34 -06001193 * A pointer to first char in the next path.
1194 * The next path (or NULL) in the list is returned in next_path.
1195 * Note: input string is modified in some cases. PASS IN A COPY!
1196 */
Jon Ashburn2077e382015-06-29 11:25:34 -06001197static char *loader_get_next_path(char *path)
1198{
1199 uint32_t len;
1200 char *next;
1201
1202 if (path == NULL)
1203 return NULL;
1204 next = strchr(path, PATH_SEPERATOR);
1205 if (next == NULL) {
1206 len = (uint32_t) strlen(path);
1207 next = path + len;
1208 }
1209 else {
1210 *next = '\0';
1211 next++;
1212 }
1213
1214 return next;
1215}
1216
1217/**
Jon Ashburn15315172015-07-07 15:06:25 -06001218 * Given a path which is absolute or relative. Expand the path if relative otherwise
1219 * leave the path unmodified if absolute. The path which is relative from is
1220 * given in rel_base and should include trailing directory seperator '/'
1221 *
1222 * \returns
1223 * A string in out_fullpath of the full absolute path
1224 * Side effect is that dir string maybe modified.
1225 */
1226static void loader_expand_path(const char *path,
1227 const char *rel_base,
1228 size_t out_size,
1229 char *out_fullpath)
1230{
1231 if (loader_platform_is_path_absolute(path)) {
1232 strncpy(out_fullpath, path, out_size);
1233 out_fullpath[out_size - 1] = '\0';
1234 }
1235 else {
1236 // convert relative to absolute path based on rel_base
1237 size_t len = strlen(path);
1238 strncpy(out_fullpath, rel_base, out_size);
1239 out_fullpath[out_size - 1] = '\0';
1240 assert(out_size >= strlen(out_fullpath) + len + 1);
1241 strncat(out_fullpath, path, len);
1242 }
1243}
1244
1245/**
Jon Ashburn2077e382015-06-29 11:25:34 -06001246 * Given a filename (file) and a list of paths (dir), try to find an existing
1247 * file in the paths. If filename already is a path then no
1248 * searching in the given paths.
1249 *
1250 * \returns
1251 * A string in out_fullpath of either the full path or file.
1252 * Side effect is that dir string maybe modified.
1253 */
1254static void loader_get_fullpath(const char *file,
1255 char *dir,
1256 size_t out_size,
1257 char *out_fullpath)
1258{
1259 char *next_dir;
1260 if (strchr(file,DIRECTORY_SYMBOL) == NULL) {
1261 //find file exists with prepending given path
1262 while (*dir) {
1263 next_dir = loader_get_next_path(dir);
1264 snprintf(out_fullpath, out_size, "%s%c%s",
1265 dir, DIRECTORY_SYMBOL, file);
1266 if (loader_platform_file_exists(out_fullpath)) {
1267 return;
1268 }
1269 dir = next_dir;
1270 }
1271 }
1272 snprintf(out_fullpath, out_size, "%s", file);
1273}
1274
1275/**
1276 * Read a JSON file into a buffer.
1277 *
1278 * \returns
1279 * A pointer to a cJSON object representing the JSON parse tree.
1280 * This returned buffer should be freed by caller.
1281 */
1282static cJSON *loader_get_json(const char *filename)
1283{
1284 FILE *file;
1285 char *json_buf;
1286 cJSON *json;
1287 uint64_t len;
1288 file = fopen(filename,"rb");
Jon Ashburnaa4ea472015-08-27 08:30:50 -06001289 if (!file) {
1290 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Couldn't open JSON file %s", filename);
1291 return NULL;
1292 }
Jon Ashburn2077e382015-06-29 11:25:34 -06001293 fseek(file, 0, SEEK_END);
1294 len = ftell(file);
1295 fseek(file, 0, SEEK_SET);
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -06001296 json_buf = (char*) loader_stack_alloc(len+1);
Jon Ashburn2077e382015-06-29 11:25:34 -06001297 if (json_buf == NULL) {
1298 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get JSON file");
1299 fclose(file);
1300 return NULL;
1301 }
1302 if (fread(json_buf, sizeof(char), len, file) != len) {
1303 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "fread failed can't get JSON file");
1304 fclose(file);
1305 return NULL;
1306 }
1307 fclose(file);
1308 json_buf[len] = '\0';
1309
1310 //parse text from file
1311 json = cJSON_Parse(json_buf);
1312 if (json == NULL)
1313 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Can't parse JSON file %s", filename);
1314 return json;
1315}
1316
1317/**
Jon Ashburn3d002332015-08-20 16:35:30 -06001318 * Do a deep copy of the loader_layer_properties structure.
1319 */
1320static void loader_copy_layer_properties(
Jon Ashburne39a4f82015-08-28 13:38:21 -06001321 const struct loader_instance *inst,
Jon Ashburn3d002332015-08-20 16:35:30 -06001322 struct loader_layer_properties *dst,
1323 struct loader_layer_properties *src)
1324{
1325 memcpy(dst, src, sizeof (*src));
Jon Ashburne39a4f82015-08-28 13:38:21 -06001326 dst->instance_extension_list.list = loader_heap_alloc(
1327 inst,
1328 sizeof(VkExtensionProperties) *
1329 src->instance_extension_list.count,
1330 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
1331 dst->instance_extension_list.capacity = sizeof(VkExtensionProperties) *
1332 src->instance_extension_list.count;
1333 memcpy(dst->instance_extension_list.list, src->instance_extension_list.list,
1334 dst->instance_extension_list.capacity);
1335 dst->device_extension_list.list = loader_heap_alloc(
1336 inst,
1337 sizeof(VkExtensionProperties) *
1338 src->device_extension_list.count,
1339 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
1340 dst->device_extension_list.capacity = sizeof(VkExtensionProperties) *
1341 src->device_extension_list.count;
1342 memcpy(dst->device_extension_list.list, src->device_extension_list.list,
1343 dst->device_extension_list.capacity);
Jon Ashburn3d002332015-08-20 16:35:30 -06001344}
1345
1346/**
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001347 * Given a cJSON struct (json) of the top level JSON object from layer manifest
1348 * file, add entry to the layer_list.
Jon Ashburne13ecc92015-08-03 17:19:30 -06001349 * Fill out the layer_properties in this list entry from the input cJSON object.
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001350 *
1351 * \returns
1352 * void
1353 * layer_list has a new entry and initialized accordingly.
1354 * If the json input object does not have all the required fields no entry
1355 * is added to the list.
1356 */
Jon Ashburne39a4f82015-08-28 13:38:21 -06001357static void loader_add_layer_properties(const struct loader_instance *inst,
1358 struct loader_layer_list *layer_instance_list,
Jon Ashburnb2ef1372015-07-16 17:19:31 -06001359 struct loader_layer_list *layer_device_list,
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001360 cJSON *json,
1361 bool is_implicit,
1362 char *filename)
1363{
1364 /* Fields in layer manifest file that are required:
1365 * (required) “file_format_version”
1366 * following are required in the "layer" object:
1367 * (required) "name"
1368 * (required) "type"
1369 * (required) “library_path”
1370 * (required) “abi_versions”
1371 * (required) “implementation_version”
1372 * (required) “description”
1373 * (required for implicit layers) “disable_environment”
1374 *
1375 * First get all required items and if any missing abort
1376 */
1377
1378 cJSON *item, *layer_node, *ext_item;
1379 char *temp;
1380 char *name, *type, *library_path, *abi_versions;
1381 char *implementation_version, *description;
1382 cJSON *disable_environment;
1383 int i;
Jon Ashburn5c042ea2015-08-04 11:14:18 -06001384 VkExtensionProperties ext_prop;
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001385 item = cJSON_GetObjectItem(json, "file_format_version");
1386 if (item == NULL) {
1387 return;
1388 }
1389 char *file_vers = cJSON_PrintUnformatted(item);
1390 loader_log(VK_DBG_REPORT_INFO_BIT, 0, "Found manifest file %s, version %s",
1391 filename, file_vers);
1392 if (strcmp(file_vers, "\"0.9.0\"") != 0)
Jon Ashburne13ecc92015-08-03 17:19:30 -06001393 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 -06001394 loader_tls_heap_free(file_vers);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001395
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001396 layer_node = cJSON_GetObjectItem(json, "layer");
1397 if (layer_node == NULL) {
1398 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"layer\" object in manifest JSON file, skipping");
1399 return;
1400 }
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001401
1402 // loop through all "layer" objects in the file
1403 do {
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001404#define GET_JSON_OBJECT(node, var) { \
1405 var = cJSON_GetObjectItem(node, #var); \
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001406 if (var == NULL) { \
1407 layer_node = layer_node->next; \
1408 continue; \
1409 } \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001410 }
1411#define GET_JSON_ITEM(node, var) { \
1412 item = cJSON_GetObjectItem(node, #var); \
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001413 if (item == NULL) { \
1414 layer_node = layer_node->next; \
1415 continue; \
1416 } \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001417 temp = cJSON_Print(item); \
1418 temp[strlen(temp) - 1] = '\0'; \
Jon Ashburnf73e9212015-08-04 10:22:33 -06001419 var = loader_stack_alloc(strlen(temp) + 1); \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001420 strcpy(var, &temp[1]); \
Jon Ashburn87d6aa92015-08-28 15:19:27 -06001421 loader_tls_heap_free(temp); \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001422 }
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001423 GET_JSON_ITEM(layer_node, name)
1424 GET_JSON_ITEM(layer_node, type)
1425 GET_JSON_ITEM(layer_node, library_path)
1426 GET_JSON_ITEM(layer_node, abi_versions)
1427 GET_JSON_ITEM(layer_node, implementation_version)
1428 GET_JSON_ITEM(layer_node, description)
1429 if (is_implicit) {
1430 GET_JSON_OBJECT(layer_node, disable_environment)
1431 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001432#undef GET_JSON_ITEM
1433#undef GET_JSON_OBJECT
1434
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001435 // add list entry
Jon Ashburn432d2762015-09-18 12:53:16 -06001436 struct loader_layer_properties *props=NULL;
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001437 if (!strcmp(type, "DEVICE")) {
1438 if (layer_device_list == NULL) {
1439 layer_node = layer_node->next;
1440 continue;
1441 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06001442 props = loader_get_next_layer_property(inst, layer_device_list);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001443 props->type = (is_implicit) ? VK_LAYER_TYPE_DEVICE_IMPLICIT : VK_LAYER_TYPE_DEVICE_EXPLICIT;
1444 }
1445 if (!strcmp(type, "INSTANCE")) {
1446 if (layer_instance_list == NULL) {
1447 layer_node = layer_node->next;
1448 continue;
1449 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06001450 props = loader_get_next_layer_property(inst, layer_instance_list);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001451 props->type = (is_implicit) ? VK_LAYER_TYPE_INSTANCE_IMPLICIT : VK_LAYER_TYPE_INSTANCE_EXPLICIT;
1452 }
1453 if (!strcmp(type, "GLOBAL")) {
1454 if (layer_instance_list != NULL)
Jon Ashburne39a4f82015-08-28 13:38:21 -06001455 props = loader_get_next_layer_property(inst, layer_instance_list);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001456 else if (layer_device_list != NULL)
Jon Ashburne39a4f82015-08-28 13:38:21 -06001457 props = loader_get_next_layer_property(inst, layer_device_list);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001458 else {
1459 layer_node = layer_node->next;
1460 continue;
1461 }
1462 props->type = (is_implicit) ? VK_LAYER_TYPE_GLOBAL_IMPLICIT : VK_LAYER_TYPE_GLOBAL_EXPLICIT;
1463 }
Jon Ashburnb2ef1372015-07-16 17:19:31 -06001464
Jon Ashburn432d2762015-09-18 12:53:16 -06001465 if (props == NULL) {
1466 layer_node = layer_node->next;
1467 continue;
1468 }
1469
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001470 strncpy(props->info.layerName, name, sizeof (props->info.layerName));
1471 props->info.layerName[sizeof (props->info.layerName) - 1] = '\0';
Jon Ashburn15315172015-07-07 15:06:25 -06001472
Jon Ashburn3d002332015-08-20 16:35:30 -06001473 char *fullpath = props->lib_name;
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001474 char *rel_base;
1475 if (strchr(library_path, DIRECTORY_SYMBOL) == NULL) {
1476 // a filename which is assumed in the system directory
1477 char *def_path = loader_stack_alloc(strlen(DEFAULT_VK_LAYERS_PATH) + 1);
1478 strcpy(def_path, DEFAULT_VK_LAYERS_PATH);
1479 loader_get_fullpath(library_path, def_path, MAX_STRING_SIZE, fullpath);
1480 } else {
1481 // a relative or absolute path
1482 char *name_copy = loader_stack_alloc(strlen(filename) + 2);
1483 size_t len;
1484 strcpy(name_copy, filename);
1485 rel_base = loader_platform_dirname(name_copy);
1486 len = strlen(rel_base);
1487 rel_base[len] = DIRECTORY_SYMBOL;
1488 rel_base[len + 1] = '\0';
1489 loader_expand_path(library_path, rel_base, MAX_STRING_SIZE, fullpath);
1490 }
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001491 props->info.specVersion = loader_make_version(abi_versions);
1492 props->info.implVersion = loader_make_version(implementation_version);
1493 strncpy((char *) props->info.description, description, sizeof (props->info.description));
1494 props->info.description[sizeof (props->info.description) - 1] = '\0';
1495 if (is_implicit) {
1496 strncpy(props->disable_env_var.name, disable_environment->child->string, sizeof (props->disable_env_var.name));
1497 props->disable_env_var.name[sizeof (props->disable_env_var.name) - 1] = '\0';
1498 strncpy(props->disable_env_var.value, disable_environment->child->valuestring, sizeof (props->disable_env_var.value));
1499 props->disable_env_var.value[sizeof (props->disable_env_var.value) - 1] = '\0';
1500 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001501
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001502 /**
1503 * Now get all optional items and objects and put in list:
1504 * functions
1505 * instance_extensions
1506 * device_extensions
1507 * enable_environment (implicit layers only)
1508 */
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001509#define GET_JSON_OBJECT(node, var) { \
1510 var = cJSON_GetObjectItem(node, #var); \
1511 }
1512#define GET_JSON_ITEM(node, var) { \
1513 item = cJSON_GetObjectItem(node, #var); \
Jon Ashburn21c21ee2015-09-09 11:29:24 -06001514 if (item != NULL) { \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001515 temp = cJSON_Print(item); \
Jon Ashburn21c21ee2015-09-09 11:29:24 -06001516 temp[strlen(temp) - 1] = '\0'; \
1517 var = loader_stack_alloc(strlen(temp) + 1);\
1518 strcpy(var, &temp[1]); \
1519 loader_tls_heap_free(temp); \
1520 } \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001521 }
1522
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001523 cJSON *instance_extensions, *device_extensions, *functions, *enable_environment;
Jon Ashburn432d2762015-09-18 12:53:16 -06001524 char *vkGetInstanceProcAddr = NULL, *vkGetDeviceProcAddr = NULL, *version=NULL;
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001525 GET_JSON_OBJECT(layer_node, functions)
1526 if (functions != NULL) {
1527 GET_JSON_ITEM(functions, vkGetInstanceProcAddr)
1528 GET_JSON_ITEM(functions, vkGetDeviceProcAddr)
Jon Ashburn21c21ee2015-09-09 11:29:24 -06001529 if (vkGetInstanceProcAddr != NULL)
1530 strncpy(props->functions.str_gipa, vkGetInstanceProcAddr, sizeof (props->functions.str_gipa));
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001531 props->functions.str_gipa[sizeof (props->functions.str_gipa) - 1] = '\0';
Jon Ashburn21c21ee2015-09-09 11:29:24 -06001532 if (vkGetDeviceProcAddr != NULL)
1533 strncpy(props->functions.str_gdpa, vkGetDeviceProcAddr, sizeof (props->functions.str_gdpa));
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001534 props->functions.str_gdpa[sizeof (props->functions.str_gdpa) - 1] = '\0';
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001535 }
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001536 GET_JSON_OBJECT(layer_node, instance_extensions)
1537 if (instance_extensions != NULL) {
1538 int count = cJSON_GetArraySize(instance_extensions);
1539 for (i = 0; i < count; i++) {
1540 ext_item = cJSON_GetArrayItem(instance_extensions, i);
1541 GET_JSON_ITEM(ext_item, name)
1542 GET_JSON_ITEM(ext_item, version)
1543 strncpy(ext_prop.extName, name, sizeof (ext_prop.extName));
1544 ext_prop.extName[sizeof (ext_prop.extName) - 1] = '\0';
1545 ext_prop.specVersion = loader_make_version(version);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001546 loader_add_to_ext_list(inst, &props->instance_extension_list, 1, &ext_prop);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001547 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001548 }
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001549 GET_JSON_OBJECT(layer_node, device_extensions)
1550 if (device_extensions != NULL) {
1551 int count = cJSON_GetArraySize(device_extensions);
1552 for (i = 0; i < count; i++) {
1553 ext_item = cJSON_GetArrayItem(device_extensions, i);
1554 GET_JSON_ITEM(ext_item, name);
1555 GET_JSON_ITEM(ext_item, version);
1556 strncpy(ext_prop.extName, name, sizeof (ext_prop.extName));
1557 ext_prop.extName[sizeof (ext_prop.extName) - 1] = '\0';
1558 ext_prop.specVersion = loader_make_version(version);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001559 loader_add_to_ext_list(inst, &props->device_extension_list, 1, &ext_prop);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001560 }
1561 }
1562 if (is_implicit) {
1563 GET_JSON_OBJECT(layer_node, enable_environment)
1564 strncpy(props->enable_env_var.name, enable_environment->child->string, sizeof (props->enable_env_var.name));
1565 props->enable_env_var.name[sizeof (props->enable_env_var.name) - 1] = '\0';
1566 strncpy(props->enable_env_var.value, enable_environment->child->valuestring, sizeof (props->enable_env_var.value));
1567 props->enable_env_var.value[sizeof (props->enable_env_var.value) - 1] = '\0';
1568 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001569#undef GET_JSON_ITEM
1570#undef GET_JSON_OBJECT
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001571 // for global layers need to add them to both device and instance list
1572 if (!strcmp(type, "GLOBAL")) {
1573 struct loader_layer_properties *dev_props;
1574 if (layer_instance_list == NULL || layer_device_list == NULL) {
1575 layer_node = layer_node->next;
1576 continue;
1577 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06001578 dev_props = loader_get_next_layer_property(inst, layer_device_list);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001579 //copy into device layer list
Jon Ashburne39a4f82015-08-28 13:38:21 -06001580 loader_copy_layer_properties(inst, dev_props, props);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001581 }
1582 layer_node = layer_node->next;
1583 } while (layer_node != NULL);
1584 return;
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001585}
1586
1587/**
Jon Ashburn2077e382015-06-29 11:25:34 -06001588 * Find the Vulkan library manifest files.
1589 *
1590 * This function scans the location or env_override directories/files
1591 * for a list of JSON manifest files. If env_override is non-NULL
1592 * and has a valid value. Then the location is ignored. Otherwise
1593 * location is used to look for manifest files. The location
1594 * is interpreted as Registry path on Windows and a directory path(s)
1595 * on Linux.
1596 *
1597 * \returns
1598 * A string list of manifest files to be opened in out_files param.
1599 * List has a pointer to string for each manifest filename.
1600 * When done using the list in out_files, pointers should be freed.
Jon Ashburnffad94d2015-06-30 14:46:22 -07001601 * Location or override string lists can be either files or directories as follows:
1602 * | location | override
1603 * --------------------------------
1604 * Win ICD | files | files
1605 * Win Layer | files | dirs
1606 * Linux ICD | dirs | files
1607 * Linux Layer| dirs | dirs
Jon Ashburn2077e382015-06-29 11:25:34 -06001608 */
Jon Ashburne39a4f82015-08-28 13:38:21 -06001609static void loader_get_manifest_files(const struct loader_instance *inst,
1610 const char *env_override,
Jon Ashburnffad94d2015-06-30 14:46:22 -07001611 bool is_layer,
1612 const char *location,
1613 struct loader_manifest_files *out_files)
Jon Ashburn2077e382015-06-29 11:25:34 -06001614{
1615 char *override = NULL;
1616 char *loc;
1617 char *file, *next_file, *name;
1618 size_t alloced_count = 64;
1619 char full_path[2048];
1620 DIR *sysdir = NULL;
Jon Ashburnffad94d2015-06-30 14:46:22 -07001621 bool list_is_dirs = false;
Jon Ashburn2077e382015-06-29 11:25:34 -06001622 struct dirent *dent;
1623
1624 out_files->count = 0;
1625 out_files->filename_list = NULL;
1626
Jon Ashburn2077e382015-06-29 11:25:34 -06001627 if (env_override != NULL && (override = getenv(env_override))) {
1628#if defined(__linux__)
1629 if (geteuid() != getuid()) {
Jon Ashburnffad94d2015-06-30 14:46:22 -07001630 /* Don't allow setuid apps to use the env var: */
Jon Ashburn2077e382015-06-29 11:25:34 -06001631 override = NULL;
1632 }
1633#endif
1634 }
1635
1636 if (location == NULL) {
1637 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
Jon Ashburnffad94d2015-06-30 14:46:22 -07001638 "Can't get manifest files with NULL location, env_override=%s",
1639 env_override);
Jon Ashburn2077e382015-06-29 11:25:34 -06001640 return;
1641 }
1642
Jon Ashburnffad94d2015-06-30 14:46:22 -07001643#if defined(__linux__)
1644 list_is_dirs = (override == NULL || is_layer) ? true : false;
1645#else //WIN32
1646 list_is_dirs = (is_layer && override != NULL) ? true : false;
1647#endif
Jon Ashburn2077e382015-06-29 11:25:34 -06001648 // Make a copy of the input we are using so it is not modified
Jon Ashburnffad94d2015-06-30 14:46:22 -07001649 // Also handle getting the location(s) from registry on Windows
1650 if (override == NULL) {
Jon Ashburn3b78e462015-07-31 10:11:24 -06001651 loc = loader_stack_alloc(strlen(location) + 1);
Jon Ashburnffad94d2015-06-30 14:46:22 -07001652 if (loc == NULL) {
1653 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files");
1654 return;
1655 }
1656 strcpy(loc, location);
Jon Ashburn24265ac2015-07-31 09:33:21 -06001657#if defined (_WIN32)
Jon Ashburn480a50a2015-08-28 14:58:46 -07001658 loc = loader_get_registry_files(inst, loc);
Jon Ashburn24265ac2015-07-31 09:33:21 -06001659 if (loc == NULL) {
1660 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Registry lookup failed can't get manifest files");
1661 return;
1662 }
Jon Ashburnffad94d2015-06-30 14:46:22 -07001663#endif
Jon Ashburn2077e382015-06-29 11:25:34 -06001664 }
Jon Ashburnffad94d2015-06-30 14:46:22 -07001665 else {
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -06001666 loc = loader_stack_alloc(strlen(override) + 1);
Jon Ashburnffad94d2015-06-30 14:46:22 -07001667 if (loc == NULL) {
1668 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files");
1669 return;
1670 }
1671 strcpy(loc, override);
1672 }
Jon Ashburn2077e382015-06-29 11:25:34 -06001673
Liam Middlebrook9b14e892015-07-23 18:32:20 -07001674 // Print out the paths being searched if debugging is enabled
Jon Ashburn46e20d82015-07-31 09:41:31 -06001675 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 -07001676
Jon Ashburn2077e382015-06-29 11:25:34 -06001677 file = loc;
1678 while (*file) {
1679 next_file = loader_get_next_path(file);
Jon Ashburnffad94d2015-06-30 14:46:22 -07001680 if (list_is_dirs) {
Jon Ashburn2077e382015-06-29 11:25:34 -06001681 sysdir = opendir(file);
1682 name = NULL;
1683 if (sysdir) {
1684 dent = readdir(sysdir);
1685 if (dent == NULL)
1686 break;
1687 name = &(dent->d_name[0]);
1688 loader_get_fullpath(name, file, sizeof(full_path), full_path);
1689 name = full_path;
1690 }
1691 }
1692 else {
Jon Ashburnffad94d2015-06-30 14:46:22 -07001693#if defined(__linux__)
1694 // only Linux has relative paths
Jon Ashburn2077e382015-06-29 11:25:34 -06001695 char *dir;
1696 // make a copy of location so it isn't modified
Jason Ekstrandcc7550e2015-10-10 08:33:37 -07001697 dir = loader_stack_alloc(strlen(loc) + 1);
Jon Ashburn2077e382015-06-29 11:25:34 -06001698 if (dir == NULL) {
1699 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files");
1700 return;
1701 }
Jason Ekstrandcc7550e2015-10-10 08:33:37 -07001702 strcpy(dir, loc);
Jon Ashburn2077e382015-06-29 11:25:34 -06001703
1704 loader_get_fullpath(file, dir, sizeof(full_path), full_path);
1705
1706 name = full_path;
Jon Ashburnffad94d2015-06-30 14:46:22 -07001707#else // WIN32
1708 name = file;
1709#endif
Jon Ashburn2077e382015-06-29 11:25:34 -06001710 }
1711 while (name) {
1712 /* Look for files ending with ".json" suffix */
1713 uint32_t nlen = (uint32_t) strlen(name);
1714 const char *suf = name + nlen - 5;
1715 if ((nlen > 5) && !strncmp(suf, ".json", 5)) {
1716 if (out_files->count == 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06001717 out_files->filename_list = loader_heap_alloc(inst,
1718 alloced_count * sizeof(char *),
1719 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburn2077e382015-06-29 11:25:34 -06001720 }
1721 else if (out_files->count == alloced_count) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06001722 out_files->filename_list = loader_heap_realloc(inst,
1723 out_files->filename_list,
1724 alloced_count * sizeof(char *),
1725 alloced_count * sizeof(char *) * 2,
1726 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburn2077e382015-06-29 11:25:34 -06001727 alloced_count *= 2;
1728 }
1729 if (out_files->filename_list == NULL) {
1730 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't alloc manifest file list");
1731 return;
1732 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06001733 out_files->filename_list[out_files->count] = loader_heap_alloc(
1734 inst,
1735 strlen(name) + 1,
1736 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburn2077e382015-06-29 11:25:34 -06001737 if (out_files->filename_list[out_files->count] == NULL) {
1738 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files");
1739 return;
1740 }
1741 strcpy(out_files->filename_list[out_files->count], name);
1742 out_files->count++;
Jon Ashburnf70f3612015-07-02 10:08:47 -06001743 } else if (!list_is_dirs) {
1744 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 -06001745 }
Jon Ashburnffad94d2015-06-30 14:46:22 -07001746 if (list_is_dirs) {
Jon Ashburn2077e382015-06-29 11:25:34 -06001747 dent = readdir(sysdir);
1748 if (dent == NULL)
1749 break;
1750 name = &(dent->d_name[0]);
1751 loader_get_fullpath(name, file, sizeof(full_path), full_path);
1752 name = full_path;
1753 }
1754 else {
1755 break;
1756 }
1757 }
1758 if (sysdir)
1759 closedir(sysdir);
1760 file = next_file;
1761 }
1762 return;
1763}
1764
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001765void loader_init_icd_lib_list()
1766{
1767
1768}
1769
1770void loader_destroy_icd_lib_list()
1771{
1772
1773}
Jon Ashburn2077e382015-06-29 11:25:34 -06001774/**
1775 * Try to find the Vulkan ICD driver(s).
1776 *
1777 * This function scans the default system loader path(s) or path
1778 * specified by the \c VK_ICD_FILENAMES environment variable in
1779 * order to find loadable VK ICDs manifest files. From these
1780 * manifest files it finds the ICD libraries.
1781 *
1782 * \returns
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001783 * a list of icds that were discovered
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06001784 */
Jon Ashburne39a4f82015-08-28 13:38:21 -06001785void loader_icd_scan(
1786 const struct loader_instance *inst,
1787 struct loader_icd_libs *icds)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001788{
Jon Ashburn2077e382015-06-29 11:25:34 -06001789 char *file_str;
1790 struct loader_manifest_files manifest_files;
1791
Jon Ashburne39a4f82015-08-28 13:38:21 -06001792 loader_scanned_icd_init(inst, icds);
Jon Ashburn2077e382015-06-29 11:25:34 -06001793 // Get a list of manifest files for ICDs
Jon Ashburne39a4f82015-08-28 13:38:21 -06001794 loader_get_manifest_files(inst, "VK_ICD_FILENAMES", false,
1795 DEFAULT_VK_DRIVERS_INFO, &manifest_files);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001796 if (manifest_files.count == 0)
1797 return;
Jon Ashburn6461ef22015-09-22 13:11:00 -06001798 loader_platform_thread_lock_mutex(&loader_json_lock);
Jon Ashburn2077e382015-06-29 11:25:34 -06001799 for (uint32_t i = 0; i < manifest_files.count; i++) {
1800 file_str = manifest_files.filename_list[i];
1801 if (file_str == NULL)
1802 continue;
1803
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001804 cJSON *json;
Jon Ashburn2077e382015-06-29 11:25:34 -06001805 json = loader_get_json(file_str);
Jon Ashburnaa4ea472015-08-27 08:30:50 -06001806 if (!json)
1807 continue;
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001808 cJSON *item;
1809 item = cJSON_GetObjectItem(json, "file_format_version");
Jon Ashburn6461ef22015-09-22 13:11:00 -06001810 if (item == NULL) {
1811 loader_platform_thread_unlock_mutex(&loader_json_lock);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001812 return;
Jon Ashburn6461ef22015-09-22 13:11:00 -06001813 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001814 char *file_vers = cJSON_Print(item);
1815 loader_log(VK_DBG_REPORT_INFO_BIT, 0, "Found manifest file %s, version %s",
1816 file_str, file_vers);
1817 if (strcmp(file_vers, "\"1.0.0\"") != 0)
1818 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 -06001819 loader_tls_heap_free(file_vers);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001820 item = cJSON_GetObjectItem(json, "ICD");
1821 if (item != NULL) {
1822 item = cJSON_GetObjectItem(item, "library_path");
1823 if (item != NULL) {
Jon Ashburn86251302015-08-25 16:48:24 -06001824 char *temp= cJSON_Print(item);
1825 if (!temp || strlen(temp) == 0) {
1826 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 -06001827 loader_tls_heap_free(temp);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001828 loader_heap_free(inst, file_str);
Jon Ashburn86251302015-08-25 16:48:24 -06001829 cJSON_Delete(json);
1830 continue;
Jon Ashburn2077e382015-06-29 11:25:34 -06001831 }
Jon Ashburn86251302015-08-25 16:48:24 -06001832 //strip out extra quotes
1833 temp[strlen(temp) - 1] = '\0';
1834 char *library_path = loader_stack_alloc(strlen(temp) + 1);
1835 strcpy(library_path, &temp[1]);
Jon Ashburn87d6aa92015-08-28 15:19:27 -06001836 loader_tls_heap_free(temp);
Jon Ashburn86251302015-08-25 16:48:24 -06001837 if (!library_path || strlen(library_path) == 0) {
1838 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 -06001839 loader_heap_free(inst, file_str);
Jon Ashburn86251302015-08-25 16:48:24 -06001840 cJSON_Delete(json);
1841 continue;
1842 }
1843 char *fullpath;
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -06001844 size_t path_len;
Jon Ashburn86251302015-08-25 16:48:24 -06001845 char *rel_base;
1846 // Print out the paths being searched if debugging is enabled
1847 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, "Searching for ICD drivers named %s default dir %s\n", library_path, DEFAULT_VK_DRIVERS_PATH);
1848 if (strchr(library_path, DIRECTORY_SYMBOL) == NULL) {
1849 // a filename which is assumed in the system directory
1850 char *def_path = loader_stack_alloc(strlen(DEFAULT_VK_DRIVERS_PATH) + 1);
1851 strcpy(def_path, DEFAULT_VK_DRIVERS_PATH);
1852 path_len = strlen(DEFAULT_VK_DRIVERS_PATH) + strlen(library_path) + 2;
1853 fullpath = loader_stack_alloc(path_len);
1854#if defined(__linux__)
1855 loader_get_fullpath(library_path, def_path, path_len, fullpath);
1856#else // WIN32
1857 strncpy(fullpath, library_path, sizeof (fullpath));
1858 fullpath[sizeof (fullpath) - 1] = '\0';
1859#endif
1860 } else {
1861 // a relative or absolute path
1862 char *name_copy = loader_stack_alloc(strlen(file_str) + 2);
1863 size_t len;
1864 strcpy(name_copy, file_str);
1865 rel_base = loader_platform_dirname(name_copy);
1866 len = strlen(rel_base);
1867 rel_base[len] = DIRECTORY_SYMBOL;
1868 rel_base[len + 1] = '\0';
1869 path_len = strlen(rel_base) + strlen(library_path) + 2;
1870 fullpath = loader_stack_alloc(path_len);
1871 loader_expand_path(library_path, rel_base, path_len, fullpath);
1872 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06001873 loader_scanned_icd_add(inst, icds, fullpath);
Jon Ashburn2077e382015-06-29 11:25:34 -06001874 }
Jon Ashburn86251302015-08-25 16:48:24 -06001875
Jon Ashburn2077e382015-06-29 11:25:34 -06001876 }
1877 else
1878 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"ICD\" object in ICD JSON file %s, skipping", file_str);
1879
Jon Ashburne39a4f82015-08-28 13:38:21 -06001880 loader_heap_free(inst, file_str);
Jon Ashburn2077e382015-06-29 11:25:34 -06001881 cJSON_Delete(json);
1882 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06001883 loader_heap_free(inst, manifest_files.filename_list);
Jon Ashburn6461ef22015-09-22 13:11:00 -06001884 loader_platform_thread_unlock_mutex(&loader_json_lock);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001885}
1886
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001887
Jon Ashburne39a4f82015-08-28 13:38:21 -06001888void loader_layer_scan(
1889 const struct loader_instance *inst,
1890 struct loader_layer_list *instance_layers,
1891 struct loader_layer_list *device_layers)
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001892{
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001893 char *file_str;
1894 struct loader_manifest_files manifest_files;
1895 cJSON *json;
1896 uint32_t i;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001897
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001898 // Get a list of manifest files for layers
Jon Ashburne39a4f82015-08-28 13:38:21 -06001899 loader_get_manifest_files(inst, LAYERS_PATH_ENV, true, DEFAULT_VK_LAYERS_INFO,
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001900 &manifest_files);
1901 if (manifest_files.count == 0)
Courtney Goeltzenleuchter57985ce2014-12-01 09:29:42 -07001902 return;
Jon Ashburn90c6a0e2015-06-04 15:30:58 -06001903
Jon Ashburne13ecc92015-08-03 17:19:30 -06001904#if 0 //TODO
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001905 /**
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -06001906 * We need a list of the layer libraries, not just a list of
1907 * the layer properties (a layer library could expose more than
1908 * one layer property). This list of scanned layers would be
1909 * used to check for global and physicaldevice layer properties.
1910 */
1911 if (!loader_init_layer_library_list(&loader.scanned_layer_libraries)) {
1912 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
Jon Ashburne39a4f82015-08-28 13:38:21 -06001913 "Alloc for layer list failed: %s line: %d", __FILE__, __LINE__);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -06001914 return;
Jon Ashburn5ef20602015-07-02 09:40:15 -06001915 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001916#endif
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001917
Jon Ashburne13ecc92015-08-03 17:19:30 -06001918 /* cleanup any previously scanned libraries */
Jon Ashburne39a4f82015-08-28 13:38:21 -06001919 loader_delete_layer_properties(inst, instance_layers);
1920 loader_delete_layer_properties(inst, device_layers);
Jon Ashburnb2ef1372015-07-16 17:19:31 -06001921
Jon Ashburn6461ef22015-09-22 13:11:00 -06001922 loader_platform_thread_lock_mutex(&loader_json_lock);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001923 for (i = 0; i < manifest_files.count; i++) {
1924 file_str = manifest_files.filename_list[i];
1925 if (file_str == NULL)
1926 continue;
Courtney Goeltzenleuchtera9e4af42015-06-01 14:49:17 -06001927
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001928 // parse file into JSON struct
1929 json = loader_get_json(file_str);
1930 if (!json) {
1931 continue;
1932 }
Jon Ashburne13ecc92015-08-03 17:19:30 -06001933
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001934 //TODO pass in implicit versus explicit bool
Jon Ashburnb2ef1372015-07-16 17:19:31 -06001935 //TODO error if device layers expose instance_extensions
1936 //TODO error if instance layers expose device extensions
Jon Ashburne39a4f82015-08-28 13:38:21 -06001937 loader_add_layer_properties(inst,
1938 instance_layers,
Jon Ashburnb82c1852015-08-11 14:49:54 -06001939 device_layers,
Jon Ashburnb2ef1372015-07-16 17:19:31 -06001940 json,
1941 false,
1942 file_str);
1943
Jon Ashburne39a4f82015-08-28 13:38:21 -06001944 loader_heap_free(inst, file_str);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001945 cJSON_Delete(json);
1946 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06001947 loader_heap_free(inst, manifest_files.filename_list);
Jon Ashburn6461ef22015-09-22 13:11:00 -06001948 loader_platform_thread_unlock_mutex(&loader_json_lock);
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001949}
1950
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06001951static PFN_vkVoidFunction VKAPI loader_gpa_instance_internal(VkInstance inst, const char * pName)
Jon Ashburn27cd5842015-05-12 17:26:48 -06001952{
1953 // inst is not wrapped
1954 if (inst == VK_NULL_HANDLE) {
1955 return NULL;
1956 }
1957 VkLayerInstanceDispatchTable* disp_table = * (VkLayerInstanceDispatchTable **) inst;
1958 void *addr;
1959
Jon Ashburn8fd08252015-05-28 16:25:02 -06001960 if (!strcmp(pName, "vkGetInstanceProcAddr"))
1961 return (void *) loader_gpa_instance_internal;
1962
Jon Ashburn27cd5842015-05-12 17:26:48 -06001963 if (disp_table == NULL)
1964 return NULL;
1965
1966 addr = loader_lookup_instance_dispatch_table(disp_table, pName);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001967 if (addr) {
Jon Ashburn27cd5842015-05-12 17:26:48 -06001968 return addr;
Jon Ashburn3d526cb2015-04-13 18:10:06 -06001969 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001970
1971 if (disp_table->GetInstanceProcAddr == NULL) {
1972 return NULL;
1973 }
1974 return disp_table->GetInstanceProcAddr(inst, pName);
Jon Ashburn3d526cb2015-04-13 18:10:06 -06001975}
1976
Jon Ashburne0e64572015-09-30 12:56:42 -06001977struct loader_instance *loader_get_instance(const VkInstance instance)
1978{
1979 /* look up the loader_instance in our list by comparing dispatch tables, as
1980 * there is no guarantee the instance is still a loader_instance* after any
1981 * layers which wrap the instance object.
1982 */
1983 const VkLayerInstanceDispatchTable *disp;
1984 struct loader_instance *ptr_instance = NULL;
1985 disp = loader_get_instance_dispatch(instance);
1986 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
1987 if (inst->disp == disp) {
1988 ptr_instance = inst;
1989 break;
1990 }
1991 }
1992 return ptr_instance;
1993}
1994
Jon Ashburn128f9422015-05-28 19:16:58 -06001995struct loader_icd * loader_get_icd(const VkPhysicalDevice gpu, uint32_t *gpu_index)
Jon Ashburn876b1ac2014-10-17 15:09:07 -06001996{
Jon Ashburn128f9422015-05-28 19:16:58 -06001997
Tony Barbourb5d2c942015-07-14 13:34:05 -06001998 *gpu_index = 0;
Jon Ashburn98bd4542015-01-29 16:44:24 -07001999 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
2000 for (struct loader_icd *icd = inst->icds; icd; icd = icd->next) {
2001 for (uint32_t i = 0; i < icd->gpu_count; i++)
Jon Ashburne0e64572015-09-30 12:56:42 -06002002 /* Value comparison of VkPhysicalDevice prevents wrapping, use
2003 * instance device table instead (TODO this aliases GPUs within
2004 * an instance, since they have identical dispatch tables)
2005 */
2006 if (loader_get_instance_dispatch(icd->gpus[i]) == loader_get_instance_dispatch(gpu)) {
Jon Ashburn98bd4542015-01-29 16:44:24 -07002007 *gpu_index = i;
2008 return icd;
2009 }
2010 }
Jon Ashburn876b1ac2014-10-17 15:09:07 -06002011 }
2012 return NULL;
2013}
2014
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002015static loader_platform_dl_handle loader_add_layer_lib(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002016 const struct loader_instance *inst,
Jon Ashburn4f67d742015-05-27 13:19:22 -06002017 const char *chain_type,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002018 struct loader_layer_properties *layer_prop)
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002019{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002020 struct loader_lib_info *new_layer_lib_list, *my_lib;
Jon Ashburne39a4f82015-08-28 13:38:21 -06002021 size_t new_alloc_size;
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -06002022 /*
2023 * TODO: We can now track this information in the
2024 * scanned_layer_libraries list.
2025 */
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002026 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) {
Jon Ashburn3d002332015-08-20 16:35:30 -06002027 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, layer_prop->lib_name) == 0) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002028 /* Have already loaded this library, just increment ref count */
2029 loader.loaded_layer_lib_list[i].ref_count++;
Courtney Goeltzenleuchterca8c81a2015-06-14 11:59:07 -06002030 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002031 "%s Chain: Increment layer reference count for layer library %s",
Jon Ashburn3d002332015-08-20 16:35:30 -06002032 chain_type, layer_prop->lib_name);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002033 return loader.loaded_layer_lib_list[i].lib_handle;
2034 }
2035 }
2036
2037 /* Haven't seen this library so load it */
Jon Ashburne39a4f82015-08-28 13:38:21 -06002038 new_alloc_size = 0;
2039 if (loader.loaded_layer_lib_capacity == 0)
2040 new_alloc_size = 8 * sizeof(struct loader_lib_info);
2041 else if (loader.loaded_layer_lib_capacity <= loader.loaded_layer_lib_count *
2042 sizeof(struct loader_lib_info))
2043 new_alloc_size = loader.loaded_layer_lib_capacity * 2;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002044
Jon Ashburne39a4f82015-08-28 13:38:21 -06002045 if (new_alloc_size) {
2046 new_layer_lib_list = loader_heap_realloc(
2047 inst, loader.loaded_layer_lib_list,
2048 loader.loaded_layer_lib_capacity,
2049 new_alloc_size,
2050 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
2051 if (!new_layer_lib_list) {
2052 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "loader: realloc failed in loader_add_layer_lib");
2053 return NULL;
2054 }
2055 loader.loaded_layer_lib_capacity = new_alloc_size;
2056 } else
2057 new_layer_lib_list = loader.loaded_layer_lib_list;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002058 my_lib = &new_layer_lib_list[loader.loaded_layer_lib_count];
2059
Jon Ashburn3d002332015-08-20 16:35:30 -06002060 strncpy(my_lib->lib_name, layer_prop->lib_name, sizeof(my_lib->lib_name));
2061 my_lib->lib_name[sizeof(my_lib->lib_name) - 1] = '\0';
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002062 my_lib->ref_count = 0;
2063 my_lib->lib_handle = NULL;
2064
2065 if ((my_lib->lib_handle = loader_platform_open_library(my_lib->lib_name)) == NULL) {
2066 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
2067 loader_platform_open_library_error(my_lib->lib_name));
2068 return NULL;
2069 } else {
Courtney Goeltzenleuchterca8c81a2015-06-14 11:59:07 -06002070 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002071 "Chain: %s: Loading layer library %s",
Jon Ashburn3d002332015-08-20 16:35:30 -06002072 chain_type, layer_prop->lib_name);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002073 }
2074 loader.loaded_layer_lib_count++;
2075 loader.loaded_layer_lib_list = new_layer_lib_list;
2076 my_lib->ref_count++;
2077
2078 return my_lib->lib_handle;
2079}
2080
2081static void loader_remove_layer_lib(
2082 struct loader_instance *inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002083 struct loader_layer_properties *layer_prop)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002084{
2085 uint32_t idx;
Tony Barbourb5d2c942015-07-14 13:34:05 -06002086 struct loader_lib_info *new_layer_lib_list, *my_lib = NULL;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002087
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002088 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) {
Jon Ashburn3d002332015-08-20 16:35:30 -06002089 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, layer_prop->lib_name) == 0) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002090 /* found matching library */
2091 idx = i;
2092 my_lib = &loader.loaded_layer_lib_list[i];
2093 break;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002094 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002095 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002096
Tony Barbourb5d2c942015-07-14 13:34:05 -06002097 if (my_lib) {
2098 my_lib->ref_count--;
2099 if (my_lib->ref_count > 0) {
2100 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Jon Ashburn3d002332015-08-20 16:35:30 -06002101 "Decrement reference count for layer library %s", layer_prop->lib_name);
Tony Barbourb5d2c942015-07-14 13:34:05 -06002102 return;
2103 }
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07002104 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002105 loader_platform_close_library(my_lib->lib_handle);
Courtney Goeltzenleuchterca8c81a2015-06-14 11:59:07 -06002106 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Jon Ashburn3d002332015-08-20 16:35:30 -06002107 "Unloading layer library %s", layer_prop->lib_name);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002108
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002109 /* Need to remove unused library from list */
Jon Ashburne39a4f82015-08-28 13:38:21 -06002110 new_layer_lib_list = loader_heap_alloc(inst,
2111 loader.loaded_layer_lib_capacity,
2112 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002113 if (!new_layer_lib_list) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06002114 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "loader: heap alloc failed loader_remove_layer_library");
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002115 return;
2116 }
2117
2118 if (idx > 0) {
2119 /* Copy records before idx */
2120 memcpy(new_layer_lib_list, &loader.loaded_layer_lib_list[0],
2121 sizeof(struct loader_lib_info) * idx);
2122 }
2123 if (idx < (loader.loaded_layer_lib_count - 1)) {
2124 /* Copy records after idx */
2125 memcpy(&new_layer_lib_list[idx], &loader.loaded_layer_lib_list[idx+1],
2126 sizeof(struct loader_lib_info) * (loader.loaded_layer_lib_count - idx - 1));
2127 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002128
Jon Ashburne39a4f82015-08-28 13:38:21 -06002129 loader_heap_free(inst, loader.loaded_layer_lib_list);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002130 loader.loaded_layer_lib_count--;
2131 loader.loaded_layer_lib_list = new_layer_lib_list;
Jon Ashburnb8358052014-11-18 09:06:04 -07002132}
2133
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002134
2135/**
2136 * Go through the search_list and find any layers which match type. If layer
2137 * type match is found in then add it to ext_list.
2138 */
2139//TODO need to handle implict layer enable env var and disable env var
Jon Ashburn0c26e712015-07-02 16:10:32 -06002140static void loader_add_layer_implicit(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002141 const struct loader_instance *inst,
Jon Ashburn0c26e712015-07-02 16:10:32 -06002142 const enum layer_type type,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002143 struct loader_layer_list *list,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002144 const struct loader_layer_list *search_list)
Jon Ashburn0c26e712015-07-02 16:10:32 -06002145{
2146 uint32_t i;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002147 for (i = 0; i < search_list->count; i++) {
2148 const struct loader_layer_properties *prop = &search_list->list[i];
Jon Ashburn0c26e712015-07-02 16:10:32 -06002149 if (prop->type & type) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002150 /* Found an layer with the same type, add to layer_list */
Jon Ashburne39a4f82015-08-28 13:38:21 -06002151 loader_add_to_layer_list(inst, list, 1, prop);
Jon Ashburn0c26e712015-07-02 16:10:32 -06002152 }
2153 }
2154
2155}
2156
2157/**
2158 * Get the layer name(s) from the env_name environment variable. If layer
Jon Ashburnbd332cc2015-07-07 10:27:45 -06002159 * is found in search_list then add it to layer_list. But only add it to
2160 * layer_list if type matches.
Jon Ashburn0c26e712015-07-02 16:10:32 -06002161 */
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002162static void loader_add_layer_env(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002163 const struct loader_instance *inst,
Jon Ashburnbd332cc2015-07-07 10:27:45 -06002164 const enum layer_type type,
Jon Ashburneb6d5682015-07-02 14:10:53 -06002165 const char *env_name,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002166 struct loader_layer_list *layer_list,
2167 const struct loader_layer_list *search_list)
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002168{
Ian Elliott4470a302015-02-17 10:33:47 -07002169 char *layerEnv;
Jon Ashburneb6d5682015-07-02 14:10:53 -06002170 char *next, *name;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002171
Jon Ashburneb6d5682015-07-02 14:10:53 -06002172 layerEnv = getenv(env_name);
Ian Elliott4470a302015-02-17 10:33:47 -07002173 if (layerEnv == NULL) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002174 return;
Ian Elliott4470a302015-02-17 10:33:47 -07002175 }
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -06002176 name = loader_stack_alloc(strlen(layerEnv) + 1);
Jon Ashburneb6d5682015-07-02 14:10:53 -06002177 if (name == NULL) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002178 return;
Ian Elliott4470a302015-02-17 10:33:47 -07002179 }
Jon Ashburneb6d5682015-07-02 14:10:53 -06002180 strcpy(name, layerEnv);
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002181
Jon Ashburneb6d5682015-07-02 14:10:53 -06002182 while (name && *name ) {
2183 next = loader_get_next_path(name);
Jon Ashburne39a4f82015-08-28 13:38:21 -06002184 loader_find_layer_name_add_list(inst, name, type, search_list, layer_list);
Jon Ashburneb6d5682015-07-02 14:10:53 -06002185 name = next;
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07002186 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002187
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002188 return;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002189}
2190
Courtney Goeltzenleuchter7d0023c2015-06-08 15:09:22 -06002191void loader_deactivate_instance_layers(struct loader_instance *instance)
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002192{
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002193 if (!instance->activated_layer_list.count) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002194 return;
2195 }
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002196
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002197 /* Create instance chain of enabled layers */
Courtney Goeltzenleuchter7d0023c2015-06-08 15:09:22 -06002198 for (uint32_t i = 0; i < instance->activated_layer_list.count; i++) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002199 struct loader_layer_properties *layer_prop = &instance->activated_layer_list.list[i];
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002200
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002201 loader_remove_layer_lib(instance, layer_prop);
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002202 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06002203 loader_destroy_layer_list(instance, &instance->activated_layer_list);
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002204}
2205
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002206VkResult loader_enable_instance_layers(
Jon Ashburnb82c1852015-08-11 14:49:54 -06002207 struct loader_instance *inst,
2208 const VkInstanceCreateInfo *pCreateInfo,
2209 const struct loader_layer_list *instance_layers)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002210{
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002211 VkResult err;
2212
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06002213 assert(inst && "Cannot have null instance");
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002214
Jon Ashburne39a4f82015-08-28 13:38:21 -06002215 if (!loader_init_layer_list(inst, &inst->activated_layer_list)) {
2216 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc Instance activated layer list");
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002217 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002218 }
2219
Jon Ashburn0c26e712015-07-02 16:10:32 -06002220 /* Add any implicit layers first */
2221 loader_add_layer_implicit(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002222 inst,
Jon Ashburn0c26e712015-07-02 16:10:32 -06002223 VK_LAYER_TYPE_INSTANCE_IMPLICIT,
2224 &inst->activated_layer_list,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002225 instance_layers);
Jon Ashburn0c26e712015-07-02 16:10:32 -06002226
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002227 /* Add any layers specified via environment variable next */
Jon Ashburneb6d5682015-07-02 14:10:53 -06002228 loader_add_layer_env(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002229 inst,
Jon Ashburnbd332cc2015-07-07 10:27:45 -06002230 VK_LAYER_TYPE_INSTANCE_EXPLICIT,
Jon Ashburneb6d5682015-07-02 14:10:53 -06002231 "VK_INSTANCE_LAYERS",
2232 &inst->activated_layer_list,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002233 instance_layers);
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002234
2235 /* Add layers specified by the application */
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002236 err = loader_add_layer_names_to_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002237 inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002238 &inst->activated_layer_list,
2239 pCreateInfo->layerCount,
2240 pCreateInfo->ppEnabledLayerNames,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002241 instance_layers);
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002242
2243 return err;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002244}
2245
Jon Ashburn27cd5842015-05-12 17:26:48 -06002246uint32_t loader_activate_instance_layers(struct loader_instance *inst)
2247{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002248 uint32_t layer_idx;
Jon Ashburn128f9422015-05-28 19:16:58 -06002249 VkBaseLayerObject *wrappedInstance;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002250
David Pinedoa0a8a242015-06-24 15:29:18 -06002251 if (inst == NULL) {
Jon Ashburn27cd5842015-05-12 17:26:48 -06002252 return 0;
David Pinedoa0a8a242015-06-24 15:29:18 -06002253 }
Jon Ashburn27cd5842015-05-12 17:26:48 -06002254
2255 // NOTE inst is unwrapped at this point in time
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002256 void* baseObj = (void*) inst;
2257 void* nextObj = (void*) inst;
Jon Ashburn27cd5842015-05-12 17:26:48 -06002258 VkBaseLayerObject *nextInstObj;
2259 PFN_vkGetInstanceProcAddr nextGPA = loader_gpa_instance_internal;
2260
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002261 if (!inst->activated_layer_list.count) {
Courtney Goeltzenleuchtered1a8dd2015-08-07 09:53:18 -06002262 loader_init_instance_core_dispatch_table(inst->disp, nextGPA, (VkInstance) nextObj, (VkInstance) baseObj);
Jon Ashburn27cd5842015-05-12 17:26:48 -06002263 return 0;
2264 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002265
Courtney Goeltzenleuchter6f460c52015-07-06 09:04:55 -06002266 wrappedInstance = loader_stack_alloc(sizeof(VkBaseLayerObject)
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002267 * inst->activated_layer_list.count);
Jon Ashburn128f9422015-05-28 19:16:58 -06002268 if (!wrappedInstance) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06002269 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc Instance objects for layer");
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002270 return 0;
2271 }
2272
2273 /* Create instance chain of enabled layers */
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002274 layer_idx = inst->activated_layer_list.count - 1;
Courtney Goeltzenleuchter0f1d8eb2015-06-07 17:28:17 -06002275 for (int32_t i = inst->activated_layer_list.count - 1; i >= 0; i--) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002276 struct loader_layer_properties *layer_prop = &inst->activated_layer_list.list[i];
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002277 loader_platform_dl_handle lib_handle;
2278
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002279 /*
Courtney Goeltzenleuchteree3b16a2015-06-01 14:12:42 -06002280 * Note: An extension's Get*ProcAddr should not return a function pointer for
2281 * any extension entry points until the extension has been enabled.
2282 * To do this requires a different behavior from Get*ProcAddr functions implemented
2283 * in layers.
2284 * The very first call to a layer will be it's Get*ProcAddr function requesting
Tobin Ehlis1cb7f572015-10-06 09:09:24 -06002285 * the layer's vkGet*ProcAddr. The layer should initialize its internal dispatch table
Courtney Goeltzenleuchteree3b16a2015-06-01 14:12:42 -06002286 * with the wrapped object given (either Instance or Device) and return the layer's
2287 * Get*ProcAddr function. The layer should also use this opportunity to record the
2288 * baseObject so that it can find the correct local dispatch table on future calls.
2289 * Subsequent calls to Get*ProcAddr, CreateInstance, CreateDevice
2290 * will not use a wrapped object and must look up their local dispatch table from
2291 * the given baseObject.
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002292 */
Jon Ashburn128f9422015-05-28 19:16:58 -06002293 nextInstObj = (wrappedInstance + layer_idx);
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002294 nextInstObj->pGPA = (PFN_vkGPA) nextGPA;
Jon Ashburn27cd5842015-05-12 17:26:48 -06002295 nextInstObj->baseObject = baseObj;
2296 nextInstObj->nextObject = nextObj;
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002297 nextObj = (void*) nextInstObj;
Jon Ashburn27cd5842015-05-12 17:26:48 -06002298
Jon Ashburne39a4f82015-08-28 13:38:21 -06002299 lib_handle = loader_add_layer_lib(inst, "instance", layer_prop);
Jon Ashburn21c21ee2015-09-09 11:29:24 -06002300 if ((nextGPA = layer_prop->functions.get_instance_proc_addr) == NULL) {
2301 if (layer_prop->functions.str_gipa == NULL || strlen(layer_prop->functions.str_gipa) == 0) {
2302 nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetInstanceProcAddr");
2303 layer_prop->functions.get_instance_proc_addr = nextGPA;
2304 } else
2305 nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gipa);
2306 if (!nextGPA) {
2307 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 -06002308
Jon Ashburn21c21ee2015-09-09 11:29:24 -06002309 /* TODO: Should we return nextObj, nextGPA to previous? or decrement layer_list count*/
2310 continue;
2311 }
Jon Ashburn27cd5842015-05-12 17:26:48 -06002312 }
2313
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002314 loader_log(VK_DBG_REPORT_INFO_BIT, 0,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002315 "Insert instance layer %s (%s)",
2316 layer_prop->info.layerName,
Jon Ashburn3d002332015-08-20 16:35:30 -06002317 layer_prop->lib_name);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002318
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002319 layer_idx--;
Jon Ashburn27cd5842015-05-12 17:26:48 -06002320 }
2321
Jon Ashburn8fd08252015-05-28 16:25:02 -06002322 loader_init_instance_core_dispatch_table(inst->disp, nextGPA, (VkInstance) nextObj, (VkInstance) baseObj);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002323
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002324 return inst->activated_layer_list.count;
Jon Ashburn27cd5842015-05-12 17:26:48 -06002325}
2326
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002327void loader_activate_instance_layer_extensions(struct loader_instance *inst)
2328{
2329
2330 loader_init_instance_extension_dispatch_table(inst->disp,
2331 inst->disp->GetInstanceProcAddr,
Jon Ashburn128f9422015-05-28 19:16:58 -06002332 (VkInstance) inst);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002333}
2334
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002335static VkResult loader_enable_device_layers(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002336 const struct loader_instance *inst,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002337 struct loader_icd *icd,
2338 struct loader_device *dev,
2339 const VkDeviceCreateInfo *pCreateInfo,
2340 const struct loader_layer_list *device_layers)
2341
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002342{
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002343 VkResult err;
2344
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06002345 assert(dev && "Cannot have null device");
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002346
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002347 if (dev->activated_layer_list.list == NULL || dev->activated_layer_list.capacity == 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06002348 loader_init_layer_list(inst, &dev->activated_layer_list);
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002349 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002350
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002351 if (dev->activated_layer_list.list == NULL) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06002352 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc device activated layer list");
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002353 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002354 }
2355
Jon Ashburn0c26e712015-07-02 16:10:32 -06002356 /* Add any implicit layers first */
2357 loader_add_layer_implicit(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002358 inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002359 VK_LAYER_TYPE_DEVICE_IMPLICIT,
2360 &dev->activated_layer_list,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002361 device_layers);
Jon Ashburn0c26e712015-07-02 16:10:32 -06002362
2363 /* Add any layers specified via environment variable next */
Jon Ashburneb6d5682015-07-02 14:10:53 -06002364 loader_add_layer_env(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002365 inst,
Jon Ashburnbd332cc2015-07-07 10:27:45 -06002366 VK_LAYER_TYPE_DEVICE_EXPLICIT,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002367 "VK_DEVICE_LAYERS",
2368 &dev->activated_layer_list,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002369 device_layers);
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002370
2371 /* Add layers specified by the application */
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002372 err = loader_add_layer_names_to_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002373 inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002374 &dev->activated_layer_list,
2375 pCreateInfo->layerCount,
2376 pCreateInfo->ppEnabledLayerNames,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002377 device_layers);
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002378
2379 return err;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002380}
2381
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002382/*
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06002383 * This function terminates the device chain for CreateDevice.
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002384 * CreateDevice is a special case and so the loader call's
2385 * the ICD's CreateDevice before creating the chain. Since
2386 * we can't call CreateDevice twice we must terminate the
2387 * device chain with something else.
2388 */
Dan Ginsburg78556e82015-07-23 13:15:00 -04002389static VkResult VKAPI scratch_vkCreateDevice(
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002390 VkPhysicalDevice gpu,
2391 const VkDeviceCreateInfo *pCreateInfo,
2392 VkDevice *pDevice)
2393{
2394 return VK_SUCCESS;
2395}
2396
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06002397static PFN_vkVoidFunction VKAPI loader_GetDeviceChainProcAddr(VkDevice device, const char * name)
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002398{
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002399 if (!strcmp(name, "vkGetDeviceProcAddr"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06002400 return (PFN_vkVoidFunction) loader_GetDeviceChainProcAddr;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002401 if (!strcmp(name, "vkCreateDevice"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06002402 return (PFN_vkVoidFunction) scratch_vkCreateDevice;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002403
Courtney Goeltzenleuchter3e029d12015-06-29 16:09:23 -06002404 struct loader_device *found_dev;
2405 struct loader_icd *icd = loader_get_icd_and_device(device, &found_dev);
2406 return icd->GetDeviceProcAddr(device, name);
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002407}
2408
Jon Ashburndc6fcad2015-06-10 10:06:06 -06002409static uint32_t loader_activate_device_layers(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002410 const struct loader_instance *inst,
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002411 struct loader_device *dev,
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -06002412 VkDevice device)
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002413{
David Pinedoa0a8a242015-06-24 15:29:18 -06002414 if (!dev) {
Jon Ashburndc6fcad2015-06-10 10:06:06 -06002415 return 0;
David Pinedoa0a8a242015-06-24 15:29:18 -06002416 }
Jon Ashburn94e70492015-06-10 10:13:10 -06002417
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002418 /* activate any layer libraries */
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002419 void* nextObj = (void*) device;
2420 void* baseObj = nextObj;
Jon Ashburn94e70492015-06-10 10:13:10 -06002421 VkBaseLayerObject *nextGpuObj;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002422 PFN_vkGetDeviceProcAddr nextGPA = loader_GetDeviceChainProcAddr;
Jon Ashburn94e70492015-06-10 10:13:10 -06002423 VkBaseLayerObject *wrappedGpus;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002424
Courtney Goeltzenleuchtered1a8dd2015-08-07 09:53:18 -06002425 if (!dev->activated_layer_list.count) {
2426 loader_init_device_dispatch_table(&dev->loader_dispatch, nextGPA,
2427 (VkDevice) nextObj, (VkDevice) baseObj);
Jon Ashburn94e70492015-06-10 10:13:10 -06002428 return 0;
Courtney Goeltzenleuchtered1a8dd2015-08-07 09:53:18 -06002429 }
Jon Ashburn94e70492015-06-10 10:13:10 -06002430
Jon Ashburne39a4f82015-08-28 13:38:21 -06002431 wrappedGpus = loader_heap_alloc(inst,
2432 sizeof (VkBaseLayerObject) * dev->activated_layer_list.count,
2433 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburn94e70492015-06-10 10:13:10 -06002434 if (!wrappedGpus) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06002435 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc Gpu objects for layer");
Jon Ashburn94e70492015-06-10 10:13:10 -06002436 return 0;
2437 }
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002438
Jon Ashburn94e70492015-06-10 10:13:10 -06002439 for (int32_t i = dev->activated_layer_list.count - 1; i >= 0; i--) {
2440
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002441 struct loader_layer_properties *layer_prop = &dev->activated_layer_list.list[i];
Jon Ashburn94e70492015-06-10 10:13:10 -06002442 loader_platform_dl_handle lib_handle;
2443
Jon Ashburn94e70492015-06-10 10:13:10 -06002444 nextGpuObj = (wrappedGpus + i);
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002445 nextGpuObj->pGPA = (PFN_vkGPA)nextGPA;
Jon Ashburn94e70492015-06-10 10:13:10 -06002446 nextGpuObj->baseObject = baseObj;
2447 nextGpuObj->nextObject = nextObj;
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002448 nextObj = (void*) nextGpuObj;
Jon Ashburn94e70492015-06-10 10:13:10 -06002449
Jon Ashburne39a4f82015-08-28 13:38:21 -06002450 lib_handle = loader_add_layer_lib(inst, "device", layer_prop);
Jon Ashburn21c21ee2015-09-09 11:29:24 -06002451 if ((nextGPA = layer_prop->functions.get_device_proc_addr) == NULL) {
2452 if (layer_prop->functions.str_gdpa == NULL || strlen(layer_prop->functions.str_gdpa) == 0) {
2453 nextGPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetDeviceProcAddr");
2454 layer_prop->functions.get_device_proc_addr = nextGPA;
2455 } else
2456 nextGPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gdpa);
2457 if (!nextGPA) {
2458 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to find vkGetDeviceProcAddr in layer %s", layer_prop->lib_name);
2459 continue;
2460 }
Jon Ashburn94e70492015-06-10 10:13:10 -06002461 }
2462
2463 loader_log(VK_DBG_REPORT_INFO_BIT, 0,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002464 "Insert device layer library %s (%s)",
2465 layer_prop->info.layerName,
Jon Ashburn3d002332015-08-20 16:35:30 -06002466 layer_prop->lib_name);
Jon Ashburn94e70492015-06-10 10:13:10 -06002467
2468 }
2469
2470 loader_init_device_dispatch_table(&dev->loader_dispatch, nextGPA,
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002471 (VkDevice) nextObj, (VkDevice) baseObj);
Jon Ashburne39a4f82015-08-28 13:38:21 -06002472 loader_heap_free(inst, wrappedGpus);
Jon Ashburn94e70492015-06-10 10:13:10 -06002473
Jon Ashburndc6fcad2015-06-10 10:06:06 -06002474 return dev->activated_layer_list.count;
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002475}
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002476
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002477VkResult loader_validate_layers(
2478 const uint32_t layer_count,
2479 const char * const *ppEnabledLayerNames,
Jon Ashburn3d002332015-08-20 16:35:30 -06002480 const struct loader_layer_list *list)
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06002481{
2482 struct loader_layer_properties *prop;
2483
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002484 for (uint32_t i = 0; i < layer_count; i++) {
Jon Ashburne13ecc92015-08-03 17:19:30 -06002485 prop = loader_get_layer_property(ppEnabledLayerNames[i],
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002486 list);
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06002487 if (!prop) {
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06002488 return VK_ERROR_LAYER_NOT_PRESENT;
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06002489 }
2490 }
2491
2492 return VK_SUCCESS;
2493}
2494
2495VkResult loader_validate_instance_extensions(
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06002496 const struct loader_extension_list *icd_exts,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002497 const struct loader_layer_list *instance_layer,
2498 const VkInstanceCreateInfo *pCreateInfo)
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06002499{
Jon Ashburn5c042ea2015-08-04 11:14:18 -06002500 VkExtensionProperties *extension_prop;
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002501 struct loader_layer_properties *layer_prop;
2502
2503 for (uint32_t i = 0; i < pCreateInfo->extensionCount; i++) {
2504 extension_prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06002505 icd_exts);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002506
2507 if (extension_prop) {
2508 continue;
2509 }
2510
2511 extension_prop = NULL;
2512
2513 /* Not in global list, search layer extension lists */
2514 for (uint32_t j = 0; j < pCreateInfo->layerCount; j++) {
Jon Ashburne13ecc92015-08-03 17:19:30 -06002515 layer_prop = loader_get_layer_property(pCreateInfo->ppEnabledLayerNames[i],
Jon Ashburnb82c1852015-08-11 14:49:54 -06002516 instance_layer);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002517 if (!layer_prop) {
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06002518 /* Should NOT get here, loader_validate_layers
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002519 * should have already filtered this case out.
2520 */
2521 continue;
2522 }
2523
2524 extension_prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
2525 &layer_prop->instance_extension_list);
2526 if (extension_prop) {
2527 /* Found the extension in one of the layers enabled by the app. */
2528 break;
2529 }
2530 }
2531
2532 if (!extension_prop) {
2533 /* Didn't find extension name in any of the global layers, error out */
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06002534 return VK_ERROR_EXTENSION_NOT_PRESENT;
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002535 }
2536 }
2537 return VK_SUCCESS;
2538}
2539
2540VkResult loader_validate_device_extensions(
Jon Ashburnb82c1852015-08-11 14:49:54 -06002541 struct loader_icd *icd,
2542 uint32_t gpu_index,
2543 const struct loader_layer_list *device_layer,
2544 const VkDeviceCreateInfo *pCreateInfo)
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002545{
Jon Ashburn5c042ea2015-08-04 11:14:18 -06002546 VkExtensionProperties *extension_prop;
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002547 struct loader_layer_properties *layer_prop;
2548
2549 for (uint32_t i = 0; i < pCreateInfo->extensionCount; i++) {
2550 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i];
2551 extension_prop = get_extension_property(extension_name,
Courtney Goeltzenleuchterfedb2a52015-07-08 21:13:16 -06002552 &icd->device_extension_cache[gpu_index]);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002553
2554 if (extension_prop) {
2555 continue;
2556 }
2557
2558 /* Not in global list, search layer extension lists */
2559 for (uint32_t j = 0; j < pCreateInfo->layerCount; j++) {
2560 const char *layer_name = pCreateInfo->ppEnabledLayerNames[j];
Jon Ashburne13ecc92015-08-03 17:19:30 -06002561 layer_prop = loader_get_layer_property(layer_name,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002562 device_layer);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002563
2564 if (!layer_prop) {
2565 /* Should NOT get here, loader_validate_instance_layers
2566 * should have already filtered this case out.
2567 */
2568 continue;
2569 }
2570
2571 extension_prop = get_extension_property(extension_name,
2572 &layer_prop->device_extension_list);
2573 if (extension_prop) {
2574 /* Found the extension in one of the layers enabled by the app. */
2575 break;
2576 }
2577 }
2578
2579 if (!extension_prop) {
2580 /* Didn't find extension name in any of the device layers, error out */
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06002581 return VK_ERROR_EXTENSION_NOT_PRESENT;
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002582 }
2583 }
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06002584 return VK_SUCCESS;
2585}
2586
Dan Ginsburg78556e82015-07-23 13:15:00 -04002587VkResult VKAPI loader_CreateInstance(
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002588 const VkInstanceCreateInfo* pCreateInfo,
2589 VkInstance* pInstance)
Jon Ashburn1beab2d2015-01-26 14:51:40 -07002590{
Jon Ashburneed0c002015-05-21 17:42:17 -06002591 struct loader_instance *ptr_instance = *(struct loader_instance **) pInstance;
Jon Ashburn46888392015-01-29 15:45:51 -07002592 struct loader_icd *icd;
Jon Ashburn5c042ea2015-08-04 11:14:18 -06002593 VkExtensionProperties *prop;
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06002594 char **filtered_extension_names = NULL;
2595 VkInstanceCreateInfo icd_create_info;
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002596 VkResult res = VK_SUCCESS;
Jon Ashburnc624c882015-07-16 10:17:29 -06002597 bool success;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07002598
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06002599 icd_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
2600 icd_create_info.layerCount = 0;
2601 icd_create_info.ppEnabledLayerNames = NULL;
2602 icd_create_info.pAllocCb = pCreateInfo->pAllocCb;
2603 icd_create_info.pAppInfo = pCreateInfo->pAppInfo;
2604 icd_create_info.pNext = pCreateInfo->pNext;
2605
2606 /*
2607 * NOTE: Need to filter the extensions to only those
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002608 * supported by the ICD.
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06002609 * No ICD will advertise support for layers. An ICD
2610 * library could support a layer, but it would be
2611 * independent of the actual ICD, just in the same library.
2612 */
2613 filtered_extension_names = loader_stack_alloc(pCreateInfo->extensionCount * sizeof(char *));
2614 if (!filtered_extension_names) {
2615 return VK_ERROR_OUT_OF_HOST_MEMORY;
2616 }
2617 icd_create_info.ppEnabledExtensionNames = (const char * const *) filtered_extension_names;
2618
Jon Ashburn8810c5f2015-08-18 18:04:47 -06002619 for (uint32_t i = 0; i < ptr_instance->icd_libs.count; i++) {
2620 icd = loader_icd_add(ptr_instance, &ptr_instance->icd_libs.list[i]);
Jon Ashburn46888392015-01-29 15:45:51 -07002621 if (icd) {
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06002622 icd_create_info.extensionCount = 0;
2623 for (uint32_t i = 0; i < pCreateInfo->extensionCount; i++) {
2624 prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
Jon Ashburn5c6a46f2015-08-14 14:49:22 -06002625 &ptr_instance->ext_list);
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06002626 if (prop) {
2627 filtered_extension_names[icd_create_info.extensionCount] = (char *) pCreateInfo->ppEnabledExtensionNames[i];
2628 icd_create_info.extensionCount++;
2629 }
2630 }
2631
Jon Ashburn8810c5f2015-08-18 18:04:47 -06002632 res = ptr_instance->icd_libs.list[i].CreateInstance(&icd_create_info,
Jon Ashburn3da71f22015-05-14 12:43:38 -06002633 &(icd->instance));
Jon Ashburnc624c882015-07-16 10:17:29 -06002634 success = loader_icd_init_entrys(
2635 icd,
2636 icd->instance,
Jon Ashburn8810c5f2015-08-18 18:04:47 -06002637 ptr_instance->icd_libs.list[i].GetInstanceProcAddr);
Jon Ashburnc624c882015-07-16 10:17:29 -06002638
2639 if (res != VK_SUCCESS || !success)
Jon Ashburn46888392015-01-29 15:45:51 -07002640 {
2641 ptr_instance->icds = ptr_instance->icds->next;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002642 loader_icd_destroy(ptr_instance, icd);
Jon Ashburn3da71f22015-05-14 12:43:38 -06002643 icd->instance = VK_NULL_HANDLE;
Jon Ashburnc624c882015-07-16 10:17:29 -06002644 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
2645 "ICD ignored: failed to CreateInstance and find entrypoints with ICD");
Jon Ashburn46888392015-01-29 15:45:51 -07002646 }
2647 }
Jon Ashburn46888392015-01-29 15:45:51 -07002648 }
Jon Ashburn1beab2d2015-01-26 14:51:40 -07002649
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002650 /*
2651 * If no ICDs were added to instance list and res is unchanged
2652 * from it's initial value, the loader was unable to find
2653 * a suitable ICD.
2654 */
Ian Elliotteb450762015-02-05 15:19:15 -07002655 if (ptr_instance->icds == NULL) {
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002656 if (res == VK_SUCCESS) {
2657 return VK_ERROR_INCOMPATIBLE_DRIVER;
2658 } else {
2659 return res;
2660 }
Ian Elliotteb450762015-02-05 15:19:15 -07002661 }
Jon Ashburn46888392015-01-29 15:45:51 -07002662
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002663 return VK_SUCCESS;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07002664}
2665
Mark Lobodzinski2141f652015-09-07 13:59:43 -06002666void VKAPI loader_DestroyInstance(
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -06002667 VkInstance instance)
Jon Ashburn1beab2d2015-01-26 14:51:40 -07002668{
Courtney Goeltzenleuchterdeceded2015-06-08 15:04:02 -06002669 struct loader_instance *ptr_instance = loader_instance(instance);
Jon Ashburn3da71f22015-05-14 12:43:38 -06002670 struct loader_icd *icds = ptr_instance->icds;
Jon Ashburna6fd2612015-06-16 14:43:19 -06002671 struct loader_icd *next_icd;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07002672
2673 // Remove this instance from the list of instances:
2674 struct loader_instance *prev = NULL;
2675 struct loader_instance *next = loader.instances;
2676 while (next != NULL) {
2677 if (next == ptr_instance) {
2678 // Remove this instance from the list:
2679 if (prev)
2680 prev->next = next->next;
Jon Ashburnc5c49602015-02-03 09:26:59 -07002681 else
2682 loader.instances = next->next;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07002683 break;
2684 }
2685 prev = next;
2686 next = next->next;
2687 }
Jon Ashburn1beab2d2015-01-26 14:51:40 -07002688
Jon Ashburn3da71f22015-05-14 12:43:38 -06002689 while (icds) {
2690 if (icds->instance) {
Mark Lobodzinski2141f652015-09-07 13:59:43 -06002691 icds->DestroyInstance(icds->instance);
Tony Barbourf20f87b2015-04-22 09:02:32 -06002692 }
Jon Ashburna6fd2612015-06-16 14:43:19 -06002693 next_icd = icds->next;
Jon Ashburn3da71f22015-05-14 12:43:38 -06002694 icds->instance = VK_NULL_HANDLE;
Jon Ashburna6fd2612015-06-16 14:43:19 -06002695 loader_icd_destroy(ptr_instance, icds);
2696
2697 icds = next_icd;
Jon Ashburn46888392015-01-29 15:45:51 -07002698 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06002699 loader_delete_layer_properties(ptr_instance, &ptr_instance->device_layer_list);
2700 loader_delete_layer_properties(ptr_instance, &ptr_instance->instance_layer_list);
2701 loader_scanned_icd_clear(ptr_instance, &ptr_instance->icd_libs);
2702 loader_destroy_ext_list(ptr_instance, &ptr_instance->ext_list);
Jon Ashburn1beab2d2015-01-26 14:51:40 -07002703}
2704
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002705VkResult loader_init_physical_device_info(
2706 struct loader_instance *ptr_instance)
2707{
2708 struct loader_icd *icd;
2709 uint32_t n, count = 0;
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06002710 VkResult res;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002711
2712 icd = ptr_instance->icds;
2713 while (icd) {
2714 res = icd->EnumeratePhysicalDevices(icd->instance, &n, NULL);
2715 if (res != VK_SUCCESS)
2716 return res;
2717 icd->gpu_count = n;
2718 count += n;
2719 icd = icd->next;
2720 }
2721
2722 ptr_instance->total_gpu_count = count;
2723
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002724 icd = ptr_instance->icds;
2725 while (icd) {
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002726
2727 n = icd->gpu_count;
Jon Ashburne39a4f82015-08-28 13:38:21 -06002728 icd->gpus = (VkPhysicalDevice *) loader_heap_alloc(
2729 ptr_instance,
2730 n * sizeof(VkPhysicalDevice),
2731 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
Jon Ashburn128f9422015-05-28 19:16:58 -06002732 if (!icd->gpus) {
2733 /* TODO: Add cleanup code here */
2734 return VK_ERROR_OUT_OF_HOST_MEMORY;
2735 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002736 res = icd->EnumeratePhysicalDevices(
2737 icd->instance,
2738 &n,
Jon Ashburn128f9422015-05-28 19:16:58 -06002739 icd->gpus);
2740 if ((res == VK_SUCCESS) && (n == icd->gpu_count)) {
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002741
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002742 for (unsigned int i = 0; i < n; i++) {
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002743
Jon Ashburn128f9422015-05-28 19:16:58 -06002744 loader_init_dispatch(icd->gpus[i], ptr_instance->disp);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002745
Jon Ashburne39a4f82015-08-28 13:38:21 -06002746 if (!loader_init_ext_list(ptr_instance, &icd->device_extension_cache[i])) {
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002747 /* TODO: Add cleanup code here */
2748 res = VK_ERROR_OUT_OF_HOST_MEMORY;
2749 }
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002750 if (res == VK_SUCCESS) {
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002751
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002752 loader_add_physical_device_extensions(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002753 ptr_instance,
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06002754 icd->EnumerateDeviceExtensionProperties,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002755 icd->gpus[0],
Jon Ashburn3d002332015-08-20 16:35:30 -06002756 icd->this_icd_lib->lib_name,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002757 &icd->device_extension_cache[i]);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002758
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002759 }
2760
2761 if (res != VK_SUCCESS) {
2762 /* clean up any extension lists previously created before this request failed */
2763 for (uint32_t j = 0; j < i; j++) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06002764 loader_destroy_ext_list(
2765 ptr_instance,
2766 &icd->device_extension_cache[i]);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002767 }
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002768
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002769 return res;
2770 }
2771 }
2772
2773 count += n;
2774 }
2775
2776 icd = icd->next;
2777 }
2778
2779 return VK_SUCCESS;
2780}
2781
Dan Ginsburg78556e82015-07-23 13:15:00 -04002782VkResult VKAPI loader_EnumeratePhysicalDevices(
Courtney Goeltzenleuchter5e41f1d2015-04-20 12:48:54 -06002783 VkInstance instance,
2784 uint32_t* pPhysicalDeviceCount,
2785 VkPhysicalDevice* pPhysicalDevices)
Jon Ashburn1beab2d2015-01-26 14:51:40 -07002786{
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002787 uint32_t index = 0;
Jon Ashburn4c392fb2015-01-28 19:57:09 -07002788 struct loader_instance *ptr_instance = (struct loader_instance *) instance;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002789 struct loader_icd *icd = ptr_instance->icds;
Jon Ashburn4c392fb2015-01-28 19:57:09 -07002790
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002791 if (ptr_instance->total_gpu_count == 0) {
2792 loader_init_physical_device_info(ptr_instance);
Jon Ashburn4c392fb2015-01-28 19:57:09 -07002793 }
2794
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002795 *pPhysicalDeviceCount = ptr_instance->total_gpu_count;
2796 if (!pPhysicalDevices) {
2797 return VK_SUCCESS;
2798 }
Jon Ashburn4c392fb2015-01-28 19:57:09 -07002799
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002800 while (icd) {
2801 assert((index + icd->gpu_count) <= *pPhysicalDeviceCount);
Jon Ashburn128f9422015-05-28 19:16:58 -06002802 memcpy(&pPhysicalDevices[index], icd->gpus, icd->gpu_count * sizeof(VkPhysicalDevice));
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002803 index += icd->gpu_count;
2804 icd = icd->next;
2805 }
2806
2807 return VK_SUCCESS;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07002808}
2809
Dan Ginsburg78556e82015-07-23 13:15:00 -04002810VkResult VKAPI loader_GetPhysicalDeviceProperties(
Jon Ashburn3da71f22015-05-14 12:43:38 -06002811 VkPhysicalDevice gpu,
Tony Barbour59a47322015-06-24 16:06:58 -06002812 VkPhysicalDeviceProperties* pProperties)
Jon Ashburn3da71f22015-05-14 12:43:38 -06002813{
2814 uint32_t gpu_index;
Jon Ashburn128f9422015-05-28 19:16:58 -06002815 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
Jon Ashburn3da71f22015-05-14 12:43:38 -06002816 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2817
Tony Barbour59a47322015-06-24 16:06:58 -06002818 if (icd->GetPhysicalDeviceProperties)
2819 res = icd->GetPhysicalDeviceProperties(gpu, pProperties);
2820
2821 return res;
2822}
2823
Cody Northropd0802882015-08-03 17:04:53 -06002824VkResult VKAPI loader_GetPhysicalDeviceQueueFamilyProperties (
Tony Barbour59a47322015-06-24 16:06:58 -06002825 VkPhysicalDevice gpu,
Cody Northropd0802882015-08-03 17:04:53 -06002826 uint32_t* pCount,
2827 VkQueueFamilyProperties* pProperties)
Tony Barbour59a47322015-06-24 16:06:58 -06002828{
2829 uint32_t gpu_index;
2830 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
2831 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2832
Cody Northropd0802882015-08-03 17:04:53 -06002833 if (icd->GetPhysicalDeviceQueueFamilyProperties)
2834 res = icd->GetPhysicalDeviceQueueFamilyProperties(gpu, pCount, pProperties);
Tony Barbour59a47322015-06-24 16:06:58 -06002835
2836 return res;
2837}
2838
Dan Ginsburg78556e82015-07-23 13:15:00 -04002839VkResult VKAPI loader_GetPhysicalDeviceMemoryProperties (
Tony Barbour59a47322015-06-24 16:06:58 -06002840 VkPhysicalDevice gpu,
2841 VkPhysicalDeviceMemoryProperties* pProperties)
2842{
2843 uint32_t gpu_index;
2844 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
2845 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2846
2847 if (icd->GetPhysicalDeviceMemoryProperties)
2848 res = icd->GetPhysicalDeviceMemoryProperties(gpu, pProperties);
Jon Ashburn3da71f22015-05-14 12:43:38 -06002849
2850 return res;
2851}
2852
Dan Ginsburg78556e82015-07-23 13:15:00 -04002853VkResult VKAPI loader_GetPhysicalDeviceFeatures(
Chris Forbesbc0bb772015-06-21 22:55:02 +12002854 VkPhysicalDevice physicalDevice,
2855 VkPhysicalDeviceFeatures* pFeatures)
2856{
2857 uint32_t gpu_index;
2858 struct loader_icd *icd = loader_get_icd(physicalDevice, &gpu_index);
2859 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2860
2861 if (icd->GetPhysicalDeviceFeatures)
2862 res = icd->GetPhysicalDeviceFeatures(physicalDevice, pFeatures);
2863
2864 return res;
2865}
2866
Dan Ginsburg78556e82015-07-23 13:15:00 -04002867VkResult VKAPI loader_GetPhysicalDeviceFormatProperties(
Chris Forbesbc0bb772015-06-21 22:55:02 +12002868 VkPhysicalDevice physicalDevice,
2869 VkFormat format,
2870 VkFormatProperties* pFormatInfo)
2871{
2872 uint32_t gpu_index;
2873 struct loader_icd *icd = loader_get_icd(physicalDevice, &gpu_index);
2874 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2875
Courtney Goeltzenleuchter2caec862015-07-12 12:52:09 -06002876 if (icd->GetPhysicalDeviceFormatProperties)
2877 res = icd->GetPhysicalDeviceFormatProperties(physicalDevice, format, pFormatInfo);
Chris Forbesbc0bb772015-06-21 22:55:02 +12002878
2879 return res;
2880}
2881
Jon Ashburn754864f2015-07-23 18:49:07 -06002882VkResult VKAPI loader_GetPhysicalDeviceImageFormatProperties(
2883 VkPhysicalDevice physicalDevice,
2884 VkFormat format,
2885 VkImageType type,
2886 VkImageTiling tiling,
2887 VkImageUsageFlags usage,
Courtney Goeltzenleuchtera22097a2015-09-10 13:44:12 -06002888 VkImageCreateFlags flags,
Jon Ashburn754864f2015-07-23 18:49:07 -06002889 VkImageFormatProperties* pImageFormatProperties)
2890{
2891 uint32_t gpu_index;
2892 struct loader_icd *icd = loader_get_icd(physicalDevice, &gpu_index);
2893 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2894
2895 if (icd->GetPhysicalDeviceImageFormatProperties)
2896 res = icd->GetPhysicalDeviceImageFormatProperties(physicalDevice, format,
Courtney Goeltzenleuchtera22097a2015-09-10 13:44:12 -06002897 type, tiling, usage, flags, pImageFormatProperties);
Jon Ashburn754864f2015-07-23 18:49:07 -06002898
2899 return res;
2900}
2901
Dan Ginsburg78556e82015-07-23 13:15:00 -04002902VkResult VKAPI loader_GetPhysicalDeviceSparseImageFormatProperties(
Mark Lobodzinski16e8bef2015-07-03 15:58:09 -06002903 VkPhysicalDevice physicalDevice,
2904 VkFormat format,
2905 VkImageType type,
2906 uint32_t samples,
2907 VkImageUsageFlags usage,
2908 VkImageTiling tiling,
2909 uint32_t* pNumProperties,
2910 VkSparseImageFormatProperties* pProperties)
2911{
2912 uint32_t gpu_index;
2913 struct loader_icd *icd = loader_get_icd(physicalDevice, &gpu_index);
2914 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2915
2916 if (icd->GetPhysicalDeviceSparseImageFormatProperties)
2917 res = icd->GetPhysicalDeviceSparseImageFormatProperties(physicalDevice, format, type, samples, usage, tiling, pNumProperties, pProperties);
2918
2919 return res;
2920}
2921
Dan Ginsburg78556e82015-07-23 13:15:00 -04002922VkResult VKAPI loader_CreateDevice(
Jon Ashburn95a77ba2015-05-15 15:09:35 -06002923 VkPhysicalDevice gpu,
2924 const VkDeviceCreateInfo* pCreateInfo,
2925 VkDevice* pDevice)
2926{
2927 uint32_t gpu_index;
Jon Ashburn128f9422015-05-28 19:16:58 -06002928 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
Jon Ashburndc6fcad2015-06-10 10:06:06 -06002929 struct loader_device *dev;
Jon Ashburne39a4f82015-08-28 13:38:21 -06002930 const struct loader_instance *inst = icd->this_instance;
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06002931 VkDeviceCreateInfo device_create_info;
2932 char **filtered_extension_names = NULL;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002933 VkResult res;
Jon Ashburn95a77ba2015-05-15 15:09:35 -06002934
Mark Lobodzinski0c29b922015-09-17 15:17:34 -06002935 assert(pCreateInfo->queueRecordCount >= 1);
2936
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002937 if (!icd->CreateDevice) {
2938 return VK_ERROR_INITIALIZATION_FAILED;
Jon Ashburn95a77ba2015-05-15 15:09:35 -06002939 }
2940
Jon Ashburnb82c1852015-08-11 14:49:54 -06002941 /* validate any app enabled layers are available */
2942 if (pCreateInfo->layerCount > 0) {
2943 res = loader_validate_layers(pCreateInfo->layerCount,
2944 pCreateInfo->ppEnabledLayerNames,
Jon Ashburne39a4f82015-08-28 13:38:21 -06002945 &inst->device_layer_list);
Jon Ashburnb82c1852015-08-11 14:49:54 -06002946 if (res != VK_SUCCESS) {
2947 return res;
2948 }
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002949 }
2950
Jon Ashburne39a4f82015-08-28 13:38:21 -06002951 res = loader_validate_device_extensions(icd, gpu_index, &inst->device_layer_list, pCreateInfo);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002952 if (res != VK_SUCCESS) {
2953 return res;
2954 }
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002955
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06002956 /*
2957 * NOTE: Need to filter the extensions to only those
2958 * supported by the ICD.
2959 * No ICD will advertise support for layers. An ICD
2960 * library could support a layer, but it would be
2961 * independent of the actual ICD, just in the same library.
2962 */
2963 filtered_extension_names = loader_stack_alloc(pCreateInfo->extensionCount * sizeof(char *));
2964 if (!filtered_extension_names) {
2965 return VK_ERROR_OUT_OF_HOST_MEMORY;
2966 }
2967
2968 /* Copy user's data */
2969 memcpy(&device_create_info, pCreateInfo, sizeof(VkDeviceCreateInfo));
2970
2971 /* ICD's do not use layers */
2972 device_create_info.layerCount = 0;
2973 device_create_info.ppEnabledLayerNames = NULL;
2974
2975 device_create_info.extensionCount = 0;
2976 device_create_info.ppEnabledExtensionNames = (const char * const *) filtered_extension_names;
2977
2978 for (uint32_t i = 0; i < pCreateInfo->extensionCount; i++) {
2979 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i];
Jon Ashburn5c042ea2015-08-04 11:14:18 -06002980 VkExtensionProperties *prop = get_extension_property(extension_name,
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06002981 &icd->device_extension_cache[gpu_index]);
2982 if (prop) {
2983 filtered_extension_names[device_create_info.extensionCount] = (char *) extension_name;
2984 device_create_info.extensionCount++;
2985 }
2986 }
2987
Jon Ashburne0e64572015-09-30 12:56:42 -06002988 // since gpu object maybe wrapped by a layer need to get unwrapped version
2989 // we haven't yet called down the chain for the layer to unwrap the object
2990 res = icd->CreateDevice(icd->gpus[gpu_index], pCreateInfo, pDevice);
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002991 if (res != VK_SUCCESS) {
2992 return res;
2993 }
2994
Jon Ashburne39a4f82015-08-28 13:38:21 -06002995 dev = loader_add_logical_device(inst, *pDevice, &icd->logical_device_list);
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002996 if (dev == NULL) {
2997 return VK_ERROR_OUT_OF_HOST_MEMORY;
2998 }
2999 PFN_vkGetDeviceProcAddr get_proc_addr = icd->GetDeviceProcAddr;
3000 loader_init_device_dispatch_table(&dev->loader_dispatch, get_proc_addr,
Courtney Goeltzenleuchtere315d3c2015-07-16 10:36:57 -06003001 *pDevice, *pDevice);
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003002
3003 dev->loader_dispatch.CreateDevice = scratch_vkCreateDevice;
3004 loader_init_dispatch(*pDevice, &dev->loader_dispatch);
3005
Jon Ashburnb82c1852015-08-11 14:49:54 -06003006 /* activate any layers on device chain which terminates with device*/
Jon Ashburne39a4f82015-08-28 13:38:21 -06003007 res = loader_enable_device_layers(inst, icd, dev, pCreateInfo, &inst->device_layer_list);
Jon Ashburnb82c1852015-08-11 14:49:54 -06003008 if (res != VK_SUCCESS) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06003009 loader_destroy_logical_device(inst, dev);
Jon Ashburnb82c1852015-08-11 14:49:54 -06003010 return res;
3011 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06003012 loader_activate_device_layers(inst, dev, *pDevice);
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003013
3014 res = dev->loader_dispatch.CreateDevice(gpu, pCreateInfo, pDevice);
3015
3016 dev->loader_dispatch.CreateDevice = icd->CreateDevice;
3017
Jon Ashburn95a77ba2015-05-15 15:09:35 -06003018 return res;
3019}
3020
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003021/**
3022 * Get an instance level or global level entry point address.
3023 * @param instance
3024 * @param pName
3025 * @return
3026 * If instance == NULL returns a global level entrypoint for all core entry points
3027 * If instance is valid returns a instance relative entry point for instance level
3028 * entry points both core and extensions.
3029 * Instance relative means call down the instance chain. Global means trampoline entry points.
3030 */
3031LOADER_EXPORT PFN_vkVoidFunction VKAPI vkGetInstanceProcAddr(VkInstance instance, const char * pName)
Jon Ashburnb0fbe912015-05-06 10:15:07 -06003032{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003033
Jon Ashburn07daee72015-05-21 18:13:33 -06003034 void *addr;
Jon Ashburnb0fbe912015-05-06 10:15:07 -06003035
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003036 if (instance == VK_NULL_HANDLE) {
Jon Ashburnf7a48db2015-10-01 12:03:17 -06003037 /* get entrypoint addresses that are global (in the loader),
3038 doesn't include any instance extensions since they may not be enabled yet*/
Jon Ashburne0e64572015-09-30 12:56:42 -06003039
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003040 addr = globalGetProcAddr(pName);
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003041
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003042 return addr;
3043 }
3044
Jon Ashburnf7a48db2015-10-01 12:03:17 -06003045
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003046 /* return any instance entrypoints that must resolve to loader code */
3047 addr = loader_non_passthrough_gipa(pName);
David Pinedoa0a8a242015-06-24 15:29:18 -06003048 if (addr) {
Jon Ashburn922c8f62015-06-18 09:05:37 -06003049 return addr;
David Pinedoa0a8a242015-06-24 15:29:18 -06003050 }
Jon Ashburn07daee72015-05-21 18:13:33 -06003051
Jon Ashburnf7a48db2015-10-01 12:03:17 -06003052 /* debug_report is a special case; need to return loader trampoline entrypoints
3053 * unless the extension is not enabled; also need to handle debug_report
3054 * utility functions */
Jon Ashburne0e64572015-09-30 12:56:42 -06003055 struct loader_instance *ptr_instance = loader_get_instance(instance);
Jon Ashburnf7a48db2015-10-01 12:03:17 -06003056 if (debug_report_instance_gpa(ptr_instance, pName, &addr)) {
3057 return addr;
3058 }
3059
3060 /* return the instance dispatch table entrypoint for core and extensions */
Jon Ashburn07daee72015-05-21 18:13:33 -06003061 const VkLayerInstanceDispatchTable *disp_table = * (VkLayerInstanceDispatchTable **) instance;
3062 if (disp_table == NULL)
3063 return NULL;
3064
3065 addr = loader_lookup_instance_dispatch_table(disp_table, pName);
3066 if (addr)
3067 return addr;
Jon Ashburnb0fbe912015-05-06 10:15:07 -06003068
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003069 // NOTE: any instance extensions must be known to loader and resolved
3070 // in the above call to loader_lookup_instance_dispatch_table())
Jon Ashburnb0fbe912015-05-06 10:15:07 -06003071 return NULL;
3072}
3073
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003074/**
3075 * Get a device level or global level entry point address.
3076 * @param device
3077 * @param pName
3078 * @return
3079 * If device == NULL, returns a global level entrypoint for all core entry points
3080 * If device is valid, returns a device relative entry point for device level
3081 * entry points both core and extensions.
3082 * Device relative means call down the device chain. Global means trampoline entry points.
3083 */
3084LOADER_EXPORT PFN_vkVoidFunction VKAPI vkGetDeviceProcAddr(VkDevice device, const char * pName)
Courtney Goeltzenleuchter9ec39ac2015-06-22 17:45:21 -06003085{
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003086 void *addr;
Courtney Goeltzenleuchter9ec39ac2015-06-22 17:45:21 -06003087
Jon Ashburn8d1b0b52015-05-18 13:20:15 -06003088 if (device == VK_NULL_HANDLE) {
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003089 /* get entrypoint addresses that are global (in the loader)*/
3090 addr = globalGetProcAddr(pName);
3091 return addr;
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07003092 }
Jon Ashburn3d526cb2015-04-13 18:10:06 -06003093
Jon Ashburnd38bfb12014-10-14 19:15:22 -06003094
Jon Ashburn3d526cb2015-04-13 18:10:06 -06003095 /* for entrypoints that loader must handle (ie non-dispatchable or create object)
3096 make sure the loader entrypoint is returned */
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003097 addr = loader_non_passthrough_gdpa(pName);
Ian Elliotte19c9152015-04-15 12:53:19 -06003098 if (addr) {
Jon Ashburn3d526cb2015-04-13 18:10:06 -06003099 return addr;
Ian Elliotte19c9152015-04-15 12:53:19 -06003100 }
Jon Ashburn3d526cb2015-04-13 18:10:06 -06003101
3102 /* return the dispatch table entrypoint for the fastest case */
Jon Ashburn8d1b0b52015-05-18 13:20:15 -06003103 const VkLayerDispatchTable *disp_table = * (VkLayerDispatchTable **) device;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06003104 if (disp_table == NULL)
3105 return NULL;
3106
Jon Ashburn27cd5842015-05-12 17:26:48 -06003107 addr = loader_lookup_device_dispatch_table(disp_table, pName);
Chia-I Wuf46b81a2015-01-04 11:12:47 +08003108 if (addr)
3109 return addr;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06003110 else {
Jon Ashburn8d1b0b52015-05-18 13:20:15 -06003111 if (disp_table->GetDeviceProcAddr == NULL)
Jon Ashburnd38bfb12014-10-14 19:15:22 -06003112 return NULL;
Jon Ashburn8d1b0b52015-05-18 13:20:15 -06003113 return disp_table->GetDeviceProcAddr(device, pName);
Jon Ashburnd38bfb12014-10-14 19:15:22 -06003114 }
3115}
3116
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06003117LOADER_EXPORT VkResult VKAPI vkEnumerateInstanceExtensionProperties(
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003118 const char* pLayerName,
3119 uint32_t* pCount,
3120 VkExtensionProperties* pProperties)
3121{
Jon Ashburn432d2762015-09-18 12:53:16 -06003122 struct loader_extension_list *global_ext_list=NULL;
Jon Ashburnb82c1852015-08-11 14:49:54 -06003123 struct loader_layer_list instance_layers;
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003124 struct loader_extension_list icd_extensions;
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003125 struct loader_icd_libs icd_libs;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003126 uint32_t copy_size;
3127
Jon Ashburn87d6aa92015-08-28 15:19:27 -06003128 tls_instance = NULL;
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003129 memset(&icd_extensions, 0, sizeof(icd_extensions));
Mike Stroyan09c06c72015-10-01 15:23:48 -06003130 memset(&instance_layers, 0, sizeof(instance_layers));
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003131 loader_platform_thread_once(&once_init, loader_initialize);
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003132
Jon Ashburnb82c1852015-08-11 14:49:54 -06003133 /* get layer libraries if needed */
3134 if (pLayerName && strlen(pLayerName) != 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06003135 loader_layer_scan(NULL, &instance_layers, NULL);
Jon Ashburnb82c1852015-08-11 14:49:54 -06003136 for (uint32_t i = 0; i < instance_layers.count; i++) {
3137 struct loader_layer_properties *props = &instance_layers.list[i];
3138 if (strcmp(props->info.layerName, pLayerName) == 0) {
3139 global_ext_list = &props->instance_extension_list;
3140 }
3141 }
3142 }
3143 else {
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003144 /* Scan/discover all ICD libraries */
3145 memset(&icd_libs, 0 , sizeof(struct loader_icd_libs));
Jon Ashburne39a4f82015-08-28 13:38:21 -06003146 loader_icd_scan(NULL, &icd_libs);
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003147 /* get extensions from all ICD's, merge so no duplicates */
Jon Ashburne39a4f82015-08-28 13:38:21 -06003148 loader_get_icd_loader_instance_extensions(NULL, &icd_libs, &icd_extensions);
3149 loader_scanned_icd_clear(NULL, &icd_libs);
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003150 global_ext_list = &icd_extensions;
Jon Ashburnb82c1852015-08-11 14:49:54 -06003151 }
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003152
Jon Ashburnb82c1852015-08-11 14:49:54 -06003153 if (global_ext_list == NULL) {
Mike Stroyan09c06c72015-10-01 15:23:48 -06003154 loader_destroy_layer_list(NULL, &instance_layers);
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06003155 return VK_ERROR_LAYER_NOT_PRESENT;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003156 }
3157
3158 if (pProperties == NULL) {
Mike Stroyan09c06c72015-10-01 15:23:48 -06003159 *pCount = global_ext_list->count;
3160 loader_destroy_layer_list(NULL, &instance_layers);
Jon Ashburne39a4f82015-08-28 13:38:21 -06003161 loader_destroy_ext_list(NULL, &icd_extensions);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003162 return VK_SUCCESS;
3163 }
3164
Jon Ashburnb82c1852015-08-11 14:49:54 -06003165 copy_size = *pCount < global_ext_list->count ? *pCount : global_ext_list->count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003166 for (uint32_t i = 0; i < copy_size; i++) {
3167 memcpy(&pProperties[i],
Jon Ashburnb82c1852015-08-11 14:49:54 -06003168 &global_ext_list->list[i],
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003169 sizeof(VkExtensionProperties));
3170 }
3171 *pCount = copy_size;
Jon Ashburne39a4f82015-08-28 13:38:21 -06003172 loader_destroy_ext_list(NULL, &icd_extensions);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003173
Jon Ashburnb82c1852015-08-11 14:49:54 -06003174 if (copy_size < global_ext_list->count) {
Mike Stroyan09c06c72015-10-01 15:23:48 -06003175 loader_destroy_layer_list(NULL, &instance_layers);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003176 return VK_INCOMPLETE;
3177 }
3178
Mike Stroyan09c06c72015-10-01 15:23:48 -06003179 loader_destroy_layer_list(NULL, &instance_layers);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003180 return VK_SUCCESS;
3181}
3182
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06003183LOADER_EXPORT VkResult VKAPI vkEnumerateInstanceLayerProperties(
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003184 uint32_t* pCount,
3185 VkLayerProperties* pProperties)
Tony Barbour59a47322015-06-24 16:06:58 -06003186{
Jon Ashburn6301a0f2015-05-29 13:15:39 -06003187
Jon Ashburnb82c1852015-08-11 14:49:54 -06003188 struct loader_layer_list instance_layer_list;
Jon Ashburn87d6aa92015-08-28 15:19:27 -06003189 tls_instance = NULL;
Jon Ashburnb82c1852015-08-11 14:49:54 -06003190
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003191 loader_platform_thread_once(&once_init, loader_initialize);
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07003192
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003193 uint32_t copy_size;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06003194
Jon Ashburnb82c1852015-08-11 14:49:54 -06003195 /* get layer libraries */
3196 memset(&instance_layer_list, 0, sizeof(instance_layer_list));
Jon Ashburne39a4f82015-08-28 13:38:21 -06003197 loader_layer_scan(NULL, &instance_layer_list, NULL);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003198
3199 if (pProperties == NULL) {
Jon Ashburnb82c1852015-08-11 14:49:54 -06003200 *pCount = instance_layer_list.count;
Jon Ashburne39a4f82015-08-28 13:38:21 -06003201 loader_destroy_layer_list(NULL, &instance_layer_list);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003202 return VK_SUCCESS;
3203 }
3204
Jon Ashburnb82c1852015-08-11 14:49:54 -06003205 copy_size = (*pCount < instance_layer_list.count) ? *pCount : instance_layer_list.count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003206 for (uint32_t i = 0; i < copy_size; i++) {
Jon Ashburnb82c1852015-08-11 14:49:54 -06003207 memcpy(&pProperties[i], &instance_layer_list.list[i].info, sizeof(VkLayerProperties));
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003208 }
3209 *pCount = copy_size;
Jon Ashburne39a4f82015-08-28 13:38:21 -06003210 loader_destroy_layer_list(NULL, &instance_layer_list);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003211
Jon Ashburnb82c1852015-08-11 14:49:54 -06003212 if (copy_size < instance_layer_list.count) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003213 return VK_INCOMPLETE;
3214 }
Tony Barbour59a47322015-06-24 16:06:58 -06003215
3216 return VK_SUCCESS;
3217}
3218
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06003219VkResult VKAPI loader_EnumerateDeviceExtensionProperties(
Tony Barbour59a47322015-06-24 16:06:58 -06003220 VkPhysicalDevice gpu,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003221 const char* pLayerName,
3222 uint32_t* pCount,
Tony Barbour59a47322015-06-24 16:06:58 -06003223 VkExtensionProperties* pProperties)
3224{
3225 uint32_t gpu_index;
Jon Ashburn128f9422015-05-28 19:16:58 -06003226 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003227 uint32_t copy_size;
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07003228
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003229 uint32_t count;
Jon Ashburn432d2762015-09-18 12:53:16 -06003230 struct loader_extension_list *dev_ext_list=NULL;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003231
Jon Ashburnb82c1852015-08-11 14:49:54 -06003232 /* get layer libraries if needed */
3233 if (pLayerName && strlen(pLayerName) != 0) {
Jon Ashburn3d002332015-08-20 16:35:30 -06003234 for (uint32_t i = 0; i < icd->this_instance->device_layer_list.count; i++) {
3235 struct loader_layer_properties *props = &icd->this_instance->device_layer_list.list[i];
Jon Ashburnb82c1852015-08-11 14:49:54 -06003236 if (strcmp(props->info.layerName, pLayerName) == 0) {
3237 dev_ext_list = &props->device_extension_list;
3238 }
3239 }
3240 }
3241 else {
3242 dev_ext_list = &icd->device_extension_cache[gpu_index];
3243 }
3244
Jon Ashburn432d2762015-09-18 12:53:16 -06003245 count = (dev_ext_list == NULL) ? 0: dev_ext_list->count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003246 if (pProperties == NULL) {
3247 *pCount = count;
3248 return VK_SUCCESS;
3249 }
3250
3251 copy_size = *pCount < count ? *pCount : count;
3252 for (uint32_t i = 0; i < copy_size; i++) {
3253 memcpy(&pProperties[i],
Jon Ashburnb82c1852015-08-11 14:49:54 -06003254 &dev_ext_list->list[i],
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003255 sizeof(VkExtensionProperties));
3256 }
3257 *pCount = copy_size;
3258
3259 if (copy_size < count) {
3260 return VK_INCOMPLETE;
3261 }
3262
3263 return VK_SUCCESS;
3264}
3265
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06003266VkResult VKAPI loader_EnumerateDeviceLayerProperties(
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003267 VkPhysicalDevice gpu,
3268 uint32_t* pCount,
3269 VkLayerProperties* pProperties)
3270{
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003271 uint32_t copy_size;
Jon Ashburn3d002332015-08-20 16:35:30 -06003272 uint32_t gpu_index;
3273 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003274
Jon Ashburn3d002332015-08-20 16:35:30 -06003275 uint32_t count = icd->this_instance->device_layer_list.count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003276
3277 if (pProperties == NULL) {
3278 *pCount = count;
3279 return VK_SUCCESS;
3280 }
3281
Jon Ashburnb82c1852015-08-11 14:49:54 -06003282 copy_size = (*pCount < count) ? *pCount : count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003283 for (uint32_t i = 0; i < copy_size; i++) {
Jon Ashburn3d002332015-08-20 16:35:30 -06003284 memcpy(&pProperties[i], &(icd->this_instance->device_layer_list.list[i].info), sizeof(VkLayerProperties));
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003285 }
3286 *pCount = copy_size;
3287
3288 if (copy_size < count) {
3289 return VK_INCOMPLETE;
3290 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003291
3292 return VK_SUCCESS;
Jon Ashburn95a77ba2015-05-15 15:09:35 -06003293}