blob: 94aff5946efb0101fd1fe00c3355b72788e68be7 [file] [log] [blame]
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001/*
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06002 * Vulkan
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08003 *
4 * Copyright (C) 2014 LunarG, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
Chia-I Wu44e42362014-09-02 08:32:09 +080023 *
24 * Authors:
25 * Chia-I Wu <olv@lunarg.com>
Jon Ashburn406a0fe2014-11-14 09:52:42 -070026 * Jon Ashburn <jon@lunarg.com>
Chia-I Wu44e42362014-09-02 08:32:09 +080027 * Courtney Goeltzenleuchter <courtney@lunarg.com>
Ian Elliott76005132015-03-31 15:32:41 -060028 * Ian Elliott <ian@lunarg.com>
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080029 */
Jon Ashburn183dfd02014-10-22 18:13:16 -060030#define _GNU_SOURCE
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080031#include <stdio.h>
32#include <stdlib.h>
33#include <stdarg.h>
34#include <stdbool.h>
35#include <string.h>
36
Chia-I Wu894a1172014-08-04 11:18:20 +080037#include <sys/types.h>
Johannes van Waverena6ce7b72015-10-28 11:45:00 -050038#if defined(_WIN32)
Ian Elliott81ac44c2015-01-13 17:52:38 -070039#include "dirent_on_windows.h"
Johannes van Waverena6ce7b72015-10-28 11:45:00 -050040#else // _WIN32
Chia-I Wu894a1172014-08-04 11:18:20 +080041#include <dirent.h>
Johannes van Waverena6ce7b72015-10-28 11:45:00 -050042#endif // _WIN32
Tobin Ehlis7a51d902015-07-03 10:34:49 -060043#include "vk_loader_platform.h"
Chia-I Wu468e3c32014-08-04 08:03:57 +080044#include "loader.h"
Jon Ashburnfce93d92015-05-12 17:26:48 -060045#include "gpa_helper.h"
46#include "table_ops.h"
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -060047#include "debug_report.h"
Tobin Ehlis2d1d9702015-07-03 09:42:57 -060048#include "vk_icd.h"
Jon Ashburnffd5d672015-06-29 11:25:34 -060049#include "cJSON.h"
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080050
Courtney Goeltzenleuchter71cd74d2015-06-01 14:09:34 -060051static loader_platform_dl_handle loader_add_layer_lib(
Jon Ashburne58f1a32015-08-28 13:38:21 -060052 const struct loader_instance *inst,
Courtney Goeltzenleuchter71cd74d2015-06-01 14:09:34 -060053 const char *chain_type,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -060054 struct loader_layer_properties *layer_prop);
Courtney Goeltzenleuchter71cd74d2015-06-01 14:09:34 -060055
56static void loader_remove_layer_lib(
57 struct loader_instance *inst,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -060058 struct loader_layer_properties *layer_prop);
Courtney Goeltzenleuchter71cd74d2015-06-01 14:09:34 -060059
Jon Ashburnfce93d92015-05-12 17:26:48 -060060struct loader_struct loader = {0};
Jon Ashburn413d6582015-08-28 15:19:27 -060061// TLS for instance for alloc/free callbacks
62THREAD_LOCAL_DECL struct loader_instance *tls_instance;
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080063
Jon Ashburne58f1a32015-08-28 13:38:21 -060064static bool loader_init_ext_list(
65 const struct loader_instance *inst,
66 struct loader_extension_list *ext_info);
Courtney Goeltzenleuchter9a4f38c2015-06-22 17:45:21 -060067
Daniel Dadap2e13fca2015-09-30 11:50:51 -050068static int loader_platform_combine_path(char *dest, int len, ...);
69
Jon Ashburn251258f2015-11-01 14:04:06 -070070struct loader_phys_dev_per_icd {
71 uint32_t count;
72 VkPhysicalDevice *phys_devs;
73};
74
Courtney Goeltzenleuchter8b253f92015-06-08 15:11:18 -060075enum loader_debug {
Courtney Goeltzenleuchter1d4c50f2015-07-08 18:41:08 -060076 LOADER_INFO_BIT = 0x01,
77 LOADER_WARN_BIT = 0x02,
78 LOADER_PERF_BIT = 0x04,
79 LOADER_ERROR_BIT = 0x08,
80 LOADER_DEBUG_BIT = 0x10,
Courtney Goeltzenleuchter8b253f92015-06-08 15:11:18 -060081};
82
83uint32_t g_loader_debug = 0;
84uint32_t g_loader_log_msgs = 0;
85
Jon Ashburnb40f2562015-05-29 13:15:39 -060086//thread safety lock for accessing global data structures such as "loader"
87// all entrypoints on the instance chain need to be locked except GPA
Jon Ashburnffd5d672015-06-29 11:25:34 -060088// additionally CreateDevice and DestroyDevice needs to be locked
Jon Ashburnb40f2562015-05-29 13:15:39 -060089loader_platform_thread_mutex loader_lock;
Jon Ashburnd02fc2c2015-09-22 13:11:00 -060090loader_platform_thread_mutex loader_json_lock;
Jon Ashburnb40f2562015-05-29 13:15:39 -060091
Ian Elliott1d73e662015-07-06 14:36:13 -060092// This table contains the loader's instance dispatch table, which contains
93// default functions if no instance layers are activated. This contains
94// pointers to "terminator functions".
Jon Ashburnb40f2562015-05-29 13:15:39 -060095const VkLayerInstanceDispatchTable instance_disp = {
Jon Ashburn8aa75cb2015-09-28 16:15:00 -060096 .GetInstanceProcAddr = vkGetInstanceProcAddr,
Jon Ashburnfce93d92015-05-12 17:26:48 -060097 .CreateInstance = loader_CreateInstance,
98 .DestroyInstance = loader_DestroyInstance,
99 .EnumeratePhysicalDevices = loader_EnumeratePhysicalDevices,
Chris Forbesd7576302015-06-21 22:55:02 +1200100 .GetPhysicalDeviceFeatures = loader_GetPhysicalDeviceFeatures,
Courtney Goeltzenleuchter4da96aa2015-07-12 12:52:09 -0600101 .GetPhysicalDeviceFormatProperties = loader_GetPhysicalDeviceFormatProperties,
Jon Ashburn4e189562015-07-23 18:49:07 -0600102 .GetPhysicalDeviceImageFormatProperties = loader_GetPhysicalDeviceImageFormatProperties,
Tony Barbour426b9052015-06-24 16:06:58 -0600103 .GetPhysicalDeviceProperties = loader_GetPhysicalDeviceProperties,
Cody Northropef72e2a2015-08-03 17:04:53 -0600104 .GetPhysicalDeviceQueueFamilyProperties = loader_GetPhysicalDeviceQueueFamilyProperties,
Tony Barbour426b9052015-06-24 16:06:58 -0600105 .GetPhysicalDeviceMemoryProperties = loader_GetPhysicalDeviceMemoryProperties,
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -0600106 .EnumerateDeviceExtensionProperties = loader_EnumerateDeviceExtensionProperties,
107 .EnumerateDeviceLayerProperties = loader_EnumerateDeviceLayerProperties,
Mark Lobodzinski83d4e6a2015-07-03 15:58:09 -0600108 .GetPhysicalDeviceSparseImageFormatProperties = loader_GetPhysicalDeviceSparseImageFormatProperties,
Ian Elliott338dedb2015-08-21 15:09:33 -0600109 .GetPhysicalDeviceSurfaceSupportKHR = loader_GetPhysicalDeviceSurfaceSupportKHR,
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600110 .DbgCreateMsgCallback = loader_DbgCreateMsgCallback,
111 .DbgDestroyMsgCallback = loader_DbgDestroyMsgCallback,
Jon Ashburnfce93d92015-05-12 17:26:48 -0600112};
113
Jon Ashburn754f1992015-08-18 18:04:47 -0600114LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_init);
Ian Elliott81ac44c2015-01-13 17:52:38 -0700115
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600116void* loader_heap_alloc(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600117 const struct loader_instance *instance,
118 size_t size,
Chia-I Wu1f851912015-10-27 18:04:07 +0800119 VkSystemAllocationScope alloc_scope)
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600120{
Chia-I Wu1f851912015-10-27 18:04:07 +0800121 if (instance && instance->alloc_callbacks.pfnAllocation) {
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600122 /* TODO: What should default alignment be? 1, 4, 8, other? */
Chia-I Wu1f851912015-10-27 18:04:07 +0800123 return instance->alloc_callbacks.pfnAllocation(instance->alloc_callbacks.pUserData, size, 4, alloc_scope);
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600124 }
125 return malloc(size);
126}
127
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600128void loader_heap_free(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600129 const struct loader_instance *instance,
Chia-I Wu1f851912015-10-27 18:04:07 +0800130 void *pMemory)
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600131{
Chia-I Wu1f851912015-10-27 18:04:07 +0800132 if (pMemory == NULL) return;
Jon Ashburncfe4e682015-08-14 12:51:47 -0600133 if (instance && instance->alloc_callbacks.pfnFree) {
Chia-I Wu1f851912015-10-27 18:04:07 +0800134 instance->alloc_callbacks.pfnFree(instance->alloc_callbacks.pUserData, pMemory);
Jon Ashburnfab6ee22015-08-13 08:28:48 -0600135 return;
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600136 }
Chia-I Wu1f851912015-10-27 18:04:07 +0800137 free(pMemory);
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600138}
139
Jon Ashburne5e60df2015-08-27 15:23:52 -0600140void* loader_heap_realloc(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600141 const struct loader_instance *instance,
Chia-I Wu1f851912015-10-27 18:04:07 +0800142 void *pMemory,
Jon Ashburne5e60df2015-08-27 15:23:52 -0600143 size_t orig_size,
144 size_t size,
Chia-I Wu1f851912015-10-27 18:04:07 +0800145 VkSystemAllocationScope alloc_scope)
Jon Ashburne5e60df2015-08-27 15:23:52 -0600146{
Chia-I Wu1f851912015-10-27 18:04:07 +0800147 if (pMemory == NULL || orig_size == 0)
Chia-I Wu69f40122015-10-26 21:10:41 +0800148 return loader_heap_alloc(instance, size, alloc_scope);
Jon Ashburne5e60df2015-08-27 15:23:52 -0600149 if (size == 0) {
Chia-I Wu1f851912015-10-27 18:04:07 +0800150 loader_heap_free(instance, pMemory);
Jon Ashburne5e60df2015-08-27 15:23:52 -0600151 return NULL;
152 }
Chia-I Wu1f851912015-10-27 18:04:07 +0800153 if (instance && instance->alloc_callbacks.pfnAllocation) {
Jon Ashburne5e60df2015-08-27 15:23:52 -0600154 if (size <= orig_size) {
Chia-I Wu1f851912015-10-27 18:04:07 +0800155 memset(((uint8_t *)pMemory) + size, 0, orig_size - size);
156 return pMemory;
Jon Ashburne5e60df2015-08-27 15:23:52 -0600157 }
Chia-I Wu1f851912015-10-27 18:04:07 +0800158 void *new_ptr = instance->alloc_callbacks.pfnAllocation(instance->alloc_callbacks.pUserData, size, 4, alloc_scope);
Jon Ashburne5e60df2015-08-27 15:23:52 -0600159 if (!new_ptr)
160 return NULL;
Chia-I Wu1f851912015-10-27 18:04:07 +0800161 memcpy(new_ptr, pMemory, orig_size);
162 instance->alloc_callbacks.pfnFree(instance->alloc_callbacks.pUserData, pMemory);
Jon Ashburn37984152015-10-21 16:09:27 -0600163 return new_ptr;
Jon Ashburne5e60df2015-08-27 15:23:52 -0600164 }
Chia-I Wu1f851912015-10-27 18:04:07 +0800165 return realloc(pMemory, size);
Jon Ashburne5e60df2015-08-27 15:23:52 -0600166}
167
Jon Ashburn413d6582015-08-28 15:19:27 -0600168void *loader_tls_heap_alloc(size_t size)
169{
Chia-I Wu1f851912015-10-27 18:04:07 +0800170 return loader_heap_alloc(tls_instance, size, VK_SYSTEM_ALLOCATION_SCOPE_FUNCTION);
Jon Ashburn413d6582015-08-28 15:19:27 -0600171}
172
Chia-I Wu1f851912015-10-27 18:04:07 +0800173void loader_tls_heap_free(void *pMemory)
Jon Ashburn413d6582015-08-28 15:19:27 -0600174{
Chia-I Wu1f851912015-10-27 18:04:07 +0800175 loader_heap_free(tls_instance, pMemory);
Jon Ashburn413d6582015-08-28 15:19:27 -0600176}
177
Jon Ashburnee33ae72015-06-30 14:46:22 -0700178static void loader_log(VkFlags msg_type, int32_t msg_code,
179 const char *format, ...)
180{
Jon Ashburn2b779162015-07-31 15:47:59 -0600181 char msg[512];
Jon Ashburnee33ae72015-06-30 14:46:22 -0700182 va_list ap;
183 int ret;
184
185 if (!(msg_type & g_loader_log_msgs)) {
186 return;
187 }
188
189 va_start(ap, format);
190 ret = vsnprintf(msg, sizeof(msg), format, ap);
191 if ((ret >= (int) sizeof(msg)) || ret < 0) {
192 msg[sizeof(msg)-1] = '\0';
193 }
194 va_end(ap);
195
Ian Elliott225188f2015-02-17 10:33:47 -0700196#if defined(WIN32)
Jon Ashburnee33ae72015-06-30 14:46:22 -0700197 OutputDebugString(msg);
mschott632564c2015-07-22 14:11:29 +0200198 OutputDebugString("\n");
Jon Ashburnee33ae72015-06-30 14:46:22 -0700199#endif
200 fputs(msg, stderr);
201 fputc('\n', stderr);
202}
203
204#if defined(WIN32)
Tony Barbour76096e62015-07-29 14:26:21 -0600205static char *loader_get_next_path(char *path);
Jon Ashburnee33ae72015-06-30 14:46:22 -0700206/**
207* Find the list of registry files (names within a key) in key "location".
208*
209* This function looks in the registry (hive = DEFAULT_VK_REGISTRY_HIVE) key as given in "location"
210* for a list or name/values which are added to a returned list (function return value).
211* The DWORD values within the key must be 0 or they are skipped.
Jon Ashburne58f1a32015-08-28 13:38:21 -0600212* Function return is a string with a ';' separated list of filenames.
Jon Ashburnee33ae72015-06-30 14:46:22 -0700213* Function return is NULL if no valid name/value pairs are found in the key,
214* or the key is not found.
215*
216* \returns
217* A string list of filenames as pointer.
218* When done using the returned string list, pointer should be freed.
219*/
Jon Ashburne58f1a32015-08-28 13:38:21 -0600220static char *loader_get_registry_files(const struct loader_instance *inst, char *location)
Jon Ashburnee33ae72015-06-30 14:46:22 -0700221{
222 LONG rtn_value;
223 HKEY hive, key;
224 DWORD access_flags = KEY_QUERY_VALUE;
225 char name[2048];
226 char *out = NULL;
Tony Barbour76096e62015-07-29 14:26:21 -0600227 char *loc = location;
228 char *next;
Jon Ashburnee33ae72015-06-30 14:46:22 -0700229 DWORD idx = 0;
230 DWORD name_size = sizeof(name);
231 DWORD value;
232 DWORD total_size = 4096;
233 DWORD value_size = sizeof(value);
Tony Barbour76096e62015-07-29 14:26:21 -0600234
235 while(*loc)
236 {
237 next = loader_get_next_path(loc);
238 hive = DEFAULT_VK_REGISTRY_HIVE;
239 rtn_value = RegOpenKeyEx(hive, loc, 0, access_flags, &key);
240 if (rtn_value != ERROR_SUCCESS) {
241 // We didn't find the key. Try the 32-bit hive (where we've seen the
242 // key end up on some people's systems):
243 access_flags |= KEY_WOW64_32KEY;
244 rtn_value = RegOpenKeyEx(hive, loc, 0, access_flags, &key);
245 if (rtn_value != ERROR_SUCCESS) {
246 // We still couldn't find the key, so give up:
247 loc = next;
248 continue;
Jon Ashburnee33ae72015-06-30 14:46:22 -0700249 }
Jon Ashburnee33ae72015-06-30 14:46:22 -0700250 }
Tony Barbour76096e62015-07-29 14:26:21 -0600251
Jon Ashburne58f1a32015-08-28 13:38:21 -0600252 while ((rtn_value = RegEnumValue(key, idx++, name, &name_size, NULL, NULL, (LPBYTE) &value, &value_size)) == ERROR_SUCCESS) {
Tony Barbour76096e62015-07-29 14:26:21 -0600253 if (value_size == sizeof(value) && value == 0) {
254 if (out == NULL) {
Courtney Goeltzenleuchterbed84552015-11-02 17:43:04 -0700255 out = loader_heap_alloc(inst, total_size, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Tony Barbour76096e62015-07-29 14:26:21 -0600256 out[0] = '\0';
257 }
258 else if (strlen(out) + name_size + 1 > total_size) {
Courtney Goeltzenleuchterbed84552015-11-02 17:43:04 -0700259 out = loader_heap_realloc(inst, out, total_size, total_size * 2, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Tony Barbour76096e62015-07-29 14:26:21 -0600260 total_size *= 2;
261 }
262 if (out == NULL) {
263 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory, failed loader_get_registry_files");
264 return NULL;
265 }
266 if (strlen(out) == 0)
267 snprintf(out, name_size + 1, "%s", name);
268 else
269 snprintf(out + strlen(out), name_size + 2, "%c%s", PATH_SEPERATOR, name);
270 }
271 name_size = 2048;
272 }
273 loc = next;
Jon Ashburnee33ae72015-06-30 14:46:22 -0700274 }
Tony Barbour76096e62015-07-29 14:26:21 -0600275
Jon Ashburnee33ae72015-06-30 14:46:22 -0700276 return out;
277}
278
Ian Elliott225188f2015-02-17 10:33:47 -0700279#endif // WIN32
280
Jon Ashburn4b7f35f2015-08-03 09:08:46 -0600281/**
Daniel Dadap2e13fca2015-09-30 11:50:51 -0500282 * Combine path elements, separating each element with the platform-specific
283 * directory separator, and save the combined string to a destination buffer,
284 * not exceeding the given length. Path elements are given as variadic args,
285 * with a NULL element terminating the list.
286 *
287 * \returns the total length of the combined string, not including an ASCII
288 * NUL termination character. This length may exceed the available storage:
289 * in this case, the written string will be truncated to avoid a buffer
290 * overrun, and the return value will greater than or equal to the storage
291 * size. A NULL argument may be provided as the destination buffer in order
292 * to determine the required string length without actually writing a string.
293 */
294
295static int loader_platform_combine_path(char *dest, int len, ...)
296{
297 int required_len = 0;
298 va_list ap;
299 const char *component;
300
301 va_start(ap, len);
302
303 while((component = va_arg(ap, const char *))) {
304 if (required_len > 0) {
305 // This path element is not the first non-empty element; prepend
306 // a directory separator if space allows
307 if (dest && required_len + 1 < len) {
308 snprintf(dest + required_len, len - required_len, "%c",
309 DIRECTORY_SYMBOL);
310 }
311 required_len++;
312 }
313
314 if (dest && required_len < len) {
315 strncpy(dest + required_len, component, len - required_len);
316 }
317 required_len += strlen(component);
318 }
319
320 va_end(ap);
321
322 // strncpy(3) won't add a NUL terminating byte in the event of truncation.
323 if (dest && required_len >= len) {
324 dest[len - 1] = '\0';
325 }
326
327 return required_len;
328}
329
330
331/**
Jon Ashburn4b7f35f2015-08-03 09:08:46 -0600332 * Given string of three part form "maj.min.pat" convert to a vulkan version
333 * number.
334 */
335static uint32_t loader_make_version(const char *vers_str)
336{
Jon Ashburnb8605fe2015-09-18 12:53:16 -0600337 uint32_t vers = 0, major=0, minor=0, patch=0;
Jon Ashburn4b7f35f2015-08-03 09:08:46 -0600338 char *minor_str= NULL;
339 char *patch_str = NULL;
340 char *cstr;
341 char *str;
342
343 if (!vers_str)
344 return vers;
345 cstr = loader_stack_alloc(strlen(vers_str) + 1);
346 strcpy(cstr, vers_str);
347 while ((str = strchr(cstr, '.')) != NULL) {
348 if (minor_str == NULL) {
349 minor_str = str + 1;
350 *str = '\0';
351 major = atoi(cstr);
352 }
353 else if (patch_str == NULL) {
354 patch_str = str + 1;
355 *str = '\0';
356 minor = atoi(minor_str);
357 }
358 else {
359 return vers;
360 }
361 cstr = str + 1;
362 }
363 patch = atoi(patch_str);
364
365 return VK_MAKE_VERSION(major, minor, patch);
366
367}
368
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600369bool compare_vk_extension_properties(const VkExtensionProperties *op1, const VkExtensionProperties *op2)
370{
Chia-I Wu1f851912015-10-27 18:04:07 +0800371 return strcmp(op1->extensionName, op2->extensionName) == 0 ? true : false;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600372}
373
Jon Ashburn1b111de2015-07-06 15:40:35 -0600374/**
Jon Ashburn60378412015-07-02 12:59:25 -0600375 * Search the given ext_array for an extension
376 * matching the given vk_ext_prop
377 */
378bool has_vk_extension_property_array(
379 const VkExtensionProperties *vk_ext_prop,
380 const uint32_t count,
381 const VkExtensionProperties *ext_array)
382{
383 for (uint32_t i = 0; i < count; i++) {
384 if (compare_vk_extension_properties(vk_ext_prop, &ext_array[i]))
385 return true;
386 }
387 return false;
388}
389
Jon Ashburn1b111de2015-07-06 15:40:35 -0600390/**
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600391 * Search the given ext_list for an extension
392 * matching the given vk_ext_prop
393 */
394bool has_vk_extension_property(
395 const VkExtensionProperties *vk_ext_prop,
396 const struct loader_extension_list *ext_list)
397{
398 for (uint32_t i = 0; i < ext_list->count; i++) {
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600399 if (compare_vk_extension_properties(&ext_list->list[i], vk_ext_prop))
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600400 return true;
401 }
402 return false;
403}
404
Jon Ashburn0bf6a182015-07-16 17:19:31 -0600405static inline bool loader_is_layer_type_device(const enum layer_type type) {
406 if ((type & VK_LAYER_TYPE_DEVICE_EXPLICIT) ||
407 (type & VK_LAYER_TYPE_DEVICE_IMPLICIT))
408 return true;
409 return false;
410}
411
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600412/*
Jon Ashburn1b111de2015-07-06 15:40:35 -0600413 * Search the given layer list for a layer matching the given layer name
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600414 */
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600415static struct loader_layer_properties *loader_get_layer_property(
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600416 const char *name,
417 const struct loader_layer_list *layer_list)
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600418{
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600419 for (uint32_t i = 0; i < layer_list->count; i++) {
420 const VkLayerProperties *item = &layer_list->list[i].info;
421 if (strcmp(name, item->layerName) == 0)
422 return &layer_list->list[i];
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600423 }
424 return NULL;
425}
426
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600427/**
428 * Get the next unused layer property in the list. Init the property to zero.
429 */
430static struct loader_layer_properties *loader_get_next_layer_property(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600431 const struct loader_instance *inst,
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600432 struct loader_layer_list *layer_list)
433{
434 if (layer_list->capacity == 0) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600435 layer_list->list = loader_heap_alloc(inst,
436 sizeof(struct loader_layer_properties) * 64,
Chia-I Wu1f851912015-10-27 18:04:07 +0800437 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600438 if (layer_list->list == NULL) {
439 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't add any layer properties to list");
440 return NULL;
441 }
442 memset(layer_list->list, 0, sizeof(struct loader_layer_properties) * 64);
443 layer_list->capacity = sizeof(struct loader_layer_properties) * 64;
444 }
445
446 // ensure enough room to add an entry
447 if ((layer_list->count + 1) * sizeof (struct loader_layer_properties)
448 > layer_list->capacity) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600449 layer_list->list = loader_heap_realloc(inst, layer_list->list,
450 layer_list->capacity,
451 layer_list->capacity * 2,
Chia-I Wu1f851912015-10-27 18:04:07 +0800452 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600453 if (layer_list->list == NULL) {
454 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
455 "realloc failed for layer list");
456 }
457 layer_list->capacity *= 2;
458 }
459
460 layer_list->count++;
461 return &(layer_list->list[layer_list->count - 1]);
462}
463
464/**
465 * Remove all layer properties entrys from the list
466 */
Jon Ashburne58f1a32015-08-28 13:38:21 -0600467void loader_delete_layer_properties(
468 const struct loader_instance *inst,
469 struct loader_layer_list *layer_list)
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600470{
471 uint32_t i;
472
Jon Ashburn182b8302015-08-11 14:49:54 -0600473 if (!layer_list)
474 return;
475
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600476 for (i = 0; i < layer_list->count; i++) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600477 loader_destroy_ext_list(inst, &layer_list->list[i].instance_extension_list);
478 loader_destroy_ext_list(inst, &layer_list->list[i].device_extension_list);
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600479 }
480 layer_list->count = 0;
481
Jon Ashburn182b8302015-08-11 14:49:54 -0600482 if (layer_list->capacity > 0) {
483 layer_list->capacity = 0;
Jon Ashburne58f1a32015-08-28 13:38:21 -0600484 loader_heap_free(inst, layer_list->list);
Jon Ashburn182b8302015-08-11 14:49:54 -0600485 }
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600486
487}
488
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600489static void loader_add_global_extensions(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600490 const struct loader_instance *inst,
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -0600491 const PFN_vkEnumerateInstanceExtensionProperties fp_get_props,
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600492 const char *lib_name,
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600493 struct loader_extension_list *ext_list)
494{
495 uint32_t i, count;
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600496 VkExtensionProperties *ext_props;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600497 VkResult res;
498
Courtney Goeltzenleuchteraa9faab2015-07-06 22:28:18 -0600499 if (!fp_get_props) {
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -0600500 /* No EnumerateInstanceExtensionProperties defined */
Courtney Goeltzenleuchteraa9faab2015-07-06 22:28:18 -0600501 return;
502 }
503
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600504 res = fp_get_props(NULL, &count, NULL);
Jon Ashburneb2728b2015-04-10 14:33:07 -0600505 if (res != VK_SUCCESS) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600506 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Error getting global extension count from %s", lib_name);
Jon Ashburneb2728b2015-04-10 14:33:07 -0600507 return;
508 }
Jon Ashburn60699262015-06-10 16:11:42 -0600509
Courtney Goeltzenleuchteraa9faab2015-07-06 22:28:18 -0600510 if (count == 0) {
511 /* No ExtensionProperties to report */
512 return;
513 }
514
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600515 ext_props = loader_stack_alloc(count * sizeof(VkExtensionProperties));
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600516
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600517 res = fp_get_props(NULL, &count, ext_props);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600518 if (res != VK_SUCCESS) {
519 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Error getting global extensions from %s", lib_name);
520 return;
521 }
Tony Barbour426b9052015-06-24 16:06:58 -0600522
Jon Ashburneb2728b2015-04-10 14:33:07 -0600523 for (i = 0; i < count; i++) {
Courtney Goeltzenleuchter73a21d32015-07-12 13:20:05 -0600524 char spec_version[64];
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600525
526 snprintf(spec_version, sizeof(spec_version), "%d.%d.%d",
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600527 VK_MAJOR(ext_props[i].specVersion),
528 VK_MINOR(ext_props[i].specVersion),
529 VK_PATCH(ext_props[i].specVersion));
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600530 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Courtney Goeltzenleuchter73a21d32015-07-12 13:20:05 -0600531 "Global Extension: %s (%s) version %s",
Chia-I Wu1f851912015-10-27 18:04:07 +0800532 ext_props[i].extensionName, lib_name, spec_version);
Jon Ashburne58f1a32015-08-28 13:38:21 -0600533 loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600534 }
535
536 return;
537}
538
Jon Ashburndb5a5bc2015-11-02 17:40:01 -0700539/*
540 * Initialize ext_list with the physical device extensions.
541 * The extension properties are passed as inputs in count and ext_props.
542 */
543static VkResult loader_init_physical_device_extensions(
544 const struct loader_instance *inst,
545 struct loader_physical_device *phys_dev,
546 uint32_t count,
547 VkExtensionProperties *ext_props,
548 struct loader_extension_list *ext_list)
549{
550 VkResult res;
551 uint32_t i;
552
553 if (!loader_init_ext_list(inst, ext_list)) {
554 return VK_ERROR_OUT_OF_HOST_MEMORY;
555 }
556
557 for (i = 0; i < count; i++) {
558 char spec_version[64];
559
560 snprintf(spec_version, sizeof (spec_version), "%d.%d.%d",
561 VK_MAJOR(ext_props[i].specVersion),
562 VK_MINOR(ext_props[i].specVersion),
563 VK_PATCH(ext_props[i].specVersion));
564 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
565 "PhysicalDevice Extension: %s (%s) version %s",
566 ext_props[i].extensionName, phys_dev->this_icd->this_icd_lib->lib_name, spec_version);
567 res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
568 if (res != VK_SUCCESS)
569 return res;
570 }
571
572 return VK_SUCCESS;
573}
574
Jon Ashburn251258f2015-11-01 14:04:06 -0700575static VkResult loader_add_physical_device_extensions(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600576 const struct loader_instance *inst,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600577 VkPhysicalDevice physical_device,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600578 const char *lib_name,
579 struct loader_extension_list *ext_list)
580{
581 uint32_t i, count;
582 VkResult res;
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600583 VkExtensionProperties *ext_props;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600584
Jon Ashburndb5a5bc2015-11-02 17:40:01 -0700585 res = loader_EnumerateDeviceExtensionProperties(physical_device, NULL, &count, NULL);
586 if (res == VK_SUCCESS && count > 0) {
587 ext_props = loader_stack_alloc(count * sizeof (VkExtensionProperties));
588 if (!ext_props)
589 return VK_ERROR_OUT_OF_HOST_MEMORY;
590 res = loader_EnumerateDeviceExtensionProperties(physical_device, NULL, &count, ext_props);
591 if (res != VK_SUCCESS)
Jon Ashburn251258f2015-11-01 14:04:06 -0700592 return res;
Jon Ashburndb5a5bc2015-11-02 17:40:01 -0700593 for (i = 0; i < count; i++) {
594 char spec_version[64];
595
596 snprintf(spec_version, sizeof (spec_version), "%d.%d.%d",
597 VK_MAJOR(ext_props[i].specVersion),
598 VK_MINOR(ext_props[i].specVersion),
599 VK_PATCH(ext_props[i].specVersion));
600 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
601 "PhysicalDevice Extension: %s (%s) version %s",
602 ext_props[i].extensionName, lib_name, spec_version);
603 res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
604 if (res != VK_SUCCESS)
605 return res;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600606 }
Jon Ashburndb5a5bc2015-11-02 17:40:01 -0700607 } else {
608 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Error getting physical device extension info count from library %s", lib_name);
609 return res;
610 }
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600611
Jon Ashburn251258f2015-11-01 14:04:06 -0700612 return VK_SUCCESS;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600613}
614
Jon Ashburne58f1a32015-08-28 13:38:21 -0600615static bool loader_init_ext_list(const struct loader_instance *inst,
616 struct loader_extension_list *ext_info)
Jon Ashburneb2728b2015-04-10 14:33:07 -0600617{
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600618 ext_info->capacity = 32 * sizeof(VkExtensionProperties);
Chia-I Wu1f851912015-10-27 18:04:07 +0800619 ext_info->list = loader_heap_alloc(inst, ext_info->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600620 if (ext_info->list == NULL) {
621 return false;
622 }
623 memset(ext_info->list, 0, ext_info->capacity);
624 ext_info->count = 0;
625 return true;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600626}
627
Jon Ashburne58f1a32015-08-28 13:38:21 -0600628void loader_destroy_ext_list(const struct loader_instance *inst,
629 struct loader_extension_list *ext_info)
Jon Ashburneb2728b2015-04-10 14:33:07 -0600630{
Jon Ashburne58f1a32015-08-28 13:38:21 -0600631 loader_heap_free(inst, ext_info->list);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600632 ext_info->count = 0;
633 ext_info->capacity = 0;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600634}
Jon Ashburneb2728b2015-04-10 14:33:07 -0600635
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600636/*
637 * Append non-duplicate extension properties defined in props
638 * to the given ext_list.
Jon Ashburn251258f2015-11-01 14:04:06 -0700639 * Return
640 * Vk_SUCCESS on success
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600641 */
Jon Ashburn251258f2015-11-01 14:04:06 -0700642VkResult loader_add_to_ext_list(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600643 const struct loader_instance *inst,
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600644 struct loader_extension_list *ext_list,
645 uint32_t prop_list_count,
646 const VkExtensionProperties *props)
647{
648 uint32_t i;
649 const VkExtensionProperties *cur_ext;
650
651 if (ext_list->list == NULL || ext_list->capacity == 0) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600652 loader_init_ext_list(inst, ext_list);
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600653 }
654
655 if (ext_list->list == NULL)
Jon Ashburn251258f2015-11-01 14:04:06 -0700656 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600657
658 for (i = 0; i < prop_list_count; i++) {
659 cur_ext = &props[i];
660
661 // look for duplicates
662 if (has_vk_extension_property(cur_ext, ext_list)) {
663 continue;
664 }
665
666 // add to list at end
667 // check for enough capacity
668 if (ext_list->count * sizeof(VkExtensionProperties)
669 >= ext_list->capacity) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600670
671 ext_list->list = loader_heap_realloc(inst,
672 ext_list->list,
673 ext_list->capacity,
674 ext_list->capacity * 2,
Chia-I Wu1f851912015-10-27 18:04:07 +0800675 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn251258f2015-11-01 14:04:06 -0700676
677 if (ext_list->list == NULL)
678 return VK_ERROR_OUT_OF_HOST_MEMORY;
679
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600680 // double capacity
681 ext_list->capacity *= 2;
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600682 }
683
684 memcpy(&ext_list->list[ext_list->count], cur_ext, sizeof(VkExtensionProperties));
685 ext_list->count++;
686 }
Jon Ashburn251258f2015-11-01 14:04:06 -0700687 return VK_SUCCESS;
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600688}
689
Jon Ashburn60378412015-07-02 12:59:25 -0600690/**
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600691 * Search the given search_list for any layers in the props list.
692 * Add these to the output layer_list. Don't add duplicates to the output layer_list.
Jon Ashburn60378412015-07-02 12:59:25 -0600693 */
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -0600694static VkResult loader_add_layer_names_to_list(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600695 const struct loader_instance *inst,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600696 struct loader_layer_list *output_list,
697 uint32_t name_count,
698 const char * const *names,
699 const struct loader_layer_list *search_list)
Jon Ashburneb2728b2015-04-10 14:33:07 -0600700{
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600701 struct loader_layer_properties *layer_prop;
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -0600702 VkResult err = VK_SUCCESS;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600703
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600704 for (uint32_t i = 0; i < name_count; i++) {
705 const char *search_target = names[i];
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600706 layer_prop = loader_get_layer_property(search_target, search_list);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600707 if (!layer_prop) {
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -0600708 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Unable to find layer %s", search_target);
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -0600709 err = VK_ERROR_LAYER_NOT_PRESENT;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600710 continue;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600711 }
712
Jon Ashburne58f1a32015-08-28 13:38:21 -0600713 loader_add_to_layer_list(inst, output_list, 1, layer_prop);
Jon Ashburneb2728b2015-04-10 14:33:07 -0600714 }
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -0600715
716 return err;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600717}
718
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600719
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600720/*
721 * Manage lists of VkLayerProperties
722 */
Jon Ashburne58f1a32015-08-28 13:38:21 -0600723static bool loader_init_layer_list(const struct loader_instance *inst,
724 struct loader_layer_list *list)
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600725{
726 list->capacity = 32 * sizeof(struct loader_layer_properties);
Chia-I Wu1f851912015-10-27 18:04:07 +0800727 list->list = loader_heap_alloc(inst, list->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600728 if (list->list == NULL) {
729 return false;
730 }
731 memset(list->list, 0, list->capacity);
732 list->count = 0;
733 return true;
734}
735
Jon Ashburne58f1a32015-08-28 13:38:21 -0600736void loader_destroy_layer_list(const struct loader_instance *inst,
737 struct loader_layer_list *layer_list)
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600738{
Jon Ashburne58f1a32015-08-28 13:38:21 -0600739 loader_heap_free(inst, layer_list->list);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600740 layer_list->count = 0;
741 layer_list->capacity = 0;
742}
743
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600744/*
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600745 * Manage list of layer libraries (loader_lib_info)
746 */
Jon Ashburne58f1a32015-08-28 13:38:21 -0600747static bool loader_init_layer_library_list(const struct loader_instance *inst,
748 struct loader_layer_library_list *list)
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600749{
750 list->capacity = 32 * sizeof(struct loader_lib_info);
Chia-I Wu1f851912015-10-27 18:04:07 +0800751 list->list = loader_heap_alloc(inst, list->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600752 if (list->list == NULL) {
753 return false;
754 }
755 memset(list->list, 0, list->capacity);
756 list->count = 0;
757 return true;
758}
759
Jon Ashburne58f1a32015-08-28 13:38:21 -0600760void loader_destroy_layer_library_list(const struct loader_instance *inst,
761 struct loader_layer_library_list *list)
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600762{
763 for (uint32_t i = 0; i < list->count; i++) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600764 loader_heap_free(inst, list->list[i].lib_name);
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600765 }
Jon Ashburne58f1a32015-08-28 13:38:21 -0600766 loader_heap_free(inst, list->list);
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600767 list->count = 0;
768 list->capacity = 0;
769}
770
771void loader_add_to_layer_library_list(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600772 const struct loader_instance *inst,
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600773 struct loader_layer_library_list *list,
774 uint32_t item_count,
775 const struct loader_lib_info *new_items)
776{
777 uint32_t i;
778 struct loader_lib_info *item;
779
780 if (list->list == NULL || list->capacity == 0) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600781 loader_init_layer_library_list(inst, list);
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600782 }
783
784 if (list->list == NULL)
785 return;
786
787 for (i = 0; i < item_count; i++) {
788 item = (struct loader_lib_info *) &new_items[i];
789
790 // look for duplicates
791 for (uint32_t j = 0; j < list->count; j++) {
792 if (strcmp(list->list[i].lib_name, new_items->lib_name) == 0) {
793 continue;
794 }
795 }
796
797 // add to list at end
798 // check for enough capacity
799 if (list->count * sizeof(struct loader_lib_info)
800 >= list->capacity) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600801
802 list->list = loader_heap_realloc(inst,
803 list->list,
804 list->capacity,
805 list->capacity * 2,
Chia-I Wu1f851912015-10-27 18:04:07 +0800806 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600807 // double capacity
808 list->capacity *= 2;
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600809 }
810
811 memcpy(&list->list[list->count], item, sizeof(struct loader_lib_info));
812 list->count++;
813 }
814}
815
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600816
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600817/*
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600818 * Search the given layer list for a list
819 * matching the given VkLayerProperties
820 */
821bool has_vk_layer_property(
822 const VkLayerProperties *vk_layer_prop,
823 const struct loader_layer_list *list)
824{
825 for (uint32_t i = 0; i < list->count; i++) {
826 if (strcmp(vk_layer_prop->layerName, list->list[i].info.layerName) == 0)
827 return true;
828 }
829 return false;
830}
831
832/*
833 * Search the given layer list for a layer
834 * matching the given name
835 */
836bool has_layer_name(
837 const char *name,
838 const struct loader_layer_list *list)
839{
840 for (uint32_t i = 0; i < list->count; i++) {
841 if (strcmp(name, list->list[i].info.layerName) == 0)
842 return true;
843 }
844 return false;
845}
846
847/*
848 * Append non-duplicate layer properties defined in prop_list
849 * to the given layer_info list
850 */
851void loader_add_to_layer_list(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600852 const struct loader_instance *inst,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600853 struct loader_layer_list *list,
854 uint32_t prop_list_count,
855 const struct loader_layer_properties *props)
856{
857 uint32_t i;
858 struct loader_layer_properties *layer;
859
860 if (list->list == NULL || list->capacity == 0) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600861 loader_init_layer_list(inst, list);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600862 }
863
864 if (list->list == NULL)
865 return;
866
867 for (i = 0; i < prop_list_count; i++) {
868 layer = (struct loader_layer_properties *) &props[i];
869
870 // look for duplicates
871 if (has_vk_layer_property(&layer->info, list)) {
872 continue;
873 }
874
875 // add to list at end
876 // check for enough capacity
877 if (list->count * sizeof(struct loader_layer_properties)
878 >= list->capacity) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600879
880 list->list = loader_heap_realloc(inst,
881 list->list,
882 list->capacity,
883 list->capacity * 2,
Chia-I Wu1f851912015-10-27 18:04:07 +0800884 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600885 // double capacity
886 list->capacity *= 2;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600887 }
888
889 memcpy(&list->list[list->count], layer, sizeof(struct loader_layer_properties));
890 list->count++;
891 }
892}
893
Jon Ashburnf2ddb732015-07-07 10:27:45 -0600894/**
895 * Search the search_list for any layer with a name
896 * that matches the given name and a type that matches the given type
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600897 * Add all matching layers to the found_list
Jon Ashburnf2ddb732015-07-07 10:27:45 -0600898 * Do not add if found loader_layer_properties is already
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600899 * on the found_list.
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600900 */
Jon Ashburn60378412015-07-02 12:59:25 -0600901static void loader_find_layer_name_add_list(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600902 const struct loader_instance *inst,
Jon Ashburn60378412015-07-02 12:59:25 -0600903 const char *name,
Jon Ashburnf2ddb732015-07-07 10:27:45 -0600904 const enum layer_type type,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600905 const struct loader_layer_list *search_list,
906 struct loader_layer_list *found_list)
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600907{
Jon Ashburn87c8fe92015-10-05 09:03:21 -0600908 bool found = false;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600909 for (uint32_t i = 0; i < search_list->count; i++) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600910 struct loader_layer_properties *layer_prop = &search_list->list[i];
Jon Ashburnf2ddb732015-07-07 10:27:45 -0600911 if (0 == strcmp(layer_prop->info.layerName, name) &&
912 (layer_prop->type & type)) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600913 /* Found a layer with the same name, add to found_list */
Jon Ashburne58f1a32015-08-28 13:38:21 -0600914 loader_add_to_layer_list(inst, found_list, 1, layer_prop);
Jon Ashburn87c8fe92015-10-05 09:03:21 -0600915 found = true;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600916 }
917 }
Jon Ashburn87c8fe92015-10-05 09:03:21 -0600918 if (!found) {
919 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Warning, couldn't find layer name %s to activate", name);
920 }
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600921}
922
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600923static VkExtensionProperties *get_extension_property(
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -0600924 const char *name,
925 const struct loader_extension_list *list)
Jon Ashburn42e41032015-04-14 09:15:32 -0600926{
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -0600927 for (uint32_t i = 0; i < list->count; i++) {
Chia-I Wu1f851912015-10-27 18:04:07 +0800928 if (strcmp(name, list->list[i].extensionName) == 0)
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -0600929 return &list->list[i];
Jon Ashburn42e41032015-04-14 09:15:32 -0600930 }
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -0600931 return NULL;
Jon Ashburn42e41032015-04-14 09:15:32 -0600932}
933
Jon Ashburn60378412015-07-02 12:59:25 -0600934/*
935 * For global exenstions implemented within the loader (i.e. DEBUG_REPORT
936 * the extension must provide two entry points for the loader to use:
937 * - "trampoline" entry point - this is the address returned by GetProcAddr
938 * and will always do what's necessary to support a global call.
939 * - "terminator" function - this function will be put at the end of the
940 * instance chain and will contain the necessary logica to call / process
941 * the extension for the appropriate ICDs that are available.
942 * There is no generic mechanism for including these functions, the references
943 * must be placed into the appropriate loader entry points.
944 * GetInstanceProcAddr: call extension GetInstanceProcAddr to check for GetProcAddr requests
945 * loader_coalesce_extensions(void) - add extension records to the list of global
946 * extension available to the app.
947 * instance_disp - add function pointer for terminator function to this array.
948 * The extension itself should be in a separate file that will be
949 * linked directly with the loader.
950 */
Jon Ashburnc1d1eb72015-08-14 11:57:54 -0600951
Jon Ashburn754f1992015-08-18 18:04:47 -0600952void loader_get_icd_loader_instance_extensions(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600953 const struct loader_instance *inst,
Jon Ashburn754f1992015-08-18 18:04:47 -0600954 struct loader_icd_libs *icd_libs,
955 struct loader_extension_list *inst_exts)
Jon Ashburneb2728b2015-04-10 14:33:07 -0600956{
Jon Ashburn85f98072015-08-14 14:49:22 -0600957 struct loader_extension_list icd_exts;
Jon Ashburnc1d1eb72015-08-14 11:57:54 -0600958 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, "Build ICD instance extension list");
Jon Ashburneb2728b2015-04-10 14:33:07 -0600959 // traverse scanned icd list adding non-duplicate extensions to the list
Jon Ashburn754f1992015-08-18 18:04:47 -0600960 for (uint32_t i = 0; i < icd_libs->count; i++) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600961 loader_init_ext_list(inst, &icd_exts);
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -0600962 loader_add_global_extensions(inst, icd_libs->list[i].EnumerateInstanceExtensionProperties,
Jon Ashburn754f1992015-08-18 18:04:47 -0600963 icd_libs->list[i].lib_name,
Jon Ashburn85f98072015-08-14 14:49:22 -0600964 &icd_exts);
Jon Ashburne58f1a32015-08-28 13:38:21 -0600965 loader_add_to_ext_list(inst, inst_exts,
Jon Ashburn85f98072015-08-14 14:49:22 -0600966 icd_exts.count,
967 icd_exts.list);
Jon Ashburne58f1a32015-08-28 13:38:21 -0600968 loader_destroy_ext_list(inst, &icd_exts);
Jon Ashburneb2728b2015-04-10 14:33:07 -0600969 };
970
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600971 // Traverse loader's extensions, adding non-duplicate extensions to the list
Jon Ashburne58f1a32015-08-28 13:38:21 -0600972 wsi_swapchain_add_instance_extensions(inst, inst_exts);
973 debug_report_add_instance_extensions(inst, inst_exts);
Jon Ashburneb2728b2015-04-10 14:33:07 -0600974}
975
Jon Ashburne58f1a32015-08-28 13:38:21 -0600976struct loader_icd *loader_get_icd_and_device(const VkDevice device,
977 struct loader_device **found_dev)
Jon Ashburncb5a5ac2015-06-10 10:06:06 -0600978{
979 *found_dev = NULL;
980 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
981 for (struct loader_icd *icd = inst->icds; icd; icd = icd->next) {
982 for (struct loader_device *dev = icd->logical_device_list; dev; dev = dev->next)
Jon Ashburn0c5eea22015-09-30 12:56:42 -0600983 /* Value comparison of device prevents object wrapping by layers */
984 if (loader_get_dispatch(dev->device) == loader_get_dispatch(device)) {
Jon Ashburncb5a5ac2015-06-10 10:06:06 -0600985 *found_dev = dev;
986 return icd;
987 }
988 }
989 }
990 return NULL;
991}
992
Jon Ashburne58f1a32015-08-28 13:38:21 -0600993static void loader_destroy_logical_device(const struct loader_instance *inst,
994 struct loader_device *dev)
Jon Ashburncb5a5ac2015-06-10 10:06:06 -0600995{
Jon Ashburne58f1a32015-08-28 13:38:21 -0600996 loader_heap_free(inst, dev->app_extension_props);
Jon Ashburncb5a5ac2015-06-10 10:06:06 -0600997 if (dev->activated_layer_list.count)
Jon Ashburne58f1a32015-08-28 13:38:21 -0600998 loader_destroy_layer_list(inst, &dev->activated_layer_list);
999 loader_heap_free(inst, dev);
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06001000}
1001
Jon Ashburne58f1a32015-08-28 13:38:21 -06001002static struct loader_device *loader_add_logical_device(
1003 const struct loader_instance *inst,
1004 const VkDevice dev,
1005 struct loader_device **device_list)
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06001006{
1007 struct loader_device *new_dev;
1008
Chia-I Wu1f851912015-10-27 18:04:07 +08001009 new_dev = loader_heap_alloc(inst, sizeof(struct loader_device), VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06001010 if (!new_dev) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06001011 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc struct laoder-device");
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06001012 return NULL;
1013 }
1014
1015 memset(new_dev, 0, sizeof(struct loader_device));
1016
1017 new_dev->next = *device_list;
1018 new_dev->device = dev;
1019 *device_list = new_dev;
1020 return new_dev;
1021}
1022
Jon Ashburne58f1a32015-08-28 13:38:21 -06001023void loader_remove_logical_device(
1024 const struct loader_instance *inst,
1025 VkDevice device)
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06001026{
1027 struct loader_device *found_dev, *dev, *prev_dev;
1028 struct loader_icd *icd;
1029 icd = loader_get_icd_and_device(device, &found_dev);
1030
1031 if (!icd || !found_dev)
1032 return;
1033
1034 prev_dev = NULL;
1035 dev = icd->logical_device_list;
1036 while (dev && dev != found_dev) {
1037 prev_dev = dev;
1038 dev = dev->next;
1039 }
1040
1041 if (prev_dev)
1042 prev_dev->next = found_dev->next;
1043 else
1044 icd->logical_device_list = found_dev->next;
Jon Ashburne58f1a32015-08-28 13:38:21 -06001045 loader_destroy_logical_device(inst, found_dev);
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06001046}
1047
1048
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001049static void loader_icd_destroy(
1050 struct loader_instance *ptr_inst,
1051 struct loader_icd *icd)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001052{
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001053 ptr_inst->total_icd_count--;
Courtney Goeltzenleuchter6b70e362015-06-14 19:57:15 -06001054 for (struct loader_device *dev = icd->logical_device_list; dev; ) {
1055 struct loader_device *next_dev = dev->next;
Jon Ashburne58f1a32015-08-28 13:38:21 -06001056 loader_destroy_logical_device(ptr_inst, dev);
Courtney Goeltzenleuchter6b70e362015-06-14 19:57:15 -06001057 dev = next_dev;
1058 }
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06001059
Jon Ashburne58f1a32015-08-28 13:38:21 -06001060 loader_heap_free(ptr_inst, icd);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001061}
1062
Jon Ashburne58f1a32015-08-28 13:38:21 -06001063static struct loader_icd * loader_icd_create(const struct loader_instance *inst)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001064{
1065 struct loader_icd *icd;
1066
Chia-I Wu1f851912015-10-27 18:04:07 +08001067 icd = loader_heap_alloc(inst, sizeof(*icd), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001068 if (!icd)
1069 return NULL;
1070
Courtney Goeltzenleuchter6f928162014-10-28 10:29:27 -06001071 memset(icd, 0, sizeof(*icd));
1072
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001073 return icd;
1074}
1075
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001076static struct loader_icd *loader_icd_add(
1077 struct loader_instance *ptr_inst,
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06001078 const struct loader_scanned_icds *icd_lib)
Chia-I Wu894a1172014-08-04 11:18:20 +08001079{
1080 struct loader_icd *icd;
1081
Jon Ashburne58f1a32015-08-28 13:38:21 -06001082 icd = loader_icd_create(ptr_inst);
Chia-I Wu894a1172014-08-04 11:18:20 +08001083 if (!icd)
1084 return NULL;
1085
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06001086 icd->this_icd_lib = icd_lib;
1087 icd->this_instance = ptr_inst;
1088
Chia-I Wu894a1172014-08-04 11:18:20 +08001089 /* prepend to the list */
Jon Ashburn3336df82015-01-29 15:45:51 -07001090 icd->next = ptr_inst->icds;
1091 ptr_inst->icds = icd;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001092 ptr_inst->total_icd_count++;
Chia-I Wu894a1172014-08-04 11:18:20 +08001093
1094 return icd;
1095}
1096
Jon Ashburne58f1a32015-08-28 13:38:21 -06001097void loader_scanned_icd_clear(
1098 const struct loader_instance *inst,
1099 struct loader_icd_libs *icd_libs)
Jon Ashburn754f1992015-08-18 18:04:47 -06001100{
1101 if (icd_libs->capacity == 0)
1102 return;
1103 for (uint32_t i = 0; i < icd_libs->count; i++) {
1104 loader_platform_close_library(icd_libs->list[i].handle);
Jon Ashburne58f1a32015-08-28 13:38:21 -06001105 loader_heap_free(inst, icd_libs->list[i].lib_name);
Jon Ashburn754f1992015-08-18 18:04:47 -06001106 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06001107 loader_heap_free(inst, icd_libs->list);
Jon Ashburn754f1992015-08-18 18:04:47 -06001108 icd_libs->capacity = 0;
1109 icd_libs->count = 0;
1110 icd_libs->list = NULL;
1111}
1112
Jon Ashburne58f1a32015-08-28 13:38:21 -06001113static void loader_scanned_icd_init(const struct loader_instance *inst,
1114 struct loader_icd_libs *icd_libs)
Jon Ashburn754f1992015-08-18 18:04:47 -06001115{
Jon Ashburne58f1a32015-08-28 13:38:21 -06001116 loader_scanned_icd_clear(inst, icd_libs);
Jon Ashburn754f1992015-08-18 18:04:47 -06001117 icd_libs->capacity = 8 * sizeof(struct loader_scanned_icds);
Chia-I Wu1f851912015-10-27 18:04:07 +08001118 icd_libs->list = loader_heap_alloc(inst, icd_libs->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn754f1992015-08-18 18:04:47 -06001119
1120}
1121
1122static void loader_scanned_icd_add(
Jon Ashburne58f1a32015-08-28 13:38:21 -06001123 const struct loader_instance *inst,
Jon Ashburn754f1992015-08-18 18:04:47 -06001124 struct loader_icd_libs *icd_libs,
1125 const char *filename)
Jon Ashburn14275da2015-01-28 11:01:35 -07001126{
Ian Elliott81ac44c2015-01-13 17:52:38 -07001127 loader_platform_dl_handle handle;
Tony Barbourde4124d2015-07-03 10:33:54 -06001128 PFN_vkCreateInstance fp_create_inst;
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -06001129 PFN_vkEnumerateInstanceExtensionProperties fp_get_global_ext_props;
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001130 PFN_vkGetInstanceProcAddr fp_get_proc_addr;
Jon Ashburn14275da2015-01-28 11:01:35 -07001131 struct loader_scanned_icds *new_node;
1132
Jon Ashburn754f1992015-08-18 18:04:47 -06001133 /* TODO implement ref counting of libraries, for now this function leaves
1134 libraries open and the scanned_icd_clear closes them */
Ian Elliott81ac44c2015-01-13 17:52:38 -07001135 // Used to call: dlopen(filename, RTLD_LAZY);
1136 handle = loader_platform_open_library(filename);
Jon Ashburn14275da2015-01-28 11:01:35 -07001137 if (!handle) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001138 loader_log(VK_DBG_REPORT_WARN_BIT, 0, loader_platform_open_library_error(filename));
Jon Ashburn14275da2015-01-28 11:01:35 -07001139 return;
1140 }
1141
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001142#define LOOKUP_LD(func_ptr, func) do { \
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -06001143 func_ptr = (PFN_vk ##func) loader_platform_get_proc_address(handle, "vk" #func); \
Jon Ashburn14275da2015-01-28 11:01:35 -07001144 if (!func_ptr) { \
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001145 loader_log(VK_DBG_REPORT_WARN_BIT, 0, loader_platform_get_proc_address_error("vk" #func)); \
Jon Ashburn14275da2015-01-28 11:01:35 -07001146 return; \
1147 } \
1148} while (0)
1149
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001150 LOOKUP_LD(fp_get_proc_addr, GetInstanceProcAddr);
1151 LOOKUP_LD(fp_create_inst, CreateInstance);
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -06001152 LOOKUP_LD(fp_get_global_ext_props, EnumerateInstanceExtensionProperties);
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001153
1154#undef LOOKUP_LD
Jon Ashburn14275da2015-01-28 11:01:35 -07001155
Jon Ashburn754f1992015-08-18 18:04:47 -06001156 // check for enough capacity
1157 if ((icd_libs->count * sizeof(struct loader_scanned_icds)) >= icd_libs->capacity) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06001158
1159 icd_libs->list = loader_heap_realloc(inst,
1160 icd_libs->list,
1161 icd_libs->capacity,
1162 icd_libs->capacity * 2,
Chia-I Wu1f851912015-10-27 18:04:07 +08001163 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn754f1992015-08-18 18:04:47 -06001164 // double capacity
1165 icd_libs->capacity *= 2;
Jon Ashburn14275da2015-01-28 11:01:35 -07001166 }
Jon Ashburn754f1992015-08-18 18:04:47 -06001167 new_node = &(icd_libs->list[icd_libs->count]);
Jon Ashburn14275da2015-01-28 11:01:35 -07001168
1169 new_node->handle = handle;
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001170 new_node->GetInstanceProcAddr = fp_get_proc_addr;
Jon Ashburn3336df82015-01-29 15:45:51 -07001171 new_node->CreateInstance = fp_create_inst;
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -06001172 new_node->EnumerateInstanceExtensionProperties = fp_get_global_ext_props;
Jon Ashburn14275da2015-01-28 11:01:35 -07001173
Jon Ashburne58f1a32015-08-28 13:38:21 -06001174 new_node->lib_name = (char *) loader_heap_alloc(inst,
1175 strlen(filename) + 1,
Chia-I Wu1f851912015-10-27 18:04:07 +08001176 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001177 if (!new_node->lib_name) {
1178 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Out of memory can't add icd");
1179 return;
1180 }
1181 strcpy(new_node->lib_name, filename);
Jon Ashburn754f1992015-08-18 18:04:47 -06001182 icd_libs->count++;
Jon Ashburneb2728b2015-04-10 14:33:07 -06001183}
Ian Elliott81ac44c2015-01-13 17:52:38 -07001184
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001185static bool loader_icd_init_entrys(struct loader_icd *icd,
1186 VkInstance inst,
1187 const PFN_vkGetInstanceProcAddr fp_gipa)
Jon Ashburn0dd356d2015-05-14 12:43:38 -06001188{
1189 /* initialize entrypoint function pointers */
1190
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001191 #define LOOKUP_GIPA(func, required) do { \
1192 icd->func = (PFN_vk ##func) fp_gipa(inst, "vk" #func); \
1193 if (!icd->func && required) { \
1194 loader_log(VK_DBG_REPORT_WARN_BIT, 0, \
1195 loader_platform_get_proc_address_error("vk" #func)); \
1196 return false; \
1197 } \
Jon Ashburn0dd356d2015-05-14 12:43:38 -06001198 } while (0)
1199
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001200 LOOKUP_GIPA(GetDeviceProcAddr, true);
1201 LOOKUP_GIPA(DestroyInstance, true);
1202 LOOKUP_GIPA(EnumeratePhysicalDevices, true);
1203 LOOKUP_GIPA(GetPhysicalDeviceFeatures, true);
1204 LOOKUP_GIPA(GetPhysicalDeviceFormatProperties, true);
Jon Ashburn4e189562015-07-23 18:49:07 -06001205 LOOKUP_GIPA(GetPhysicalDeviceImageFormatProperties, true);
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001206 LOOKUP_GIPA(CreateDevice, true);
1207 LOOKUP_GIPA(GetPhysicalDeviceProperties, true);
1208 LOOKUP_GIPA(GetPhysicalDeviceMemoryProperties, true);
Cody Northropef72e2a2015-08-03 17:04:53 -06001209 LOOKUP_GIPA(GetPhysicalDeviceQueueFamilyProperties, true);
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -06001210 LOOKUP_GIPA(EnumerateDeviceExtensionProperties, true);
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001211 LOOKUP_GIPA(GetPhysicalDeviceSparseImageFormatProperties, true);
1212 LOOKUP_GIPA(DbgCreateMsgCallback, false);
1213 LOOKUP_GIPA(DbgDestroyMsgCallback, false);
Ian Elliott338dedb2015-08-21 15:09:33 -06001214 LOOKUP_GIPA(GetPhysicalDeviceSurfaceSupportKHR, false);
Jon Ashburn0dd356d2015-05-14 12:43:38 -06001215
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001216#undef LOOKUP_GIPA
Ian Elliott1d73e662015-07-06 14:36:13 -06001217
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001218 return true;
Jon Ashburn0dd356d2015-05-14 12:43:38 -06001219}
1220
Courtney Goeltzenleuchter8b253f92015-06-08 15:11:18 -06001221static void loader_debug_init(void)
1222{
1223 const char *env;
1224
1225 if (g_loader_debug > 0)
1226 return;
1227
1228 g_loader_debug = 0;
1229
1230 /* parse comma-separated debug options */
Courtney Goeltzenleuchter893f2872015-07-29 09:08:22 -06001231 env = getenv("VK_LOADER_DEBUG");
Courtney Goeltzenleuchter8b253f92015-06-08 15:11:18 -06001232 while (env) {
1233 const char *p = strchr(env, ',');
1234 size_t len;
1235
1236 if (p)
1237 len = p - env;
1238 else
1239 len = strlen(env);
1240
1241 if (len > 0) {
1242 if (strncmp(env, "warn", len) == 0) {
1243 g_loader_debug |= LOADER_WARN_BIT;
1244 g_loader_log_msgs |= VK_DBG_REPORT_WARN_BIT;
1245 } else if (strncmp(env, "info", len) == 0) {
1246 g_loader_debug |= LOADER_INFO_BIT;
1247 g_loader_log_msgs |= VK_DBG_REPORT_INFO_BIT;
1248 } else if (strncmp(env, "perf", len) == 0) {
1249 g_loader_debug |= LOADER_PERF_BIT;
1250 g_loader_log_msgs |= VK_DBG_REPORT_PERF_WARN_BIT;
1251 } else if (strncmp(env, "error", len) == 0) {
1252 g_loader_debug |= LOADER_ERROR_BIT;
1253 g_loader_log_msgs |= VK_DBG_REPORT_ERROR_BIT;
1254 } else if (strncmp(env, "debug", len) == 0) {
1255 g_loader_debug |= LOADER_DEBUG_BIT;
1256 g_loader_log_msgs |= VK_DBG_REPORT_DEBUG_BIT;
1257 }
1258 }
1259
1260 if (!p)
1261 break;
1262
1263 env = p + 1;
1264 }
1265}
1266
Jon Ashburn754f1992015-08-18 18:04:47 -06001267void loader_initialize(void)
1268{
Jon Ashburnd02fc2c2015-09-22 13:11:00 -06001269 // initialize mutexs
Jon Ashburn754f1992015-08-18 18:04:47 -06001270 loader_platform_thread_create_mutex(&loader_lock);
Jon Ashburnd02fc2c2015-09-22 13:11:00 -06001271 loader_platform_thread_create_mutex(&loader_json_lock);
Jon Ashburn754f1992015-08-18 18:04:47 -06001272
1273 // initialize logging
1274 loader_debug_init();
Jon Ashburn413d6582015-08-28 15:19:27 -06001275
1276 // initial cJSON to use alloc callbacks
1277 cJSON_Hooks alloc_fns = {
1278 .malloc_fn = loader_tls_heap_alloc,
1279 .free_fn = loader_tls_heap_free,
1280 };
1281 cJSON_InitHooks(&alloc_fns);
Jon Ashburn754f1992015-08-18 18:04:47 -06001282}
1283
Jon Ashburnffd5d672015-06-29 11:25:34 -06001284struct loader_manifest_files {
1285 uint32_t count;
1286 char **filename_list;
1287};
1288
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06001289/**
Jon Ashburnffd5d672015-06-29 11:25:34 -06001290 * Get next file or dirname given a string list or registry key path
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06001291 *
1292 * \returns
Jon Ashburnffd5d672015-06-29 11:25:34 -06001293 * A pointer to first char in the next path.
1294 * The next path (or NULL) in the list is returned in next_path.
1295 * Note: input string is modified in some cases. PASS IN A COPY!
1296 */
Jon Ashburnffd5d672015-06-29 11:25:34 -06001297static char *loader_get_next_path(char *path)
1298{
1299 uint32_t len;
1300 char *next;
1301
1302 if (path == NULL)
1303 return NULL;
1304 next = strchr(path, PATH_SEPERATOR);
1305 if (next == NULL) {
1306 len = (uint32_t) strlen(path);
1307 next = path + len;
1308 }
1309 else {
1310 *next = '\0';
1311 next++;
1312 }
1313
1314 return next;
1315}
1316
1317/**
Daniel Dadap2e13fca2015-09-30 11:50:51 -05001318 * Given a path which is absolute or relative, expand the path if relative or
1319 * leave the path unmodified if absolute. The base path to prepend to relative
1320 * paths is given in rel_base.
Jon Ashburn38144502015-07-07 15:06:25 -06001321 *
1322 * \returns
1323 * A string in out_fullpath of the full absolute path
Jon Ashburn38144502015-07-07 15:06:25 -06001324 */
1325static void loader_expand_path(const char *path,
1326 const char *rel_base,
1327 size_t out_size,
1328 char *out_fullpath)
1329{
1330 if (loader_platform_is_path_absolute(path)) {
Daniel Dadap2e13fca2015-09-30 11:50:51 -05001331 // do not prepend a base to an absolute path
1332 rel_base = "";
Jon Ashburn38144502015-07-07 15:06:25 -06001333 }
Daniel Dadap2e13fca2015-09-30 11:50:51 -05001334
1335 loader_platform_combine_path(out_fullpath, out_size, rel_base, path, NULL);
Jon Ashburn38144502015-07-07 15:06:25 -06001336}
1337
1338/**
Jon Ashburnffd5d672015-06-29 11:25:34 -06001339 * Given a filename (file) and a list of paths (dir), try to find an existing
1340 * file in the paths. If filename already is a path then no
1341 * searching in the given paths.
1342 *
1343 * \returns
1344 * A string in out_fullpath of either the full path or file.
Jon Ashburnffd5d672015-06-29 11:25:34 -06001345 */
1346static void loader_get_fullpath(const char *file,
Daniel Dadap2e13fca2015-09-30 11:50:51 -05001347 const char *dirs,
Jon Ashburnffd5d672015-06-29 11:25:34 -06001348 size_t out_size,
1349 char *out_fullpath)
1350{
Daniel Dadap2e13fca2015-09-30 11:50:51 -05001351 if (!loader_platform_is_path(file) && *dirs) {
1352 char *dirs_copy, *dir, *next_dir;
1353
1354 dirs_copy = loader_stack_alloc(strlen(dirs) + 1);
1355 strcpy(dirs_copy, dirs);
1356
1357 //find if file exists after prepending paths in given list
1358 for (dir = dirs_copy;
1359 *dir && (next_dir = loader_get_next_path(dir));
1360 dir = next_dir) {
1361 loader_platform_combine_path(out_fullpath, out_size, dir, file, NULL);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001362 if (loader_platform_file_exists(out_fullpath)) {
1363 return;
1364 }
Jon Ashburnffd5d672015-06-29 11:25:34 -06001365 }
1366 }
Daniel Dadap2e13fca2015-09-30 11:50:51 -05001367
Jon Ashburnffd5d672015-06-29 11:25:34 -06001368 snprintf(out_fullpath, out_size, "%s", file);
1369}
1370
1371/**
1372 * Read a JSON file into a buffer.
1373 *
1374 * \returns
1375 * A pointer to a cJSON object representing the JSON parse tree.
1376 * This returned buffer should be freed by caller.
1377 */
1378static cJSON *loader_get_json(const char *filename)
1379{
1380 FILE *file;
1381 char *json_buf;
1382 cJSON *json;
1383 uint64_t len;
1384 file = fopen(filename,"rb");
Jon Ashburna01fb3e2015-08-27 08:30:50 -06001385 if (!file) {
1386 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Couldn't open JSON file %s", filename);
1387 return NULL;
1388 }
Jon Ashburnffd5d672015-06-29 11:25:34 -06001389 fseek(file, 0, SEEK_END);
1390 len = ftell(file);
1391 fseek(file, 0, SEEK_SET);
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -06001392 json_buf = (char*) loader_stack_alloc(len+1);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001393 if (json_buf == NULL) {
1394 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get JSON file");
1395 fclose(file);
1396 return NULL;
1397 }
1398 if (fread(json_buf, sizeof(char), len, file) != len) {
1399 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "fread failed can't get JSON file");
1400 fclose(file);
1401 return NULL;
1402 }
1403 fclose(file);
1404 json_buf[len] = '\0';
1405
1406 //parse text from file
1407 json = cJSON_Parse(json_buf);
1408 if (json == NULL)
1409 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Can't parse JSON file %s", filename);
1410 return json;
1411}
1412
1413/**
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06001414 * Do a deep copy of the loader_layer_properties structure.
1415 */
1416static void loader_copy_layer_properties(
Jon Ashburne58f1a32015-08-28 13:38:21 -06001417 const struct loader_instance *inst,
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06001418 struct loader_layer_properties *dst,
1419 struct loader_layer_properties *src)
1420{
1421 memcpy(dst, src, sizeof (*src));
Jon Ashburne58f1a32015-08-28 13:38:21 -06001422 dst->instance_extension_list.list = loader_heap_alloc(
1423 inst,
1424 sizeof(VkExtensionProperties) *
1425 src->instance_extension_list.count,
Chia-I Wu1f851912015-10-27 18:04:07 +08001426 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburne58f1a32015-08-28 13:38:21 -06001427 dst->instance_extension_list.capacity = sizeof(VkExtensionProperties) *
1428 src->instance_extension_list.count;
1429 memcpy(dst->instance_extension_list.list, src->instance_extension_list.list,
1430 dst->instance_extension_list.capacity);
1431 dst->device_extension_list.list = loader_heap_alloc(
1432 inst,
1433 sizeof(VkExtensionProperties) *
1434 src->device_extension_list.count,
Chia-I Wu1f851912015-10-27 18:04:07 +08001435 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburne58f1a32015-08-28 13:38:21 -06001436 dst->device_extension_list.capacity = sizeof(VkExtensionProperties) *
1437 src->device_extension_list.count;
1438 memcpy(dst->device_extension_list.list, src->device_extension_list.list,
1439 dst->device_extension_list.capacity);
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06001440}
1441
1442/**
Jon Ashburn1b111de2015-07-06 15:40:35 -06001443 * Given a cJSON struct (json) of the top level JSON object from layer manifest
1444 * file, add entry to the layer_list.
Jon Ashburn8e4fab42015-08-03 17:19:30 -06001445 * Fill out the layer_properties in this list entry from the input cJSON object.
Jon Ashburn1b111de2015-07-06 15:40:35 -06001446 *
1447 * \returns
1448 * void
1449 * layer_list has a new entry and initialized accordingly.
1450 * If the json input object does not have all the required fields no entry
1451 * is added to the list.
1452 */
Jon Ashburne58f1a32015-08-28 13:38:21 -06001453static void loader_add_layer_properties(const struct loader_instance *inst,
1454 struct loader_layer_list *layer_instance_list,
Jon Ashburn0bf6a182015-07-16 17:19:31 -06001455 struct loader_layer_list *layer_device_list,
Jon Ashburn1b111de2015-07-06 15:40:35 -06001456 cJSON *json,
1457 bool is_implicit,
1458 char *filename)
1459{
1460 /* Fields in layer manifest file that are required:
1461 * (required) “file_format_version”
1462 * following are required in the "layer" object:
1463 * (required) "name"
1464 * (required) "type"
1465 * (required) “library_path”
1466 * (required) “abi_versions”
1467 * (required) “implementation_version”
1468 * (required) “description”
1469 * (required for implicit layers) “disable_environment”
1470 *
1471 * First get all required items and if any missing abort
1472 */
1473
1474 cJSON *item, *layer_node, *ext_item;
1475 char *temp;
1476 char *name, *type, *library_path, *abi_versions;
1477 char *implementation_version, *description;
1478 cJSON *disable_environment;
1479 int i;
Jon Ashburnc4748dc2015-08-04 11:14:18 -06001480 VkExtensionProperties ext_prop;
Jon Ashburn1b111de2015-07-06 15:40:35 -06001481 item = cJSON_GetObjectItem(json, "file_format_version");
1482 if (item == NULL) {
1483 return;
1484 }
1485 char *file_vers = cJSON_PrintUnformatted(item);
1486 loader_log(VK_DBG_REPORT_INFO_BIT, 0, "Found manifest file %s, version %s",
1487 filename, file_vers);
1488 if (strcmp(file_vers, "\"0.9.0\"") != 0)
Jon Ashburn8e4fab42015-08-03 17:19:30 -06001489 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Unexpected manifest file version (expected 0.9.0), may cause errors");
Jon Ashburn413d6582015-08-28 15:19:27 -06001490 loader_tls_heap_free(file_vers);
Jon Ashburn1b111de2015-07-06 15:40:35 -06001491
Jon Ashburn1b111de2015-07-06 15:40:35 -06001492 layer_node = cJSON_GetObjectItem(json, "layer");
1493 if (layer_node == NULL) {
1494 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"layer\" object in manifest JSON file, skipping");
1495 return;
1496 }
Jon Ashburn082569b2015-08-12 16:39:32 -06001497
1498 // loop through all "layer" objects in the file
1499 do {
Jon Ashburn1b111de2015-07-06 15:40:35 -06001500#define GET_JSON_OBJECT(node, var) { \
1501 var = cJSON_GetObjectItem(node, #var); \
Jon Ashburn082569b2015-08-12 16:39:32 -06001502 if (var == NULL) { \
1503 layer_node = layer_node->next; \
1504 continue; \
1505 } \
Jon Ashburn1b111de2015-07-06 15:40:35 -06001506 }
1507#define GET_JSON_ITEM(node, var) { \
1508 item = cJSON_GetObjectItem(node, #var); \
Jon Ashburn082569b2015-08-12 16:39:32 -06001509 if (item == NULL) { \
1510 layer_node = layer_node->next; \
1511 continue; \
1512 } \
Jon Ashburn1b111de2015-07-06 15:40:35 -06001513 temp = cJSON_Print(item); \
1514 temp[strlen(temp) - 1] = '\0'; \
Jon Ashburn0b728052015-08-04 10:22:33 -06001515 var = loader_stack_alloc(strlen(temp) + 1); \
Jon Ashburn1b111de2015-07-06 15:40:35 -06001516 strcpy(var, &temp[1]); \
Jon Ashburn413d6582015-08-28 15:19:27 -06001517 loader_tls_heap_free(temp); \
Jon Ashburn1b111de2015-07-06 15:40:35 -06001518 }
Jon Ashburn082569b2015-08-12 16:39:32 -06001519 GET_JSON_ITEM(layer_node, name)
1520 GET_JSON_ITEM(layer_node, type)
1521 GET_JSON_ITEM(layer_node, library_path)
1522 GET_JSON_ITEM(layer_node, abi_versions)
1523 GET_JSON_ITEM(layer_node, implementation_version)
1524 GET_JSON_ITEM(layer_node, description)
1525 if (is_implicit) {
1526 GET_JSON_OBJECT(layer_node, disable_environment)
1527 }
Jon Ashburn1b111de2015-07-06 15:40:35 -06001528#undef GET_JSON_ITEM
1529#undef GET_JSON_OBJECT
1530
Jon Ashburn082569b2015-08-12 16:39:32 -06001531 // add list entry
Jon Ashburnb8605fe2015-09-18 12:53:16 -06001532 struct loader_layer_properties *props=NULL;
Jon Ashburn082569b2015-08-12 16:39:32 -06001533 if (!strcmp(type, "DEVICE")) {
1534 if (layer_device_list == NULL) {
1535 layer_node = layer_node->next;
1536 continue;
1537 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06001538 props = loader_get_next_layer_property(inst, layer_device_list);
Jon Ashburn082569b2015-08-12 16:39:32 -06001539 props->type = (is_implicit) ? VK_LAYER_TYPE_DEVICE_IMPLICIT : VK_LAYER_TYPE_DEVICE_EXPLICIT;
1540 }
1541 if (!strcmp(type, "INSTANCE")) {
1542 if (layer_instance_list == NULL) {
1543 layer_node = layer_node->next;
1544 continue;
1545 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06001546 props = loader_get_next_layer_property(inst, layer_instance_list);
Jon Ashburn082569b2015-08-12 16:39:32 -06001547 props->type = (is_implicit) ? VK_LAYER_TYPE_INSTANCE_IMPLICIT : VK_LAYER_TYPE_INSTANCE_EXPLICIT;
1548 }
1549 if (!strcmp(type, "GLOBAL")) {
1550 if (layer_instance_list != NULL)
Jon Ashburne58f1a32015-08-28 13:38:21 -06001551 props = loader_get_next_layer_property(inst, layer_instance_list);
Jon Ashburn082569b2015-08-12 16:39:32 -06001552 else if (layer_device_list != NULL)
Jon Ashburne58f1a32015-08-28 13:38:21 -06001553 props = loader_get_next_layer_property(inst, layer_device_list);
Jon Ashburn082569b2015-08-12 16:39:32 -06001554 else {
1555 layer_node = layer_node->next;
1556 continue;
1557 }
1558 props->type = (is_implicit) ? VK_LAYER_TYPE_GLOBAL_IMPLICIT : VK_LAYER_TYPE_GLOBAL_EXPLICIT;
1559 }
Jon Ashburn0bf6a182015-07-16 17:19:31 -06001560
Jon Ashburnb8605fe2015-09-18 12:53:16 -06001561 if (props == NULL) {
1562 layer_node = layer_node->next;
1563 continue;
1564 }
1565
Jon Ashburn082569b2015-08-12 16:39:32 -06001566 strncpy(props->info.layerName, name, sizeof (props->info.layerName));
1567 props->info.layerName[sizeof (props->info.layerName) - 1] = '\0';
Jon Ashburn38144502015-07-07 15:06:25 -06001568
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06001569 char *fullpath = props->lib_name;
Jon Ashburn082569b2015-08-12 16:39:32 -06001570 char *rel_base;
Daniel Dadap2e13fca2015-09-30 11:50:51 -05001571 if (loader_platform_is_path(filename)) {
Jon Ashburn082569b2015-08-12 16:39:32 -06001572 // a relative or absolute path
Daniel Dadap2e13fca2015-09-30 11:50:51 -05001573 char *name_copy = loader_stack_alloc(strlen(filename) + 1);
Jon Ashburn082569b2015-08-12 16:39:32 -06001574 strcpy(name_copy, filename);
1575 rel_base = loader_platform_dirname(name_copy);
Jon Ashburn082569b2015-08-12 16:39:32 -06001576 loader_expand_path(library_path, rel_base, MAX_STRING_SIZE, fullpath);
Daniel Dadap2e13fca2015-09-30 11:50:51 -05001577 } else {
1578 // a filename which is assumed in a system directory
1579 loader_get_fullpath(library_path, DEFAULT_VK_LAYERS_PATH, MAX_STRING_SIZE, fullpath);
Jon Ashburn082569b2015-08-12 16:39:32 -06001580 }
Jon Ashburn082569b2015-08-12 16:39:32 -06001581 props->info.specVersion = loader_make_version(abi_versions);
Chia-I Wu1f851912015-10-27 18:04:07 +08001582 props->info.implementationVersion = loader_make_version(implementation_version);
Jon Ashburn082569b2015-08-12 16:39:32 -06001583 strncpy((char *) props->info.description, description, sizeof (props->info.description));
1584 props->info.description[sizeof (props->info.description) - 1] = '\0';
1585 if (is_implicit) {
1586 strncpy(props->disable_env_var.name, disable_environment->child->string, sizeof (props->disable_env_var.name));
1587 props->disable_env_var.name[sizeof (props->disable_env_var.name) - 1] = '\0';
1588 strncpy(props->disable_env_var.value, disable_environment->child->valuestring, sizeof (props->disable_env_var.value));
1589 props->disable_env_var.value[sizeof (props->disable_env_var.value) - 1] = '\0';
1590 }
Jon Ashburn1b111de2015-07-06 15:40:35 -06001591
Jon Ashburn082569b2015-08-12 16:39:32 -06001592 /**
1593 * Now get all optional items and objects and put in list:
1594 * functions
1595 * instance_extensions
1596 * device_extensions
1597 * enable_environment (implicit layers only)
1598 */
Jon Ashburn1b111de2015-07-06 15:40:35 -06001599#define GET_JSON_OBJECT(node, var) { \
1600 var = cJSON_GetObjectItem(node, #var); \
1601 }
1602#define GET_JSON_ITEM(node, var) { \
1603 item = cJSON_GetObjectItem(node, #var); \
Jon Ashburn2db08042015-09-09 11:29:24 -06001604 if (item != NULL) { \
Jon Ashburn1b111de2015-07-06 15:40:35 -06001605 temp = cJSON_Print(item); \
Jon Ashburn2db08042015-09-09 11:29:24 -06001606 temp[strlen(temp) - 1] = '\0'; \
1607 var = loader_stack_alloc(strlen(temp) + 1);\
1608 strcpy(var, &temp[1]); \
1609 loader_tls_heap_free(temp); \
1610 } \
Jon Ashburn1b111de2015-07-06 15:40:35 -06001611 }
1612
Jon Ashburn082569b2015-08-12 16:39:32 -06001613 cJSON *instance_extensions, *device_extensions, *functions, *enable_environment;
Jon Ashburnb8605fe2015-09-18 12:53:16 -06001614 char *vkGetInstanceProcAddr = NULL, *vkGetDeviceProcAddr = NULL, *version=NULL;
Jon Ashburn082569b2015-08-12 16:39:32 -06001615 GET_JSON_OBJECT(layer_node, functions)
1616 if (functions != NULL) {
1617 GET_JSON_ITEM(functions, vkGetInstanceProcAddr)
1618 GET_JSON_ITEM(functions, vkGetDeviceProcAddr)
Jon Ashburn2db08042015-09-09 11:29:24 -06001619 if (vkGetInstanceProcAddr != NULL)
1620 strncpy(props->functions.str_gipa, vkGetInstanceProcAddr, sizeof (props->functions.str_gipa));
Jon Ashburn082569b2015-08-12 16:39:32 -06001621 props->functions.str_gipa[sizeof (props->functions.str_gipa) - 1] = '\0';
Jon Ashburn2db08042015-09-09 11:29:24 -06001622 if (vkGetDeviceProcAddr != NULL)
1623 strncpy(props->functions.str_gdpa, vkGetDeviceProcAddr, sizeof (props->functions.str_gdpa));
Jon Ashburn082569b2015-08-12 16:39:32 -06001624 props->functions.str_gdpa[sizeof (props->functions.str_gdpa) - 1] = '\0';
Jon Ashburn1b111de2015-07-06 15:40:35 -06001625 }
Jon Ashburn082569b2015-08-12 16:39:32 -06001626 GET_JSON_OBJECT(layer_node, instance_extensions)
1627 if (instance_extensions != NULL) {
1628 int count = cJSON_GetArraySize(instance_extensions);
1629 for (i = 0; i < count; i++) {
1630 ext_item = cJSON_GetArrayItem(instance_extensions, i);
1631 GET_JSON_ITEM(ext_item, name)
1632 GET_JSON_ITEM(ext_item, version)
Chia-I Wu1f851912015-10-27 18:04:07 +08001633 strncpy(ext_prop.extensionName, name, sizeof (ext_prop.extensionName));
1634 ext_prop.extensionName[sizeof (ext_prop.extensionName) - 1] = '\0';
Jon Ashburn082569b2015-08-12 16:39:32 -06001635 ext_prop.specVersion = loader_make_version(version);
Jon Ashburne58f1a32015-08-28 13:38:21 -06001636 loader_add_to_ext_list(inst, &props->instance_extension_list, 1, &ext_prop);
Jon Ashburn082569b2015-08-12 16:39:32 -06001637 }
Jon Ashburn1b111de2015-07-06 15:40:35 -06001638 }
Jon Ashburn082569b2015-08-12 16:39:32 -06001639 GET_JSON_OBJECT(layer_node, device_extensions)
1640 if (device_extensions != NULL) {
1641 int count = cJSON_GetArraySize(device_extensions);
1642 for (i = 0; i < count; i++) {
1643 ext_item = cJSON_GetArrayItem(device_extensions, i);
1644 GET_JSON_ITEM(ext_item, name);
1645 GET_JSON_ITEM(ext_item, version);
Chia-I Wu1f851912015-10-27 18:04:07 +08001646 strncpy(ext_prop.extensionName, name, sizeof (ext_prop.extensionName));
1647 ext_prop.extensionName[sizeof (ext_prop.extensionName) - 1] = '\0';
Jon Ashburn082569b2015-08-12 16:39:32 -06001648 ext_prop.specVersion = loader_make_version(version);
Jon Ashburne58f1a32015-08-28 13:38:21 -06001649 loader_add_to_ext_list(inst, &props->device_extension_list, 1, &ext_prop);
Jon Ashburn082569b2015-08-12 16:39:32 -06001650 }
1651 }
1652 if (is_implicit) {
1653 GET_JSON_OBJECT(layer_node, enable_environment)
1654 strncpy(props->enable_env_var.name, enable_environment->child->string, sizeof (props->enable_env_var.name));
1655 props->enable_env_var.name[sizeof (props->enable_env_var.name) - 1] = '\0';
1656 strncpy(props->enable_env_var.value, enable_environment->child->valuestring, sizeof (props->enable_env_var.value));
1657 props->enable_env_var.value[sizeof (props->enable_env_var.value) - 1] = '\0';
1658 }
Jon Ashburn1b111de2015-07-06 15:40:35 -06001659#undef GET_JSON_ITEM
1660#undef GET_JSON_OBJECT
Jon Ashburn082569b2015-08-12 16:39:32 -06001661 // for global layers need to add them to both device and instance list
1662 if (!strcmp(type, "GLOBAL")) {
1663 struct loader_layer_properties *dev_props;
1664 if (layer_instance_list == NULL || layer_device_list == NULL) {
1665 layer_node = layer_node->next;
1666 continue;
1667 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06001668 dev_props = loader_get_next_layer_property(inst, layer_device_list);
Jon Ashburn082569b2015-08-12 16:39:32 -06001669 //copy into device layer list
Jon Ashburne58f1a32015-08-28 13:38:21 -06001670 loader_copy_layer_properties(inst, dev_props, props);
Jon Ashburn082569b2015-08-12 16:39:32 -06001671 }
1672 layer_node = layer_node->next;
1673 } while (layer_node != NULL);
1674 return;
Jon Ashburn1b111de2015-07-06 15:40:35 -06001675}
1676
1677/**
Jon Ashburnffd5d672015-06-29 11:25:34 -06001678 * Find the Vulkan library manifest files.
1679 *
1680 * This function scans the location or env_override directories/files
1681 * for a list of JSON manifest files. If env_override is non-NULL
1682 * and has a valid value. Then the location is ignored. Otherwise
1683 * location is used to look for manifest files. The location
1684 * is interpreted as Registry path on Windows and a directory path(s)
1685 * on Linux.
1686 *
1687 * \returns
1688 * A string list of manifest files to be opened in out_files param.
1689 * List has a pointer to string for each manifest filename.
1690 * When done using the list in out_files, pointers should be freed.
Jon Ashburnee33ae72015-06-30 14:46:22 -07001691 * Location or override string lists can be either files or directories as follows:
1692 * | location | override
1693 * --------------------------------
1694 * Win ICD | files | files
1695 * Win Layer | files | dirs
1696 * Linux ICD | dirs | files
1697 * Linux Layer| dirs | dirs
Jon Ashburnffd5d672015-06-29 11:25:34 -06001698 */
Jon Ashburne58f1a32015-08-28 13:38:21 -06001699static void loader_get_manifest_files(const struct loader_instance *inst,
1700 const char *env_override,
Jon Ashburnee33ae72015-06-30 14:46:22 -07001701 bool is_layer,
1702 const char *location,
1703 struct loader_manifest_files *out_files)
Jon Ashburnffd5d672015-06-29 11:25:34 -06001704{
1705 char *override = NULL;
1706 char *loc;
1707 char *file, *next_file, *name;
1708 size_t alloced_count = 64;
1709 char full_path[2048];
1710 DIR *sysdir = NULL;
Jon Ashburnee33ae72015-06-30 14:46:22 -07001711 bool list_is_dirs = false;
Jon Ashburnffd5d672015-06-29 11:25:34 -06001712 struct dirent *dent;
1713
1714 out_files->count = 0;
1715 out_files->filename_list = NULL;
1716
Jon Ashburnffd5d672015-06-29 11:25:34 -06001717 if (env_override != NULL && (override = getenv(env_override))) {
Johannes van Waverena6ce7b72015-10-28 11:45:00 -05001718#if !defined(_WIN32)
Jon Ashburnffd5d672015-06-29 11:25:34 -06001719 if (geteuid() != getuid()) {
Jon Ashburnee33ae72015-06-30 14:46:22 -07001720 /* Don't allow setuid apps to use the env var: */
Jon Ashburnffd5d672015-06-29 11:25:34 -06001721 override = NULL;
1722 }
1723#endif
1724 }
1725
1726 if (location == NULL) {
1727 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
Jon Ashburnee33ae72015-06-30 14:46:22 -07001728 "Can't get manifest files with NULL location, env_override=%s",
1729 env_override);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001730 return;
1731 }
1732
Johannes van Waverena6ce7b72015-10-28 11:45:00 -05001733#if defined(_WIN32)
Jon Ashburnee33ae72015-06-30 14:46:22 -07001734 list_is_dirs = (is_layer && override != NULL) ? true : false;
Johannes van Waverena6ce7b72015-10-28 11:45:00 -05001735#else
1736 list_is_dirs = (override == NULL || is_layer) ? true : false;
Jon Ashburnee33ae72015-06-30 14:46:22 -07001737#endif
Jon Ashburnffd5d672015-06-29 11:25:34 -06001738 // Make a copy of the input we are using so it is not modified
Jon Ashburnee33ae72015-06-30 14:46:22 -07001739 // Also handle getting the location(s) from registry on Windows
1740 if (override == NULL) {
Jon Ashburncdc9f0a2015-07-31 10:11:24 -06001741 loc = loader_stack_alloc(strlen(location) + 1);
Jon Ashburnee33ae72015-06-30 14:46:22 -07001742 if (loc == NULL) {
1743 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files");
1744 return;
1745 }
1746 strcpy(loc, location);
Johannes van Waverena6ce7b72015-10-28 11:45:00 -05001747#if defined(_WIN32)
Jon Ashburn6fb9a532015-08-28 14:58:46 -07001748 loc = loader_get_registry_files(inst, loc);
Jon Ashburnc1381ed2015-07-31 09:33:21 -06001749 if (loc == NULL) {
1750 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Registry lookup failed can't get manifest files");
1751 return;
1752 }
Jon Ashburnee33ae72015-06-30 14:46:22 -07001753#endif
Jon Ashburnffd5d672015-06-29 11:25:34 -06001754 }
Jon Ashburnee33ae72015-06-30 14:46:22 -07001755 else {
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -06001756 loc = loader_stack_alloc(strlen(override) + 1);
Jon Ashburnee33ae72015-06-30 14:46:22 -07001757 if (loc == NULL) {
1758 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files");
1759 return;
1760 }
1761 strcpy(loc, override);
1762 }
Jon Ashburnffd5d672015-06-29 11:25:34 -06001763
Liam Middlebrookf2a6ec42015-07-23 18:32:20 -07001764 // Print out the paths being searched if debugging is enabled
Jon Ashburn6ff63e42015-07-31 09:41:31 -06001765 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, "Searching the following paths for manifest files: %s\n", loc);
Liam Middlebrookf2a6ec42015-07-23 18:32:20 -07001766
Jon Ashburnffd5d672015-06-29 11:25:34 -06001767 file = loc;
1768 while (*file) {
1769 next_file = loader_get_next_path(file);
Jon Ashburnee33ae72015-06-30 14:46:22 -07001770 if (list_is_dirs) {
Jon Ashburnffd5d672015-06-29 11:25:34 -06001771 sysdir = opendir(file);
1772 name = NULL;
1773 if (sysdir) {
1774 dent = readdir(sysdir);
1775 if (dent == NULL)
1776 break;
1777 name = &(dent->d_name[0]);
1778 loader_get_fullpath(name, file, sizeof(full_path), full_path);
1779 name = full_path;
1780 }
1781 }
1782 else {
Johannes van Waverena6ce7b72015-10-28 11:45:00 -05001783#if defined(_WIN32)
1784 name = file;
1785#else
Jon Ashburnee33ae72015-06-30 14:46:22 -07001786 // only Linux has relative paths
Jon Ashburnffd5d672015-06-29 11:25:34 -06001787 char *dir;
1788 // make a copy of location so it isn't modified
Jason Ekstrand35fa1a12015-10-10 08:33:37 -07001789 dir = loader_stack_alloc(strlen(loc) + 1);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001790 if (dir == NULL) {
1791 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files");
1792 return;
1793 }
Jason Ekstrand35fa1a12015-10-10 08:33:37 -07001794 strcpy(dir, loc);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001795
1796 loader_get_fullpath(file, dir, sizeof(full_path), full_path);
1797
1798 name = full_path;
Jon Ashburnee33ae72015-06-30 14:46:22 -07001799#endif
Jon Ashburnffd5d672015-06-29 11:25:34 -06001800 }
1801 while (name) {
1802 /* Look for files ending with ".json" suffix */
1803 uint32_t nlen = (uint32_t) strlen(name);
1804 const char *suf = name + nlen - 5;
1805 if ((nlen > 5) && !strncmp(suf, ".json", 5)) {
1806 if (out_files->count == 0) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06001807 out_files->filename_list = loader_heap_alloc(inst,
1808 alloced_count * sizeof(char *),
Chia-I Wu1f851912015-10-27 18:04:07 +08001809 VK_SYSTEM_ALLOCATION_SCOPE_FUNCTION);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001810 }
1811 else if (out_files->count == alloced_count) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06001812 out_files->filename_list = loader_heap_realloc(inst,
1813 out_files->filename_list,
1814 alloced_count * sizeof(char *),
1815 alloced_count * sizeof(char *) * 2,
Chia-I Wu1f851912015-10-27 18:04:07 +08001816 VK_SYSTEM_ALLOCATION_SCOPE_FUNCTION);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001817 alloced_count *= 2;
1818 }
1819 if (out_files->filename_list == NULL) {
1820 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't alloc manifest file list");
1821 return;
1822 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06001823 out_files->filename_list[out_files->count] = loader_heap_alloc(
1824 inst,
1825 strlen(name) + 1,
Chia-I Wu1f851912015-10-27 18:04:07 +08001826 VK_SYSTEM_ALLOCATION_SCOPE_FUNCTION);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001827 if (out_files->filename_list[out_files->count] == NULL) {
1828 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files");
1829 return;
1830 }
1831 strcpy(out_files->filename_list[out_files->count], name);
1832 out_files->count++;
Jon Ashburnc5662f62015-07-02 10:08:47 -06001833 } else if (!list_is_dirs) {
1834 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Skipping manifest file %s, file name must end in .json", name);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001835 }
Jon Ashburnee33ae72015-06-30 14:46:22 -07001836 if (list_is_dirs) {
Jon Ashburnffd5d672015-06-29 11:25:34 -06001837 dent = readdir(sysdir);
1838 if (dent == NULL)
1839 break;
1840 name = &(dent->d_name[0]);
1841 loader_get_fullpath(name, file, sizeof(full_path), full_path);
1842 name = full_path;
1843 }
1844 else {
1845 break;
1846 }
1847 }
1848 if (sysdir)
1849 closedir(sysdir);
1850 file = next_file;
1851 }
1852 return;
1853}
1854
Jon Ashburn754f1992015-08-18 18:04:47 -06001855void loader_init_icd_lib_list()
1856{
1857
1858}
1859
1860void loader_destroy_icd_lib_list()
1861{
1862
1863}
Jon Ashburnffd5d672015-06-29 11:25:34 -06001864/**
1865 * Try to find the Vulkan ICD driver(s).
1866 *
1867 * This function scans the default system loader path(s) or path
1868 * specified by the \c VK_ICD_FILENAMES environment variable in
1869 * order to find loadable VK ICDs manifest files. From these
1870 * manifest files it finds the ICD libraries.
1871 *
1872 * \returns
Jon Ashburn754f1992015-08-18 18:04:47 -06001873 * a list of icds that were discovered
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06001874 */
Jon Ashburne58f1a32015-08-28 13:38:21 -06001875void loader_icd_scan(
1876 const struct loader_instance *inst,
1877 struct loader_icd_libs *icds)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001878{
Jon Ashburnffd5d672015-06-29 11:25:34 -06001879 char *file_str;
1880 struct loader_manifest_files manifest_files;
1881
Jon Ashburne58f1a32015-08-28 13:38:21 -06001882 loader_scanned_icd_init(inst, icds);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001883 // Get a list of manifest files for ICDs
Jon Ashburne58f1a32015-08-28 13:38:21 -06001884 loader_get_manifest_files(inst, "VK_ICD_FILENAMES", false,
1885 DEFAULT_VK_DRIVERS_INFO, &manifest_files);
Jon Ashburn1b111de2015-07-06 15:40:35 -06001886 if (manifest_files.count == 0)
1887 return;
Jon Ashburnd02fc2c2015-09-22 13:11:00 -06001888 loader_platform_thread_lock_mutex(&loader_json_lock);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001889 for (uint32_t i = 0; i < manifest_files.count; i++) {
1890 file_str = manifest_files.filename_list[i];
1891 if (file_str == NULL)
1892 continue;
1893
Jon Ashburn1b111de2015-07-06 15:40:35 -06001894 cJSON *json;
Jon Ashburnffd5d672015-06-29 11:25:34 -06001895 json = loader_get_json(file_str);
Jon Ashburna01fb3e2015-08-27 08:30:50 -06001896 if (!json)
1897 continue;
Jon Ashburn1b111de2015-07-06 15:40:35 -06001898 cJSON *item;
1899 item = cJSON_GetObjectItem(json, "file_format_version");
Jon Ashburnd02fc2c2015-09-22 13:11:00 -06001900 if (item == NULL) {
1901 loader_platform_thread_unlock_mutex(&loader_json_lock);
Jon Ashburn1b111de2015-07-06 15:40:35 -06001902 return;
Jon Ashburnd02fc2c2015-09-22 13:11:00 -06001903 }
Jon Ashburn1b111de2015-07-06 15:40:35 -06001904 char *file_vers = cJSON_Print(item);
1905 loader_log(VK_DBG_REPORT_INFO_BIT, 0, "Found manifest file %s, version %s",
1906 file_str, file_vers);
1907 if (strcmp(file_vers, "\"1.0.0\"") != 0)
1908 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Unexpected manifest file version (expected 1.0.0), may cause errors");
Jon Ashburn413d6582015-08-28 15:19:27 -06001909 loader_tls_heap_free(file_vers);
Jon Ashburn1b111de2015-07-06 15:40:35 -06001910 item = cJSON_GetObjectItem(json, "ICD");
1911 if (item != NULL) {
1912 item = cJSON_GetObjectItem(item, "library_path");
1913 if (item != NULL) {
Jon Ashburn10442c12015-08-25 16:48:24 -06001914 char *temp= cJSON_Print(item);
1915 if (!temp || strlen(temp) == 0) {
1916 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"library_path\" in ICD JSON file %s, skipping", file_str);
Jon Ashburn413d6582015-08-28 15:19:27 -06001917 loader_tls_heap_free(temp);
Jon Ashburne58f1a32015-08-28 13:38:21 -06001918 loader_heap_free(inst, file_str);
Jon Ashburn10442c12015-08-25 16:48:24 -06001919 cJSON_Delete(json);
1920 continue;
Jon Ashburnffd5d672015-06-29 11:25:34 -06001921 }
Jon Ashburn10442c12015-08-25 16:48:24 -06001922 //strip out extra quotes
1923 temp[strlen(temp) - 1] = '\0';
1924 char *library_path = loader_stack_alloc(strlen(temp) + 1);
1925 strcpy(library_path, &temp[1]);
Jon Ashburn413d6582015-08-28 15:19:27 -06001926 loader_tls_heap_free(temp);
Jon Ashburn10442c12015-08-25 16:48:24 -06001927 if (!library_path || strlen(library_path) == 0) {
1928 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"library_path\" in ICD JSON file %s, skipping", file_str);
Jon Ashburne58f1a32015-08-28 13:38:21 -06001929 loader_heap_free(inst, file_str);
Jon Ashburn10442c12015-08-25 16:48:24 -06001930 cJSON_Delete(json);
1931 continue;
1932 }
Daniel Dadap2e13fca2015-09-30 11:50:51 -05001933 char fullpath[MAX_STRING_SIZE];
Jon Ashburn10442c12015-08-25 16:48:24 -06001934 // Print out the paths being searched if debugging is enabled
1935 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, "Searching for ICD drivers named %s default dir %s\n", library_path, DEFAULT_VK_DRIVERS_PATH);
Daniel Dadap2e13fca2015-09-30 11:50:51 -05001936 if (loader_platform_is_path(library_path)) {
Jon Ashburn10442c12015-08-25 16:48:24 -06001937 // a relative or absolute path
Daniel Dadap2e13fca2015-09-30 11:50:51 -05001938 char *name_copy = loader_stack_alloc(strlen(file_str) + 1);
1939 char *rel_base;
Jon Ashburn10442c12015-08-25 16:48:24 -06001940 strcpy(name_copy, file_str);
1941 rel_base = loader_platform_dirname(name_copy);
Daniel Dadap2e13fca2015-09-30 11:50:51 -05001942 loader_expand_path(library_path, rel_base, sizeof(fullpath), fullpath);
1943 } else {
1944 // a filename which is assumed in a system directory
1945 loader_get_fullpath(library_path, DEFAULT_VK_DRIVERS_PATH, sizeof(fullpath), fullpath);
Jon Ashburn10442c12015-08-25 16:48:24 -06001946 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06001947 loader_scanned_icd_add(inst, icds, fullpath);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001948 }
Jon Ashburnffd5d672015-06-29 11:25:34 -06001949 }
1950 else
1951 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"ICD\" object in ICD JSON file %s, skipping", file_str);
1952
Jon Ashburne58f1a32015-08-28 13:38:21 -06001953 loader_heap_free(inst, file_str);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001954 cJSON_Delete(json);
1955 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06001956 loader_heap_free(inst, manifest_files.filename_list);
Jon Ashburnd02fc2c2015-09-22 13:11:00 -06001957 loader_platform_thread_unlock_mutex(&loader_json_lock);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001958}
1959
Jon Ashburnd43f9b62014-10-14 19:15:22 -06001960
Jon Ashburne58f1a32015-08-28 13:38:21 -06001961void loader_layer_scan(
1962 const struct loader_instance *inst,
1963 struct loader_layer_list *instance_layers,
1964 struct loader_layer_list *device_layers)
Jon Ashburnd43f9b62014-10-14 19:15:22 -06001965{
Jon Ashburn1b111de2015-07-06 15:40:35 -06001966 char *file_str;
1967 struct loader_manifest_files manifest_files;
1968 cJSON *json;
1969 uint32_t i;
Jon Ashburnd43f9b62014-10-14 19:15:22 -06001970
Jon Ashburn1b111de2015-07-06 15:40:35 -06001971 // Get a list of manifest files for layers
Jon Ashburne58f1a32015-08-28 13:38:21 -06001972 loader_get_manifest_files(inst, LAYERS_PATH_ENV, true, DEFAULT_VK_LAYERS_INFO,
Jon Ashburn1b111de2015-07-06 15:40:35 -06001973 &manifest_files);
1974 if (manifest_files.count == 0)
Courtney Goeltzenleuchterbce445a2014-12-01 09:29:42 -07001975 return;
Jon Ashburn0dcd6192015-06-04 15:30:58 -06001976
Jon Ashburn8e4fab42015-08-03 17:19:30 -06001977#if 0 //TODO
Jon Ashburn1b111de2015-07-06 15:40:35 -06001978 /**
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -06001979 * We need a list of the layer libraries, not just a list of
1980 * the layer properties (a layer library could expose more than
1981 * one layer property). This list of scanned layers would be
1982 * used to check for global and physicaldevice layer properties.
1983 */
1984 if (!loader_init_layer_library_list(&loader.scanned_layer_libraries)) {
1985 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
Jon Ashburne58f1a32015-08-28 13:38:21 -06001986 "Alloc for layer list failed: %s line: %d", __FILE__, __LINE__);
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -06001987 return;
Jon Ashburn68a63922015-07-02 09:40:15 -06001988 }
Jon Ashburn1b111de2015-07-06 15:40:35 -06001989#endif
Jon Ashburnd43f9b62014-10-14 19:15:22 -06001990
Jon Ashburn8e4fab42015-08-03 17:19:30 -06001991 /* cleanup any previously scanned libraries */
Jon Ashburne58f1a32015-08-28 13:38:21 -06001992 loader_delete_layer_properties(inst, instance_layers);
1993 loader_delete_layer_properties(inst, device_layers);
Jon Ashburn0bf6a182015-07-16 17:19:31 -06001994
Jon Ashburnd02fc2c2015-09-22 13:11:00 -06001995 loader_platform_thread_lock_mutex(&loader_json_lock);
Jon Ashburn1b111de2015-07-06 15:40:35 -06001996 for (i = 0; i < manifest_files.count; i++) {
1997 file_str = manifest_files.filename_list[i];
1998 if (file_str == NULL)
1999 continue;
Courtney Goeltzenleuchteraa685052015-06-01 14:49:17 -06002000
Jon Ashburn1b111de2015-07-06 15:40:35 -06002001 // parse file into JSON struct
2002 json = loader_get_json(file_str);
2003 if (!json) {
2004 continue;
2005 }
Jon Ashburn8e4fab42015-08-03 17:19:30 -06002006
Jon Ashburn1b111de2015-07-06 15:40:35 -06002007 //TODO pass in implicit versus explicit bool
Jon Ashburn0bf6a182015-07-16 17:19:31 -06002008 //TODO error if device layers expose instance_extensions
2009 //TODO error if instance layers expose device extensions
Jon Ashburne58f1a32015-08-28 13:38:21 -06002010 loader_add_layer_properties(inst,
2011 instance_layers,
Jon Ashburn182b8302015-08-11 14:49:54 -06002012 device_layers,
Jon Ashburn0bf6a182015-07-16 17:19:31 -06002013 json,
2014 false,
2015 file_str);
2016
Jon Ashburne58f1a32015-08-28 13:38:21 -06002017 loader_heap_free(inst, file_str);
Jon Ashburn1b111de2015-07-06 15:40:35 -06002018 cJSON_Delete(json);
2019 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06002020 loader_heap_free(inst, manifest_files.filename_list);
Jon Ashburnd02fc2c2015-09-22 13:11:00 -06002021 loader_platform_thread_unlock_mutex(&loader_json_lock);
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002022}
2023
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -06002024static PFN_vkVoidFunction VKAPI loader_gpa_instance_internal(VkInstance inst, const char * pName)
Jon Ashburnfce93d92015-05-12 17:26:48 -06002025{
2026 // inst is not wrapped
2027 if (inst == VK_NULL_HANDLE) {
2028 return NULL;
2029 }
2030 VkLayerInstanceDispatchTable* disp_table = * (VkLayerInstanceDispatchTable **) inst;
2031 void *addr;
2032
Jon Ashburn4f2575f2015-05-28 16:25:02 -06002033 if (!strcmp(pName, "vkGetInstanceProcAddr"))
2034 return (void *) loader_gpa_instance_internal;
2035
Jon Ashburnfce93d92015-05-12 17:26:48 -06002036 if (disp_table == NULL)
2037 return NULL;
2038
2039 addr = loader_lookup_instance_dispatch_table(disp_table, pName);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002040 if (addr) {
Jon Ashburnfce93d92015-05-12 17:26:48 -06002041 return addr;
Jon Ashburne18431b2015-04-13 18:10:06 -06002042 }
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002043
2044 if (disp_table->GetInstanceProcAddr == NULL) {
2045 return NULL;
2046 }
2047 return disp_table->GetInstanceProcAddr(inst, pName);
Jon Ashburne18431b2015-04-13 18:10:06 -06002048}
2049
Jon Ashburn0c5eea22015-09-30 12:56:42 -06002050struct loader_instance *loader_get_instance(const VkInstance instance)
2051{
2052 /* look up the loader_instance in our list by comparing dispatch tables, as
2053 * there is no guarantee the instance is still a loader_instance* after any
2054 * layers which wrap the instance object.
2055 */
2056 const VkLayerInstanceDispatchTable *disp;
2057 struct loader_instance *ptr_instance = NULL;
2058 disp = loader_get_instance_dispatch(instance);
2059 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
2060 if (inst->disp == disp) {
2061 ptr_instance = inst;
2062 break;
2063 }
2064 }
2065 return ptr_instance;
2066}
2067
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002068static loader_platform_dl_handle loader_add_layer_lib(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002069 const struct loader_instance *inst,
Jon Ashburn9a9de1f2015-05-27 13:19:22 -06002070 const char *chain_type,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002071 struct loader_layer_properties *layer_prop)
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002072{
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002073 struct loader_lib_info *new_layer_lib_list, *my_lib;
Jon Ashburne58f1a32015-08-28 13:38:21 -06002074 size_t new_alloc_size;
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -06002075 /*
2076 * TODO: We can now track this information in the
2077 * scanned_layer_libraries list.
2078 */
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002079 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) {
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002080 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, layer_prop->lib_name) == 0) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002081 /* Have already loaded this library, just increment ref count */
2082 loader.loaded_layer_lib_list[i].ref_count++;
Courtney Goeltzenleuchter926f39e2015-06-14 11:59:07 -06002083 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002084 "%s Chain: Increment layer reference count for layer library %s",
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002085 chain_type, layer_prop->lib_name);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002086 return loader.loaded_layer_lib_list[i].lib_handle;
2087 }
2088 }
2089
2090 /* Haven't seen this library so load it */
Jon Ashburne58f1a32015-08-28 13:38:21 -06002091 new_alloc_size = 0;
2092 if (loader.loaded_layer_lib_capacity == 0)
2093 new_alloc_size = 8 * sizeof(struct loader_lib_info);
2094 else if (loader.loaded_layer_lib_capacity <= loader.loaded_layer_lib_count *
2095 sizeof(struct loader_lib_info))
2096 new_alloc_size = loader.loaded_layer_lib_capacity * 2;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002097
Jon Ashburne58f1a32015-08-28 13:38:21 -06002098 if (new_alloc_size) {
2099 new_layer_lib_list = loader_heap_realloc(
2100 inst, loader.loaded_layer_lib_list,
2101 loader.loaded_layer_lib_capacity,
2102 new_alloc_size,
Chia-I Wu1f851912015-10-27 18:04:07 +08002103 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburne58f1a32015-08-28 13:38:21 -06002104 if (!new_layer_lib_list) {
2105 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "loader: realloc failed in loader_add_layer_lib");
2106 return NULL;
2107 }
2108 loader.loaded_layer_lib_capacity = new_alloc_size;
2109 } else
2110 new_layer_lib_list = loader.loaded_layer_lib_list;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002111 my_lib = &new_layer_lib_list[loader.loaded_layer_lib_count];
2112
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002113 strncpy(my_lib->lib_name, layer_prop->lib_name, sizeof(my_lib->lib_name));
2114 my_lib->lib_name[sizeof(my_lib->lib_name) - 1] = '\0';
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002115 my_lib->ref_count = 0;
2116 my_lib->lib_handle = NULL;
2117
2118 if ((my_lib->lib_handle = loader_platform_open_library(my_lib->lib_name)) == NULL) {
2119 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
2120 loader_platform_open_library_error(my_lib->lib_name));
2121 return NULL;
2122 } else {
Courtney Goeltzenleuchter926f39e2015-06-14 11:59:07 -06002123 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002124 "Chain: %s: Loading layer library %s",
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002125 chain_type, layer_prop->lib_name);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002126 }
2127 loader.loaded_layer_lib_count++;
2128 loader.loaded_layer_lib_list = new_layer_lib_list;
2129 my_lib->ref_count++;
2130
2131 return my_lib->lib_handle;
2132}
2133
2134static void loader_remove_layer_lib(
2135 struct loader_instance *inst,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002136 struct loader_layer_properties *layer_prop)
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002137{
2138 uint32_t idx;
Tony Barbour9687cb12015-07-14 13:34:05 -06002139 struct loader_lib_info *new_layer_lib_list, *my_lib = NULL;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002140
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002141 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) {
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002142 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, layer_prop->lib_name) == 0) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002143 /* found matching library */
2144 idx = i;
2145 my_lib = &loader.loaded_layer_lib_list[i];
2146 break;
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002147 }
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002148 }
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002149
Tony Barbour9687cb12015-07-14 13:34:05 -06002150 if (my_lib) {
2151 my_lib->ref_count--;
2152 if (my_lib->ref_count > 0) {
2153 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002154 "Decrement reference count for layer library %s", layer_prop->lib_name);
Tony Barbour9687cb12015-07-14 13:34:05 -06002155 return;
2156 }
Courtney Goeltzenleuchter0199e952015-02-27 15:19:33 -07002157 }
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002158 loader_platform_close_library(my_lib->lib_handle);
Courtney Goeltzenleuchter926f39e2015-06-14 11:59:07 -06002159 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002160 "Unloading layer library %s", layer_prop->lib_name);
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002161
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002162 /* Need to remove unused library from list */
Jon Ashburne58f1a32015-08-28 13:38:21 -06002163 new_layer_lib_list = loader_heap_alloc(inst,
2164 loader.loaded_layer_lib_capacity,
Chia-I Wu1f851912015-10-27 18:04:07 +08002165 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002166 if (!new_layer_lib_list) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06002167 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "loader: heap alloc failed loader_remove_layer_library");
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002168 return;
2169 }
2170
2171 if (idx > 0) {
2172 /* Copy records before idx */
2173 memcpy(new_layer_lib_list, &loader.loaded_layer_lib_list[0],
2174 sizeof(struct loader_lib_info) * idx);
2175 }
2176 if (idx < (loader.loaded_layer_lib_count - 1)) {
2177 /* Copy records after idx */
2178 memcpy(&new_layer_lib_list[idx], &loader.loaded_layer_lib_list[idx+1],
2179 sizeof(struct loader_lib_info) * (loader.loaded_layer_lib_count - idx - 1));
2180 }
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002181
Jon Ashburne58f1a32015-08-28 13:38:21 -06002182 loader_heap_free(inst, loader.loaded_layer_lib_list);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002183 loader.loaded_layer_lib_count--;
2184 loader.loaded_layer_lib_list = new_layer_lib_list;
Jon Ashburnead95c52014-11-18 09:06:04 -07002185}
2186
Jon Ashburn1b111de2015-07-06 15:40:35 -06002187
2188/**
2189 * Go through the search_list and find any layers which match type. If layer
2190 * type match is found in then add it to ext_list.
2191 */
2192//TODO need to handle implict layer enable env var and disable env var
Jon Ashburn535bd002015-07-02 16:10:32 -06002193static void loader_add_layer_implicit(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002194 const struct loader_instance *inst,
Jon Ashburn535bd002015-07-02 16:10:32 -06002195 const enum layer_type type,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002196 struct loader_layer_list *list,
Jon Ashburn182b8302015-08-11 14:49:54 -06002197 const struct loader_layer_list *search_list)
Jon Ashburn535bd002015-07-02 16:10:32 -06002198{
2199 uint32_t i;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002200 for (i = 0; i < search_list->count; i++) {
2201 const struct loader_layer_properties *prop = &search_list->list[i];
Jon Ashburn535bd002015-07-02 16:10:32 -06002202 if (prop->type & type) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002203 /* Found an layer with the same type, add to layer_list */
Jon Ashburne58f1a32015-08-28 13:38:21 -06002204 loader_add_to_layer_list(inst, list, 1, prop);
Jon Ashburn535bd002015-07-02 16:10:32 -06002205 }
2206 }
2207
2208}
2209
2210/**
2211 * Get the layer name(s) from the env_name environment variable. If layer
Jon Ashburnf2ddb732015-07-07 10:27:45 -06002212 * is found in search_list then add it to layer_list. But only add it to
2213 * layer_list if type matches.
Jon Ashburn535bd002015-07-02 16:10:32 -06002214 */
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002215static void loader_add_layer_env(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002216 const struct loader_instance *inst,
Jon Ashburnf2ddb732015-07-07 10:27:45 -06002217 const enum layer_type type,
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002218 const char *env_name,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002219 struct loader_layer_list *layer_list,
2220 const struct loader_layer_list *search_list)
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002221{
Ian Elliott225188f2015-02-17 10:33:47 -07002222 char *layerEnv;
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002223 char *next, *name;
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002224
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002225 layerEnv = getenv(env_name);
Ian Elliott225188f2015-02-17 10:33:47 -07002226 if (layerEnv == NULL) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002227 return;
Ian Elliott225188f2015-02-17 10:33:47 -07002228 }
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -06002229 name = loader_stack_alloc(strlen(layerEnv) + 1);
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002230 if (name == NULL) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002231 return;
Ian Elliott225188f2015-02-17 10:33:47 -07002232 }
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002233 strcpy(name, layerEnv);
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002234
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002235 while (name && *name ) {
2236 next = loader_get_next_path(name);
Jon Ashburne58f1a32015-08-28 13:38:21 -06002237 loader_find_layer_name_add_list(inst, name, type, search_list, layer_list);
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002238 name = next;
Courtney Goeltzenleuchter0199e952015-02-27 15:19:33 -07002239 }
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002240
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002241 return;
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002242}
2243
Courtney Goeltzenleuchter3d8dc1f2015-06-08 15:09:22 -06002244void loader_deactivate_instance_layers(struct loader_instance *instance)
Jon Ashburn183dfd02014-10-22 18:13:16 -06002245{
Jon Ashburn60378412015-07-02 12:59:25 -06002246 if (!instance->activated_layer_list.count) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002247 return;
2248 }
Jon Ashburn183dfd02014-10-22 18:13:16 -06002249
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002250 /* Create instance chain of enabled layers */
Courtney Goeltzenleuchter3d8dc1f2015-06-08 15:09:22 -06002251 for (uint32_t i = 0; i < instance->activated_layer_list.count; i++) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002252 struct loader_layer_properties *layer_prop = &instance->activated_layer_list.list[i];
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002253
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002254 loader_remove_layer_lib(instance, layer_prop);
Jon Ashburn183dfd02014-10-22 18:13:16 -06002255 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06002256 loader_destroy_layer_list(instance, &instance->activated_layer_list);
Jon Ashburn183dfd02014-10-22 18:13:16 -06002257}
2258
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002259VkResult loader_enable_instance_layers(
Jon Ashburn182b8302015-08-11 14:49:54 -06002260 struct loader_instance *inst,
2261 const VkInstanceCreateInfo *pCreateInfo,
2262 const struct loader_layer_list *instance_layers)
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002263{
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002264 VkResult err;
2265
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -06002266 assert(inst && "Cannot have null instance");
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002267
Jon Ashburne58f1a32015-08-28 13:38:21 -06002268 if (!loader_init_layer_list(inst, &inst->activated_layer_list)) {
2269 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc Instance activated layer list");
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002270 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburn60378412015-07-02 12:59:25 -06002271 }
2272
Jon Ashburn535bd002015-07-02 16:10:32 -06002273 /* Add any implicit layers first */
2274 loader_add_layer_implicit(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002275 inst,
Jon Ashburn535bd002015-07-02 16:10:32 -06002276 VK_LAYER_TYPE_INSTANCE_IMPLICIT,
2277 &inst->activated_layer_list,
Jon Ashburn182b8302015-08-11 14:49:54 -06002278 instance_layers);
Jon Ashburn535bd002015-07-02 16:10:32 -06002279
Jon Ashburn1b111de2015-07-06 15:40:35 -06002280 /* Add any layers specified via environment variable next */
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002281 loader_add_layer_env(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002282 inst,
Jon Ashburnf2ddb732015-07-07 10:27:45 -06002283 VK_LAYER_TYPE_INSTANCE_EXPLICIT,
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002284 "VK_INSTANCE_LAYERS",
2285 &inst->activated_layer_list,
Jon Ashburn182b8302015-08-11 14:49:54 -06002286 instance_layers);
Jon Ashburn60378412015-07-02 12:59:25 -06002287
2288 /* Add layers specified by the application */
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002289 err = loader_add_layer_names_to_list(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002290 inst,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002291 &inst->activated_layer_list,
Chia-I Wu763a7492015-10-26 20:48:51 +08002292 pCreateInfo->enabledLayerNameCount,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002293 pCreateInfo->ppEnabledLayerNames,
Jon Ashburn182b8302015-08-11 14:49:54 -06002294 instance_layers);
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002295
2296 return err;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002297}
2298
Jon Ashburnfce93d92015-05-12 17:26:48 -06002299uint32_t loader_activate_instance_layers(struct loader_instance *inst)
2300{
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002301 uint32_t layer_idx;
Jon Ashburnd5df54d2015-05-28 19:16:58 -06002302 VkBaseLayerObject *wrappedInstance;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002303
David Pinedo0fab78b2015-06-24 15:29:18 -06002304 if (inst == NULL) {
Jon Ashburnfce93d92015-05-12 17:26:48 -06002305 return 0;
David Pinedo0fab78b2015-06-24 15:29:18 -06002306 }
Jon Ashburnfce93d92015-05-12 17:26:48 -06002307
2308 // NOTE inst is unwrapped at this point in time
Tony Barbourde4124d2015-07-03 10:33:54 -06002309 void* baseObj = (void*) inst;
2310 void* nextObj = (void*) inst;
Jon Ashburnfce93d92015-05-12 17:26:48 -06002311 VkBaseLayerObject *nextInstObj;
2312 PFN_vkGetInstanceProcAddr nextGPA = loader_gpa_instance_internal;
2313
Jon Ashburn60378412015-07-02 12:59:25 -06002314 if (!inst->activated_layer_list.count) {
Courtney Goeltzenleuchter33243142015-08-07 09:53:18 -06002315 loader_init_instance_core_dispatch_table(inst->disp, nextGPA, (VkInstance) nextObj, (VkInstance) baseObj);
Jon Ashburnfce93d92015-05-12 17:26:48 -06002316 return 0;
2317 }
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002318
Courtney Goeltzenleuchter0248b992015-07-06 09:04:55 -06002319 wrappedInstance = loader_stack_alloc(sizeof(VkBaseLayerObject)
Jon Ashburn60378412015-07-02 12:59:25 -06002320 * inst->activated_layer_list.count);
Jon Ashburnd5df54d2015-05-28 19:16:58 -06002321 if (!wrappedInstance) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06002322 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc Instance objects for layer");
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002323 return 0;
2324 }
2325
2326 /* Create instance chain of enabled layers */
Jon Ashburn60378412015-07-02 12:59:25 -06002327 layer_idx = inst->activated_layer_list.count - 1;
Courtney Goeltzenleuchterf4b430e2015-06-07 17:28:17 -06002328 for (int32_t i = inst->activated_layer_list.count - 1; i >= 0; i--) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002329 struct loader_layer_properties *layer_prop = &inst->activated_layer_list.list[i];
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002330 loader_platform_dl_handle lib_handle;
2331
Jon Ashburn60378412015-07-02 12:59:25 -06002332 /*
Courtney Goeltzenleuchterc27292a2015-06-01 14:12:42 -06002333 * Note: An extension's Get*ProcAddr should not return a function pointer for
2334 * any extension entry points until the extension has been enabled.
2335 * To do this requires a different behavior from Get*ProcAddr functions implemented
2336 * in layers.
2337 * The very first call to a layer will be it's Get*ProcAddr function requesting
Tobin Ehlis84492ee2015-10-06 09:09:24 -06002338 * the layer's vkGet*ProcAddr. The layer should initialize its internal dispatch table
Courtney Goeltzenleuchterc27292a2015-06-01 14:12:42 -06002339 * with the wrapped object given (either Instance or Device) and return the layer's
2340 * Get*ProcAddr function. The layer should also use this opportunity to record the
2341 * baseObject so that it can find the correct local dispatch table on future calls.
2342 * Subsequent calls to Get*ProcAddr, CreateInstance, CreateDevice
2343 * will not use a wrapped object and must look up their local dispatch table from
2344 * the given baseObject.
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002345 */
Jon Ashburnd5df54d2015-05-28 19:16:58 -06002346 nextInstObj = (wrappedInstance + layer_idx);
Tony Barbourde4124d2015-07-03 10:33:54 -06002347 nextInstObj->pGPA = (PFN_vkGPA) nextGPA;
Jon Ashburnfce93d92015-05-12 17:26:48 -06002348 nextInstObj->baseObject = baseObj;
2349 nextInstObj->nextObject = nextObj;
Tony Barbourde4124d2015-07-03 10:33:54 -06002350 nextObj = (void*) nextInstObj;
Jon Ashburnfce93d92015-05-12 17:26:48 -06002351
Jon Ashburne58f1a32015-08-28 13:38:21 -06002352 lib_handle = loader_add_layer_lib(inst, "instance", layer_prop);
Jon Ashburn2db08042015-09-09 11:29:24 -06002353 if ((nextGPA = layer_prop->functions.get_instance_proc_addr) == NULL) {
2354 if (layer_prop->functions.str_gipa == NULL || strlen(layer_prop->functions.str_gipa) == 0) {
2355 nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetInstanceProcAddr");
2356 layer_prop->functions.get_instance_proc_addr = nextGPA;
2357 } else
2358 nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gipa);
2359 if (!nextGPA) {
2360 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to find vkGetInstanceProcAddr in layer %s", layer_prop->lib_name);
Courtney Goeltzenleuchteraa685052015-06-01 14:49:17 -06002361
Jon Ashburn2db08042015-09-09 11:29:24 -06002362 /* TODO: Should we return nextObj, nextGPA to previous? or decrement layer_list count*/
2363 continue;
2364 }
Jon Ashburnfce93d92015-05-12 17:26:48 -06002365 }
2366
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002367 loader_log(VK_DBG_REPORT_INFO_BIT, 0,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002368 "Insert instance layer %s (%s)",
2369 layer_prop->info.layerName,
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002370 layer_prop->lib_name);
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002371
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002372 layer_idx--;
Jon Ashburnfce93d92015-05-12 17:26:48 -06002373 }
2374
Jon Ashburn4f2575f2015-05-28 16:25:02 -06002375 loader_init_instance_core_dispatch_table(inst->disp, nextGPA, (VkInstance) nextObj, (VkInstance) baseObj);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002376
Jon Ashburn60378412015-07-02 12:59:25 -06002377 return inst->activated_layer_list.count;
Jon Ashburnfce93d92015-05-12 17:26:48 -06002378}
2379
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002380void loader_activate_instance_layer_extensions(struct loader_instance *inst)
2381{
2382
2383 loader_init_instance_extension_dispatch_table(inst->disp,
2384 inst->disp->GetInstanceProcAddr,
Jon Ashburnd5df54d2015-05-28 19:16:58 -06002385 (VkInstance) inst);
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002386}
2387
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002388static VkResult loader_enable_device_layers(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002389 const struct loader_instance *inst,
Jon Ashburn182b8302015-08-11 14:49:54 -06002390 struct loader_icd *icd,
2391 struct loader_device *dev,
2392 const VkDeviceCreateInfo *pCreateInfo,
2393 const struct loader_layer_list *device_layers)
2394
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002395{
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002396 VkResult err;
2397
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -06002398 assert(dev && "Cannot have null device");
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002399
Jon Ashburn60378412015-07-02 12:59:25 -06002400 if (dev->activated_layer_list.list == NULL || dev->activated_layer_list.capacity == 0) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06002401 loader_init_layer_list(inst, &dev->activated_layer_list);
Jon Ashburn60378412015-07-02 12:59:25 -06002402 }
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002403
Jon Ashburn60378412015-07-02 12:59:25 -06002404 if (dev->activated_layer_list.list == NULL) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06002405 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc device activated layer list");
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002406 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburn60378412015-07-02 12:59:25 -06002407 }
2408
Jon Ashburn535bd002015-07-02 16:10:32 -06002409 /* Add any implicit layers first */
2410 loader_add_layer_implicit(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002411 inst,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002412 VK_LAYER_TYPE_DEVICE_IMPLICIT,
2413 &dev->activated_layer_list,
Jon Ashburn182b8302015-08-11 14:49:54 -06002414 device_layers);
Jon Ashburn535bd002015-07-02 16:10:32 -06002415
2416 /* Add any layers specified via environment variable next */
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002417 loader_add_layer_env(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002418 inst,
Jon Ashburnf2ddb732015-07-07 10:27:45 -06002419 VK_LAYER_TYPE_DEVICE_EXPLICIT,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002420 "VK_DEVICE_LAYERS",
2421 &dev->activated_layer_list,
Jon Ashburn182b8302015-08-11 14:49:54 -06002422 device_layers);
Jon Ashburn60378412015-07-02 12:59:25 -06002423
2424 /* Add layers specified by the application */
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002425 err = loader_add_layer_names_to_list(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002426 inst,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002427 &dev->activated_layer_list,
Chia-I Wu763a7492015-10-26 20:48:51 +08002428 pCreateInfo->enabledLayerNameCount,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002429 pCreateInfo->ppEnabledLayerNames,
Jon Ashburn182b8302015-08-11 14:49:54 -06002430 device_layers);
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002431
2432 return err;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002433}
2434
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002435/*
Jon Ashburnc1d1eb72015-08-14 11:57:54 -06002436 * This function terminates the device chain for CreateDevice.
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002437 * CreateDevice is a special case and so the loader call's
2438 * the ICD's CreateDevice before creating the chain. Since
2439 * we can't call CreateDevice twice we must terminate the
2440 * device chain with something else.
2441 */
Dan Ginsburgf99e4102015-07-23 13:15:00 -04002442static VkResult VKAPI scratch_vkCreateDevice(
Jon Ashburn251258f2015-11-01 14:04:06 -07002443 VkPhysicalDevice physicalDevice,
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002444 const VkDeviceCreateInfo *pCreateInfo,
Chia-I Wu1f851912015-10-27 18:04:07 +08002445 const VkAllocationCallbacks* pAllocator,
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002446 VkDevice *pDevice)
2447{
2448 return VK_SUCCESS;
2449}
2450
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -06002451static PFN_vkVoidFunction VKAPI loader_GetDeviceChainProcAddr(VkDevice device, const char * name)
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002452{
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002453 if (!strcmp(name, "vkGetDeviceProcAddr"))
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -06002454 return (PFN_vkVoidFunction) loader_GetDeviceChainProcAddr;
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002455 if (!strcmp(name, "vkCreateDevice"))
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -06002456 return (PFN_vkVoidFunction) scratch_vkCreateDevice;
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002457
Courtney Goeltzenleuchtere76db422015-06-29 16:09:23 -06002458 struct loader_device *found_dev;
2459 struct loader_icd *icd = loader_get_icd_and_device(device, &found_dev);
2460 return icd->GetDeviceProcAddr(device, name);
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002461}
2462
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06002463static uint32_t loader_activate_device_layers(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002464 const struct loader_instance *inst,
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002465 struct loader_device *dev,
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -06002466 VkDevice device)
Jon Ashburn183dfd02014-10-22 18:13:16 -06002467{
David Pinedo0fab78b2015-06-24 15:29:18 -06002468 if (!dev) {
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06002469 return 0;
David Pinedo0fab78b2015-06-24 15:29:18 -06002470 }
Jon Ashburn612539f2015-06-10 10:13:10 -06002471
Jon Ashburn183dfd02014-10-22 18:13:16 -06002472 /* activate any layer libraries */
Tony Barbourde4124d2015-07-03 10:33:54 -06002473 void* nextObj = (void*) device;
2474 void* baseObj = nextObj;
Jon Ashburn612539f2015-06-10 10:13:10 -06002475 VkBaseLayerObject *nextGpuObj;
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002476 PFN_vkGetDeviceProcAddr nextGPA = loader_GetDeviceChainProcAddr;
Jon Ashburn612539f2015-06-10 10:13:10 -06002477 VkBaseLayerObject *wrappedGpus;
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002478
Courtney Goeltzenleuchter33243142015-08-07 09:53:18 -06002479 if (!dev->activated_layer_list.count) {
2480 loader_init_device_dispatch_table(&dev->loader_dispatch, nextGPA,
2481 (VkDevice) nextObj, (VkDevice) baseObj);
Jon Ashburn612539f2015-06-10 10:13:10 -06002482 return 0;
Courtney Goeltzenleuchter33243142015-08-07 09:53:18 -06002483 }
Jon Ashburn612539f2015-06-10 10:13:10 -06002484
Jon Ashburne58f1a32015-08-28 13:38:21 -06002485 wrappedGpus = loader_heap_alloc(inst,
2486 sizeof (VkBaseLayerObject) * dev->activated_layer_list.count,
Chia-I Wu1f851912015-10-27 18:04:07 +08002487 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn612539f2015-06-10 10:13:10 -06002488 if (!wrappedGpus) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06002489 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc Gpu objects for layer");
Jon Ashburn612539f2015-06-10 10:13:10 -06002490 return 0;
2491 }
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002492
Jon Ashburn612539f2015-06-10 10:13:10 -06002493 for (int32_t i = dev->activated_layer_list.count - 1; i >= 0; i--) {
2494
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002495 struct loader_layer_properties *layer_prop = &dev->activated_layer_list.list[i];
Jon Ashburn612539f2015-06-10 10:13:10 -06002496 loader_platform_dl_handle lib_handle;
2497
Jon Ashburn612539f2015-06-10 10:13:10 -06002498 nextGpuObj = (wrappedGpus + i);
Tony Barbourde4124d2015-07-03 10:33:54 -06002499 nextGpuObj->pGPA = (PFN_vkGPA)nextGPA;
Jon Ashburn612539f2015-06-10 10:13:10 -06002500 nextGpuObj->baseObject = baseObj;
2501 nextGpuObj->nextObject = nextObj;
Tony Barbourde4124d2015-07-03 10:33:54 -06002502 nextObj = (void*) nextGpuObj;
Jon Ashburn612539f2015-06-10 10:13:10 -06002503
Jon Ashburne58f1a32015-08-28 13:38:21 -06002504 lib_handle = loader_add_layer_lib(inst, "device", layer_prop);
Jon Ashburn2db08042015-09-09 11:29:24 -06002505 if ((nextGPA = layer_prop->functions.get_device_proc_addr) == NULL) {
2506 if (layer_prop->functions.str_gdpa == NULL || strlen(layer_prop->functions.str_gdpa) == 0) {
2507 nextGPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetDeviceProcAddr");
2508 layer_prop->functions.get_device_proc_addr = nextGPA;
2509 } else
2510 nextGPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gdpa);
2511 if (!nextGPA) {
2512 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to find vkGetDeviceProcAddr in layer %s", layer_prop->lib_name);
2513 continue;
2514 }
Jon Ashburn612539f2015-06-10 10:13:10 -06002515 }
2516
2517 loader_log(VK_DBG_REPORT_INFO_BIT, 0,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002518 "Insert device layer library %s (%s)",
2519 layer_prop->info.layerName,
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002520 layer_prop->lib_name);
Jon Ashburn612539f2015-06-10 10:13:10 -06002521
2522 }
2523
2524 loader_init_device_dispatch_table(&dev->loader_dispatch, nextGPA,
Tony Barbourde4124d2015-07-03 10:33:54 -06002525 (VkDevice) nextObj, (VkDevice) baseObj);
Jon Ashburne58f1a32015-08-28 13:38:21 -06002526 loader_heap_free(inst, wrappedGpus);
Jon Ashburn612539f2015-06-10 10:13:10 -06002527
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06002528 return dev->activated_layer_list.count;
Jon Ashburn183dfd02014-10-22 18:13:16 -06002529}
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002530
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002531VkResult loader_validate_layers(
2532 const uint32_t layer_count,
2533 const char * const *ppEnabledLayerNames,
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002534 const struct loader_layer_list *list)
Courtney Goeltzenleuchter5d9f29b2015-07-06 17:45:08 -06002535{
2536 struct loader_layer_properties *prop;
2537
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002538 for (uint32_t i = 0; i < layer_count; i++) {
Jon Ashburn8e4fab42015-08-03 17:19:30 -06002539 prop = loader_get_layer_property(ppEnabledLayerNames[i],
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002540 list);
Courtney Goeltzenleuchter5d9f29b2015-07-06 17:45:08 -06002541 if (!prop) {
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -06002542 return VK_ERROR_LAYER_NOT_PRESENT;
Courtney Goeltzenleuchter5d9f29b2015-07-06 17:45:08 -06002543 }
2544 }
2545
2546 return VK_SUCCESS;
2547}
2548
2549VkResult loader_validate_instance_extensions(
Jon Ashburnc1d1eb72015-08-14 11:57:54 -06002550 const struct loader_extension_list *icd_exts,
Jon Ashburn182b8302015-08-11 14:49:54 -06002551 const struct loader_layer_list *instance_layer,
2552 const VkInstanceCreateInfo *pCreateInfo)
Courtney Goeltzenleuchter5d9f29b2015-07-06 17:45:08 -06002553{
Jon Ashburnc4748dc2015-08-04 11:14:18 -06002554 VkExtensionProperties *extension_prop;
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002555 struct loader_layer_properties *layer_prop;
2556
Chia-I Wu763a7492015-10-26 20:48:51 +08002557 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) {
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002558 extension_prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
Jon Ashburnc1d1eb72015-08-14 11:57:54 -06002559 icd_exts);
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002560
2561 if (extension_prop) {
2562 continue;
2563 }
2564
2565 extension_prop = NULL;
2566
2567 /* Not in global list, search layer extension lists */
Chia-I Wu763a7492015-10-26 20:48:51 +08002568 for (uint32_t j = 0; j < pCreateInfo->enabledLayerNameCount; j++) {
Jon Ashburn8e4fab42015-08-03 17:19:30 -06002569 layer_prop = loader_get_layer_property(pCreateInfo->ppEnabledLayerNames[i],
Jon Ashburn182b8302015-08-11 14:49:54 -06002570 instance_layer);
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002571 if (!layer_prop) {
Courtney Goeltzenleuchter91371ff2015-07-06 20:46:50 -06002572 /* Should NOT get here, loader_validate_layers
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002573 * should have already filtered this case out.
2574 */
2575 continue;
2576 }
2577
2578 extension_prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
2579 &layer_prop->instance_extension_list);
2580 if (extension_prop) {
2581 /* Found the extension in one of the layers enabled by the app. */
2582 break;
2583 }
2584 }
2585
2586 if (!extension_prop) {
2587 /* Didn't find extension name in any of the global layers, error out */
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -06002588 return VK_ERROR_EXTENSION_NOT_PRESENT;
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002589 }
2590 }
2591 return VK_SUCCESS;
2592}
2593
2594VkResult loader_validate_device_extensions(
Jon Ashburn251258f2015-11-01 14:04:06 -07002595 struct loader_physical_device *phys_dev,
Jon Ashburn182b8302015-08-11 14:49:54 -06002596 const struct loader_layer_list *device_layer,
2597 const VkDeviceCreateInfo *pCreateInfo)
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002598{
Jon Ashburnc4748dc2015-08-04 11:14:18 -06002599 VkExtensionProperties *extension_prop;
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002600 struct loader_layer_properties *layer_prop;
2601
Chia-I Wu763a7492015-10-26 20:48:51 +08002602 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) {
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002603 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i];
2604 extension_prop = get_extension_property(extension_name,
Jon Ashburn251258f2015-11-01 14:04:06 -07002605 &phys_dev->device_extension_cache);
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002606
2607 if (extension_prop) {
2608 continue;
2609 }
2610
2611 /* Not in global list, search layer extension lists */
Chia-I Wu763a7492015-10-26 20:48:51 +08002612 for (uint32_t j = 0; j < pCreateInfo->enabledLayerNameCount; j++) {
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002613 const char *layer_name = pCreateInfo->ppEnabledLayerNames[j];
Jon Ashburn8e4fab42015-08-03 17:19:30 -06002614 layer_prop = loader_get_layer_property(layer_name,
Jon Ashburn182b8302015-08-11 14:49:54 -06002615 device_layer);
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002616
2617 if (!layer_prop) {
2618 /* Should NOT get here, loader_validate_instance_layers
2619 * should have already filtered this case out.
2620 */
2621 continue;
2622 }
2623
2624 extension_prop = get_extension_property(extension_name,
2625 &layer_prop->device_extension_list);
2626 if (extension_prop) {
2627 /* Found the extension in one of the layers enabled by the app. */
2628 break;
2629 }
2630 }
2631
2632 if (!extension_prop) {
2633 /* Didn't find extension name in any of the device layers, error out */
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -06002634 return VK_ERROR_EXTENSION_NOT_PRESENT;
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002635 }
2636 }
Courtney Goeltzenleuchter5d9f29b2015-07-06 17:45:08 -06002637 return VK_SUCCESS;
2638}
2639
Dan Ginsburgf99e4102015-07-23 13:15:00 -04002640VkResult VKAPI loader_CreateInstance(
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002641 const VkInstanceCreateInfo* pCreateInfo,
Chia-I Wu1f851912015-10-27 18:04:07 +08002642 const VkAllocationCallbacks* pAllocator,
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002643 VkInstance* pInstance)
Jon Ashburn349508d2015-01-26 14:51:40 -07002644{
Jon Ashburna179dcf2015-05-21 17:42:17 -06002645 struct loader_instance *ptr_instance = *(struct loader_instance **) pInstance;
Jon Ashburn3336df82015-01-29 15:45:51 -07002646 struct loader_icd *icd;
Jon Ashburnc4748dc2015-08-04 11:14:18 -06002647 VkExtensionProperties *prop;
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06002648 char **filtered_extension_names = NULL;
2649 VkInstanceCreateInfo icd_create_info;
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002650 VkResult res = VK_SUCCESS;
Jon Ashburnce7e3d92015-07-16 10:17:29 -06002651 bool success;
Jon Ashburn349508d2015-01-26 14:51:40 -07002652
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06002653 icd_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
Chia-I Wu763a7492015-10-26 20:48:51 +08002654 icd_create_info.enabledLayerNameCount = 0;
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06002655 icd_create_info.ppEnabledLayerNames = NULL;
Chia-I Wu1f851912015-10-27 18:04:07 +08002656 icd_create_info.pApplicationInfo = pCreateInfo->pApplicationInfo;
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06002657 icd_create_info.pNext = pCreateInfo->pNext;
2658
2659 /*
2660 * NOTE: Need to filter the extensions to only those
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002661 * supported by the ICD.
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06002662 * No ICD will advertise support for layers. An ICD
2663 * library could support a layer, but it would be
2664 * independent of the actual ICD, just in the same library.
2665 */
Chia-I Wu763a7492015-10-26 20:48:51 +08002666 filtered_extension_names = loader_stack_alloc(pCreateInfo->enabledExtensionNameCount * sizeof(char *));
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06002667 if (!filtered_extension_names) {
2668 return VK_ERROR_OUT_OF_HOST_MEMORY;
2669 }
2670 icd_create_info.ppEnabledExtensionNames = (const char * const *) filtered_extension_names;
2671
Jon Ashburn754f1992015-08-18 18:04:47 -06002672 for (uint32_t i = 0; i < ptr_instance->icd_libs.count; i++) {
2673 icd = loader_icd_add(ptr_instance, &ptr_instance->icd_libs.list[i]);
Jon Ashburn3336df82015-01-29 15:45:51 -07002674 if (icd) {
Chia-I Wu763a7492015-10-26 20:48:51 +08002675 icd_create_info.enabledExtensionNameCount = 0;
2676 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) {
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06002677 prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
Jon Ashburn85f98072015-08-14 14:49:22 -06002678 &ptr_instance->ext_list);
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06002679 if (prop) {
Chia-I Wu763a7492015-10-26 20:48:51 +08002680 filtered_extension_names[icd_create_info.enabledExtensionNameCount] = (char *) pCreateInfo->ppEnabledExtensionNames[i];
2681 icd_create_info.enabledExtensionNameCount++;
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06002682 }
2683 }
2684
Jon Ashburn754f1992015-08-18 18:04:47 -06002685 res = ptr_instance->icd_libs.list[i].CreateInstance(&icd_create_info,
Chia-I Wu69f40122015-10-26 21:10:41 +08002686 pAllocator,
Jon Ashburn0dd356d2015-05-14 12:43:38 -06002687 &(icd->instance));
Jon Ashburnce7e3d92015-07-16 10:17:29 -06002688 success = loader_icd_init_entrys(
2689 icd,
2690 icd->instance,
Jon Ashburn754f1992015-08-18 18:04:47 -06002691 ptr_instance->icd_libs.list[i].GetInstanceProcAddr);
Jon Ashburnce7e3d92015-07-16 10:17:29 -06002692
2693 if (res != VK_SUCCESS || !success)
Jon Ashburn3336df82015-01-29 15:45:51 -07002694 {
2695 ptr_instance->icds = ptr_instance->icds->next;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002696 loader_icd_destroy(ptr_instance, icd);
Jon Ashburn0dd356d2015-05-14 12:43:38 -06002697 icd->instance = VK_NULL_HANDLE;
Jon Ashburnce7e3d92015-07-16 10:17:29 -06002698 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
2699 "ICD ignored: failed to CreateInstance and find entrypoints with ICD");
Jon Ashburn3336df82015-01-29 15:45:51 -07002700 }
2701 }
Jon Ashburn3336df82015-01-29 15:45:51 -07002702 }
Jon Ashburn349508d2015-01-26 14:51:40 -07002703
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002704 /*
2705 * If no ICDs were added to instance list and res is unchanged
2706 * from it's initial value, the loader was unable to find
2707 * a suitable ICD.
2708 */
Ian Elliott617fdec2015-02-05 15:19:15 -07002709 if (ptr_instance->icds == NULL) {
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002710 if (res == VK_SUCCESS) {
2711 return VK_ERROR_INCOMPATIBLE_DRIVER;
2712 } else {
2713 return res;
2714 }
Ian Elliott617fdec2015-02-05 15:19:15 -07002715 }
Jon Ashburn3336df82015-01-29 15:45:51 -07002716
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002717 return VK_SUCCESS;
Jon Ashburn349508d2015-01-26 14:51:40 -07002718}
2719
Mark Lobodzinski67b42b72015-09-07 13:59:43 -06002720void VKAPI loader_DestroyInstance(
Chia-I Wu69f40122015-10-26 21:10:41 +08002721 VkInstance instance,
Chia-I Wu1f851912015-10-27 18:04:07 +08002722 const VkAllocationCallbacks* pAllocator)
Jon Ashburn349508d2015-01-26 14:51:40 -07002723{
Courtney Goeltzenleuchter8afefb52015-06-08 15:04:02 -06002724 struct loader_instance *ptr_instance = loader_instance(instance);
Jon Ashburn0dd356d2015-05-14 12:43:38 -06002725 struct loader_icd *icds = ptr_instance->icds;
Jon Ashburn16a16d62015-06-16 14:43:19 -06002726 struct loader_icd *next_icd;
Jon Ashburn349508d2015-01-26 14:51:40 -07002727
2728 // Remove this instance from the list of instances:
2729 struct loader_instance *prev = NULL;
2730 struct loader_instance *next = loader.instances;
2731 while (next != NULL) {
2732 if (next == ptr_instance) {
2733 // Remove this instance from the list:
2734 if (prev)
2735 prev->next = next->next;
Jon Ashburn2cabd252015-02-03 09:26:59 -07002736 else
2737 loader.instances = next->next;
Jon Ashburn349508d2015-01-26 14:51:40 -07002738 break;
2739 }
2740 prev = next;
2741 next = next->next;
2742 }
Jon Ashburn349508d2015-01-26 14:51:40 -07002743
Jon Ashburn0dd356d2015-05-14 12:43:38 -06002744 while (icds) {
2745 if (icds->instance) {
Chia-I Wu69f40122015-10-26 21:10:41 +08002746 icds->DestroyInstance(icds->instance, pAllocator);
Tony Barbour22a30862015-04-22 09:02:32 -06002747 }
Jon Ashburn16a16d62015-06-16 14:43:19 -06002748 next_icd = icds->next;
Jon Ashburn0dd356d2015-05-14 12:43:38 -06002749 icds->instance = VK_NULL_HANDLE;
Jon Ashburn16a16d62015-06-16 14:43:19 -06002750 loader_icd_destroy(ptr_instance, icds);
2751
2752 icds = next_icd;
Jon Ashburn3336df82015-01-29 15:45:51 -07002753 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06002754 loader_delete_layer_properties(ptr_instance, &ptr_instance->device_layer_list);
2755 loader_delete_layer_properties(ptr_instance, &ptr_instance->instance_layer_list);
2756 loader_scanned_icd_clear(ptr_instance, &ptr_instance->icd_libs);
2757 loader_destroy_ext_list(ptr_instance, &ptr_instance->ext_list);
Jon Ashburn251258f2015-11-01 14:04:06 -07002758 for (uint32_t i = 0; i < ptr_instance->total_gpu_count; i++)
2759 loader_destroy_ext_list(ptr_instance, &ptr_instance->phys_devs[i].device_extension_cache);
2760 loader_heap_free(ptr_instance, ptr_instance->phys_devs);
Jon Ashburn349508d2015-01-26 14:51:40 -07002761}
2762
Jon Ashburn251258f2015-11-01 14:04:06 -07002763VkResult loader_init_physical_device_info(struct loader_instance *ptr_instance)
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002764{
2765 struct loader_icd *icd;
Jon Ashburn251258f2015-11-01 14:04:06 -07002766 uint32_t i, j, idx, count = 0;
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -06002767 VkResult res;
Jon Ashburn251258f2015-11-01 14:04:06 -07002768 struct loader_phys_dev_per_icd *phys_devs;
2769
2770 ptr_instance->total_gpu_count = 0;
2771 phys_devs = (struct loader_phys_dev_per_icd *) loader_stack_alloc(
2772 sizeof(struct loader_phys_dev_per_icd) *
2773 ptr_instance->total_icd_count);
2774 if (!phys_devs)
2775 return VK_ERROR_OUT_OF_HOST_MEMORY;
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002776
2777 icd = ptr_instance->icds;
Jon Ashburn251258f2015-11-01 14:04:06 -07002778 for (i = 0; i < ptr_instance->total_icd_count; i++) {
2779 assert(icd);
2780 res = icd->EnumeratePhysicalDevices(icd->instance, &phys_devs[i].count, NULL);
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002781 if (res != VK_SUCCESS)
2782 return res;
Jon Ashburn251258f2015-11-01 14:04:06 -07002783 count += phys_devs[i].count;
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002784 icd = icd->next;
2785 }
2786
Jon Ashburn251258f2015-11-01 14:04:06 -07002787 ptr_instance->phys_devs = (struct loader_physical_device *) loader_heap_alloc(
2788 ptr_instance,
2789 count * sizeof(struct loader_physical_device),
2790 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
2791 if (!ptr_instance->phys_devs)
2792 return VK_ERROR_OUT_OF_HOST_MEMORY;
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002793
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002794 icd = ptr_instance->icds;
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002795
Jon Ashburn251258f2015-11-01 14:04:06 -07002796 struct loader_physical_device *inst_phys_devs = ptr_instance->phys_devs;
2797 idx = 0;
2798 for (i = 0; i < ptr_instance->total_icd_count; i++) {
2799 assert(icd);
2800
2801 phys_devs[i].phys_devs = (VkPhysicalDevice *) loader_stack_alloc(
2802 phys_devs[i].count * sizeof(VkPhysicalDevice));
2803 if (!phys_devs[i].phys_devs) {
Jon Ashburna8ca5c42015-11-02 17:59:02 -07002804 loader_heap_free(ptr_instance, ptr_instance->phys_devs);
2805 ptr_instance->phys_devs = NULL;
Jon Ashburnd5df54d2015-05-28 19:16:58 -06002806 return VK_ERROR_OUT_OF_HOST_MEMORY;
2807 }
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002808 res = icd->EnumeratePhysicalDevices(
2809 icd->instance,
Jon Ashburn251258f2015-11-01 14:04:06 -07002810 &(phys_devs[i].count),
2811 phys_devs[i].phys_devs);
2812 if ((res == VK_SUCCESS)) {
2813 ptr_instance->total_gpu_count += phys_devs[i].count;
2814 for (j = 0; j < phys_devs[i].count; j++) {
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002815
Jon Ashburn251258f2015-11-01 14:04:06 -07002816 // initialize the loader's physicalDevice object
2817 loader_set_dispatch((void *) &inst_phys_devs[idx], ptr_instance->disp);
2818 inst_phys_devs[idx].this_instance = ptr_instance;
2819 inst_phys_devs[idx].this_icd = icd;
2820 inst_phys_devs[idx].phys_dev = phys_devs[i].phys_devs[j];
Jon Ashburndb5a5bc2015-11-02 17:40:01 -07002821 memset(&inst_phys_devs[idx].device_extension_cache, 0, sizeof(struct loader_extension_list));
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002822
Jon Ashburn251258f2015-11-01 14:04:06 -07002823 idx++;
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002824 }
Jon Ashburna8ca5c42015-11-02 17:59:02 -07002825 } else {
2826 loader_heap_free(ptr_instance, ptr_instance->phys_devs);
2827 ptr_instance->phys_devs = NULL;
Jon Ashburn251258f2015-11-01 14:04:06 -07002828 return res;
Jon Ashburna8ca5c42015-11-02 17:59:02 -07002829 }
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002830
2831 icd = icd->next;
2832 }
2833
2834 return VK_SUCCESS;
2835}
2836
Dan Ginsburgf99e4102015-07-23 13:15:00 -04002837VkResult VKAPI loader_EnumeratePhysicalDevices(
Courtney Goeltzenleuchter9f530cb2015-04-20 12:48:54 -06002838 VkInstance instance,
2839 uint32_t* pPhysicalDeviceCount,
2840 VkPhysicalDevice* pPhysicalDevices)
Jon Ashburn349508d2015-01-26 14:51:40 -07002841{
Jon Ashburn251258f2015-11-01 14:04:06 -07002842 uint32_t i;
Jon Ashburnb048a9b2015-01-28 19:57:09 -07002843 struct loader_instance *ptr_instance = (struct loader_instance *) instance;
Jon Ashburn251258f2015-11-01 14:04:06 -07002844 VkResult res = VK_SUCCESS;
Jon Ashburnb048a9b2015-01-28 19:57:09 -07002845
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002846 if (ptr_instance->total_gpu_count == 0) {
Jon Ashburn251258f2015-11-01 14:04:06 -07002847 res = loader_init_physical_device_info(ptr_instance);
Jon Ashburnb048a9b2015-01-28 19:57:09 -07002848 }
2849
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002850 *pPhysicalDeviceCount = ptr_instance->total_gpu_count;
2851 if (!pPhysicalDevices) {
Jon Ashburn251258f2015-11-01 14:04:06 -07002852 return res;
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002853 }
Jon Ashburnb048a9b2015-01-28 19:57:09 -07002854
Jon Ashburn251258f2015-11-01 14:04:06 -07002855 for (i = 0; i < ptr_instance->total_gpu_count; i++) {
2856 pPhysicalDevices[i] = (VkPhysicalDevice) &ptr_instance->phys_devs[i];
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002857 }
2858
Jon Ashburn251258f2015-11-01 14:04:06 -07002859 return res;
Jon Ashburn349508d2015-01-26 14:51:40 -07002860}
2861
Courtney Goeltzenleuchter01d2ae12015-10-20 16:40:38 -06002862void VKAPI loader_GetPhysicalDeviceProperties(
Jon Ashburn251258f2015-11-01 14:04:06 -07002863 VkPhysicalDevice physicalDevice,
Tony Barbour426b9052015-06-24 16:06:58 -06002864 VkPhysicalDeviceProperties* pProperties)
Jon Ashburn0dd356d2015-05-14 12:43:38 -06002865{
Jon Ashburn251258f2015-11-01 14:04:06 -07002866 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
2867 struct loader_icd *icd = phys_dev->this_icd;
Jon Ashburn0dd356d2015-05-14 12:43:38 -06002868
Tony Barbour426b9052015-06-24 16:06:58 -06002869 if (icd->GetPhysicalDeviceProperties)
Jon Ashburn251258f2015-11-01 14:04:06 -07002870 icd->GetPhysicalDeviceProperties(phys_dev->phys_dev, pProperties);
Tony Barbour426b9052015-06-24 16:06:58 -06002871}
2872
Courtney Goeltzenleuchter01d2ae12015-10-20 16:40:38 -06002873void VKAPI loader_GetPhysicalDeviceQueueFamilyProperties (
Jon Ashburn251258f2015-11-01 14:04:06 -07002874 VkPhysicalDevice physicalDevice,
Chia-I Wu763a7492015-10-26 20:48:51 +08002875 uint32_t* pQueueFamilyPropertyCount,
Cody Northropef72e2a2015-08-03 17:04:53 -06002876 VkQueueFamilyProperties* pProperties)
Tony Barbour426b9052015-06-24 16:06:58 -06002877{
Jon Ashburn251258f2015-11-01 14:04:06 -07002878 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
2879 struct loader_icd *icd = phys_dev->this_icd;
Tony Barbour426b9052015-06-24 16:06:58 -06002880
Cody Northropef72e2a2015-08-03 17:04:53 -06002881 if (icd->GetPhysicalDeviceQueueFamilyProperties)
Jon Ashburn251258f2015-11-01 14:04:06 -07002882 icd->GetPhysicalDeviceQueueFamilyProperties(phys_dev->phys_dev, pQueueFamilyPropertyCount, pProperties);
Tony Barbour426b9052015-06-24 16:06:58 -06002883}
2884
Courtney Goeltzenleuchter01d2ae12015-10-20 16:40:38 -06002885void VKAPI loader_GetPhysicalDeviceMemoryProperties (
Jon Ashburn251258f2015-11-01 14:04:06 -07002886 VkPhysicalDevice physicalDevice,
Tony Barbour426b9052015-06-24 16:06:58 -06002887 VkPhysicalDeviceMemoryProperties* pProperties)
2888{
Jon Ashburn251258f2015-11-01 14:04:06 -07002889 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
2890 struct loader_icd *icd = phys_dev->this_icd;
Tony Barbour426b9052015-06-24 16:06:58 -06002891
2892 if (icd->GetPhysicalDeviceMemoryProperties)
Jon Ashburn251258f2015-11-01 14:04:06 -07002893 icd->GetPhysicalDeviceMemoryProperties(phys_dev->phys_dev, pProperties);
Jon Ashburn0dd356d2015-05-14 12:43:38 -06002894}
2895
Courtney Goeltzenleuchter01d2ae12015-10-20 16:40:38 -06002896void VKAPI loader_GetPhysicalDeviceFeatures(
Chris Forbesd7576302015-06-21 22:55:02 +12002897 VkPhysicalDevice physicalDevice,
2898 VkPhysicalDeviceFeatures* pFeatures)
2899{
Jon Ashburn251258f2015-11-01 14:04:06 -07002900 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
2901 struct loader_icd *icd = phys_dev->this_icd;
Chris Forbesd7576302015-06-21 22:55:02 +12002902
2903 if (icd->GetPhysicalDeviceFeatures)
Jon Ashburn251258f2015-11-01 14:04:06 -07002904 icd->GetPhysicalDeviceFeatures(phys_dev->phys_dev, pFeatures);
Chris Forbesd7576302015-06-21 22:55:02 +12002905}
2906
Courtney Goeltzenleuchter01d2ae12015-10-20 16:40:38 -06002907void VKAPI loader_GetPhysicalDeviceFormatProperties(
Chris Forbesd7576302015-06-21 22:55:02 +12002908 VkPhysicalDevice physicalDevice,
2909 VkFormat format,
2910 VkFormatProperties* pFormatInfo)
2911{
Jon Ashburn251258f2015-11-01 14:04:06 -07002912 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
2913 struct loader_icd *icd = phys_dev->this_icd;
Chris Forbesd7576302015-06-21 22:55:02 +12002914
Courtney Goeltzenleuchter4da96aa2015-07-12 12:52:09 -06002915 if (icd->GetPhysicalDeviceFormatProperties)
Jon Ashburn251258f2015-11-01 14:04:06 -07002916 icd->GetPhysicalDeviceFormatProperties(phys_dev->phys_dev, format, pFormatInfo);
Chris Forbesd7576302015-06-21 22:55:02 +12002917}
2918
Courtney Goeltzenleuchter01d2ae12015-10-20 16:40:38 -06002919void VKAPI loader_GetPhysicalDeviceImageFormatProperties(
Jon Ashburn4e189562015-07-23 18:49:07 -06002920 VkPhysicalDevice physicalDevice,
2921 VkFormat format,
2922 VkImageType type,
2923 VkImageTiling tiling,
2924 VkImageUsageFlags usage,
Courtney Goeltzenleuchter83c95f82015-09-10 13:44:12 -06002925 VkImageCreateFlags flags,
Jon Ashburn4e189562015-07-23 18:49:07 -06002926 VkImageFormatProperties* pImageFormatProperties)
2927{
Jon Ashburn251258f2015-11-01 14:04:06 -07002928 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
2929 struct loader_icd *icd = phys_dev->this_icd;
Jon Ashburn4e189562015-07-23 18:49:07 -06002930
2931 if (icd->GetPhysicalDeviceImageFormatProperties)
Jon Ashburn251258f2015-11-01 14:04:06 -07002932 icd->GetPhysicalDeviceImageFormatProperties(phys_dev->phys_dev, format,
Courtney Goeltzenleuchter83c95f82015-09-10 13:44:12 -06002933 type, tiling, usage, flags, pImageFormatProperties);
Jon Ashburn4e189562015-07-23 18:49:07 -06002934}
2935
Courtney Goeltzenleuchter01d2ae12015-10-20 16:40:38 -06002936void VKAPI loader_GetPhysicalDeviceSparseImageFormatProperties(
Mark Lobodzinski83d4e6a2015-07-03 15:58:09 -06002937 VkPhysicalDevice physicalDevice,
2938 VkFormat format,
2939 VkImageType type,
2940 uint32_t samples,
2941 VkImageUsageFlags usage,
2942 VkImageTiling tiling,
2943 uint32_t* pNumProperties,
2944 VkSparseImageFormatProperties* pProperties)
2945{
Jon Ashburn251258f2015-11-01 14:04:06 -07002946 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
2947 struct loader_icd *icd = phys_dev->this_icd;
Mark Lobodzinski83d4e6a2015-07-03 15:58:09 -06002948
2949 if (icd->GetPhysicalDeviceSparseImageFormatProperties)
Jon Ashburn251258f2015-11-01 14:04:06 -07002950 icd->GetPhysicalDeviceSparseImageFormatProperties(phys_dev->phys_dev, format, type, samples, usage, tiling, pNumProperties, pProperties);
Mark Lobodzinski83d4e6a2015-07-03 15:58:09 -06002951}
2952
Dan Ginsburgf99e4102015-07-23 13:15:00 -04002953VkResult VKAPI loader_CreateDevice(
Jon Ashburn251258f2015-11-01 14:04:06 -07002954 VkPhysicalDevice physicalDevice,
Jon Ashburn2666e2f2015-05-15 15:09:35 -06002955 const VkDeviceCreateInfo* pCreateInfo,
Chia-I Wu1f851912015-10-27 18:04:07 +08002956 const VkAllocationCallbacks* pAllocator,
Jon Ashburn2666e2f2015-05-15 15:09:35 -06002957 VkDevice* pDevice)
2958{
Jon Ashburn251258f2015-11-01 14:04:06 -07002959 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
2960 struct loader_icd *icd = phys_dev->this_icd;
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06002961 struct loader_device *dev;
Jon Ashburn6853e7e2015-10-26 16:54:51 -06002962 const struct loader_instance *inst;
Courtney Goeltzenleuchter91371ff2015-07-06 20:46:50 -06002963 VkDeviceCreateInfo device_create_info;
2964 char **filtered_extension_names = NULL;
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002965 VkResult res;
Jon Ashburn2666e2f2015-05-15 15:09:35 -06002966
Courtney Goeltzenleuchterdfd53f52015-10-15 16:58:44 -06002967 assert(pCreateInfo->requestedQueueCount >= 1);
Mark Lobodzinski5ea338c2015-09-17 15:17:34 -06002968
Jon Ashburn6853e7e2015-10-26 16:54:51 -06002969 if (!icd)
2970 return VK_ERROR_INITIALIZATION_FAILED;
2971
Jon Ashburn251258f2015-11-01 14:04:06 -07002972 inst = phys_dev->this_instance;
Jon Ashburn6853e7e2015-10-26 16:54:51 -06002973
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002974 if (!icd->CreateDevice) {
2975 return VK_ERROR_INITIALIZATION_FAILED;
Jon Ashburn2666e2f2015-05-15 15:09:35 -06002976 }
2977
Jon Ashburn182b8302015-08-11 14:49:54 -06002978 /* validate any app enabled layers are available */
Chia-I Wu763a7492015-10-26 20:48:51 +08002979 if (pCreateInfo->enabledLayerNameCount > 0) {
2980 res = loader_validate_layers(pCreateInfo->enabledLayerNameCount,
Jon Ashburn182b8302015-08-11 14:49:54 -06002981 pCreateInfo->ppEnabledLayerNames,
Jon Ashburne58f1a32015-08-28 13:38:21 -06002982 &inst->device_layer_list);
Jon Ashburn182b8302015-08-11 14:49:54 -06002983 if (res != VK_SUCCESS) {
2984 return res;
2985 }
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06002986 }
2987
Jon Ashburndb5a5bc2015-11-02 17:40:01 -07002988 /* Get the physical device extensions if they haven't been retrieved yet */
2989 if (phys_dev->device_extension_cache.capacity == 0) {
2990 if (!loader_init_ext_list(inst, &phys_dev->device_extension_cache)) {
2991 return VK_ERROR_OUT_OF_HOST_MEMORY;
2992 }
2993 res = loader_add_physical_device_extensions(
2994 inst, physicalDevice,
2995 phys_dev->this_icd->this_icd_lib->lib_name,
2996 &phys_dev->device_extension_cache);
2997 if (res != VK_SUCCESS) {
2998 return res;
2999 }
3000 }
3001 /* make sure requested extensions to be enabled are supported */
Jon Ashburn251258f2015-11-01 14:04:06 -07003002 res = loader_validate_device_extensions(phys_dev, &inst->device_layer_list, pCreateInfo);
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06003003 if (res != VK_SUCCESS) {
3004 return res;
3005 }
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003006
Courtney Goeltzenleuchter91371ff2015-07-06 20:46:50 -06003007 /*
3008 * NOTE: Need to filter the extensions to only those
3009 * supported by the ICD.
3010 * No ICD will advertise support for layers. An ICD
3011 * library could support a layer, but it would be
3012 * independent of the actual ICD, just in the same library.
3013 */
Chia-I Wu763a7492015-10-26 20:48:51 +08003014 filtered_extension_names = loader_stack_alloc(pCreateInfo->enabledExtensionNameCount * sizeof(char *));
Courtney Goeltzenleuchter91371ff2015-07-06 20:46:50 -06003015 if (!filtered_extension_names) {
3016 return VK_ERROR_OUT_OF_HOST_MEMORY;
3017 }
3018
3019 /* Copy user's data */
3020 memcpy(&device_create_info, pCreateInfo, sizeof(VkDeviceCreateInfo));
3021
3022 /* ICD's do not use layers */
Chia-I Wu763a7492015-10-26 20:48:51 +08003023 device_create_info.enabledLayerNameCount = 0;
Courtney Goeltzenleuchter91371ff2015-07-06 20:46:50 -06003024 device_create_info.ppEnabledLayerNames = NULL;
3025
Chia-I Wu763a7492015-10-26 20:48:51 +08003026 device_create_info.enabledExtensionNameCount = 0;
Courtney Goeltzenleuchter91371ff2015-07-06 20:46:50 -06003027 device_create_info.ppEnabledExtensionNames = (const char * const *) filtered_extension_names;
3028
Chia-I Wu763a7492015-10-26 20:48:51 +08003029 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) {
Courtney Goeltzenleuchter91371ff2015-07-06 20:46:50 -06003030 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i];
Jon Ashburnc4748dc2015-08-04 11:14:18 -06003031 VkExtensionProperties *prop = get_extension_property(extension_name,
Jon Ashburn251258f2015-11-01 14:04:06 -07003032 &phys_dev->device_extension_cache);
Courtney Goeltzenleuchter91371ff2015-07-06 20:46:50 -06003033 if (prop) {
Chia-I Wu763a7492015-10-26 20:48:51 +08003034 filtered_extension_names[device_create_info.enabledExtensionNameCount] = (char *) extension_name;
3035 device_create_info.enabledExtensionNameCount++;
Courtney Goeltzenleuchter91371ff2015-07-06 20:46:50 -06003036 }
3037 }
3038
Jon Ashburn251258f2015-11-01 14:04:06 -07003039 // since physicalDevice object maybe wrapped by a layer need to get unwrapped version
Jon Ashburn0c5eea22015-09-30 12:56:42 -06003040 // we haven't yet called down the chain for the layer to unwrap the object
Jon Ashburn251258f2015-11-01 14:04:06 -07003041 res = icd->CreateDevice(phys_dev->phys_dev, pCreateInfo, pAllocator, pDevice);
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06003042 if (res != VK_SUCCESS) {
3043 return res;
3044 }
3045
Jon Ashburne58f1a32015-08-28 13:38:21 -06003046 dev = loader_add_logical_device(inst, *pDevice, &icd->logical_device_list);
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06003047 if (dev == NULL) {
3048 return VK_ERROR_OUT_OF_HOST_MEMORY;
3049 }
3050 PFN_vkGetDeviceProcAddr get_proc_addr = icd->GetDeviceProcAddr;
3051 loader_init_device_dispatch_table(&dev->loader_dispatch, get_proc_addr,
Courtney Goeltzenleuchter08f54e72015-07-16 10:36:57 -06003052 *pDevice, *pDevice);
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06003053
3054 dev->loader_dispatch.CreateDevice = scratch_vkCreateDevice;
3055 loader_init_dispatch(*pDevice, &dev->loader_dispatch);
3056
Jon Ashburn182b8302015-08-11 14:49:54 -06003057 /* activate any layers on device chain which terminates with device*/
Jon Ashburne58f1a32015-08-28 13:38:21 -06003058 res = loader_enable_device_layers(inst, icd, dev, pCreateInfo, &inst->device_layer_list);
Jon Ashburn182b8302015-08-11 14:49:54 -06003059 if (res != VK_SUCCESS) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06003060 loader_destroy_logical_device(inst, dev);
Jon Ashburn182b8302015-08-11 14:49:54 -06003061 return res;
3062 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06003063 loader_activate_device_layers(inst, dev, *pDevice);
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06003064
Jon Ashburn251258f2015-11-01 14:04:06 -07003065 res = dev->loader_dispatch.CreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06003066
3067 dev->loader_dispatch.CreateDevice = icd->CreateDevice;
3068
Jon Ashburn2666e2f2015-05-15 15:09:35 -06003069 return res;
3070}
3071
Jon Ashburn8aa75cb2015-09-28 16:15:00 -06003072/**
3073 * Get an instance level or global level entry point address.
3074 * @param instance
3075 * @param pName
3076 * @return
3077 * If instance == NULL returns a global level entrypoint for all core entry points
3078 * If instance is valid returns a instance relative entry point for instance level
3079 * entry points both core and extensions.
3080 * Instance relative means call down the instance chain. Global means trampoline entry points.
3081 */
3082LOADER_EXPORT PFN_vkVoidFunction VKAPI vkGetInstanceProcAddr(VkInstance instance, const char * pName)
Jon Ashburn53c16772015-05-06 10:15:07 -06003083{
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06003084
Jon Ashburncedc15f2015-05-21 18:13:33 -06003085 void *addr;
Jon Ashburn53c16772015-05-06 10:15:07 -06003086
Jon Ashburn8aa75cb2015-09-28 16:15:00 -06003087 if (instance == VK_NULL_HANDLE) {
Jon Ashburn05b4ec62015-10-01 12:03:17 -06003088 /* get entrypoint addresses that are global (in the loader),
3089 doesn't include any instance extensions since they may not be enabled yet*/
Jon Ashburn0c5eea22015-09-30 12:56:42 -06003090
Jon Ashburn8aa75cb2015-09-28 16:15:00 -06003091 addr = globalGetProcAddr(pName);
Jon Ashburn8aa75cb2015-09-28 16:15:00 -06003092
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06003093 return addr;
3094 }
3095
Jon Ashburn05b4ec62015-10-01 12:03:17 -06003096
Jon Ashburn8aa75cb2015-09-28 16:15:00 -06003097 /* return any instance entrypoints that must resolve to loader code */
3098 addr = loader_non_passthrough_gipa(pName);
David Pinedo0fab78b2015-06-24 15:29:18 -06003099 if (addr) {
Jon Ashburn4ebc0962015-06-18 09:05:37 -06003100 return addr;
David Pinedo0fab78b2015-06-24 15:29:18 -06003101 }
Jon Ashburncedc15f2015-05-21 18:13:33 -06003102
Jon Ashburn05b4ec62015-10-01 12:03:17 -06003103 /* debug_report is a special case; need to return loader trampoline entrypoints
3104 * unless the extension is not enabled; also need to handle debug_report
3105 * utility functions */
Jon Ashburn0c5eea22015-09-30 12:56:42 -06003106 struct loader_instance *ptr_instance = loader_get_instance(instance);
Jon Ashburn05b4ec62015-10-01 12:03:17 -06003107 if (debug_report_instance_gpa(ptr_instance, pName, &addr)) {
3108 return addr;
3109 }
3110
3111 /* return the instance dispatch table entrypoint for core and extensions */
Jon Ashburncedc15f2015-05-21 18:13:33 -06003112 const VkLayerInstanceDispatchTable *disp_table = * (VkLayerInstanceDispatchTable **) instance;
3113 if (disp_table == NULL)
3114 return NULL;
3115
3116 addr = loader_lookup_instance_dispatch_table(disp_table, pName);
3117 if (addr)
3118 return addr;
Jon Ashburn53c16772015-05-06 10:15:07 -06003119
Jon Ashburn8aa75cb2015-09-28 16:15:00 -06003120 // NOTE: any instance extensions must be known to loader and resolved
3121 // in the above call to loader_lookup_instance_dispatch_table())
Jon Ashburn53c16772015-05-06 10:15:07 -06003122 return NULL;
3123}
3124
Jon Ashburn8aa75cb2015-09-28 16:15:00 -06003125/**
3126 * Get a device level or global level entry point address.
3127 * @param device
3128 * @param pName
3129 * @return
3130 * If device == NULL, returns a global level entrypoint for all core entry points
3131 * If device is valid, returns a device relative entry point for device level
3132 * entry points both core and extensions.
3133 * Device relative means call down the device chain. Global means trampoline entry points.
3134 */
3135LOADER_EXPORT PFN_vkVoidFunction VKAPI vkGetDeviceProcAddr(VkDevice device, const char * pName)
Courtney Goeltzenleuchter9a4f38c2015-06-22 17:45:21 -06003136{
Jon Ashburn8aa75cb2015-09-28 16:15:00 -06003137 void *addr;
Courtney Goeltzenleuchter9a4f38c2015-06-22 17:45:21 -06003138
Jon Ashburn1245cec2015-05-18 13:20:15 -06003139 if (device == VK_NULL_HANDLE) {
Jon Ashburn8aa75cb2015-09-28 16:15:00 -06003140 /* get entrypoint addresses that are global (in the loader)*/
3141 addr = globalGetProcAddr(pName);
3142 return addr;
Ian Elliott81ac44c2015-01-13 17:52:38 -07003143 }
Jon Ashburne18431b2015-04-13 18:10:06 -06003144
Jon Ashburnd43f9b62014-10-14 19:15:22 -06003145
Jon Ashburne18431b2015-04-13 18:10:06 -06003146 /* for entrypoints that loader must handle (ie non-dispatchable or create object)
3147 make sure the loader entrypoint is returned */
Jon Ashburn8aa75cb2015-09-28 16:15:00 -06003148 addr = loader_non_passthrough_gdpa(pName);
Ian Elliottfdf00b62015-04-15 12:53:19 -06003149 if (addr) {
Jon Ashburne18431b2015-04-13 18:10:06 -06003150 return addr;
Ian Elliottfdf00b62015-04-15 12:53:19 -06003151 }
Jon Ashburne18431b2015-04-13 18:10:06 -06003152
3153 /* return the dispatch table entrypoint for the fastest case */
Jon Ashburn1245cec2015-05-18 13:20:15 -06003154 const VkLayerDispatchTable *disp_table = * (VkLayerDispatchTable **) device;
Jon Ashburnd43f9b62014-10-14 19:15:22 -06003155 if (disp_table == NULL)
3156 return NULL;
3157
Jon Ashburnfce93d92015-05-12 17:26:48 -06003158 addr = loader_lookup_device_dispatch_table(disp_table, pName);
Chia-I Wu38e5a2c2015-01-04 11:12:47 +08003159 if (addr)
3160 return addr;
Jon Ashburnd43f9b62014-10-14 19:15:22 -06003161 else {
Jon Ashburn1245cec2015-05-18 13:20:15 -06003162 if (disp_table->GetDeviceProcAddr == NULL)
Jon Ashburnd43f9b62014-10-14 19:15:22 -06003163 return NULL;
Jon Ashburn1245cec2015-05-18 13:20:15 -06003164 return disp_table->GetDeviceProcAddr(device, pName);
Jon Ashburnd43f9b62014-10-14 19:15:22 -06003165 }
3166}
3167
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -06003168LOADER_EXPORT VkResult VKAPI vkEnumerateInstanceExtensionProperties(
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003169 const char* pLayerName,
Chia-I Wu763a7492015-10-26 20:48:51 +08003170 uint32_t* pPropertyCount,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003171 VkExtensionProperties* pProperties)
3172{
Jon Ashburnb8605fe2015-09-18 12:53:16 -06003173 struct loader_extension_list *global_ext_list=NULL;
Jon Ashburn182b8302015-08-11 14:49:54 -06003174 struct loader_layer_list instance_layers;
Jon Ashburnc1d1eb72015-08-14 11:57:54 -06003175 struct loader_extension_list icd_extensions;
Jon Ashburn754f1992015-08-18 18:04:47 -06003176 struct loader_icd_libs icd_libs;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003177 uint32_t copy_size;
3178
Jon Ashburn413d6582015-08-28 15:19:27 -06003179 tls_instance = NULL;
Jon Ashburnc1d1eb72015-08-14 11:57:54 -06003180 memset(&icd_extensions, 0, sizeof(icd_extensions));
Mike Stroyana73e50c2015-10-01 15:23:48 -06003181 memset(&instance_layers, 0, sizeof(instance_layers));
Jon Ashburn754f1992015-08-18 18:04:47 -06003182 loader_platform_thread_once(&once_init, loader_initialize);
Jon Ashburnc1d1eb72015-08-14 11:57:54 -06003183
Jon Ashburn182b8302015-08-11 14:49:54 -06003184 /* get layer libraries if needed */
3185 if (pLayerName && strlen(pLayerName) != 0) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06003186 loader_layer_scan(NULL, &instance_layers, NULL);
Jon Ashburn182b8302015-08-11 14:49:54 -06003187 for (uint32_t i = 0; i < instance_layers.count; i++) {
3188 struct loader_layer_properties *props = &instance_layers.list[i];
3189 if (strcmp(props->info.layerName, pLayerName) == 0) {
3190 global_ext_list = &props->instance_extension_list;
3191 }
3192 }
3193 }
3194 else {
Jon Ashburn754f1992015-08-18 18:04:47 -06003195 /* Scan/discover all ICD libraries */
3196 memset(&icd_libs, 0 , sizeof(struct loader_icd_libs));
Jon Ashburne58f1a32015-08-28 13:38:21 -06003197 loader_icd_scan(NULL, &icd_libs);
Jon Ashburnc1d1eb72015-08-14 11:57:54 -06003198 /* get extensions from all ICD's, merge so no duplicates */
Jon Ashburne58f1a32015-08-28 13:38:21 -06003199 loader_get_icd_loader_instance_extensions(NULL, &icd_libs, &icd_extensions);
3200 loader_scanned_icd_clear(NULL, &icd_libs);
Jon Ashburnc1d1eb72015-08-14 11:57:54 -06003201 global_ext_list = &icd_extensions;
Jon Ashburn182b8302015-08-11 14:49:54 -06003202 }
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003203
Jon Ashburn182b8302015-08-11 14:49:54 -06003204 if (global_ext_list == NULL) {
Mike Stroyana73e50c2015-10-01 15:23:48 -06003205 loader_destroy_layer_list(NULL, &instance_layers);
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -06003206 return VK_ERROR_LAYER_NOT_PRESENT;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003207 }
3208
3209 if (pProperties == NULL) {
Chia-I Wu763a7492015-10-26 20:48:51 +08003210 *pPropertyCount = global_ext_list->count;
Mike Stroyana73e50c2015-10-01 15:23:48 -06003211 loader_destroy_layer_list(NULL, &instance_layers);
Jon Ashburne58f1a32015-08-28 13:38:21 -06003212 loader_destroy_ext_list(NULL, &icd_extensions);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003213 return VK_SUCCESS;
3214 }
3215
Chia-I Wu763a7492015-10-26 20:48:51 +08003216 copy_size = *pPropertyCount < global_ext_list->count ? *pPropertyCount : global_ext_list->count;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003217 for (uint32_t i = 0; i < copy_size; i++) {
3218 memcpy(&pProperties[i],
Jon Ashburn182b8302015-08-11 14:49:54 -06003219 &global_ext_list->list[i],
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003220 sizeof(VkExtensionProperties));
3221 }
Chia-I Wu763a7492015-10-26 20:48:51 +08003222 *pPropertyCount = copy_size;
Jon Ashburne58f1a32015-08-28 13:38:21 -06003223 loader_destroy_ext_list(NULL, &icd_extensions);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003224
Jon Ashburn182b8302015-08-11 14:49:54 -06003225 if (copy_size < global_ext_list->count) {
Mike Stroyana73e50c2015-10-01 15:23:48 -06003226 loader_destroy_layer_list(NULL, &instance_layers);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003227 return VK_INCOMPLETE;
3228 }
3229
Mike Stroyana73e50c2015-10-01 15:23:48 -06003230 loader_destroy_layer_list(NULL, &instance_layers);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003231 return VK_SUCCESS;
3232}
3233
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -06003234LOADER_EXPORT VkResult VKAPI vkEnumerateInstanceLayerProperties(
Chia-I Wu763a7492015-10-26 20:48:51 +08003235 uint32_t* pPropertyCount,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003236 VkLayerProperties* pProperties)
Tony Barbour426b9052015-06-24 16:06:58 -06003237{
Jon Ashburnb40f2562015-05-29 13:15:39 -06003238
Jon Ashburn182b8302015-08-11 14:49:54 -06003239 struct loader_layer_list instance_layer_list;
Jon Ashburn413d6582015-08-28 15:19:27 -06003240 tls_instance = NULL;
Jon Ashburn182b8302015-08-11 14:49:54 -06003241
Jon Ashburn754f1992015-08-18 18:04:47 -06003242 loader_platform_thread_once(&once_init, loader_initialize);
Courtney Goeltzenleuchter0199e952015-02-27 15:19:33 -07003243
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003244 uint32_t copy_size;
Jon Ashburneb2728b2015-04-10 14:33:07 -06003245
Jon Ashburn182b8302015-08-11 14:49:54 -06003246 /* get layer libraries */
3247 memset(&instance_layer_list, 0, sizeof(instance_layer_list));
Jon Ashburne58f1a32015-08-28 13:38:21 -06003248 loader_layer_scan(NULL, &instance_layer_list, NULL);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003249
3250 if (pProperties == NULL) {
Chia-I Wu763a7492015-10-26 20:48:51 +08003251 *pPropertyCount = instance_layer_list.count;
Jon Ashburne58f1a32015-08-28 13:38:21 -06003252 loader_destroy_layer_list(NULL, &instance_layer_list);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003253 return VK_SUCCESS;
3254 }
3255
Chia-I Wu763a7492015-10-26 20:48:51 +08003256 copy_size = (*pPropertyCount < instance_layer_list.count) ? *pPropertyCount : instance_layer_list.count;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003257 for (uint32_t i = 0; i < copy_size; i++) {
Jon Ashburn182b8302015-08-11 14:49:54 -06003258 memcpy(&pProperties[i], &instance_layer_list.list[i].info, sizeof(VkLayerProperties));
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003259 }
Chia-I Wu763a7492015-10-26 20:48:51 +08003260 *pPropertyCount = copy_size;
Jon Ashburne58f1a32015-08-28 13:38:21 -06003261 loader_destroy_layer_list(NULL, &instance_layer_list);
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003262
Jon Ashburn182b8302015-08-11 14:49:54 -06003263 if (copy_size < instance_layer_list.count) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003264 return VK_INCOMPLETE;
3265 }
Tony Barbour426b9052015-06-24 16:06:58 -06003266
3267 return VK_SUCCESS;
3268}
3269
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -06003270VkResult VKAPI loader_EnumerateDeviceExtensionProperties(
Jon Ashburn251258f2015-11-01 14:04:06 -07003271 VkPhysicalDevice physicalDevice,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003272 const char* pLayerName,
Chia-I Wu763a7492015-10-26 20:48:51 +08003273 uint32_t* pPropertyCount,
Tony Barbour426b9052015-06-24 16:06:58 -06003274 VkExtensionProperties* pProperties)
3275{
Jon Ashburn251258f2015-11-01 14:04:06 -07003276 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003277 uint32_t copy_size;
Courtney Goeltzenleuchter0199e952015-02-27 15:19:33 -07003278
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003279 uint32_t count;
Jon Ashburnb8605fe2015-09-18 12:53:16 -06003280 struct loader_extension_list *dev_ext_list=NULL;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003281
Jon Ashburn182b8302015-08-11 14:49:54 -06003282 /* get layer libraries if needed */
3283 if (pLayerName && strlen(pLayerName) != 0) {
Jon Ashburn251258f2015-11-01 14:04:06 -07003284 for (uint32_t i = 0; i < phys_dev->this_instance->device_layer_list.count; i++) {
3285 struct loader_layer_properties *props = &phys_dev->this_instance->device_layer_list.list[i];
Jon Ashburn182b8302015-08-11 14:49:54 -06003286 if (strcmp(props->info.layerName, pLayerName) == 0) {
3287 dev_ext_list = &props->device_extension_list;
3288 }
3289 }
3290 }
3291 else {
Jon Ashburndb5a5bc2015-11-02 17:40:01 -07003292 /* this case is during the call down the instance chain */
3293 struct loader_icd *icd = phys_dev->this_icd;
3294 VkResult res;
3295 res = icd->EnumerateDeviceExtensionProperties(phys_dev->phys_dev, NULL, pPropertyCount, pProperties);
3296 if (pProperties != NULL && res == VK_SUCCESS) {
3297 /* initialize dev_extension list within the physicalDevice object */
3298 res = loader_init_physical_device_extensions(phys_dev->this_instance,
3299 phys_dev, *pPropertyCount, pProperties,
3300 &phys_dev->device_extension_cache);
3301 }
3302 return res;
Jon Ashburn182b8302015-08-11 14:49:54 -06003303 }
3304
Jon Ashburnb8605fe2015-09-18 12:53:16 -06003305 count = (dev_ext_list == NULL) ? 0: dev_ext_list->count;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003306 if (pProperties == NULL) {
Chia-I Wu763a7492015-10-26 20:48:51 +08003307 *pPropertyCount = count;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003308 return VK_SUCCESS;
3309 }
3310
Chia-I Wu763a7492015-10-26 20:48:51 +08003311 copy_size = *pPropertyCount < count ? *pPropertyCount : count;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003312 for (uint32_t i = 0; i < copy_size; i++) {
3313 memcpy(&pProperties[i],
Jon Ashburn182b8302015-08-11 14:49:54 -06003314 &dev_ext_list->list[i],
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003315 sizeof(VkExtensionProperties));
3316 }
Chia-I Wu763a7492015-10-26 20:48:51 +08003317 *pPropertyCount = copy_size;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003318
3319 if (copy_size < count) {
3320 return VK_INCOMPLETE;
3321 }
3322
3323 return VK_SUCCESS;
3324}
3325
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -06003326VkResult VKAPI loader_EnumerateDeviceLayerProperties(
Jon Ashburn251258f2015-11-01 14:04:06 -07003327 VkPhysicalDevice physicalDevice,
Chia-I Wu763a7492015-10-26 20:48:51 +08003328 uint32_t* pPropertyCount,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003329 VkLayerProperties* pProperties)
3330{
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003331 uint32_t copy_size;
Jon Ashburn251258f2015-11-01 14:04:06 -07003332 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003333
Jon Ashburn251258f2015-11-01 14:04:06 -07003334 uint32_t count = phys_dev->this_instance->device_layer_list.count;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003335
3336 if (pProperties == NULL) {
Chia-I Wu763a7492015-10-26 20:48:51 +08003337 *pPropertyCount = count;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003338 return VK_SUCCESS;
3339 }
3340
Chia-I Wu763a7492015-10-26 20:48:51 +08003341 copy_size = (*pPropertyCount < count) ? *pPropertyCount : count;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003342 for (uint32_t i = 0; i < copy_size; i++) {
Jon Ashburn251258f2015-11-01 14:04:06 -07003343 memcpy(&pProperties[i], &(phys_dev->this_instance->device_layer_list.list[i].info), sizeof(VkLayerProperties));
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003344 }
Chia-I Wu763a7492015-10-26 20:48:51 +08003345 *pPropertyCount = copy_size;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003346
3347 if (copy_size < count) {
3348 return VK_INCOMPLETE;
3349 }
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003350
3351 return VK_SUCCESS;
Jon Ashburn2666e2f2015-05-15 15:09:35 -06003352}