blob: 9ab4729464a63d89fa5c5899274fde49dbd43d90 [file] [log] [blame]
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001/*
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08002 *
Courtney Goeltzenleuchterfcbe16f2015-10-29 13:50:34 -06003 * Copyright (C) 2015 Valve Corporation
Courtney Goeltzenleuchterf821dad2015-12-02 14:53:22 -07004 * Copyright (C) 2015 Google Inc.
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08005 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
Chia-I Wu701f3f62014-09-02 08:32:09 +080023 *
Courtney Goeltzenleuchter05559522015-10-30 11:14:30 -060024 * Author: Chia-I Wu <olvaffe@gmail.com>
25 * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
26 * Author: Ian Elliott <ian@LunarG.com>
27 * Author: Jon Ashburn <jon@lunarg.com>
28 *
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080029 */
Mark Lobodzinskifaa90812015-11-25 13:26:15 -070030
Jon Ashburn6b4d70c2014-10-22 18:13:16 -060031#define _GNU_SOURCE
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080032#include <stdio.h>
33#include <stdlib.h>
34#include <stdarg.h>
35#include <stdbool.h>
36#include <string.h>
37
Chia-I Wu13a61a52014-08-04 11:18:20 +080038#include <sys/types.h>
Johannes van Waveren9bd805012015-10-28 11:45:00 -050039#if defined(_WIN32)
Ian Elliott2d4ab1e2015-01-13 17:52:38 -070040#include "dirent_on_windows.h"
Johannes van Waveren9bd805012015-10-28 11:45:00 -050041#else // _WIN32
Chia-I Wu13a61a52014-08-04 11:18:20 +080042#include <dirent.h>
Johannes van Waveren9bd805012015-10-28 11:45:00 -050043#endif // _WIN32
Tobin Ehlisb835d1b2015-07-03 10:34:49 -060044#include "vk_loader_platform.h"
Chia-I Wu19300602014-08-04 08:03:57 +080045#include "loader.h"
Jon Ashburn27cd5842015-05-12 17:26:48 -060046#include "gpa_helper.h"
47#include "table_ops.h"
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -060048#include "debug_report.h"
Ian Elliott954fa342015-10-30 15:28:23 -060049#include "wsi.h"
David Pinedo9316d3b2015-11-06 12:54:48 -070050#include "vulkan/vk_icd.h"
Jon Ashburn2077e382015-06-29 11:25:34 -060051#include "cJSON.h"
Jon Ashburnfc1031e2015-11-17 15:31:02 -070052#include "murmurhash.h"
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080053
Courtney Goeltzenleuchtered488302015-06-01 14:09:34 -060054static loader_platform_dl_handle loader_add_layer_lib(
Jon Ashburne39a4f82015-08-28 13:38:21 -060055 const struct loader_instance *inst,
Courtney Goeltzenleuchtered488302015-06-01 14:09:34 -060056 const char *chain_type,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -060057 struct loader_layer_properties *layer_prop);
Courtney Goeltzenleuchtered488302015-06-01 14:09:34 -060058
59static void loader_remove_layer_lib(
60 struct loader_instance *inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -060061 struct loader_layer_properties *layer_prop);
Courtney Goeltzenleuchtered488302015-06-01 14:09:34 -060062
Jon Ashburn27cd5842015-05-12 17:26:48 -060063struct loader_struct loader = {0};
Jon Ashburn87d6aa92015-08-28 15:19:27 -060064// TLS for instance for alloc/free callbacks
65THREAD_LOCAL_DECL struct loader_instance *tls_instance;
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080066
Jon Ashburn6e6a2162015-12-10 08:51:10 -070067static bool loader_init_generic_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -060068 const struct loader_instance *inst,
Jon Ashburn6e6a2162015-12-10 08:51:10 -070069 struct loader_generic_list *list_info,
70 size_t element_size);
Courtney Goeltzenleuchter9ec39ac2015-06-22 17:45:21 -060071
Courtney Goeltzenleuchter0ef13a02015-12-16 16:19:46 -070072static size_t loader_platform_combine_path(char *dest, size_t len, ...);
Daniel Dadap00b4aba2015-09-30 11:50:51 -050073
Jon Ashburn24cd4be2015-11-01 14:04:06 -070074struct loader_phys_dev_per_icd {
75 uint32_t count;
76 VkPhysicalDevice *phys_devs;
77};
78
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -060079enum loader_debug {
Courtney Goeltzenleuchterf3387652015-07-08 18:41:08 -060080 LOADER_INFO_BIT = 0x01,
81 LOADER_WARN_BIT = 0x02,
82 LOADER_PERF_BIT = 0x04,
83 LOADER_ERROR_BIT = 0x08,
84 LOADER_DEBUG_BIT = 0x10,
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -060085};
86
87uint32_t g_loader_debug = 0;
88uint32_t g_loader_log_msgs = 0;
89
Jon Ashburn6301a0f2015-05-29 13:15:39 -060090//thread safety lock for accessing global data structures such as "loader"
91// all entrypoints on the instance chain need to be locked except GPA
Jon Ashburn2077e382015-06-29 11:25:34 -060092// additionally CreateDevice and DestroyDevice needs to be locked
Jon Ashburn6301a0f2015-05-29 13:15:39 -060093loader_platform_thread_mutex loader_lock;
Jon Ashburn6461ef22015-09-22 13:11:00 -060094loader_platform_thread_mutex loader_json_lock;
Jon Ashburn6301a0f2015-05-29 13:15:39 -060095
Ian Elliottd3ef02f2015-07-06 14:36:13 -060096// This table contains the loader's instance dispatch table, which contains
97// default functions if no instance layers are activated. This contains
98// pointers to "terminator functions".
Jon Ashburn6301a0f2015-05-29 13:15:39 -060099const VkLayerInstanceDispatchTable instance_disp = {
Jon Ashburn69e9ea22015-09-28 16:15:00 -0600100 .GetInstanceProcAddr = vkGetInstanceProcAddr,
Jon Ashburn27cd5842015-05-12 17:26:48 -0600101 .CreateInstance = loader_CreateInstance,
102 .DestroyInstance = loader_DestroyInstance,
103 .EnumeratePhysicalDevices = loader_EnumeratePhysicalDevices,
Chris Forbesbc0bb772015-06-21 22:55:02 +1200104 .GetPhysicalDeviceFeatures = loader_GetPhysicalDeviceFeatures,
Courtney Goeltzenleuchter2caec862015-07-12 12:52:09 -0600105 .GetPhysicalDeviceFormatProperties = loader_GetPhysicalDeviceFormatProperties,
Jon Ashburn754864f2015-07-23 18:49:07 -0600106 .GetPhysicalDeviceImageFormatProperties = loader_GetPhysicalDeviceImageFormatProperties,
Tony Barbour59a47322015-06-24 16:06:58 -0600107 .GetPhysicalDeviceProperties = loader_GetPhysicalDeviceProperties,
Cody Northropd0802882015-08-03 17:04:53 -0600108 .GetPhysicalDeviceQueueFamilyProperties = loader_GetPhysicalDeviceQueueFamilyProperties,
Tony Barbour59a47322015-06-24 16:06:58 -0600109 .GetPhysicalDeviceMemoryProperties = loader_GetPhysicalDeviceMemoryProperties,
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -0600110 .EnumerateDeviceExtensionProperties = loader_EnumerateDeviceExtensionProperties,
111 .EnumerateDeviceLayerProperties = loader_EnumerateDeviceLayerProperties,
Mark Lobodzinski16e8bef2015-07-03 15:58:09 -0600112 .GetPhysicalDeviceSparseImageFormatProperties = loader_GetPhysicalDeviceSparseImageFormatProperties,
Ian Elliottfb42cd72015-11-25 14:43:02 -0700113 .DestroySurfaceKHR = loader_DestroySurfaceKHR,
Ian Elliott7e40db92015-08-21 15:09:33 -0600114 .GetPhysicalDeviceSurfaceSupportKHR = loader_GetPhysicalDeviceSurfaceSupportKHR,
Ian Elliott486c5502015-11-19 16:05:09 -0700115 .GetPhysicalDeviceSurfaceCapabilitiesKHR = loader_GetPhysicalDeviceSurfaceCapabilitiesKHR,
116 .GetPhysicalDeviceSurfaceFormatsKHR = loader_GetPhysicalDeviceSurfaceFormatsKHR,
117 .GetPhysicalDeviceSurfacePresentModesKHR = loader_GetPhysicalDeviceSurfacePresentModesKHR,
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700118 .CreateDebugReportCallbackEXT = loader_CreateDebugReportCallback,
119 .DestroyDebugReportCallbackEXT = loader_DestroyDebugReportCallback,
120 .DebugReportMessageEXT = loader_DebugReportMessage,
Ian Elliottdb4300a2015-11-23 10:17:23 -0700121#ifdef VK_USE_PLATFORM_MIR_KHR
Jon Ashburnf72a04b2015-11-25 17:55:49 -0700122 .CreateMirSurfaceKHR = loader_CreateMirSurfaceKHR,
Ian Elliott919fa302015-11-24 15:39:10 -0700123 .GetPhysicalDeviceMirPresentationSupportKHR = loader_GetPhysicalDeviceMirPresentationSupportKHR,
Ian Elliottdb4300a2015-11-23 10:17:23 -0700124#endif
125#ifdef VK_USE_PLATFORM_WAYLAND_KHR
Jon Ashburnf72a04b2015-11-25 17:55:49 -0700126 .CreateWaylandSurfaceKHR = loader_CreateWaylandSurfaceKHR,
Ian Elliott919fa302015-11-24 15:39:10 -0700127 .GetPhysicalDeviceWaylandPresentationSupportKHR = loader_GetPhysicalDeviceWaylandPresentationSupportKHR,
Ian Elliottdb4300a2015-11-23 10:17:23 -0700128#endif
129#ifdef VK_USE_PLATFORM_WIN32_KHR
Jon Ashburnf72a04b2015-11-25 17:55:49 -0700130 .CreateWin32SurfaceKHR = loader_CreateWin32SurfaceKHR,
Ian Elliott919fa302015-11-24 15:39:10 -0700131 .GetPhysicalDeviceWin32PresentationSupportKHR = loader_GetPhysicalDeviceWin32PresentationSupportKHR,
Ian Elliottdb4300a2015-11-23 10:17:23 -0700132#endif
133#ifdef VK_USE_PLATFORM_XCB_KHR
Jon Ashburnf72a04b2015-11-25 17:55:49 -0700134 .CreateXcbSurfaceKHR = loader_CreateXcbSurfaceKHR,
Ian Elliott919fa302015-11-24 15:39:10 -0700135 .GetPhysicalDeviceXcbPresentationSupportKHR = loader_GetPhysicalDeviceXcbPresentationSupportKHR,
Ian Elliottdb4300a2015-11-23 10:17:23 -0700136#endif
137#ifdef VK_USE_PLATFORM_XLIB_KHR
Jon Ashburnf72a04b2015-11-25 17:55:49 -0700138 .CreateXlibSurfaceKHR = loader_CreateXlibSurfaceKHR,
Ian Elliott919fa302015-11-24 15:39:10 -0700139 .GetPhysicalDeviceXlibPresentationSupportKHR = loader_GetPhysicalDeviceXlibPresentationSupportKHR,
Ian Elliottdb4300a2015-11-23 10:17:23 -0700140#endif
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -0700141#ifdef VK_USE_PLATFORM_ANDROID_KHR
142 .CreateAndroidSurfaceKHR = loader_CreateAndroidSurfaceKHR,
143#endif
Jon Ashburn27cd5842015-05-12 17:26:48 -0600144};
145
Jon Ashburn8810c5f2015-08-18 18:04:47 -0600146LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_init);
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700147
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600148void* loader_heap_alloc(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600149 const struct loader_instance *instance,
150 size_t size,
Jon Ashburn39fbd4e2015-12-10 18:17:34 -0700151 VkSystemAllocationScope alloc_scope)
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600152{
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800153 if (instance && instance->alloc_callbacks.pfnAllocation) {
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600154 /* TODO: What should default alignment be? 1, 4, 8, other? */
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800155 return instance->alloc_callbacks.pfnAllocation(instance->alloc_callbacks.pUserData, size, 4, alloc_scope);
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600156 }
157 return malloc(size);
158}
159
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600160void loader_heap_free(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600161 const struct loader_instance *instance,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800162 void *pMemory)
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600163{
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800164 if (pMemory == NULL) return;
Jon Ashburneacfa3a2015-08-14 12:51:47 -0600165 if (instance && instance->alloc_callbacks.pfnFree) {
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800166 instance->alloc_callbacks.pfnFree(instance->alloc_callbacks.pUserData, pMemory);
Jon Ashburnd2c171b2015-08-13 08:28:48 -0600167 return;
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600168 }
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800169 free(pMemory);
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600170}
171
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600172void* loader_heap_realloc(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600173 const struct loader_instance *instance,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800174 void *pMemory,
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600175 size_t orig_size,
176 size_t size,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800177 VkSystemAllocationScope alloc_scope)
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600178{
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800179 if (pMemory == NULL || orig_size == 0)
Chia-I Wuf7458c52015-10-26 21:10:41 +0800180 return loader_heap_alloc(instance, size, alloc_scope);
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600181 if (size == 0) {
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800182 loader_heap_free(instance, pMemory);
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600183 return NULL;
184 }
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800185 if (instance && instance->alloc_callbacks.pfnAllocation) {
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600186 if (size <= orig_size) {
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800187 memset(((uint8_t *)pMemory) + size, 0, orig_size - size);
188 return pMemory;
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600189 }
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800190 void *new_ptr = instance->alloc_callbacks.pfnAllocation(instance->alloc_callbacks.pUserData, size, 4, alloc_scope);
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600191 if (!new_ptr)
192 return NULL;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800193 memcpy(new_ptr, pMemory, orig_size);
194 instance->alloc_callbacks.pfnFree(instance->alloc_callbacks.pUserData, pMemory);
Jon Ashburne3753b32015-10-21 16:09:27 -0600195 return new_ptr;
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600196 }
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800197 return realloc(pMemory, size);
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600198}
199
Jon Ashburn87d6aa92015-08-28 15:19:27 -0600200void *loader_tls_heap_alloc(size_t size)
201{
Chia-I Wucf804e82015-10-31 00:31:16 +0800202 return loader_heap_alloc(tls_instance, size, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
Jon Ashburn87d6aa92015-08-28 15:19:27 -0600203}
204
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800205void loader_tls_heap_free(void *pMemory)
Jon Ashburn87d6aa92015-08-28 15:19:27 -0600206{
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800207 loader_heap_free(tls_instance, pMemory);
Jon Ashburn87d6aa92015-08-28 15:19:27 -0600208}
209
Courtney Goeltzenleuchter73477392015-12-03 13:48:01 -0700210static void loader_log(const struct loader_instance *inst, VkFlags msg_type, int32_t msg_code,
Jon Ashburnffad94d2015-06-30 14:46:22 -0700211 const char *format, ...)
212{
Jon Ashburn86723b02015-07-31 15:47:59 -0600213 char msg[512];
Jon Ashburnffad94d2015-06-30 14:46:22 -0700214 va_list ap;
215 int ret;
216
Jon Ashburnffad94d2015-06-30 14:46:22 -0700217 va_start(ap, format);
218 ret = vsnprintf(msg, sizeof(msg), format, ap);
219 if ((ret >= (int) sizeof(msg)) || ret < 0) {
220 msg[sizeof(msg)-1] = '\0';
221 }
222 va_end(ap);
223
Courtney Goeltzenleuchter73477392015-12-03 13:48:01 -0700224 if (inst) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700225 util_DebugReportMessage(inst, msg_type, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, (uint64_t) inst, 0, msg_code, "loader", msg);
Courtney Goeltzenleuchter73477392015-12-03 13:48:01 -0700226 }
227
228 if (!(msg_type & g_loader_log_msgs)) {
229 return;
230 }
231
Ian Elliott4470a302015-02-17 10:33:47 -0700232#if defined(WIN32)
Jon Ashburnffad94d2015-06-30 14:46:22 -0700233 OutputDebugString(msg);
mschottb9cdb782015-07-22 14:11:29 +0200234 OutputDebugString("\n");
Jon Ashburnffad94d2015-06-30 14:46:22 -0700235#endif
236 fputs(msg, stderr);
237 fputc('\n', stderr);
238}
239
240#if defined(WIN32)
Tony Barbourea968902015-07-29 14:26:21 -0600241static char *loader_get_next_path(char *path);
Jon Ashburnffad94d2015-06-30 14:46:22 -0700242/**
243* Find the list of registry files (names within a key) in key "location".
244*
245* This function looks in the registry (hive = DEFAULT_VK_REGISTRY_HIVE) key as given in "location"
246* for a list or name/values which are added to a returned list (function return value).
247* The DWORD values within the key must be 0 or they are skipped.
Jon Ashburne39a4f82015-08-28 13:38:21 -0600248* Function return is a string with a ';' separated list of filenames.
Jon Ashburnffad94d2015-06-30 14:46:22 -0700249* Function return is NULL if no valid name/value pairs are found in the key,
250* or the key is not found.
251*
252* \returns
253* A string list of filenames as pointer.
254* When done using the returned string list, pointer should be freed.
255*/
Jon Ashburne39a4f82015-08-28 13:38:21 -0600256static char *loader_get_registry_files(const struct loader_instance *inst, char *location)
Jon Ashburnffad94d2015-06-30 14:46:22 -0700257{
258 LONG rtn_value;
259 HKEY hive, key;
Piers Daniell524ec732015-11-05 16:58:26 -0700260 DWORD access_flags;
Jon Ashburnffad94d2015-06-30 14:46:22 -0700261 char name[2048];
262 char *out = NULL;
Tony Barbourea968902015-07-29 14:26:21 -0600263 char *loc = location;
264 char *next;
Jon Ashburnffad94d2015-06-30 14:46:22 -0700265 DWORD idx = 0;
266 DWORD name_size = sizeof(name);
267 DWORD value;
268 DWORD total_size = 4096;
269 DWORD value_size = sizeof(value);
Tony Barbourea968902015-07-29 14:26:21 -0600270
271 while(*loc)
272 {
273 next = loader_get_next_path(loc);
274 hive = DEFAULT_VK_REGISTRY_HIVE;
Piers Daniell524ec732015-11-05 16:58:26 -0700275 access_flags = KEY_QUERY_VALUE;
Tony Barbourea968902015-07-29 14:26:21 -0600276 rtn_value = RegOpenKeyEx(hive, loc, 0, access_flags, &key);
277 if (rtn_value != ERROR_SUCCESS) {
278 // We didn't find the key. Try the 32-bit hive (where we've seen the
279 // key end up on some people's systems):
280 access_flags |= KEY_WOW64_32KEY;
281 rtn_value = RegOpenKeyEx(hive, loc, 0, access_flags, &key);
282 if (rtn_value != ERROR_SUCCESS) {
283 // We still couldn't find the key, so give up:
284 loc = next;
285 continue;
Jon Ashburnffad94d2015-06-30 14:46:22 -0700286 }
Jon Ashburnffad94d2015-06-30 14:46:22 -0700287 }
Tony Barbourea968902015-07-29 14:26:21 -0600288
Jon Ashburne39a4f82015-08-28 13:38:21 -0600289 while ((rtn_value = RegEnumValue(key, idx++, name, &name_size, NULL, NULL, (LPBYTE) &value, &value_size)) == ERROR_SUCCESS) {
Tony Barbourea968902015-07-29 14:26:21 -0600290 if (value_size == sizeof(value) && value == 0) {
291 if (out == NULL) {
Courtney Goeltzenleuchter2961e1c2015-11-02 17:43:04 -0700292 out = loader_heap_alloc(inst, total_size, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Tony Barbourea968902015-07-29 14:26:21 -0600293 out[0] = '\0';
294 }
295 else if (strlen(out) + name_size + 1 > total_size) {
Courtney Goeltzenleuchter2961e1c2015-11-02 17:43:04 -0700296 out = loader_heap_realloc(inst, out, total_size, total_size * 2, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Tony Barbourea968902015-07-29 14:26:21 -0600297 total_size *= 2;
298 }
299 if (out == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700300 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Out of memory, failed loader_get_registry_files");
Tony Barbourea968902015-07-29 14:26:21 -0600301 return NULL;
302 }
303 if (strlen(out) == 0)
304 snprintf(out, name_size + 1, "%s", name);
305 else
306 snprintf(out + strlen(out), name_size + 2, "%c%s", PATH_SEPERATOR, name);
307 }
308 name_size = 2048;
309 }
310 loc = next;
Jon Ashburnffad94d2015-06-30 14:46:22 -0700311 }
Tony Barbourea968902015-07-29 14:26:21 -0600312
Jon Ashburnffad94d2015-06-30 14:46:22 -0700313 return out;
314}
315
Ian Elliott4470a302015-02-17 10:33:47 -0700316#endif // WIN32
317
Jon Ashburnc7237a72015-08-03 09:08:46 -0600318/**
Daniel Dadap00b4aba2015-09-30 11:50:51 -0500319 * Combine path elements, separating each element with the platform-specific
320 * directory separator, and save the combined string to a destination buffer,
321 * not exceeding the given length. Path elements are given as variadic args,
322 * with a NULL element terminating the list.
323 *
324 * \returns the total length of the combined string, not including an ASCII
325 * NUL termination character. This length may exceed the available storage:
326 * in this case, the written string will be truncated to avoid a buffer
327 * overrun, and the return value will greater than or equal to the storage
328 * size. A NULL argument may be provided as the destination buffer in order
329 * to determine the required string length without actually writing a string.
330 */
331
Courtney Goeltzenleuchter0ef13a02015-12-16 16:19:46 -0700332static size_t loader_platform_combine_path(char *dest, size_t len, ...)
Daniel Dadap00b4aba2015-09-30 11:50:51 -0500333{
Courtney Goeltzenleuchter0ef13a02015-12-16 16:19:46 -0700334 size_t required_len = 0;
Daniel Dadap00b4aba2015-09-30 11:50:51 -0500335 va_list ap;
336 const char *component;
337
338 va_start(ap, len);
339
340 while((component = va_arg(ap, const char *))) {
341 if (required_len > 0) {
342 // This path element is not the first non-empty element; prepend
343 // a directory separator if space allows
344 if (dest && required_len + 1 < len) {
345 snprintf(dest + required_len, len - required_len, "%c",
346 DIRECTORY_SYMBOL);
347 }
348 required_len++;
349 }
350
351 if (dest && required_len < len) {
352 strncpy(dest + required_len, component, len - required_len);
353 }
354 required_len += strlen(component);
355 }
356
357 va_end(ap);
358
359 // strncpy(3) won't add a NUL terminating byte in the event of truncation.
360 if (dest && required_len >= len) {
361 dest[len - 1] = '\0';
362 }
363
364 return required_len;
365}
366
367
368/**
Jon Ashburnc7237a72015-08-03 09:08:46 -0600369 * Given string of three part form "maj.min.pat" convert to a vulkan version
370 * number.
371 */
372static uint32_t loader_make_version(const char *vers_str)
373{
Jon Ashburn432d2762015-09-18 12:53:16 -0600374 uint32_t vers = 0, major=0, minor=0, patch=0;
Jon Ashburnc7237a72015-08-03 09:08:46 -0600375 char *minor_str= NULL;
376 char *patch_str = NULL;
377 char *cstr;
378 char *str;
379
380 if (!vers_str)
381 return vers;
382 cstr = loader_stack_alloc(strlen(vers_str) + 1);
383 strcpy(cstr, vers_str);
384 while ((str = strchr(cstr, '.')) != NULL) {
385 if (minor_str == NULL) {
386 minor_str = str + 1;
387 *str = '\0';
388 major = atoi(cstr);
389 }
390 else if (patch_str == NULL) {
391 patch_str = str + 1;
392 *str = '\0';
393 minor = atoi(minor_str);
394 }
395 else {
396 return vers;
397 }
398 cstr = str + 1;
399 }
400 patch = atoi(patch_str);
401
402 return VK_MAKE_VERSION(major, minor, patch);
403
404}
405
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600406bool compare_vk_extension_properties(const VkExtensionProperties *op1, const VkExtensionProperties *op2)
407{
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800408 return strcmp(op1->extensionName, op2->extensionName) == 0 ? true : false;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600409}
410
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -0600411/**
Jon Ashburnbd6c4882015-07-02 12:59:25 -0600412 * Search the given ext_array for an extension
413 * matching the given vk_ext_prop
414 */
415bool has_vk_extension_property_array(
416 const VkExtensionProperties *vk_ext_prop,
417 const uint32_t count,
418 const VkExtensionProperties *ext_array)
419{
420 for (uint32_t i = 0; i < count; i++) {
421 if (compare_vk_extension_properties(vk_ext_prop, &ext_array[i]))
422 return true;
423 }
424 return false;
425}
426
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -0600427/**
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600428 * Search the given ext_list for an extension
429 * matching the given vk_ext_prop
430 */
431bool has_vk_extension_property(
432 const VkExtensionProperties *vk_ext_prop,
433 const struct loader_extension_list *ext_list)
434{
435 for (uint32_t i = 0; i < ext_list->count; i++) {
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600436 if (compare_vk_extension_properties(&ext_list->list[i], vk_ext_prop))
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600437 return true;
438 }
439 return false;
440}
441
Jon Ashburnb2ef1372015-07-16 17:19:31 -0600442static inline bool loader_is_layer_type_device(const enum layer_type type) {
443 if ((type & VK_LAYER_TYPE_DEVICE_EXPLICIT) ||
444 (type & VK_LAYER_TYPE_DEVICE_IMPLICIT))
445 return true;
446 return false;
447}
448
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600449/*
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -0600450 * Search the given layer list for a layer matching the given layer name
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600451 */
Jon Ashburne13ecc92015-08-03 17:19:30 -0600452static struct loader_layer_properties *loader_get_layer_property(
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600453 const char *name,
454 const struct loader_layer_list *layer_list)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600455{
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600456 for (uint32_t i = 0; i < layer_list->count; i++) {
457 const VkLayerProperties *item = &layer_list->list[i].info;
458 if (strcmp(name, item->layerName) == 0)
459 return &layer_list->list[i];
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600460 }
461 return NULL;
462}
463
Jon Ashburne13ecc92015-08-03 17:19:30 -0600464/**
465 * Get the next unused layer property in the list. Init the property to zero.
466 */
467static struct loader_layer_properties *loader_get_next_layer_property(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600468 const struct loader_instance *inst,
Jon Ashburne13ecc92015-08-03 17:19:30 -0600469 struct loader_layer_list *layer_list)
470{
471 if (layer_list->capacity == 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600472 layer_list->list = loader_heap_alloc(inst,
473 sizeof(struct loader_layer_properties) * 64,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800474 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburne13ecc92015-08-03 17:19:30 -0600475 if (layer_list->list == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700476 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Out of memory can't add any layer properties to list");
Jon Ashburne13ecc92015-08-03 17:19:30 -0600477 return NULL;
478 }
479 memset(layer_list->list, 0, sizeof(struct loader_layer_properties) * 64);
480 layer_list->capacity = sizeof(struct loader_layer_properties) * 64;
481 }
482
483 // ensure enough room to add an entry
484 if ((layer_list->count + 1) * sizeof (struct loader_layer_properties)
485 > layer_list->capacity) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600486 layer_list->list = loader_heap_realloc(inst, layer_list->list,
487 layer_list->capacity,
488 layer_list->capacity * 2,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800489 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburne13ecc92015-08-03 17:19:30 -0600490 if (layer_list->list == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700491 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburne13ecc92015-08-03 17:19:30 -0600492 "realloc failed for layer list");
493 }
494 layer_list->capacity *= 2;
495 }
496
497 layer_list->count++;
498 return &(layer_list->list[layer_list->count - 1]);
499}
500
501/**
502 * Remove all layer properties entrys from the list
503 */
Jon Ashburne39a4f82015-08-28 13:38:21 -0600504void loader_delete_layer_properties(
505 const struct loader_instance *inst,
506 struct loader_layer_list *layer_list)
Jon Ashburne13ecc92015-08-03 17:19:30 -0600507{
Jon Ashburn39fbd4e2015-12-10 18:17:34 -0700508 uint32_t i, j;
509 struct loader_device_extension_list *dev_ext_list;
Jon Ashburnb82c1852015-08-11 14:49:54 -0600510 if (!layer_list)
511 return;
512
Jon Ashburne13ecc92015-08-03 17:19:30 -0600513 for (i = 0; i < layer_list->count; i++) {
Jon Ashburn6e6a2162015-12-10 08:51:10 -0700514 loader_destroy_generic_list(inst, (struct loader_generic_list *)
515 &layer_list->list[i].instance_extension_list);
Jon Ashburn39fbd4e2015-12-10 18:17:34 -0700516 dev_ext_list = &layer_list->list[i].device_extension_list;
517 if (dev_ext_list->capacity > 0 && dev_ext_list->list->entrypoint_count > 0) {
518 for (j= 0; j < dev_ext_list->list->entrypoint_count; j++) {
519 loader_heap_free(inst, dev_ext_list->list->entrypoints[j]);
520 }
521 loader_heap_free(inst, dev_ext_list->list->entrypoints);
522 }
Jon Ashburn6e6a2162015-12-10 08:51:10 -0700523 loader_destroy_generic_list(inst, (struct loader_generic_list *)
Jon Ashburn39fbd4e2015-12-10 18:17:34 -0700524 dev_ext_list);
Jon Ashburne13ecc92015-08-03 17:19:30 -0600525 }
526 layer_list->count = 0;
527
Jon Ashburnb82c1852015-08-11 14:49:54 -0600528 if (layer_list->capacity > 0) {
529 layer_list->capacity = 0;
Jon Ashburne39a4f82015-08-28 13:38:21 -0600530 loader_heap_free(inst, layer_list->list);
Jon Ashburnb82c1852015-08-11 14:49:54 -0600531 }
Jon Ashburne13ecc92015-08-03 17:19:30 -0600532
533}
534
Courtney Goeltzenleuchterf538ef72015-12-02 14:00:19 -0700535static void loader_add_instance_extensions(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600536 const struct loader_instance *inst,
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -0600537 const PFN_vkEnumerateInstanceExtensionProperties fp_get_props,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600538 const char *lib_name,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600539 struct loader_extension_list *ext_list)
540{
Courtney Goeltzenleuchter36eeb742015-12-21 16:41:47 -0700541 uint32_t i, count = 0;
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600542 VkExtensionProperties *ext_props;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600543 VkResult res;
544
Courtney Goeltzenleuchter5c6cf472015-07-06 22:28:18 -0600545 if (!fp_get_props) {
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -0600546 /* No EnumerateInstanceExtensionProperties defined */
Courtney Goeltzenleuchter5c6cf472015-07-06 22:28:18 -0600547 return;
548 }
549
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600550 res = fp_get_props(NULL, &count, NULL);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600551 if (res != VK_SUCCESS) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700552 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0, "Error getting Instance extension count from %s", lib_name);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600553 return;
554 }
Jon Ashburn953bb3c2015-06-10 16:11:42 -0600555
Courtney Goeltzenleuchter5c6cf472015-07-06 22:28:18 -0600556 if (count == 0) {
557 /* No ExtensionProperties to report */
558 return;
559 }
560
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600561 ext_props = loader_stack_alloc(count * sizeof(VkExtensionProperties));
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600562
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600563 res = fp_get_props(NULL, &count, ext_props);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600564 if (res != VK_SUCCESS) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700565 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0, "Error getting Instance extensions from %s", lib_name);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600566 return;
567 }
Tony Barbour59a47322015-06-24 16:06:58 -0600568
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600569 for (i = 0; i < count; i++) {
Courtney Goeltzenleuchter53043732015-07-12 13:20:05 -0600570 char spec_version[64];
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600571
572 snprintf(spec_version, sizeof(spec_version), "%d.%d.%d",
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600573 VK_MAJOR(ext_props[i].specVersion),
574 VK_MINOR(ext_props[i].specVersion),
575 VK_PATCH(ext_props[i].specVersion));
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700576 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
Courtney Goeltzenleuchterf538ef72015-12-02 14:00:19 -0700577 "Instance Extension: %s (%s) version %s",
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800578 ext_props[i].extensionName, lib_name, spec_version);
Jon Ashburne39a4f82015-08-28 13:38:21 -0600579 loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600580 }
581
582 return;
583}
584
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700585/*
586 * Initialize ext_list with the physical device extensions.
587 * The extension properties are passed as inputs in count and ext_props.
588 */
Courtney Goeltzenleuchterf538ef72015-12-02 14:00:19 -0700589static VkResult loader_init_device_extensions(
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700590 const struct loader_instance *inst,
591 struct loader_physical_device *phys_dev,
592 uint32_t count,
593 VkExtensionProperties *ext_props,
594 struct loader_extension_list *ext_list)
595{
596 VkResult res;
597 uint32_t i;
598
Jon Ashburn6e6a2162015-12-10 08:51:10 -0700599 if (!loader_init_generic_list(inst, (struct loader_generic_list *) ext_list,
600 sizeof(VkExtensionProperties))) {
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700601 return VK_ERROR_OUT_OF_HOST_MEMORY;
602 }
603
604 for (i = 0; i < count; i++) {
605 char spec_version[64];
606
607 snprintf(spec_version, sizeof (spec_version), "%d.%d.%d",
608 VK_MAJOR(ext_props[i].specVersion),
609 VK_MINOR(ext_props[i].specVersion),
610 VK_PATCH(ext_props[i].specVersion));
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700611 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
Courtney Goeltzenleuchterf538ef72015-12-02 14:00:19 -0700612 "Device Extension: %s (%s) version %s",
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700613 ext_props[i].extensionName, phys_dev->this_icd->this_icd_lib->lib_name, spec_version);
614 res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
615 if (res != VK_SUCCESS)
616 return res;
617 }
618
619 return VK_SUCCESS;
620}
621
Courtney Goeltzenleuchterf538ef72015-12-02 14:00:19 -0700622static VkResult loader_add_device_extensions(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600623 const struct loader_instance *inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600624 VkPhysicalDevice physical_device,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600625 const char *lib_name,
626 struct loader_extension_list *ext_list)
627{
628 uint32_t i, count;
629 VkResult res;
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600630 VkExtensionProperties *ext_props;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600631
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700632 res = loader_EnumerateDeviceExtensionProperties(physical_device, NULL, &count, NULL);
633 if (res == VK_SUCCESS && count > 0) {
634 ext_props = loader_stack_alloc(count * sizeof (VkExtensionProperties));
635 if (!ext_props)
636 return VK_ERROR_OUT_OF_HOST_MEMORY;
637 res = loader_EnumerateDeviceExtensionProperties(physical_device, NULL, &count, ext_props);
638 if (res != VK_SUCCESS)
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700639 return res;
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700640 for (i = 0; i < count; i++) {
641 char spec_version[64];
642
643 snprintf(spec_version, sizeof (spec_version), "%d.%d.%d",
644 VK_MAJOR(ext_props[i].specVersion),
645 VK_MINOR(ext_props[i].specVersion),
646 VK_PATCH(ext_props[i].specVersion));
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700647 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
Courtney Goeltzenleuchterf538ef72015-12-02 14:00:19 -0700648 "Device Extension: %s (%s) version %s",
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700649 ext_props[i].extensionName, lib_name, spec_version);
650 res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
651 if (res != VK_SUCCESS)
652 return res;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600653 }
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700654 } else {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700655 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Error getting physical device extension info count from library %s", lib_name);
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700656 return res;
657 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600658
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700659 return VK_SUCCESS;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600660}
661
Jon Ashburn6e6a2162015-12-10 08:51:10 -0700662static bool loader_init_generic_list(const struct loader_instance *inst,
663 struct loader_generic_list *list_info,
664 size_t element_size)
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600665{
Jon Ashburn6e6a2162015-12-10 08:51:10 -0700666 list_info->capacity = 32 * element_size;
667 list_info->list = loader_heap_alloc(inst, list_info->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
668 if (list_info->list == NULL) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600669 return false;
670 }
Jon Ashburn6e6a2162015-12-10 08:51:10 -0700671 memset(list_info->list, 0, list_info->capacity);
672 list_info->count = 0;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600673 return true;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600674}
675
Jon Ashburn6e6a2162015-12-10 08:51:10 -0700676void loader_destroy_generic_list(const struct loader_instance *inst,
677 struct loader_generic_list *list)
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600678{
Jon Ashburn6e6a2162015-12-10 08:51:10 -0700679 loader_heap_free(inst, list->list);
680 list->count = 0;
681 list->capacity = 0;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600682}
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600683
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600684/*
685 * Append non-duplicate extension properties defined in props
686 * to the given ext_list.
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700687 * Return
688 * Vk_SUCCESS on success
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600689 */
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700690VkResult loader_add_to_ext_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600691 const struct loader_instance *inst,
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600692 struct loader_extension_list *ext_list,
693 uint32_t prop_list_count,
694 const VkExtensionProperties *props)
695{
696 uint32_t i;
697 const VkExtensionProperties *cur_ext;
698
699 if (ext_list->list == NULL || ext_list->capacity == 0) {
Jon Ashburn6e6a2162015-12-10 08:51:10 -0700700 loader_init_generic_list(inst, (struct loader_generic_list *) ext_list,
701 sizeof(VkExtensionProperties));
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600702 }
703
704 if (ext_list->list == NULL)
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700705 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600706
707 for (i = 0; i < prop_list_count; i++) {
708 cur_ext = &props[i];
709
710 // look for duplicates
711 if (has_vk_extension_property(cur_ext, ext_list)) {
712 continue;
713 }
714
715 // add to list at end
716 // check for enough capacity
717 if (ext_list->count * sizeof(VkExtensionProperties)
718 >= ext_list->capacity) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600719
720 ext_list->list = loader_heap_realloc(inst,
721 ext_list->list,
722 ext_list->capacity,
723 ext_list->capacity * 2,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800724 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700725
726 if (ext_list->list == NULL)
727 return VK_ERROR_OUT_OF_HOST_MEMORY;
728
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600729 // double capacity
730 ext_list->capacity *= 2;
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600731 }
732
733 memcpy(&ext_list->list[ext_list->count], cur_ext, sizeof(VkExtensionProperties));
734 ext_list->count++;
735 }
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700736 return VK_SUCCESS;
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600737}
738
Jon Ashburn39fbd4e2015-12-10 18:17:34 -0700739/*
740 * Append one extension property defined in props with entrypoints
741 * defined in entrys to the given ext_list.
742 * Return
743 * Vk_SUCCESS on success
744 */
745VkResult loader_add_to_dev_ext_list(
746 const struct loader_instance *inst,
747 struct loader_device_extension_list *ext_list,
748 const VkExtensionProperties *props,
749 uint32_t entry_count,
750 char **entrys)
751{
752 uint32_t idx;
753 if (ext_list->list == NULL || ext_list->capacity == 0) {
754 loader_init_generic_list(inst, (struct loader_generic_list *) ext_list,
755 sizeof(struct loader_dev_ext_props));
756 }
757
758 if (ext_list->list == NULL)
759 return VK_ERROR_OUT_OF_HOST_MEMORY;
760
761 idx =ext_list->count;
762 // add to list at end
763 // check for enough capacity
764 if (idx * sizeof (struct loader_dev_ext_props)
765 >= ext_list->capacity) {
766
767 ext_list->list = loader_heap_realloc(inst,
768 ext_list->list,
769 ext_list->capacity,
770 ext_list->capacity * 2,
771 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
772
773 if (ext_list->list == NULL)
774 return VK_ERROR_OUT_OF_HOST_MEMORY;
775
776 // double capacity
777 ext_list->capacity *= 2;
778 }
779
780 memcpy(&ext_list->list[idx].props, props, sizeof(struct loader_dev_ext_props));
781 ext_list->list[idx].entrypoint_count = entry_count;
782 ext_list->list[idx].entrypoints = loader_heap_alloc(inst,
783 sizeof(char *) * entry_count,
784 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
785 if (ext_list->list[idx].entrypoints == NULL)
786 return VK_ERROR_OUT_OF_HOST_MEMORY;
787 for (uint32_t i = 0; i < entry_count; i++) {
788 ext_list->list[idx].entrypoints[i] = loader_heap_alloc(inst,
789 strlen(entrys[i]) + 1,
790 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
791 if (ext_list->list[idx].entrypoints[i] == NULL)
792 return VK_ERROR_OUT_OF_HOST_MEMORY;
793 strcpy(ext_list->list[idx].entrypoints[i], entrys[i]);
794 }
795 ext_list->count++;
796
797 return VK_SUCCESS;
798}
799
Jon Ashburnbd6c4882015-07-02 12:59:25 -0600800/**
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600801 * Search the given search_list for any layers in the props list.
802 * Add these to the output layer_list. Don't add duplicates to the output layer_list.
Jon Ashburnbd6c4882015-07-02 12:59:25 -0600803 */
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -0600804static VkResult loader_add_layer_names_to_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600805 const struct loader_instance *inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600806 struct loader_layer_list *output_list,
807 uint32_t name_count,
808 const char * const *names,
809 const struct loader_layer_list *search_list)
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600810{
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600811 struct loader_layer_properties *layer_prop;
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -0600812 VkResult err = VK_SUCCESS;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600813
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600814 for (uint32_t i = 0; i < name_count; i++) {
815 const char *search_target = names[i];
Jon Ashburne13ecc92015-08-03 17:19:30 -0600816 layer_prop = loader_get_layer_property(search_target, search_list);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600817 if (!layer_prop) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700818 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Unable to find layer %s", search_target);
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -0600819 err = VK_ERROR_LAYER_NOT_PRESENT;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600820 continue;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600821 }
822
Jon Ashburne39a4f82015-08-28 13:38:21 -0600823 loader_add_to_layer_list(inst, output_list, 1, layer_prop);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600824 }
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -0600825
826 return err;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600827}
828
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600829
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600830/*
831 * Manage lists of VkLayerProperties
832 */
Jon Ashburne39a4f82015-08-28 13:38:21 -0600833static bool loader_init_layer_list(const struct loader_instance *inst,
834 struct loader_layer_list *list)
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600835{
836 list->capacity = 32 * sizeof(struct loader_layer_properties);
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800837 list->list = loader_heap_alloc(inst, list->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600838 if (list->list == NULL) {
839 return false;
840 }
841 memset(list->list, 0, list->capacity);
842 list->count = 0;
843 return true;
844}
845
Jon Ashburne39a4f82015-08-28 13:38:21 -0600846void loader_destroy_layer_list(const struct loader_instance *inst,
847 struct loader_layer_list *layer_list)
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600848{
Jon Ashburne39a4f82015-08-28 13:38:21 -0600849 loader_heap_free(inst, layer_list->list);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600850 layer_list->count = 0;
851 layer_list->capacity = 0;
852}
853
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600854/*
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600855 * Manage list of layer libraries (loader_lib_info)
856 */
Jon Ashburne39a4f82015-08-28 13:38:21 -0600857static bool loader_init_layer_library_list(const struct loader_instance *inst,
858 struct loader_layer_library_list *list)
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600859{
860 list->capacity = 32 * sizeof(struct loader_lib_info);
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800861 list->list = loader_heap_alloc(inst, list->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600862 if (list->list == NULL) {
863 return false;
864 }
865 memset(list->list, 0, list->capacity);
866 list->count = 0;
867 return true;
868}
869
Jon Ashburne39a4f82015-08-28 13:38:21 -0600870void loader_destroy_layer_library_list(const struct loader_instance *inst,
871 struct loader_layer_library_list *list)
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600872{
873 for (uint32_t i = 0; i < list->count; i++) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600874 loader_heap_free(inst, list->list[i].lib_name);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600875 }
Jon Ashburne39a4f82015-08-28 13:38:21 -0600876 loader_heap_free(inst, list->list);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600877 list->count = 0;
878 list->capacity = 0;
879}
880
881void loader_add_to_layer_library_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600882 const struct loader_instance *inst,
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600883 struct loader_layer_library_list *list,
884 uint32_t item_count,
885 const struct loader_lib_info *new_items)
886{
887 uint32_t i;
888 struct loader_lib_info *item;
889
890 if (list->list == NULL || list->capacity == 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600891 loader_init_layer_library_list(inst, list);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600892 }
893
894 if (list->list == NULL)
895 return;
896
897 for (i = 0; i < item_count; i++) {
898 item = (struct loader_lib_info *) &new_items[i];
899
900 // look for duplicates
901 for (uint32_t j = 0; j < list->count; j++) {
902 if (strcmp(list->list[i].lib_name, new_items->lib_name) == 0) {
903 continue;
904 }
905 }
906
907 // add to list at end
908 // check for enough capacity
909 if (list->count * sizeof(struct loader_lib_info)
910 >= list->capacity) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600911
912 list->list = loader_heap_realloc(inst,
913 list->list,
914 list->capacity,
915 list->capacity * 2,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800916 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600917 // double capacity
918 list->capacity *= 2;
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600919 }
920
921 memcpy(&list->list[list->count], item, sizeof(struct loader_lib_info));
922 list->count++;
923 }
924}
925
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600926
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600927/*
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600928 * Search the given layer list for a list
929 * matching the given VkLayerProperties
930 */
931bool has_vk_layer_property(
932 const VkLayerProperties *vk_layer_prop,
933 const struct loader_layer_list *list)
934{
935 for (uint32_t i = 0; i < list->count; i++) {
936 if (strcmp(vk_layer_prop->layerName, list->list[i].info.layerName) == 0)
937 return true;
938 }
939 return false;
940}
941
942/*
943 * Search the given layer list for a layer
944 * matching the given name
945 */
946bool has_layer_name(
947 const char *name,
948 const struct loader_layer_list *list)
949{
950 for (uint32_t i = 0; i < list->count; i++) {
951 if (strcmp(name, list->list[i].info.layerName) == 0)
952 return true;
953 }
954 return false;
955}
956
957/*
958 * Append non-duplicate layer properties defined in prop_list
959 * to the given layer_info list
960 */
961void loader_add_to_layer_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600962 const struct loader_instance *inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600963 struct loader_layer_list *list,
964 uint32_t prop_list_count,
965 const struct loader_layer_properties *props)
966{
967 uint32_t i;
968 struct loader_layer_properties *layer;
969
970 if (list->list == NULL || list->capacity == 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600971 loader_init_layer_list(inst, list);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600972 }
973
974 if (list->list == NULL)
975 return;
976
977 for (i = 0; i < prop_list_count; i++) {
978 layer = (struct loader_layer_properties *) &props[i];
979
980 // look for duplicates
981 if (has_vk_layer_property(&layer->info, list)) {
982 continue;
983 }
984
985 // add to list at end
986 // check for enough capacity
987 if (list->count * sizeof(struct loader_layer_properties)
988 >= list->capacity) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600989
990 list->list = loader_heap_realloc(inst,
991 list->list,
992 list->capacity,
993 list->capacity * 2,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800994 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600995 // double capacity
996 list->capacity *= 2;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600997 }
998
999 memcpy(&list->list[list->count], layer, sizeof(struct loader_layer_properties));
1000 list->count++;
1001 }
1002}
1003
Jon Ashburnbd332cc2015-07-07 10:27:45 -06001004/**
1005 * Search the search_list for any layer with a name
1006 * that matches the given name and a type that matches the given type
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06001007 * Add all matching layers to the found_list
Jon Ashburnbd332cc2015-07-07 10:27:45 -06001008 * Do not add if found loader_layer_properties is already
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06001009 * on the found_list.
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001010 */
Jon Ashburnbd6c4882015-07-02 12:59:25 -06001011static void loader_find_layer_name_add_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -06001012 const struct loader_instance *inst,
Jon Ashburnbd6c4882015-07-02 12:59:25 -06001013 const char *name,
Jon Ashburnbd332cc2015-07-07 10:27:45 -06001014 const enum layer_type type,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06001015 const struct loader_layer_list *search_list,
1016 struct loader_layer_list *found_list)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001017{
Jon Ashburn56151d62015-10-05 09:03:21 -06001018 bool found = false;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001019 for (uint32_t i = 0; i < search_list->count; i++) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06001020 struct loader_layer_properties *layer_prop = &search_list->list[i];
Jon Ashburnbd332cc2015-07-07 10:27:45 -06001021 if (0 == strcmp(layer_prop->info.layerName, name) &&
1022 (layer_prop->type & type)) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06001023 /* Found a layer with the same name, add to found_list */
Jon Ashburne39a4f82015-08-28 13:38:21 -06001024 loader_add_to_layer_list(inst, found_list, 1, layer_prop);
Jon Ashburn56151d62015-10-05 09:03:21 -06001025 found = true;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001026 }
1027 }
Jon Ashburn56151d62015-10-05 09:03:21 -06001028 if (!found) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001029 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0, "Warning, couldn't find layer name %s to activate", name);
Jon Ashburn56151d62015-10-05 09:03:21 -06001030 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001031}
1032
Jon Ashburn5c042ea2015-08-04 11:14:18 -06001033static VkExtensionProperties *get_extension_property(
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06001034 const char *name,
1035 const struct loader_extension_list *list)
Jon Ashburnfc2e38c2015-04-14 09:15:32 -06001036{
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06001037 for (uint32_t i = 0; i < list->count; i++) {
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001038 if (strcmp(name, list->list[i].extensionName) == 0)
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06001039 return &list->list[i];
Jon Ashburnfc2e38c2015-04-14 09:15:32 -06001040 }
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06001041 return NULL;
Jon Ashburnfc2e38c2015-04-14 09:15:32 -06001042}
1043
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001044static VkExtensionProperties *get_dev_extension_property(
1045 const char *name,
1046 const struct loader_device_extension_list *list)
1047{
1048 for (uint32_t i = 0; i < list->count; i++) {
1049 if (strcmp(name, list->list[i].props.extensionName) == 0)
1050 return &list->list[i].props;
1051 }
1052 return NULL;
1053}
1054
Jon Ashburnbd6c4882015-07-02 12:59:25 -06001055/*
Courtney Goeltzenleuchterf538ef72015-12-02 14:00:19 -07001056 * For Instance extensions implemented within the loader (i.e. DEBUG_REPORT
Jon Ashburnbd6c4882015-07-02 12:59:25 -06001057 * the extension must provide two entry points for the loader to use:
1058 * - "trampoline" entry point - this is the address returned by GetProcAddr
1059 * and will always do what's necessary to support a global call.
1060 * - "terminator" function - this function will be put at the end of the
Jon Ashburn232e3af2015-11-30 17:21:25 -07001061 * instance chain and will contain the necessary logic to call / process
Jon Ashburnbd6c4882015-07-02 12:59:25 -06001062 * the extension for the appropriate ICDs that are available.
1063 * There is no generic mechanism for including these functions, the references
1064 * must be placed into the appropriate loader entry points.
1065 * GetInstanceProcAddr: call extension GetInstanceProcAddr to check for GetProcAddr requests
1066 * loader_coalesce_extensions(void) - add extension records to the list of global
1067 * extension available to the app.
1068 * instance_disp - add function pointer for terminator function to this array.
1069 * The extension itself should be in a separate file that will be
1070 * linked directly with the loader.
1071 */
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06001072
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001073void loader_get_icd_loader_instance_extensions(
Jon Ashburne39a4f82015-08-28 13:38:21 -06001074 const struct loader_instance *inst,
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001075 struct loader_icd_libs *icd_libs,
1076 struct loader_extension_list *inst_exts)
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001077{
Jon Ashburn5c6a46f2015-08-14 14:49:22 -06001078 struct loader_extension_list icd_exts;
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001079 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Build ICD instance extension list");
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001080 // traverse scanned icd list adding non-duplicate extensions to the list
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001081 for (uint32_t i = 0; i < icd_libs->count; i++) {
Jon Ashburn6e6a2162015-12-10 08:51:10 -07001082 loader_init_generic_list(inst, (struct loader_generic_list *) &icd_exts,
1083 sizeof(VkExtensionProperties));
Courtney Goeltzenleuchterf538ef72015-12-02 14:00:19 -07001084 loader_add_instance_extensions(inst, icd_libs->list[i].EnumerateInstanceExtensionProperties,
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001085 icd_libs->list[i].lib_name,
Jon Ashburn5c6a46f2015-08-14 14:49:22 -06001086 &icd_exts);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001087 loader_add_to_ext_list(inst, inst_exts,
Jon Ashburn5c6a46f2015-08-14 14:49:22 -06001088 icd_exts.count,
1089 icd_exts.list);
Jon Ashburn6e6a2162015-12-10 08:51:10 -07001090 loader_destroy_generic_list(inst, (struct loader_generic_list *) &icd_exts);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001091 };
1092
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001093 // Traverse loader's extensions, adding non-duplicate extensions to the list
Ian Elliott954fa342015-10-30 15:28:23 -06001094 wsi_add_instance_extensions(inst, inst_exts);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001095 debug_report_add_instance_extensions(inst, inst_exts);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001096}
1097
Jon Ashburn46674bf2015-12-11 09:41:34 -07001098struct loader_physical_device *loader_get_physical_device(const VkPhysicalDevice physdev)
1099{
1100 uint32_t i;
1101 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
1102 for (i = 0; i < inst->total_gpu_count; i++) {
1103 //TODO this aliases physDevices within instances, need for this
1104 // function to go away
1105 if (inst->phys_devs[i].disp == loader_get_instance_dispatch(physdev)) {
1106 return &inst->phys_devs[i];
1107 }
1108 }
1109 }
1110 return NULL;
1111}
1112
Jon Ashburne39a4f82015-08-28 13:38:21 -06001113struct loader_icd *loader_get_icd_and_device(const VkDevice device,
1114 struct loader_device **found_dev)
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001115{
1116 *found_dev = NULL;
1117 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
1118 for (struct loader_icd *icd = inst->icds; icd; icd = icd->next) {
1119 for (struct loader_device *dev = icd->logical_device_list; dev; dev = dev->next)
Jon Ashburne0e64572015-09-30 12:56:42 -06001120 /* Value comparison of device prevents object wrapping by layers */
1121 if (loader_get_dispatch(dev->device) == loader_get_dispatch(device)) {
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001122 *found_dev = dev;
1123 return icd;
1124 }
1125 }
1126 }
1127 return NULL;
1128}
1129
Jon Ashburne39a4f82015-08-28 13:38:21 -06001130static void loader_destroy_logical_device(const struct loader_instance *inst,
1131 struct loader_device *dev)
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001132{
Jon Ashburne39a4f82015-08-28 13:38:21 -06001133 loader_heap_free(inst, dev->app_extension_props);
BogDan Vatra9ef09832016-01-04 14:05:49 +02001134 loader_destroy_layer_list(inst, &dev->activated_layer_list);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001135 loader_heap_free(inst, dev);
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001136}
1137
Jon Ashburne39a4f82015-08-28 13:38:21 -06001138static struct loader_device *loader_add_logical_device(
1139 const struct loader_instance *inst,
1140 const VkDevice dev,
1141 struct loader_device **device_list)
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001142{
1143 struct loader_device *new_dev;
1144
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001145 new_dev = loader_heap_alloc(inst, sizeof(struct loader_device), VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001146 if (!new_dev) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001147 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Failed to alloc struct laoder-device");
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001148 return NULL;
1149 }
1150
1151 memset(new_dev, 0, sizeof(struct loader_device));
1152
1153 new_dev->next = *device_list;
1154 new_dev->device = dev;
1155 *device_list = new_dev;
1156 return new_dev;
1157}
1158
Jon Ashburne39a4f82015-08-28 13:38:21 -06001159void loader_remove_logical_device(
1160 const struct loader_instance *inst,
Jon Ashburn781a7ae2015-11-19 15:43:26 -07001161 struct loader_icd *icd,
1162 struct loader_device *found_dev)
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001163{
Jon Ashburn781a7ae2015-11-19 15:43:26 -07001164 struct loader_device *dev, *prev_dev;
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001165
1166 if (!icd || !found_dev)
1167 return;
1168
1169 prev_dev = NULL;
1170 dev = icd->logical_device_list;
1171 while (dev && dev != found_dev) {
1172 prev_dev = dev;
1173 dev = dev->next;
1174 }
1175
1176 if (prev_dev)
1177 prev_dev->next = found_dev->next;
1178 else
1179 icd->logical_device_list = found_dev->next;
Jon Ashburne39a4f82015-08-28 13:38:21 -06001180 loader_destroy_logical_device(inst, found_dev);
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001181}
1182
1183
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001184static void loader_icd_destroy(
1185 struct loader_instance *ptr_inst,
1186 struct loader_icd *icd)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001187{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001188 ptr_inst->total_icd_count--;
Courtney Goeltzenleuchter1f157ac2015-06-14 19:57:15 -06001189 for (struct loader_device *dev = icd->logical_device_list; dev; ) {
1190 struct loader_device *next_dev = dev->next;
Jon Ashburne39a4f82015-08-28 13:38:21 -06001191 loader_destroy_logical_device(ptr_inst, dev);
Courtney Goeltzenleuchter1f157ac2015-06-14 19:57:15 -06001192 dev = next_dev;
1193 }
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001194
Jon Ashburne39a4f82015-08-28 13:38:21 -06001195 loader_heap_free(ptr_inst, icd);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001196}
1197
Jon Ashburne39a4f82015-08-28 13:38:21 -06001198static struct loader_icd * loader_icd_create(const struct loader_instance *inst)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001199{
1200 struct loader_icd *icd;
1201
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001202 icd = loader_heap_alloc(inst, sizeof(*icd), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001203 if (!icd)
1204 return NULL;
1205
Courtney Goeltzenleuchter55001bb2014-10-28 10:29:27 -06001206 memset(icd, 0, sizeof(*icd));
1207
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001208 return icd;
1209}
1210
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001211static struct loader_icd *loader_icd_add(
1212 struct loader_instance *ptr_inst,
Jon Ashburn3d002332015-08-20 16:35:30 -06001213 const struct loader_scanned_icds *icd_lib)
Chia-I Wu13a61a52014-08-04 11:18:20 +08001214{
1215 struct loader_icd *icd;
1216
Jon Ashburne39a4f82015-08-28 13:38:21 -06001217 icd = loader_icd_create(ptr_inst);
Chia-I Wu13a61a52014-08-04 11:18:20 +08001218 if (!icd)
1219 return NULL;
1220
Jon Ashburn3d002332015-08-20 16:35:30 -06001221 icd->this_icd_lib = icd_lib;
1222 icd->this_instance = ptr_inst;
1223
Chia-I Wu13a61a52014-08-04 11:18:20 +08001224 /* prepend to the list */
Jon Ashburn46888392015-01-29 15:45:51 -07001225 icd->next = ptr_inst->icds;
1226 ptr_inst->icds = icd;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001227 ptr_inst->total_icd_count++;
Chia-I Wu13a61a52014-08-04 11:18:20 +08001228
1229 return icd;
1230}
1231
Jon Ashburne39a4f82015-08-28 13:38:21 -06001232void loader_scanned_icd_clear(
1233 const struct loader_instance *inst,
1234 struct loader_icd_libs *icd_libs)
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001235{
1236 if (icd_libs->capacity == 0)
1237 return;
1238 for (uint32_t i = 0; i < icd_libs->count; i++) {
1239 loader_platform_close_library(icd_libs->list[i].handle);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001240 loader_heap_free(inst, icd_libs->list[i].lib_name);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001241 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06001242 loader_heap_free(inst, icd_libs->list);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001243 icd_libs->capacity = 0;
1244 icd_libs->count = 0;
1245 icd_libs->list = NULL;
1246}
1247
Jon Ashburne39a4f82015-08-28 13:38:21 -06001248static void loader_scanned_icd_init(const struct loader_instance *inst,
1249 struct loader_icd_libs *icd_libs)
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001250{
Jon Ashburne39a4f82015-08-28 13:38:21 -06001251 loader_scanned_icd_clear(inst, icd_libs);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001252 icd_libs->capacity = 8 * sizeof(struct loader_scanned_icds);
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001253 icd_libs->list = loader_heap_alloc(inst, icd_libs->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001254
1255}
1256
1257static void loader_scanned_icd_add(
Jon Ashburne39a4f82015-08-28 13:38:21 -06001258 const struct loader_instance *inst,
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001259 struct loader_icd_libs *icd_libs,
Jon Ashburn005617f2015-11-17 17:35:40 -07001260 const char *filename,
1261 uint32_t api_version)
Jon Ashburn46d1f582015-01-28 11:01:35 -07001262{
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001263 loader_platform_dl_handle handle;
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06001264 PFN_vkCreateInstance fp_create_inst;
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06001265 PFN_vkEnumerateInstanceExtensionProperties fp_get_global_ext_props;
Jon Ashburnc624c882015-07-16 10:17:29 -06001266 PFN_vkGetInstanceProcAddr fp_get_proc_addr;
Jon Ashburn46d1f582015-01-28 11:01:35 -07001267 struct loader_scanned_icds *new_node;
1268
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001269 /* TODO implement ref counting of libraries, for now this function leaves
1270 libraries open and the scanned_icd_clear closes them */
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001271 // Used to call: dlopen(filename, RTLD_LAZY);
1272 handle = loader_platform_open_library(filename);
Jon Ashburn46d1f582015-01-28 11:01:35 -07001273 if (!handle) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001274 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0, loader_platform_open_library_error(filename));
Jon Ashburn46d1f582015-01-28 11:01:35 -07001275 return;
1276 }
1277
Jon Ashburnc624c882015-07-16 10:17:29 -06001278#define LOOKUP_LD(func_ptr, func) do { \
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -06001279 func_ptr = (PFN_vk ##func) loader_platform_get_proc_address(handle, "vk" #func); \
Jon Ashburn46d1f582015-01-28 11:01:35 -07001280 if (!func_ptr) { \
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001281 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0, loader_platform_get_proc_address_error("vk" #func)); \
Jon Ashburn46d1f582015-01-28 11:01:35 -07001282 return; \
1283 } \
1284} while (0)
1285
Jon Ashburnc624c882015-07-16 10:17:29 -06001286 LOOKUP_LD(fp_get_proc_addr, GetInstanceProcAddr);
1287 LOOKUP_LD(fp_create_inst, CreateInstance);
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06001288 LOOKUP_LD(fp_get_global_ext_props, EnumerateInstanceExtensionProperties);
Jon Ashburnc624c882015-07-16 10:17:29 -06001289
1290#undef LOOKUP_LD
Jon Ashburn46d1f582015-01-28 11:01:35 -07001291
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001292 // check for enough capacity
1293 if ((icd_libs->count * sizeof(struct loader_scanned_icds)) >= icd_libs->capacity) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06001294
1295 icd_libs->list = loader_heap_realloc(inst,
1296 icd_libs->list,
1297 icd_libs->capacity,
1298 icd_libs->capacity * 2,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001299 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001300 // double capacity
1301 icd_libs->capacity *= 2;
Jon Ashburn46d1f582015-01-28 11:01:35 -07001302 }
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001303 new_node = &(icd_libs->list[icd_libs->count]);
Jon Ashburn46d1f582015-01-28 11:01:35 -07001304
1305 new_node->handle = handle;
Jon Ashburn005617f2015-11-17 17:35:40 -07001306 new_node->api_version = api_version;
Jon Ashburnc624c882015-07-16 10:17:29 -06001307 new_node->GetInstanceProcAddr = fp_get_proc_addr;
Jon Ashburn46888392015-01-29 15:45:51 -07001308 new_node->CreateInstance = fp_create_inst;
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06001309 new_node->EnumerateInstanceExtensionProperties = fp_get_global_ext_props;
Jon Ashburn46d1f582015-01-28 11:01:35 -07001310
Jon Ashburne39a4f82015-08-28 13:38:21 -06001311 new_node->lib_name = (char *) loader_heap_alloc(inst,
1312 strlen(filename) + 1,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001313 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001314 if (!new_node->lib_name) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001315 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0, "Out of memory can't add icd");
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001316 return;
1317 }
1318 strcpy(new_node->lib_name, filename);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001319 icd_libs->count++;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001320}
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001321
Jon Ashburnc624c882015-07-16 10:17:29 -06001322static bool loader_icd_init_entrys(struct loader_icd *icd,
1323 VkInstance inst,
1324 const PFN_vkGetInstanceProcAddr fp_gipa)
Jon Ashburn3da71f22015-05-14 12:43:38 -06001325{
1326 /* initialize entrypoint function pointers */
1327
Jon Ashburnc624c882015-07-16 10:17:29 -06001328 #define LOOKUP_GIPA(func, required) do { \
1329 icd->func = (PFN_vk ##func) fp_gipa(inst, "vk" #func); \
1330 if (!icd->func && required) { \
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001331 loader_log((struct loader_instance *) inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0, \
Jon Ashburnc624c882015-07-16 10:17:29 -06001332 loader_platform_get_proc_address_error("vk" #func)); \
1333 return false; \
1334 } \
Jon Ashburn3da71f22015-05-14 12:43:38 -06001335 } while (0)
1336
Jon Ashburnc624c882015-07-16 10:17:29 -06001337 LOOKUP_GIPA(GetDeviceProcAddr, true);
1338 LOOKUP_GIPA(DestroyInstance, true);
1339 LOOKUP_GIPA(EnumeratePhysicalDevices, true);
1340 LOOKUP_GIPA(GetPhysicalDeviceFeatures, true);
1341 LOOKUP_GIPA(GetPhysicalDeviceFormatProperties, true);
Jon Ashburn754864f2015-07-23 18:49:07 -06001342 LOOKUP_GIPA(GetPhysicalDeviceImageFormatProperties, true);
Jon Ashburnc624c882015-07-16 10:17:29 -06001343 LOOKUP_GIPA(CreateDevice, true);
1344 LOOKUP_GIPA(GetPhysicalDeviceProperties, true);
1345 LOOKUP_GIPA(GetPhysicalDeviceMemoryProperties, true);
Cody Northropd0802882015-08-03 17:04:53 -06001346 LOOKUP_GIPA(GetPhysicalDeviceQueueFamilyProperties, true);
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06001347 LOOKUP_GIPA(EnumerateDeviceExtensionProperties, true);
Jon Ashburnc624c882015-07-16 10:17:29 -06001348 LOOKUP_GIPA(GetPhysicalDeviceSparseImageFormatProperties, true);
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001349 LOOKUP_GIPA(CreateDebugReportCallbackEXT, false);
1350 LOOKUP_GIPA(DestroyDebugReportCallbackEXT, false);
Ian Elliott7e40db92015-08-21 15:09:33 -06001351 LOOKUP_GIPA(GetPhysicalDeviceSurfaceSupportKHR, false);
Ian Elliott486c5502015-11-19 16:05:09 -07001352 LOOKUP_GIPA(GetPhysicalDeviceSurfaceCapabilitiesKHR, false);
1353 LOOKUP_GIPA(GetPhysicalDeviceSurfaceFormatsKHR, false);
1354 LOOKUP_GIPA(GetPhysicalDeviceSurfacePresentModesKHR, false);
Ian Elliott919fa302015-11-24 15:39:10 -07001355#ifdef VK_USE_PLATFORM_WIN32_KHR
1356 LOOKUP_GIPA(GetPhysicalDeviceWin32PresentationSupportKHR, false);
1357#endif
1358#ifdef VK_USE_PLATFORM_XCB_KHR
1359 LOOKUP_GIPA(GetPhysicalDeviceXcbPresentationSupportKHR, false);
1360#endif
Jon Ashburn3da71f22015-05-14 12:43:38 -06001361
Jon Ashburnc624c882015-07-16 10:17:29 -06001362#undef LOOKUP_GIPA
Ian Elliottd3ef02f2015-07-06 14:36:13 -06001363
Jon Ashburnc624c882015-07-16 10:17:29 -06001364 return true;
Jon Ashburn3da71f22015-05-14 12:43:38 -06001365}
1366
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001367static void loader_debug_init(void)
1368{
1369 const char *env;
1370
1371 if (g_loader_debug > 0)
1372 return;
1373
1374 g_loader_debug = 0;
1375
1376 /* parse comma-separated debug options */
Courtney Goeltzenleuchterfce60db2015-07-29 09:08:22 -06001377 env = getenv("VK_LOADER_DEBUG");
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001378 while (env) {
1379 const char *p = strchr(env, ',');
1380 size_t len;
1381
1382 if (p)
1383 len = p - env;
1384 else
1385 len = strlen(env);
1386
1387 if (len > 0) {
Michael Worcester25c73e72015-12-10 18:06:24 +00001388 if (strncmp(env, "all", len) == 0) {
1389 g_loader_debug = ~0u;
1390 g_loader_log_msgs = ~0u;
1391 } else if (strncmp(env, "warn", len) == 0) {
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001392 g_loader_debug |= LOADER_WARN_BIT;
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001393 g_loader_log_msgs |= VK_DEBUG_REPORT_WARN_BIT_EXT;
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001394 } else if (strncmp(env, "info", len) == 0) {
1395 g_loader_debug |= LOADER_INFO_BIT;
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001396 g_loader_log_msgs |= VK_DEBUG_REPORT_INFO_BIT_EXT;
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001397 } else if (strncmp(env, "perf", len) == 0) {
1398 g_loader_debug |= LOADER_PERF_BIT;
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001399 g_loader_log_msgs |= VK_DEBUG_REPORT_PERF_WARN_BIT_EXT;
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001400 } else if (strncmp(env, "error", len) == 0) {
1401 g_loader_debug |= LOADER_ERROR_BIT;
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001402 g_loader_log_msgs |= VK_DEBUG_REPORT_ERROR_BIT_EXT;
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001403 } else if (strncmp(env, "debug", len) == 0) {
1404 g_loader_debug |= LOADER_DEBUG_BIT;
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001405 g_loader_log_msgs |= VK_DEBUG_REPORT_DEBUG_BIT_EXT;
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001406 }
1407 }
1408
1409 if (!p)
1410 break;
1411
1412 env = p + 1;
1413 }
1414}
1415
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001416void loader_initialize(void)
1417{
Jon Ashburn6461ef22015-09-22 13:11:00 -06001418 // initialize mutexs
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001419 loader_platform_thread_create_mutex(&loader_lock);
Jon Ashburn6461ef22015-09-22 13:11:00 -06001420 loader_platform_thread_create_mutex(&loader_json_lock);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001421
1422 // initialize logging
1423 loader_debug_init();
Jon Ashburn87d6aa92015-08-28 15:19:27 -06001424
1425 // initial cJSON to use alloc callbacks
1426 cJSON_Hooks alloc_fns = {
1427 .malloc_fn = loader_tls_heap_alloc,
1428 .free_fn = loader_tls_heap_free,
1429 };
1430 cJSON_InitHooks(&alloc_fns);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001431}
1432
Jon Ashburn2077e382015-06-29 11:25:34 -06001433struct loader_manifest_files {
1434 uint32_t count;
1435 char **filename_list;
1436};
1437
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06001438/**
Jon Ashburn2077e382015-06-29 11:25:34 -06001439 * Get next file or dirname given a string list or registry key path
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06001440 *
1441 * \returns
Jon Ashburn2077e382015-06-29 11:25:34 -06001442 * A pointer to first char in the next path.
1443 * The next path (or NULL) in the list is returned in next_path.
1444 * Note: input string is modified in some cases. PASS IN A COPY!
1445 */
Jon Ashburn2077e382015-06-29 11:25:34 -06001446static char *loader_get_next_path(char *path)
1447{
1448 uint32_t len;
1449 char *next;
1450
1451 if (path == NULL)
1452 return NULL;
1453 next = strchr(path, PATH_SEPERATOR);
1454 if (next == NULL) {
1455 len = (uint32_t) strlen(path);
1456 next = path + len;
1457 }
1458 else {
1459 *next = '\0';
1460 next++;
1461 }
1462
1463 return next;
1464}
1465
1466/**
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001467 * Given a path which is absolute or relative, expand the path if relative or
1468 * leave the path unmodified if absolute. The base path to prepend to relative
1469 * paths is given in rel_base.
Jon Ashburn15315172015-07-07 15:06:25 -06001470 *
1471 * \returns
1472 * A string in out_fullpath of the full absolute path
Jon Ashburn15315172015-07-07 15:06:25 -06001473 */
1474static void loader_expand_path(const char *path,
1475 const char *rel_base,
1476 size_t out_size,
1477 char *out_fullpath)
1478{
1479 if (loader_platform_is_path_absolute(path)) {
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001480 // do not prepend a base to an absolute path
1481 rel_base = "";
Jon Ashburn15315172015-07-07 15:06:25 -06001482 }
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001483
1484 loader_platform_combine_path(out_fullpath, out_size, rel_base, path, NULL);
Jon Ashburn15315172015-07-07 15:06:25 -06001485}
1486
1487/**
Jon Ashburn2077e382015-06-29 11:25:34 -06001488 * Given a filename (file) and a list of paths (dir), try to find an existing
1489 * file in the paths. If filename already is a path then no
1490 * searching in the given paths.
1491 *
1492 * \returns
1493 * A string in out_fullpath of either the full path or file.
Jon Ashburn2077e382015-06-29 11:25:34 -06001494 */
1495static void loader_get_fullpath(const char *file,
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001496 const char *dirs,
Jon Ashburn2077e382015-06-29 11:25:34 -06001497 size_t out_size,
1498 char *out_fullpath)
1499{
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001500 if (!loader_platform_is_path(file) && *dirs) {
1501 char *dirs_copy, *dir, *next_dir;
1502
1503 dirs_copy = loader_stack_alloc(strlen(dirs) + 1);
1504 strcpy(dirs_copy, dirs);
1505
1506 //find if file exists after prepending paths in given list
1507 for (dir = dirs_copy;
1508 *dir && (next_dir = loader_get_next_path(dir));
1509 dir = next_dir) {
1510 loader_platform_combine_path(out_fullpath, out_size, dir, file, NULL);
Jon Ashburn2077e382015-06-29 11:25:34 -06001511 if (loader_platform_file_exists(out_fullpath)) {
1512 return;
1513 }
Jon Ashburn2077e382015-06-29 11:25:34 -06001514 }
1515 }
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001516
Jon Ashburn2077e382015-06-29 11:25:34 -06001517 snprintf(out_fullpath, out_size, "%s", file);
1518}
1519
1520/**
1521 * Read a JSON file into a buffer.
1522 *
1523 * \returns
1524 * A pointer to a cJSON object representing the JSON parse tree.
1525 * This returned buffer should be freed by caller.
1526 */
Courtney Goeltzenleuchter73477392015-12-03 13:48:01 -07001527static cJSON *loader_get_json(const struct loader_instance *inst, const char *filename)
Jon Ashburn2077e382015-06-29 11:25:34 -06001528{
1529 FILE *file;
1530 char *json_buf;
1531 cJSON *json;
1532 uint64_t len;
1533 file = fopen(filename,"rb");
Jon Ashburnaa4ea472015-08-27 08:30:50 -06001534 if (!file) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001535 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Couldn't open JSON file %s", filename);
Jon Ashburnaa4ea472015-08-27 08:30:50 -06001536 return NULL;
1537 }
Jon Ashburn2077e382015-06-29 11:25:34 -06001538 fseek(file, 0, SEEK_END);
1539 len = ftell(file);
1540 fseek(file, 0, SEEK_SET);
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -06001541 json_buf = (char*) loader_stack_alloc(len+1);
Jon Ashburn2077e382015-06-29 11:25:34 -06001542 if (json_buf == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001543 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Out of memory can't get JSON file");
Jon Ashburn2077e382015-06-29 11:25:34 -06001544 fclose(file);
1545 return NULL;
1546 }
1547 if (fread(json_buf, sizeof(char), len, file) != len) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001548 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "fread failed can't get JSON file");
Jon Ashburn2077e382015-06-29 11:25:34 -06001549 fclose(file);
1550 return NULL;
1551 }
1552 fclose(file);
1553 json_buf[len] = '\0';
1554
1555 //parse text from file
1556 json = cJSON_Parse(json_buf);
1557 if (json == NULL)
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001558 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Can't parse JSON file %s", filename);
Jon Ashburn2077e382015-06-29 11:25:34 -06001559 return json;
1560}
1561
1562/**
Jon Ashburn3d002332015-08-20 16:35:30 -06001563 * Do a deep copy of the loader_layer_properties structure.
1564 */
1565static void loader_copy_layer_properties(
Jon Ashburne39a4f82015-08-28 13:38:21 -06001566 const struct loader_instance *inst,
Jon Ashburn3d002332015-08-20 16:35:30 -06001567 struct loader_layer_properties *dst,
1568 struct loader_layer_properties *src)
1569{
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001570 uint32_t cnt, i;
Jon Ashburn3d002332015-08-20 16:35:30 -06001571 memcpy(dst, src, sizeof (*src));
Jon Ashburne39a4f82015-08-28 13:38:21 -06001572 dst->instance_extension_list.list = loader_heap_alloc(
1573 inst,
1574 sizeof(VkExtensionProperties) *
1575 src->instance_extension_list.count,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001576 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001577 dst->instance_extension_list.capacity = sizeof(VkExtensionProperties) *
1578 src->instance_extension_list.count;
1579 memcpy(dst->instance_extension_list.list, src->instance_extension_list.list,
1580 dst->instance_extension_list.capacity);
1581 dst->device_extension_list.list = loader_heap_alloc(
1582 inst,
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001583 sizeof(struct loader_dev_ext_props) *
Jon Ashburne39a4f82015-08-28 13:38:21 -06001584 src->device_extension_list.count,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001585 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001586
1587 dst->device_extension_list.capacity = sizeof(struct loader_dev_ext_props) *
Jon Ashburne39a4f82015-08-28 13:38:21 -06001588 src->device_extension_list.count;
1589 memcpy(dst->device_extension_list.list, src->device_extension_list.list,
1590 dst->device_extension_list.capacity);
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001591 if (src->device_extension_list.count > 0 &&
1592 src->device_extension_list.list->entrypoint_count > 0) {
1593 cnt = src->device_extension_list.list->entrypoint_count;
1594 dst->device_extension_list.list->entrypoints = loader_heap_alloc(
1595 inst,
1596 sizeof(char *) * cnt,
1597 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
1598 for (i = 0; i < cnt; i++) {
1599 dst->device_extension_list.list->entrypoints[i] = loader_heap_alloc(
1600 inst,
1601 strlen(src->device_extension_list.list->entrypoints[i]) + 1,
1602 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
1603 strcpy(dst->device_extension_list.list->entrypoints[i],
1604 src->device_extension_list.list->entrypoints[i]);
1605 }
1606 }
Jon Ashburn3d002332015-08-20 16:35:30 -06001607}
1608
1609/**
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001610 * Given a cJSON struct (json) of the top level JSON object from layer manifest
1611 * file, add entry to the layer_list.
Jon Ashburne13ecc92015-08-03 17:19:30 -06001612 * Fill out the layer_properties in this list entry from the input cJSON object.
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001613 *
1614 * \returns
1615 * void
1616 * layer_list has a new entry and initialized accordingly.
1617 * If the json input object does not have all the required fields no entry
1618 * is added to the list.
1619 */
Jon Ashburne39a4f82015-08-28 13:38:21 -06001620static void loader_add_layer_properties(const struct loader_instance *inst,
1621 struct loader_layer_list *layer_instance_list,
Jon Ashburnb2ef1372015-07-16 17:19:31 -06001622 struct loader_layer_list *layer_device_list,
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001623 cJSON *json,
1624 bool is_implicit,
1625 char *filename)
1626{
1627 /* Fields in layer manifest file that are required:
1628 * (required) “file_format_version”
1629 * following are required in the "layer" object:
1630 * (required) "name"
1631 * (required) "type"
1632 * (required) “library_path”
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001633 * (required) “api_version”
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001634 * (required) “implementation_version”
1635 * (required) “description”
1636 * (required for implicit layers) “disable_environment”
1637 *
1638 * First get all required items and if any missing abort
1639 */
1640
1641 cJSON *item, *layer_node, *ext_item;
1642 char *temp;
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001643 char *name, *type, *library_path, *api_version;
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001644 char *implementation_version, *description;
1645 cJSON *disable_environment;
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001646 int i, j;
Jon Ashburn5c042ea2015-08-04 11:14:18 -06001647 VkExtensionProperties ext_prop;
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001648 item = cJSON_GetObjectItem(json, "file_format_version");
1649 if (item == NULL) {
1650 return;
1651 }
1652 char *file_vers = cJSON_PrintUnformatted(item);
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001653 loader_log(inst, VK_DEBUG_REPORT_INFO_BIT_EXT, 0, "Found manifest file %s, version %s",
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001654 filename, file_vers);
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001655 if (strcmp(file_vers, "\"1.0.0\"") != 0)
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001656 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0, "Unexpected manifest file version (expected 1.0.0), may cause errors");
Jon Ashburn87d6aa92015-08-28 15:19:27 -06001657 loader_tls_heap_free(file_vers);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001658
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001659 layer_node = cJSON_GetObjectItem(json, "layer");
1660 if (layer_node == NULL) {
Jon Ashburn075ce432015-12-17 17:38:24 -07001661 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0, "Can't find \"layer\" object in manifest JSON file, skipping this file");
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001662 return;
1663 }
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001664
1665 // loop through all "layer" objects in the file
1666 do {
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001667#define GET_JSON_OBJECT(node, var) { \
1668 var = cJSON_GetObjectItem(node, #var); \
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001669 if (var == NULL) { \
1670 layer_node = layer_node->next; \
Jon Ashburn075ce432015-12-17 17:38:24 -07001671 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0,\
1672 "Didn't find required layer object %s in manifest JSON file, skipping this layer",\
1673 #var); \
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001674 continue; \
1675 } \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001676 }
1677#define GET_JSON_ITEM(node, var) { \
1678 item = cJSON_GetObjectItem(node, #var); \
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001679 if (item == NULL) { \
1680 layer_node = layer_node->next; \
Jon Ashburn075ce432015-12-17 17:38:24 -07001681 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0,\
1682 "Didn't find required layer value %s in manifest JSON file, skipping this layer",\
1683 #var); \
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001684 continue; \
1685 } \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001686 temp = cJSON_Print(item); \
1687 temp[strlen(temp) - 1] = '\0'; \
Jon Ashburnf73e9212015-08-04 10:22:33 -06001688 var = loader_stack_alloc(strlen(temp) + 1); \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001689 strcpy(var, &temp[1]); \
Jon Ashburn87d6aa92015-08-28 15:19:27 -06001690 loader_tls_heap_free(temp); \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001691 }
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001692 GET_JSON_ITEM(layer_node, name)
1693 GET_JSON_ITEM(layer_node, type)
1694 GET_JSON_ITEM(layer_node, library_path)
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001695 GET_JSON_ITEM(layer_node, api_version)
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001696 GET_JSON_ITEM(layer_node, implementation_version)
1697 GET_JSON_ITEM(layer_node, description)
1698 if (is_implicit) {
1699 GET_JSON_OBJECT(layer_node, disable_environment)
1700 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001701#undef GET_JSON_ITEM
1702#undef GET_JSON_OBJECT
1703
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001704 // add list entry
Jon Ashburn432d2762015-09-18 12:53:16 -06001705 struct loader_layer_properties *props=NULL;
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001706 if (!strcmp(type, "DEVICE")) {
1707 if (layer_device_list == NULL) {
1708 layer_node = layer_node->next;
1709 continue;
1710 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06001711 props = loader_get_next_layer_property(inst, layer_device_list);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001712 props->type = (is_implicit) ? VK_LAYER_TYPE_DEVICE_IMPLICIT : VK_LAYER_TYPE_DEVICE_EXPLICIT;
1713 }
1714 if (!strcmp(type, "INSTANCE")) {
1715 if (layer_instance_list == NULL) {
1716 layer_node = layer_node->next;
1717 continue;
1718 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06001719 props = loader_get_next_layer_property(inst, layer_instance_list);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001720 props->type = (is_implicit) ? VK_LAYER_TYPE_INSTANCE_IMPLICIT : VK_LAYER_TYPE_INSTANCE_EXPLICIT;
1721 }
1722 if (!strcmp(type, "GLOBAL")) {
1723 if (layer_instance_list != NULL)
Jon Ashburne39a4f82015-08-28 13:38:21 -06001724 props = loader_get_next_layer_property(inst, layer_instance_list);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001725 else if (layer_device_list != NULL)
Jon Ashburne39a4f82015-08-28 13:38:21 -06001726 props = loader_get_next_layer_property(inst, layer_device_list);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001727 else {
1728 layer_node = layer_node->next;
1729 continue;
1730 }
1731 props->type = (is_implicit) ? VK_LAYER_TYPE_GLOBAL_IMPLICIT : VK_LAYER_TYPE_GLOBAL_EXPLICIT;
1732 }
Jon Ashburnb2ef1372015-07-16 17:19:31 -06001733
Jon Ashburn432d2762015-09-18 12:53:16 -06001734 if (props == NULL) {
1735 layer_node = layer_node->next;
1736 continue;
1737 }
1738
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001739 strncpy(props->info.layerName, name, sizeof (props->info.layerName));
1740 props->info.layerName[sizeof (props->info.layerName) - 1] = '\0';
Jon Ashburn15315172015-07-07 15:06:25 -06001741
Jon Ashburn3d002332015-08-20 16:35:30 -06001742 char *fullpath = props->lib_name;
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001743 char *rel_base;
Jon Ashburn6e08ebd2015-12-01 17:11:02 -07001744 if (loader_platform_is_path(library_path)) {
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001745 // a relative or absolute path
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001746 char *name_copy = loader_stack_alloc(strlen(filename) + 1);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001747 strcpy(name_copy, filename);
1748 rel_base = loader_platform_dirname(name_copy);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001749 loader_expand_path(library_path, rel_base, MAX_STRING_SIZE, fullpath);
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001750 } else {
1751 // a filename which is assumed in a system directory
1752 loader_get_fullpath(library_path, DEFAULT_VK_LAYERS_PATH, MAX_STRING_SIZE, fullpath);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001753 }
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001754 props->info.specVersion = loader_make_version(api_version);
1755 props->info.implementationVersion = atoi(implementation_version);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001756 strncpy((char *) props->info.description, description, sizeof (props->info.description));
1757 props->info.description[sizeof (props->info.description) - 1] = '\0';
1758 if (is_implicit) {
1759 strncpy(props->disable_env_var.name, disable_environment->child->string, sizeof (props->disable_env_var.name));
1760 props->disable_env_var.name[sizeof (props->disable_env_var.name) - 1] = '\0';
1761 strncpy(props->disable_env_var.value, disable_environment->child->valuestring, sizeof (props->disable_env_var.value));
1762 props->disable_env_var.value[sizeof (props->disable_env_var.value) - 1] = '\0';
1763 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001764
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001765 /**
1766 * Now get all optional items and objects and put in list:
1767 * functions
1768 * instance_extensions
1769 * device_extensions
1770 * enable_environment (implicit layers only)
1771 */
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001772#define GET_JSON_OBJECT(node, var) { \
1773 var = cJSON_GetObjectItem(node, #var); \
1774 }
1775#define GET_JSON_ITEM(node, var) { \
1776 item = cJSON_GetObjectItem(node, #var); \
Jon Ashburn21c21ee2015-09-09 11:29:24 -06001777 if (item != NULL) { \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001778 temp = cJSON_Print(item); \
Jon Ashburn21c21ee2015-09-09 11:29:24 -06001779 temp[strlen(temp) - 1] = '\0'; \
1780 var = loader_stack_alloc(strlen(temp) + 1);\
1781 strcpy(var, &temp[1]); \
1782 loader_tls_heap_free(temp); \
1783 } \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001784 }
1785
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001786 cJSON *instance_extensions, *device_extensions, *functions, *enable_environment;
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001787 cJSON *entrypoints;
1788 char *vkGetInstanceProcAddr, *vkGetDeviceProcAddr, *spec_version;
1789 char **entry_array;
1790 vkGetInstanceProcAddr = NULL;
1791 vkGetDeviceProcAddr = NULL;
1792 spec_version = NULL;
1793 entrypoints = NULL;
1794 entry_array = NULL;
1795 /**
1796 * functions
1797 * vkGetInstanceProcAddr
1798 * vkGetDeviceProcAddr
1799 */
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001800 GET_JSON_OBJECT(layer_node, functions)
1801 if (functions != NULL) {
1802 GET_JSON_ITEM(functions, vkGetInstanceProcAddr)
1803 GET_JSON_ITEM(functions, vkGetDeviceProcAddr)
Jon Ashburn21c21ee2015-09-09 11:29:24 -06001804 if (vkGetInstanceProcAddr != NULL)
1805 strncpy(props->functions.str_gipa, vkGetInstanceProcAddr, sizeof (props->functions.str_gipa));
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001806 props->functions.str_gipa[sizeof (props->functions.str_gipa) - 1] = '\0';
Jon Ashburn21c21ee2015-09-09 11:29:24 -06001807 if (vkGetDeviceProcAddr != NULL)
1808 strncpy(props->functions.str_gdpa, vkGetDeviceProcAddr, sizeof (props->functions.str_gdpa));
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001809 props->functions.str_gdpa[sizeof (props->functions.str_gdpa) - 1] = '\0';
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001810 }
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001811 /**
1812 * instance_extensions
1813 * array of
1814 * name
1815 * spec_version
1816 */
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001817 GET_JSON_OBJECT(layer_node, instance_extensions)
1818 if (instance_extensions != NULL) {
1819 int count = cJSON_GetArraySize(instance_extensions);
1820 for (i = 0; i < count; i++) {
1821 ext_item = cJSON_GetArrayItem(instance_extensions, i);
1822 GET_JSON_ITEM(ext_item, name)
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001823 GET_JSON_ITEM(ext_item, spec_version)
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001824 if (name != NULL) {
Jon Ashburn6e6a2162015-12-10 08:51:10 -07001825 strncpy(ext_prop.extensionName, name, sizeof (ext_prop.extensionName));
1826 ext_prop.extensionName[sizeof (ext_prop.extensionName) - 1] = '\0';
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001827 }
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001828 ext_prop.specVersion = atoi(spec_version);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001829 loader_add_to_ext_list(inst, &props->instance_extension_list, 1, &ext_prop);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001830 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001831 }
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001832 /**
1833 * device_extensions
1834 * array of
1835 * name
1836 * spec_version
1837 * entrypoints
1838 */
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001839 GET_JSON_OBJECT(layer_node, device_extensions)
1840 if (device_extensions != NULL) {
1841 int count = cJSON_GetArraySize(device_extensions);
1842 for (i = 0; i < count; i++) {
1843 ext_item = cJSON_GetArrayItem(device_extensions, i);
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001844 GET_JSON_ITEM(ext_item, name)
1845 GET_JSON_ITEM(ext_item, spec_version)
1846 if (name != NULL) {
Jon Ashburn6e6a2162015-12-10 08:51:10 -07001847 strncpy(ext_prop.extensionName, name, sizeof (ext_prop.extensionName));
1848 ext_prop.extensionName[sizeof (ext_prop.extensionName) - 1] = '\0';
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001849 }
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001850 ext_prop.specVersion = atoi(spec_version);
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001851 //entrypoints = cJSON_GetObjectItem(ext_item, "entrypoints");
1852 GET_JSON_OBJECT(ext_item, entrypoints)
1853 int entry_count;
1854 if (entrypoints == NULL)
1855 continue;
1856 entry_count = cJSON_GetArraySize(entrypoints);
1857 if (entry_count)
1858 entry_array = (char **) loader_stack_alloc(sizeof(char *) * entry_count);
1859 for (j = 0; j < entry_count; j++) {
1860 ext_item = cJSON_GetArrayItem(entrypoints, j);
1861 if (ext_item != NULL) {
1862 temp = cJSON_Print(ext_item);
1863 temp[strlen(temp) - 1] = '\0';
1864 entry_array[j] = loader_stack_alloc(strlen(temp) + 1);
1865 strcpy(entry_array[j], &temp[1]);
1866 loader_tls_heap_free(temp);
Jon Ashburn6e6a2162015-12-10 08:51:10 -07001867 }
1868 }
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001869 loader_add_to_dev_ext_list(inst, &props->device_extension_list,
1870 &ext_prop, entry_count, entry_array);
1871 }
1872 }
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001873 if (is_implicit) {
1874 GET_JSON_OBJECT(layer_node, enable_environment)
Jon Ashburn075ce432015-12-17 17:38:24 -07001875
1876 // enable_environment is optional
1877 if (enable_environment) {
1878 strncpy(props->enable_env_var.name, enable_environment->child->string, sizeof (props->enable_env_var.name));
1879 props->enable_env_var.name[sizeof (props->enable_env_var.name) - 1] = '\0';
1880 strncpy(props->enable_env_var.value, enable_environment->child->valuestring, sizeof (props->enable_env_var.value));
1881 props->enable_env_var.value[sizeof (props->enable_env_var.value) - 1] = '\0';
1882 }
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001883 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001884#undef GET_JSON_ITEM
1885#undef GET_JSON_OBJECT
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001886 // for global layers need to add them to both device and instance list
1887 if (!strcmp(type, "GLOBAL")) {
1888 struct loader_layer_properties *dev_props;
1889 if (layer_instance_list == NULL || layer_device_list == NULL) {
1890 layer_node = layer_node->next;
1891 continue;
1892 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06001893 dev_props = loader_get_next_layer_property(inst, layer_device_list);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001894 //copy into device layer list
Jon Ashburne39a4f82015-08-28 13:38:21 -06001895 loader_copy_layer_properties(inst, dev_props, props);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001896 }
1897 layer_node = layer_node->next;
1898 } while (layer_node != NULL);
1899 return;
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001900}
1901
1902/**
Jon Ashburn2077e382015-06-29 11:25:34 -06001903 * Find the Vulkan library manifest files.
1904 *
1905 * This function scans the location or env_override directories/files
1906 * for a list of JSON manifest files. If env_override is non-NULL
1907 * and has a valid value. Then the location is ignored. Otherwise
1908 * location is used to look for manifest files. The location
1909 * is interpreted as Registry path on Windows and a directory path(s)
1910 * on Linux.
1911 *
1912 * \returns
1913 * A string list of manifest files to be opened in out_files param.
1914 * List has a pointer to string for each manifest filename.
1915 * When done using the list in out_files, pointers should be freed.
Jon Ashburnffad94d2015-06-30 14:46:22 -07001916 * Location or override string lists can be either files or directories as follows:
1917 * | location | override
1918 * --------------------------------
1919 * Win ICD | files | files
1920 * Win Layer | files | dirs
1921 * Linux ICD | dirs | files
1922 * Linux Layer| dirs | dirs
Jon Ashburn2077e382015-06-29 11:25:34 -06001923 */
Jon Ashburne39a4f82015-08-28 13:38:21 -06001924static void loader_get_manifest_files(const struct loader_instance *inst,
1925 const char *env_override,
Jon Ashburnffad94d2015-06-30 14:46:22 -07001926 bool is_layer,
1927 const char *location,
1928 struct loader_manifest_files *out_files)
Jon Ashburn2077e382015-06-29 11:25:34 -06001929{
1930 char *override = NULL;
1931 char *loc;
1932 char *file, *next_file, *name;
1933 size_t alloced_count = 64;
1934 char full_path[2048];
1935 DIR *sysdir = NULL;
Jon Ashburnffad94d2015-06-30 14:46:22 -07001936 bool list_is_dirs = false;
Jon Ashburn2077e382015-06-29 11:25:34 -06001937 struct dirent *dent;
1938
1939 out_files->count = 0;
1940 out_files->filename_list = NULL;
1941
Jon Ashburn2077e382015-06-29 11:25:34 -06001942 if (env_override != NULL && (override = getenv(env_override))) {
Johannes van Waveren9bd805012015-10-28 11:45:00 -05001943#if !defined(_WIN32)
Jon Ashburn2077e382015-06-29 11:25:34 -06001944 if (geteuid() != getuid()) {
Jon Ashburnffad94d2015-06-30 14:46:22 -07001945 /* Don't allow setuid apps to use the env var: */
Jon Ashburn2077e382015-06-29 11:25:34 -06001946 override = NULL;
1947 }
1948#endif
1949 }
1950
1951 if (location == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001952 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburnffad94d2015-06-30 14:46:22 -07001953 "Can't get manifest files with NULL location, env_override=%s",
1954 env_override);
Jon Ashburn2077e382015-06-29 11:25:34 -06001955 return;
1956 }
1957
Johannes van Waveren9bd805012015-10-28 11:45:00 -05001958#if defined(_WIN32)
Jon Ashburnffad94d2015-06-30 14:46:22 -07001959 list_is_dirs = (is_layer && override != NULL) ? true : false;
Johannes van Waveren9bd805012015-10-28 11:45:00 -05001960#else
1961 list_is_dirs = (override == NULL || is_layer) ? true : false;
Jon Ashburnffad94d2015-06-30 14:46:22 -07001962#endif
Jon Ashburn2077e382015-06-29 11:25:34 -06001963 // Make a copy of the input we are using so it is not modified
Jon Ashburnffad94d2015-06-30 14:46:22 -07001964 // Also handle getting the location(s) from registry on Windows
1965 if (override == NULL) {
Jon Ashburn3b78e462015-07-31 10:11:24 -06001966 loc = loader_stack_alloc(strlen(location) + 1);
Jon Ashburnffad94d2015-06-30 14:46:22 -07001967 if (loc == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001968 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Out of memory can't get manifest files");
Jon Ashburnffad94d2015-06-30 14:46:22 -07001969 return;
1970 }
1971 strcpy(loc, location);
Johannes van Waveren9bd805012015-10-28 11:45:00 -05001972#if defined(_WIN32)
Jon Ashburn480a50a2015-08-28 14:58:46 -07001973 loc = loader_get_registry_files(inst, loc);
Jon Ashburn24265ac2015-07-31 09:33:21 -06001974 if (loc == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001975 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Registry lookup failed can't get manifest files");
Jon Ashburn24265ac2015-07-31 09:33:21 -06001976 return;
1977 }
Jon Ashburnffad94d2015-06-30 14:46:22 -07001978#endif
Jon Ashburn2077e382015-06-29 11:25:34 -06001979 }
Jon Ashburnffad94d2015-06-30 14:46:22 -07001980 else {
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -06001981 loc = loader_stack_alloc(strlen(override) + 1);
Jon Ashburnffad94d2015-06-30 14:46:22 -07001982 if (loc == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001983 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Out of memory can't get manifest files");
Jon Ashburnffad94d2015-06-30 14:46:22 -07001984 return;
1985 }
1986 strcpy(loc, override);
1987 }
Jon Ashburn2077e382015-06-29 11:25:34 -06001988
Liam Middlebrook9b14e892015-07-23 18:32:20 -07001989 // Print out the paths being searched if debugging is enabled
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001990 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Searching the following paths for manifest files: %s\n", loc);
Liam Middlebrook9b14e892015-07-23 18:32:20 -07001991
Jon Ashburn2077e382015-06-29 11:25:34 -06001992 file = loc;
1993 while (*file) {
1994 next_file = loader_get_next_path(file);
Jon Ashburnffad94d2015-06-30 14:46:22 -07001995 if (list_is_dirs) {
Jon Ashburn2077e382015-06-29 11:25:34 -06001996 sysdir = opendir(file);
1997 name = NULL;
1998 if (sysdir) {
1999 dent = readdir(sysdir);
2000 if (dent == NULL)
2001 break;
2002 name = &(dent->d_name[0]);
2003 loader_get_fullpath(name, file, sizeof(full_path), full_path);
2004 name = full_path;
2005 }
2006 }
2007 else {
Johannes van Waveren9bd805012015-10-28 11:45:00 -05002008#if defined(_WIN32)
2009 name = file;
2010#else
Jon Ashburnffad94d2015-06-30 14:46:22 -07002011 // only Linux has relative paths
Jon Ashburn2077e382015-06-29 11:25:34 -06002012 char *dir;
2013 // make a copy of location so it isn't modified
Jason Ekstrandcc7550e2015-10-10 08:33:37 -07002014 dir = loader_stack_alloc(strlen(loc) + 1);
Jon Ashburn2077e382015-06-29 11:25:34 -06002015 if (dir == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002016 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Out of memory can't get manifest files");
Jon Ashburn2077e382015-06-29 11:25:34 -06002017 return;
2018 }
Jason Ekstrandcc7550e2015-10-10 08:33:37 -07002019 strcpy(dir, loc);
Jon Ashburn2077e382015-06-29 11:25:34 -06002020
2021 loader_get_fullpath(file, dir, sizeof(full_path), full_path);
2022
2023 name = full_path;
Jon Ashburnffad94d2015-06-30 14:46:22 -07002024#endif
Jon Ashburn2077e382015-06-29 11:25:34 -06002025 }
2026 while (name) {
2027 /* Look for files ending with ".json" suffix */
2028 uint32_t nlen = (uint32_t) strlen(name);
2029 const char *suf = name + nlen - 5;
2030 if ((nlen > 5) && !strncmp(suf, ".json", 5)) {
2031 if (out_files->count == 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06002032 out_files->filename_list = loader_heap_alloc(inst,
2033 alloced_count * sizeof(char *),
Chia-I Wucf804e82015-10-31 00:31:16 +08002034 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
Jon Ashburn2077e382015-06-29 11:25:34 -06002035 }
2036 else if (out_files->count == alloced_count) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06002037 out_files->filename_list = loader_heap_realloc(inst,
2038 out_files->filename_list,
2039 alloced_count * sizeof(char *),
2040 alloced_count * sizeof(char *) * 2,
Chia-I Wucf804e82015-10-31 00:31:16 +08002041 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
Jon Ashburn2077e382015-06-29 11:25:34 -06002042 alloced_count *= 2;
2043 }
2044 if (out_files->filename_list == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002045 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Out of memory can't alloc manifest file list");
Jon Ashburn2077e382015-06-29 11:25:34 -06002046 return;
2047 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06002048 out_files->filename_list[out_files->count] = loader_heap_alloc(
2049 inst,
2050 strlen(name) + 1,
Chia-I Wucf804e82015-10-31 00:31:16 +08002051 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
Jon Ashburn2077e382015-06-29 11:25:34 -06002052 if (out_files->filename_list[out_files->count] == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002053 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Out of memory can't get manifest files");
Jon Ashburn2077e382015-06-29 11:25:34 -06002054 return;
2055 }
2056 strcpy(out_files->filename_list[out_files->count], name);
2057 out_files->count++;
Jon Ashburnf70f3612015-07-02 10:08:47 -06002058 } else if (!list_is_dirs) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002059 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0, "Skipping manifest file %s, file name must end in .json", name);
Jon Ashburn2077e382015-06-29 11:25:34 -06002060 }
Jon Ashburnffad94d2015-06-30 14:46:22 -07002061 if (list_is_dirs) {
Jon Ashburn2077e382015-06-29 11:25:34 -06002062 dent = readdir(sysdir);
2063 if (dent == NULL)
2064 break;
2065 name = &(dent->d_name[0]);
2066 loader_get_fullpath(name, file, sizeof(full_path), full_path);
2067 name = full_path;
2068 }
2069 else {
2070 break;
2071 }
2072 }
2073 if (sysdir)
2074 closedir(sysdir);
2075 file = next_file;
2076 }
2077 return;
2078}
2079
Jon Ashburn8810c5f2015-08-18 18:04:47 -06002080void loader_init_icd_lib_list()
2081{
2082
2083}
2084
2085void loader_destroy_icd_lib_list()
2086{
2087
2088}
Jon Ashburn2077e382015-06-29 11:25:34 -06002089/**
2090 * Try to find the Vulkan ICD driver(s).
2091 *
2092 * This function scans the default system loader path(s) or path
2093 * specified by the \c VK_ICD_FILENAMES environment variable in
2094 * order to find loadable VK ICDs manifest files. From these
2095 * manifest files it finds the ICD libraries.
2096 *
2097 * \returns
Jon Ashburn8810c5f2015-08-18 18:04:47 -06002098 * a list of icds that were discovered
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06002099 */
Jon Ashburne39a4f82015-08-28 13:38:21 -06002100void loader_icd_scan(
2101 const struct loader_instance *inst,
2102 struct loader_icd_libs *icds)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08002103{
Jon Ashburn2077e382015-06-29 11:25:34 -06002104 char *file_str;
2105 struct loader_manifest_files manifest_files;
2106
Jon Ashburne39a4f82015-08-28 13:38:21 -06002107 loader_scanned_icd_init(inst, icds);
Jon Ashburn2077e382015-06-29 11:25:34 -06002108 // Get a list of manifest files for ICDs
Jon Ashburne39a4f82015-08-28 13:38:21 -06002109 loader_get_manifest_files(inst, "VK_ICD_FILENAMES", false,
2110 DEFAULT_VK_DRIVERS_INFO, &manifest_files);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002111 if (manifest_files.count == 0)
2112 return;
Jon Ashburn6461ef22015-09-22 13:11:00 -06002113 loader_platform_thread_lock_mutex(&loader_json_lock);
Jon Ashburn2077e382015-06-29 11:25:34 -06002114 for (uint32_t i = 0; i < manifest_files.count; i++) {
2115 file_str = manifest_files.filename_list[i];
2116 if (file_str == NULL)
2117 continue;
2118
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002119 cJSON *json;
Courtney Goeltzenleuchter73477392015-12-03 13:48:01 -07002120 json = loader_get_json(inst, file_str);
Jon Ashburnaa4ea472015-08-27 08:30:50 -06002121 if (!json)
2122 continue;
Jon Ashburn005617f2015-11-17 17:35:40 -07002123 cJSON *item, *itemICD;
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002124 item = cJSON_GetObjectItem(json, "file_format_version");
Jon Ashburn6461ef22015-09-22 13:11:00 -06002125 if (item == NULL) {
2126 loader_platform_thread_unlock_mutex(&loader_json_lock);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002127 return;
Jon Ashburn6461ef22015-09-22 13:11:00 -06002128 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002129 char *file_vers = cJSON_Print(item);
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002130 loader_log(inst, VK_DEBUG_REPORT_INFO_BIT_EXT, 0, "Found manifest file %s, version %s",
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002131 file_str, file_vers);
2132 if (strcmp(file_vers, "\"1.0.0\"") != 0)
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002133 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0, "Unexpected manifest file version (expected 1.0.0), may cause errors");
Jon Ashburn87d6aa92015-08-28 15:19:27 -06002134 loader_tls_heap_free(file_vers);
Jon Ashburn005617f2015-11-17 17:35:40 -07002135 itemICD = cJSON_GetObjectItem(json, "ICD");
2136 if (itemICD != NULL) {
2137 item = cJSON_GetObjectItem(itemICD, "library_path");
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002138 if (item != NULL) {
Jon Ashburn86251302015-08-25 16:48:24 -06002139 char *temp= cJSON_Print(item);
2140 if (!temp || strlen(temp) == 0) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002141 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0, "Can't find \"library_path\" in ICD JSON file %s, skipping", file_str);
Jon Ashburn87d6aa92015-08-28 15:19:27 -06002142 loader_tls_heap_free(temp);
Jon Ashburne39a4f82015-08-28 13:38:21 -06002143 loader_heap_free(inst, file_str);
Jon Ashburn86251302015-08-25 16:48:24 -06002144 cJSON_Delete(json);
2145 continue;
Jon Ashburn2077e382015-06-29 11:25:34 -06002146 }
Jon Ashburn86251302015-08-25 16:48:24 -06002147 //strip out extra quotes
2148 temp[strlen(temp) - 1] = '\0';
2149 char *library_path = loader_stack_alloc(strlen(temp) + 1);
2150 strcpy(library_path, &temp[1]);
Jon Ashburn87d6aa92015-08-28 15:19:27 -06002151 loader_tls_heap_free(temp);
Jon Ashburn86251302015-08-25 16:48:24 -06002152 if (!library_path || strlen(library_path) == 0) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002153 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0, "Can't find \"library_path\" in ICD JSON file %s, skipping", file_str);
Jon Ashburne39a4f82015-08-28 13:38:21 -06002154 loader_heap_free(inst, file_str);
Jon Ashburn86251302015-08-25 16:48:24 -06002155 cJSON_Delete(json);
2156 continue;
2157 }
Daniel Dadap00b4aba2015-09-30 11:50:51 -05002158 char fullpath[MAX_STRING_SIZE];
Jon Ashburn86251302015-08-25 16:48:24 -06002159 // Print out the paths being searched if debugging is enabled
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002160 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Searching for ICD drivers named %s default dir %s\n", library_path, DEFAULT_VK_DRIVERS_PATH);
Daniel Dadap00b4aba2015-09-30 11:50:51 -05002161 if (loader_platform_is_path(library_path)) {
Jon Ashburn86251302015-08-25 16:48:24 -06002162 // a relative or absolute path
Daniel Dadap00b4aba2015-09-30 11:50:51 -05002163 char *name_copy = loader_stack_alloc(strlen(file_str) + 1);
2164 char *rel_base;
Jon Ashburn86251302015-08-25 16:48:24 -06002165 strcpy(name_copy, file_str);
2166 rel_base = loader_platform_dirname(name_copy);
Daniel Dadap00b4aba2015-09-30 11:50:51 -05002167 loader_expand_path(library_path, rel_base, sizeof(fullpath), fullpath);
2168 } else {
2169 // a filename which is assumed in a system directory
2170 loader_get_fullpath(library_path, DEFAULT_VK_DRIVERS_PATH, sizeof(fullpath), fullpath);
Jon Ashburn86251302015-08-25 16:48:24 -06002171 }
Jon Ashburn005617f2015-11-17 17:35:40 -07002172
2173 uint32_t vers = 0;
2174 item = cJSON_GetObjectItem(itemICD, "api_version");
2175 if (item != NULL) {
2176 temp= cJSON_Print(item);
2177 vers = loader_make_version(temp);
2178 loader_tls_heap_free(temp);
2179 }
2180 loader_scanned_icd_add(inst, icds, fullpath, vers);
Jon Ashburn2077e382015-06-29 11:25:34 -06002181 }
Jon Ashburn005617f2015-11-17 17:35:40 -07002182 else
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002183 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0, "Can't find \"library_path\" object in ICD JSON file %s, skipping", file_str);
Jon Ashburn2077e382015-06-29 11:25:34 -06002184 }
2185 else
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002186 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0, "Can't find \"ICD\" object in ICD JSON file %s, skipping", file_str);
Jon Ashburn2077e382015-06-29 11:25:34 -06002187
Jon Ashburne39a4f82015-08-28 13:38:21 -06002188 loader_heap_free(inst, file_str);
Jon Ashburn2077e382015-06-29 11:25:34 -06002189 cJSON_Delete(json);
2190 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06002191 loader_heap_free(inst, manifest_files.filename_list);
Jon Ashburn6461ef22015-09-22 13:11:00 -06002192 loader_platform_thread_unlock_mutex(&loader_json_lock);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08002193}
2194
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002195
Jon Ashburne39a4f82015-08-28 13:38:21 -06002196void loader_layer_scan(
2197 const struct loader_instance *inst,
2198 struct loader_layer_list *instance_layers,
2199 struct loader_layer_list *device_layers)
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002200{
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002201 char *file_str;
Jon Ashburn075ce432015-12-17 17:38:24 -07002202 struct loader_manifest_files manifest_files[2]; // [0] = explicit, [1] = implicit
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002203 cJSON *json;
2204 uint32_t i;
Jon Ashburn075ce432015-12-17 17:38:24 -07002205 uint32_t implicit;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002206
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002207 // Get a list of manifest files for layers
Jon Ashburn075ce432015-12-17 17:38:24 -07002208 loader_get_manifest_files(inst, LAYERS_PATH_ENV, true, DEFAULT_VK_ELAYERS_INFO,
2209 &manifest_files[0]);
Jon Ashburnb1a03e02015-12-24 13:58:35 -07002210 // Pass NULL for environment variable override - implicit layers are not overridden by LAYERS_PATH_ENV
2211 loader_get_manifest_files(inst, NULL, true, DEFAULT_VK_ILAYERS_INFO,
Jon Ashburn075ce432015-12-17 17:38:24 -07002212 &manifest_files[1]);
2213 if (manifest_files[0].count == 0 && manifest_files[1].count == 0)
Courtney Goeltzenleuchter57985ce2014-12-01 09:29:42 -07002214 return;
Jon Ashburn90c6a0e2015-06-04 15:30:58 -06002215
Jon Ashburne13ecc92015-08-03 17:19:30 -06002216#if 0 //TODO
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002217 /**
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -06002218 * We need a list of the layer libraries, not just a list of
2219 * the layer properties (a layer library could expose more than
2220 * one layer property). This list of scanned layers would be
2221 * used to check for global and physicaldevice layer properties.
2222 */
2223 if (!loader_init_layer_library_list(&loader.scanned_layer_libraries)) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002224 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburne39a4f82015-08-28 13:38:21 -06002225 "Alloc for layer list failed: %s line: %d", __FILE__, __LINE__);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -06002226 return;
Jon Ashburn5ef20602015-07-02 09:40:15 -06002227 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002228#endif
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002229
Jon Ashburne13ecc92015-08-03 17:19:30 -06002230 /* cleanup any previously scanned libraries */
Jon Ashburne39a4f82015-08-28 13:38:21 -06002231 loader_delete_layer_properties(inst, instance_layers);
2232 loader_delete_layer_properties(inst, device_layers);
Jon Ashburnb2ef1372015-07-16 17:19:31 -06002233
Jon Ashburn6461ef22015-09-22 13:11:00 -06002234 loader_platform_thread_lock_mutex(&loader_json_lock);
Jon Ashburn075ce432015-12-17 17:38:24 -07002235 for (implicit = 0; implicit < 2; implicit++) {
2236 for (i = 0; i < manifest_files[implicit].count; i++) {
2237 file_str = manifest_files[implicit].filename_list[i];
2238 if (file_str == NULL)
2239 continue;
Courtney Goeltzenleuchtera9e4af42015-06-01 14:49:17 -06002240
Jon Ashburn075ce432015-12-17 17:38:24 -07002241 // parse file into JSON struct
2242 json = loader_get_json(inst, file_str);
2243 if (!json) {
2244 continue;
2245 }
2246
2247 //TODO error if device layers expose instance_extensions
2248 //TODO error if instance layers expose device extensions
2249 loader_add_layer_properties(inst,
2250 instance_layers,
2251 device_layers,
2252 json,
2253 (implicit == 1),
2254 file_str);
2255
2256 loader_heap_free(inst, file_str);
2257 cJSON_Delete(json);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002258 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002259 }
Jon Ashburn075ce432015-12-17 17:38:24 -07002260 if (manifest_files[0].count != 0)
2261 loader_heap_free(inst, manifest_files[0].filename_list);
2262
2263 if (manifest_files[1].count != 0)
2264 loader_heap_free(inst, manifest_files[1].filename_list);
Jon Ashburn6461ef22015-09-22 13:11:00 -06002265 loader_platform_thread_unlock_mutex(&loader_json_lock);
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002266}
2267
Chia-I Wu9ab61502015-11-06 06:42:02 +08002268static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL loader_gpa_instance_internal(VkInstance inst, const char * pName)
Jon Ashburn27cd5842015-05-12 17:26:48 -06002269{
2270 // inst is not wrapped
2271 if (inst == VK_NULL_HANDLE) {
2272 return NULL;
2273 }
2274 VkLayerInstanceDispatchTable* disp_table = * (VkLayerInstanceDispatchTable **) inst;
2275 void *addr;
2276
Jon Ashburn8fd08252015-05-28 16:25:02 -06002277 if (!strcmp(pName, "vkGetInstanceProcAddr"))
2278 return (void *) loader_gpa_instance_internal;
2279
Jon Ashburn27cd5842015-05-12 17:26:48 -06002280 if (disp_table == NULL)
2281 return NULL;
2282
2283 addr = loader_lookup_instance_dispatch_table(disp_table, pName);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002284 if (addr) {
Jon Ashburn27cd5842015-05-12 17:26:48 -06002285 return addr;
Jon Ashburn3d526cb2015-04-13 18:10:06 -06002286 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002287
2288 if (disp_table->GetInstanceProcAddr == NULL) {
2289 return NULL;
2290 }
2291 return disp_table->GetInstanceProcAddr(inst, pName);
Jon Ashburn3d526cb2015-04-13 18:10:06 -06002292}
2293
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002294/**
2295 * Initialize device_ext dispatch table entry as follows:
2296 * If dev == NULL find all logical devices created within this instance and
2297 * init the entry (given by idx) in the ext dispatch table.
2298 * If dev != NULL only initialize the entry in the given dev's dispatch table.
2299 * The initialization value is gotten by calling down the device chain with GDPA.
2300 * If GDPA returns NULL then don't initialize the dispatch table entry.
2301 */
2302static void loader_init_dispatch_dev_ext_entry(struct loader_instance *inst,
2303 struct loader_device *dev,
2304 uint32_t idx,
2305 const char *funcName)
2306
2307 {
2308 void *gdpa_value;
2309 if (dev != NULL) {
2310 gdpa_value = dev->loader_dispatch.core_dispatch.GetDeviceProcAddr(
2311 dev->device, funcName);
2312 if (gdpa_value != NULL)
2313 dev->loader_dispatch.ext_dispatch.DevExt[idx] = (PFN_vkDevExt) gdpa_value;
2314 } else {
2315 for (uint32_t i = 0; i < inst->total_icd_count; i++) {
2316 struct loader_icd *icd = &inst->icds[i];
2317 struct loader_device *dev = icd->logical_device_list;
2318 while (dev) {
2319 gdpa_value = dev->loader_dispatch.core_dispatch.GetDeviceProcAddr(
2320 dev->device, funcName);
2321 if (gdpa_value != NULL)
2322 dev->loader_dispatch.ext_dispatch.DevExt[idx] =
2323 (PFN_vkDevExt) gdpa_value;
2324 dev = dev->next;
2325 }
2326 }
2327 }
2328
2329}
2330
2331/**
2332 * Find all dev extension in the hash table and initialize the dispatch table
2333 * for dev for each of those extension entrypoints found in hash table.
2334
2335 */
2336static void loader_init_dispatch_dev_ext(struct loader_instance *inst,
2337 struct loader_device *dev)
2338{
2339 for (uint32_t i = 0; i < MAX_NUM_DEV_EXTS; i++) {
2340 if (inst->disp_hash[i].func_name != NULL)
2341 loader_init_dispatch_dev_ext_entry(inst, dev, i,
2342 inst->disp_hash[i].func_name);
2343 }
2344}
2345
2346static bool loader_check_icds_for_address(struct loader_instance *inst,
2347 const char *funcName)
2348{
2349 struct loader_icd *icd;
2350 icd = inst->icds;
2351 while (icd) {
2352 if (icd->this_icd_lib->GetInstanceProcAddr(icd->instance, funcName))
2353 // this icd supports funcName
2354 return true;
2355 icd = icd->next;
2356 }
2357
2358 return false;
2359}
2360
2361static void loader_free_dev_ext_table(struct loader_instance *inst)
2362{
2363 for (uint32_t i = 0; i < MAX_NUM_DEV_EXTS; i++) {
2364 loader_heap_free(inst, inst->disp_hash[i].func_name);
2365 loader_heap_free(inst, inst->disp_hash[i].list.index);
2366
2367 }
2368 memset(inst->disp_hash, 0, sizeof(inst->disp_hash));
2369}
2370
2371static bool loader_add_dev_ext_table(struct loader_instance *inst,
2372 uint32_t *ptr_idx,
2373 const char *funcName)
2374{
2375 uint32_t i;
2376 uint32_t idx = *ptr_idx;
2377 struct loader_dispatch_hash_list *list = &inst->disp_hash[idx].list;
2378
2379 if (!inst->disp_hash[idx].func_name) {
2380 // no entry here at this idx, so use it
2381 assert(list->capacity == 0);
2382 inst->disp_hash[idx].func_name = (char *) loader_heap_alloc(inst,
2383 strlen(funcName) + 1,
2384 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
2385 if (inst->disp_hash[idx].func_name == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002386 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002387 "loader_add_dev_ext_table() can't allocate memory for func_name");
2388 return false;
2389 }
2390 strncpy(inst->disp_hash[idx].func_name, funcName, strlen(funcName) + 1);
2391 return true;
2392 }
2393
2394 // check for enough capacity
2395 if (list->capacity == 0) {
2396 list->index = loader_heap_alloc(inst, 8 * sizeof(*(list->index)),
2397 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
2398 if (list->index == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002399 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002400 "loader_add_dev_ext_table() can't allocate list memory");
2401 return false;
2402 }
2403 list->capacity = 8 * sizeof(*(list->index));
2404 } else if (list->capacity < (list->count + 1) * sizeof(*(list->index))) {
2405 list->index = loader_heap_realloc(inst, list->index, list->capacity,
2406 list->capacity * 2,
2407 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
2408 if (list->index == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002409 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002410 "loader_add_dev_ext_table() can't reallocate list memory");
2411 return false;
2412 }
2413 list->capacity *= 2;
2414 }
2415
2416 //find an unused index in the hash table and use it
2417 i = (idx + 1) % MAX_NUM_DEV_EXTS;
2418 do {
2419 if (!inst->disp_hash[i].func_name) {
2420 assert(inst->disp_hash[i].list.capacity == 0);
2421 inst->disp_hash[i].func_name = (char *) loader_heap_alloc(inst,
2422 strlen(funcName) + 1,
2423 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
2424 if (inst->disp_hash[i].func_name == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002425 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002426 "loader_add_dev_ext_table() can't rallocate func_name memory");
2427 return false;
2428 }
2429 strncpy(inst->disp_hash[i].func_name, funcName, strlen(funcName) + 1);
2430 list->index[list->count] = i;
2431 list->count++;
2432 *ptr_idx = i;
2433 return true;
2434 }
2435 i = (i + 1) % MAX_NUM_DEV_EXTS;
2436 } while (i != idx);
2437
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002438 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002439 "loader_add_dev_ext_table() couldn't insert into hash table; is it full?");
2440 return false;
2441}
2442
2443static bool loader_name_in_dev_ext_table(struct loader_instance *inst,
2444 uint32_t *idx,
2445 const char *funcName)
2446{
2447 uint32_t alt_idx;
2448 if (inst->disp_hash[*idx].func_name && !strcmp(
2449 inst->disp_hash[*idx].func_name,
2450 funcName))
2451 return true;
2452
2453 // funcName wasn't at the primary spot in the hash table
2454 // search the list of secondary locations (shallow search, not deep search)
2455 for (uint32_t i = 0; i < inst->disp_hash[*idx].list.count; i++) {
2456 alt_idx = inst->disp_hash[*idx].list.index[i];
2457 if (!strcmp(inst->disp_hash[*idx].func_name, funcName)) {
2458 *idx = alt_idx;
2459 return true;
2460 }
2461 }
2462
2463 return false;
2464}
2465
2466/**
2467 * This function returns generic trampoline code address for unknown entry points.
2468 * Presumably, these unknown entry points (as given by funcName) are device
2469 * extension entrypoints. A hash table is used to keep a list of unknown entry
2470 * points and their mapping to the device extension dispatch table
2471 * (struct loader_dev_ext_dispatch_table).
2472 * \returns
2473 * For a given entry point string (funcName), if an existing mapping is found the
2474 * trampoline address for that mapping is returned. Otherwise, this unknown entry point
2475 * has not been seen yet. Next check if a layer or ICD supports it. If so then a
2476 * new entry in the hash table is initialized and that trampoline address for
2477 * the new entry is returned. Null is returned if the hash table is full or
2478 * if no discovered layer or ICD returns a non-NULL GetProcAddr for it.
2479 */
2480void *loader_dev_ext_gpa(struct loader_instance *inst,
2481 const char *funcName)
2482{
2483 uint32_t idx;
2484 uint32_t seed = 0;
2485
2486 idx = murmurhash(funcName, strlen(funcName), seed) % MAX_NUM_DEV_EXTS;
2487
2488 if (loader_name_in_dev_ext_table(inst, &idx, funcName))
2489 // found funcName already in hash
2490 return loader_get_dev_ext_trampoline(idx);
2491
2492 // Check if funcName is supported in either ICDs or a layer library
2493 if (!loader_check_icds_for_address(inst, funcName)) {
2494 // TODO Add check in layer libraries for support of address
2495 // if support found in layers continue on
2496 return NULL;
2497 }
2498
2499 if (loader_add_dev_ext_table(inst, &idx, funcName)) {
2500 // successfully added new table entry
2501 // init any dev dispatch table entrys as needed
2502 loader_init_dispatch_dev_ext_entry(inst, NULL, idx, funcName);
2503 return loader_get_dev_ext_trampoline(idx);
2504 }
2505
2506 return NULL;
2507}
2508
Jon Ashburne0e64572015-09-30 12:56:42 -06002509struct loader_instance *loader_get_instance(const VkInstance instance)
2510{
2511 /* look up the loader_instance in our list by comparing dispatch tables, as
2512 * there is no guarantee the instance is still a loader_instance* after any
2513 * layers which wrap the instance object.
2514 */
2515 const VkLayerInstanceDispatchTable *disp;
2516 struct loader_instance *ptr_instance = NULL;
2517 disp = loader_get_instance_dispatch(instance);
2518 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
2519 if (inst->disp == disp) {
2520 ptr_instance = inst;
2521 break;
2522 }
2523 }
2524 return ptr_instance;
2525}
2526
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002527static loader_platform_dl_handle loader_add_layer_lib(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002528 const struct loader_instance *inst,
Jon Ashburn4f67d742015-05-27 13:19:22 -06002529 const char *chain_type,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002530 struct loader_layer_properties *layer_prop)
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002531{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002532 struct loader_lib_info *new_layer_lib_list, *my_lib;
Jon Ashburne39a4f82015-08-28 13:38:21 -06002533 size_t new_alloc_size;
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -06002534 /*
2535 * TODO: We can now track this information in the
2536 * scanned_layer_libraries list.
2537 */
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002538 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) {
Jon Ashburn3d002332015-08-20 16:35:30 -06002539 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, layer_prop->lib_name) == 0) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002540 /* Have already loaded this library, just increment ref count */
2541 loader.loaded_layer_lib_list[i].ref_count++;
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002542 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002543 "%s Chain: Increment layer reference count for layer library %s",
Jon Ashburn3d002332015-08-20 16:35:30 -06002544 chain_type, layer_prop->lib_name);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002545 return loader.loaded_layer_lib_list[i].lib_handle;
2546 }
2547 }
2548
2549 /* Haven't seen this library so load it */
Jon Ashburne39a4f82015-08-28 13:38:21 -06002550 new_alloc_size = 0;
2551 if (loader.loaded_layer_lib_capacity == 0)
2552 new_alloc_size = 8 * sizeof(struct loader_lib_info);
2553 else if (loader.loaded_layer_lib_capacity <= loader.loaded_layer_lib_count *
2554 sizeof(struct loader_lib_info))
2555 new_alloc_size = loader.loaded_layer_lib_capacity * 2;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002556
Jon Ashburne39a4f82015-08-28 13:38:21 -06002557 if (new_alloc_size) {
2558 new_layer_lib_list = loader_heap_realloc(
2559 inst, loader.loaded_layer_lib_list,
2560 loader.loaded_layer_lib_capacity,
2561 new_alloc_size,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002562 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburne39a4f82015-08-28 13:38:21 -06002563 if (!new_layer_lib_list) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002564 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "loader: realloc failed in loader_add_layer_lib");
Jon Ashburne39a4f82015-08-28 13:38:21 -06002565 return NULL;
2566 }
2567 loader.loaded_layer_lib_capacity = new_alloc_size;
Courtney Goeltzenleuchter54ce81a2015-12-09 12:26:34 -07002568 loader.loaded_layer_lib_list = new_layer_lib_list;
Jon Ashburne39a4f82015-08-28 13:38:21 -06002569 } else
2570 new_layer_lib_list = loader.loaded_layer_lib_list;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002571 my_lib = &new_layer_lib_list[loader.loaded_layer_lib_count];
2572
Jon Ashburn3d002332015-08-20 16:35:30 -06002573 strncpy(my_lib->lib_name, layer_prop->lib_name, sizeof(my_lib->lib_name));
2574 my_lib->lib_name[sizeof(my_lib->lib_name) - 1] = '\0';
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002575 my_lib->ref_count = 0;
2576 my_lib->lib_handle = NULL;
2577
2578 if ((my_lib->lib_handle = loader_platform_open_library(my_lib->lib_name)) == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002579 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002580 loader_platform_open_library_error(my_lib->lib_name));
2581 return NULL;
2582 } else {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002583 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002584 "Chain: %s: Loading layer library %s",
Jon Ashburn3d002332015-08-20 16:35:30 -06002585 chain_type, layer_prop->lib_name);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002586 }
2587 loader.loaded_layer_lib_count++;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002588 my_lib->ref_count++;
2589
2590 return my_lib->lib_handle;
2591}
2592
2593static void loader_remove_layer_lib(
2594 struct loader_instance *inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002595 struct loader_layer_properties *layer_prop)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002596{
Courtney Goeltzenleuchter80bfd0e2015-12-17 09:51:22 -07002597 uint32_t idx = loader.loaded_layer_lib_count;
Tony Barbourb5d2c942015-07-14 13:34:05 -06002598 struct loader_lib_info *new_layer_lib_list, *my_lib = NULL;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002599
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002600 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) {
Jon Ashburn3d002332015-08-20 16:35:30 -06002601 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, layer_prop->lib_name) == 0) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002602 /* found matching library */
2603 idx = i;
2604 my_lib = &loader.loaded_layer_lib_list[i];
2605 break;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002606 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002607 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002608
Courtney Goeltzenleuchter80bfd0e2015-12-17 09:51:22 -07002609 if (idx == loader.loaded_layer_lib_count) {
Jon Ashburn6766ae92015-12-17 14:30:21 -07002610 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Courtney Goeltzenleuchter80bfd0e2015-12-17 09:51:22 -07002611 "Unable to unref library %s", layer_prop->lib_name);
2612 return;
2613 }
2614
Tony Barbourb5d2c942015-07-14 13:34:05 -06002615 if (my_lib) {
2616 my_lib->ref_count--;
2617 if (my_lib->ref_count > 0) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002618 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
Jon Ashburn3d002332015-08-20 16:35:30 -06002619 "Decrement reference count for layer library %s", layer_prop->lib_name);
Tony Barbourb5d2c942015-07-14 13:34:05 -06002620 return;
2621 }
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07002622 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002623 loader_platform_close_library(my_lib->lib_handle);
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002624 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
Jon Ashburn3d002332015-08-20 16:35:30 -06002625 "Unloading layer library %s", layer_prop->lib_name);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002626
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002627 /* Need to remove unused library from list */
Jon Ashburne39a4f82015-08-28 13:38:21 -06002628 new_layer_lib_list = loader_heap_alloc(inst,
2629 loader.loaded_layer_lib_capacity,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002630 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002631 if (!new_layer_lib_list) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002632 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "loader: heap alloc failed loader_remove_layer_library");
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002633 return;
2634 }
2635
2636 if (idx > 0) {
2637 /* Copy records before idx */
2638 memcpy(new_layer_lib_list, &loader.loaded_layer_lib_list[0],
2639 sizeof(struct loader_lib_info) * idx);
2640 }
2641 if (idx < (loader.loaded_layer_lib_count - 1)) {
2642 /* Copy records after idx */
2643 memcpy(&new_layer_lib_list[idx], &loader.loaded_layer_lib_list[idx+1],
2644 sizeof(struct loader_lib_info) * (loader.loaded_layer_lib_count - idx - 1));
2645 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002646
Jon Ashburne39a4f82015-08-28 13:38:21 -06002647 loader_heap_free(inst, loader.loaded_layer_lib_list);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002648 loader.loaded_layer_lib_count--;
2649 loader.loaded_layer_lib_list = new_layer_lib_list;
Jon Ashburnb8358052014-11-18 09:06:04 -07002650}
2651
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002652
2653/**
2654 * Go through the search_list and find any layers which match type. If layer
2655 * type match is found in then add it to ext_list.
2656 */
Jon Ashburn0c26e712015-07-02 16:10:32 -06002657static void loader_add_layer_implicit(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002658 const struct loader_instance *inst,
Jon Ashburn0c26e712015-07-02 16:10:32 -06002659 const enum layer_type type,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002660 struct loader_layer_list *list,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002661 const struct loader_layer_list *search_list)
Jon Ashburn0c26e712015-07-02 16:10:32 -06002662{
Jon Ashburn075ce432015-12-17 17:38:24 -07002663 bool enable;
2664 char *env_value;
Jon Ashburn0c26e712015-07-02 16:10:32 -06002665 uint32_t i;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002666 for (i = 0; i < search_list->count; i++) {
2667 const struct loader_layer_properties *prop = &search_list->list[i];
Jon Ashburn0c26e712015-07-02 16:10:32 -06002668 if (prop->type & type) {
Jon Ashburn075ce432015-12-17 17:38:24 -07002669 /* Found an implicit layer, see if it should be enabled */
2670 enable = false;
2671
2672 // if no enable_environment variable is specified, this implicit layer
2673 // should always be enabled. Otherwise check if the variable is set
2674 if (prop->enable_env_var.name[0] == 0) {
2675 enable = true;
2676 } else {
2677 env_value = getenv(prop->enable_env_var.name);
2678 if (env_value && !strcmp(prop->enable_env_var.value, env_value))
2679 enable = true;
2680 }
2681
2682 // disable_environment has priority, i.e. if both enable and disable
2683 // environment variables are set, the layer is disabled. Implicit layers
2684 // are required to have a disable_environment variables
2685 env_value = getenv(prop->disable_env_var.name);
2686 if (env_value)
2687 enable = false;
2688
2689 if (enable)
2690 loader_add_to_layer_list(inst, list, 1, prop);
Jon Ashburn0c26e712015-07-02 16:10:32 -06002691 }
2692 }
2693
2694}
2695
2696/**
2697 * Get the layer name(s) from the env_name environment variable. If layer
Jon Ashburnbd332cc2015-07-07 10:27:45 -06002698 * is found in search_list then add it to layer_list. But only add it to
2699 * layer_list if type matches.
Jon Ashburn0c26e712015-07-02 16:10:32 -06002700 */
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002701static void loader_add_layer_env(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002702 const struct loader_instance *inst,
Jon Ashburnbd332cc2015-07-07 10:27:45 -06002703 const enum layer_type type,
Jon Ashburneb6d5682015-07-02 14:10:53 -06002704 const char *env_name,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002705 struct loader_layer_list *layer_list,
2706 const struct loader_layer_list *search_list)
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002707{
Ian Elliott4470a302015-02-17 10:33:47 -07002708 char *layerEnv;
Jon Ashburneb6d5682015-07-02 14:10:53 -06002709 char *next, *name;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002710
Jon Ashburneb6d5682015-07-02 14:10:53 -06002711 layerEnv = getenv(env_name);
Ian Elliott4470a302015-02-17 10:33:47 -07002712 if (layerEnv == NULL) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002713 return;
Ian Elliott4470a302015-02-17 10:33:47 -07002714 }
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -06002715 name = loader_stack_alloc(strlen(layerEnv) + 1);
Jon Ashburneb6d5682015-07-02 14:10:53 -06002716 if (name == NULL) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002717 return;
Ian Elliott4470a302015-02-17 10:33:47 -07002718 }
Jon Ashburneb6d5682015-07-02 14:10:53 -06002719 strcpy(name, layerEnv);
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002720
Jon Ashburneb6d5682015-07-02 14:10:53 -06002721 while (name && *name ) {
2722 next = loader_get_next_path(name);
Jon Ashburne39a4f82015-08-28 13:38:21 -06002723 loader_find_layer_name_add_list(inst, name, type, search_list, layer_list);
Jon Ashburneb6d5682015-07-02 14:10:53 -06002724 name = next;
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07002725 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002726
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002727 return;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002728}
2729
Courtney Goeltzenleuchter7d0023c2015-06-08 15:09:22 -06002730void loader_deactivate_instance_layers(struct loader_instance *instance)
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002731{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002732 /* Create instance chain of enabled layers */
Courtney Goeltzenleuchter7d0023c2015-06-08 15:09:22 -06002733 for (uint32_t i = 0; i < instance->activated_layer_list.count; i++) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002734 struct loader_layer_properties *layer_prop = &instance->activated_layer_list.list[i];
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002735
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002736 loader_remove_layer_lib(instance, layer_prop);
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002737 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06002738 loader_destroy_layer_list(instance, &instance->activated_layer_list);
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002739}
2740
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002741VkResult loader_enable_instance_layers(
Jon Ashburnb82c1852015-08-11 14:49:54 -06002742 struct loader_instance *inst,
2743 const VkInstanceCreateInfo *pCreateInfo,
2744 const struct loader_layer_list *instance_layers)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002745{
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002746 VkResult err;
2747
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06002748 assert(inst && "Cannot have null instance");
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002749
Jon Ashburne39a4f82015-08-28 13:38:21 -06002750 if (!loader_init_layer_list(inst, &inst->activated_layer_list)) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002751 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Failed to alloc Instance activated layer list");
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002752 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002753 }
2754
Jon Ashburn0c26e712015-07-02 16:10:32 -06002755 /* Add any implicit layers first */
2756 loader_add_layer_implicit(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002757 inst,
Jon Ashburn0c26e712015-07-02 16:10:32 -06002758 VK_LAYER_TYPE_INSTANCE_IMPLICIT,
2759 &inst->activated_layer_list,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002760 instance_layers);
Jon Ashburn0c26e712015-07-02 16:10:32 -06002761
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002762 /* Add any layers specified via environment variable next */
Jon Ashburneb6d5682015-07-02 14:10:53 -06002763 loader_add_layer_env(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002764 inst,
Jon Ashburnbd332cc2015-07-07 10:27:45 -06002765 VK_LAYER_TYPE_INSTANCE_EXPLICIT,
Jon Ashburneb6d5682015-07-02 14:10:53 -06002766 "VK_INSTANCE_LAYERS",
2767 &inst->activated_layer_list,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002768 instance_layers);
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002769
2770 /* Add layers specified by the application */
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002771 err = loader_add_layer_names_to_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002772 inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002773 &inst->activated_layer_list,
Chia-I Wud50a7d72015-10-26 20:48:51 +08002774 pCreateInfo->enabledLayerNameCount,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002775 pCreateInfo->ppEnabledLayerNames,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002776 instance_layers);
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002777
2778 return err;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002779}
2780
Jon Ashburn27cd5842015-05-12 17:26:48 -06002781uint32_t loader_activate_instance_layers(struct loader_instance *inst)
2782{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002783 uint32_t layer_idx;
Jon Ashburn128f9422015-05-28 19:16:58 -06002784 VkBaseLayerObject *wrappedInstance;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002785
David Pinedoa0a8a242015-06-24 15:29:18 -06002786 if (inst == NULL) {
Jon Ashburn27cd5842015-05-12 17:26:48 -06002787 return 0;
David Pinedoa0a8a242015-06-24 15:29:18 -06002788 }
Jon Ashburn27cd5842015-05-12 17:26:48 -06002789
2790 // NOTE inst is unwrapped at this point in time
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002791 void* baseObj = (void*) inst;
2792 void* nextObj = (void*) inst;
Jon Ashburn27cd5842015-05-12 17:26:48 -06002793 VkBaseLayerObject *nextInstObj;
2794 PFN_vkGetInstanceProcAddr nextGPA = loader_gpa_instance_internal;
2795
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002796 if (!inst->activated_layer_list.count) {
Courtney Goeltzenleuchtered1a8dd2015-08-07 09:53:18 -06002797 loader_init_instance_core_dispatch_table(inst->disp, nextGPA, (VkInstance) nextObj, (VkInstance) baseObj);
Jon Ashburn27cd5842015-05-12 17:26:48 -06002798 return 0;
2799 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002800
Courtney Goeltzenleuchter6f460c52015-07-06 09:04:55 -06002801 wrappedInstance = loader_stack_alloc(sizeof(VkBaseLayerObject)
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002802 * inst->activated_layer_list.count);
Jon Ashburn128f9422015-05-28 19:16:58 -06002803 if (!wrappedInstance) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002804 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Failed to alloc Instance objects for layer");
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002805 return 0;
2806 }
2807
2808 /* Create instance chain of enabled layers */
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002809 layer_idx = inst->activated_layer_list.count - 1;
Courtney Goeltzenleuchter0f1d8eb2015-06-07 17:28:17 -06002810 for (int32_t i = inst->activated_layer_list.count - 1; i >= 0; i--) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002811 struct loader_layer_properties *layer_prop = &inst->activated_layer_list.list[i];
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002812 loader_platform_dl_handle lib_handle;
2813
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002814 /*
Courtney Goeltzenleuchteree3b16a2015-06-01 14:12:42 -06002815 * Note: An extension's Get*ProcAddr should not return a function pointer for
2816 * any extension entry points until the extension has been enabled.
2817 * To do this requires a different behavior from Get*ProcAddr functions implemented
2818 * in layers.
2819 * The very first call to a layer will be it's Get*ProcAddr function requesting
Tobin Ehlis1cb7f572015-10-06 09:09:24 -06002820 * the layer's vkGet*ProcAddr. The layer should initialize its internal dispatch table
Courtney Goeltzenleuchteree3b16a2015-06-01 14:12:42 -06002821 * with the wrapped object given (either Instance or Device) and return the layer's
2822 * Get*ProcAddr function. The layer should also use this opportunity to record the
2823 * baseObject so that it can find the correct local dispatch table on future calls.
2824 * Subsequent calls to Get*ProcAddr, CreateInstance, CreateDevice
2825 * will not use a wrapped object and must look up their local dispatch table from
2826 * the given baseObject.
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002827 */
Jon Ashburn128f9422015-05-28 19:16:58 -06002828 nextInstObj = (wrappedInstance + layer_idx);
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002829 nextInstObj->pGPA = (PFN_vkGPA) nextGPA;
Jon Ashburn27cd5842015-05-12 17:26:48 -06002830 nextInstObj->baseObject = baseObj;
2831 nextInstObj->nextObject = nextObj;
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002832 nextObj = (void*) nextInstObj;
Jon Ashburn27cd5842015-05-12 17:26:48 -06002833
Jon Ashburne39a4f82015-08-28 13:38:21 -06002834 lib_handle = loader_add_layer_lib(inst, "instance", layer_prop);
Jon Ashburnf72a04b2015-11-25 17:55:49 -07002835 if (!lib_handle)
2836 continue; // TODO what should we do in this case
Jon Ashburn21c21ee2015-09-09 11:29:24 -06002837 if ((nextGPA = layer_prop->functions.get_instance_proc_addr) == NULL) {
2838 if (layer_prop->functions.str_gipa == NULL || strlen(layer_prop->functions.str_gipa) == 0) {
2839 nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetInstanceProcAddr");
2840 layer_prop->functions.get_instance_proc_addr = nextGPA;
2841 } else
2842 nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gipa);
2843 if (!nextGPA) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002844 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Failed to find vkGetInstanceProcAddr in layer %s", layer_prop->lib_name);
Courtney Goeltzenleuchtera9e4af42015-06-01 14:49:17 -06002845
Jon Ashburn21c21ee2015-09-09 11:29:24 -06002846 /* TODO: Should we return nextObj, nextGPA to previous? or decrement layer_list count*/
2847 continue;
2848 }
Jon Ashburn27cd5842015-05-12 17:26:48 -06002849 }
2850
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002851 loader_log(inst, VK_DEBUG_REPORT_INFO_BIT_EXT, 0,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002852 "Insert instance layer %s (%s)",
2853 layer_prop->info.layerName,
Jon Ashburn3d002332015-08-20 16:35:30 -06002854 layer_prop->lib_name);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002855
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002856 layer_idx--;
Jon Ashburn27cd5842015-05-12 17:26:48 -06002857 }
2858
Jon Ashburn8fd08252015-05-28 16:25:02 -06002859 loader_init_instance_core_dispatch_table(inst->disp, nextGPA, (VkInstance) nextObj, (VkInstance) baseObj);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002860
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002861 return inst->activated_layer_list.count;
Jon Ashburn27cd5842015-05-12 17:26:48 -06002862}
2863
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002864void loader_activate_instance_layer_extensions(struct loader_instance *inst)
2865{
2866
2867 loader_init_instance_extension_dispatch_table(inst->disp,
2868 inst->disp->GetInstanceProcAddr,
Jon Ashburn128f9422015-05-28 19:16:58 -06002869 (VkInstance) inst);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002870}
2871
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002872static VkResult loader_enable_device_layers(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002873 const struct loader_instance *inst,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002874 struct loader_icd *icd,
2875 struct loader_device *dev,
2876 const VkDeviceCreateInfo *pCreateInfo,
2877 const struct loader_layer_list *device_layers)
2878
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002879{
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002880 VkResult err;
2881
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06002882 assert(dev && "Cannot have null device");
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002883
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002884 if (dev->activated_layer_list.list == NULL || dev->activated_layer_list.capacity == 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06002885 loader_init_layer_list(inst, &dev->activated_layer_list);
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002886 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002887
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002888 if (dev->activated_layer_list.list == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002889 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Failed to alloc device activated layer list");
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002890 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002891 }
2892
Jon Ashburn0c26e712015-07-02 16:10:32 -06002893 /* Add any implicit layers first */
2894 loader_add_layer_implicit(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002895 inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002896 VK_LAYER_TYPE_DEVICE_IMPLICIT,
2897 &dev->activated_layer_list,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002898 device_layers);
Jon Ashburn0c26e712015-07-02 16:10:32 -06002899
2900 /* Add any layers specified via environment variable next */
Jon Ashburneb6d5682015-07-02 14:10:53 -06002901 loader_add_layer_env(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002902 inst,
Jon Ashburnbd332cc2015-07-07 10:27:45 -06002903 VK_LAYER_TYPE_DEVICE_EXPLICIT,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002904 "VK_DEVICE_LAYERS",
2905 &dev->activated_layer_list,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002906 device_layers);
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002907
2908 /* Add layers specified by the application */
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002909 err = loader_add_layer_names_to_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002910 inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002911 &dev->activated_layer_list,
Chia-I Wud50a7d72015-10-26 20:48:51 +08002912 pCreateInfo->enabledLayerNameCount,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002913 pCreateInfo->ppEnabledLayerNames,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002914 device_layers);
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002915
2916 return err;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002917}
2918
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002919/*
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06002920 * This function terminates the device chain for CreateDevice.
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002921 * CreateDevice is a special case and so the loader call's
2922 * the ICD's CreateDevice before creating the chain. Since
2923 * we can't call CreateDevice twice we must terminate the
2924 * device chain with something else.
2925 */
Chia-I Wu9ab61502015-11-06 06:42:02 +08002926static VKAPI_ATTR VkResult VKAPI_CALL scratch_vkCreateDevice(
Jon Ashburn24cd4be2015-11-01 14:04:06 -07002927 VkPhysicalDevice physicalDevice,
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002928 const VkDeviceCreateInfo *pCreateInfo,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002929 const VkAllocationCallbacks* pAllocator,
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002930 VkDevice *pDevice)
2931{
2932 return VK_SUCCESS;
2933}
2934
Chia-I Wu9ab61502015-11-06 06:42:02 +08002935static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL loader_GetDeviceChainProcAddr(VkDevice device, const char * name)
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002936{
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002937 if (!strcmp(name, "vkGetDeviceProcAddr"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06002938 return (PFN_vkVoidFunction) loader_GetDeviceChainProcAddr;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002939 if (!strcmp(name, "vkCreateDevice"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06002940 return (PFN_vkVoidFunction) scratch_vkCreateDevice;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002941
Courtney Goeltzenleuchter3e029d12015-06-29 16:09:23 -06002942 struct loader_device *found_dev;
2943 struct loader_icd *icd = loader_get_icd_and_device(device, &found_dev);
2944 return icd->GetDeviceProcAddr(device, name);
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002945}
2946
Jon Ashburndc6fcad2015-06-10 10:06:06 -06002947static uint32_t loader_activate_device_layers(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002948 const struct loader_instance *inst,
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002949 struct loader_device *dev,
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -06002950 VkDevice device)
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002951{
David Pinedoa0a8a242015-06-24 15:29:18 -06002952 if (!dev) {
Jon Ashburndc6fcad2015-06-10 10:06:06 -06002953 return 0;
David Pinedoa0a8a242015-06-24 15:29:18 -06002954 }
Jon Ashburn94e70492015-06-10 10:13:10 -06002955
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002956 /* activate any layer libraries */
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002957 void* nextObj = (void*) device;
2958 void* baseObj = nextObj;
Jon Ashburn94e70492015-06-10 10:13:10 -06002959 VkBaseLayerObject *nextGpuObj;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002960 PFN_vkGetDeviceProcAddr nextGPA = loader_GetDeviceChainProcAddr;
Jon Ashburn94e70492015-06-10 10:13:10 -06002961 VkBaseLayerObject *wrappedGpus;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002962
Courtney Goeltzenleuchtered1a8dd2015-08-07 09:53:18 -06002963 if (!dev->activated_layer_list.count) {
2964 loader_init_device_dispatch_table(&dev->loader_dispatch, nextGPA,
2965 (VkDevice) nextObj, (VkDevice) baseObj);
Jon Ashburn94e70492015-06-10 10:13:10 -06002966 return 0;
Courtney Goeltzenleuchtered1a8dd2015-08-07 09:53:18 -06002967 }
Jon Ashburn94e70492015-06-10 10:13:10 -06002968
Jon Ashburne39a4f82015-08-28 13:38:21 -06002969 wrappedGpus = loader_heap_alloc(inst,
2970 sizeof (VkBaseLayerObject) * dev->activated_layer_list.count,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002971 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn94e70492015-06-10 10:13:10 -06002972 if (!wrappedGpus) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002973 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Failed to alloc Gpu objects for layer");
Jon Ashburn94e70492015-06-10 10:13:10 -06002974 return 0;
2975 }
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002976
Jon Ashburn94e70492015-06-10 10:13:10 -06002977 for (int32_t i = dev->activated_layer_list.count - 1; i >= 0; i--) {
2978
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002979 struct loader_layer_properties *layer_prop = &dev->activated_layer_list.list[i];
Jon Ashburn94e70492015-06-10 10:13:10 -06002980 loader_platform_dl_handle lib_handle;
2981
Jon Ashburn94e70492015-06-10 10:13:10 -06002982 nextGpuObj = (wrappedGpus + i);
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002983 nextGpuObj->pGPA = (PFN_vkGPA)nextGPA;
Jon Ashburn94e70492015-06-10 10:13:10 -06002984 nextGpuObj->baseObject = baseObj;
2985 nextGpuObj->nextObject = nextObj;
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002986 nextObj = (void*) nextGpuObj;
Jon Ashburn94e70492015-06-10 10:13:10 -06002987
Jon Ashburne39a4f82015-08-28 13:38:21 -06002988 lib_handle = loader_add_layer_lib(inst, "device", layer_prop);
Jon Ashburn21c21ee2015-09-09 11:29:24 -06002989 if ((nextGPA = layer_prop->functions.get_device_proc_addr) == NULL) {
2990 if (layer_prop->functions.str_gdpa == NULL || strlen(layer_prop->functions.str_gdpa) == 0) {
2991 nextGPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetDeviceProcAddr");
2992 layer_prop->functions.get_device_proc_addr = nextGPA;
2993 } else
2994 nextGPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gdpa);
2995 if (!nextGPA) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002996 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Failed to find vkGetDeviceProcAddr in layer %s", layer_prop->lib_name);
Jon Ashburn21c21ee2015-09-09 11:29:24 -06002997 continue;
2998 }
Jon Ashburn94e70492015-06-10 10:13:10 -06002999 }
3000
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07003001 loader_log(inst, VK_DEBUG_REPORT_INFO_BIT_EXT, 0,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003002 "Insert device layer library %s (%s)",
3003 layer_prop->info.layerName,
Jon Ashburn3d002332015-08-20 16:35:30 -06003004 layer_prop->lib_name);
Jon Ashburn94e70492015-06-10 10:13:10 -06003005
3006 }
3007
3008 loader_init_device_dispatch_table(&dev->loader_dispatch, nextGPA,
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06003009 (VkDevice) nextObj, (VkDevice) baseObj);
Jon Ashburne39a4f82015-08-28 13:38:21 -06003010 loader_heap_free(inst, wrappedGpus);
Jon Ashburn94e70492015-06-10 10:13:10 -06003011
Jon Ashburndc6fcad2015-06-10 10:06:06 -06003012 return dev->activated_layer_list.count;
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06003013}
Jon Ashburnd38bfb12014-10-14 19:15:22 -06003014
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003015VkResult loader_validate_layers(
3016 const uint32_t layer_count,
3017 const char * const *ppEnabledLayerNames,
Jon Ashburn3d002332015-08-20 16:35:30 -06003018 const struct loader_layer_list *list)
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06003019{
3020 struct loader_layer_properties *prop;
3021
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003022 for (uint32_t i = 0; i < layer_count; i++) {
Jon Ashburne13ecc92015-08-03 17:19:30 -06003023 prop = loader_get_layer_property(ppEnabledLayerNames[i],
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003024 list);
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06003025 if (!prop) {
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06003026 return VK_ERROR_LAYER_NOT_PRESENT;
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06003027 }
3028 }
3029
3030 return VK_SUCCESS;
3031}
3032
3033VkResult loader_validate_instance_extensions(
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003034 const struct loader_extension_list *icd_exts,
Jon Ashburnb82c1852015-08-11 14:49:54 -06003035 const struct loader_layer_list *instance_layer,
3036 const VkInstanceCreateInfo *pCreateInfo)
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06003037{
Jon Ashburn5c042ea2015-08-04 11:14:18 -06003038 VkExtensionProperties *extension_prop;
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003039 struct loader_layer_properties *layer_prop;
3040
Chia-I Wud50a7d72015-10-26 20:48:51 +08003041 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) {
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003042 extension_prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003043 icd_exts);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003044
3045 if (extension_prop) {
3046 continue;
3047 }
3048
3049 extension_prop = NULL;
3050
3051 /* Not in global list, search layer extension lists */
Chia-I Wud50a7d72015-10-26 20:48:51 +08003052 for (uint32_t j = 0; j < pCreateInfo->enabledLayerNameCount; j++) {
Jon Ashburne13ecc92015-08-03 17:19:30 -06003053 layer_prop = loader_get_layer_property(pCreateInfo->ppEnabledLayerNames[i],
Jon Ashburnb82c1852015-08-11 14:49:54 -06003054 instance_layer);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003055 if (!layer_prop) {
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003056 /* Should NOT get here, loader_validate_layers
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003057 * should have already filtered this case out.
3058 */
3059 continue;
3060 }
3061
3062 extension_prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
3063 &layer_prop->instance_extension_list);
3064 if (extension_prop) {
3065 /* Found the extension in one of the layers enabled by the app. */
3066 break;
3067 }
3068 }
3069
3070 if (!extension_prop) {
3071 /* Didn't find extension name in any of the global layers, error out */
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06003072 return VK_ERROR_EXTENSION_NOT_PRESENT;
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003073 }
3074 }
3075 return VK_SUCCESS;
3076}
3077
3078VkResult loader_validate_device_extensions(
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003079 struct loader_physical_device *phys_dev,
Jon Ashburnb82c1852015-08-11 14:49:54 -06003080 const struct loader_layer_list *device_layer,
3081 const VkDeviceCreateInfo *pCreateInfo)
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003082{
Jon Ashburn5c042ea2015-08-04 11:14:18 -06003083 VkExtensionProperties *extension_prop;
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003084 struct loader_layer_properties *layer_prop;
3085
Chia-I Wud50a7d72015-10-26 20:48:51 +08003086 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) {
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003087 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i];
3088 extension_prop = get_extension_property(extension_name,
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003089 &phys_dev->device_extension_cache);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003090
3091 if (extension_prop) {
3092 continue;
3093 }
3094
3095 /* Not in global list, search layer extension lists */
Chia-I Wud50a7d72015-10-26 20:48:51 +08003096 for (uint32_t j = 0; j < pCreateInfo->enabledLayerNameCount; j++) {
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003097 const char *layer_name = pCreateInfo->ppEnabledLayerNames[j];
Jon Ashburne13ecc92015-08-03 17:19:30 -06003098 layer_prop = loader_get_layer_property(layer_name,
Jon Ashburnb82c1852015-08-11 14:49:54 -06003099 device_layer);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003100
3101 if (!layer_prop) {
3102 /* Should NOT get here, loader_validate_instance_layers
3103 * should have already filtered this case out.
3104 */
3105 continue;
3106 }
3107
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07003108 extension_prop = get_dev_extension_property(extension_name,
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003109 &layer_prop->device_extension_list);
3110 if (extension_prop) {
3111 /* Found the extension in one of the layers enabled by the app. */
3112 break;
3113 }
3114 }
3115
3116 if (!extension_prop) {
3117 /* Didn't find extension name in any of the device layers, error out */
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06003118 return VK_ERROR_EXTENSION_NOT_PRESENT;
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003119 }
3120 }
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06003121 return VK_SUCCESS;
3122}
3123
Chia-I Wu9ab61502015-11-06 06:42:02 +08003124VKAPI_ATTR VkResult VKAPI_CALL loader_CreateInstance(
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003125 const VkInstanceCreateInfo* pCreateInfo,
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07003126 const VkAllocationCallbacks* pAllocator,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003127 VkInstance* pInstance)
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003128{
Jon Ashburneed0c002015-05-21 17:42:17 -06003129 struct loader_instance *ptr_instance = *(struct loader_instance **) pInstance;
Jon Ashburn46888392015-01-29 15:45:51 -07003130 struct loader_icd *icd;
Jon Ashburn5c042ea2015-08-04 11:14:18 -06003131 VkExtensionProperties *prop;
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003132 char **filtered_extension_names = NULL;
3133 VkInstanceCreateInfo icd_create_info;
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06003134 VkResult res = VK_SUCCESS;
Jon Ashburn7e18de02015-11-19 09:29:51 -07003135 bool success = false;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003136
Tony Barbour3c78ff42015-12-04 13:24:39 -07003137 memcpy(&icd_create_info, pCreateInfo, sizeof(icd_create_info));
3138
Chia-I Wud50a7d72015-10-26 20:48:51 +08003139 icd_create_info.enabledLayerNameCount = 0;
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003140 icd_create_info.ppEnabledLayerNames = NULL;
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003141
3142 /*
3143 * NOTE: Need to filter the extensions to only those
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003144 * supported by the ICD.
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003145 * No ICD will advertise support for layers. An ICD
3146 * library could support a layer, but it would be
3147 * independent of the actual ICD, just in the same library.
3148 */
Chia-I Wud50a7d72015-10-26 20:48:51 +08003149 filtered_extension_names = loader_stack_alloc(pCreateInfo->enabledExtensionNameCount * sizeof(char *));
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003150 if (!filtered_extension_names) {
3151 return VK_ERROR_OUT_OF_HOST_MEMORY;
3152 }
3153 icd_create_info.ppEnabledExtensionNames = (const char * const *) filtered_extension_names;
3154
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003155 for (uint32_t i = 0; i < ptr_instance->icd_libs.count; i++) {
3156 icd = loader_icd_add(ptr_instance, &ptr_instance->icd_libs.list[i]);
Jon Ashburn46888392015-01-29 15:45:51 -07003157 if (icd) {
Chia-I Wud50a7d72015-10-26 20:48:51 +08003158 icd_create_info.enabledExtensionNameCount = 0;
Courtney Goeltzenleuchter36eeb742015-12-21 16:41:47 -07003159 struct loader_extension_list icd_exts;
3160
3161 loader_log(ptr_instance, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Build ICD instance extension list");
3162 // traverse scanned icd list adding non-duplicate extensions to the list
3163 loader_init_generic_list(ptr_instance, (struct loader_generic_list *) &icd_exts,
3164 sizeof(VkExtensionProperties));
3165 loader_add_instance_extensions(ptr_instance,
3166 icd->this_icd_lib->EnumerateInstanceExtensionProperties,
3167 icd->this_icd_lib->lib_name,
3168 &icd_exts);
3169
Chia-I Wud50a7d72015-10-26 20:48:51 +08003170 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) {
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003171 prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
Courtney Goeltzenleuchter36eeb742015-12-21 16:41:47 -07003172 &icd_exts);
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003173 if (prop) {
Chia-I Wud50a7d72015-10-26 20:48:51 +08003174 filtered_extension_names[icd_create_info.enabledExtensionNameCount] = (char *) pCreateInfo->ppEnabledExtensionNames[i];
3175 icd_create_info.enabledExtensionNameCount++;
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003176 }
3177 }
3178
Courtney Goeltzenleuchter36eeb742015-12-21 16:41:47 -07003179 loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *) &icd_exts);
3180
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003181 res = ptr_instance->icd_libs.list[i].CreateInstance(&icd_create_info,
Chia-I Wuf7458c52015-10-26 21:10:41 +08003182 pAllocator,
Jon Ashburn3da71f22015-05-14 12:43:38 -06003183 &(icd->instance));
Jon Ashburn7e18de02015-11-19 09:29:51 -07003184 if (res == VK_SUCCESS)
3185 success = loader_icd_init_entrys(
Jon Ashburnc624c882015-07-16 10:17:29 -06003186 icd,
3187 icd->instance,
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003188 ptr_instance->icd_libs.list[i].GetInstanceProcAddr);
Jon Ashburnc624c882015-07-16 10:17:29 -06003189
3190 if (res != VK_SUCCESS || !success)
Jon Ashburn46888392015-01-29 15:45:51 -07003191 {
3192 ptr_instance->icds = ptr_instance->icds->next;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003193 loader_icd_destroy(ptr_instance, icd);
Jon Ashburn3da71f22015-05-14 12:43:38 -06003194 icd->instance = VK_NULL_HANDLE;
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07003195 loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburnc624c882015-07-16 10:17:29 -06003196 "ICD ignored: failed to CreateInstance and find entrypoints with ICD");
Jon Ashburn46888392015-01-29 15:45:51 -07003197 }
3198 }
Jon Ashburn46888392015-01-29 15:45:51 -07003199 }
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003200
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06003201 /*
3202 * If no ICDs were added to instance list and res is unchanged
3203 * from it's initial value, the loader was unable to find
3204 * a suitable ICD.
3205 */
Ian Elliotteb450762015-02-05 15:19:15 -07003206 if (ptr_instance->icds == NULL) {
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06003207 if (res == VK_SUCCESS) {
3208 return VK_ERROR_INCOMPATIBLE_DRIVER;
3209 } else {
3210 return res;
3211 }
Ian Elliotteb450762015-02-05 15:19:15 -07003212 }
Jon Ashburn46888392015-01-29 15:45:51 -07003213
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06003214 return VK_SUCCESS;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003215}
3216
Chia-I Wu9ab61502015-11-06 06:42:02 +08003217VKAPI_ATTR void VKAPI_CALL loader_DestroyInstance(
Chia-I Wuf7458c52015-10-26 21:10:41 +08003218 VkInstance instance,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003219 const VkAllocationCallbacks* pAllocator)
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003220{
Courtney Goeltzenleuchterdeceded2015-06-08 15:04:02 -06003221 struct loader_instance *ptr_instance = loader_instance(instance);
Jon Ashburn3da71f22015-05-14 12:43:38 -06003222 struct loader_icd *icds = ptr_instance->icds;
Jon Ashburna6fd2612015-06-16 14:43:19 -06003223 struct loader_icd *next_icd;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003224
3225 // Remove this instance from the list of instances:
3226 struct loader_instance *prev = NULL;
3227 struct loader_instance *next = loader.instances;
3228 while (next != NULL) {
3229 if (next == ptr_instance) {
3230 // Remove this instance from the list:
3231 if (prev)
3232 prev->next = next->next;
Jon Ashburnc5c49602015-02-03 09:26:59 -07003233 else
3234 loader.instances = next->next;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003235 break;
3236 }
3237 prev = next;
3238 next = next->next;
3239 }
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003240
Jon Ashburn3da71f22015-05-14 12:43:38 -06003241 while (icds) {
3242 if (icds->instance) {
Chia-I Wuf7458c52015-10-26 21:10:41 +08003243 icds->DestroyInstance(icds->instance, pAllocator);
Tony Barbourf20f87b2015-04-22 09:02:32 -06003244 }
Jon Ashburna6fd2612015-06-16 14:43:19 -06003245 next_icd = icds->next;
Jon Ashburn3da71f22015-05-14 12:43:38 -06003246 icds->instance = VK_NULL_HANDLE;
Jon Ashburna6fd2612015-06-16 14:43:19 -06003247 loader_icd_destroy(ptr_instance, icds);
3248
3249 icds = next_icd;
Jon Ashburn46888392015-01-29 15:45:51 -07003250 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06003251 loader_delete_layer_properties(ptr_instance, &ptr_instance->device_layer_list);
3252 loader_delete_layer_properties(ptr_instance, &ptr_instance->instance_layer_list);
3253 loader_scanned_icd_clear(ptr_instance, &ptr_instance->icd_libs);
Jon Ashburn6e6a2162015-12-10 08:51:10 -07003254 loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *)
3255 &ptr_instance->ext_list);
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003256 for (uint32_t i = 0; i < ptr_instance->total_gpu_count; i++)
Jon Ashburn6e6a2162015-12-10 08:51:10 -07003257 loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *)
3258 &ptr_instance->phys_devs[i].device_extension_cache);
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003259 loader_heap_free(ptr_instance, ptr_instance->phys_devs);
Jon Ashburnfc1031e2015-11-17 15:31:02 -07003260 loader_free_dev_ext_table(ptr_instance);
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003261}
3262
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003263VkResult loader_init_physical_device_info(struct loader_instance *ptr_instance)
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003264{
3265 struct loader_icd *icd;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003266 uint32_t i, j, idx, count = 0;
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06003267 VkResult res;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003268 struct loader_phys_dev_per_icd *phys_devs;
3269
3270 ptr_instance->total_gpu_count = 0;
3271 phys_devs = (struct loader_phys_dev_per_icd *) loader_stack_alloc(
3272 sizeof(struct loader_phys_dev_per_icd) *
3273 ptr_instance->total_icd_count);
3274 if (!phys_devs)
3275 return VK_ERROR_OUT_OF_HOST_MEMORY;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003276
3277 icd = ptr_instance->icds;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003278 for (i = 0; i < ptr_instance->total_icd_count; i++) {
3279 assert(icd);
3280 res = icd->EnumeratePhysicalDevices(icd->instance, &phys_devs[i].count, NULL);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003281 if (res != VK_SUCCESS)
3282 return res;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003283 count += phys_devs[i].count;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003284 icd = icd->next;
3285 }
3286
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003287 ptr_instance->phys_devs = (struct loader_physical_device *) loader_heap_alloc(
3288 ptr_instance,
3289 count * sizeof(struct loader_physical_device),
3290 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
3291 if (!ptr_instance->phys_devs)
3292 return VK_ERROR_OUT_OF_HOST_MEMORY;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003293
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003294 icd = ptr_instance->icds;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003295
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003296 struct loader_physical_device *inst_phys_devs = ptr_instance->phys_devs;
3297 idx = 0;
3298 for (i = 0; i < ptr_instance->total_icd_count; i++) {
3299 assert(icd);
3300
3301 phys_devs[i].phys_devs = (VkPhysicalDevice *) loader_stack_alloc(
3302 phys_devs[i].count * sizeof(VkPhysicalDevice));
3303 if (!phys_devs[i].phys_devs) {
Jon Ashburn093ce202015-11-02 17:59:02 -07003304 loader_heap_free(ptr_instance, ptr_instance->phys_devs);
3305 ptr_instance->phys_devs = NULL;
Jon Ashburn128f9422015-05-28 19:16:58 -06003306 return VK_ERROR_OUT_OF_HOST_MEMORY;
3307 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003308 res = icd->EnumeratePhysicalDevices(
3309 icd->instance,
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003310 &(phys_devs[i].count),
3311 phys_devs[i].phys_devs);
3312 if ((res == VK_SUCCESS)) {
3313 ptr_instance->total_gpu_count += phys_devs[i].count;
3314 for (j = 0; j < phys_devs[i].count; j++) {
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003315
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003316 // initialize the loader's physicalDevice object
3317 loader_set_dispatch((void *) &inst_phys_devs[idx], ptr_instance->disp);
3318 inst_phys_devs[idx].this_instance = ptr_instance;
3319 inst_phys_devs[idx].this_icd = icd;
3320 inst_phys_devs[idx].phys_dev = phys_devs[i].phys_devs[j];
Jon Ashburn00eb6c02015-11-02 17:40:01 -07003321 memset(&inst_phys_devs[idx].device_extension_cache, 0, sizeof(struct loader_extension_list));
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003322
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003323 idx++;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003324 }
Jon Ashburn093ce202015-11-02 17:59:02 -07003325 } else {
3326 loader_heap_free(ptr_instance, ptr_instance->phys_devs);
3327 ptr_instance->phys_devs = NULL;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003328 return res;
Jon Ashburn093ce202015-11-02 17:59:02 -07003329 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003330
3331 icd = icd->next;
3332 }
3333
3334 return VK_SUCCESS;
3335}
3336
Chia-I Wu9ab61502015-11-06 06:42:02 +08003337VKAPI_ATTR VkResult VKAPI_CALL loader_EnumeratePhysicalDevices(
Courtney Goeltzenleuchter5e41f1d2015-04-20 12:48:54 -06003338 VkInstance instance,
3339 uint32_t* pPhysicalDeviceCount,
3340 VkPhysicalDevice* pPhysicalDevices)
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003341{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003342 uint32_t i;
Jon Ashburn4c392fb2015-01-28 19:57:09 -07003343 struct loader_instance *ptr_instance = (struct loader_instance *) instance;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003344 VkResult res = VK_SUCCESS;
Jon Ashburn4c392fb2015-01-28 19:57:09 -07003345
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003346 if (ptr_instance->total_gpu_count == 0) {
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003347 res = loader_init_physical_device_info(ptr_instance);
Jon Ashburn4c392fb2015-01-28 19:57:09 -07003348 }
3349
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003350 *pPhysicalDeviceCount = ptr_instance->total_gpu_count;
3351 if (!pPhysicalDevices) {
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003352 return res;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003353 }
Jon Ashburn4c392fb2015-01-28 19:57:09 -07003354
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003355 for (i = 0; i < ptr_instance->total_gpu_count; i++) {
3356 pPhysicalDevices[i] = (VkPhysicalDevice) &ptr_instance->phys_devs[i];
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003357 }
3358
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003359 return res;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003360}
3361
Chia-I Wu9ab61502015-11-06 06:42:02 +08003362VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceProperties(
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003363 VkPhysicalDevice physicalDevice,
Tony Barbour59a47322015-06-24 16:06:58 -06003364 VkPhysicalDeviceProperties* pProperties)
Jon Ashburn3da71f22015-05-14 12:43:38 -06003365{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003366 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3367 struct loader_icd *icd = phys_dev->this_icd;
Jon Ashburn3da71f22015-05-14 12:43:38 -06003368
Tony Barbour59a47322015-06-24 16:06:58 -06003369 if (icd->GetPhysicalDeviceProperties)
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003370 icd->GetPhysicalDeviceProperties(phys_dev->phys_dev, pProperties);
Tony Barbour59a47322015-06-24 16:06:58 -06003371}
3372
Chia-I Wu9ab61502015-11-06 06:42:02 +08003373VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceQueueFamilyProperties (
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003374 VkPhysicalDevice physicalDevice,
Chia-I Wud50a7d72015-10-26 20:48:51 +08003375 uint32_t* pQueueFamilyPropertyCount,
Cody Northropd0802882015-08-03 17:04:53 -06003376 VkQueueFamilyProperties* pProperties)
Tony Barbour59a47322015-06-24 16:06:58 -06003377{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003378 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3379 struct loader_icd *icd = phys_dev->this_icd;
Tony Barbour59a47322015-06-24 16:06:58 -06003380
Cody Northropd0802882015-08-03 17:04:53 -06003381 if (icd->GetPhysicalDeviceQueueFamilyProperties)
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003382 icd->GetPhysicalDeviceQueueFamilyProperties(phys_dev->phys_dev, pQueueFamilyPropertyCount, pProperties);
Tony Barbour59a47322015-06-24 16:06:58 -06003383}
3384
Chia-I Wu9ab61502015-11-06 06:42:02 +08003385VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceMemoryProperties (
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003386 VkPhysicalDevice physicalDevice,
Tony Barbour59a47322015-06-24 16:06:58 -06003387 VkPhysicalDeviceMemoryProperties* pProperties)
3388{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003389 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3390 struct loader_icd *icd = phys_dev->this_icd;
Tony Barbour59a47322015-06-24 16:06:58 -06003391
3392 if (icd->GetPhysicalDeviceMemoryProperties)
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003393 icd->GetPhysicalDeviceMemoryProperties(phys_dev->phys_dev, pProperties);
Jon Ashburn3da71f22015-05-14 12:43:38 -06003394}
3395
Chia-I Wu9ab61502015-11-06 06:42:02 +08003396VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceFeatures(
Chris Forbesbc0bb772015-06-21 22:55:02 +12003397 VkPhysicalDevice physicalDevice,
3398 VkPhysicalDeviceFeatures* pFeatures)
3399{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003400 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3401 struct loader_icd *icd = phys_dev->this_icd;
Chris Forbesbc0bb772015-06-21 22:55:02 +12003402
3403 if (icd->GetPhysicalDeviceFeatures)
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003404 icd->GetPhysicalDeviceFeatures(phys_dev->phys_dev, pFeatures);
Chris Forbesbc0bb772015-06-21 22:55:02 +12003405}
3406
Chia-I Wu9ab61502015-11-06 06:42:02 +08003407VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceFormatProperties(
Chris Forbesbc0bb772015-06-21 22:55:02 +12003408 VkPhysicalDevice physicalDevice,
3409 VkFormat format,
3410 VkFormatProperties* pFormatInfo)
3411{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003412 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3413 struct loader_icd *icd = phys_dev->this_icd;
Chris Forbesbc0bb772015-06-21 22:55:02 +12003414
Courtney Goeltzenleuchter2caec862015-07-12 12:52:09 -06003415 if (icd->GetPhysicalDeviceFormatProperties)
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003416 icd->GetPhysicalDeviceFormatProperties(phys_dev->phys_dev, format, pFormatInfo);
Chris Forbesbc0bb772015-06-21 22:55:02 +12003417}
3418
Chia-I Wu9ab61502015-11-06 06:42:02 +08003419VKAPI_ATTR VkResult VKAPI_CALL loader_GetPhysicalDeviceImageFormatProperties(
Jon Ashburn754864f2015-07-23 18:49:07 -06003420 VkPhysicalDevice physicalDevice,
3421 VkFormat format,
3422 VkImageType type,
3423 VkImageTiling tiling,
3424 VkImageUsageFlags usage,
Courtney Goeltzenleuchtera22097a2015-09-10 13:44:12 -06003425 VkImageCreateFlags flags,
Jon Ashburn754864f2015-07-23 18:49:07 -06003426 VkImageFormatProperties* pImageFormatProperties)
3427{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003428 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3429 struct loader_icd *icd = phys_dev->this_icd;
Jon Ashburn754864f2015-07-23 18:49:07 -06003430
Chia-I Wu17241042015-10-31 00:31:16 +08003431 if (!icd->GetPhysicalDeviceImageFormatProperties)
3432 return VK_ERROR_INITIALIZATION_FAILED;
3433
3434 return icd->GetPhysicalDeviceImageFormatProperties(phys_dev->phys_dev, format,
3435 type, tiling, usage, flags, pImageFormatProperties);
Jon Ashburn754864f2015-07-23 18:49:07 -06003436}
3437
Chia-I Wu9ab61502015-11-06 06:42:02 +08003438VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceSparseImageFormatProperties(
Mark Lobodzinski16e8bef2015-07-03 15:58:09 -06003439 VkPhysicalDevice physicalDevice,
3440 VkFormat format,
3441 VkImageType type,
Chia-I Wu5c17c962015-10-31 00:31:16 +08003442 VkSampleCountFlagBits samples,
Mark Lobodzinski16e8bef2015-07-03 15:58:09 -06003443 VkImageUsageFlags usage,
3444 VkImageTiling tiling,
3445 uint32_t* pNumProperties,
3446 VkSparseImageFormatProperties* pProperties)
3447{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003448 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3449 struct loader_icd *icd = phys_dev->this_icd;
Mark Lobodzinski16e8bef2015-07-03 15:58:09 -06003450
3451 if (icd->GetPhysicalDeviceSparseImageFormatProperties)
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003452 icd->GetPhysicalDeviceSparseImageFormatProperties(phys_dev->phys_dev, format, type, samples, usage, tiling, pNumProperties, pProperties);
Mark Lobodzinski16e8bef2015-07-03 15:58:09 -06003453}
3454
Chia-I Wu9ab61502015-11-06 06:42:02 +08003455VKAPI_ATTR VkResult VKAPI_CALL loader_CreateDevice(
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003456 VkPhysicalDevice physicalDevice,
Jon Ashburn95a77ba2015-05-15 15:09:35 -06003457 const VkDeviceCreateInfo* pCreateInfo,
Jon Ashburn46674bf2015-12-11 09:41:34 -07003458 const VkAllocationCallbacks* pAllocator,
Jon Ashburn95a77ba2015-05-15 15:09:35 -06003459 VkDevice* pDevice)
3460{
Jon Ashburn46674bf2015-12-11 09:41:34 -07003461 struct loader_physical_device *phys_dev;
3462 struct loader_icd *icd;
Jon Ashburndc6fcad2015-06-10 10:06:06 -06003463 struct loader_device *dev;
Jon Ashburnfc1031e2015-11-17 15:31:02 -07003464 struct loader_instance *inst;
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003465 VkDeviceCreateInfo device_create_info;
3466 char **filtered_extension_names = NULL;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003467 VkResult res;
Jon Ashburn95a77ba2015-05-15 15:09:35 -06003468
Chia-I Wu02124482015-11-06 06:42:02 +08003469 assert(pCreateInfo->queueCreateInfoCount >= 1);
Mark Lobodzinski0c29b922015-09-17 15:17:34 -06003470
Jon Ashburn46674bf2015-12-11 09:41:34 -07003471 //TODO this only works for one physical device per instance
3472 // once CreateDevice layer bootstrapping is done via DeviceCreateInfo
3473 // hopefully don't need this anymore in trampoline code
3474 phys_dev = loader_get_physical_device(physicalDevice);
3475 icd = phys_dev->this_icd;
Jon Ashburna4cf12b2015-10-26 16:54:51 -06003476 if (!icd)
3477 return VK_ERROR_INITIALIZATION_FAILED;
3478
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003479 inst = phys_dev->this_instance;
Jon Ashburna4cf12b2015-10-26 16:54:51 -06003480
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003481 if (!icd->CreateDevice) {
3482 return VK_ERROR_INITIALIZATION_FAILED;
Jon Ashburn95a77ba2015-05-15 15:09:35 -06003483 }
3484
Jon Ashburnb82c1852015-08-11 14:49:54 -06003485 /* validate any app enabled layers are available */
Chia-I Wud50a7d72015-10-26 20:48:51 +08003486 if (pCreateInfo->enabledLayerNameCount > 0) {
3487 res = loader_validate_layers(pCreateInfo->enabledLayerNameCount,
Jon Ashburnb82c1852015-08-11 14:49:54 -06003488 pCreateInfo->ppEnabledLayerNames,
Jon Ashburne39a4f82015-08-28 13:38:21 -06003489 &inst->device_layer_list);
Jon Ashburnb82c1852015-08-11 14:49:54 -06003490 if (res != VK_SUCCESS) {
3491 return res;
3492 }
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003493 }
3494
Jon Ashburn00eb6c02015-11-02 17:40:01 -07003495 /* Get the physical device extensions if they haven't been retrieved yet */
3496 if (phys_dev->device_extension_cache.capacity == 0) {
Jon Ashburn6e6a2162015-12-10 08:51:10 -07003497 if (!loader_init_generic_list(inst, (struct loader_generic_list *)
3498 &phys_dev->device_extension_cache,
3499 sizeof(VkExtensionProperties))) {
Jon Ashburn00eb6c02015-11-02 17:40:01 -07003500 return VK_ERROR_OUT_OF_HOST_MEMORY;
3501 }
Courtney Goeltzenleuchterf538ef72015-12-02 14:00:19 -07003502 res = loader_add_device_extensions(
Jon Ashburn00eb6c02015-11-02 17:40:01 -07003503 inst, physicalDevice,
3504 phys_dev->this_icd->this_icd_lib->lib_name,
3505 &phys_dev->device_extension_cache);
3506 if (res != VK_SUCCESS) {
3507 return res;
3508 }
3509 }
3510 /* make sure requested extensions to be enabled are supported */
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003511 res = loader_validate_device_extensions(phys_dev, &inst->device_layer_list, pCreateInfo);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003512 if (res != VK_SUCCESS) {
3513 return res;
3514 }
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003515
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003516 /*
3517 * NOTE: Need to filter the extensions to only those
3518 * supported by the ICD.
3519 * No ICD will advertise support for layers. An ICD
3520 * library could support a layer, but it would be
3521 * independent of the actual ICD, just in the same library.
3522 */
Chia-I Wud50a7d72015-10-26 20:48:51 +08003523 filtered_extension_names = loader_stack_alloc(pCreateInfo->enabledExtensionNameCount * sizeof(char *));
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003524 if (!filtered_extension_names) {
3525 return VK_ERROR_OUT_OF_HOST_MEMORY;
3526 }
3527
3528 /* Copy user's data */
3529 memcpy(&device_create_info, pCreateInfo, sizeof(VkDeviceCreateInfo));
3530
3531 /* ICD's do not use layers */
Chia-I Wud50a7d72015-10-26 20:48:51 +08003532 device_create_info.enabledLayerNameCount = 0;
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003533 device_create_info.ppEnabledLayerNames = NULL;
3534
Chia-I Wud50a7d72015-10-26 20:48:51 +08003535 device_create_info.enabledExtensionNameCount = 0;
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003536 device_create_info.ppEnabledExtensionNames = (const char * const *) filtered_extension_names;
3537
Chia-I Wud50a7d72015-10-26 20:48:51 +08003538 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) {
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003539 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i];
Jon Ashburn5c042ea2015-08-04 11:14:18 -06003540 VkExtensionProperties *prop = get_extension_property(extension_name,
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003541 &phys_dev->device_extension_cache);
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003542 if (prop) {
Chia-I Wud50a7d72015-10-26 20:48:51 +08003543 filtered_extension_names[device_create_info.enabledExtensionNameCount] = (char *) extension_name;
3544 device_create_info.enabledExtensionNameCount++;
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003545 }
3546 }
3547
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003548 // since physicalDevice object maybe wrapped by a layer need to get unwrapped version
Jon Ashburne0e64572015-09-30 12:56:42 -06003549 // we haven't yet called down the chain for the layer to unwrap the object
Jon Ashburn0704af92015-12-24 10:50:08 -07003550 res = icd->CreateDevice(phys_dev->phys_dev, &device_create_info, pAllocator, pDevice);
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003551 if (res != VK_SUCCESS) {
3552 return res;
3553 }
3554
Jon Ashburne39a4f82015-08-28 13:38:21 -06003555 dev = loader_add_logical_device(inst, *pDevice, &icd->logical_device_list);
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003556 if (dev == NULL) {
3557 return VK_ERROR_OUT_OF_HOST_MEMORY;
3558 }
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003559
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003560 loader_init_dispatch(*pDevice, &dev->loader_dispatch);
3561
Jon Ashburnb82c1852015-08-11 14:49:54 -06003562 /* activate any layers on device chain which terminates with device*/
Jon Ashburne39a4f82015-08-28 13:38:21 -06003563 res = loader_enable_device_layers(inst, icd, dev, pCreateInfo, &inst->device_layer_list);
Jon Ashburnb82c1852015-08-11 14:49:54 -06003564 if (res != VK_SUCCESS) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06003565 loader_destroy_logical_device(inst, dev);
Jon Ashburnb82c1852015-08-11 14:49:54 -06003566 return res;
3567 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06003568 loader_activate_device_layers(inst, dev, *pDevice);
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003569
Jon Ashburnfc1031e2015-11-17 15:31:02 -07003570 /* finally can call down the chain */
3571 res = dev->loader_dispatch.core_dispatch.CreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
3572
Jon Ashburn54978592015-12-11 10:45:00 -07003573 /* initialize any device extension dispatch entry's from the instance list*/
3574 loader_init_dispatch_dev_ext(inst, dev);
3575
Jon Ashburn232e3af2015-11-30 17:21:25 -07003576 /* initialize WSI device extensions as part of core dispatch since loader has
3577 * dedicated trampoline code for these*/
3578 loader_init_device_extension_dispatch_table(&dev->loader_dispatch,
3579 dev->loader_dispatch.core_dispatch.GetDeviceProcAddr,
3580 *pDevice);
Jon Ashburnfc1031e2015-11-17 15:31:02 -07003581 dev->loader_dispatch.core_dispatch.CreateDevice = icd->CreateDevice;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003582
Jon Ashburn95a77ba2015-05-15 15:09:35 -06003583 return res;
3584}
3585
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003586/**
3587 * Get an instance level or global level entry point address.
3588 * @param instance
3589 * @param pName
3590 * @return
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003591 * If instance == NULL returns a global level functions only
3592 * If instance is valid returns a trampoline entry point for all dispatchable Vulkan
3593 * functions both core and extensions.
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003594 */
Chia-I Wu9ab61502015-11-06 06:42:02 +08003595LOADER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char * pName)
Jon Ashburnb0fbe912015-05-06 10:15:07 -06003596{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003597
Jon Ashburn07daee72015-05-21 18:13:33 -06003598 void *addr;
Jon Ashburnb0fbe912015-05-06 10:15:07 -06003599
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003600 addr = globalGetProcAddr(pName);
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003601 if (instance == VK_NULL_HANDLE) {
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003602 // get entrypoint addresses that are global (no dispatchable object)
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003603
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003604 return addr;
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003605 } else {
3606 // if a global entrypoint return NULL
3607 if (addr)
3608 return NULL;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003609 }
3610
Jon Ashburne0e64572015-09-30 12:56:42 -06003611 struct loader_instance *ptr_instance = loader_get_instance(instance);
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003612 if (ptr_instance == NULL)
Jon Ashburn07daee72015-05-21 18:13:33 -06003613 return NULL;
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003614 // Return trampoline code for non-global entrypoints including any extensions.
3615 // Device extensions are returned if a layer or ICD supports the extension.
3616 // Instance extensions are returned if the extension is enabled and the loader
3617 // or someone else supports the extension
3618 return trampolineGetProcAddr(ptr_instance, pName);
Jon Ashburn07daee72015-05-21 18:13:33 -06003619
Jon Ashburnb0fbe912015-05-06 10:15:07 -06003620}
3621
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003622/**
3623 * Get a device level or global level entry point address.
3624 * @param device
3625 * @param pName
3626 * @return
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003627 * If device is valid, returns a device relative entry point for device level
3628 * entry points both core and extensions.
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003629 * Device relative means call down the device chain.
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003630 */
Chia-I Wu9ab61502015-11-06 06:42:02 +08003631LOADER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char * pName)
Courtney Goeltzenleuchter9ec39ac2015-06-22 17:45:21 -06003632{
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003633 void *addr;
Courtney Goeltzenleuchter9ec39ac2015-06-22 17:45:21 -06003634
Jon Ashburn3d526cb2015-04-13 18:10:06 -06003635 /* for entrypoints that loader must handle (ie non-dispatchable or create object)
3636 make sure the loader entrypoint is returned */
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003637 addr = loader_non_passthrough_gdpa(pName);
Ian Elliotte19c9152015-04-15 12:53:19 -06003638 if (addr) {
Jon Ashburn3d526cb2015-04-13 18:10:06 -06003639 return addr;
Ian Elliotte19c9152015-04-15 12:53:19 -06003640 }
Jon Ashburn3d526cb2015-04-13 18:10:06 -06003641
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003642 /* Although CreateDevice is on device chain it's dispatchable object isn't
3643 * a VkDevice or child of VkDevice so return NULL.
3644 */
3645 if (!strcmp(pName, "CreateDevice"))
3646 return NULL;
3647
Jon Ashburn3d526cb2015-04-13 18:10:06 -06003648 /* return the dispatch table entrypoint for the fastest case */
Jon Ashburn8d1b0b52015-05-18 13:20:15 -06003649 const VkLayerDispatchTable *disp_table = * (VkLayerDispatchTable **) device;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06003650 if (disp_table == NULL)
3651 return NULL;
3652
Jon Ashburn27cd5842015-05-12 17:26:48 -06003653 addr = loader_lookup_device_dispatch_table(disp_table, pName);
Chia-I Wuf46b81a2015-01-04 11:12:47 +08003654 if (addr)
3655 return addr;
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003656
3657 if (disp_table->GetDeviceProcAddr == NULL)
3658 return NULL;
3659 return disp_table->GetDeviceProcAddr(device, pName);
Jon Ashburnd38bfb12014-10-14 19:15:22 -06003660}
3661
Chia-I Wu9ab61502015-11-06 06:42:02 +08003662LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003663 const char* pLayerName,
Chia-I Wud50a7d72015-10-26 20:48:51 +08003664 uint32_t* pPropertyCount,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003665 VkExtensionProperties* pProperties)
3666{
Jon Ashburn432d2762015-09-18 12:53:16 -06003667 struct loader_extension_list *global_ext_list=NULL;
Jon Ashburnb82c1852015-08-11 14:49:54 -06003668 struct loader_layer_list instance_layers;
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003669 struct loader_extension_list icd_extensions;
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003670 struct loader_icd_libs icd_libs;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003671 uint32_t copy_size;
3672
Jon Ashburn87d6aa92015-08-28 15:19:27 -06003673 tls_instance = NULL;
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003674 memset(&icd_extensions, 0, sizeof(icd_extensions));
Mike Stroyan09c06c72015-10-01 15:23:48 -06003675 memset(&instance_layers, 0, sizeof(instance_layers));
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003676 loader_platform_thread_once(&once_init, loader_initialize);
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003677
Jon Ashburnb82c1852015-08-11 14:49:54 -06003678 /* get layer libraries if needed */
3679 if (pLayerName && strlen(pLayerName) != 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06003680 loader_layer_scan(NULL, &instance_layers, NULL);
Jon Ashburnb82c1852015-08-11 14:49:54 -06003681 for (uint32_t i = 0; i < instance_layers.count; i++) {
3682 struct loader_layer_properties *props = &instance_layers.list[i];
3683 if (strcmp(props->info.layerName, pLayerName) == 0) {
3684 global_ext_list = &props->instance_extension_list;
3685 }
3686 }
3687 }
3688 else {
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003689 /* Scan/discover all ICD libraries */
3690 memset(&icd_libs, 0 , sizeof(struct loader_icd_libs));
Jon Ashburne39a4f82015-08-28 13:38:21 -06003691 loader_icd_scan(NULL, &icd_libs);
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003692 /* get extensions from all ICD's, merge so no duplicates */
Jon Ashburne39a4f82015-08-28 13:38:21 -06003693 loader_get_icd_loader_instance_extensions(NULL, &icd_libs, &icd_extensions);
3694 loader_scanned_icd_clear(NULL, &icd_libs);
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003695 global_ext_list = &icd_extensions;
Jon Ashburnb82c1852015-08-11 14:49:54 -06003696 }
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003697
Jon Ashburnb82c1852015-08-11 14:49:54 -06003698 if (global_ext_list == NULL) {
Mike Stroyan09c06c72015-10-01 15:23:48 -06003699 loader_destroy_layer_list(NULL, &instance_layers);
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06003700 return VK_ERROR_LAYER_NOT_PRESENT;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003701 }
3702
3703 if (pProperties == NULL) {
Chia-I Wud50a7d72015-10-26 20:48:51 +08003704 *pPropertyCount = global_ext_list->count;
Mike Stroyan09c06c72015-10-01 15:23:48 -06003705 loader_destroy_layer_list(NULL, &instance_layers);
Jon Ashburn6e6a2162015-12-10 08:51:10 -07003706 loader_destroy_generic_list(NULL, (struct loader_generic_list *)
3707 &icd_extensions);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003708 return VK_SUCCESS;
3709 }
3710
Chia-I Wud50a7d72015-10-26 20:48:51 +08003711 copy_size = *pPropertyCount < global_ext_list->count ? *pPropertyCount : global_ext_list->count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003712 for (uint32_t i = 0; i < copy_size; i++) {
3713 memcpy(&pProperties[i],
Jon Ashburnb82c1852015-08-11 14:49:54 -06003714 &global_ext_list->list[i],
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003715 sizeof(VkExtensionProperties));
3716 }
Chia-I Wud50a7d72015-10-26 20:48:51 +08003717 *pPropertyCount = copy_size;
Jon Ashburn6e6a2162015-12-10 08:51:10 -07003718 loader_destroy_generic_list(NULL, (struct loader_generic_list *)
3719 &icd_extensions);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003720
Jon Ashburnb82c1852015-08-11 14:49:54 -06003721 if (copy_size < global_ext_list->count) {
Mike Stroyan09c06c72015-10-01 15:23:48 -06003722 loader_destroy_layer_list(NULL, &instance_layers);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003723 return VK_INCOMPLETE;
3724 }
3725
Mike Stroyan09c06c72015-10-01 15:23:48 -06003726 loader_destroy_layer_list(NULL, &instance_layers);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003727 return VK_SUCCESS;
3728}
3729
Chia-I Wu9ab61502015-11-06 06:42:02 +08003730LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(
Chia-I Wud50a7d72015-10-26 20:48:51 +08003731 uint32_t* pPropertyCount,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003732 VkLayerProperties* pProperties)
Tony Barbour59a47322015-06-24 16:06:58 -06003733{
Jon Ashburn6301a0f2015-05-29 13:15:39 -06003734
Jon Ashburnb82c1852015-08-11 14:49:54 -06003735 struct loader_layer_list instance_layer_list;
Jon Ashburn87d6aa92015-08-28 15:19:27 -06003736 tls_instance = NULL;
Jon Ashburnb82c1852015-08-11 14:49:54 -06003737
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003738 loader_platform_thread_once(&once_init, loader_initialize);
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07003739
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003740 uint32_t copy_size;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06003741
Jon Ashburnb82c1852015-08-11 14:49:54 -06003742 /* get layer libraries */
3743 memset(&instance_layer_list, 0, sizeof(instance_layer_list));
Jon Ashburne39a4f82015-08-28 13:38:21 -06003744 loader_layer_scan(NULL, &instance_layer_list, NULL);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003745
3746 if (pProperties == NULL) {
Chia-I Wud50a7d72015-10-26 20:48:51 +08003747 *pPropertyCount = instance_layer_list.count;
Jon Ashburne39a4f82015-08-28 13:38:21 -06003748 loader_destroy_layer_list(NULL, &instance_layer_list);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003749 return VK_SUCCESS;
3750 }
3751
Chia-I Wud50a7d72015-10-26 20:48:51 +08003752 copy_size = (*pPropertyCount < instance_layer_list.count) ? *pPropertyCount : instance_layer_list.count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003753 for (uint32_t i = 0; i < copy_size; i++) {
Jon Ashburnb82c1852015-08-11 14:49:54 -06003754 memcpy(&pProperties[i], &instance_layer_list.list[i].info, sizeof(VkLayerProperties));
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003755 }
Chia-I Wud50a7d72015-10-26 20:48:51 +08003756 *pPropertyCount = copy_size;
Jon Ashburne39a4f82015-08-28 13:38:21 -06003757 loader_destroy_layer_list(NULL, &instance_layer_list);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003758
Jon Ashburnb82c1852015-08-11 14:49:54 -06003759 if (copy_size < instance_layer_list.count) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003760 return VK_INCOMPLETE;
3761 }
Tony Barbour59a47322015-06-24 16:06:58 -06003762
3763 return VK_SUCCESS;
3764}
3765
Chia-I Wu9ab61502015-11-06 06:42:02 +08003766VKAPI_ATTR VkResult VKAPI_CALL loader_EnumerateDeviceExtensionProperties(
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003767 VkPhysicalDevice physicalDevice,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003768 const char* pLayerName,
Chia-I Wud50a7d72015-10-26 20:48:51 +08003769 uint32_t* pPropertyCount,
Tony Barbour59a47322015-06-24 16:06:58 -06003770 VkExtensionProperties* pProperties)
3771{
Jon Ashburna760a512015-12-14 08:52:14 -07003772 struct loader_physical_device *phys_dev;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003773 uint32_t copy_size;
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07003774
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003775 uint32_t count;
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07003776 struct loader_device_extension_list *dev_ext_list=NULL;
Jon Ashburna760a512015-12-14 08:52:14 -07003777 //TODO fix this aliases physical devices
3778 phys_dev = loader_get_physical_device(physicalDevice);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003779
Jon Ashburnb82c1852015-08-11 14:49:54 -06003780 /* get layer libraries if needed */
3781 if (pLayerName && strlen(pLayerName) != 0) {
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003782 for (uint32_t i = 0; i < phys_dev->this_instance->device_layer_list.count; i++) {
3783 struct loader_layer_properties *props = &phys_dev->this_instance->device_layer_list.list[i];
Jon Ashburnb82c1852015-08-11 14:49:54 -06003784 if (strcmp(props->info.layerName, pLayerName) == 0) {
3785 dev_ext_list = &props->device_extension_list;
3786 }
3787 }
3788 }
3789 else {
Jon Ashburn00eb6c02015-11-02 17:40:01 -07003790 /* this case is during the call down the instance chain */
3791 struct loader_icd *icd = phys_dev->this_icd;
3792 VkResult res;
3793 res = icd->EnumerateDeviceExtensionProperties(phys_dev->phys_dev, NULL, pPropertyCount, pProperties);
3794 if (pProperties != NULL && res == VK_SUCCESS) {
3795 /* initialize dev_extension list within the physicalDevice object */
Courtney Goeltzenleuchterf538ef72015-12-02 14:00:19 -07003796 res = loader_init_device_extensions(phys_dev->this_instance,
Jon Ashburn00eb6c02015-11-02 17:40:01 -07003797 phys_dev, *pPropertyCount, pProperties,
3798 &phys_dev->device_extension_cache);
3799 }
3800 return res;
Jon Ashburnb82c1852015-08-11 14:49:54 -06003801 }
3802
Jon Ashburn432d2762015-09-18 12:53:16 -06003803 count = (dev_ext_list == NULL) ? 0: dev_ext_list->count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003804 if (pProperties == NULL) {
Chia-I Wud50a7d72015-10-26 20:48:51 +08003805 *pPropertyCount = count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003806 return VK_SUCCESS;
3807 }
3808
Chia-I Wud50a7d72015-10-26 20:48:51 +08003809 copy_size = *pPropertyCount < count ? *pPropertyCount : count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003810 for (uint32_t i = 0; i < copy_size; i++) {
3811 memcpy(&pProperties[i],
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07003812 &dev_ext_list->list[i].props,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003813 sizeof(VkExtensionProperties));
3814 }
Chia-I Wud50a7d72015-10-26 20:48:51 +08003815 *pPropertyCount = copy_size;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003816
3817 if (copy_size < count) {
3818 return VK_INCOMPLETE;
3819 }
3820
3821 return VK_SUCCESS;
3822}
3823
Chia-I Wu9ab61502015-11-06 06:42:02 +08003824VKAPI_ATTR VkResult VKAPI_CALL loader_EnumerateDeviceLayerProperties(
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003825 VkPhysicalDevice physicalDevice,
Chia-I Wud50a7d72015-10-26 20:48:51 +08003826 uint32_t* pPropertyCount,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003827 VkLayerProperties* pProperties)
3828{
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003829 uint32_t copy_size;
Jon Ashburna760a512015-12-14 08:52:14 -07003830 struct loader_physical_device *phys_dev;
3831 //TODO fix this, aliases physical devices
3832 phys_dev = loader_get_physical_device(physicalDevice);
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003833 uint32_t count = phys_dev->this_instance->device_layer_list.count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003834
3835 if (pProperties == NULL) {
Chia-I Wud50a7d72015-10-26 20:48:51 +08003836 *pPropertyCount = count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003837 return VK_SUCCESS;
3838 }
3839
Chia-I Wud50a7d72015-10-26 20:48:51 +08003840 copy_size = (*pPropertyCount < count) ? *pPropertyCount : count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003841 for (uint32_t i = 0; i < copy_size; i++) {
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003842 memcpy(&pProperties[i], &(phys_dev->this_instance->device_layer_list.list[i].info), sizeof(VkLayerProperties));
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003843 }
Chia-I Wud50a7d72015-10-26 20:48:51 +08003844 *pPropertyCount = copy_size;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003845
3846 if (copy_size < count) {
3847 return VK_INCOMPLETE;
3848 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003849
3850 return VK_SUCCESS;
Jon Ashburn95a77ba2015-05-15 15:09:35 -06003851}