blob: 3b29efbc7da33c3fa85d400093f2a909c58849eb [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{
Jon Ashburn38a497f2016-01-04 14:01:38 -07001369 const char *env, *orig;
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001370
1371 if (g_loader_debug > 0)
1372 return;
1373
1374 g_loader_debug = 0;
1375
1376 /* parse comma-separated debug options */
Jon Ashburn38a497f2016-01-04 14:01:38 -07001377 orig = env = loader_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 }
Jon Ashburn38a497f2016-01-04 14:01:38 -07001414
1415 loader_free_getenv(orig);
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001416}
1417
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001418void loader_initialize(void)
1419{
Jon Ashburn6461ef22015-09-22 13:11:00 -06001420 // initialize mutexs
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001421 loader_platform_thread_create_mutex(&loader_lock);
Jon Ashburn6461ef22015-09-22 13:11:00 -06001422 loader_platform_thread_create_mutex(&loader_json_lock);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001423
1424 // initialize logging
1425 loader_debug_init();
Jon Ashburn87d6aa92015-08-28 15:19:27 -06001426
1427 // initial cJSON to use alloc callbacks
1428 cJSON_Hooks alloc_fns = {
1429 .malloc_fn = loader_tls_heap_alloc,
1430 .free_fn = loader_tls_heap_free,
1431 };
1432 cJSON_InitHooks(&alloc_fns);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001433}
1434
Jon Ashburn2077e382015-06-29 11:25:34 -06001435struct loader_manifest_files {
1436 uint32_t count;
1437 char **filename_list;
1438};
1439
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06001440/**
Jon Ashburn2077e382015-06-29 11:25:34 -06001441 * Get next file or dirname given a string list or registry key path
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06001442 *
1443 * \returns
Jon Ashburn2077e382015-06-29 11:25:34 -06001444 * A pointer to first char in the next path.
1445 * The next path (or NULL) in the list is returned in next_path.
1446 * Note: input string is modified in some cases. PASS IN A COPY!
1447 */
Jon Ashburn2077e382015-06-29 11:25:34 -06001448static char *loader_get_next_path(char *path)
1449{
1450 uint32_t len;
1451 char *next;
1452
1453 if (path == NULL)
1454 return NULL;
1455 next = strchr(path, PATH_SEPERATOR);
1456 if (next == NULL) {
1457 len = (uint32_t) strlen(path);
1458 next = path + len;
1459 }
1460 else {
1461 *next = '\0';
1462 next++;
1463 }
1464
1465 return next;
1466}
1467
1468/**
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001469 * Given a path which is absolute or relative, expand the path if relative or
1470 * leave the path unmodified if absolute. The base path to prepend to relative
1471 * paths is given in rel_base.
Jon Ashburn15315172015-07-07 15:06:25 -06001472 *
1473 * \returns
1474 * A string in out_fullpath of the full absolute path
Jon Ashburn15315172015-07-07 15:06:25 -06001475 */
1476static void loader_expand_path(const char *path,
1477 const char *rel_base,
1478 size_t out_size,
1479 char *out_fullpath)
1480{
1481 if (loader_platform_is_path_absolute(path)) {
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001482 // do not prepend a base to an absolute path
1483 rel_base = "";
Jon Ashburn15315172015-07-07 15:06:25 -06001484 }
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001485
1486 loader_platform_combine_path(out_fullpath, out_size, rel_base, path, NULL);
Jon Ashburn15315172015-07-07 15:06:25 -06001487}
1488
1489/**
Jon Ashburn2077e382015-06-29 11:25:34 -06001490 * Given a filename (file) and a list of paths (dir), try to find an existing
1491 * file in the paths. If filename already is a path then no
1492 * searching in the given paths.
1493 *
1494 * \returns
1495 * A string in out_fullpath of either the full path or file.
Jon Ashburn2077e382015-06-29 11:25:34 -06001496 */
1497static void loader_get_fullpath(const char *file,
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001498 const char *dirs,
Jon Ashburn2077e382015-06-29 11:25:34 -06001499 size_t out_size,
1500 char *out_fullpath)
1501{
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001502 if (!loader_platform_is_path(file) && *dirs) {
1503 char *dirs_copy, *dir, *next_dir;
1504
1505 dirs_copy = loader_stack_alloc(strlen(dirs) + 1);
1506 strcpy(dirs_copy, dirs);
1507
1508 //find if file exists after prepending paths in given list
1509 for (dir = dirs_copy;
1510 *dir && (next_dir = loader_get_next_path(dir));
1511 dir = next_dir) {
1512 loader_platform_combine_path(out_fullpath, out_size, dir, file, NULL);
Jon Ashburn2077e382015-06-29 11:25:34 -06001513 if (loader_platform_file_exists(out_fullpath)) {
1514 return;
1515 }
Jon Ashburn2077e382015-06-29 11:25:34 -06001516 }
1517 }
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001518
Jon Ashburn2077e382015-06-29 11:25:34 -06001519 snprintf(out_fullpath, out_size, "%s", file);
1520}
1521
1522/**
1523 * Read a JSON file into a buffer.
1524 *
1525 * \returns
1526 * A pointer to a cJSON object representing the JSON parse tree.
1527 * This returned buffer should be freed by caller.
1528 */
Courtney Goeltzenleuchter73477392015-12-03 13:48:01 -07001529static cJSON *loader_get_json(const struct loader_instance *inst, const char *filename)
Jon Ashburn2077e382015-06-29 11:25:34 -06001530{
1531 FILE *file;
1532 char *json_buf;
1533 cJSON *json;
1534 uint64_t len;
1535 file = fopen(filename,"rb");
Jon Ashburnaa4ea472015-08-27 08:30:50 -06001536 if (!file) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001537 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Couldn't open JSON file %s", filename);
Jon Ashburnaa4ea472015-08-27 08:30:50 -06001538 return NULL;
1539 }
Jon Ashburn2077e382015-06-29 11:25:34 -06001540 fseek(file, 0, SEEK_END);
1541 len = ftell(file);
1542 fseek(file, 0, SEEK_SET);
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -06001543 json_buf = (char*) loader_stack_alloc(len+1);
Jon Ashburn2077e382015-06-29 11:25:34 -06001544 if (json_buf == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001545 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 -06001546 fclose(file);
1547 return NULL;
1548 }
1549 if (fread(json_buf, sizeof(char), len, file) != len) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001550 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "fread failed can't get JSON file");
Jon Ashburn2077e382015-06-29 11:25:34 -06001551 fclose(file);
1552 return NULL;
1553 }
1554 fclose(file);
1555 json_buf[len] = '\0';
1556
1557 //parse text from file
1558 json = cJSON_Parse(json_buf);
1559 if (json == NULL)
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001560 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Can't parse JSON file %s", filename);
Jon Ashburn2077e382015-06-29 11:25:34 -06001561 return json;
1562}
1563
1564/**
Jon Ashburn3d002332015-08-20 16:35:30 -06001565 * Do a deep copy of the loader_layer_properties structure.
1566 */
1567static void loader_copy_layer_properties(
Jon Ashburne39a4f82015-08-28 13:38:21 -06001568 const struct loader_instance *inst,
Jon Ashburn3d002332015-08-20 16:35:30 -06001569 struct loader_layer_properties *dst,
1570 struct loader_layer_properties *src)
1571{
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001572 uint32_t cnt, i;
Jon Ashburn3d002332015-08-20 16:35:30 -06001573 memcpy(dst, src, sizeof (*src));
Jon Ashburne39a4f82015-08-28 13:38:21 -06001574 dst->instance_extension_list.list = loader_heap_alloc(
1575 inst,
1576 sizeof(VkExtensionProperties) *
1577 src->instance_extension_list.count,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001578 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001579 dst->instance_extension_list.capacity = sizeof(VkExtensionProperties) *
1580 src->instance_extension_list.count;
1581 memcpy(dst->instance_extension_list.list, src->instance_extension_list.list,
1582 dst->instance_extension_list.capacity);
1583 dst->device_extension_list.list = loader_heap_alloc(
1584 inst,
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001585 sizeof(struct loader_dev_ext_props) *
Jon Ashburne39a4f82015-08-28 13:38:21 -06001586 src->device_extension_list.count,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001587 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001588
1589 dst->device_extension_list.capacity = sizeof(struct loader_dev_ext_props) *
Jon Ashburne39a4f82015-08-28 13:38:21 -06001590 src->device_extension_list.count;
1591 memcpy(dst->device_extension_list.list, src->device_extension_list.list,
1592 dst->device_extension_list.capacity);
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001593 if (src->device_extension_list.count > 0 &&
1594 src->device_extension_list.list->entrypoint_count > 0) {
1595 cnt = src->device_extension_list.list->entrypoint_count;
1596 dst->device_extension_list.list->entrypoints = loader_heap_alloc(
1597 inst,
1598 sizeof(char *) * cnt,
1599 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
1600 for (i = 0; i < cnt; i++) {
1601 dst->device_extension_list.list->entrypoints[i] = loader_heap_alloc(
1602 inst,
1603 strlen(src->device_extension_list.list->entrypoints[i]) + 1,
1604 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
1605 strcpy(dst->device_extension_list.list->entrypoints[i],
1606 src->device_extension_list.list->entrypoints[i]);
1607 }
1608 }
Jon Ashburn3d002332015-08-20 16:35:30 -06001609}
1610
1611/**
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001612 * Given a cJSON struct (json) of the top level JSON object from layer manifest
1613 * file, add entry to the layer_list.
Jon Ashburne13ecc92015-08-03 17:19:30 -06001614 * Fill out the layer_properties in this list entry from the input cJSON object.
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001615 *
1616 * \returns
1617 * void
1618 * layer_list has a new entry and initialized accordingly.
1619 * If the json input object does not have all the required fields no entry
1620 * is added to the list.
1621 */
Jon Ashburne39a4f82015-08-28 13:38:21 -06001622static void loader_add_layer_properties(const struct loader_instance *inst,
1623 struct loader_layer_list *layer_instance_list,
Jon Ashburnb2ef1372015-07-16 17:19:31 -06001624 struct loader_layer_list *layer_device_list,
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001625 cJSON *json,
1626 bool is_implicit,
1627 char *filename)
1628{
1629 /* Fields in layer manifest file that are required:
1630 * (required) “file_format_version”
1631 * following are required in the "layer" object:
1632 * (required) "name"
1633 * (required) "type"
1634 * (required) “library_path”
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001635 * (required) “api_version”
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001636 * (required) “implementation_version”
1637 * (required) “description”
1638 * (required for implicit layers) “disable_environment”
1639 *
1640 * First get all required items and if any missing abort
1641 */
1642
1643 cJSON *item, *layer_node, *ext_item;
1644 char *temp;
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001645 char *name, *type, *library_path, *api_version;
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001646 char *implementation_version, *description;
1647 cJSON *disable_environment;
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001648 int i, j;
Jon Ashburn5c042ea2015-08-04 11:14:18 -06001649 VkExtensionProperties ext_prop;
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001650 item = cJSON_GetObjectItem(json, "file_format_version");
1651 if (item == NULL) {
1652 return;
1653 }
1654 char *file_vers = cJSON_PrintUnformatted(item);
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001655 loader_log(inst, VK_DEBUG_REPORT_INFO_BIT_EXT, 0, "Found manifest file %s, version %s",
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001656 filename, file_vers);
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001657 if (strcmp(file_vers, "\"1.0.0\"") != 0)
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001658 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 -06001659 loader_tls_heap_free(file_vers);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001660
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001661 layer_node = cJSON_GetObjectItem(json, "layer");
1662 if (layer_node == NULL) {
Jon Ashburn075ce432015-12-17 17:38:24 -07001663 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 -06001664 return;
1665 }
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001666
1667 // loop through all "layer" objects in the file
1668 do {
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001669#define GET_JSON_OBJECT(node, var) { \
1670 var = cJSON_GetObjectItem(node, #var); \
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001671 if (var == NULL) { \
1672 layer_node = layer_node->next; \
Jon Ashburn075ce432015-12-17 17:38:24 -07001673 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0,\
1674 "Didn't find required layer object %s in manifest JSON file, skipping this layer",\
1675 #var); \
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001676 continue; \
1677 } \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001678 }
1679#define GET_JSON_ITEM(node, var) { \
1680 item = cJSON_GetObjectItem(node, #var); \
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001681 if (item == NULL) { \
1682 layer_node = layer_node->next; \
Jon Ashburn075ce432015-12-17 17:38:24 -07001683 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0,\
1684 "Didn't find required layer value %s in manifest JSON file, skipping this layer",\
1685 #var); \
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001686 continue; \
1687 } \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001688 temp = cJSON_Print(item); \
1689 temp[strlen(temp) - 1] = '\0'; \
Jon Ashburnf73e9212015-08-04 10:22:33 -06001690 var = loader_stack_alloc(strlen(temp) + 1); \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001691 strcpy(var, &temp[1]); \
Jon Ashburn87d6aa92015-08-28 15:19:27 -06001692 loader_tls_heap_free(temp); \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001693 }
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001694 GET_JSON_ITEM(layer_node, name)
1695 GET_JSON_ITEM(layer_node, type)
1696 GET_JSON_ITEM(layer_node, library_path)
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001697 GET_JSON_ITEM(layer_node, api_version)
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001698 GET_JSON_ITEM(layer_node, implementation_version)
1699 GET_JSON_ITEM(layer_node, description)
1700 if (is_implicit) {
1701 GET_JSON_OBJECT(layer_node, disable_environment)
1702 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001703#undef GET_JSON_ITEM
1704#undef GET_JSON_OBJECT
1705
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001706 // add list entry
Jon Ashburn432d2762015-09-18 12:53:16 -06001707 struct loader_layer_properties *props=NULL;
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001708 if (!strcmp(type, "DEVICE")) {
1709 if (layer_device_list == NULL) {
1710 layer_node = layer_node->next;
1711 continue;
1712 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06001713 props = loader_get_next_layer_property(inst, layer_device_list);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001714 props->type = (is_implicit) ? VK_LAYER_TYPE_DEVICE_IMPLICIT : VK_LAYER_TYPE_DEVICE_EXPLICIT;
1715 }
1716 if (!strcmp(type, "INSTANCE")) {
1717 if (layer_instance_list == NULL) {
1718 layer_node = layer_node->next;
1719 continue;
1720 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06001721 props = loader_get_next_layer_property(inst, layer_instance_list);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001722 props->type = (is_implicit) ? VK_LAYER_TYPE_INSTANCE_IMPLICIT : VK_LAYER_TYPE_INSTANCE_EXPLICIT;
1723 }
1724 if (!strcmp(type, "GLOBAL")) {
1725 if (layer_instance_list != NULL)
Jon Ashburne39a4f82015-08-28 13:38:21 -06001726 props = loader_get_next_layer_property(inst, layer_instance_list);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001727 else if (layer_device_list != NULL)
Jon Ashburne39a4f82015-08-28 13:38:21 -06001728 props = loader_get_next_layer_property(inst, layer_device_list);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001729 else {
1730 layer_node = layer_node->next;
1731 continue;
1732 }
1733 props->type = (is_implicit) ? VK_LAYER_TYPE_GLOBAL_IMPLICIT : VK_LAYER_TYPE_GLOBAL_EXPLICIT;
1734 }
Jon Ashburnb2ef1372015-07-16 17:19:31 -06001735
Jon Ashburn432d2762015-09-18 12:53:16 -06001736 if (props == NULL) {
1737 layer_node = layer_node->next;
1738 continue;
1739 }
1740
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001741 strncpy(props->info.layerName, name, sizeof (props->info.layerName));
1742 props->info.layerName[sizeof (props->info.layerName) - 1] = '\0';
Jon Ashburn15315172015-07-07 15:06:25 -06001743
Jon Ashburn3d002332015-08-20 16:35:30 -06001744 char *fullpath = props->lib_name;
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001745 char *rel_base;
Jon Ashburn6e08ebd2015-12-01 17:11:02 -07001746 if (loader_platform_is_path(library_path)) {
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001747 // a relative or absolute path
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001748 char *name_copy = loader_stack_alloc(strlen(filename) + 1);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001749 strcpy(name_copy, filename);
1750 rel_base = loader_platform_dirname(name_copy);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001751 loader_expand_path(library_path, rel_base, MAX_STRING_SIZE, fullpath);
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001752 } else {
1753 // a filename which is assumed in a system directory
1754 loader_get_fullpath(library_path, DEFAULT_VK_LAYERS_PATH, MAX_STRING_SIZE, fullpath);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001755 }
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001756 props->info.specVersion = loader_make_version(api_version);
1757 props->info.implementationVersion = atoi(implementation_version);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001758 strncpy((char *) props->info.description, description, sizeof (props->info.description));
1759 props->info.description[sizeof (props->info.description) - 1] = '\0';
1760 if (is_implicit) {
1761 strncpy(props->disable_env_var.name, disable_environment->child->string, sizeof (props->disable_env_var.name));
1762 props->disable_env_var.name[sizeof (props->disable_env_var.name) - 1] = '\0';
1763 strncpy(props->disable_env_var.value, disable_environment->child->valuestring, sizeof (props->disable_env_var.value));
1764 props->disable_env_var.value[sizeof (props->disable_env_var.value) - 1] = '\0';
1765 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001766
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001767 /**
1768 * Now get all optional items and objects and put in list:
1769 * functions
1770 * instance_extensions
1771 * device_extensions
1772 * enable_environment (implicit layers only)
1773 */
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001774#define GET_JSON_OBJECT(node, var) { \
1775 var = cJSON_GetObjectItem(node, #var); \
1776 }
1777#define GET_JSON_ITEM(node, var) { \
1778 item = cJSON_GetObjectItem(node, #var); \
Jon Ashburn21c21ee2015-09-09 11:29:24 -06001779 if (item != NULL) { \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001780 temp = cJSON_Print(item); \
Jon Ashburn21c21ee2015-09-09 11:29:24 -06001781 temp[strlen(temp) - 1] = '\0'; \
1782 var = loader_stack_alloc(strlen(temp) + 1);\
1783 strcpy(var, &temp[1]); \
1784 loader_tls_heap_free(temp); \
1785 } \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001786 }
1787
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001788 cJSON *instance_extensions, *device_extensions, *functions, *enable_environment;
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001789 cJSON *entrypoints;
1790 char *vkGetInstanceProcAddr, *vkGetDeviceProcAddr, *spec_version;
1791 char **entry_array;
1792 vkGetInstanceProcAddr = NULL;
1793 vkGetDeviceProcAddr = NULL;
1794 spec_version = NULL;
1795 entrypoints = NULL;
1796 entry_array = NULL;
1797 /**
1798 * functions
1799 * vkGetInstanceProcAddr
1800 * vkGetDeviceProcAddr
1801 */
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001802 GET_JSON_OBJECT(layer_node, functions)
1803 if (functions != NULL) {
1804 GET_JSON_ITEM(functions, vkGetInstanceProcAddr)
1805 GET_JSON_ITEM(functions, vkGetDeviceProcAddr)
Jon Ashburn21c21ee2015-09-09 11:29:24 -06001806 if (vkGetInstanceProcAddr != NULL)
1807 strncpy(props->functions.str_gipa, vkGetInstanceProcAddr, sizeof (props->functions.str_gipa));
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001808 props->functions.str_gipa[sizeof (props->functions.str_gipa) - 1] = '\0';
Jon Ashburn21c21ee2015-09-09 11:29:24 -06001809 if (vkGetDeviceProcAddr != NULL)
1810 strncpy(props->functions.str_gdpa, vkGetDeviceProcAddr, sizeof (props->functions.str_gdpa));
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001811 props->functions.str_gdpa[sizeof (props->functions.str_gdpa) - 1] = '\0';
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001812 }
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001813 /**
1814 * instance_extensions
1815 * array of
1816 * name
1817 * spec_version
1818 */
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001819 GET_JSON_OBJECT(layer_node, instance_extensions)
1820 if (instance_extensions != NULL) {
1821 int count = cJSON_GetArraySize(instance_extensions);
1822 for (i = 0; i < count; i++) {
1823 ext_item = cJSON_GetArrayItem(instance_extensions, i);
1824 GET_JSON_ITEM(ext_item, name)
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001825 GET_JSON_ITEM(ext_item, spec_version)
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001826 if (name != NULL) {
Jon Ashburn6e6a2162015-12-10 08:51:10 -07001827 strncpy(ext_prop.extensionName, name, sizeof (ext_prop.extensionName));
1828 ext_prop.extensionName[sizeof (ext_prop.extensionName) - 1] = '\0';
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001829 }
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001830 ext_prop.specVersion = atoi(spec_version);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001831 loader_add_to_ext_list(inst, &props->instance_extension_list, 1, &ext_prop);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001832 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001833 }
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001834 /**
1835 * device_extensions
1836 * array of
1837 * name
1838 * spec_version
1839 * entrypoints
1840 */
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001841 GET_JSON_OBJECT(layer_node, device_extensions)
1842 if (device_extensions != NULL) {
1843 int count = cJSON_GetArraySize(device_extensions);
1844 for (i = 0; i < count; i++) {
1845 ext_item = cJSON_GetArrayItem(device_extensions, i);
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001846 GET_JSON_ITEM(ext_item, name)
1847 GET_JSON_ITEM(ext_item, spec_version)
1848 if (name != NULL) {
Jon Ashburn6e6a2162015-12-10 08:51:10 -07001849 strncpy(ext_prop.extensionName, name, sizeof (ext_prop.extensionName));
1850 ext_prop.extensionName[sizeof (ext_prop.extensionName) - 1] = '\0';
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001851 }
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001852 ext_prop.specVersion = atoi(spec_version);
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001853 //entrypoints = cJSON_GetObjectItem(ext_item, "entrypoints");
1854 GET_JSON_OBJECT(ext_item, entrypoints)
1855 int entry_count;
1856 if (entrypoints == NULL)
1857 continue;
1858 entry_count = cJSON_GetArraySize(entrypoints);
1859 if (entry_count)
1860 entry_array = (char **) loader_stack_alloc(sizeof(char *) * entry_count);
1861 for (j = 0; j < entry_count; j++) {
1862 ext_item = cJSON_GetArrayItem(entrypoints, j);
1863 if (ext_item != NULL) {
1864 temp = cJSON_Print(ext_item);
1865 temp[strlen(temp) - 1] = '\0';
1866 entry_array[j] = loader_stack_alloc(strlen(temp) + 1);
1867 strcpy(entry_array[j], &temp[1]);
1868 loader_tls_heap_free(temp);
Jon Ashburn6e6a2162015-12-10 08:51:10 -07001869 }
1870 }
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001871 loader_add_to_dev_ext_list(inst, &props->device_extension_list,
1872 &ext_prop, entry_count, entry_array);
1873 }
1874 }
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001875 if (is_implicit) {
1876 GET_JSON_OBJECT(layer_node, enable_environment)
Jon Ashburn075ce432015-12-17 17:38:24 -07001877
1878 // enable_environment is optional
1879 if (enable_environment) {
1880 strncpy(props->enable_env_var.name, enable_environment->child->string, sizeof (props->enable_env_var.name));
1881 props->enable_env_var.name[sizeof (props->enable_env_var.name) - 1] = '\0';
1882 strncpy(props->enable_env_var.value, enable_environment->child->valuestring, sizeof (props->enable_env_var.value));
1883 props->enable_env_var.value[sizeof (props->enable_env_var.value) - 1] = '\0';
1884 }
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001885 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001886#undef GET_JSON_ITEM
1887#undef GET_JSON_OBJECT
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001888 // for global layers need to add them to both device and instance list
1889 if (!strcmp(type, "GLOBAL")) {
1890 struct loader_layer_properties *dev_props;
1891 if (layer_instance_list == NULL || layer_device_list == NULL) {
1892 layer_node = layer_node->next;
1893 continue;
1894 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06001895 dev_props = loader_get_next_layer_property(inst, layer_device_list);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001896 //copy into device layer list
Jon Ashburne39a4f82015-08-28 13:38:21 -06001897 loader_copy_layer_properties(inst, dev_props, props);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001898 }
1899 layer_node = layer_node->next;
1900 } while (layer_node != NULL);
1901 return;
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001902}
1903
1904/**
Jon Ashburn2077e382015-06-29 11:25:34 -06001905 * Find the Vulkan library manifest files.
1906 *
1907 * This function scans the location or env_override directories/files
1908 * for a list of JSON manifest files. If env_override is non-NULL
1909 * and has a valid value. Then the location is ignored. Otherwise
1910 * location is used to look for manifest files. The location
1911 * is interpreted as Registry path on Windows and a directory path(s)
1912 * on Linux.
1913 *
1914 * \returns
1915 * A string list of manifest files to be opened in out_files param.
1916 * List has a pointer to string for each manifest filename.
1917 * When done using the list in out_files, pointers should be freed.
Jon Ashburnffad94d2015-06-30 14:46:22 -07001918 * Location or override string lists can be either files or directories as follows:
1919 * | location | override
1920 * --------------------------------
1921 * Win ICD | files | files
1922 * Win Layer | files | dirs
1923 * Linux ICD | dirs | files
1924 * Linux Layer| dirs | dirs
Jon Ashburn2077e382015-06-29 11:25:34 -06001925 */
Jon Ashburne39a4f82015-08-28 13:38:21 -06001926static void loader_get_manifest_files(const struct loader_instance *inst,
1927 const char *env_override,
Jon Ashburnffad94d2015-06-30 14:46:22 -07001928 bool is_layer,
1929 const char *location,
1930 struct loader_manifest_files *out_files)
Jon Ashburn2077e382015-06-29 11:25:34 -06001931{
1932 char *override = NULL;
1933 char *loc;
1934 char *file, *next_file, *name;
1935 size_t alloced_count = 64;
1936 char full_path[2048];
1937 DIR *sysdir = NULL;
Jon Ashburnffad94d2015-06-30 14:46:22 -07001938 bool list_is_dirs = false;
Jon Ashburn2077e382015-06-29 11:25:34 -06001939 struct dirent *dent;
1940
1941 out_files->count = 0;
1942 out_files->filename_list = NULL;
1943
Jon Ashburn38a497f2016-01-04 14:01:38 -07001944 if (env_override != NULL && (override = loader_getenv(env_override))) {
Johannes van Waveren9bd805012015-10-28 11:45:00 -05001945#if !defined(_WIN32)
Jon Ashburn2077e382015-06-29 11:25:34 -06001946 if (geteuid() != getuid()) {
Jon Ashburnffad94d2015-06-30 14:46:22 -07001947 /* Don't allow setuid apps to use the env var: */
Jon Ashburn38a497f2016-01-04 14:01:38 -07001948 loader_free_getenv(override);
Jon Ashburn2077e382015-06-29 11:25:34 -06001949 override = NULL;
1950 }
1951#endif
1952 }
1953
1954 if (location == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001955 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburnffad94d2015-06-30 14:46:22 -07001956 "Can't get manifest files with NULL location, env_override=%s",
1957 env_override);
Jon Ashburn2077e382015-06-29 11:25:34 -06001958 return;
1959 }
1960
Johannes van Waveren9bd805012015-10-28 11:45:00 -05001961#if defined(_WIN32)
Jon Ashburnffad94d2015-06-30 14:46:22 -07001962 list_is_dirs = (is_layer && override != NULL) ? true : false;
Johannes van Waveren9bd805012015-10-28 11:45:00 -05001963#else
1964 list_is_dirs = (override == NULL || is_layer) ? true : false;
Jon Ashburnffad94d2015-06-30 14:46:22 -07001965#endif
Jon Ashburn2077e382015-06-29 11:25:34 -06001966 // Make a copy of the input we are using so it is not modified
Jon Ashburnffad94d2015-06-30 14:46:22 -07001967 // Also handle getting the location(s) from registry on Windows
1968 if (override == NULL) {
Jon Ashburn3b78e462015-07-31 10:11:24 -06001969 loc = loader_stack_alloc(strlen(location) + 1);
Jon Ashburnffad94d2015-06-30 14:46:22 -07001970 if (loc == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001971 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 -07001972 return;
1973 }
1974 strcpy(loc, location);
Johannes van Waveren9bd805012015-10-28 11:45:00 -05001975#if defined(_WIN32)
Jon Ashburn480a50a2015-08-28 14:58:46 -07001976 loc = loader_get_registry_files(inst, loc);
Jon Ashburn24265ac2015-07-31 09:33:21 -06001977 if (loc == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001978 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 -06001979 return;
1980 }
Jon Ashburnffad94d2015-06-30 14:46:22 -07001981#endif
Jon Ashburn2077e382015-06-29 11:25:34 -06001982 }
Jon Ashburnffad94d2015-06-30 14:46:22 -07001983 else {
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -06001984 loc = loader_stack_alloc(strlen(override) + 1);
Jon Ashburnffad94d2015-06-30 14:46:22 -07001985 if (loc == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001986 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 -07001987 return;
1988 }
1989 strcpy(loc, override);
Jon Ashburn38a497f2016-01-04 14:01:38 -07001990 loader_free_getenv(override);
Jon Ashburnffad94d2015-06-30 14:46:22 -07001991 }
Jon Ashburn2077e382015-06-29 11:25:34 -06001992
Liam Middlebrook9b14e892015-07-23 18:32:20 -07001993 // Print out the paths being searched if debugging is enabled
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001994 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 -07001995
Jon Ashburn2077e382015-06-29 11:25:34 -06001996 file = loc;
1997 while (*file) {
1998 next_file = loader_get_next_path(file);
Jon Ashburnffad94d2015-06-30 14:46:22 -07001999 if (list_is_dirs) {
Jon Ashburn2077e382015-06-29 11:25:34 -06002000 sysdir = opendir(file);
2001 name = NULL;
2002 if (sysdir) {
2003 dent = readdir(sysdir);
2004 if (dent == NULL)
2005 break;
2006 name = &(dent->d_name[0]);
2007 loader_get_fullpath(name, file, sizeof(full_path), full_path);
2008 name = full_path;
2009 }
2010 }
2011 else {
Johannes van Waveren9bd805012015-10-28 11:45:00 -05002012#if defined(_WIN32)
2013 name = file;
2014#else
Jon Ashburnffad94d2015-06-30 14:46:22 -07002015 // only Linux has relative paths
Jon Ashburn2077e382015-06-29 11:25:34 -06002016 char *dir;
2017 // make a copy of location so it isn't modified
Jason Ekstrandcc7550e2015-10-10 08:33:37 -07002018 dir = loader_stack_alloc(strlen(loc) + 1);
Jon Ashburn2077e382015-06-29 11:25:34 -06002019 if (dir == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002020 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 -06002021 return;
2022 }
Jason Ekstrandcc7550e2015-10-10 08:33:37 -07002023 strcpy(dir, loc);
Jon Ashburn2077e382015-06-29 11:25:34 -06002024
2025 loader_get_fullpath(file, dir, sizeof(full_path), full_path);
2026
2027 name = full_path;
Jon Ashburnffad94d2015-06-30 14:46:22 -07002028#endif
Jon Ashburn2077e382015-06-29 11:25:34 -06002029 }
2030 while (name) {
2031 /* Look for files ending with ".json" suffix */
2032 uint32_t nlen = (uint32_t) strlen(name);
2033 const char *suf = name + nlen - 5;
2034 if ((nlen > 5) && !strncmp(suf, ".json", 5)) {
2035 if (out_files->count == 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06002036 out_files->filename_list = loader_heap_alloc(inst,
2037 alloced_count * sizeof(char *),
Chia-I Wucf804e82015-10-31 00:31:16 +08002038 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
Jon Ashburn2077e382015-06-29 11:25:34 -06002039 }
2040 else if (out_files->count == alloced_count) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06002041 out_files->filename_list = loader_heap_realloc(inst,
2042 out_files->filename_list,
2043 alloced_count * sizeof(char *),
2044 alloced_count * sizeof(char *) * 2,
Chia-I Wucf804e82015-10-31 00:31:16 +08002045 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
Jon Ashburn2077e382015-06-29 11:25:34 -06002046 alloced_count *= 2;
2047 }
2048 if (out_files->filename_list == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002049 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 -06002050 return;
2051 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06002052 out_files->filename_list[out_files->count] = loader_heap_alloc(
2053 inst,
2054 strlen(name) + 1,
Chia-I Wucf804e82015-10-31 00:31:16 +08002055 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
Jon Ashburn2077e382015-06-29 11:25:34 -06002056 if (out_files->filename_list[out_files->count] == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002057 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 -06002058 return;
2059 }
2060 strcpy(out_files->filename_list[out_files->count], name);
2061 out_files->count++;
Jon Ashburnf70f3612015-07-02 10:08:47 -06002062 } else if (!list_is_dirs) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002063 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 -06002064 }
Jon Ashburnffad94d2015-06-30 14:46:22 -07002065 if (list_is_dirs) {
Jon Ashburn2077e382015-06-29 11:25:34 -06002066 dent = readdir(sysdir);
2067 if (dent == NULL)
2068 break;
2069 name = &(dent->d_name[0]);
2070 loader_get_fullpath(name, file, sizeof(full_path), full_path);
2071 name = full_path;
2072 }
2073 else {
2074 break;
2075 }
2076 }
2077 if (sysdir)
2078 closedir(sysdir);
2079 file = next_file;
2080 }
2081 return;
2082}
2083
Jon Ashburn8810c5f2015-08-18 18:04:47 -06002084void loader_init_icd_lib_list()
2085{
2086
2087}
2088
2089void loader_destroy_icd_lib_list()
2090{
2091
2092}
Jon Ashburn2077e382015-06-29 11:25:34 -06002093/**
2094 * Try to find the Vulkan ICD driver(s).
2095 *
2096 * This function scans the default system loader path(s) or path
2097 * specified by the \c VK_ICD_FILENAMES environment variable in
2098 * order to find loadable VK ICDs manifest files. From these
2099 * manifest files it finds the ICD libraries.
2100 *
2101 * \returns
Jon Ashburn8810c5f2015-08-18 18:04:47 -06002102 * a list of icds that were discovered
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06002103 */
Jon Ashburne39a4f82015-08-28 13:38:21 -06002104void loader_icd_scan(
2105 const struct loader_instance *inst,
2106 struct loader_icd_libs *icds)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08002107{
Jon Ashburn2077e382015-06-29 11:25:34 -06002108 char *file_str;
2109 struct loader_manifest_files manifest_files;
2110
Jon Ashburne39a4f82015-08-28 13:38:21 -06002111 loader_scanned_icd_init(inst, icds);
Jon Ashburn2077e382015-06-29 11:25:34 -06002112 // Get a list of manifest files for ICDs
Jon Ashburne39a4f82015-08-28 13:38:21 -06002113 loader_get_manifest_files(inst, "VK_ICD_FILENAMES", false,
2114 DEFAULT_VK_DRIVERS_INFO, &manifest_files);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002115 if (manifest_files.count == 0)
2116 return;
Jon Ashburn6461ef22015-09-22 13:11:00 -06002117 loader_platform_thread_lock_mutex(&loader_json_lock);
Jon Ashburn2077e382015-06-29 11:25:34 -06002118 for (uint32_t i = 0; i < manifest_files.count; i++) {
2119 file_str = manifest_files.filename_list[i];
2120 if (file_str == NULL)
2121 continue;
2122
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002123 cJSON *json;
Courtney Goeltzenleuchter73477392015-12-03 13:48:01 -07002124 json = loader_get_json(inst, file_str);
Jon Ashburnaa4ea472015-08-27 08:30:50 -06002125 if (!json)
2126 continue;
Jon Ashburn005617f2015-11-17 17:35:40 -07002127 cJSON *item, *itemICD;
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002128 item = cJSON_GetObjectItem(json, "file_format_version");
Jon Ashburn6461ef22015-09-22 13:11:00 -06002129 if (item == NULL) {
2130 loader_platform_thread_unlock_mutex(&loader_json_lock);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002131 return;
Jon Ashburn6461ef22015-09-22 13:11:00 -06002132 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002133 char *file_vers = cJSON_Print(item);
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002134 loader_log(inst, VK_DEBUG_REPORT_INFO_BIT_EXT, 0, "Found manifest file %s, version %s",
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002135 file_str, file_vers);
2136 if (strcmp(file_vers, "\"1.0.0\"") != 0)
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002137 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 -06002138 loader_tls_heap_free(file_vers);
Jon Ashburn005617f2015-11-17 17:35:40 -07002139 itemICD = cJSON_GetObjectItem(json, "ICD");
2140 if (itemICD != NULL) {
2141 item = cJSON_GetObjectItem(itemICD, "library_path");
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002142 if (item != NULL) {
Jon Ashburn86251302015-08-25 16:48:24 -06002143 char *temp= cJSON_Print(item);
2144 if (!temp || strlen(temp) == 0) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002145 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 -06002146 loader_tls_heap_free(temp);
Jon Ashburne39a4f82015-08-28 13:38:21 -06002147 loader_heap_free(inst, file_str);
Jon Ashburn86251302015-08-25 16:48:24 -06002148 cJSON_Delete(json);
2149 continue;
Jon Ashburn2077e382015-06-29 11:25:34 -06002150 }
Jon Ashburn86251302015-08-25 16:48:24 -06002151 //strip out extra quotes
2152 temp[strlen(temp) - 1] = '\0';
2153 char *library_path = loader_stack_alloc(strlen(temp) + 1);
2154 strcpy(library_path, &temp[1]);
Jon Ashburn87d6aa92015-08-28 15:19:27 -06002155 loader_tls_heap_free(temp);
Jon Ashburn86251302015-08-25 16:48:24 -06002156 if (!library_path || strlen(library_path) == 0) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002157 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 -06002158 loader_heap_free(inst, file_str);
Jon Ashburn86251302015-08-25 16:48:24 -06002159 cJSON_Delete(json);
2160 continue;
2161 }
Daniel Dadap00b4aba2015-09-30 11:50:51 -05002162 char fullpath[MAX_STRING_SIZE];
Jon Ashburn86251302015-08-25 16:48:24 -06002163 // Print out the paths being searched if debugging is enabled
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002164 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 -05002165 if (loader_platform_is_path(library_path)) {
Jon Ashburn86251302015-08-25 16:48:24 -06002166 // a relative or absolute path
Daniel Dadap00b4aba2015-09-30 11:50:51 -05002167 char *name_copy = loader_stack_alloc(strlen(file_str) + 1);
2168 char *rel_base;
Jon Ashburn86251302015-08-25 16:48:24 -06002169 strcpy(name_copy, file_str);
2170 rel_base = loader_platform_dirname(name_copy);
Daniel Dadap00b4aba2015-09-30 11:50:51 -05002171 loader_expand_path(library_path, rel_base, sizeof(fullpath), fullpath);
2172 } else {
2173 // a filename which is assumed in a system directory
2174 loader_get_fullpath(library_path, DEFAULT_VK_DRIVERS_PATH, sizeof(fullpath), fullpath);
Jon Ashburn86251302015-08-25 16:48:24 -06002175 }
Jon Ashburn005617f2015-11-17 17:35:40 -07002176
2177 uint32_t vers = 0;
2178 item = cJSON_GetObjectItem(itemICD, "api_version");
2179 if (item != NULL) {
2180 temp= cJSON_Print(item);
2181 vers = loader_make_version(temp);
2182 loader_tls_heap_free(temp);
2183 }
2184 loader_scanned_icd_add(inst, icds, fullpath, vers);
Jon Ashburn2077e382015-06-29 11:25:34 -06002185 }
Jon Ashburn005617f2015-11-17 17:35:40 -07002186 else
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002187 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 -06002188 }
2189 else
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002190 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 -06002191
Jon Ashburne39a4f82015-08-28 13:38:21 -06002192 loader_heap_free(inst, file_str);
Jon Ashburn2077e382015-06-29 11:25:34 -06002193 cJSON_Delete(json);
2194 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06002195 loader_heap_free(inst, manifest_files.filename_list);
Jon Ashburn6461ef22015-09-22 13:11:00 -06002196 loader_platform_thread_unlock_mutex(&loader_json_lock);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08002197}
2198
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002199
Jon Ashburne39a4f82015-08-28 13:38:21 -06002200void loader_layer_scan(
2201 const struct loader_instance *inst,
2202 struct loader_layer_list *instance_layers,
2203 struct loader_layer_list *device_layers)
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002204{
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002205 char *file_str;
Jon Ashburn075ce432015-12-17 17:38:24 -07002206 struct loader_manifest_files manifest_files[2]; // [0] = explicit, [1] = implicit
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002207 cJSON *json;
2208 uint32_t i;
Jon Ashburn075ce432015-12-17 17:38:24 -07002209 uint32_t implicit;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002210
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002211 // Get a list of manifest files for layers
Jon Ashburn075ce432015-12-17 17:38:24 -07002212 loader_get_manifest_files(inst, LAYERS_PATH_ENV, true, DEFAULT_VK_ELAYERS_INFO,
2213 &manifest_files[0]);
Jon Ashburnb1a03e02015-12-24 13:58:35 -07002214 // Pass NULL for environment variable override - implicit layers are not overridden by LAYERS_PATH_ENV
2215 loader_get_manifest_files(inst, NULL, true, DEFAULT_VK_ILAYERS_INFO,
Jon Ashburn075ce432015-12-17 17:38:24 -07002216 &manifest_files[1]);
2217 if (manifest_files[0].count == 0 && manifest_files[1].count == 0)
Courtney Goeltzenleuchter57985ce2014-12-01 09:29:42 -07002218 return;
Jon Ashburn90c6a0e2015-06-04 15:30:58 -06002219
Jon Ashburne13ecc92015-08-03 17:19:30 -06002220#if 0 //TODO
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002221 /**
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -06002222 * We need a list of the layer libraries, not just a list of
2223 * the layer properties (a layer library could expose more than
2224 * one layer property). This list of scanned layers would be
2225 * used to check for global and physicaldevice layer properties.
2226 */
2227 if (!loader_init_layer_library_list(&loader.scanned_layer_libraries)) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002228 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburne39a4f82015-08-28 13:38:21 -06002229 "Alloc for layer list failed: %s line: %d", __FILE__, __LINE__);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -06002230 return;
Jon Ashburn5ef20602015-07-02 09:40:15 -06002231 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002232#endif
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002233
Jon Ashburne13ecc92015-08-03 17:19:30 -06002234 /* cleanup any previously scanned libraries */
Jon Ashburne39a4f82015-08-28 13:38:21 -06002235 loader_delete_layer_properties(inst, instance_layers);
2236 loader_delete_layer_properties(inst, device_layers);
Jon Ashburnb2ef1372015-07-16 17:19:31 -06002237
Jon Ashburn6461ef22015-09-22 13:11:00 -06002238 loader_platform_thread_lock_mutex(&loader_json_lock);
Jon Ashburn075ce432015-12-17 17:38:24 -07002239 for (implicit = 0; implicit < 2; implicit++) {
2240 for (i = 0; i < manifest_files[implicit].count; i++) {
2241 file_str = manifest_files[implicit].filename_list[i];
2242 if (file_str == NULL)
2243 continue;
Courtney Goeltzenleuchtera9e4af42015-06-01 14:49:17 -06002244
Jon Ashburn075ce432015-12-17 17:38:24 -07002245 // parse file into JSON struct
2246 json = loader_get_json(inst, file_str);
2247 if (!json) {
2248 continue;
2249 }
2250
2251 //TODO error if device layers expose instance_extensions
2252 //TODO error if instance layers expose device extensions
2253 loader_add_layer_properties(inst,
2254 instance_layers,
2255 device_layers,
2256 json,
2257 (implicit == 1),
2258 file_str);
2259
2260 loader_heap_free(inst, file_str);
2261 cJSON_Delete(json);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002262 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002263 }
Jon Ashburn075ce432015-12-17 17:38:24 -07002264 if (manifest_files[0].count != 0)
2265 loader_heap_free(inst, manifest_files[0].filename_list);
2266
2267 if (manifest_files[1].count != 0)
2268 loader_heap_free(inst, manifest_files[1].filename_list);
Jon Ashburn6461ef22015-09-22 13:11:00 -06002269 loader_platform_thread_unlock_mutex(&loader_json_lock);
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002270}
2271
Chia-I Wu9ab61502015-11-06 06:42:02 +08002272static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL loader_gpa_instance_internal(VkInstance inst, const char * pName)
Jon Ashburn27cd5842015-05-12 17:26:48 -06002273{
2274 // inst is not wrapped
2275 if (inst == VK_NULL_HANDLE) {
2276 return NULL;
2277 }
2278 VkLayerInstanceDispatchTable* disp_table = * (VkLayerInstanceDispatchTable **) inst;
2279 void *addr;
2280
Jon Ashburn8fd08252015-05-28 16:25:02 -06002281 if (!strcmp(pName, "vkGetInstanceProcAddr"))
2282 return (void *) loader_gpa_instance_internal;
2283
Jon Ashburn27cd5842015-05-12 17:26:48 -06002284 if (disp_table == NULL)
2285 return NULL;
2286
2287 addr = loader_lookup_instance_dispatch_table(disp_table, pName);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002288 if (addr) {
Jon Ashburn27cd5842015-05-12 17:26:48 -06002289 return addr;
Jon Ashburn3d526cb2015-04-13 18:10:06 -06002290 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002291
2292 if (disp_table->GetInstanceProcAddr == NULL) {
2293 return NULL;
2294 }
2295 return disp_table->GetInstanceProcAddr(inst, pName);
Jon Ashburn3d526cb2015-04-13 18:10:06 -06002296}
2297
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002298/**
2299 * Initialize device_ext dispatch table entry as follows:
2300 * If dev == NULL find all logical devices created within this instance and
2301 * init the entry (given by idx) in the ext dispatch table.
2302 * If dev != NULL only initialize the entry in the given dev's dispatch table.
2303 * The initialization value is gotten by calling down the device chain with GDPA.
2304 * If GDPA returns NULL then don't initialize the dispatch table entry.
2305 */
2306static void loader_init_dispatch_dev_ext_entry(struct loader_instance *inst,
2307 struct loader_device *dev,
2308 uint32_t idx,
2309 const char *funcName)
2310
2311 {
2312 void *gdpa_value;
2313 if (dev != NULL) {
2314 gdpa_value = dev->loader_dispatch.core_dispatch.GetDeviceProcAddr(
2315 dev->device, funcName);
2316 if (gdpa_value != NULL)
2317 dev->loader_dispatch.ext_dispatch.DevExt[idx] = (PFN_vkDevExt) gdpa_value;
2318 } else {
2319 for (uint32_t i = 0; i < inst->total_icd_count; i++) {
2320 struct loader_icd *icd = &inst->icds[i];
2321 struct loader_device *dev = icd->logical_device_list;
2322 while (dev) {
2323 gdpa_value = dev->loader_dispatch.core_dispatch.GetDeviceProcAddr(
2324 dev->device, funcName);
2325 if (gdpa_value != NULL)
2326 dev->loader_dispatch.ext_dispatch.DevExt[idx] =
2327 (PFN_vkDevExt) gdpa_value;
2328 dev = dev->next;
2329 }
2330 }
2331 }
2332
2333}
2334
2335/**
2336 * Find all dev extension in the hash table and initialize the dispatch table
2337 * for dev for each of those extension entrypoints found in hash table.
2338
2339 */
2340static void loader_init_dispatch_dev_ext(struct loader_instance *inst,
2341 struct loader_device *dev)
2342{
2343 for (uint32_t i = 0; i < MAX_NUM_DEV_EXTS; i++) {
2344 if (inst->disp_hash[i].func_name != NULL)
2345 loader_init_dispatch_dev_ext_entry(inst, dev, i,
2346 inst->disp_hash[i].func_name);
2347 }
2348}
2349
2350static bool loader_check_icds_for_address(struct loader_instance *inst,
2351 const char *funcName)
2352{
2353 struct loader_icd *icd;
2354 icd = inst->icds;
2355 while (icd) {
2356 if (icd->this_icd_lib->GetInstanceProcAddr(icd->instance, funcName))
2357 // this icd supports funcName
2358 return true;
2359 icd = icd->next;
2360 }
2361
2362 return false;
2363}
2364
2365static void loader_free_dev_ext_table(struct loader_instance *inst)
2366{
2367 for (uint32_t i = 0; i < MAX_NUM_DEV_EXTS; i++) {
2368 loader_heap_free(inst, inst->disp_hash[i].func_name);
2369 loader_heap_free(inst, inst->disp_hash[i].list.index);
2370
2371 }
2372 memset(inst->disp_hash, 0, sizeof(inst->disp_hash));
2373}
2374
2375static bool loader_add_dev_ext_table(struct loader_instance *inst,
2376 uint32_t *ptr_idx,
2377 const char *funcName)
2378{
2379 uint32_t i;
2380 uint32_t idx = *ptr_idx;
2381 struct loader_dispatch_hash_list *list = &inst->disp_hash[idx].list;
2382
2383 if (!inst->disp_hash[idx].func_name) {
2384 // no entry here at this idx, so use it
2385 assert(list->capacity == 0);
2386 inst->disp_hash[idx].func_name = (char *) loader_heap_alloc(inst,
2387 strlen(funcName) + 1,
2388 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
2389 if (inst->disp_hash[idx].func_name == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002390 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002391 "loader_add_dev_ext_table() can't allocate memory for func_name");
2392 return false;
2393 }
2394 strncpy(inst->disp_hash[idx].func_name, funcName, strlen(funcName) + 1);
2395 return true;
2396 }
2397
2398 // check for enough capacity
2399 if (list->capacity == 0) {
2400 list->index = loader_heap_alloc(inst, 8 * sizeof(*(list->index)),
2401 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
2402 if (list->index == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002403 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002404 "loader_add_dev_ext_table() can't allocate list memory");
2405 return false;
2406 }
2407 list->capacity = 8 * sizeof(*(list->index));
2408 } else if (list->capacity < (list->count + 1) * sizeof(*(list->index))) {
2409 list->index = loader_heap_realloc(inst, list->index, list->capacity,
2410 list->capacity * 2,
2411 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
2412 if (list->index == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002413 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002414 "loader_add_dev_ext_table() can't reallocate list memory");
2415 return false;
2416 }
2417 list->capacity *= 2;
2418 }
2419
2420 //find an unused index in the hash table and use it
2421 i = (idx + 1) % MAX_NUM_DEV_EXTS;
2422 do {
2423 if (!inst->disp_hash[i].func_name) {
2424 assert(inst->disp_hash[i].list.capacity == 0);
2425 inst->disp_hash[i].func_name = (char *) loader_heap_alloc(inst,
2426 strlen(funcName) + 1,
2427 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
2428 if (inst->disp_hash[i].func_name == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002429 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002430 "loader_add_dev_ext_table() can't rallocate func_name memory");
2431 return false;
2432 }
2433 strncpy(inst->disp_hash[i].func_name, funcName, strlen(funcName) + 1);
2434 list->index[list->count] = i;
2435 list->count++;
2436 *ptr_idx = i;
2437 return true;
2438 }
2439 i = (i + 1) % MAX_NUM_DEV_EXTS;
2440 } while (i != idx);
2441
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002442 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002443 "loader_add_dev_ext_table() couldn't insert into hash table; is it full?");
2444 return false;
2445}
2446
2447static bool loader_name_in_dev_ext_table(struct loader_instance *inst,
2448 uint32_t *idx,
2449 const char *funcName)
2450{
2451 uint32_t alt_idx;
2452 if (inst->disp_hash[*idx].func_name && !strcmp(
2453 inst->disp_hash[*idx].func_name,
2454 funcName))
2455 return true;
2456
2457 // funcName wasn't at the primary spot in the hash table
2458 // search the list of secondary locations (shallow search, not deep search)
2459 for (uint32_t i = 0; i < inst->disp_hash[*idx].list.count; i++) {
2460 alt_idx = inst->disp_hash[*idx].list.index[i];
2461 if (!strcmp(inst->disp_hash[*idx].func_name, funcName)) {
2462 *idx = alt_idx;
2463 return true;
2464 }
2465 }
2466
2467 return false;
2468}
2469
2470/**
2471 * This function returns generic trampoline code address for unknown entry points.
2472 * Presumably, these unknown entry points (as given by funcName) are device
2473 * extension entrypoints. A hash table is used to keep a list of unknown entry
2474 * points and their mapping to the device extension dispatch table
2475 * (struct loader_dev_ext_dispatch_table).
2476 * \returns
2477 * For a given entry point string (funcName), if an existing mapping is found the
2478 * trampoline address for that mapping is returned. Otherwise, this unknown entry point
2479 * has not been seen yet. Next check if a layer or ICD supports it. If so then a
2480 * new entry in the hash table is initialized and that trampoline address for
2481 * the new entry is returned. Null is returned if the hash table is full or
2482 * if no discovered layer or ICD returns a non-NULL GetProcAddr for it.
2483 */
2484void *loader_dev_ext_gpa(struct loader_instance *inst,
2485 const char *funcName)
2486{
2487 uint32_t idx;
2488 uint32_t seed = 0;
2489
2490 idx = murmurhash(funcName, strlen(funcName), seed) % MAX_NUM_DEV_EXTS;
2491
2492 if (loader_name_in_dev_ext_table(inst, &idx, funcName))
2493 // found funcName already in hash
2494 return loader_get_dev_ext_trampoline(idx);
2495
2496 // Check if funcName is supported in either ICDs or a layer library
2497 if (!loader_check_icds_for_address(inst, funcName)) {
2498 // TODO Add check in layer libraries for support of address
2499 // if support found in layers continue on
2500 return NULL;
2501 }
2502
2503 if (loader_add_dev_ext_table(inst, &idx, funcName)) {
2504 // successfully added new table entry
2505 // init any dev dispatch table entrys as needed
2506 loader_init_dispatch_dev_ext_entry(inst, NULL, idx, funcName);
2507 return loader_get_dev_ext_trampoline(idx);
2508 }
2509
2510 return NULL;
2511}
2512
Jon Ashburne0e64572015-09-30 12:56:42 -06002513struct loader_instance *loader_get_instance(const VkInstance instance)
2514{
2515 /* look up the loader_instance in our list by comparing dispatch tables, as
2516 * there is no guarantee the instance is still a loader_instance* after any
2517 * layers which wrap the instance object.
2518 */
2519 const VkLayerInstanceDispatchTable *disp;
2520 struct loader_instance *ptr_instance = NULL;
2521 disp = loader_get_instance_dispatch(instance);
2522 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
2523 if (inst->disp == disp) {
2524 ptr_instance = inst;
2525 break;
2526 }
2527 }
2528 return ptr_instance;
2529}
2530
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002531static loader_platform_dl_handle loader_add_layer_lib(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002532 const struct loader_instance *inst,
Jon Ashburn4f67d742015-05-27 13:19:22 -06002533 const char *chain_type,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002534 struct loader_layer_properties *layer_prop)
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002535{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002536 struct loader_lib_info *new_layer_lib_list, *my_lib;
Jon Ashburne39a4f82015-08-28 13:38:21 -06002537 size_t new_alloc_size;
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -06002538 /*
2539 * TODO: We can now track this information in the
2540 * scanned_layer_libraries list.
2541 */
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002542 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) {
Jon Ashburn3d002332015-08-20 16:35:30 -06002543 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, layer_prop->lib_name) == 0) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002544 /* Have already loaded this library, just increment ref count */
2545 loader.loaded_layer_lib_list[i].ref_count++;
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002546 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002547 "%s Chain: Increment layer reference count for layer library %s",
Jon Ashburn3d002332015-08-20 16:35:30 -06002548 chain_type, layer_prop->lib_name);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002549 return loader.loaded_layer_lib_list[i].lib_handle;
2550 }
2551 }
2552
2553 /* Haven't seen this library so load it */
Jon Ashburne39a4f82015-08-28 13:38:21 -06002554 new_alloc_size = 0;
2555 if (loader.loaded_layer_lib_capacity == 0)
2556 new_alloc_size = 8 * sizeof(struct loader_lib_info);
2557 else if (loader.loaded_layer_lib_capacity <= loader.loaded_layer_lib_count *
2558 sizeof(struct loader_lib_info))
2559 new_alloc_size = loader.loaded_layer_lib_capacity * 2;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002560
Jon Ashburne39a4f82015-08-28 13:38:21 -06002561 if (new_alloc_size) {
2562 new_layer_lib_list = loader_heap_realloc(
2563 inst, loader.loaded_layer_lib_list,
2564 loader.loaded_layer_lib_capacity,
2565 new_alloc_size,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002566 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburne39a4f82015-08-28 13:38:21 -06002567 if (!new_layer_lib_list) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002568 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 -06002569 return NULL;
2570 }
2571 loader.loaded_layer_lib_capacity = new_alloc_size;
Courtney Goeltzenleuchter54ce81a2015-12-09 12:26:34 -07002572 loader.loaded_layer_lib_list = new_layer_lib_list;
Jon Ashburne39a4f82015-08-28 13:38:21 -06002573 } else
2574 new_layer_lib_list = loader.loaded_layer_lib_list;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002575 my_lib = &new_layer_lib_list[loader.loaded_layer_lib_count];
2576
Jon Ashburn3d002332015-08-20 16:35:30 -06002577 strncpy(my_lib->lib_name, layer_prop->lib_name, sizeof(my_lib->lib_name));
2578 my_lib->lib_name[sizeof(my_lib->lib_name) - 1] = '\0';
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002579 my_lib->ref_count = 0;
2580 my_lib->lib_handle = NULL;
2581
2582 if ((my_lib->lib_handle = loader_platform_open_library(my_lib->lib_name)) == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002583 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002584 loader_platform_open_library_error(my_lib->lib_name));
2585 return NULL;
2586 } else {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002587 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002588 "Chain: %s: Loading layer library %s",
Jon Ashburn3d002332015-08-20 16:35:30 -06002589 chain_type, layer_prop->lib_name);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002590 }
2591 loader.loaded_layer_lib_count++;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002592 my_lib->ref_count++;
2593
2594 return my_lib->lib_handle;
2595}
2596
2597static void loader_remove_layer_lib(
2598 struct loader_instance *inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002599 struct loader_layer_properties *layer_prop)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002600{
Courtney Goeltzenleuchter80bfd0e2015-12-17 09:51:22 -07002601 uint32_t idx = loader.loaded_layer_lib_count;
Tony Barbourb5d2c942015-07-14 13:34:05 -06002602 struct loader_lib_info *new_layer_lib_list, *my_lib = NULL;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002603
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002604 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) {
Jon Ashburn3d002332015-08-20 16:35:30 -06002605 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, layer_prop->lib_name) == 0) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002606 /* found matching library */
2607 idx = i;
2608 my_lib = &loader.loaded_layer_lib_list[i];
2609 break;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002610 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002611 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002612
Courtney Goeltzenleuchter80bfd0e2015-12-17 09:51:22 -07002613 if (idx == loader.loaded_layer_lib_count) {
Jon Ashburn6766ae92015-12-17 14:30:21 -07002614 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Courtney Goeltzenleuchter80bfd0e2015-12-17 09:51:22 -07002615 "Unable to unref library %s", layer_prop->lib_name);
2616 return;
2617 }
2618
Tony Barbourb5d2c942015-07-14 13:34:05 -06002619 if (my_lib) {
2620 my_lib->ref_count--;
2621 if (my_lib->ref_count > 0) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002622 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
Jon Ashburn3d002332015-08-20 16:35:30 -06002623 "Decrement reference count for layer library %s", layer_prop->lib_name);
Tony Barbourb5d2c942015-07-14 13:34:05 -06002624 return;
2625 }
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07002626 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002627 loader_platform_close_library(my_lib->lib_handle);
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002628 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
Jon Ashburn3d002332015-08-20 16:35:30 -06002629 "Unloading layer library %s", layer_prop->lib_name);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002630
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002631 /* Need to remove unused library from list */
Jon Ashburne39a4f82015-08-28 13:38:21 -06002632 new_layer_lib_list = loader_heap_alloc(inst,
2633 loader.loaded_layer_lib_capacity,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002634 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002635 if (!new_layer_lib_list) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002636 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 -06002637 return;
2638 }
2639
2640 if (idx > 0) {
2641 /* Copy records before idx */
2642 memcpy(new_layer_lib_list, &loader.loaded_layer_lib_list[0],
2643 sizeof(struct loader_lib_info) * idx);
2644 }
2645 if (idx < (loader.loaded_layer_lib_count - 1)) {
2646 /* Copy records after idx */
2647 memcpy(&new_layer_lib_list[idx], &loader.loaded_layer_lib_list[idx+1],
2648 sizeof(struct loader_lib_info) * (loader.loaded_layer_lib_count - idx - 1));
2649 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002650
Jon Ashburne39a4f82015-08-28 13:38:21 -06002651 loader_heap_free(inst, loader.loaded_layer_lib_list);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002652 loader.loaded_layer_lib_count--;
2653 loader.loaded_layer_lib_list = new_layer_lib_list;
Jon Ashburnb8358052014-11-18 09:06:04 -07002654}
2655
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002656
2657/**
2658 * Go through the search_list and find any layers which match type. If layer
2659 * type match is found in then add it to ext_list.
2660 */
Jon Ashburn0c26e712015-07-02 16:10:32 -06002661static void loader_add_layer_implicit(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002662 const struct loader_instance *inst,
Jon Ashburn0c26e712015-07-02 16:10:32 -06002663 const enum layer_type type,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002664 struct loader_layer_list *list,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002665 const struct loader_layer_list *search_list)
Jon Ashburn0c26e712015-07-02 16:10:32 -06002666{
Jon Ashburn075ce432015-12-17 17:38:24 -07002667 bool enable;
2668 char *env_value;
Jon Ashburn0c26e712015-07-02 16:10:32 -06002669 uint32_t i;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002670 for (i = 0; i < search_list->count; i++) {
2671 const struct loader_layer_properties *prop = &search_list->list[i];
Jon Ashburn0c26e712015-07-02 16:10:32 -06002672 if (prop->type & type) {
Jon Ashburn075ce432015-12-17 17:38:24 -07002673 /* Found an implicit layer, see if it should be enabled */
2674 enable = false;
2675
2676 // if no enable_environment variable is specified, this implicit layer
2677 // should always be enabled. Otherwise check if the variable is set
2678 if (prop->enable_env_var.name[0] == 0) {
2679 enable = true;
2680 } else {
Jon Ashburn38a497f2016-01-04 14:01:38 -07002681 env_value = loader_getenv(prop->enable_env_var.name);
Jon Ashburn075ce432015-12-17 17:38:24 -07002682 if (env_value && !strcmp(prop->enable_env_var.value, env_value))
2683 enable = true;
Jon Ashburn38a497f2016-01-04 14:01:38 -07002684 loader_free_getenv(env_value);
Jon Ashburn075ce432015-12-17 17:38:24 -07002685 }
2686
2687 // disable_environment has priority, i.e. if both enable and disable
2688 // environment variables are set, the layer is disabled. Implicit layers
2689 // are required to have a disable_environment variables
Jon Ashburn38a497f2016-01-04 14:01:38 -07002690 env_value = loader_getenv(prop->disable_env_var.name);
Jon Ashburn075ce432015-12-17 17:38:24 -07002691 if (env_value)
2692 enable = false;
Jon Ashburn38a497f2016-01-04 14:01:38 -07002693 loader_free_getenv(env_value);
Jon Ashburn075ce432015-12-17 17:38:24 -07002694
2695 if (enable)
2696 loader_add_to_layer_list(inst, list, 1, prop);
Jon Ashburn0c26e712015-07-02 16:10:32 -06002697 }
2698 }
2699
2700}
2701
2702/**
2703 * Get the layer name(s) from the env_name environment variable. If layer
Jon Ashburnbd332cc2015-07-07 10:27:45 -06002704 * is found in search_list then add it to layer_list. But only add it to
2705 * layer_list if type matches.
Jon Ashburn0c26e712015-07-02 16:10:32 -06002706 */
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002707static void loader_add_layer_env(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002708 const struct loader_instance *inst,
Jon Ashburnbd332cc2015-07-07 10:27:45 -06002709 const enum layer_type type,
Jon Ashburneb6d5682015-07-02 14:10:53 -06002710 const char *env_name,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002711 struct loader_layer_list *layer_list,
2712 const struct loader_layer_list *search_list)
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002713{
Ian Elliott4470a302015-02-17 10:33:47 -07002714 char *layerEnv;
Jon Ashburneb6d5682015-07-02 14:10:53 -06002715 char *next, *name;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002716
Jon Ashburn38a497f2016-01-04 14:01:38 -07002717 layerEnv = loader_getenv(env_name);
Ian Elliott4470a302015-02-17 10:33:47 -07002718 if (layerEnv == NULL) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002719 return;
Ian Elliott4470a302015-02-17 10:33:47 -07002720 }
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -06002721 name = loader_stack_alloc(strlen(layerEnv) + 1);
Jon Ashburneb6d5682015-07-02 14:10:53 -06002722 if (name == NULL) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002723 return;
Ian Elliott4470a302015-02-17 10:33:47 -07002724 }
Jon Ashburneb6d5682015-07-02 14:10:53 -06002725 strcpy(name, layerEnv);
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002726
Jon Ashburn38a497f2016-01-04 14:01:38 -07002727 loader_free_getenv(layerEnv);
2728
Jon Ashburneb6d5682015-07-02 14:10:53 -06002729 while (name && *name ) {
2730 next = loader_get_next_path(name);
Jon Ashburne39a4f82015-08-28 13:38:21 -06002731 loader_find_layer_name_add_list(inst, name, type, search_list, layer_list);
Jon Ashburneb6d5682015-07-02 14:10:53 -06002732 name = next;
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07002733 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002734
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002735 return;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002736}
2737
Courtney Goeltzenleuchter7d0023c2015-06-08 15:09:22 -06002738void loader_deactivate_instance_layers(struct loader_instance *instance)
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002739{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002740 /* Create instance chain of enabled layers */
Courtney Goeltzenleuchter7d0023c2015-06-08 15:09:22 -06002741 for (uint32_t i = 0; i < instance->activated_layer_list.count; i++) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002742 struct loader_layer_properties *layer_prop = &instance->activated_layer_list.list[i];
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002743
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002744 loader_remove_layer_lib(instance, layer_prop);
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002745 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06002746 loader_destroy_layer_list(instance, &instance->activated_layer_list);
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002747}
2748
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002749VkResult loader_enable_instance_layers(
Jon Ashburnb82c1852015-08-11 14:49:54 -06002750 struct loader_instance *inst,
2751 const VkInstanceCreateInfo *pCreateInfo,
2752 const struct loader_layer_list *instance_layers)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002753{
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002754 VkResult err;
2755
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06002756 assert(inst && "Cannot have null instance");
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002757
Jon Ashburne39a4f82015-08-28 13:38:21 -06002758 if (!loader_init_layer_list(inst, &inst->activated_layer_list)) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002759 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Failed to alloc Instance activated layer list");
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002760 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002761 }
2762
Jon Ashburn0c26e712015-07-02 16:10:32 -06002763 /* Add any implicit layers first */
2764 loader_add_layer_implicit(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002765 inst,
Jon Ashburn0c26e712015-07-02 16:10:32 -06002766 VK_LAYER_TYPE_INSTANCE_IMPLICIT,
2767 &inst->activated_layer_list,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002768 instance_layers);
Jon Ashburn0c26e712015-07-02 16:10:32 -06002769
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002770 /* Add any layers specified via environment variable next */
Jon Ashburneb6d5682015-07-02 14:10:53 -06002771 loader_add_layer_env(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002772 inst,
Jon Ashburnbd332cc2015-07-07 10:27:45 -06002773 VK_LAYER_TYPE_INSTANCE_EXPLICIT,
Jon Ashburneb6d5682015-07-02 14:10:53 -06002774 "VK_INSTANCE_LAYERS",
2775 &inst->activated_layer_list,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002776 instance_layers);
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002777
2778 /* Add layers specified by the application */
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002779 err = loader_add_layer_names_to_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002780 inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002781 &inst->activated_layer_list,
Chia-I Wud50a7d72015-10-26 20:48:51 +08002782 pCreateInfo->enabledLayerNameCount,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002783 pCreateInfo->ppEnabledLayerNames,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002784 instance_layers);
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002785
2786 return err;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002787}
2788
Jon Ashburn27cd5842015-05-12 17:26:48 -06002789uint32_t loader_activate_instance_layers(struct loader_instance *inst)
2790{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002791 uint32_t layer_idx;
Jon Ashburn128f9422015-05-28 19:16:58 -06002792 VkBaseLayerObject *wrappedInstance;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002793
David Pinedoa0a8a242015-06-24 15:29:18 -06002794 if (inst == NULL) {
Jon Ashburn27cd5842015-05-12 17:26:48 -06002795 return 0;
David Pinedoa0a8a242015-06-24 15:29:18 -06002796 }
Jon Ashburn27cd5842015-05-12 17:26:48 -06002797
2798 // NOTE inst is unwrapped at this point in time
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002799 void* baseObj = (void*) inst;
2800 void* nextObj = (void*) inst;
Jon Ashburn27cd5842015-05-12 17:26:48 -06002801 VkBaseLayerObject *nextInstObj;
2802 PFN_vkGetInstanceProcAddr nextGPA = loader_gpa_instance_internal;
2803
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002804 if (!inst->activated_layer_list.count) {
Courtney Goeltzenleuchtered1a8dd2015-08-07 09:53:18 -06002805 loader_init_instance_core_dispatch_table(inst->disp, nextGPA, (VkInstance) nextObj, (VkInstance) baseObj);
Jon Ashburn27cd5842015-05-12 17:26:48 -06002806 return 0;
2807 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002808
Courtney Goeltzenleuchter6f460c52015-07-06 09:04:55 -06002809 wrappedInstance = loader_stack_alloc(sizeof(VkBaseLayerObject)
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002810 * inst->activated_layer_list.count);
Jon Ashburn128f9422015-05-28 19:16:58 -06002811 if (!wrappedInstance) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002812 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Failed to alloc Instance objects for layer");
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002813 return 0;
2814 }
2815
2816 /* Create instance chain of enabled layers */
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002817 layer_idx = inst->activated_layer_list.count - 1;
Courtney Goeltzenleuchter0f1d8eb2015-06-07 17:28:17 -06002818 for (int32_t i = inst->activated_layer_list.count - 1; i >= 0; i--) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002819 struct loader_layer_properties *layer_prop = &inst->activated_layer_list.list[i];
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002820 loader_platform_dl_handle lib_handle;
2821
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002822 /*
Courtney Goeltzenleuchteree3b16a2015-06-01 14:12:42 -06002823 * Note: An extension's Get*ProcAddr should not return a function pointer for
2824 * any extension entry points until the extension has been enabled.
2825 * To do this requires a different behavior from Get*ProcAddr functions implemented
2826 * in layers.
2827 * The very first call to a layer will be it's Get*ProcAddr function requesting
Tobin Ehlis1cb7f572015-10-06 09:09:24 -06002828 * the layer's vkGet*ProcAddr. The layer should initialize its internal dispatch table
Courtney Goeltzenleuchteree3b16a2015-06-01 14:12:42 -06002829 * with the wrapped object given (either Instance or Device) and return the layer's
2830 * Get*ProcAddr function. The layer should also use this opportunity to record the
2831 * baseObject so that it can find the correct local dispatch table on future calls.
2832 * Subsequent calls to Get*ProcAddr, CreateInstance, CreateDevice
2833 * will not use a wrapped object and must look up their local dispatch table from
2834 * the given baseObject.
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002835 */
Jon Ashburn128f9422015-05-28 19:16:58 -06002836 nextInstObj = (wrappedInstance + layer_idx);
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002837 nextInstObj->pGPA = (PFN_vkGPA) nextGPA;
Jon Ashburn27cd5842015-05-12 17:26:48 -06002838 nextInstObj->baseObject = baseObj;
2839 nextInstObj->nextObject = nextObj;
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002840 nextObj = (void*) nextInstObj;
Jon Ashburn27cd5842015-05-12 17:26:48 -06002841
Jon Ashburne39a4f82015-08-28 13:38:21 -06002842 lib_handle = loader_add_layer_lib(inst, "instance", layer_prop);
Jon Ashburnf72a04b2015-11-25 17:55:49 -07002843 if (!lib_handle)
2844 continue; // TODO what should we do in this case
Jon Ashburn21c21ee2015-09-09 11:29:24 -06002845 if ((nextGPA = layer_prop->functions.get_instance_proc_addr) == NULL) {
2846 if (layer_prop->functions.str_gipa == NULL || strlen(layer_prop->functions.str_gipa) == 0) {
2847 nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetInstanceProcAddr");
2848 layer_prop->functions.get_instance_proc_addr = nextGPA;
2849 } else
2850 nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gipa);
2851 if (!nextGPA) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002852 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 -06002853
Jon Ashburn21c21ee2015-09-09 11:29:24 -06002854 /* TODO: Should we return nextObj, nextGPA to previous? or decrement layer_list count*/
2855 continue;
2856 }
Jon Ashburn27cd5842015-05-12 17:26:48 -06002857 }
2858
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002859 loader_log(inst, VK_DEBUG_REPORT_INFO_BIT_EXT, 0,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002860 "Insert instance layer %s (%s)",
2861 layer_prop->info.layerName,
Jon Ashburn3d002332015-08-20 16:35:30 -06002862 layer_prop->lib_name);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002863
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002864 layer_idx--;
Jon Ashburn27cd5842015-05-12 17:26:48 -06002865 }
2866
Jon Ashburn8fd08252015-05-28 16:25:02 -06002867 loader_init_instance_core_dispatch_table(inst->disp, nextGPA, (VkInstance) nextObj, (VkInstance) baseObj);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002868
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002869 return inst->activated_layer_list.count;
Jon Ashburn27cd5842015-05-12 17:26:48 -06002870}
2871
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002872void loader_activate_instance_layer_extensions(struct loader_instance *inst)
2873{
2874
2875 loader_init_instance_extension_dispatch_table(inst->disp,
2876 inst->disp->GetInstanceProcAddr,
Jon Ashburn128f9422015-05-28 19:16:58 -06002877 (VkInstance) inst);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002878}
2879
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002880static VkResult loader_enable_device_layers(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002881 const struct loader_instance *inst,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002882 struct loader_icd *icd,
2883 struct loader_device *dev,
2884 const VkDeviceCreateInfo *pCreateInfo,
2885 const struct loader_layer_list *device_layers)
2886
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002887{
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002888 VkResult err;
2889
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06002890 assert(dev && "Cannot have null device");
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002891
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002892 if (dev->activated_layer_list.list == NULL || dev->activated_layer_list.capacity == 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06002893 loader_init_layer_list(inst, &dev->activated_layer_list);
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002894 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002895
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002896 if (dev->activated_layer_list.list == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002897 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Failed to alloc device activated layer list");
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002898 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002899 }
2900
Jon Ashburn0c26e712015-07-02 16:10:32 -06002901 /* Add any implicit layers first */
2902 loader_add_layer_implicit(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002903 inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002904 VK_LAYER_TYPE_DEVICE_IMPLICIT,
2905 &dev->activated_layer_list,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002906 device_layers);
Jon Ashburn0c26e712015-07-02 16:10:32 -06002907
2908 /* Add any layers specified via environment variable next */
Jon Ashburneb6d5682015-07-02 14:10:53 -06002909 loader_add_layer_env(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002910 inst,
Jon Ashburnbd332cc2015-07-07 10:27:45 -06002911 VK_LAYER_TYPE_DEVICE_EXPLICIT,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002912 "VK_DEVICE_LAYERS",
2913 &dev->activated_layer_list,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002914 device_layers);
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002915
2916 /* Add layers specified by the application */
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002917 err = loader_add_layer_names_to_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002918 inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002919 &dev->activated_layer_list,
Chia-I Wud50a7d72015-10-26 20:48:51 +08002920 pCreateInfo->enabledLayerNameCount,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002921 pCreateInfo->ppEnabledLayerNames,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002922 device_layers);
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002923
2924 return err;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002925}
2926
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002927/*
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06002928 * This function terminates the device chain for CreateDevice.
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002929 * CreateDevice is a special case and so the loader call's
2930 * the ICD's CreateDevice before creating the chain. Since
2931 * we can't call CreateDevice twice we must terminate the
2932 * device chain with something else.
2933 */
Chia-I Wu9ab61502015-11-06 06:42:02 +08002934static VKAPI_ATTR VkResult VKAPI_CALL scratch_vkCreateDevice(
Jon Ashburn24cd4be2015-11-01 14:04:06 -07002935 VkPhysicalDevice physicalDevice,
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002936 const VkDeviceCreateInfo *pCreateInfo,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002937 const VkAllocationCallbacks* pAllocator,
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002938 VkDevice *pDevice)
2939{
2940 return VK_SUCCESS;
2941}
2942
Chia-I Wu9ab61502015-11-06 06:42:02 +08002943static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL loader_GetDeviceChainProcAddr(VkDevice device, const char * name)
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002944{
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002945 if (!strcmp(name, "vkGetDeviceProcAddr"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06002946 return (PFN_vkVoidFunction) loader_GetDeviceChainProcAddr;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002947 if (!strcmp(name, "vkCreateDevice"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06002948 return (PFN_vkVoidFunction) scratch_vkCreateDevice;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002949
Courtney Goeltzenleuchter3e029d12015-06-29 16:09:23 -06002950 struct loader_device *found_dev;
2951 struct loader_icd *icd = loader_get_icd_and_device(device, &found_dev);
2952 return icd->GetDeviceProcAddr(device, name);
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002953}
2954
Jon Ashburndc6fcad2015-06-10 10:06:06 -06002955static uint32_t loader_activate_device_layers(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002956 const struct loader_instance *inst,
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002957 struct loader_device *dev,
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -06002958 VkDevice device)
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002959{
David Pinedoa0a8a242015-06-24 15:29:18 -06002960 if (!dev) {
Jon Ashburndc6fcad2015-06-10 10:06:06 -06002961 return 0;
David Pinedoa0a8a242015-06-24 15:29:18 -06002962 }
Jon Ashburn94e70492015-06-10 10:13:10 -06002963
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002964 /* activate any layer libraries */
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002965 void* nextObj = (void*) device;
2966 void* baseObj = nextObj;
Jon Ashburn94e70492015-06-10 10:13:10 -06002967 VkBaseLayerObject *nextGpuObj;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002968 PFN_vkGetDeviceProcAddr nextGPA = loader_GetDeviceChainProcAddr;
Jon Ashburn94e70492015-06-10 10:13:10 -06002969 VkBaseLayerObject *wrappedGpus;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002970
Courtney Goeltzenleuchtered1a8dd2015-08-07 09:53:18 -06002971 if (!dev->activated_layer_list.count) {
2972 loader_init_device_dispatch_table(&dev->loader_dispatch, nextGPA,
2973 (VkDevice) nextObj, (VkDevice) baseObj);
Jon Ashburn94e70492015-06-10 10:13:10 -06002974 return 0;
Courtney Goeltzenleuchtered1a8dd2015-08-07 09:53:18 -06002975 }
Jon Ashburn94e70492015-06-10 10:13:10 -06002976
Jon Ashburne39a4f82015-08-28 13:38:21 -06002977 wrappedGpus = loader_heap_alloc(inst,
2978 sizeof (VkBaseLayerObject) * dev->activated_layer_list.count,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002979 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn94e70492015-06-10 10:13:10 -06002980 if (!wrappedGpus) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002981 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Failed to alloc Gpu objects for layer");
Jon Ashburn94e70492015-06-10 10:13:10 -06002982 return 0;
2983 }
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002984
Jon Ashburn94e70492015-06-10 10:13:10 -06002985 for (int32_t i = dev->activated_layer_list.count - 1; i >= 0; i--) {
2986
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002987 struct loader_layer_properties *layer_prop = &dev->activated_layer_list.list[i];
Jon Ashburn94e70492015-06-10 10:13:10 -06002988 loader_platform_dl_handle lib_handle;
2989
Jon Ashburn94e70492015-06-10 10:13:10 -06002990 nextGpuObj = (wrappedGpus + i);
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002991 nextGpuObj->pGPA = (PFN_vkGPA)nextGPA;
Jon Ashburn94e70492015-06-10 10:13:10 -06002992 nextGpuObj->baseObject = baseObj;
2993 nextGpuObj->nextObject = nextObj;
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002994 nextObj = (void*) nextGpuObj;
Jon Ashburn94e70492015-06-10 10:13:10 -06002995
Jon Ashburne39a4f82015-08-28 13:38:21 -06002996 lib_handle = loader_add_layer_lib(inst, "device", layer_prop);
Jon Ashburn21c21ee2015-09-09 11:29:24 -06002997 if ((nextGPA = layer_prop->functions.get_device_proc_addr) == NULL) {
2998 if (layer_prop->functions.str_gdpa == NULL || strlen(layer_prop->functions.str_gdpa) == 0) {
2999 nextGPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetDeviceProcAddr");
3000 layer_prop->functions.get_device_proc_addr = nextGPA;
3001 } else
3002 nextGPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gdpa);
3003 if (!nextGPA) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07003004 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 -06003005 continue;
3006 }
Jon Ashburn94e70492015-06-10 10:13:10 -06003007 }
3008
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07003009 loader_log(inst, VK_DEBUG_REPORT_INFO_BIT_EXT, 0,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003010 "Insert device layer library %s (%s)",
3011 layer_prop->info.layerName,
Jon Ashburn3d002332015-08-20 16:35:30 -06003012 layer_prop->lib_name);
Jon Ashburn94e70492015-06-10 10:13:10 -06003013
3014 }
3015
3016 loader_init_device_dispatch_table(&dev->loader_dispatch, nextGPA,
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06003017 (VkDevice) nextObj, (VkDevice) baseObj);
Jon Ashburne39a4f82015-08-28 13:38:21 -06003018 loader_heap_free(inst, wrappedGpus);
Jon Ashburn94e70492015-06-10 10:13:10 -06003019
Jon Ashburndc6fcad2015-06-10 10:06:06 -06003020 return dev->activated_layer_list.count;
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06003021}
Jon Ashburnd38bfb12014-10-14 19:15:22 -06003022
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003023VkResult loader_validate_layers(
3024 const uint32_t layer_count,
3025 const char * const *ppEnabledLayerNames,
Jon Ashburn3d002332015-08-20 16:35:30 -06003026 const struct loader_layer_list *list)
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06003027{
3028 struct loader_layer_properties *prop;
3029
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003030 for (uint32_t i = 0; i < layer_count; i++) {
Jon Ashburne13ecc92015-08-03 17:19:30 -06003031 prop = loader_get_layer_property(ppEnabledLayerNames[i],
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003032 list);
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06003033 if (!prop) {
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06003034 return VK_ERROR_LAYER_NOT_PRESENT;
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06003035 }
3036 }
3037
3038 return VK_SUCCESS;
3039}
3040
3041VkResult loader_validate_instance_extensions(
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003042 const struct loader_extension_list *icd_exts,
Jon Ashburnb82c1852015-08-11 14:49:54 -06003043 const struct loader_layer_list *instance_layer,
3044 const VkInstanceCreateInfo *pCreateInfo)
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06003045{
Jon Ashburn5c042ea2015-08-04 11:14:18 -06003046 VkExtensionProperties *extension_prop;
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003047 struct loader_layer_properties *layer_prop;
3048
Chia-I Wud50a7d72015-10-26 20:48:51 +08003049 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) {
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003050 extension_prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003051 icd_exts);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003052
3053 if (extension_prop) {
3054 continue;
3055 }
3056
3057 extension_prop = NULL;
3058
3059 /* Not in global list, search layer extension lists */
Chia-I Wud50a7d72015-10-26 20:48:51 +08003060 for (uint32_t j = 0; j < pCreateInfo->enabledLayerNameCount; j++) {
Jon Ashburne13ecc92015-08-03 17:19:30 -06003061 layer_prop = loader_get_layer_property(pCreateInfo->ppEnabledLayerNames[i],
Jon Ashburnb82c1852015-08-11 14:49:54 -06003062 instance_layer);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003063 if (!layer_prop) {
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003064 /* Should NOT get here, loader_validate_layers
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003065 * should have already filtered this case out.
3066 */
3067 continue;
3068 }
3069
3070 extension_prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
3071 &layer_prop->instance_extension_list);
3072 if (extension_prop) {
3073 /* Found the extension in one of the layers enabled by the app. */
3074 break;
3075 }
3076 }
3077
3078 if (!extension_prop) {
3079 /* Didn't find extension name in any of the global layers, error out */
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06003080 return VK_ERROR_EXTENSION_NOT_PRESENT;
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003081 }
3082 }
3083 return VK_SUCCESS;
3084}
3085
3086VkResult loader_validate_device_extensions(
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003087 struct loader_physical_device *phys_dev,
Jon Ashburnb82c1852015-08-11 14:49:54 -06003088 const struct loader_layer_list *device_layer,
3089 const VkDeviceCreateInfo *pCreateInfo)
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003090{
Jon Ashburn5c042ea2015-08-04 11:14:18 -06003091 VkExtensionProperties *extension_prop;
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003092 struct loader_layer_properties *layer_prop;
3093
Chia-I Wud50a7d72015-10-26 20:48:51 +08003094 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) {
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003095 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i];
3096 extension_prop = get_extension_property(extension_name,
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003097 &phys_dev->device_extension_cache);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003098
3099 if (extension_prop) {
3100 continue;
3101 }
3102
3103 /* Not in global list, search layer extension lists */
Chia-I Wud50a7d72015-10-26 20:48:51 +08003104 for (uint32_t j = 0; j < pCreateInfo->enabledLayerNameCount; j++) {
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003105 const char *layer_name = pCreateInfo->ppEnabledLayerNames[j];
Jon Ashburne13ecc92015-08-03 17:19:30 -06003106 layer_prop = loader_get_layer_property(layer_name,
Jon Ashburnb82c1852015-08-11 14:49:54 -06003107 device_layer);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003108
3109 if (!layer_prop) {
3110 /* Should NOT get here, loader_validate_instance_layers
3111 * should have already filtered this case out.
3112 */
3113 continue;
3114 }
3115
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07003116 extension_prop = get_dev_extension_property(extension_name,
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003117 &layer_prop->device_extension_list);
3118 if (extension_prop) {
3119 /* Found the extension in one of the layers enabled by the app. */
3120 break;
3121 }
3122 }
3123
3124 if (!extension_prop) {
3125 /* Didn't find extension name in any of the device layers, error out */
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06003126 return VK_ERROR_EXTENSION_NOT_PRESENT;
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003127 }
3128 }
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06003129 return VK_SUCCESS;
3130}
3131
Chia-I Wu9ab61502015-11-06 06:42:02 +08003132VKAPI_ATTR VkResult VKAPI_CALL loader_CreateInstance(
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003133 const VkInstanceCreateInfo* pCreateInfo,
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07003134 const VkAllocationCallbacks* pAllocator,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003135 VkInstance* pInstance)
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003136{
Jon Ashburneed0c002015-05-21 17:42:17 -06003137 struct loader_instance *ptr_instance = *(struct loader_instance **) pInstance;
Jon Ashburn46888392015-01-29 15:45:51 -07003138 struct loader_icd *icd;
Jon Ashburn5c042ea2015-08-04 11:14:18 -06003139 VkExtensionProperties *prop;
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003140 char **filtered_extension_names = NULL;
3141 VkInstanceCreateInfo icd_create_info;
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06003142 VkResult res = VK_SUCCESS;
Jon Ashburn7e18de02015-11-19 09:29:51 -07003143 bool success = false;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003144
Tony Barbour3c78ff42015-12-04 13:24:39 -07003145 memcpy(&icd_create_info, pCreateInfo, sizeof(icd_create_info));
3146
Chia-I Wud50a7d72015-10-26 20:48:51 +08003147 icd_create_info.enabledLayerNameCount = 0;
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003148 icd_create_info.ppEnabledLayerNames = NULL;
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003149
3150 /*
3151 * NOTE: Need to filter the extensions to only those
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003152 * supported by the ICD.
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003153 * No ICD will advertise support for layers. An ICD
3154 * library could support a layer, but it would be
3155 * independent of the actual ICD, just in the same library.
3156 */
Chia-I Wud50a7d72015-10-26 20:48:51 +08003157 filtered_extension_names = loader_stack_alloc(pCreateInfo->enabledExtensionNameCount * sizeof(char *));
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003158 if (!filtered_extension_names) {
3159 return VK_ERROR_OUT_OF_HOST_MEMORY;
3160 }
3161 icd_create_info.ppEnabledExtensionNames = (const char * const *) filtered_extension_names;
3162
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003163 for (uint32_t i = 0; i < ptr_instance->icd_libs.count; i++) {
3164 icd = loader_icd_add(ptr_instance, &ptr_instance->icd_libs.list[i]);
Jon Ashburn46888392015-01-29 15:45:51 -07003165 if (icd) {
Chia-I Wud50a7d72015-10-26 20:48:51 +08003166 icd_create_info.enabledExtensionNameCount = 0;
Courtney Goeltzenleuchter36eeb742015-12-21 16:41:47 -07003167 struct loader_extension_list icd_exts;
3168
3169 loader_log(ptr_instance, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Build ICD instance extension list");
3170 // traverse scanned icd list adding non-duplicate extensions to the list
3171 loader_init_generic_list(ptr_instance, (struct loader_generic_list *) &icd_exts,
3172 sizeof(VkExtensionProperties));
3173 loader_add_instance_extensions(ptr_instance,
3174 icd->this_icd_lib->EnumerateInstanceExtensionProperties,
3175 icd->this_icd_lib->lib_name,
3176 &icd_exts);
3177
Chia-I Wud50a7d72015-10-26 20:48:51 +08003178 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) {
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003179 prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
Courtney Goeltzenleuchter36eeb742015-12-21 16:41:47 -07003180 &icd_exts);
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003181 if (prop) {
Chia-I Wud50a7d72015-10-26 20:48:51 +08003182 filtered_extension_names[icd_create_info.enabledExtensionNameCount] = (char *) pCreateInfo->ppEnabledExtensionNames[i];
3183 icd_create_info.enabledExtensionNameCount++;
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003184 }
3185 }
3186
Courtney Goeltzenleuchter36eeb742015-12-21 16:41:47 -07003187 loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *) &icd_exts);
3188
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003189 res = ptr_instance->icd_libs.list[i].CreateInstance(&icd_create_info,
Chia-I Wuf7458c52015-10-26 21:10:41 +08003190 pAllocator,
Jon Ashburn3da71f22015-05-14 12:43:38 -06003191 &(icd->instance));
Jon Ashburn7e18de02015-11-19 09:29:51 -07003192 if (res == VK_SUCCESS)
3193 success = loader_icd_init_entrys(
Jon Ashburnc624c882015-07-16 10:17:29 -06003194 icd,
3195 icd->instance,
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003196 ptr_instance->icd_libs.list[i].GetInstanceProcAddr);
Jon Ashburnc624c882015-07-16 10:17:29 -06003197
3198 if (res != VK_SUCCESS || !success)
Jon Ashburn46888392015-01-29 15:45:51 -07003199 {
3200 ptr_instance->icds = ptr_instance->icds->next;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003201 loader_icd_destroy(ptr_instance, icd);
Jon Ashburn3da71f22015-05-14 12:43:38 -06003202 icd->instance = VK_NULL_HANDLE;
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07003203 loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburnc624c882015-07-16 10:17:29 -06003204 "ICD ignored: failed to CreateInstance and find entrypoints with ICD");
Jon Ashburn46888392015-01-29 15:45:51 -07003205 }
3206 }
Jon Ashburn46888392015-01-29 15:45:51 -07003207 }
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003208
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06003209 /*
3210 * If no ICDs were added to instance list and res is unchanged
3211 * from it's initial value, the loader was unable to find
3212 * a suitable ICD.
3213 */
Ian Elliotteb450762015-02-05 15:19:15 -07003214 if (ptr_instance->icds == NULL) {
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06003215 if (res == VK_SUCCESS) {
3216 return VK_ERROR_INCOMPATIBLE_DRIVER;
3217 } else {
3218 return res;
3219 }
Ian Elliotteb450762015-02-05 15:19:15 -07003220 }
Jon Ashburn46888392015-01-29 15:45:51 -07003221
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06003222 return VK_SUCCESS;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003223}
3224
Chia-I Wu9ab61502015-11-06 06:42:02 +08003225VKAPI_ATTR void VKAPI_CALL loader_DestroyInstance(
Chia-I Wuf7458c52015-10-26 21:10:41 +08003226 VkInstance instance,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003227 const VkAllocationCallbacks* pAllocator)
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003228{
Courtney Goeltzenleuchterdeceded2015-06-08 15:04:02 -06003229 struct loader_instance *ptr_instance = loader_instance(instance);
Jon Ashburn3da71f22015-05-14 12:43:38 -06003230 struct loader_icd *icds = ptr_instance->icds;
Jon Ashburna6fd2612015-06-16 14:43:19 -06003231 struct loader_icd *next_icd;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003232
3233 // Remove this instance from the list of instances:
3234 struct loader_instance *prev = NULL;
3235 struct loader_instance *next = loader.instances;
3236 while (next != NULL) {
3237 if (next == ptr_instance) {
3238 // Remove this instance from the list:
3239 if (prev)
3240 prev->next = next->next;
Jon Ashburnc5c49602015-02-03 09:26:59 -07003241 else
3242 loader.instances = next->next;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003243 break;
3244 }
3245 prev = next;
3246 next = next->next;
3247 }
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003248
Jon Ashburn3da71f22015-05-14 12:43:38 -06003249 while (icds) {
3250 if (icds->instance) {
Chia-I Wuf7458c52015-10-26 21:10:41 +08003251 icds->DestroyInstance(icds->instance, pAllocator);
Tony Barbourf20f87b2015-04-22 09:02:32 -06003252 }
Jon Ashburna6fd2612015-06-16 14:43:19 -06003253 next_icd = icds->next;
Jon Ashburn3da71f22015-05-14 12:43:38 -06003254 icds->instance = VK_NULL_HANDLE;
Jon Ashburna6fd2612015-06-16 14:43:19 -06003255 loader_icd_destroy(ptr_instance, icds);
3256
3257 icds = next_icd;
Jon Ashburn46888392015-01-29 15:45:51 -07003258 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06003259 loader_delete_layer_properties(ptr_instance, &ptr_instance->device_layer_list);
3260 loader_delete_layer_properties(ptr_instance, &ptr_instance->instance_layer_list);
3261 loader_scanned_icd_clear(ptr_instance, &ptr_instance->icd_libs);
Jon Ashburn6e6a2162015-12-10 08:51:10 -07003262 loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *)
3263 &ptr_instance->ext_list);
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003264 for (uint32_t i = 0; i < ptr_instance->total_gpu_count; i++)
Jon Ashburn6e6a2162015-12-10 08:51:10 -07003265 loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *)
3266 &ptr_instance->phys_devs[i].device_extension_cache);
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003267 loader_heap_free(ptr_instance, ptr_instance->phys_devs);
Jon Ashburnfc1031e2015-11-17 15:31:02 -07003268 loader_free_dev_ext_table(ptr_instance);
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003269}
3270
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003271VkResult loader_init_physical_device_info(struct loader_instance *ptr_instance)
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003272{
3273 struct loader_icd *icd;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003274 uint32_t i, j, idx, count = 0;
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06003275 VkResult res;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003276 struct loader_phys_dev_per_icd *phys_devs;
3277
3278 ptr_instance->total_gpu_count = 0;
3279 phys_devs = (struct loader_phys_dev_per_icd *) loader_stack_alloc(
3280 sizeof(struct loader_phys_dev_per_icd) *
3281 ptr_instance->total_icd_count);
3282 if (!phys_devs)
3283 return VK_ERROR_OUT_OF_HOST_MEMORY;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003284
3285 icd = ptr_instance->icds;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003286 for (i = 0; i < ptr_instance->total_icd_count; i++) {
3287 assert(icd);
3288 res = icd->EnumeratePhysicalDevices(icd->instance, &phys_devs[i].count, NULL);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003289 if (res != VK_SUCCESS)
3290 return res;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003291 count += phys_devs[i].count;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003292 icd = icd->next;
3293 }
3294
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003295 ptr_instance->phys_devs = (struct loader_physical_device *) loader_heap_alloc(
3296 ptr_instance,
3297 count * sizeof(struct loader_physical_device),
3298 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
3299 if (!ptr_instance->phys_devs)
3300 return VK_ERROR_OUT_OF_HOST_MEMORY;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003301
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003302 icd = ptr_instance->icds;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003303
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003304 struct loader_physical_device *inst_phys_devs = ptr_instance->phys_devs;
3305 idx = 0;
3306 for (i = 0; i < ptr_instance->total_icd_count; i++) {
3307 assert(icd);
3308
3309 phys_devs[i].phys_devs = (VkPhysicalDevice *) loader_stack_alloc(
3310 phys_devs[i].count * sizeof(VkPhysicalDevice));
3311 if (!phys_devs[i].phys_devs) {
Jon Ashburn093ce202015-11-02 17:59:02 -07003312 loader_heap_free(ptr_instance, ptr_instance->phys_devs);
3313 ptr_instance->phys_devs = NULL;
Jon Ashburn128f9422015-05-28 19:16:58 -06003314 return VK_ERROR_OUT_OF_HOST_MEMORY;
3315 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003316 res = icd->EnumeratePhysicalDevices(
3317 icd->instance,
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003318 &(phys_devs[i].count),
3319 phys_devs[i].phys_devs);
3320 if ((res == VK_SUCCESS)) {
3321 ptr_instance->total_gpu_count += phys_devs[i].count;
3322 for (j = 0; j < phys_devs[i].count; j++) {
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003323
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003324 // initialize the loader's physicalDevice object
3325 loader_set_dispatch((void *) &inst_phys_devs[idx], ptr_instance->disp);
3326 inst_phys_devs[idx].this_instance = ptr_instance;
3327 inst_phys_devs[idx].this_icd = icd;
3328 inst_phys_devs[idx].phys_dev = phys_devs[i].phys_devs[j];
Jon Ashburn00eb6c02015-11-02 17:40:01 -07003329 memset(&inst_phys_devs[idx].device_extension_cache, 0, sizeof(struct loader_extension_list));
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003330
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003331 idx++;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003332 }
Jon Ashburn093ce202015-11-02 17:59:02 -07003333 } else {
3334 loader_heap_free(ptr_instance, ptr_instance->phys_devs);
3335 ptr_instance->phys_devs = NULL;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003336 return res;
Jon Ashburn093ce202015-11-02 17:59:02 -07003337 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003338
3339 icd = icd->next;
3340 }
3341
3342 return VK_SUCCESS;
3343}
3344
Chia-I Wu9ab61502015-11-06 06:42:02 +08003345VKAPI_ATTR VkResult VKAPI_CALL loader_EnumeratePhysicalDevices(
Courtney Goeltzenleuchter5e41f1d2015-04-20 12:48:54 -06003346 VkInstance instance,
3347 uint32_t* pPhysicalDeviceCount,
3348 VkPhysicalDevice* pPhysicalDevices)
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003349{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003350 uint32_t i;
Jon Ashburn4c392fb2015-01-28 19:57:09 -07003351 struct loader_instance *ptr_instance = (struct loader_instance *) instance;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003352 VkResult res = VK_SUCCESS;
Jon Ashburn4c392fb2015-01-28 19:57:09 -07003353
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003354 if (ptr_instance->total_gpu_count == 0) {
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003355 res = loader_init_physical_device_info(ptr_instance);
Jon Ashburn4c392fb2015-01-28 19:57:09 -07003356 }
3357
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003358 *pPhysicalDeviceCount = ptr_instance->total_gpu_count;
3359 if (!pPhysicalDevices) {
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003360 return res;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003361 }
Jon Ashburn4c392fb2015-01-28 19:57:09 -07003362
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003363 for (i = 0; i < ptr_instance->total_gpu_count; i++) {
3364 pPhysicalDevices[i] = (VkPhysicalDevice) &ptr_instance->phys_devs[i];
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003365 }
3366
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003367 return res;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003368}
3369
Chia-I Wu9ab61502015-11-06 06:42:02 +08003370VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceProperties(
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003371 VkPhysicalDevice physicalDevice,
Tony Barbour59a47322015-06-24 16:06:58 -06003372 VkPhysicalDeviceProperties* pProperties)
Jon Ashburn3da71f22015-05-14 12:43:38 -06003373{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003374 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3375 struct loader_icd *icd = phys_dev->this_icd;
Jon Ashburn3da71f22015-05-14 12:43:38 -06003376
Tony Barbour59a47322015-06-24 16:06:58 -06003377 if (icd->GetPhysicalDeviceProperties)
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003378 icd->GetPhysicalDeviceProperties(phys_dev->phys_dev, pProperties);
Tony Barbour59a47322015-06-24 16:06:58 -06003379}
3380
Chia-I Wu9ab61502015-11-06 06:42:02 +08003381VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceQueueFamilyProperties (
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003382 VkPhysicalDevice physicalDevice,
Chia-I Wud50a7d72015-10-26 20:48:51 +08003383 uint32_t* pQueueFamilyPropertyCount,
Cody Northropd0802882015-08-03 17:04:53 -06003384 VkQueueFamilyProperties* pProperties)
Tony Barbour59a47322015-06-24 16:06:58 -06003385{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003386 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3387 struct loader_icd *icd = phys_dev->this_icd;
Tony Barbour59a47322015-06-24 16:06:58 -06003388
Cody Northropd0802882015-08-03 17:04:53 -06003389 if (icd->GetPhysicalDeviceQueueFamilyProperties)
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003390 icd->GetPhysicalDeviceQueueFamilyProperties(phys_dev->phys_dev, pQueueFamilyPropertyCount, pProperties);
Tony Barbour59a47322015-06-24 16:06:58 -06003391}
3392
Chia-I Wu9ab61502015-11-06 06:42:02 +08003393VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceMemoryProperties (
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003394 VkPhysicalDevice physicalDevice,
Tony Barbour59a47322015-06-24 16:06:58 -06003395 VkPhysicalDeviceMemoryProperties* pProperties)
3396{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003397 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3398 struct loader_icd *icd = phys_dev->this_icd;
Tony Barbour59a47322015-06-24 16:06:58 -06003399
3400 if (icd->GetPhysicalDeviceMemoryProperties)
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003401 icd->GetPhysicalDeviceMemoryProperties(phys_dev->phys_dev, pProperties);
Jon Ashburn3da71f22015-05-14 12:43:38 -06003402}
3403
Chia-I Wu9ab61502015-11-06 06:42:02 +08003404VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceFeatures(
Chris Forbesbc0bb772015-06-21 22:55:02 +12003405 VkPhysicalDevice physicalDevice,
3406 VkPhysicalDeviceFeatures* pFeatures)
3407{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003408 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3409 struct loader_icd *icd = phys_dev->this_icd;
Chris Forbesbc0bb772015-06-21 22:55:02 +12003410
3411 if (icd->GetPhysicalDeviceFeatures)
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003412 icd->GetPhysicalDeviceFeatures(phys_dev->phys_dev, pFeatures);
Chris Forbesbc0bb772015-06-21 22:55:02 +12003413}
3414
Chia-I Wu9ab61502015-11-06 06:42:02 +08003415VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceFormatProperties(
Chris Forbesbc0bb772015-06-21 22:55:02 +12003416 VkPhysicalDevice physicalDevice,
3417 VkFormat format,
3418 VkFormatProperties* pFormatInfo)
3419{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003420 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3421 struct loader_icd *icd = phys_dev->this_icd;
Chris Forbesbc0bb772015-06-21 22:55:02 +12003422
Courtney Goeltzenleuchter2caec862015-07-12 12:52:09 -06003423 if (icd->GetPhysicalDeviceFormatProperties)
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003424 icd->GetPhysicalDeviceFormatProperties(phys_dev->phys_dev, format, pFormatInfo);
Chris Forbesbc0bb772015-06-21 22:55:02 +12003425}
3426
Chia-I Wu9ab61502015-11-06 06:42:02 +08003427VKAPI_ATTR VkResult VKAPI_CALL loader_GetPhysicalDeviceImageFormatProperties(
Jon Ashburn754864f2015-07-23 18:49:07 -06003428 VkPhysicalDevice physicalDevice,
3429 VkFormat format,
3430 VkImageType type,
3431 VkImageTiling tiling,
3432 VkImageUsageFlags usage,
Courtney Goeltzenleuchtera22097a2015-09-10 13:44:12 -06003433 VkImageCreateFlags flags,
Jon Ashburn754864f2015-07-23 18:49:07 -06003434 VkImageFormatProperties* pImageFormatProperties)
3435{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003436 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3437 struct loader_icd *icd = phys_dev->this_icd;
Jon Ashburn754864f2015-07-23 18:49:07 -06003438
Chia-I Wu17241042015-10-31 00:31:16 +08003439 if (!icd->GetPhysicalDeviceImageFormatProperties)
3440 return VK_ERROR_INITIALIZATION_FAILED;
3441
3442 return icd->GetPhysicalDeviceImageFormatProperties(phys_dev->phys_dev, format,
3443 type, tiling, usage, flags, pImageFormatProperties);
Jon Ashburn754864f2015-07-23 18:49:07 -06003444}
3445
Chia-I Wu9ab61502015-11-06 06:42:02 +08003446VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceSparseImageFormatProperties(
Mark Lobodzinski16e8bef2015-07-03 15:58:09 -06003447 VkPhysicalDevice physicalDevice,
3448 VkFormat format,
3449 VkImageType type,
Chia-I Wu5c17c962015-10-31 00:31:16 +08003450 VkSampleCountFlagBits samples,
Mark Lobodzinski16e8bef2015-07-03 15:58:09 -06003451 VkImageUsageFlags usage,
3452 VkImageTiling tiling,
3453 uint32_t* pNumProperties,
3454 VkSparseImageFormatProperties* pProperties)
3455{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003456 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3457 struct loader_icd *icd = phys_dev->this_icd;
Mark Lobodzinski16e8bef2015-07-03 15:58:09 -06003458
3459 if (icd->GetPhysicalDeviceSparseImageFormatProperties)
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003460 icd->GetPhysicalDeviceSparseImageFormatProperties(phys_dev->phys_dev, format, type, samples, usage, tiling, pNumProperties, pProperties);
Mark Lobodzinski16e8bef2015-07-03 15:58:09 -06003461}
3462
Chia-I Wu9ab61502015-11-06 06:42:02 +08003463VKAPI_ATTR VkResult VKAPI_CALL loader_CreateDevice(
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003464 VkPhysicalDevice physicalDevice,
Jon Ashburn95a77ba2015-05-15 15:09:35 -06003465 const VkDeviceCreateInfo* pCreateInfo,
Jon Ashburn46674bf2015-12-11 09:41:34 -07003466 const VkAllocationCallbacks* pAllocator,
Jon Ashburn95a77ba2015-05-15 15:09:35 -06003467 VkDevice* pDevice)
3468{
Jon Ashburn46674bf2015-12-11 09:41:34 -07003469 struct loader_physical_device *phys_dev;
3470 struct loader_icd *icd;
Jon Ashburndc6fcad2015-06-10 10:06:06 -06003471 struct loader_device *dev;
Jon Ashburnfc1031e2015-11-17 15:31:02 -07003472 struct loader_instance *inst;
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003473 VkDeviceCreateInfo device_create_info;
3474 char **filtered_extension_names = NULL;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003475 VkResult res;
Jon Ashburn95a77ba2015-05-15 15:09:35 -06003476
Chia-I Wu02124482015-11-06 06:42:02 +08003477 assert(pCreateInfo->queueCreateInfoCount >= 1);
Mark Lobodzinski0c29b922015-09-17 15:17:34 -06003478
Jon Ashburn46674bf2015-12-11 09:41:34 -07003479 //TODO this only works for one physical device per instance
3480 // once CreateDevice layer bootstrapping is done via DeviceCreateInfo
3481 // hopefully don't need this anymore in trampoline code
3482 phys_dev = loader_get_physical_device(physicalDevice);
3483 icd = phys_dev->this_icd;
Jon Ashburna4cf12b2015-10-26 16:54:51 -06003484 if (!icd)
3485 return VK_ERROR_INITIALIZATION_FAILED;
3486
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003487 inst = phys_dev->this_instance;
Jon Ashburna4cf12b2015-10-26 16:54:51 -06003488
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003489 if (!icd->CreateDevice) {
3490 return VK_ERROR_INITIALIZATION_FAILED;
Jon Ashburn95a77ba2015-05-15 15:09:35 -06003491 }
3492
Jon Ashburnb82c1852015-08-11 14:49:54 -06003493 /* validate any app enabled layers are available */
Chia-I Wud50a7d72015-10-26 20:48:51 +08003494 if (pCreateInfo->enabledLayerNameCount > 0) {
3495 res = loader_validate_layers(pCreateInfo->enabledLayerNameCount,
Jon Ashburnb82c1852015-08-11 14:49:54 -06003496 pCreateInfo->ppEnabledLayerNames,
Jon Ashburne39a4f82015-08-28 13:38:21 -06003497 &inst->device_layer_list);
Jon Ashburnb82c1852015-08-11 14:49:54 -06003498 if (res != VK_SUCCESS) {
3499 return res;
3500 }
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003501 }
3502
Jon Ashburn00eb6c02015-11-02 17:40:01 -07003503 /* Get the physical device extensions if they haven't been retrieved yet */
3504 if (phys_dev->device_extension_cache.capacity == 0) {
Jon Ashburn6e6a2162015-12-10 08:51:10 -07003505 if (!loader_init_generic_list(inst, (struct loader_generic_list *)
3506 &phys_dev->device_extension_cache,
3507 sizeof(VkExtensionProperties))) {
Jon Ashburn00eb6c02015-11-02 17:40:01 -07003508 return VK_ERROR_OUT_OF_HOST_MEMORY;
3509 }
Courtney Goeltzenleuchterf538ef72015-12-02 14:00:19 -07003510 res = loader_add_device_extensions(
Jon Ashburn00eb6c02015-11-02 17:40:01 -07003511 inst, physicalDevice,
3512 phys_dev->this_icd->this_icd_lib->lib_name,
3513 &phys_dev->device_extension_cache);
3514 if (res != VK_SUCCESS) {
3515 return res;
3516 }
3517 }
3518 /* make sure requested extensions to be enabled are supported */
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003519 res = loader_validate_device_extensions(phys_dev, &inst->device_layer_list, pCreateInfo);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003520 if (res != VK_SUCCESS) {
3521 return res;
3522 }
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003523
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003524 /*
3525 * NOTE: Need to filter the extensions to only those
3526 * supported by the ICD.
3527 * No ICD will advertise support for layers. An ICD
3528 * library could support a layer, but it would be
3529 * independent of the actual ICD, just in the same library.
3530 */
Chia-I Wud50a7d72015-10-26 20:48:51 +08003531 filtered_extension_names = loader_stack_alloc(pCreateInfo->enabledExtensionNameCount * sizeof(char *));
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003532 if (!filtered_extension_names) {
3533 return VK_ERROR_OUT_OF_HOST_MEMORY;
3534 }
3535
3536 /* Copy user's data */
3537 memcpy(&device_create_info, pCreateInfo, sizeof(VkDeviceCreateInfo));
3538
3539 /* ICD's do not use layers */
Chia-I Wud50a7d72015-10-26 20:48:51 +08003540 device_create_info.enabledLayerNameCount = 0;
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003541 device_create_info.ppEnabledLayerNames = NULL;
3542
Chia-I Wud50a7d72015-10-26 20:48:51 +08003543 device_create_info.enabledExtensionNameCount = 0;
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003544 device_create_info.ppEnabledExtensionNames = (const char * const *) filtered_extension_names;
3545
Chia-I Wud50a7d72015-10-26 20:48:51 +08003546 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) {
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003547 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i];
Jon Ashburn5c042ea2015-08-04 11:14:18 -06003548 VkExtensionProperties *prop = get_extension_property(extension_name,
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003549 &phys_dev->device_extension_cache);
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003550 if (prop) {
Chia-I Wud50a7d72015-10-26 20:48:51 +08003551 filtered_extension_names[device_create_info.enabledExtensionNameCount] = (char *) extension_name;
3552 device_create_info.enabledExtensionNameCount++;
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003553 }
3554 }
3555
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003556 // since physicalDevice object maybe wrapped by a layer need to get unwrapped version
Jon Ashburne0e64572015-09-30 12:56:42 -06003557 // we haven't yet called down the chain for the layer to unwrap the object
Jon Ashburn0704af92015-12-24 10:50:08 -07003558 res = icd->CreateDevice(phys_dev->phys_dev, &device_create_info, pAllocator, pDevice);
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003559 if (res != VK_SUCCESS) {
3560 return res;
3561 }
3562
Jon Ashburne39a4f82015-08-28 13:38:21 -06003563 dev = loader_add_logical_device(inst, *pDevice, &icd->logical_device_list);
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003564 if (dev == NULL) {
3565 return VK_ERROR_OUT_OF_HOST_MEMORY;
3566 }
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003567
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003568 loader_init_dispatch(*pDevice, &dev->loader_dispatch);
3569
Jon Ashburnb82c1852015-08-11 14:49:54 -06003570 /* activate any layers on device chain which terminates with device*/
Jon Ashburne39a4f82015-08-28 13:38:21 -06003571 res = loader_enable_device_layers(inst, icd, dev, pCreateInfo, &inst->device_layer_list);
Jon Ashburnb82c1852015-08-11 14:49:54 -06003572 if (res != VK_SUCCESS) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06003573 loader_destroy_logical_device(inst, dev);
Jon Ashburnb82c1852015-08-11 14:49:54 -06003574 return res;
3575 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06003576 loader_activate_device_layers(inst, dev, *pDevice);
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003577
Jon Ashburnfc1031e2015-11-17 15:31:02 -07003578 /* finally can call down the chain */
3579 res = dev->loader_dispatch.core_dispatch.CreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
3580
Jon Ashburn54978592015-12-11 10:45:00 -07003581 /* initialize any device extension dispatch entry's from the instance list*/
3582 loader_init_dispatch_dev_ext(inst, dev);
3583
Jon Ashburn232e3af2015-11-30 17:21:25 -07003584 /* initialize WSI device extensions as part of core dispatch since loader has
3585 * dedicated trampoline code for these*/
3586 loader_init_device_extension_dispatch_table(&dev->loader_dispatch,
3587 dev->loader_dispatch.core_dispatch.GetDeviceProcAddr,
3588 *pDevice);
Jon Ashburnfc1031e2015-11-17 15:31:02 -07003589 dev->loader_dispatch.core_dispatch.CreateDevice = icd->CreateDevice;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003590
Jon Ashburn95a77ba2015-05-15 15:09:35 -06003591 return res;
3592}
3593
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003594/**
3595 * Get an instance level or global level entry point address.
3596 * @param instance
3597 * @param pName
3598 * @return
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003599 * If instance == NULL returns a global level functions only
3600 * If instance is valid returns a trampoline entry point for all dispatchable Vulkan
3601 * functions both core and extensions.
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003602 */
Chia-I Wu9ab61502015-11-06 06:42:02 +08003603LOADER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char * pName)
Jon Ashburnb0fbe912015-05-06 10:15:07 -06003604{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003605
Jon Ashburn07daee72015-05-21 18:13:33 -06003606 void *addr;
Jon Ashburnb0fbe912015-05-06 10:15:07 -06003607
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003608 addr = globalGetProcAddr(pName);
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003609 if (instance == VK_NULL_HANDLE) {
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003610 // get entrypoint addresses that are global (no dispatchable object)
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003611
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003612 return addr;
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003613 } else {
3614 // if a global entrypoint return NULL
3615 if (addr)
3616 return NULL;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003617 }
3618
Jon Ashburne0e64572015-09-30 12:56:42 -06003619 struct loader_instance *ptr_instance = loader_get_instance(instance);
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003620 if (ptr_instance == NULL)
Jon Ashburn07daee72015-05-21 18:13:33 -06003621 return NULL;
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003622 // Return trampoline code for non-global entrypoints including any extensions.
3623 // Device extensions are returned if a layer or ICD supports the extension.
3624 // Instance extensions are returned if the extension is enabled and the loader
3625 // or someone else supports the extension
3626 return trampolineGetProcAddr(ptr_instance, pName);
Jon Ashburn07daee72015-05-21 18:13:33 -06003627
Jon Ashburnb0fbe912015-05-06 10:15:07 -06003628}
3629
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003630/**
3631 * Get a device level or global level entry point address.
3632 * @param device
3633 * @param pName
3634 * @return
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003635 * If device is valid, returns a device relative entry point for device level
3636 * entry points both core and extensions.
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003637 * Device relative means call down the device chain.
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003638 */
Chia-I Wu9ab61502015-11-06 06:42:02 +08003639LOADER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char * pName)
Courtney Goeltzenleuchter9ec39ac2015-06-22 17:45:21 -06003640{
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003641 void *addr;
Courtney Goeltzenleuchter9ec39ac2015-06-22 17:45:21 -06003642
Jon Ashburn3d526cb2015-04-13 18:10:06 -06003643 /* for entrypoints that loader must handle (ie non-dispatchable or create object)
3644 make sure the loader entrypoint is returned */
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003645 addr = loader_non_passthrough_gdpa(pName);
Ian Elliotte19c9152015-04-15 12:53:19 -06003646 if (addr) {
Jon Ashburn3d526cb2015-04-13 18:10:06 -06003647 return addr;
Ian Elliotte19c9152015-04-15 12:53:19 -06003648 }
Jon Ashburn3d526cb2015-04-13 18:10:06 -06003649
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003650 /* Although CreateDevice is on device chain it's dispatchable object isn't
3651 * a VkDevice or child of VkDevice so return NULL.
3652 */
3653 if (!strcmp(pName, "CreateDevice"))
3654 return NULL;
3655
Jon Ashburn3d526cb2015-04-13 18:10:06 -06003656 /* return the dispatch table entrypoint for the fastest case */
Jon Ashburn8d1b0b52015-05-18 13:20:15 -06003657 const VkLayerDispatchTable *disp_table = * (VkLayerDispatchTable **) device;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06003658 if (disp_table == NULL)
3659 return NULL;
3660
Jon Ashburn27cd5842015-05-12 17:26:48 -06003661 addr = loader_lookup_device_dispatch_table(disp_table, pName);
Chia-I Wuf46b81a2015-01-04 11:12:47 +08003662 if (addr)
3663 return addr;
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003664
3665 if (disp_table->GetDeviceProcAddr == NULL)
3666 return NULL;
3667 return disp_table->GetDeviceProcAddr(device, pName);
Jon Ashburnd38bfb12014-10-14 19:15:22 -06003668}
3669
Chia-I Wu9ab61502015-11-06 06:42:02 +08003670LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003671 const char* pLayerName,
Chia-I Wud50a7d72015-10-26 20:48:51 +08003672 uint32_t* pPropertyCount,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003673 VkExtensionProperties* pProperties)
3674{
Jon Ashburn432d2762015-09-18 12:53:16 -06003675 struct loader_extension_list *global_ext_list=NULL;
Jon Ashburnb82c1852015-08-11 14:49:54 -06003676 struct loader_layer_list instance_layers;
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003677 struct loader_extension_list icd_extensions;
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003678 struct loader_icd_libs icd_libs;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003679 uint32_t copy_size;
3680
Jon Ashburn87d6aa92015-08-28 15:19:27 -06003681 tls_instance = NULL;
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003682 memset(&icd_extensions, 0, sizeof(icd_extensions));
Mike Stroyan09c06c72015-10-01 15:23:48 -06003683 memset(&instance_layers, 0, sizeof(instance_layers));
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003684 loader_platform_thread_once(&once_init, loader_initialize);
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003685
Jon Ashburnb82c1852015-08-11 14:49:54 -06003686 /* get layer libraries if needed */
3687 if (pLayerName && strlen(pLayerName) != 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06003688 loader_layer_scan(NULL, &instance_layers, NULL);
Jon Ashburnb82c1852015-08-11 14:49:54 -06003689 for (uint32_t i = 0; i < instance_layers.count; i++) {
3690 struct loader_layer_properties *props = &instance_layers.list[i];
3691 if (strcmp(props->info.layerName, pLayerName) == 0) {
3692 global_ext_list = &props->instance_extension_list;
3693 }
3694 }
3695 }
3696 else {
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003697 /* Scan/discover all ICD libraries */
3698 memset(&icd_libs, 0 , sizeof(struct loader_icd_libs));
Jon Ashburne39a4f82015-08-28 13:38:21 -06003699 loader_icd_scan(NULL, &icd_libs);
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003700 /* get extensions from all ICD's, merge so no duplicates */
Jon Ashburne39a4f82015-08-28 13:38:21 -06003701 loader_get_icd_loader_instance_extensions(NULL, &icd_libs, &icd_extensions);
3702 loader_scanned_icd_clear(NULL, &icd_libs);
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003703 global_ext_list = &icd_extensions;
Jon Ashburnb82c1852015-08-11 14:49:54 -06003704 }
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003705
Jon Ashburnb82c1852015-08-11 14:49:54 -06003706 if (global_ext_list == NULL) {
Mike Stroyan09c06c72015-10-01 15:23:48 -06003707 loader_destroy_layer_list(NULL, &instance_layers);
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06003708 return VK_ERROR_LAYER_NOT_PRESENT;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003709 }
3710
3711 if (pProperties == NULL) {
Chia-I Wud50a7d72015-10-26 20:48:51 +08003712 *pPropertyCount = global_ext_list->count;
Mike Stroyan09c06c72015-10-01 15:23:48 -06003713 loader_destroy_layer_list(NULL, &instance_layers);
Jon Ashburn6e6a2162015-12-10 08:51:10 -07003714 loader_destroy_generic_list(NULL, (struct loader_generic_list *)
3715 &icd_extensions);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003716 return VK_SUCCESS;
3717 }
3718
Chia-I Wud50a7d72015-10-26 20:48:51 +08003719 copy_size = *pPropertyCount < global_ext_list->count ? *pPropertyCount : global_ext_list->count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003720 for (uint32_t i = 0; i < copy_size; i++) {
3721 memcpy(&pProperties[i],
Jon Ashburnb82c1852015-08-11 14:49:54 -06003722 &global_ext_list->list[i],
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003723 sizeof(VkExtensionProperties));
3724 }
Chia-I Wud50a7d72015-10-26 20:48:51 +08003725 *pPropertyCount = copy_size;
Jon Ashburn6e6a2162015-12-10 08:51:10 -07003726 loader_destroy_generic_list(NULL, (struct loader_generic_list *)
3727 &icd_extensions);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003728
Jon Ashburnb82c1852015-08-11 14:49:54 -06003729 if (copy_size < global_ext_list->count) {
Mike Stroyan09c06c72015-10-01 15:23:48 -06003730 loader_destroy_layer_list(NULL, &instance_layers);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003731 return VK_INCOMPLETE;
3732 }
3733
Mike Stroyan09c06c72015-10-01 15:23:48 -06003734 loader_destroy_layer_list(NULL, &instance_layers);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003735 return VK_SUCCESS;
3736}
3737
Chia-I Wu9ab61502015-11-06 06:42:02 +08003738LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(
Chia-I Wud50a7d72015-10-26 20:48:51 +08003739 uint32_t* pPropertyCount,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003740 VkLayerProperties* pProperties)
Tony Barbour59a47322015-06-24 16:06:58 -06003741{
Jon Ashburn6301a0f2015-05-29 13:15:39 -06003742
Jon Ashburnb82c1852015-08-11 14:49:54 -06003743 struct loader_layer_list instance_layer_list;
Jon Ashburn87d6aa92015-08-28 15:19:27 -06003744 tls_instance = NULL;
Jon Ashburnb82c1852015-08-11 14:49:54 -06003745
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003746 loader_platform_thread_once(&once_init, loader_initialize);
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07003747
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003748 uint32_t copy_size;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06003749
Jon Ashburnb82c1852015-08-11 14:49:54 -06003750 /* get layer libraries */
3751 memset(&instance_layer_list, 0, sizeof(instance_layer_list));
Jon Ashburne39a4f82015-08-28 13:38:21 -06003752 loader_layer_scan(NULL, &instance_layer_list, NULL);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003753
3754 if (pProperties == NULL) {
Chia-I Wud50a7d72015-10-26 20:48:51 +08003755 *pPropertyCount = instance_layer_list.count;
Jon Ashburne39a4f82015-08-28 13:38:21 -06003756 loader_destroy_layer_list(NULL, &instance_layer_list);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003757 return VK_SUCCESS;
3758 }
3759
Chia-I Wud50a7d72015-10-26 20:48:51 +08003760 copy_size = (*pPropertyCount < instance_layer_list.count) ? *pPropertyCount : instance_layer_list.count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003761 for (uint32_t i = 0; i < copy_size; i++) {
Jon Ashburnb82c1852015-08-11 14:49:54 -06003762 memcpy(&pProperties[i], &instance_layer_list.list[i].info, sizeof(VkLayerProperties));
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003763 }
Chia-I Wud50a7d72015-10-26 20:48:51 +08003764 *pPropertyCount = copy_size;
Jon Ashburne39a4f82015-08-28 13:38:21 -06003765 loader_destroy_layer_list(NULL, &instance_layer_list);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003766
Jon Ashburnb82c1852015-08-11 14:49:54 -06003767 if (copy_size < instance_layer_list.count) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003768 return VK_INCOMPLETE;
3769 }
Tony Barbour59a47322015-06-24 16:06:58 -06003770
3771 return VK_SUCCESS;
3772}
3773
Chia-I Wu9ab61502015-11-06 06:42:02 +08003774VKAPI_ATTR VkResult VKAPI_CALL loader_EnumerateDeviceExtensionProperties(
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003775 VkPhysicalDevice physicalDevice,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003776 const char* pLayerName,
Chia-I Wud50a7d72015-10-26 20:48:51 +08003777 uint32_t* pPropertyCount,
Tony Barbour59a47322015-06-24 16:06:58 -06003778 VkExtensionProperties* pProperties)
3779{
Jon Ashburna760a512015-12-14 08:52:14 -07003780 struct loader_physical_device *phys_dev;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003781 uint32_t copy_size;
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07003782
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003783 uint32_t count;
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07003784 struct loader_device_extension_list *dev_ext_list=NULL;
Jon Ashburna760a512015-12-14 08:52:14 -07003785 //TODO fix this aliases physical devices
3786 phys_dev = loader_get_physical_device(physicalDevice);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003787
Jon Ashburnb82c1852015-08-11 14:49:54 -06003788 /* get layer libraries if needed */
3789 if (pLayerName && strlen(pLayerName) != 0) {
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003790 for (uint32_t i = 0; i < phys_dev->this_instance->device_layer_list.count; i++) {
3791 struct loader_layer_properties *props = &phys_dev->this_instance->device_layer_list.list[i];
Jon Ashburnb82c1852015-08-11 14:49:54 -06003792 if (strcmp(props->info.layerName, pLayerName) == 0) {
3793 dev_ext_list = &props->device_extension_list;
3794 }
3795 }
3796 }
3797 else {
Jon Ashburn00eb6c02015-11-02 17:40:01 -07003798 /* this case is during the call down the instance chain */
3799 struct loader_icd *icd = phys_dev->this_icd;
3800 VkResult res;
3801 res = icd->EnumerateDeviceExtensionProperties(phys_dev->phys_dev, NULL, pPropertyCount, pProperties);
3802 if (pProperties != NULL && res == VK_SUCCESS) {
3803 /* initialize dev_extension list within the physicalDevice object */
Courtney Goeltzenleuchterf538ef72015-12-02 14:00:19 -07003804 res = loader_init_device_extensions(phys_dev->this_instance,
Jon Ashburn00eb6c02015-11-02 17:40:01 -07003805 phys_dev, *pPropertyCount, pProperties,
3806 &phys_dev->device_extension_cache);
3807 }
3808 return res;
Jon Ashburnb82c1852015-08-11 14:49:54 -06003809 }
3810
Jon Ashburn432d2762015-09-18 12:53:16 -06003811 count = (dev_ext_list == NULL) ? 0: dev_ext_list->count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003812 if (pProperties == NULL) {
Chia-I Wud50a7d72015-10-26 20:48:51 +08003813 *pPropertyCount = count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003814 return VK_SUCCESS;
3815 }
3816
Chia-I Wud50a7d72015-10-26 20:48:51 +08003817 copy_size = *pPropertyCount < count ? *pPropertyCount : count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003818 for (uint32_t i = 0; i < copy_size; i++) {
3819 memcpy(&pProperties[i],
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07003820 &dev_ext_list->list[i].props,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003821 sizeof(VkExtensionProperties));
3822 }
Chia-I Wud50a7d72015-10-26 20:48:51 +08003823 *pPropertyCount = copy_size;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003824
3825 if (copy_size < count) {
3826 return VK_INCOMPLETE;
3827 }
3828
3829 return VK_SUCCESS;
3830}
3831
Chia-I Wu9ab61502015-11-06 06:42:02 +08003832VKAPI_ATTR VkResult VKAPI_CALL loader_EnumerateDeviceLayerProperties(
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003833 VkPhysicalDevice physicalDevice,
Chia-I Wud50a7d72015-10-26 20:48:51 +08003834 uint32_t* pPropertyCount,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003835 VkLayerProperties* pProperties)
3836{
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003837 uint32_t copy_size;
Jon Ashburna760a512015-12-14 08:52:14 -07003838 struct loader_physical_device *phys_dev;
3839 //TODO fix this, aliases physical devices
3840 phys_dev = loader_get_physical_device(physicalDevice);
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003841 uint32_t count = phys_dev->this_instance->device_layer_list.count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003842
3843 if (pProperties == NULL) {
Chia-I Wud50a7d72015-10-26 20:48:51 +08003844 *pPropertyCount = count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003845 return VK_SUCCESS;
3846 }
3847
Chia-I Wud50a7d72015-10-26 20:48:51 +08003848 copy_size = (*pPropertyCount < count) ? *pPropertyCount : count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003849 for (uint32_t i = 0; i < copy_size; i++) {
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003850 memcpy(&pProperties[i], &(phys_dev->this_instance->device_layer_list.list[i].info), sizeof(VkLayerProperties));
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003851 }
Chia-I Wud50a7d72015-10-26 20:48:51 +08003852 *pPropertyCount = copy_size;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003853
3854 if (copy_size < count) {
3855 return VK_INCOMPLETE;
3856 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003857
3858 return VK_SUCCESS;
Jon Ashburn95a77ba2015-05-15 15:09:35 -06003859}