blob: 83f1f5a5f1f64168f763cf6fb05e8e2372404696 [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 .DestroyInstance = loader_DestroyInstance,
102 .EnumeratePhysicalDevices = loader_EnumeratePhysicalDevices,
Chris Forbesbc0bb772015-06-21 22:55:02 +1200103 .GetPhysicalDeviceFeatures = loader_GetPhysicalDeviceFeatures,
Courtney Goeltzenleuchter2caec862015-07-12 12:52:09 -0600104 .GetPhysicalDeviceFormatProperties = loader_GetPhysicalDeviceFormatProperties,
Jon Ashburn754864f2015-07-23 18:49:07 -0600105 .GetPhysicalDeviceImageFormatProperties = loader_GetPhysicalDeviceImageFormatProperties,
Tony Barbour59a47322015-06-24 16:06:58 -0600106 .GetPhysicalDeviceProperties = loader_GetPhysicalDeviceProperties,
Cody Northropd0802882015-08-03 17:04:53 -0600107 .GetPhysicalDeviceQueueFamilyProperties = loader_GetPhysicalDeviceQueueFamilyProperties,
Tony Barbour59a47322015-06-24 16:06:58 -0600108 .GetPhysicalDeviceMemoryProperties = loader_GetPhysicalDeviceMemoryProperties,
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -0600109 .EnumerateDeviceExtensionProperties = loader_EnumerateDeviceExtensionProperties,
110 .EnumerateDeviceLayerProperties = loader_EnumerateDeviceLayerProperties,
Mark Lobodzinski16e8bef2015-07-03 15:58:09 -0600111 .GetPhysicalDeviceSparseImageFormatProperties = loader_GetPhysicalDeviceSparseImageFormatProperties,
Ian Elliottfb42cd72015-11-25 14:43:02 -0700112 .DestroySurfaceKHR = loader_DestroySurfaceKHR,
Ian Elliott7e40db92015-08-21 15:09:33 -0600113 .GetPhysicalDeviceSurfaceSupportKHR = loader_GetPhysicalDeviceSurfaceSupportKHR,
Ian Elliott486c5502015-11-19 16:05:09 -0700114 .GetPhysicalDeviceSurfaceCapabilitiesKHR = loader_GetPhysicalDeviceSurfaceCapabilitiesKHR,
115 .GetPhysicalDeviceSurfaceFormatsKHR = loader_GetPhysicalDeviceSurfaceFormatsKHR,
116 .GetPhysicalDeviceSurfacePresentModesKHR = loader_GetPhysicalDeviceSurfacePresentModesKHR,
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700117 .CreateDebugReportCallbackEXT = loader_CreateDebugReportCallback,
118 .DestroyDebugReportCallbackEXT = loader_DestroyDebugReportCallback,
119 .DebugReportMessageEXT = loader_DebugReportMessage,
Ian Elliottdb4300a2015-11-23 10:17:23 -0700120#ifdef VK_USE_PLATFORM_MIR_KHR
Jon Ashburnf72a04b2015-11-25 17:55:49 -0700121 .CreateMirSurfaceKHR = loader_CreateMirSurfaceKHR,
Ian Elliott919fa302015-11-24 15:39:10 -0700122 .GetPhysicalDeviceMirPresentationSupportKHR = loader_GetPhysicalDeviceMirPresentationSupportKHR,
Ian Elliottdb4300a2015-11-23 10:17:23 -0700123#endif
124#ifdef VK_USE_PLATFORM_WAYLAND_KHR
Jon Ashburnf72a04b2015-11-25 17:55:49 -0700125 .CreateWaylandSurfaceKHR = loader_CreateWaylandSurfaceKHR,
Ian Elliott919fa302015-11-24 15:39:10 -0700126 .GetPhysicalDeviceWaylandPresentationSupportKHR = loader_GetPhysicalDeviceWaylandPresentationSupportKHR,
Ian Elliottdb4300a2015-11-23 10:17:23 -0700127#endif
128#ifdef VK_USE_PLATFORM_WIN32_KHR
Jon Ashburnf72a04b2015-11-25 17:55:49 -0700129 .CreateWin32SurfaceKHR = loader_CreateWin32SurfaceKHR,
Ian Elliott919fa302015-11-24 15:39:10 -0700130 .GetPhysicalDeviceWin32PresentationSupportKHR = loader_GetPhysicalDeviceWin32PresentationSupportKHR,
Ian Elliottdb4300a2015-11-23 10:17:23 -0700131#endif
132#ifdef VK_USE_PLATFORM_XCB_KHR
Jon Ashburnf72a04b2015-11-25 17:55:49 -0700133 .CreateXcbSurfaceKHR = loader_CreateXcbSurfaceKHR,
Ian Elliott919fa302015-11-24 15:39:10 -0700134 .GetPhysicalDeviceXcbPresentationSupportKHR = loader_GetPhysicalDeviceXcbPresentationSupportKHR,
Ian Elliottdb4300a2015-11-23 10:17:23 -0700135#endif
136#ifdef VK_USE_PLATFORM_XLIB_KHR
Jon Ashburnf72a04b2015-11-25 17:55:49 -0700137 .CreateXlibSurfaceKHR = loader_CreateXlibSurfaceKHR,
Ian Elliott919fa302015-11-24 15:39:10 -0700138 .GetPhysicalDeviceXlibPresentationSupportKHR = loader_GetPhysicalDeviceXlibPresentationSupportKHR,
Ian Elliottdb4300a2015-11-23 10:17:23 -0700139#endif
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -0700140#ifdef VK_USE_PLATFORM_ANDROID_KHR
141 .CreateAndroidSurfaceKHR = loader_CreateAndroidSurfaceKHR,
142#endif
Jon Ashburn27cd5842015-05-12 17:26:48 -0600143};
144
Jon Ashburn8810c5f2015-08-18 18:04:47 -0600145LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_init);
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700146
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600147void* loader_heap_alloc(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600148 const struct loader_instance *instance,
149 size_t size,
Jon Ashburn39fbd4e2015-12-10 18:17:34 -0700150 VkSystemAllocationScope alloc_scope)
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600151{
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800152 if (instance && instance->alloc_callbacks.pfnAllocation) {
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600153 /* TODO: What should default alignment be? 1, 4, 8, other? */
Jon Ashburn6a118ae2016-01-07 15:21:14 -0700154 return instance->alloc_callbacks.pfnAllocation(instance->alloc_callbacks.pUserData, size, sizeof(int), alloc_scope);
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600155 }
156 return malloc(size);
157}
158
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600159void loader_heap_free(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600160 const struct loader_instance *instance,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800161 void *pMemory)
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600162{
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800163 if (pMemory == NULL) return;
Jon Ashburneacfa3a2015-08-14 12:51:47 -0600164 if (instance && instance->alloc_callbacks.pfnFree) {
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800165 instance->alloc_callbacks.pfnFree(instance->alloc_callbacks.pUserData, pMemory);
Jon Ashburnd2c171b2015-08-13 08:28:48 -0600166 return;
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600167 }
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800168 free(pMemory);
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600169}
170
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600171void* loader_heap_realloc(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600172 const struct loader_instance *instance,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800173 void *pMemory,
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600174 size_t orig_size,
175 size_t size,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800176 VkSystemAllocationScope alloc_scope)
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600177{
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800178 if (pMemory == NULL || orig_size == 0)
Chia-I Wuf7458c52015-10-26 21:10:41 +0800179 return loader_heap_alloc(instance, size, alloc_scope);
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600180 if (size == 0) {
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800181 loader_heap_free(instance, pMemory);
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600182 return NULL;
183 }
Jon Ashburn6a118ae2016-01-07 15:21:14 -0700184 //TODO use the callback realloc function
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 }
Jon Ashburn6a118ae2016-01-07 15:21:14 -0700190 /* TODO: What should default alignment be? 1, 4, 8, other? */
191 void *new_ptr = instance->alloc_callbacks.pfnAllocation(instance->alloc_callbacks.pUserData, size, sizeof(int), alloc_scope);
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600192 if (!new_ptr)
193 return NULL;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800194 memcpy(new_ptr, pMemory, orig_size);
195 instance->alloc_callbacks.pfnFree(instance->alloc_callbacks.pUserData, pMemory);
Jon Ashburne3753b32015-10-21 16:09:27 -0600196 return new_ptr;
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600197 }
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800198 return realloc(pMemory, size);
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600199}
200
Jon Ashburn87d6aa92015-08-28 15:19:27 -0600201void *loader_tls_heap_alloc(size_t size)
202{
Chia-I Wucf804e82015-10-31 00:31:16 +0800203 return loader_heap_alloc(tls_instance, size, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
Jon Ashburn87d6aa92015-08-28 15:19:27 -0600204}
205
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800206void loader_tls_heap_free(void *pMemory)
Jon Ashburn87d6aa92015-08-28 15:19:27 -0600207{
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800208 loader_heap_free(tls_instance, pMemory);
Jon Ashburn87d6aa92015-08-28 15:19:27 -0600209}
210
Courtney Goeltzenleuchter73477392015-12-03 13:48:01 -0700211static void loader_log(const struct loader_instance *inst, VkFlags msg_type, int32_t msg_code,
Jon Ashburnffad94d2015-06-30 14:46:22 -0700212 const char *format, ...)
213{
Jon Ashburn86723b02015-07-31 15:47:59 -0600214 char msg[512];
Jon Ashburnffad94d2015-06-30 14:46:22 -0700215 va_list ap;
216 int ret;
217
Jon Ashburnffad94d2015-06-30 14:46:22 -0700218 va_start(ap, format);
219 ret = vsnprintf(msg, sizeof(msg), format, ap);
220 if ((ret >= (int) sizeof(msg)) || ret < 0) {
221 msg[sizeof(msg)-1] = '\0';
222 }
223 va_end(ap);
224
Courtney Goeltzenleuchter73477392015-12-03 13:48:01 -0700225 if (inst) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700226 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 -0700227 }
228
229 if (!(msg_type & g_loader_log_msgs)) {
230 return;
231 }
232
Ian Elliott4470a302015-02-17 10:33:47 -0700233#if defined(WIN32)
Jon Ashburnffad94d2015-06-30 14:46:22 -0700234 OutputDebugString(msg);
mschottb9cdb782015-07-22 14:11:29 +0200235 OutputDebugString("\n");
Jon Ashburnffad94d2015-06-30 14:46:22 -0700236#endif
237 fputs(msg, stderr);
238 fputc('\n', stderr);
239}
240
241#if defined(WIN32)
Tony Barbourea968902015-07-29 14:26:21 -0600242static char *loader_get_next_path(char *path);
Jon Ashburnffad94d2015-06-30 14:46:22 -0700243/**
244* Find the list of registry files (names within a key) in key "location".
245*
246* This function looks in the registry (hive = DEFAULT_VK_REGISTRY_HIVE) key as given in "location"
247* for a list or name/values which are added to a returned list (function return value).
248* The DWORD values within the key must be 0 or they are skipped.
Jon Ashburne39a4f82015-08-28 13:38:21 -0600249* Function return is a string with a ';' separated list of filenames.
Jon Ashburnffad94d2015-06-30 14:46:22 -0700250* Function return is NULL if no valid name/value pairs are found in the key,
251* or the key is not found.
252*
253* \returns
254* A string list of filenames as pointer.
255* When done using the returned string list, pointer should be freed.
256*/
Jon Ashburne39a4f82015-08-28 13:38:21 -0600257static char *loader_get_registry_files(const struct loader_instance *inst, char *location)
Jon Ashburnffad94d2015-06-30 14:46:22 -0700258{
259 LONG rtn_value;
260 HKEY hive, key;
Piers Daniell524ec732015-11-05 16:58:26 -0700261 DWORD access_flags;
Jon Ashburnffad94d2015-06-30 14:46:22 -0700262 char name[2048];
263 char *out = NULL;
Tony Barbourea968902015-07-29 14:26:21 -0600264 char *loc = location;
265 char *next;
Jon Ashburnffad94d2015-06-30 14:46:22 -0700266 DWORD idx = 0;
267 DWORD name_size = sizeof(name);
268 DWORD value;
269 DWORD total_size = 4096;
270 DWORD value_size = sizeof(value);
Tony Barbourea968902015-07-29 14:26:21 -0600271
272 while(*loc)
273 {
274 next = loader_get_next_path(loc);
275 hive = DEFAULT_VK_REGISTRY_HIVE;
Piers Daniell524ec732015-11-05 16:58:26 -0700276 access_flags = KEY_QUERY_VALUE;
Tony Barbourea968902015-07-29 14:26:21 -0600277 rtn_value = RegOpenKeyEx(hive, loc, 0, access_flags, &key);
278 if (rtn_value != ERROR_SUCCESS) {
Mark Young93ecb1d2016-01-13 13:47:16 -0700279 // We still couldn't find the key, so give up:
280 loc = next;
281 continue;
Jon Ashburnffad94d2015-06-30 14:46:22 -0700282 }
Tony Barbourea968902015-07-29 14:26:21 -0600283
Jon Ashburne39a4f82015-08-28 13:38:21 -0600284 while ((rtn_value = RegEnumValue(key, idx++, name, &name_size, NULL, NULL, (LPBYTE) &value, &value_size)) == ERROR_SUCCESS) {
Tony Barbourea968902015-07-29 14:26:21 -0600285 if (value_size == sizeof(value) && value == 0) {
286 if (out == NULL) {
Courtney Goeltzenleuchter2961e1c2015-11-02 17:43:04 -0700287 out = loader_heap_alloc(inst, total_size, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Tony Barbourea968902015-07-29 14:26:21 -0600288 out[0] = '\0';
289 }
290 else if (strlen(out) + name_size + 1 > total_size) {
Courtney Goeltzenleuchter2961e1c2015-11-02 17:43:04 -0700291 out = loader_heap_realloc(inst, out, total_size, total_size * 2, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Tony Barbourea968902015-07-29 14:26:21 -0600292 total_size *= 2;
293 }
294 if (out == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700295 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 -0600296 return NULL;
297 }
298 if (strlen(out) == 0)
299 snprintf(out, name_size + 1, "%s", name);
300 else
301 snprintf(out + strlen(out), name_size + 2, "%c%s", PATH_SEPERATOR, name);
302 }
303 name_size = 2048;
304 }
305 loc = next;
Jon Ashburnffad94d2015-06-30 14:46:22 -0700306 }
Tony Barbourea968902015-07-29 14:26:21 -0600307
Jon Ashburnffad94d2015-06-30 14:46:22 -0700308 return out;
309}
310
Ian Elliott4470a302015-02-17 10:33:47 -0700311#endif // WIN32
312
Jon Ashburnc7237a72015-08-03 09:08:46 -0600313/**
Daniel Dadap00b4aba2015-09-30 11:50:51 -0500314 * Combine path elements, separating each element with the platform-specific
315 * directory separator, and save the combined string to a destination buffer,
316 * not exceeding the given length. Path elements are given as variadic args,
317 * with a NULL element terminating the list.
318 *
319 * \returns the total length of the combined string, not including an ASCII
320 * NUL termination character. This length may exceed the available storage:
321 * in this case, the written string will be truncated to avoid a buffer
322 * overrun, and the return value will greater than or equal to the storage
323 * size. A NULL argument may be provided as the destination buffer in order
324 * to determine the required string length without actually writing a string.
325 */
326
Courtney Goeltzenleuchter0ef13a02015-12-16 16:19:46 -0700327static size_t loader_platform_combine_path(char *dest, size_t len, ...)
Daniel Dadap00b4aba2015-09-30 11:50:51 -0500328{
Courtney Goeltzenleuchter0ef13a02015-12-16 16:19:46 -0700329 size_t required_len = 0;
Daniel Dadap00b4aba2015-09-30 11:50:51 -0500330 va_list ap;
331 const char *component;
332
333 va_start(ap, len);
334
335 while((component = va_arg(ap, const char *))) {
336 if (required_len > 0) {
337 // This path element is not the first non-empty element; prepend
338 // a directory separator if space allows
339 if (dest && required_len + 1 < len) {
340 snprintf(dest + required_len, len - required_len, "%c",
341 DIRECTORY_SYMBOL);
342 }
343 required_len++;
344 }
345
346 if (dest && required_len < len) {
347 strncpy(dest + required_len, component, len - required_len);
348 }
349 required_len += strlen(component);
350 }
351
352 va_end(ap);
353
354 // strncpy(3) won't add a NUL terminating byte in the event of truncation.
355 if (dest && required_len >= len) {
356 dest[len - 1] = '\0';
357 }
358
359 return required_len;
360}
361
362
363/**
Jon Ashburnc7237a72015-08-03 09:08:46 -0600364 * Given string of three part form "maj.min.pat" convert to a vulkan version
365 * number.
366 */
367static uint32_t loader_make_version(const char *vers_str)
368{
Jon Ashburn432d2762015-09-18 12:53:16 -0600369 uint32_t vers = 0, major=0, minor=0, patch=0;
Jon Ashburnc7237a72015-08-03 09:08:46 -0600370 char *minor_str= NULL;
371 char *patch_str = NULL;
372 char *cstr;
373 char *str;
374
375 if (!vers_str)
376 return vers;
377 cstr = loader_stack_alloc(strlen(vers_str) + 1);
378 strcpy(cstr, vers_str);
379 while ((str = strchr(cstr, '.')) != NULL) {
380 if (minor_str == NULL) {
381 minor_str = str + 1;
382 *str = '\0';
383 major = atoi(cstr);
384 }
385 else if (patch_str == NULL) {
386 patch_str = str + 1;
387 *str = '\0';
388 minor = atoi(minor_str);
389 }
390 else {
391 return vers;
392 }
393 cstr = str + 1;
394 }
395 patch = atoi(patch_str);
396
397 return VK_MAKE_VERSION(major, minor, patch);
398
399}
400
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600401bool compare_vk_extension_properties(const VkExtensionProperties *op1, const VkExtensionProperties *op2)
402{
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800403 return strcmp(op1->extensionName, op2->extensionName) == 0 ? true : false;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600404}
405
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -0600406/**
Jon Ashburnbd6c4882015-07-02 12:59:25 -0600407 * Search the given ext_array for an extension
408 * matching the given vk_ext_prop
409 */
410bool has_vk_extension_property_array(
411 const VkExtensionProperties *vk_ext_prop,
412 const uint32_t count,
413 const VkExtensionProperties *ext_array)
414{
415 for (uint32_t i = 0; i < count; i++) {
416 if (compare_vk_extension_properties(vk_ext_prop, &ext_array[i]))
417 return true;
418 }
419 return false;
420}
421
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -0600422/**
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600423 * Search the given ext_list for an extension
424 * matching the given vk_ext_prop
425 */
426bool has_vk_extension_property(
427 const VkExtensionProperties *vk_ext_prop,
428 const struct loader_extension_list *ext_list)
429{
430 for (uint32_t i = 0; i < ext_list->count; i++) {
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600431 if (compare_vk_extension_properties(&ext_list->list[i], vk_ext_prop))
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600432 return true;
433 }
434 return false;
435}
436
Jon Ashburnb2ef1372015-07-16 17:19:31 -0600437static inline bool loader_is_layer_type_device(const enum layer_type type) {
438 if ((type & VK_LAYER_TYPE_DEVICE_EXPLICIT) ||
439 (type & VK_LAYER_TYPE_DEVICE_IMPLICIT))
440 return true;
441 return false;
442}
443
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600444/*
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -0600445 * Search the given layer list for a layer matching the given layer name
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600446 */
Jon Ashburne13ecc92015-08-03 17:19:30 -0600447static struct loader_layer_properties *loader_get_layer_property(
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600448 const char *name,
449 const struct loader_layer_list *layer_list)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600450{
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600451 for (uint32_t i = 0; i < layer_list->count; i++) {
452 const VkLayerProperties *item = &layer_list->list[i].info;
453 if (strcmp(name, item->layerName) == 0)
454 return &layer_list->list[i];
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600455 }
456 return NULL;
457}
458
Jon Ashburne13ecc92015-08-03 17:19:30 -0600459/**
460 * Get the next unused layer property in the list. Init the property to zero.
461 */
462static struct loader_layer_properties *loader_get_next_layer_property(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600463 const struct loader_instance *inst,
Jon Ashburne13ecc92015-08-03 17:19:30 -0600464 struct loader_layer_list *layer_list)
465{
466 if (layer_list->capacity == 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600467 layer_list->list = loader_heap_alloc(inst,
468 sizeof(struct loader_layer_properties) * 64,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800469 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburne13ecc92015-08-03 17:19:30 -0600470 if (layer_list->list == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700471 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 -0600472 return NULL;
473 }
474 memset(layer_list->list, 0, sizeof(struct loader_layer_properties) * 64);
475 layer_list->capacity = sizeof(struct loader_layer_properties) * 64;
476 }
477
478 // ensure enough room to add an entry
479 if ((layer_list->count + 1) * sizeof (struct loader_layer_properties)
480 > layer_list->capacity) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600481 layer_list->list = loader_heap_realloc(inst, layer_list->list,
482 layer_list->capacity,
483 layer_list->capacity * 2,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800484 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburne13ecc92015-08-03 17:19:30 -0600485 if (layer_list->list == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700486 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburne13ecc92015-08-03 17:19:30 -0600487 "realloc failed for layer list");
488 }
489 layer_list->capacity *= 2;
490 }
491
492 layer_list->count++;
493 return &(layer_list->list[layer_list->count - 1]);
494}
495
496/**
497 * Remove all layer properties entrys from the list
498 */
Jon Ashburne39a4f82015-08-28 13:38:21 -0600499void loader_delete_layer_properties(
500 const struct loader_instance *inst,
501 struct loader_layer_list *layer_list)
Jon Ashburne13ecc92015-08-03 17:19:30 -0600502{
Jon Ashburn39fbd4e2015-12-10 18:17:34 -0700503 uint32_t i, j;
504 struct loader_device_extension_list *dev_ext_list;
Jon Ashburnb82c1852015-08-11 14:49:54 -0600505 if (!layer_list)
506 return;
507
Jon Ashburne13ecc92015-08-03 17:19:30 -0600508 for (i = 0; i < layer_list->count; i++) {
Jon Ashburn6e6a2162015-12-10 08:51:10 -0700509 loader_destroy_generic_list(inst, (struct loader_generic_list *)
510 &layer_list->list[i].instance_extension_list);
Jon Ashburn39fbd4e2015-12-10 18:17:34 -0700511 dev_ext_list = &layer_list->list[i].device_extension_list;
512 if (dev_ext_list->capacity > 0 && dev_ext_list->list->entrypoint_count > 0) {
513 for (j= 0; j < dev_ext_list->list->entrypoint_count; j++) {
514 loader_heap_free(inst, dev_ext_list->list->entrypoints[j]);
515 }
516 loader_heap_free(inst, dev_ext_list->list->entrypoints);
517 }
Jon Ashburn6e6a2162015-12-10 08:51:10 -0700518 loader_destroy_generic_list(inst, (struct loader_generic_list *)
Jon Ashburn39fbd4e2015-12-10 18:17:34 -0700519 dev_ext_list);
Jon Ashburne13ecc92015-08-03 17:19:30 -0600520 }
521 layer_list->count = 0;
522
Jon Ashburnb82c1852015-08-11 14:49:54 -0600523 if (layer_list->capacity > 0) {
524 layer_list->capacity = 0;
Jon Ashburne39a4f82015-08-28 13:38:21 -0600525 loader_heap_free(inst, layer_list->list);
Jon Ashburnb82c1852015-08-11 14:49:54 -0600526 }
Jon Ashburne13ecc92015-08-03 17:19:30 -0600527
528}
529
Courtney Goeltzenleuchterf538ef72015-12-02 14:00:19 -0700530static void loader_add_instance_extensions(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600531 const struct loader_instance *inst,
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -0600532 const PFN_vkEnumerateInstanceExtensionProperties fp_get_props,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600533 const char *lib_name,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600534 struct loader_extension_list *ext_list)
535{
Courtney Goeltzenleuchter36eeb742015-12-21 16:41:47 -0700536 uint32_t i, count = 0;
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600537 VkExtensionProperties *ext_props;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600538 VkResult res;
539
Courtney Goeltzenleuchter5c6cf472015-07-06 22:28:18 -0600540 if (!fp_get_props) {
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -0600541 /* No EnumerateInstanceExtensionProperties defined */
Courtney Goeltzenleuchter5c6cf472015-07-06 22:28:18 -0600542 return;
543 }
544
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600545 res = fp_get_props(NULL, &count, NULL);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600546 if (res != VK_SUCCESS) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700547 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 -0600548 return;
549 }
Jon Ashburn953bb3c2015-06-10 16:11:42 -0600550
Courtney Goeltzenleuchter5c6cf472015-07-06 22:28:18 -0600551 if (count == 0) {
552 /* No ExtensionProperties to report */
553 return;
554 }
555
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600556 ext_props = loader_stack_alloc(count * sizeof(VkExtensionProperties));
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600557
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600558 res = fp_get_props(NULL, &count, ext_props);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600559 if (res != VK_SUCCESS) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700560 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 -0600561 return;
562 }
Tony Barbour59a47322015-06-24 16:06:58 -0600563
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600564 for (i = 0; i < count; i++) {
Courtney Goeltzenleuchter53043732015-07-12 13:20:05 -0600565 char spec_version[64];
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600566
567 snprintf(spec_version, sizeof(spec_version), "%d.%d.%d",
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600568 VK_MAJOR(ext_props[i].specVersion),
569 VK_MINOR(ext_props[i].specVersion),
570 VK_PATCH(ext_props[i].specVersion));
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700571 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
Courtney Goeltzenleuchterf538ef72015-12-02 14:00:19 -0700572 "Instance Extension: %s (%s) version %s",
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800573 ext_props[i].extensionName, lib_name, spec_version);
Jon Ashburne39a4f82015-08-28 13:38:21 -0600574 loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600575 }
576
577 return;
578}
579
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700580/*
581 * Initialize ext_list with the physical device extensions.
582 * The extension properties are passed as inputs in count and ext_props.
583 */
Courtney Goeltzenleuchterf538ef72015-12-02 14:00:19 -0700584static VkResult loader_init_device_extensions(
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700585 const struct loader_instance *inst,
586 struct loader_physical_device *phys_dev,
587 uint32_t count,
588 VkExtensionProperties *ext_props,
589 struct loader_extension_list *ext_list)
590{
591 VkResult res;
592 uint32_t i;
593
Jon Ashburn6e6a2162015-12-10 08:51:10 -0700594 if (!loader_init_generic_list(inst, (struct loader_generic_list *) ext_list,
595 sizeof(VkExtensionProperties))) {
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700596 return VK_ERROR_OUT_OF_HOST_MEMORY;
597 }
598
599 for (i = 0; i < count; i++) {
600 char spec_version[64];
601
602 snprintf(spec_version, sizeof (spec_version), "%d.%d.%d",
603 VK_MAJOR(ext_props[i].specVersion),
604 VK_MINOR(ext_props[i].specVersion),
605 VK_PATCH(ext_props[i].specVersion));
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700606 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
Courtney Goeltzenleuchterf538ef72015-12-02 14:00:19 -0700607 "Device Extension: %s (%s) version %s",
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700608 ext_props[i].extensionName, phys_dev->this_icd->this_icd_lib->lib_name, spec_version);
609 res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
610 if (res != VK_SUCCESS)
611 return res;
612 }
613
614 return VK_SUCCESS;
615}
616
Courtney Goeltzenleuchterf538ef72015-12-02 14:00:19 -0700617static VkResult loader_add_device_extensions(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600618 const struct loader_instance *inst,
Jon Ashburn471f44c2016-01-13 12:51:43 -0700619 struct loader_icd *icd,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600620 VkPhysicalDevice physical_device,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600621 const char *lib_name,
622 struct loader_extension_list *ext_list)
623{
624 uint32_t i, count;
625 VkResult res;
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600626 VkExtensionProperties *ext_props;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600627
Jon Ashburn471f44c2016-01-13 12:51:43 -0700628 res = icd->EnumerateDeviceExtensionProperties(physical_device, NULL, &count, NULL);
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700629 if (res == VK_SUCCESS && count > 0) {
630 ext_props = loader_stack_alloc(count * sizeof (VkExtensionProperties));
631 if (!ext_props)
632 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburn471f44c2016-01-13 12:51:43 -0700633 res = icd->EnumerateDeviceExtensionProperties(physical_device, NULL, &count, ext_props);
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700634 if (res != VK_SUCCESS)
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700635 return res;
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700636 for (i = 0; i < count; i++) {
637 char spec_version[64];
638
639 snprintf(spec_version, sizeof (spec_version), "%d.%d.%d",
640 VK_MAJOR(ext_props[i].specVersion),
641 VK_MINOR(ext_props[i].specVersion),
642 VK_PATCH(ext_props[i].specVersion));
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700643 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
Courtney Goeltzenleuchterf538ef72015-12-02 14:00:19 -0700644 "Device Extension: %s (%s) version %s",
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700645 ext_props[i].extensionName, lib_name, spec_version);
646 res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
647 if (res != VK_SUCCESS)
648 return res;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600649 }
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700650 } else {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700651 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 -0700652 return res;
653 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600654
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700655 return VK_SUCCESS;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600656}
657
Jon Ashburn6e6a2162015-12-10 08:51:10 -0700658static bool loader_init_generic_list(const struct loader_instance *inst,
659 struct loader_generic_list *list_info,
660 size_t element_size)
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600661{
Jon Ashburn6e6a2162015-12-10 08:51:10 -0700662 list_info->capacity = 32 * element_size;
663 list_info->list = loader_heap_alloc(inst, list_info->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
664 if (list_info->list == NULL) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600665 return false;
666 }
Jon Ashburn6e6a2162015-12-10 08:51:10 -0700667 memset(list_info->list, 0, list_info->capacity);
668 list_info->count = 0;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600669 return true;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600670}
671
Jon Ashburn6e6a2162015-12-10 08:51:10 -0700672void loader_destroy_generic_list(const struct loader_instance *inst,
673 struct loader_generic_list *list)
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600674{
Jon Ashburn6e6a2162015-12-10 08:51:10 -0700675 loader_heap_free(inst, list->list);
676 list->count = 0;
677 list->capacity = 0;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600678}
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600679
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600680/*
681 * Append non-duplicate extension properties defined in props
682 * to the given ext_list.
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700683 * Return
684 * Vk_SUCCESS on success
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600685 */
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700686VkResult loader_add_to_ext_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600687 const struct loader_instance *inst,
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600688 struct loader_extension_list *ext_list,
689 uint32_t prop_list_count,
690 const VkExtensionProperties *props)
691{
692 uint32_t i;
693 const VkExtensionProperties *cur_ext;
694
695 if (ext_list->list == NULL || ext_list->capacity == 0) {
Jon Ashburn6e6a2162015-12-10 08:51:10 -0700696 loader_init_generic_list(inst, (struct loader_generic_list *) ext_list,
697 sizeof(VkExtensionProperties));
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600698 }
699
700 if (ext_list->list == NULL)
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700701 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600702
703 for (i = 0; i < prop_list_count; i++) {
704 cur_ext = &props[i];
705
706 // look for duplicates
707 if (has_vk_extension_property(cur_ext, ext_list)) {
708 continue;
709 }
710
711 // add to list at end
712 // check for enough capacity
713 if (ext_list->count * sizeof(VkExtensionProperties)
714 >= ext_list->capacity) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600715
716 ext_list->list = loader_heap_realloc(inst,
717 ext_list->list,
718 ext_list->capacity,
719 ext_list->capacity * 2,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800720 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700721
722 if (ext_list->list == NULL)
723 return VK_ERROR_OUT_OF_HOST_MEMORY;
724
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600725 // double capacity
726 ext_list->capacity *= 2;
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600727 }
728
729 memcpy(&ext_list->list[ext_list->count], cur_ext, sizeof(VkExtensionProperties));
730 ext_list->count++;
731 }
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700732 return VK_SUCCESS;
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600733}
734
Jon Ashburn39fbd4e2015-12-10 18:17:34 -0700735/*
736 * Append one extension property defined in props with entrypoints
737 * defined in entrys to the given ext_list.
738 * Return
739 * Vk_SUCCESS on success
740 */
741VkResult loader_add_to_dev_ext_list(
742 const struct loader_instance *inst,
743 struct loader_device_extension_list *ext_list,
744 const VkExtensionProperties *props,
745 uint32_t entry_count,
746 char **entrys)
747{
748 uint32_t idx;
749 if (ext_list->list == NULL || ext_list->capacity == 0) {
750 loader_init_generic_list(inst, (struct loader_generic_list *) ext_list,
751 sizeof(struct loader_dev_ext_props));
752 }
753
754 if (ext_list->list == NULL)
755 return VK_ERROR_OUT_OF_HOST_MEMORY;
756
757 idx =ext_list->count;
758 // add to list at end
759 // check for enough capacity
760 if (idx * sizeof (struct loader_dev_ext_props)
761 >= ext_list->capacity) {
762
763 ext_list->list = loader_heap_realloc(inst,
764 ext_list->list,
765 ext_list->capacity,
766 ext_list->capacity * 2,
767 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
768
769 if (ext_list->list == NULL)
770 return VK_ERROR_OUT_OF_HOST_MEMORY;
771
772 // double capacity
773 ext_list->capacity *= 2;
774 }
775
776 memcpy(&ext_list->list[idx].props, props, sizeof(struct loader_dev_ext_props));
777 ext_list->list[idx].entrypoint_count = entry_count;
778 ext_list->list[idx].entrypoints = loader_heap_alloc(inst,
779 sizeof(char *) * entry_count,
780 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
781 if (ext_list->list[idx].entrypoints == NULL)
782 return VK_ERROR_OUT_OF_HOST_MEMORY;
783 for (uint32_t i = 0; i < entry_count; i++) {
784 ext_list->list[idx].entrypoints[i] = loader_heap_alloc(inst,
785 strlen(entrys[i]) + 1,
786 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
787 if (ext_list->list[idx].entrypoints[i] == NULL)
788 return VK_ERROR_OUT_OF_HOST_MEMORY;
789 strcpy(ext_list->list[idx].entrypoints[i], entrys[i]);
790 }
791 ext_list->count++;
792
793 return VK_SUCCESS;
794}
795
Jon Ashburnbd6c4882015-07-02 12:59:25 -0600796/**
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600797 * Search the given search_list for any layers in the props list.
798 * Add these to the output layer_list. Don't add duplicates to the output layer_list.
Jon Ashburnbd6c4882015-07-02 12:59:25 -0600799 */
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -0600800static VkResult loader_add_layer_names_to_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600801 const struct loader_instance *inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600802 struct loader_layer_list *output_list,
803 uint32_t name_count,
804 const char * const *names,
805 const struct loader_layer_list *search_list)
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600806{
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600807 struct loader_layer_properties *layer_prop;
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -0600808 VkResult err = VK_SUCCESS;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600809
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600810 for (uint32_t i = 0; i < name_count; i++) {
811 const char *search_target = names[i];
Jon Ashburne13ecc92015-08-03 17:19:30 -0600812 layer_prop = loader_get_layer_property(search_target, search_list);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600813 if (!layer_prop) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700814 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Unable to find layer %s", search_target);
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -0600815 err = VK_ERROR_LAYER_NOT_PRESENT;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600816 continue;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600817 }
818
Jon Ashburne39a4f82015-08-28 13:38:21 -0600819 loader_add_to_layer_list(inst, output_list, 1, layer_prop);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600820 }
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -0600821
822 return err;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600823}
824
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600825
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600826/*
827 * Manage lists of VkLayerProperties
828 */
Jon Ashburne39a4f82015-08-28 13:38:21 -0600829static bool loader_init_layer_list(const struct loader_instance *inst,
830 struct loader_layer_list *list)
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600831{
832 list->capacity = 32 * sizeof(struct loader_layer_properties);
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800833 list->list = loader_heap_alloc(inst, list->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600834 if (list->list == NULL) {
835 return false;
836 }
837 memset(list->list, 0, list->capacity);
838 list->count = 0;
839 return true;
840}
841
Jon Ashburne39a4f82015-08-28 13:38:21 -0600842void loader_destroy_layer_list(const struct loader_instance *inst,
843 struct loader_layer_list *layer_list)
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600844{
Jon Ashburne39a4f82015-08-28 13:38:21 -0600845 loader_heap_free(inst, layer_list->list);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600846 layer_list->count = 0;
847 layer_list->capacity = 0;
848}
849
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600850/*
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600851 * Manage list of layer libraries (loader_lib_info)
852 */
Jon Ashburne39a4f82015-08-28 13:38:21 -0600853static bool loader_init_layer_library_list(const struct loader_instance *inst,
854 struct loader_layer_library_list *list)
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600855{
856 list->capacity = 32 * sizeof(struct loader_lib_info);
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800857 list->list = loader_heap_alloc(inst, list->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600858 if (list->list == NULL) {
859 return false;
860 }
861 memset(list->list, 0, list->capacity);
862 list->count = 0;
863 return true;
864}
865
Jon Ashburne39a4f82015-08-28 13:38:21 -0600866void loader_destroy_layer_library_list(const struct loader_instance *inst,
867 struct loader_layer_library_list *list)
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600868{
869 for (uint32_t i = 0; i < list->count; i++) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600870 loader_heap_free(inst, list->list[i].lib_name);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600871 }
Jon Ashburne39a4f82015-08-28 13:38:21 -0600872 loader_heap_free(inst, list->list);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600873 list->count = 0;
874 list->capacity = 0;
875}
876
877void loader_add_to_layer_library_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600878 const struct loader_instance *inst,
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600879 struct loader_layer_library_list *list,
880 uint32_t item_count,
881 const struct loader_lib_info *new_items)
882{
883 uint32_t i;
884 struct loader_lib_info *item;
885
886 if (list->list == NULL || list->capacity == 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600887 loader_init_layer_library_list(inst, list);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600888 }
889
890 if (list->list == NULL)
891 return;
892
893 for (i = 0; i < item_count; i++) {
894 item = (struct loader_lib_info *) &new_items[i];
895
896 // look for duplicates
897 for (uint32_t j = 0; j < list->count; j++) {
898 if (strcmp(list->list[i].lib_name, new_items->lib_name) == 0) {
899 continue;
900 }
901 }
902
903 // add to list at end
904 // check for enough capacity
905 if (list->count * sizeof(struct loader_lib_info)
906 >= list->capacity) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600907
908 list->list = loader_heap_realloc(inst,
909 list->list,
910 list->capacity,
911 list->capacity * 2,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800912 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600913 // double capacity
914 list->capacity *= 2;
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600915 }
916
917 memcpy(&list->list[list->count], item, sizeof(struct loader_lib_info));
918 list->count++;
919 }
920}
921
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600922
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600923/*
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600924 * Search the given layer list for a list
925 * matching the given VkLayerProperties
926 */
927bool has_vk_layer_property(
928 const VkLayerProperties *vk_layer_prop,
929 const struct loader_layer_list *list)
930{
931 for (uint32_t i = 0; i < list->count; i++) {
932 if (strcmp(vk_layer_prop->layerName, list->list[i].info.layerName) == 0)
933 return true;
934 }
935 return false;
936}
937
938/*
939 * Search the given layer list for a layer
940 * matching the given name
941 */
942bool has_layer_name(
943 const char *name,
944 const struct loader_layer_list *list)
945{
946 for (uint32_t i = 0; i < list->count; i++) {
947 if (strcmp(name, list->list[i].info.layerName) == 0)
948 return true;
949 }
950 return false;
951}
952
953/*
954 * Append non-duplicate layer properties defined in prop_list
955 * to the given layer_info list
956 */
957void loader_add_to_layer_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600958 const struct loader_instance *inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600959 struct loader_layer_list *list,
960 uint32_t prop_list_count,
961 const struct loader_layer_properties *props)
962{
963 uint32_t i;
964 struct loader_layer_properties *layer;
965
966 if (list->list == NULL || list->capacity == 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600967 loader_init_layer_list(inst, list);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600968 }
969
970 if (list->list == NULL)
971 return;
972
973 for (i = 0; i < prop_list_count; i++) {
974 layer = (struct loader_layer_properties *) &props[i];
975
976 // look for duplicates
977 if (has_vk_layer_property(&layer->info, list)) {
978 continue;
979 }
980
981 // add to list at end
982 // check for enough capacity
983 if (list->count * sizeof(struct loader_layer_properties)
984 >= list->capacity) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600985
986 list->list = loader_heap_realloc(inst,
987 list->list,
988 list->capacity,
989 list->capacity * 2,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800990 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600991 // double capacity
992 list->capacity *= 2;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600993 }
994
995 memcpy(&list->list[list->count], layer, sizeof(struct loader_layer_properties));
996 list->count++;
997 }
998}
999
Jon Ashburnbd332cc2015-07-07 10:27:45 -06001000/**
1001 * Search the search_list for any layer with a name
1002 * that matches the given name and a type that matches the given type
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06001003 * Add all matching layers to the found_list
Jon Ashburnbd332cc2015-07-07 10:27:45 -06001004 * Do not add if found loader_layer_properties is already
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06001005 * on the found_list.
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001006 */
Jon Ashburnbd6c4882015-07-02 12:59:25 -06001007static void loader_find_layer_name_add_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -06001008 const struct loader_instance *inst,
Jon Ashburnbd6c4882015-07-02 12:59:25 -06001009 const char *name,
Jon Ashburnbd332cc2015-07-07 10:27:45 -06001010 const enum layer_type type,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06001011 const struct loader_layer_list *search_list,
1012 struct loader_layer_list *found_list)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001013{
Jon Ashburn56151d62015-10-05 09:03:21 -06001014 bool found = false;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001015 for (uint32_t i = 0; i < search_list->count; i++) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06001016 struct loader_layer_properties *layer_prop = &search_list->list[i];
Jon Ashburnbd332cc2015-07-07 10:27:45 -06001017 if (0 == strcmp(layer_prop->info.layerName, name) &&
1018 (layer_prop->type & type)) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06001019 /* Found a layer with the same name, add to found_list */
Jon Ashburne39a4f82015-08-28 13:38:21 -06001020 loader_add_to_layer_list(inst, found_list, 1, layer_prop);
Jon Ashburn56151d62015-10-05 09:03:21 -06001021 found = true;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001022 }
1023 }
Jon Ashburn56151d62015-10-05 09:03:21 -06001024 if (!found) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001025 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 -06001026 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001027}
1028
Jon Ashburn5c042ea2015-08-04 11:14:18 -06001029static VkExtensionProperties *get_extension_property(
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06001030 const char *name,
1031 const struct loader_extension_list *list)
Jon Ashburnfc2e38c2015-04-14 09:15:32 -06001032{
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06001033 for (uint32_t i = 0; i < list->count; i++) {
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001034 if (strcmp(name, list->list[i].extensionName) == 0)
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06001035 return &list->list[i];
Jon Ashburnfc2e38c2015-04-14 09:15:32 -06001036 }
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06001037 return NULL;
Jon Ashburnfc2e38c2015-04-14 09:15:32 -06001038}
1039
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001040static VkExtensionProperties *get_dev_extension_property(
1041 const char *name,
1042 const struct loader_device_extension_list *list)
1043{
1044 for (uint32_t i = 0; i < list->count; i++) {
1045 if (strcmp(name, list->list[i].props.extensionName) == 0)
1046 return &list->list[i].props;
1047 }
1048 return NULL;
1049}
1050
Jon Ashburnbd6c4882015-07-02 12:59:25 -06001051/*
Courtney Goeltzenleuchterb39ccd52016-01-15 14:15:00 -07001052 * This function will return the pNext pointer of any
1053 * CreateInfo extensions that are not loader extensions.
1054 * This is used to skip past the loader extensions prepended
1055 * to the list during CreateInstance and CreateDevice.
1056 */
1057void *loader_strip_create_extensions(const void *pNext)
1058{
1059 VkLayerInstanceCreateInfo *create_info = (VkLayerInstanceCreateInfo *) pNext;
1060
1061 while (create_info && (create_info->sType == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO ||
1062 create_info->sType == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO)) {
1063 create_info = (VkLayerInstanceCreateInfo *) create_info->pNext;
1064 }
1065
1066 return create_info;
1067}
1068
1069/*
Courtney Goeltzenleuchterf538ef72015-12-02 14:00:19 -07001070 * For Instance extensions implemented within the loader (i.e. DEBUG_REPORT
Jon Ashburnbd6c4882015-07-02 12:59:25 -06001071 * the extension must provide two entry points for the loader to use:
1072 * - "trampoline" entry point - this is the address returned by GetProcAddr
1073 * and will always do what's necessary to support a global call.
1074 * - "terminator" function - this function will be put at the end of the
Jon Ashburn232e3af2015-11-30 17:21:25 -07001075 * instance chain and will contain the necessary logic to call / process
Jon Ashburnbd6c4882015-07-02 12:59:25 -06001076 * the extension for the appropriate ICDs that are available.
1077 * There is no generic mechanism for including these functions, the references
1078 * must be placed into the appropriate loader entry points.
1079 * GetInstanceProcAddr: call extension GetInstanceProcAddr to check for GetProcAddr requests
1080 * loader_coalesce_extensions(void) - add extension records to the list of global
1081 * extension available to the app.
1082 * instance_disp - add function pointer for terminator function to this array.
1083 * The extension itself should be in a separate file that will be
1084 * linked directly with the loader.
1085 */
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06001086
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001087void loader_get_icd_loader_instance_extensions(
Jon Ashburne39a4f82015-08-28 13:38:21 -06001088 const struct loader_instance *inst,
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001089 struct loader_icd_libs *icd_libs,
1090 struct loader_extension_list *inst_exts)
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001091{
Jon Ashburn5c6a46f2015-08-14 14:49:22 -06001092 struct loader_extension_list icd_exts;
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001093 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Build ICD instance extension list");
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001094 // traverse scanned icd list adding non-duplicate extensions to the list
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001095 for (uint32_t i = 0; i < icd_libs->count; i++) {
Jon Ashburn6e6a2162015-12-10 08:51:10 -07001096 loader_init_generic_list(inst, (struct loader_generic_list *) &icd_exts,
1097 sizeof(VkExtensionProperties));
Courtney Goeltzenleuchterf538ef72015-12-02 14:00:19 -07001098 loader_add_instance_extensions(inst, icd_libs->list[i].EnumerateInstanceExtensionProperties,
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001099 icd_libs->list[i].lib_name,
Jon Ashburn5c6a46f2015-08-14 14:49:22 -06001100 &icd_exts);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001101 loader_add_to_ext_list(inst, inst_exts,
Jon Ashburn5c6a46f2015-08-14 14:49:22 -06001102 icd_exts.count,
1103 icd_exts.list);
Jon Ashburn6e6a2162015-12-10 08:51:10 -07001104 loader_destroy_generic_list(inst, (struct loader_generic_list *) &icd_exts);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001105 };
1106
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001107 // Traverse loader's extensions, adding non-duplicate extensions to the list
Ian Elliott954fa342015-10-30 15:28:23 -06001108 wsi_add_instance_extensions(inst, inst_exts);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001109 debug_report_add_instance_extensions(inst, inst_exts);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001110}
1111
Jon Ashburn46674bf2015-12-11 09:41:34 -07001112struct loader_physical_device *loader_get_physical_device(const VkPhysicalDevice physdev)
1113{
1114 uint32_t i;
1115 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
1116 for (i = 0; i < inst->total_gpu_count; i++) {
1117 //TODO this aliases physDevices within instances, need for this
1118 // function to go away
1119 if (inst->phys_devs[i].disp == loader_get_instance_dispatch(physdev)) {
1120 return &inst->phys_devs[i];
1121 }
1122 }
1123 }
1124 return NULL;
1125}
1126
Jon Ashburne39a4f82015-08-28 13:38:21 -06001127struct loader_icd *loader_get_icd_and_device(const VkDevice device,
1128 struct loader_device **found_dev)
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001129{
1130 *found_dev = NULL;
1131 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
1132 for (struct loader_icd *icd = inst->icds; icd; icd = icd->next) {
1133 for (struct loader_device *dev = icd->logical_device_list; dev; dev = dev->next)
Jon Ashburne0e64572015-09-30 12:56:42 -06001134 /* Value comparison of device prevents object wrapping by layers */
1135 if (loader_get_dispatch(dev->device) == loader_get_dispatch(device)) {
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001136 *found_dev = dev;
1137 return icd;
1138 }
1139 }
1140 }
1141 return NULL;
1142}
1143
Jon Ashburne39a4f82015-08-28 13:38:21 -06001144static void loader_destroy_logical_device(const struct loader_instance *inst,
1145 struct loader_device *dev)
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001146{
Jon Ashburne39a4f82015-08-28 13:38:21 -06001147 loader_heap_free(inst, dev->app_extension_props);
BogDan Vatra9ef09832016-01-04 14:05:49 +02001148 loader_destroy_layer_list(inst, &dev->activated_layer_list);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001149 loader_heap_free(inst, dev);
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001150}
1151
Jon Ashburne39a4f82015-08-28 13:38:21 -06001152static struct loader_device *loader_add_logical_device(
1153 const struct loader_instance *inst,
Jon Ashburne39a4f82015-08-28 13:38:21 -06001154 struct loader_device **device_list)
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001155{
1156 struct loader_device *new_dev;
1157
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001158 new_dev = loader_heap_alloc(inst, sizeof(struct loader_device), VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001159 if (!new_dev) {
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07001160 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Failed to alloc struct loader-device");
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001161 return NULL;
1162 }
1163
1164 memset(new_dev, 0, sizeof(struct loader_device));
1165
1166 new_dev->next = *device_list;
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001167 *device_list = new_dev;
1168 return new_dev;
1169}
1170
Jon Ashburne39a4f82015-08-28 13:38:21 -06001171void loader_remove_logical_device(
1172 const struct loader_instance *inst,
Jon Ashburn781a7ae2015-11-19 15:43:26 -07001173 struct loader_icd *icd,
1174 struct loader_device *found_dev)
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001175{
Jon Ashburn781a7ae2015-11-19 15:43:26 -07001176 struct loader_device *dev, *prev_dev;
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001177
1178 if (!icd || !found_dev)
1179 return;
1180
1181 prev_dev = NULL;
1182 dev = icd->logical_device_list;
1183 while (dev && dev != found_dev) {
1184 prev_dev = dev;
1185 dev = dev->next;
1186 }
1187
1188 if (prev_dev)
1189 prev_dev->next = found_dev->next;
1190 else
1191 icd->logical_device_list = found_dev->next;
Jon Ashburne39a4f82015-08-28 13:38:21 -06001192 loader_destroy_logical_device(inst, found_dev);
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001193}
1194
1195
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001196static void loader_icd_destroy(
1197 struct loader_instance *ptr_inst,
1198 struct loader_icd *icd)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001199{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001200 ptr_inst->total_icd_count--;
Courtney Goeltzenleuchter1f157ac2015-06-14 19:57:15 -06001201 for (struct loader_device *dev = icd->logical_device_list; dev; ) {
1202 struct loader_device *next_dev = dev->next;
Jon Ashburne39a4f82015-08-28 13:38:21 -06001203 loader_destroy_logical_device(ptr_inst, dev);
Courtney Goeltzenleuchter1f157ac2015-06-14 19:57:15 -06001204 dev = next_dev;
1205 }
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001206
Jon Ashburne39a4f82015-08-28 13:38:21 -06001207 loader_heap_free(ptr_inst, icd);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001208}
1209
Jon Ashburne39a4f82015-08-28 13:38:21 -06001210static struct loader_icd * loader_icd_create(const struct loader_instance *inst)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001211{
1212 struct loader_icd *icd;
1213
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001214 icd = loader_heap_alloc(inst, sizeof(*icd), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001215 if (!icd)
1216 return NULL;
1217
Courtney Goeltzenleuchter55001bb2014-10-28 10:29:27 -06001218 memset(icd, 0, sizeof(*icd));
1219
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001220 return icd;
1221}
1222
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001223static struct loader_icd *loader_icd_add(
1224 struct loader_instance *ptr_inst,
Jon Ashburn3d002332015-08-20 16:35:30 -06001225 const struct loader_scanned_icds *icd_lib)
Chia-I Wu13a61a52014-08-04 11:18:20 +08001226{
1227 struct loader_icd *icd;
1228
Jon Ashburne39a4f82015-08-28 13:38:21 -06001229 icd = loader_icd_create(ptr_inst);
Chia-I Wu13a61a52014-08-04 11:18:20 +08001230 if (!icd)
1231 return NULL;
1232
Jon Ashburn3d002332015-08-20 16:35:30 -06001233 icd->this_icd_lib = icd_lib;
1234 icd->this_instance = ptr_inst;
1235
Chia-I Wu13a61a52014-08-04 11:18:20 +08001236 /* prepend to the list */
Jon Ashburn46888392015-01-29 15:45:51 -07001237 icd->next = ptr_inst->icds;
1238 ptr_inst->icds = icd;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001239 ptr_inst->total_icd_count++;
Chia-I Wu13a61a52014-08-04 11:18:20 +08001240
1241 return icd;
1242}
1243
Jon Ashburne39a4f82015-08-28 13:38:21 -06001244void loader_scanned_icd_clear(
1245 const struct loader_instance *inst,
1246 struct loader_icd_libs *icd_libs)
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001247{
1248 if (icd_libs->capacity == 0)
1249 return;
1250 for (uint32_t i = 0; i < icd_libs->count; i++) {
1251 loader_platform_close_library(icd_libs->list[i].handle);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001252 loader_heap_free(inst, icd_libs->list[i].lib_name);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001253 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06001254 loader_heap_free(inst, icd_libs->list);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001255 icd_libs->capacity = 0;
1256 icd_libs->count = 0;
1257 icd_libs->list = NULL;
1258}
1259
Jon Ashburne39a4f82015-08-28 13:38:21 -06001260static void loader_scanned_icd_init(const struct loader_instance *inst,
1261 struct loader_icd_libs *icd_libs)
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001262{
Jon Ashburne39a4f82015-08-28 13:38:21 -06001263 loader_scanned_icd_clear(inst, icd_libs);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001264 icd_libs->capacity = 8 * sizeof(struct loader_scanned_icds);
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001265 icd_libs->list = loader_heap_alloc(inst, icd_libs->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001266
1267}
1268
1269static void loader_scanned_icd_add(
Jon Ashburne39a4f82015-08-28 13:38:21 -06001270 const struct loader_instance *inst,
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001271 struct loader_icd_libs *icd_libs,
Jon Ashburn005617f2015-11-17 17:35:40 -07001272 const char *filename,
1273 uint32_t api_version)
Jon Ashburn46d1f582015-01-28 11:01:35 -07001274{
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001275 loader_platform_dl_handle handle;
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06001276 PFN_vkCreateInstance fp_create_inst;
Jon Ashburnfd4d09d2016-01-07 09:44:27 -07001277 PFN_vkEnumerateInstanceExtensionProperties fp_get_inst_ext_props;
Jon Ashburnc624c882015-07-16 10:17:29 -06001278 PFN_vkGetInstanceProcAddr fp_get_proc_addr;
Jon Ashburn46d1f582015-01-28 11:01:35 -07001279 struct loader_scanned_icds *new_node;
1280
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001281 /* TODO implement ref counting of libraries, for now this function leaves
1282 libraries open and the scanned_icd_clear closes them */
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001283 // Used to call: dlopen(filename, RTLD_LAZY);
1284 handle = loader_platform_open_library(filename);
Jon Ashburn46d1f582015-01-28 11:01:35 -07001285 if (!handle) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001286 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0, loader_platform_open_library_error(filename));
Jon Ashburn46d1f582015-01-28 11:01:35 -07001287 return;
1288 }
1289
Jon Ashburnfd4d09d2016-01-07 09:44:27 -07001290 fp_get_proc_addr = loader_platform_get_proc_address(handle, "vk_icdGetInstanceProcAddr");
1291 if (!fp_get_proc_addr) {
Jon Ashburn69a5f7a2016-01-11 14:41:35 -07001292 // Use deprecated interface
Jon Ashburnfd4d09d2016-01-07 09:44:27 -07001293 fp_get_proc_addr = loader_platform_get_proc_address(handle, "vkGetInstanceProcAddr");
1294 if (!fp_get_proc_addr) {
1295 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, loader_platform_get_proc_address_error("vk_icdGetInstanceProcAddr"));
1296 return;
1297 } else {
1298 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0, "Using deprecated ICD interface of vkGetInstanceProcAddr instead of vk_icdGetInstanceProcAddr");
1299 }
Jon Ashburn69a5f7a2016-01-11 14:41:35 -07001300 fp_create_inst = loader_platform_get_proc_address(handle, "vkCreateInstance");
1301 if (!fp_create_inst) {
1302 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Couldn't get vkCreateInstance via dlsym/loadlibrary from ICD");
1303 return;
1304 }
1305 fp_get_inst_ext_props = loader_platform_get_proc_address(handle, "vkEnumerateInstanceExtensionProperties");
1306 if (!fp_get_inst_ext_props) {
1307 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Couldn't get vkEnumerateInstanceExtensionProperties via dlsym/loadlibrary from ICD");
1308 return;
1309 }
Jon Ashburnfd4d09d2016-01-07 09:44:27 -07001310 }
Jon Ashburn69a5f7a2016-01-11 14:41:35 -07001311 else {
1312 // Use newer interface
1313 fp_create_inst = (PFN_vkCreateInstance) fp_get_proc_addr(NULL, "vkCreateInstance");
1314 if (!fp_create_inst) {
1315 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Couldn't get vkCreateInstance via vk_icdGetInstanceProcAddr from ICD");
1316 return;
1317 }
1318 fp_get_inst_ext_props = (PFN_vkEnumerateInstanceExtensionProperties)fp_get_proc_addr(NULL, "vkEnumerateInstanceExtensionProperties");
1319 if (!fp_get_inst_ext_props) {
1320 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Couldn't get vkEnumerateInstanceExtensionProperties via vk_icdGetInstanceProcAddr from ICD");
1321 return;
1322 }
Jon Ashburnfd4d09d2016-01-07 09:44:27 -07001323 }
Jon Ashburn46d1f582015-01-28 11:01:35 -07001324
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001325 // check for enough capacity
1326 if ((icd_libs->count * sizeof(struct loader_scanned_icds)) >= icd_libs->capacity) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06001327
1328 icd_libs->list = loader_heap_realloc(inst,
1329 icd_libs->list,
1330 icd_libs->capacity,
1331 icd_libs->capacity * 2,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001332 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001333 // double capacity
1334 icd_libs->capacity *= 2;
Jon Ashburn46d1f582015-01-28 11:01:35 -07001335 }
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001336 new_node = &(icd_libs->list[icd_libs->count]);
Jon Ashburn46d1f582015-01-28 11:01:35 -07001337
1338 new_node->handle = handle;
Jon Ashburn005617f2015-11-17 17:35:40 -07001339 new_node->api_version = api_version;
Jon Ashburnc624c882015-07-16 10:17:29 -06001340 new_node->GetInstanceProcAddr = fp_get_proc_addr;
Jon Ashburnfd4d09d2016-01-07 09:44:27 -07001341 new_node->EnumerateInstanceExtensionProperties = fp_get_inst_ext_props;
Jon Ashburn46888392015-01-29 15:45:51 -07001342 new_node->CreateInstance = fp_create_inst;
Jon Ashburn46d1f582015-01-28 11:01:35 -07001343
Jon Ashburne39a4f82015-08-28 13:38:21 -06001344 new_node->lib_name = (char *) loader_heap_alloc(inst,
1345 strlen(filename) + 1,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001346 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001347 if (!new_node->lib_name) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001348 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0, "Out of memory can't add icd");
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001349 return;
1350 }
1351 strcpy(new_node->lib_name, filename);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001352 icd_libs->count++;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001353}
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001354
Jon Ashburnc624c882015-07-16 10:17:29 -06001355static bool loader_icd_init_entrys(struct loader_icd *icd,
1356 VkInstance inst,
1357 const PFN_vkGetInstanceProcAddr fp_gipa)
Jon Ashburn3da71f22015-05-14 12:43:38 -06001358{
1359 /* initialize entrypoint function pointers */
1360
Jon Ashburnc624c882015-07-16 10:17:29 -06001361 #define LOOKUP_GIPA(func, required) do { \
1362 icd->func = (PFN_vk ##func) fp_gipa(inst, "vk" #func); \
1363 if (!icd->func && required) { \
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001364 loader_log((struct loader_instance *) inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0, \
Jon Ashburnc624c882015-07-16 10:17:29 -06001365 loader_platform_get_proc_address_error("vk" #func)); \
1366 return false; \
1367 } \
Jon Ashburn3da71f22015-05-14 12:43:38 -06001368 } while (0)
1369
Jon Ashburnc624c882015-07-16 10:17:29 -06001370 LOOKUP_GIPA(GetDeviceProcAddr, true);
1371 LOOKUP_GIPA(DestroyInstance, true);
1372 LOOKUP_GIPA(EnumeratePhysicalDevices, true);
1373 LOOKUP_GIPA(GetPhysicalDeviceFeatures, true);
1374 LOOKUP_GIPA(GetPhysicalDeviceFormatProperties, true);
Jon Ashburn754864f2015-07-23 18:49:07 -06001375 LOOKUP_GIPA(GetPhysicalDeviceImageFormatProperties, true);
Jon Ashburnc624c882015-07-16 10:17:29 -06001376 LOOKUP_GIPA(CreateDevice, true);
1377 LOOKUP_GIPA(GetPhysicalDeviceProperties, true);
1378 LOOKUP_GIPA(GetPhysicalDeviceMemoryProperties, true);
Cody Northropd0802882015-08-03 17:04:53 -06001379 LOOKUP_GIPA(GetPhysicalDeviceQueueFamilyProperties, true);
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06001380 LOOKUP_GIPA(EnumerateDeviceExtensionProperties, true);
Jon Ashburnc624c882015-07-16 10:17:29 -06001381 LOOKUP_GIPA(GetPhysicalDeviceSparseImageFormatProperties, true);
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001382 LOOKUP_GIPA(CreateDebugReportCallbackEXT, false);
1383 LOOKUP_GIPA(DestroyDebugReportCallbackEXT, false);
Ian Elliott7e40db92015-08-21 15:09:33 -06001384 LOOKUP_GIPA(GetPhysicalDeviceSurfaceSupportKHR, false);
Ian Elliott486c5502015-11-19 16:05:09 -07001385 LOOKUP_GIPA(GetPhysicalDeviceSurfaceCapabilitiesKHR, false);
1386 LOOKUP_GIPA(GetPhysicalDeviceSurfaceFormatsKHR, false);
1387 LOOKUP_GIPA(GetPhysicalDeviceSurfacePresentModesKHR, false);
Ian Elliott919fa302015-11-24 15:39:10 -07001388#ifdef VK_USE_PLATFORM_WIN32_KHR
1389 LOOKUP_GIPA(GetPhysicalDeviceWin32PresentationSupportKHR, false);
1390#endif
1391#ifdef VK_USE_PLATFORM_XCB_KHR
1392 LOOKUP_GIPA(GetPhysicalDeviceXcbPresentationSupportKHR, false);
1393#endif
Jon Ashburn3da71f22015-05-14 12:43:38 -06001394
Jon Ashburnc624c882015-07-16 10:17:29 -06001395#undef LOOKUP_GIPA
Ian Elliottd3ef02f2015-07-06 14:36:13 -06001396
Jon Ashburnc624c882015-07-16 10:17:29 -06001397 return true;
Jon Ashburn3da71f22015-05-14 12:43:38 -06001398}
1399
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001400static void loader_debug_init(void)
1401{
Jon Ashburn38a497f2016-01-04 14:01:38 -07001402 const char *env, *orig;
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001403
1404 if (g_loader_debug > 0)
1405 return;
1406
1407 g_loader_debug = 0;
1408
1409 /* parse comma-separated debug options */
Jon Ashburn38a497f2016-01-04 14:01:38 -07001410 orig = env = loader_getenv("VK_LOADER_DEBUG");
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001411 while (env) {
1412 const char *p = strchr(env, ',');
1413 size_t len;
1414
1415 if (p)
1416 len = p - env;
1417 else
1418 len = strlen(env);
1419
1420 if (len > 0) {
Michael Worcester25c73e72015-12-10 18:06:24 +00001421 if (strncmp(env, "all", len) == 0) {
1422 g_loader_debug = ~0u;
1423 g_loader_log_msgs = ~0u;
1424 } else if (strncmp(env, "warn", len) == 0) {
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001425 g_loader_debug |= LOADER_WARN_BIT;
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001426 g_loader_log_msgs |= VK_DEBUG_REPORT_WARN_BIT_EXT;
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001427 } else if (strncmp(env, "info", len) == 0) {
1428 g_loader_debug |= LOADER_INFO_BIT;
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001429 g_loader_log_msgs |= VK_DEBUG_REPORT_INFO_BIT_EXT;
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001430 } else if (strncmp(env, "perf", len) == 0) {
1431 g_loader_debug |= LOADER_PERF_BIT;
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001432 g_loader_log_msgs |= VK_DEBUG_REPORT_PERF_WARN_BIT_EXT;
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001433 } else if (strncmp(env, "error", len) == 0) {
1434 g_loader_debug |= LOADER_ERROR_BIT;
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001435 g_loader_log_msgs |= VK_DEBUG_REPORT_ERROR_BIT_EXT;
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001436 } else if (strncmp(env, "debug", len) == 0) {
1437 g_loader_debug |= LOADER_DEBUG_BIT;
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001438 g_loader_log_msgs |= VK_DEBUG_REPORT_DEBUG_BIT_EXT;
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001439 }
1440 }
1441
1442 if (!p)
1443 break;
1444
1445 env = p + 1;
1446 }
Jon Ashburn38a497f2016-01-04 14:01:38 -07001447
1448 loader_free_getenv(orig);
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001449}
1450
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001451void loader_initialize(void)
1452{
Jon Ashburn6461ef22015-09-22 13:11:00 -06001453 // initialize mutexs
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001454 loader_platform_thread_create_mutex(&loader_lock);
Jon Ashburn6461ef22015-09-22 13:11:00 -06001455 loader_platform_thread_create_mutex(&loader_json_lock);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001456
1457 // initialize logging
1458 loader_debug_init();
Jon Ashburn87d6aa92015-08-28 15:19:27 -06001459
1460 // initial cJSON to use alloc callbacks
1461 cJSON_Hooks alloc_fns = {
1462 .malloc_fn = loader_tls_heap_alloc,
1463 .free_fn = loader_tls_heap_free,
1464 };
1465 cJSON_InitHooks(&alloc_fns);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001466}
1467
Jon Ashburn2077e382015-06-29 11:25:34 -06001468struct loader_manifest_files {
1469 uint32_t count;
1470 char **filename_list;
1471};
1472
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06001473/**
Jon Ashburn2077e382015-06-29 11:25:34 -06001474 * Get next file or dirname given a string list or registry key path
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06001475 *
1476 * \returns
Jon Ashburn2077e382015-06-29 11:25:34 -06001477 * A pointer to first char in the next path.
1478 * The next path (or NULL) in the list is returned in next_path.
1479 * Note: input string is modified in some cases. PASS IN A COPY!
1480 */
Jon Ashburn2077e382015-06-29 11:25:34 -06001481static char *loader_get_next_path(char *path)
1482{
1483 uint32_t len;
1484 char *next;
1485
1486 if (path == NULL)
1487 return NULL;
1488 next = strchr(path, PATH_SEPERATOR);
1489 if (next == NULL) {
1490 len = (uint32_t) strlen(path);
1491 next = path + len;
1492 }
1493 else {
1494 *next = '\0';
1495 next++;
1496 }
1497
1498 return next;
1499}
1500
1501/**
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001502 * Given a path which is absolute or relative, expand the path if relative or
1503 * leave the path unmodified if absolute. The base path to prepend to relative
1504 * paths is given in rel_base.
Jon Ashburn15315172015-07-07 15:06:25 -06001505 *
1506 * \returns
1507 * A string in out_fullpath of the full absolute path
Jon Ashburn15315172015-07-07 15:06:25 -06001508 */
1509static void loader_expand_path(const char *path,
1510 const char *rel_base,
1511 size_t out_size,
1512 char *out_fullpath)
1513{
1514 if (loader_platform_is_path_absolute(path)) {
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001515 // do not prepend a base to an absolute path
1516 rel_base = "";
Jon Ashburn15315172015-07-07 15:06:25 -06001517 }
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001518
1519 loader_platform_combine_path(out_fullpath, out_size, rel_base, path, NULL);
Jon Ashburn15315172015-07-07 15:06:25 -06001520}
1521
1522/**
Jon Ashburn2077e382015-06-29 11:25:34 -06001523 * Given a filename (file) and a list of paths (dir), try to find an existing
1524 * file in the paths. If filename already is a path then no
1525 * searching in the given paths.
1526 *
1527 * \returns
1528 * A string in out_fullpath of either the full path or file.
Jon Ashburn2077e382015-06-29 11:25:34 -06001529 */
1530static void loader_get_fullpath(const char *file,
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001531 const char *dirs,
Jon Ashburn2077e382015-06-29 11:25:34 -06001532 size_t out_size,
1533 char *out_fullpath)
1534{
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001535 if (!loader_platform_is_path(file) && *dirs) {
1536 char *dirs_copy, *dir, *next_dir;
1537
1538 dirs_copy = loader_stack_alloc(strlen(dirs) + 1);
1539 strcpy(dirs_copy, dirs);
1540
1541 //find if file exists after prepending paths in given list
1542 for (dir = dirs_copy;
1543 *dir && (next_dir = loader_get_next_path(dir));
1544 dir = next_dir) {
1545 loader_platform_combine_path(out_fullpath, out_size, dir, file, NULL);
Jon Ashburn2077e382015-06-29 11:25:34 -06001546 if (loader_platform_file_exists(out_fullpath)) {
1547 return;
1548 }
Jon Ashburn2077e382015-06-29 11:25:34 -06001549 }
1550 }
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001551
Jon Ashburn2077e382015-06-29 11:25:34 -06001552 snprintf(out_fullpath, out_size, "%s", file);
1553}
1554
1555/**
1556 * Read a JSON file into a buffer.
1557 *
1558 * \returns
1559 * A pointer to a cJSON object representing the JSON parse tree.
1560 * This returned buffer should be freed by caller.
1561 */
Courtney Goeltzenleuchter73477392015-12-03 13:48:01 -07001562static cJSON *loader_get_json(const struct loader_instance *inst, const char *filename)
Jon Ashburn2077e382015-06-29 11:25:34 -06001563{
1564 FILE *file;
1565 char *json_buf;
1566 cJSON *json;
Mark Young93ecb1d2016-01-13 13:47:16 -07001567 size_t len;
Jon Ashburn2077e382015-06-29 11:25:34 -06001568 file = fopen(filename,"rb");
Jon Ashburnaa4ea472015-08-27 08:30:50 -06001569 if (!file) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001570 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Couldn't open JSON file %s", filename);
Jon Ashburnaa4ea472015-08-27 08:30:50 -06001571 return NULL;
1572 }
Jon Ashburn2077e382015-06-29 11:25:34 -06001573 fseek(file, 0, SEEK_END);
1574 len = ftell(file);
1575 fseek(file, 0, SEEK_SET);
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -06001576 json_buf = (char*) loader_stack_alloc(len+1);
Jon Ashburn2077e382015-06-29 11:25:34 -06001577 if (json_buf == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001578 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 -06001579 fclose(file);
1580 return NULL;
1581 }
1582 if (fread(json_buf, sizeof(char), len, file) != len) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001583 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "fread failed can't get JSON file");
Jon Ashburn2077e382015-06-29 11:25:34 -06001584 fclose(file);
1585 return NULL;
1586 }
1587 fclose(file);
1588 json_buf[len] = '\0';
1589
1590 //parse text from file
1591 json = cJSON_Parse(json_buf);
1592 if (json == NULL)
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001593 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Can't parse JSON file %s", filename);
Jon Ashburn2077e382015-06-29 11:25:34 -06001594 return json;
1595}
1596
1597/**
Jon Ashburn3d002332015-08-20 16:35:30 -06001598 * Do a deep copy of the loader_layer_properties structure.
1599 */
1600static void loader_copy_layer_properties(
Jon Ashburne39a4f82015-08-28 13:38:21 -06001601 const struct loader_instance *inst,
Jon Ashburn3d002332015-08-20 16:35:30 -06001602 struct loader_layer_properties *dst,
1603 struct loader_layer_properties *src)
1604{
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001605 uint32_t cnt, i;
Jon Ashburn3d002332015-08-20 16:35:30 -06001606 memcpy(dst, src, sizeof (*src));
Jon Ashburne39a4f82015-08-28 13:38:21 -06001607 dst->instance_extension_list.list = loader_heap_alloc(
1608 inst,
1609 sizeof(VkExtensionProperties) *
1610 src->instance_extension_list.count,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001611 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001612 dst->instance_extension_list.capacity = sizeof(VkExtensionProperties) *
1613 src->instance_extension_list.count;
1614 memcpy(dst->instance_extension_list.list, src->instance_extension_list.list,
1615 dst->instance_extension_list.capacity);
1616 dst->device_extension_list.list = loader_heap_alloc(
1617 inst,
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001618 sizeof(struct loader_dev_ext_props) *
Jon Ashburne39a4f82015-08-28 13:38:21 -06001619 src->device_extension_list.count,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001620 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001621
1622 dst->device_extension_list.capacity = sizeof(struct loader_dev_ext_props) *
Jon Ashburne39a4f82015-08-28 13:38:21 -06001623 src->device_extension_list.count;
1624 memcpy(dst->device_extension_list.list, src->device_extension_list.list,
1625 dst->device_extension_list.capacity);
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001626 if (src->device_extension_list.count > 0 &&
1627 src->device_extension_list.list->entrypoint_count > 0) {
1628 cnt = src->device_extension_list.list->entrypoint_count;
1629 dst->device_extension_list.list->entrypoints = loader_heap_alloc(
1630 inst,
1631 sizeof(char *) * cnt,
1632 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
1633 for (i = 0; i < cnt; i++) {
1634 dst->device_extension_list.list->entrypoints[i] = loader_heap_alloc(
1635 inst,
1636 strlen(src->device_extension_list.list->entrypoints[i]) + 1,
1637 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
1638 strcpy(dst->device_extension_list.list->entrypoints[i],
1639 src->device_extension_list.list->entrypoints[i]);
1640 }
1641 }
Jon Ashburn3d002332015-08-20 16:35:30 -06001642}
1643
1644/**
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001645 * Given a cJSON struct (json) of the top level JSON object from layer manifest
1646 * file, add entry to the layer_list.
Jon Ashburne13ecc92015-08-03 17:19:30 -06001647 * Fill out the layer_properties in this list entry from the input cJSON object.
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001648 *
1649 * \returns
1650 * void
1651 * layer_list has a new entry and initialized accordingly.
1652 * If the json input object does not have all the required fields no entry
1653 * is added to the list.
1654 */
Jon Ashburne39a4f82015-08-28 13:38:21 -06001655static void loader_add_layer_properties(const struct loader_instance *inst,
1656 struct loader_layer_list *layer_instance_list,
Jon Ashburnb2ef1372015-07-16 17:19:31 -06001657 struct loader_layer_list *layer_device_list,
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001658 cJSON *json,
1659 bool is_implicit,
1660 char *filename)
1661{
1662 /* Fields in layer manifest file that are required:
1663 * (required) “file_format_version”
1664 * following are required in the "layer" object:
1665 * (required) "name"
1666 * (required) "type"
1667 * (required) “library_path”
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001668 * (required) “api_version”
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001669 * (required) “implementation_version”
1670 * (required) “description”
1671 * (required for implicit layers) “disable_environment”
1672 *
1673 * First get all required items and if any missing abort
1674 */
1675
1676 cJSON *item, *layer_node, *ext_item;
1677 char *temp;
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001678 char *name, *type, *library_path, *api_version;
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001679 char *implementation_version, *description;
1680 cJSON *disable_environment;
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001681 int i, j;
Jon Ashburn5c042ea2015-08-04 11:14:18 -06001682 VkExtensionProperties ext_prop;
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001683 item = cJSON_GetObjectItem(json, "file_format_version");
1684 if (item == NULL) {
1685 return;
1686 }
1687 char *file_vers = cJSON_PrintUnformatted(item);
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001688 loader_log(inst, VK_DEBUG_REPORT_INFO_BIT_EXT, 0, "Found manifest file %s, version %s",
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001689 filename, file_vers);
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001690 if (strcmp(file_vers, "\"1.0.0\"") != 0)
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001691 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 -06001692 loader_tls_heap_free(file_vers);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001693
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001694 layer_node = cJSON_GetObjectItem(json, "layer");
1695 if (layer_node == NULL) {
Jon Ashburn075ce432015-12-17 17:38:24 -07001696 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 -06001697 return;
1698 }
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001699
1700 // loop through all "layer" objects in the file
1701 do {
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001702#define GET_JSON_OBJECT(node, var) { \
1703 var = cJSON_GetObjectItem(node, #var); \
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001704 if (var == NULL) { \
1705 layer_node = layer_node->next; \
Jon Ashburn075ce432015-12-17 17:38:24 -07001706 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0,\
1707 "Didn't find required layer object %s in manifest JSON file, skipping this layer",\
1708 #var); \
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001709 continue; \
1710 } \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001711 }
1712#define GET_JSON_ITEM(node, var) { \
1713 item = cJSON_GetObjectItem(node, #var); \
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001714 if (item == NULL) { \
1715 layer_node = layer_node->next; \
Jon Ashburn075ce432015-12-17 17:38:24 -07001716 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0,\
1717 "Didn't find required layer value %s in manifest JSON file, skipping this layer",\
1718 #var); \
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001719 continue; \
1720 } \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001721 temp = cJSON_Print(item); \
1722 temp[strlen(temp) - 1] = '\0'; \
Jon Ashburnf73e9212015-08-04 10:22:33 -06001723 var = loader_stack_alloc(strlen(temp) + 1); \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001724 strcpy(var, &temp[1]); \
Jon Ashburn87d6aa92015-08-28 15:19:27 -06001725 loader_tls_heap_free(temp); \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001726 }
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001727 GET_JSON_ITEM(layer_node, name)
1728 GET_JSON_ITEM(layer_node, type)
1729 GET_JSON_ITEM(layer_node, library_path)
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001730 GET_JSON_ITEM(layer_node, api_version)
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001731 GET_JSON_ITEM(layer_node, implementation_version)
1732 GET_JSON_ITEM(layer_node, description)
1733 if (is_implicit) {
1734 GET_JSON_OBJECT(layer_node, disable_environment)
1735 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001736#undef GET_JSON_ITEM
1737#undef GET_JSON_OBJECT
1738
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001739 // add list entry
Jon Ashburn432d2762015-09-18 12:53:16 -06001740 struct loader_layer_properties *props=NULL;
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001741 if (!strcmp(type, "DEVICE")) {
1742 if (layer_device_list == NULL) {
1743 layer_node = layer_node->next;
1744 continue;
1745 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06001746 props = loader_get_next_layer_property(inst, layer_device_list);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001747 props->type = (is_implicit) ? VK_LAYER_TYPE_DEVICE_IMPLICIT : VK_LAYER_TYPE_DEVICE_EXPLICIT;
1748 }
1749 if (!strcmp(type, "INSTANCE")) {
1750 if (layer_instance_list == NULL) {
1751 layer_node = layer_node->next;
1752 continue;
1753 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06001754 props = loader_get_next_layer_property(inst, layer_instance_list);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001755 props->type = (is_implicit) ? VK_LAYER_TYPE_INSTANCE_IMPLICIT : VK_LAYER_TYPE_INSTANCE_EXPLICIT;
1756 }
1757 if (!strcmp(type, "GLOBAL")) {
1758 if (layer_instance_list != NULL)
Jon Ashburne39a4f82015-08-28 13:38:21 -06001759 props = loader_get_next_layer_property(inst, layer_instance_list);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001760 else if (layer_device_list != NULL)
Jon Ashburne39a4f82015-08-28 13:38:21 -06001761 props = loader_get_next_layer_property(inst, layer_device_list);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001762 else {
1763 layer_node = layer_node->next;
1764 continue;
1765 }
1766 props->type = (is_implicit) ? VK_LAYER_TYPE_GLOBAL_IMPLICIT : VK_LAYER_TYPE_GLOBAL_EXPLICIT;
1767 }
Jon Ashburnb2ef1372015-07-16 17:19:31 -06001768
Jon Ashburn432d2762015-09-18 12:53:16 -06001769 if (props == NULL) {
1770 layer_node = layer_node->next;
1771 continue;
1772 }
1773
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001774 strncpy(props->info.layerName, name, sizeof (props->info.layerName));
1775 props->info.layerName[sizeof (props->info.layerName) - 1] = '\0';
Jon Ashburn15315172015-07-07 15:06:25 -06001776
Jon Ashburn3d002332015-08-20 16:35:30 -06001777 char *fullpath = props->lib_name;
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001778 char *rel_base;
Jon Ashburn6e08ebd2015-12-01 17:11:02 -07001779 if (loader_platform_is_path(library_path)) {
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001780 // a relative or absolute path
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001781 char *name_copy = loader_stack_alloc(strlen(filename) + 1);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001782 strcpy(name_copy, filename);
1783 rel_base = loader_platform_dirname(name_copy);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001784 loader_expand_path(library_path, rel_base, MAX_STRING_SIZE, fullpath);
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001785 } else {
1786 // a filename which is assumed in a system directory
1787 loader_get_fullpath(library_path, DEFAULT_VK_LAYERS_PATH, MAX_STRING_SIZE, fullpath);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001788 }
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001789 props->info.specVersion = loader_make_version(api_version);
1790 props->info.implementationVersion = atoi(implementation_version);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001791 strncpy((char *) props->info.description, description, sizeof (props->info.description));
1792 props->info.description[sizeof (props->info.description) - 1] = '\0';
1793 if (is_implicit) {
1794 strncpy(props->disable_env_var.name, disable_environment->child->string, sizeof (props->disable_env_var.name));
1795 props->disable_env_var.name[sizeof (props->disable_env_var.name) - 1] = '\0';
1796 strncpy(props->disable_env_var.value, disable_environment->child->valuestring, sizeof (props->disable_env_var.value));
1797 props->disable_env_var.value[sizeof (props->disable_env_var.value) - 1] = '\0';
1798 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001799
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001800 /**
1801 * Now get all optional items and objects and put in list:
1802 * functions
1803 * instance_extensions
1804 * device_extensions
1805 * enable_environment (implicit layers only)
1806 */
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001807#define GET_JSON_OBJECT(node, var) { \
1808 var = cJSON_GetObjectItem(node, #var); \
1809 }
1810#define GET_JSON_ITEM(node, var) { \
1811 item = cJSON_GetObjectItem(node, #var); \
Jon Ashburn21c21ee2015-09-09 11:29:24 -06001812 if (item != NULL) { \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001813 temp = cJSON_Print(item); \
Jon Ashburn21c21ee2015-09-09 11:29:24 -06001814 temp[strlen(temp) - 1] = '\0'; \
1815 var = loader_stack_alloc(strlen(temp) + 1);\
1816 strcpy(var, &temp[1]); \
1817 loader_tls_heap_free(temp); \
1818 } \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001819 }
1820
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001821 cJSON *instance_extensions, *device_extensions, *functions, *enable_environment;
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001822 cJSON *entrypoints;
1823 char *vkGetInstanceProcAddr, *vkGetDeviceProcAddr, *spec_version;
1824 char **entry_array;
1825 vkGetInstanceProcAddr = NULL;
1826 vkGetDeviceProcAddr = NULL;
1827 spec_version = NULL;
1828 entrypoints = NULL;
1829 entry_array = NULL;
1830 /**
1831 * functions
1832 * vkGetInstanceProcAddr
1833 * vkGetDeviceProcAddr
1834 */
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001835 GET_JSON_OBJECT(layer_node, functions)
1836 if (functions != NULL) {
1837 GET_JSON_ITEM(functions, vkGetInstanceProcAddr)
1838 GET_JSON_ITEM(functions, vkGetDeviceProcAddr)
Jon Ashburn21c21ee2015-09-09 11:29:24 -06001839 if (vkGetInstanceProcAddr != NULL)
1840 strncpy(props->functions.str_gipa, vkGetInstanceProcAddr, sizeof (props->functions.str_gipa));
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001841 props->functions.str_gipa[sizeof (props->functions.str_gipa) - 1] = '\0';
Jon Ashburn21c21ee2015-09-09 11:29:24 -06001842 if (vkGetDeviceProcAddr != NULL)
1843 strncpy(props->functions.str_gdpa, vkGetDeviceProcAddr, sizeof (props->functions.str_gdpa));
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001844 props->functions.str_gdpa[sizeof (props->functions.str_gdpa) - 1] = '\0';
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001845 }
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001846 /**
1847 * instance_extensions
1848 * array of
1849 * name
1850 * spec_version
1851 */
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001852 GET_JSON_OBJECT(layer_node, instance_extensions)
1853 if (instance_extensions != NULL) {
1854 int count = cJSON_GetArraySize(instance_extensions);
1855 for (i = 0; i < count; i++) {
1856 ext_item = cJSON_GetArrayItem(instance_extensions, i);
1857 GET_JSON_ITEM(ext_item, name)
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001858 GET_JSON_ITEM(ext_item, spec_version)
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001859 if (name != NULL) {
Jon Ashburn6e6a2162015-12-10 08:51:10 -07001860 strncpy(ext_prop.extensionName, name, sizeof (ext_prop.extensionName));
1861 ext_prop.extensionName[sizeof (ext_prop.extensionName) - 1] = '\0';
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001862 }
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001863 ext_prop.specVersion = atoi(spec_version);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001864 loader_add_to_ext_list(inst, &props->instance_extension_list, 1, &ext_prop);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001865 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001866 }
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001867 /**
1868 * device_extensions
1869 * array of
1870 * name
1871 * spec_version
1872 * entrypoints
1873 */
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001874 GET_JSON_OBJECT(layer_node, device_extensions)
1875 if (device_extensions != NULL) {
1876 int count = cJSON_GetArraySize(device_extensions);
1877 for (i = 0; i < count; i++) {
1878 ext_item = cJSON_GetArrayItem(device_extensions, i);
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001879 GET_JSON_ITEM(ext_item, name)
1880 GET_JSON_ITEM(ext_item, spec_version)
1881 if (name != NULL) {
Jon Ashburn6e6a2162015-12-10 08:51:10 -07001882 strncpy(ext_prop.extensionName, name, sizeof (ext_prop.extensionName));
1883 ext_prop.extensionName[sizeof (ext_prop.extensionName) - 1] = '\0';
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001884 }
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001885 ext_prop.specVersion = atoi(spec_version);
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001886 //entrypoints = cJSON_GetObjectItem(ext_item, "entrypoints");
1887 GET_JSON_OBJECT(ext_item, entrypoints)
1888 int entry_count;
1889 if (entrypoints == NULL)
1890 continue;
1891 entry_count = cJSON_GetArraySize(entrypoints);
1892 if (entry_count)
1893 entry_array = (char **) loader_stack_alloc(sizeof(char *) * entry_count);
1894 for (j = 0; j < entry_count; j++) {
1895 ext_item = cJSON_GetArrayItem(entrypoints, j);
1896 if (ext_item != NULL) {
1897 temp = cJSON_Print(ext_item);
1898 temp[strlen(temp) - 1] = '\0';
1899 entry_array[j] = loader_stack_alloc(strlen(temp) + 1);
1900 strcpy(entry_array[j], &temp[1]);
1901 loader_tls_heap_free(temp);
Jon Ashburn6e6a2162015-12-10 08:51:10 -07001902 }
1903 }
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001904 loader_add_to_dev_ext_list(inst, &props->device_extension_list,
1905 &ext_prop, entry_count, entry_array);
1906 }
1907 }
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001908 if (is_implicit) {
1909 GET_JSON_OBJECT(layer_node, enable_environment)
Jon Ashburn075ce432015-12-17 17:38:24 -07001910
1911 // enable_environment is optional
1912 if (enable_environment) {
1913 strncpy(props->enable_env_var.name, enable_environment->child->string, sizeof (props->enable_env_var.name));
1914 props->enable_env_var.name[sizeof (props->enable_env_var.name) - 1] = '\0';
1915 strncpy(props->enable_env_var.value, enable_environment->child->valuestring, sizeof (props->enable_env_var.value));
1916 props->enable_env_var.value[sizeof (props->enable_env_var.value) - 1] = '\0';
1917 }
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001918 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001919#undef GET_JSON_ITEM
1920#undef GET_JSON_OBJECT
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001921 // for global layers need to add them to both device and instance list
1922 if (!strcmp(type, "GLOBAL")) {
1923 struct loader_layer_properties *dev_props;
1924 if (layer_instance_list == NULL || layer_device_list == NULL) {
1925 layer_node = layer_node->next;
1926 continue;
1927 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06001928 dev_props = loader_get_next_layer_property(inst, layer_device_list);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001929 //copy into device layer list
Jon Ashburne39a4f82015-08-28 13:38:21 -06001930 loader_copy_layer_properties(inst, dev_props, props);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001931 }
1932 layer_node = layer_node->next;
1933 } while (layer_node != NULL);
1934 return;
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001935}
1936
1937/**
Jon Ashburn2077e382015-06-29 11:25:34 -06001938 * Find the Vulkan library manifest files.
1939 *
1940 * This function scans the location or env_override directories/files
1941 * for a list of JSON manifest files. If env_override is non-NULL
1942 * and has a valid value. Then the location is ignored. Otherwise
1943 * location is used to look for manifest files. The location
1944 * is interpreted as Registry path on Windows and a directory path(s)
1945 * on Linux.
1946 *
1947 * \returns
1948 * A string list of manifest files to be opened in out_files param.
1949 * List has a pointer to string for each manifest filename.
1950 * When done using the list in out_files, pointers should be freed.
Jon Ashburnffad94d2015-06-30 14:46:22 -07001951 * Location or override string lists can be either files or directories as follows:
1952 * | location | override
1953 * --------------------------------
1954 * Win ICD | files | files
1955 * Win Layer | files | dirs
1956 * Linux ICD | dirs | files
1957 * Linux Layer| dirs | dirs
Jon Ashburn2077e382015-06-29 11:25:34 -06001958 */
Jon Ashburne39a4f82015-08-28 13:38:21 -06001959static void loader_get_manifest_files(const struct loader_instance *inst,
1960 const char *env_override,
Jon Ashburnffad94d2015-06-30 14:46:22 -07001961 bool is_layer,
1962 const char *location,
1963 struct loader_manifest_files *out_files)
Jon Ashburn2077e382015-06-29 11:25:34 -06001964{
1965 char *override = NULL;
1966 char *loc;
1967 char *file, *next_file, *name;
1968 size_t alloced_count = 64;
1969 char full_path[2048];
1970 DIR *sysdir = NULL;
Jon Ashburnffad94d2015-06-30 14:46:22 -07001971 bool list_is_dirs = false;
Jon Ashburn2077e382015-06-29 11:25:34 -06001972 struct dirent *dent;
1973
1974 out_files->count = 0;
1975 out_files->filename_list = NULL;
1976
Jon Ashburn38a497f2016-01-04 14:01:38 -07001977 if (env_override != NULL && (override = loader_getenv(env_override))) {
Johannes van Waveren9bd805012015-10-28 11:45:00 -05001978#if !defined(_WIN32)
Jon Ashburn2077e382015-06-29 11:25:34 -06001979 if (geteuid() != getuid()) {
Jon Ashburnffad94d2015-06-30 14:46:22 -07001980 /* Don't allow setuid apps to use the env var: */
Jon Ashburn38a497f2016-01-04 14:01:38 -07001981 loader_free_getenv(override);
Jon Ashburn2077e382015-06-29 11:25:34 -06001982 override = NULL;
1983 }
1984#endif
1985 }
1986
1987 if (location == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001988 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburnffad94d2015-06-30 14:46:22 -07001989 "Can't get manifest files with NULL location, env_override=%s",
1990 env_override);
Jon Ashburn2077e382015-06-29 11:25:34 -06001991 return;
1992 }
1993
Johannes van Waveren9bd805012015-10-28 11:45:00 -05001994#if defined(_WIN32)
Jon Ashburnffad94d2015-06-30 14:46:22 -07001995 list_is_dirs = (is_layer && override != NULL) ? true : false;
Johannes van Waveren9bd805012015-10-28 11:45:00 -05001996#else
1997 list_is_dirs = (override == NULL || is_layer) ? true : false;
Jon Ashburnffad94d2015-06-30 14:46:22 -07001998#endif
Jon Ashburn2077e382015-06-29 11:25:34 -06001999 // Make a copy of the input we are using so it is not modified
Jon Ashburnffad94d2015-06-30 14:46:22 -07002000 // Also handle getting the location(s) from registry on Windows
2001 if (override == NULL) {
Jon Ashburn3b78e462015-07-31 10:11:24 -06002002 loc = loader_stack_alloc(strlen(location) + 1);
Jon Ashburnffad94d2015-06-30 14:46:22 -07002003 if (loc == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002004 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 -07002005 return;
2006 }
2007 strcpy(loc, location);
Johannes van Waveren9bd805012015-10-28 11:45:00 -05002008#if defined(_WIN32)
Jon Ashburn480a50a2015-08-28 14:58:46 -07002009 loc = loader_get_registry_files(inst, loc);
Jon Ashburn24265ac2015-07-31 09:33:21 -06002010 if (loc == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002011 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 -06002012 return;
2013 }
Jon Ashburnffad94d2015-06-30 14:46:22 -07002014#endif
Jon Ashburn2077e382015-06-29 11:25:34 -06002015 }
Jon Ashburnffad94d2015-06-30 14:46:22 -07002016 else {
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -06002017 loc = loader_stack_alloc(strlen(override) + 1);
Jon Ashburnffad94d2015-06-30 14:46:22 -07002018 if (loc == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002019 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 -07002020 return;
2021 }
2022 strcpy(loc, override);
Jon Ashburn38a497f2016-01-04 14:01:38 -07002023 loader_free_getenv(override);
Jon Ashburnffad94d2015-06-30 14:46:22 -07002024 }
Jon Ashburn2077e382015-06-29 11:25:34 -06002025
Liam Middlebrook9b14e892015-07-23 18:32:20 -07002026 // Print out the paths being searched if debugging is enabled
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002027 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 -07002028
Jon Ashburn2077e382015-06-29 11:25:34 -06002029 file = loc;
2030 while (*file) {
2031 next_file = loader_get_next_path(file);
Jon Ashburnffad94d2015-06-30 14:46:22 -07002032 if (list_is_dirs) {
Jon Ashburn2077e382015-06-29 11:25:34 -06002033 sysdir = opendir(file);
2034 name = NULL;
2035 if (sysdir) {
2036 dent = readdir(sysdir);
2037 if (dent == NULL)
2038 break;
2039 name = &(dent->d_name[0]);
2040 loader_get_fullpath(name, file, sizeof(full_path), full_path);
2041 name = full_path;
2042 }
2043 }
2044 else {
Johannes van Waveren9bd805012015-10-28 11:45:00 -05002045#if defined(_WIN32)
2046 name = file;
2047#else
Jon Ashburnffad94d2015-06-30 14:46:22 -07002048 // only Linux has relative paths
Jon Ashburn2077e382015-06-29 11:25:34 -06002049 char *dir;
2050 // make a copy of location so it isn't modified
Jason Ekstrandcc7550e2015-10-10 08:33:37 -07002051 dir = loader_stack_alloc(strlen(loc) + 1);
Jon Ashburn2077e382015-06-29 11:25:34 -06002052 if (dir == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002053 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Out of memory can't get manifest files");
Jon Ashburn2077e382015-06-29 11:25:34 -06002054 return;
2055 }
Jason Ekstrandcc7550e2015-10-10 08:33:37 -07002056 strcpy(dir, loc);
Jon Ashburn2077e382015-06-29 11:25:34 -06002057
2058 loader_get_fullpath(file, dir, sizeof(full_path), full_path);
2059
2060 name = full_path;
Jon Ashburnffad94d2015-06-30 14:46:22 -07002061#endif
Jon Ashburn2077e382015-06-29 11:25:34 -06002062 }
2063 while (name) {
2064 /* Look for files ending with ".json" suffix */
2065 uint32_t nlen = (uint32_t) strlen(name);
2066 const char *suf = name + nlen - 5;
2067 if ((nlen > 5) && !strncmp(suf, ".json", 5)) {
2068 if (out_files->count == 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06002069 out_files->filename_list = loader_heap_alloc(inst,
2070 alloced_count * sizeof(char *),
Chia-I Wucf804e82015-10-31 00:31:16 +08002071 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
Jon Ashburn2077e382015-06-29 11:25:34 -06002072 }
2073 else if (out_files->count == alloced_count) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06002074 out_files->filename_list = loader_heap_realloc(inst,
2075 out_files->filename_list,
2076 alloced_count * sizeof(char *),
2077 alloced_count * sizeof(char *) * 2,
Chia-I Wucf804e82015-10-31 00:31:16 +08002078 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
Jon Ashburn2077e382015-06-29 11:25:34 -06002079 alloced_count *= 2;
2080 }
2081 if (out_files->filename_list == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002082 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 -06002083 return;
2084 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06002085 out_files->filename_list[out_files->count] = loader_heap_alloc(
2086 inst,
2087 strlen(name) + 1,
Chia-I Wucf804e82015-10-31 00:31:16 +08002088 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
Jon Ashburn2077e382015-06-29 11:25:34 -06002089 if (out_files->filename_list[out_files->count] == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002090 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 -06002091 return;
2092 }
2093 strcpy(out_files->filename_list[out_files->count], name);
2094 out_files->count++;
Jon Ashburnf70f3612015-07-02 10:08:47 -06002095 } else if (!list_is_dirs) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002096 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 -06002097 }
Jon Ashburnffad94d2015-06-30 14:46:22 -07002098 if (list_is_dirs) {
Jon Ashburn2077e382015-06-29 11:25:34 -06002099 dent = readdir(sysdir);
2100 if (dent == NULL)
2101 break;
2102 name = &(dent->d_name[0]);
2103 loader_get_fullpath(name, file, sizeof(full_path), full_path);
2104 name = full_path;
2105 }
2106 else {
2107 break;
2108 }
2109 }
2110 if (sysdir)
2111 closedir(sysdir);
2112 file = next_file;
2113 }
2114 return;
2115}
2116
Jon Ashburn8810c5f2015-08-18 18:04:47 -06002117void loader_init_icd_lib_list()
2118{
2119
2120}
2121
2122void loader_destroy_icd_lib_list()
2123{
2124
2125}
Jon Ashburn2077e382015-06-29 11:25:34 -06002126/**
2127 * Try to find the Vulkan ICD driver(s).
2128 *
2129 * This function scans the default system loader path(s) or path
2130 * specified by the \c VK_ICD_FILENAMES environment variable in
2131 * order to find loadable VK ICDs manifest files. From these
2132 * manifest files it finds the ICD libraries.
2133 *
2134 * \returns
Jon Ashburn8810c5f2015-08-18 18:04:47 -06002135 * a list of icds that were discovered
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06002136 */
Jon Ashburne39a4f82015-08-28 13:38:21 -06002137void loader_icd_scan(
2138 const struct loader_instance *inst,
2139 struct loader_icd_libs *icds)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08002140{
Jon Ashburn2077e382015-06-29 11:25:34 -06002141 char *file_str;
2142 struct loader_manifest_files manifest_files;
2143
Jon Ashburne39a4f82015-08-28 13:38:21 -06002144 loader_scanned_icd_init(inst, icds);
Jon Ashburn2077e382015-06-29 11:25:34 -06002145 // Get a list of manifest files for ICDs
Jon Ashburne39a4f82015-08-28 13:38:21 -06002146 loader_get_manifest_files(inst, "VK_ICD_FILENAMES", false,
2147 DEFAULT_VK_DRIVERS_INFO, &manifest_files);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002148 if (manifest_files.count == 0)
2149 return;
Jon Ashburn6461ef22015-09-22 13:11:00 -06002150 loader_platform_thread_lock_mutex(&loader_json_lock);
Jon Ashburn2077e382015-06-29 11:25:34 -06002151 for (uint32_t i = 0; i < manifest_files.count; i++) {
2152 file_str = manifest_files.filename_list[i];
2153 if (file_str == NULL)
2154 continue;
2155
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002156 cJSON *json;
Courtney Goeltzenleuchter73477392015-12-03 13:48:01 -07002157 json = loader_get_json(inst, file_str);
Jon Ashburnaa4ea472015-08-27 08:30:50 -06002158 if (!json)
2159 continue;
Jon Ashburn005617f2015-11-17 17:35:40 -07002160 cJSON *item, *itemICD;
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002161 item = cJSON_GetObjectItem(json, "file_format_version");
Jon Ashburn6461ef22015-09-22 13:11:00 -06002162 if (item == NULL) {
2163 loader_platform_thread_unlock_mutex(&loader_json_lock);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002164 return;
Jon Ashburn6461ef22015-09-22 13:11:00 -06002165 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002166 char *file_vers = cJSON_Print(item);
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002167 loader_log(inst, VK_DEBUG_REPORT_INFO_BIT_EXT, 0, "Found manifest file %s, version %s",
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002168 file_str, file_vers);
2169 if (strcmp(file_vers, "\"1.0.0\"") != 0)
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002170 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 -06002171 loader_tls_heap_free(file_vers);
Jon Ashburn005617f2015-11-17 17:35:40 -07002172 itemICD = cJSON_GetObjectItem(json, "ICD");
2173 if (itemICD != NULL) {
2174 item = cJSON_GetObjectItem(itemICD, "library_path");
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002175 if (item != NULL) {
Jon Ashburn86251302015-08-25 16:48:24 -06002176 char *temp= cJSON_Print(item);
2177 if (!temp || strlen(temp) == 0) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002178 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 -06002179 loader_tls_heap_free(temp);
Jon Ashburne39a4f82015-08-28 13:38:21 -06002180 loader_heap_free(inst, file_str);
Jon Ashburn86251302015-08-25 16:48:24 -06002181 cJSON_Delete(json);
2182 continue;
Jon Ashburn2077e382015-06-29 11:25:34 -06002183 }
Jon Ashburn86251302015-08-25 16:48:24 -06002184 //strip out extra quotes
2185 temp[strlen(temp) - 1] = '\0';
2186 char *library_path = loader_stack_alloc(strlen(temp) + 1);
2187 strcpy(library_path, &temp[1]);
Jon Ashburn87d6aa92015-08-28 15:19:27 -06002188 loader_tls_heap_free(temp);
Jon Ashburn86251302015-08-25 16:48:24 -06002189 if (!library_path || strlen(library_path) == 0) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002190 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 -06002191 loader_heap_free(inst, file_str);
Jon Ashburn86251302015-08-25 16:48:24 -06002192 cJSON_Delete(json);
2193 continue;
2194 }
Daniel Dadap00b4aba2015-09-30 11:50:51 -05002195 char fullpath[MAX_STRING_SIZE];
Jon Ashburn86251302015-08-25 16:48:24 -06002196 // Print out the paths being searched if debugging is enabled
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002197 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 -05002198 if (loader_platform_is_path(library_path)) {
Jon Ashburn86251302015-08-25 16:48:24 -06002199 // a relative or absolute path
Daniel Dadap00b4aba2015-09-30 11:50:51 -05002200 char *name_copy = loader_stack_alloc(strlen(file_str) + 1);
2201 char *rel_base;
Jon Ashburn86251302015-08-25 16:48:24 -06002202 strcpy(name_copy, file_str);
2203 rel_base = loader_platform_dirname(name_copy);
Daniel Dadap00b4aba2015-09-30 11:50:51 -05002204 loader_expand_path(library_path, rel_base, sizeof(fullpath), fullpath);
2205 } else {
2206 // a filename which is assumed in a system directory
2207 loader_get_fullpath(library_path, DEFAULT_VK_DRIVERS_PATH, sizeof(fullpath), fullpath);
Jon Ashburn86251302015-08-25 16:48:24 -06002208 }
Jon Ashburn005617f2015-11-17 17:35:40 -07002209
2210 uint32_t vers = 0;
2211 item = cJSON_GetObjectItem(itemICD, "api_version");
2212 if (item != NULL) {
2213 temp= cJSON_Print(item);
2214 vers = loader_make_version(temp);
2215 loader_tls_heap_free(temp);
2216 }
2217 loader_scanned_icd_add(inst, icds, fullpath, vers);
Jon Ashburn2077e382015-06-29 11:25:34 -06002218 }
Jon Ashburn005617f2015-11-17 17:35:40 -07002219 else
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002220 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 -06002221 }
2222 else
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002223 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 -06002224
Jon Ashburne39a4f82015-08-28 13:38:21 -06002225 loader_heap_free(inst, file_str);
Jon Ashburn2077e382015-06-29 11:25:34 -06002226 cJSON_Delete(json);
2227 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06002228 loader_heap_free(inst, manifest_files.filename_list);
Jon Ashburn6461ef22015-09-22 13:11:00 -06002229 loader_platform_thread_unlock_mutex(&loader_json_lock);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08002230}
2231
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002232
Jon Ashburne39a4f82015-08-28 13:38:21 -06002233void loader_layer_scan(
2234 const struct loader_instance *inst,
2235 struct loader_layer_list *instance_layers,
2236 struct loader_layer_list *device_layers)
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002237{
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002238 char *file_str;
Jon Ashburn075ce432015-12-17 17:38:24 -07002239 struct loader_manifest_files manifest_files[2]; // [0] = explicit, [1] = implicit
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002240 cJSON *json;
2241 uint32_t i;
Jon Ashburn075ce432015-12-17 17:38:24 -07002242 uint32_t implicit;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002243
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002244 // Get a list of manifest files for layers
Jon Ashburn075ce432015-12-17 17:38:24 -07002245 loader_get_manifest_files(inst, LAYERS_PATH_ENV, true, DEFAULT_VK_ELAYERS_INFO,
2246 &manifest_files[0]);
Jon Ashburnb1a03e02015-12-24 13:58:35 -07002247 // Pass NULL for environment variable override - implicit layers are not overridden by LAYERS_PATH_ENV
2248 loader_get_manifest_files(inst, NULL, true, DEFAULT_VK_ILAYERS_INFO,
Jon Ashburn075ce432015-12-17 17:38:24 -07002249 &manifest_files[1]);
2250 if (manifest_files[0].count == 0 && manifest_files[1].count == 0)
Courtney Goeltzenleuchter57985ce2014-12-01 09:29:42 -07002251 return;
Jon Ashburn90c6a0e2015-06-04 15:30:58 -06002252
Jon Ashburne13ecc92015-08-03 17:19:30 -06002253#if 0 //TODO
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002254 /**
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -06002255 * We need a list of the layer libraries, not just a list of
2256 * the layer properties (a layer library could expose more than
2257 * one layer property). This list of scanned layers would be
2258 * used to check for global and physicaldevice layer properties.
2259 */
2260 if (!loader_init_layer_library_list(&loader.scanned_layer_libraries)) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002261 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburne39a4f82015-08-28 13:38:21 -06002262 "Alloc for layer list failed: %s line: %d", __FILE__, __LINE__);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -06002263 return;
Jon Ashburn5ef20602015-07-02 09:40:15 -06002264 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002265#endif
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002266
Jon Ashburne13ecc92015-08-03 17:19:30 -06002267 /* cleanup any previously scanned libraries */
Jon Ashburne39a4f82015-08-28 13:38:21 -06002268 loader_delete_layer_properties(inst, instance_layers);
2269 loader_delete_layer_properties(inst, device_layers);
Jon Ashburnb2ef1372015-07-16 17:19:31 -06002270
Jon Ashburn6461ef22015-09-22 13:11:00 -06002271 loader_platform_thread_lock_mutex(&loader_json_lock);
Jon Ashburn075ce432015-12-17 17:38:24 -07002272 for (implicit = 0; implicit < 2; implicit++) {
2273 for (i = 0; i < manifest_files[implicit].count; i++) {
2274 file_str = manifest_files[implicit].filename_list[i];
2275 if (file_str == NULL)
2276 continue;
Courtney Goeltzenleuchtera9e4af42015-06-01 14:49:17 -06002277
Jon Ashburn075ce432015-12-17 17:38:24 -07002278 // parse file into JSON struct
2279 json = loader_get_json(inst, file_str);
2280 if (!json) {
2281 continue;
2282 }
2283
2284 //TODO error if device layers expose instance_extensions
2285 //TODO error if instance layers expose device extensions
2286 loader_add_layer_properties(inst,
2287 instance_layers,
2288 device_layers,
2289 json,
2290 (implicit == 1),
2291 file_str);
2292
2293 loader_heap_free(inst, file_str);
2294 cJSON_Delete(json);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002295 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002296 }
Jon Ashburn075ce432015-12-17 17:38:24 -07002297 if (manifest_files[0].count != 0)
2298 loader_heap_free(inst, manifest_files[0].filename_list);
2299
2300 if (manifest_files[1].count != 0)
2301 loader_heap_free(inst, manifest_files[1].filename_list);
Jon Ashburn6461ef22015-09-22 13:11:00 -06002302 loader_platform_thread_unlock_mutex(&loader_json_lock);
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002303}
2304
Chia-I Wu9ab61502015-11-06 06:42:02 +08002305static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL loader_gpa_instance_internal(VkInstance inst, const char * pName)
Jon Ashburn27cd5842015-05-12 17:26:48 -06002306{
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002307 if (!strcmp(pName, "vkGetInstanceProcAddr"))
2308 return (void *) loader_gpa_instance_internal;
2309 if (!strcmp(pName, "vkCreateInstance"))
2310 return (void *) loader_CreateInstance;
2311 if (!strcmp(pName, "vkCreateDevice"))
2312 return (void *) loader_create_device_terminator;
2313
Jon Ashburn27cd5842015-05-12 17:26:48 -06002314 // inst is not wrapped
2315 if (inst == VK_NULL_HANDLE) {
2316 return NULL;
2317 }
2318 VkLayerInstanceDispatchTable* disp_table = * (VkLayerInstanceDispatchTable **) inst;
2319 void *addr;
2320
2321 if (disp_table == NULL)
2322 return NULL;
2323
2324 addr = loader_lookup_instance_dispatch_table(disp_table, pName);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002325 if (addr) {
Jon Ashburn27cd5842015-05-12 17:26:48 -06002326 return addr;
Jon Ashburn3d526cb2015-04-13 18:10:06 -06002327 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002328
2329 if (disp_table->GetInstanceProcAddr == NULL) {
2330 return NULL;
2331 }
2332 return disp_table->GetInstanceProcAddr(inst, pName);
Jon Ashburn3d526cb2015-04-13 18:10:06 -06002333}
2334
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002335/**
2336 * Initialize device_ext dispatch table entry as follows:
2337 * If dev == NULL find all logical devices created within this instance and
2338 * init the entry (given by idx) in the ext dispatch table.
2339 * If dev != NULL only initialize the entry in the given dev's dispatch table.
2340 * The initialization value is gotten by calling down the device chain with GDPA.
2341 * If GDPA returns NULL then don't initialize the dispatch table entry.
2342 */
2343static void loader_init_dispatch_dev_ext_entry(struct loader_instance *inst,
2344 struct loader_device *dev,
2345 uint32_t idx,
2346 const char *funcName)
2347
2348 {
2349 void *gdpa_value;
2350 if (dev != NULL) {
2351 gdpa_value = dev->loader_dispatch.core_dispatch.GetDeviceProcAddr(
2352 dev->device, funcName);
2353 if (gdpa_value != NULL)
2354 dev->loader_dispatch.ext_dispatch.DevExt[idx] = (PFN_vkDevExt) gdpa_value;
2355 } else {
2356 for (uint32_t i = 0; i < inst->total_icd_count; i++) {
2357 struct loader_icd *icd = &inst->icds[i];
2358 struct loader_device *dev = icd->logical_device_list;
2359 while (dev) {
2360 gdpa_value = dev->loader_dispatch.core_dispatch.GetDeviceProcAddr(
2361 dev->device, funcName);
2362 if (gdpa_value != NULL)
2363 dev->loader_dispatch.ext_dispatch.DevExt[idx] =
2364 (PFN_vkDevExt) gdpa_value;
2365 dev = dev->next;
2366 }
2367 }
2368 }
2369
2370}
2371
2372/**
2373 * Find all dev extension in the hash table and initialize the dispatch table
2374 * for dev for each of those extension entrypoints found in hash table.
2375
2376 */
2377static void loader_init_dispatch_dev_ext(struct loader_instance *inst,
2378 struct loader_device *dev)
2379{
2380 for (uint32_t i = 0; i < MAX_NUM_DEV_EXTS; i++) {
2381 if (inst->disp_hash[i].func_name != NULL)
2382 loader_init_dispatch_dev_ext_entry(inst, dev, i,
2383 inst->disp_hash[i].func_name);
2384 }
2385}
2386
2387static bool loader_check_icds_for_address(struct loader_instance *inst,
2388 const char *funcName)
2389{
2390 struct loader_icd *icd;
2391 icd = inst->icds;
2392 while (icd) {
2393 if (icd->this_icd_lib->GetInstanceProcAddr(icd->instance, funcName))
2394 // this icd supports funcName
2395 return true;
2396 icd = icd->next;
2397 }
2398
2399 return false;
2400}
2401
2402static void loader_free_dev_ext_table(struct loader_instance *inst)
2403{
2404 for (uint32_t i = 0; i < MAX_NUM_DEV_EXTS; i++) {
2405 loader_heap_free(inst, inst->disp_hash[i].func_name);
2406 loader_heap_free(inst, inst->disp_hash[i].list.index);
2407
2408 }
2409 memset(inst->disp_hash, 0, sizeof(inst->disp_hash));
2410}
2411
2412static bool loader_add_dev_ext_table(struct loader_instance *inst,
2413 uint32_t *ptr_idx,
2414 const char *funcName)
2415{
2416 uint32_t i;
2417 uint32_t idx = *ptr_idx;
2418 struct loader_dispatch_hash_list *list = &inst->disp_hash[idx].list;
2419
2420 if (!inst->disp_hash[idx].func_name) {
2421 // no entry here at this idx, so use it
2422 assert(list->capacity == 0);
2423 inst->disp_hash[idx].func_name = (char *) loader_heap_alloc(inst,
2424 strlen(funcName) + 1,
2425 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
2426 if (inst->disp_hash[idx].func_name == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002427 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002428 "loader_add_dev_ext_table() can't allocate memory for func_name");
2429 return false;
2430 }
2431 strncpy(inst->disp_hash[idx].func_name, funcName, strlen(funcName) + 1);
2432 return true;
2433 }
2434
2435 // check for enough capacity
2436 if (list->capacity == 0) {
2437 list->index = loader_heap_alloc(inst, 8 * sizeof(*(list->index)),
2438 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
2439 if (list->index == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002440 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002441 "loader_add_dev_ext_table() can't allocate list memory");
2442 return false;
2443 }
2444 list->capacity = 8 * sizeof(*(list->index));
2445 } else if (list->capacity < (list->count + 1) * sizeof(*(list->index))) {
2446 list->index = loader_heap_realloc(inst, list->index, list->capacity,
2447 list->capacity * 2,
2448 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
2449 if (list->index == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002450 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002451 "loader_add_dev_ext_table() can't reallocate list memory");
2452 return false;
2453 }
2454 list->capacity *= 2;
2455 }
2456
2457 //find an unused index in the hash table and use it
2458 i = (idx + 1) % MAX_NUM_DEV_EXTS;
2459 do {
2460 if (!inst->disp_hash[i].func_name) {
2461 assert(inst->disp_hash[i].list.capacity == 0);
2462 inst->disp_hash[i].func_name = (char *) loader_heap_alloc(inst,
2463 strlen(funcName) + 1,
2464 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
2465 if (inst->disp_hash[i].func_name == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002466 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002467 "loader_add_dev_ext_table() can't rallocate func_name memory");
2468 return false;
2469 }
2470 strncpy(inst->disp_hash[i].func_name, funcName, strlen(funcName) + 1);
2471 list->index[list->count] = i;
2472 list->count++;
2473 *ptr_idx = i;
2474 return true;
2475 }
2476 i = (i + 1) % MAX_NUM_DEV_EXTS;
2477 } while (i != idx);
2478
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002479 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002480 "loader_add_dev_ext_table() couldn't insert into hash table; is it full?");
2481 return false;
2482}
2483
2484static bool loader_name_in_dev_ext_table(struct loader_instance *inst,
2485 uint32_t *idx,
2486 const char *funcName)
2487{
2488 uint32_t alt_idx;
2489 if (inst->disp_hash[*idx].func_name && !strcmp(
2490 inst->disp_hash[*idx].func_name,
2491 funcName))
2492 return true;
2493
2494 // funcName wasn't at the primary spot in the hash table
2495 // search the list of secondary locations (shallow search, not deep search)
2496 for (uint32_t i = 0; i < inst->disp_hash[*idx].list.count; i++) {
2497 alt_idx = inst->disp_hash[*idx].list.index[i];
2498 if (!strcmp(inst->disp_hash[*idx].func_name, funcName)) {
2499 *idx = alt_idx;
2500 return true;
2501 }
2502 }
2503
2504 return false;
2505}
2506
2507/**
2508 * This function returns generic trampoline code address for unknown entry points.
2509 * Presumably, these unknown entry points (as given by funcName) are device
2510 * extension entrypoints. A hash table is used to keep a list of unknown entry
2511 * points and their mapping to the device extension dispatch table
2512 * (struct loader_dev_ext_dispatch_table).
2513 * \returns
2514 * For a given entry point string (funcName), if an existing mapping is found the
2515 * trampoline address for that mapping is returned. Otherwise, this unknown entry point
2516 * has not been seen yet. Next check if a layer or ICD supports it. If so then a
2517 * new entry in the hash table is initialized and that trampoline address for
2518 * the new entry is returned. Null is returned if the hash table is full or
2519 * if no discovered layer or ICD returns a non-NULL GetProcAddr for it.
2520 */
2521void *loader_dev_ext_gpa(struct loader_instance *inst,
2522 const char *funcName)
2523{
2524 uint32_t idx;
2525 uint32_t seed = 0;
2526
2527 idx = murmurhash(funcName, strlen(funcName), seed) % MAX_NUM_DEV_EXTS;
2528
2529 if (loader_name_in_dev_ext_table(inst, &idx, funcName))
2530 // found funcName already in hash
2531 return loader_get_dev_ext_trampoline(idx);
2532
2533 // Check if funcName is supported in either ICDs or a layer library
2534 if (!loader_check_icds_for_address(inst, funcName)) {
2535 // TODO Add check in layer libraries for support of address
2536 // if support found in layers continue on
2537 return NULL;
2538 }
2539
2540 if (loader_add_dev_ext_table(inst, &idx, funcName)) {
2541 // successfully added new table entry
2542 // init any dev dispatch table entrys as needed
2543 loader_init_dispatch_dev_ext_entry(inst, NULL, idx, funcName);
2544 return loader_get_dev_ext_trampoline(idx);
2545 }
2546
2547 return NULL;
2548}
2549
Jon Ashburne0e64572015-09-30 12:56:42 -06002550struct loader_instance *loader_get_instance(const VkInstance instance)
2551{
2552 /* look up the loader_instance in our list by comparing dispatch tables, as
2553 * there is no guarantee the instance is still a loader_instance* after any
2554 * layers which wrap the instance object.
2555 */
2556 const VkLayerInstanceDispatchTable *disp;
2557 struct loader_instance *ptr_instance = NULL;
2558 disp = loader_get_instance_dispatch(instance);
2559 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
2560 if (inst->disp == disp) {
2561 ptr_instance = inst;
2562 break;
2563 }
2564 }
2565 return ptr_instance;
2566}
2567
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002568static loader_platform_dl_handle loader_add_layer_lib(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002569 const struct loader_instance *inst,
Jon Ashburn4f67d742015-05-27 13:19:22 -06002570 const char *chain_type,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002571 struct loader_layer_properties *layer_prop)
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002572{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002573 struct loader_lib_info *new_layer_lib_list, *my_lib;
Jon Ashburne39a4f82015-08-28 13:38:21 -06002574 size_t new_alloc_size;
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -06002575 /*
2576 * TODO: We can now track this information in the
2577 * scanned_layer_libraries list.
2578 */
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002579 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) {
Jon Ashburn3d002332015-08-20 16:35:30 -06002580 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, layer_prop->lib_name) == 0) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002581 /* Have already loaded this library, just increment ref count */
2582 loader.loaded_layer_lib_list[i].ref_count++;
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002583 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002584 "%s Chain: Increment layer reference count for layer library %s",
Jon Ashburn3d002332015-08-20 16:35:30 -06002585 chain_type, layer_prop->lib_name);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002586 return loader.loaded_layer_lib_list[i].lib_handle;
2587 }
2588 }
2589
2590 /* Haven't seen this library so load it */
Jon Ashburne39a4f82015-08-28 13:38:21 -06002591 new_alloc_size = 0;
2592 if (loader.loaded_layer_lib_capacity == 0)
2593 new_alloc_size = 8 * sizeof(struct loader_lib_info);
2594 else if (loader.loaded_layer_lib_capacity <= loader.loaded_layer_lib_count *
2595 sizeof(struct loader_lib_info))
2596 new_alloc_size = loader.loaded_layer_lib_capacity * 2;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002597
Jon Ashburne39a4f82015-08-28 13:38:21 -06002598 if (new_alloc_size) {
2599 new_layer_lib_list = loader_heap_realloc(
2600 inst, loader.loaded_layer_lib_list,
2601 loader.loaded_layer_lib_capacity,
2602 new_alloc_size,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002603 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburne39a4f82015-08-28 13:38:21 -06002604 if (!new_layer_lib_list) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002605 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 -06002606 return NULL;
2607 }
2608 loader.loaded_layer_lib_capacity = new_alloc_size;
Courtney Goeltzenleuchter54ce81a2015-12-09 12:26:34 -07002609 loader.loaded_layer_lib_list = new_layer_lib_list;
Jon Ashburne39a4f82015-08-28 13:38:21 -06002610 } else
2611 new_layer_lib_list = loader.loaded_layer_lib_list;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002612 my_lib = &new_layer_lib_list[loader.loaded_layer_lib_count];
2613
Jon Ashburn3d002332015-08-20 16:35:30 -06002614 strncpy(my_lib->lib_name, layer_prop->lib_name, sizeof(my_lib->lib_name));
2615 my_lib->lib_name[sizeof(my_lib->lib_name) - 1] = '\0';
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002616 my_lib->ref_count = 0;
2617 my_lib->lib_handle = NULL;
2618
2619 if ((my_lib->lib_handle = loader_platform_open_library(my_lib->lib_name)) == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002620 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002621 loader_platform_open_library_error(my_lib->lib_name));
2622 return NULL;
2623 } else {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002624 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002625 "Chain: %s: Loading layer library %s",
Jon Ashburn3d002332015-08-20 16:35:30 -06002626 chain_type, layer_prop->lib_name);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002627 }
2628 loader.loaded_layer_lib_count++;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002629 my_lib->ref_count++;
2630
2631 return my_lib->lib_handle;
2632}
2633
2634static void loader_remove_layer_lib(
2635 struct loader_instance *inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002636 struct loader_layer_properties *layer_prop)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002637{
Courtney Goeltzenleuchter80bfd0e2015-12-17 09:51:22 -07002638 uint32_t idx = loader.loaded_layer_lib_count;
Tony Barbourb5d2c942015-07-14 13:34:05 -06002639 struct loader_lib_info *new_layer_lib_list, *my_lib = NULL;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002640
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002641 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) {
Jon Ashburn3d002332015-08-20 16:35:30 -06002642 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, layer_prop->lib_name) == 0) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002643 /* found matching library */
2644 idx = i;
2645 my_lib = &loader.loaded_layer_lib_list[i];
2646 break;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002647 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002648 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002649
Courtney Goeltzenleuchter80bfd0e2015-12-17 09:51:22 -07002650 if (idx == loader.loaded_layer_lib_count) {
Jon Ashburn6766ae92015-12-17 14:30:21 -07002651 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Courtney Goeltzenleuchter80bfd0e2015-12-17 09:51:22 -07002652 "Unable to unref library %s", layer_prop->lib_name);
2653 return;
2654 }
2655
Tony Barbourb5d2c942015-07-14 13:34:05 -06002656 if (my_lib) {
2657 my_lib->ref_count--;
2658 if (my_lib->ref_count > 0) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002659 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
Jon Ashburn3d002332015-08-20 16:35:30 -06002660 "Decrement reference count for layer library %s", layer_prop->lib_name);
Tony Barbourb5d2c942015-07-14 13:34:05 -06002661 return;
2662 }
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07002663 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002664 loader_platform_close_library(my_lib->lib_handle);
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002665 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
Jon Ashburn3d002332015-08-20 16:35:30 -06002666 "Unloading layer library %s", layer_prop->lib_name);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002667
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002668 /* Need to remove unused library from list */
Jon Ashburne39a4f82015-08-28 13:38:21 -06002669 new_layer_lib_list = loader_heap_alloc(inst,
2670 loader.loaded_layer_lib_capacity,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002671 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002672 if (!new_layer_lib_list) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002673 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 -06002674 return;
2675 }
2676
2677 if (idx > 0) {
2678 /* Copy records before idx */
2679 memcpy(new_layer_lib_list, &loader.loaded_layer_lib_list[0],
2680 sizeof(struct loader_lib_info) * idx);
2681 }
2682 if (idx < (loader.loaded_layer_lib_count - 1)) {
2683 /* Copy records after idx */
2684 memcpy(&new_layer_lib_list[idx], &loader.loaded_layer_lib_list[idx+1],
2685 sizeof(struct loader_lib_info) * (loader.loaded_layer_lib_count - idx - 1));
2686 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002687
Jon Ashburne39a4f82015-08-28 13:38:21 -06002688 loader_heap_free(inst, loader.loaded_layer_lib_list);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002689 loader.loaded_layer_lib_count--;
2690 loader.loaded_layer_lib_list = new_layer_lib_list;
Jon Ashburnb8358052014-11-18 09:06:04 -07002691}
2692
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002693
2694/**
2695 * Go through the search_list and find any layers which match type. If layer
2696 * type match is found in then add it to ext_list.
2697 */
Jon Ashburn0c26e712015-07-02 16:10:32 -06002698static void loader_add_layer_implicit(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002699 const struct loader_instance *inst,
Jon Ashburn0c26e712015-07-02 16:10:32 -06002700 const enum layer_type type,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002701 struct loader_layer_list *list,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002702 const struct loader_layer_list *search_list)
Jon Ashburn0c26e712015-07-02 16:10:32 -06002703{
Jon Ashburn075ce432015-12-17 17:38:24 -07002704 bool enable;
2705 char *env_value;
Jon Ashburn0c26e712015-07-02 16:10:32 -06002706 uint32_t i;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002707 for (i = 0; i < search_list->count; i++) {
2708 const struct loader_layer_properties *prop = &search_list->list[i];
Jon Ashburn0c26e712015-07-02 16:10:32 -06002709 if (prop->type & type) {
Jon Ashburn075ce432015-12-17 17:38:24 -07002710 /* Found an implicit layer, see if it should be enabled */
2711 enable = false;
2712
2713 // if no enable_environment variable is specified, this implicit layer
2714 // should always be enabled. Otherwise check if the variable is set
2715 if (prop->enable_env_var.name[0] == 0) {
2716 enable = true;
2717 } else {
Jon Ashburn38a497f2016-01-04 14:01:38 -07002718 env_value = loader_getenv(prop->enable_env_var.name);
Jon Ashburn075ce432015-12-17 17:38:24 -07002719 if (env_value && !strcmp(prop->enable_env_var.value, env_value))
2720 enable = true;
Jon Ashburn38a497f2016-01-04 14:01:38 -07002721 loader_free_getenv(env_value);
Jon Ashburn075ce432015-12-17 17:38:24 -07002722 }
2723
2724 // disable_environment has priority, i.e. if both enable and disable
2725 // environment variables are set, the layer is disabled. Implicit layers
2726 // are required to have a disable_environment variables
Jon Ashburn38a497f2016-01-04 14:01:38 -07002727 env_value = loader_getenv(prop->disable_env_var.name);
Jon Ashburn075ce432015-12-17 17:38:24 -07002728 if (env_value)
2729 enable = false;
Jon Ashburn38a497f2016-01-04 14:01:38 -07002730 loader_free_getenv(env_value);
Jon Ashburn075ce432015-12-17 17:38:24 -07002731
2732 if (enable)
2733 loader_add_to_layer_list(inst, list, 1, prop);
Jon Ashburn0c26e712015-07-02 16:10:32 -06002734 }
2735 }
2736
2737}
2738
2739/**
2740 * Get the layer name(s) from the env_name environment variable. If layer
Jon Ashburnbd332cc2015-07-07 10:27:45 -06002741 * is found in search_list then add it to layer_list. But only add it to
2742 * layer_list if type matches.
Jon Ashburn0c26e712015-07-02 16:10:32 -06002743 */
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002744static void loader_add_layer_env(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002745 const struct loader_instance *inst,
Jon Ashburnbd332cc2015-07-07 10:27:45 -06002746 const enum layer_type type,
Jon Ashburneb6d5682015-07-02 14:10:53 -06002747 const char *env_name,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002748 struct loader_layer_list *layer_list,
2749 const struct loader_layer_list *search_list)
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002750{
Ian Elliott4470a302015-02-17 10:33:47 -07002751 char *layerEnv;
Jon Ashburneb6d5682015-07-02 14:10:53 -06002752 char *next, *name;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002753
Jon Ashburn38a497f2016-01-04 14:01:38 -07002754 layerEnv = loader_getenv(env_name);
Ian Elliott4470a302015-02-17 10:33:47 -07002755 if (layerEnv == NULL) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002756 return;
Ian Elliott4470a302015-02-17 10:33:47 -07002757 }
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -06002758 name = loader_stack_alloc(strlen(layerEnv) + 1);
Jon Ashburneb6d5682015-07-02 14:10:53 -06002759 if (name == NULL) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002760 return;
Ian Elliott4470a302015-02-17 10:33:47 -07002761 }
Jon Ashburneb6d5682015-07-02 14:10:53 -06002762 strcpy(name, layerEnv);
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002763
Jon Ashburn38a497f2016-01-04 14:01:38 -07002764 loader_free_getenv(layerEnv);
2765
Jon Ashburneb6d5682015-07-02 14:10:53 -06002766 while (name && *name ) {
2767 next = loader_get_next_path(name);
Jon Ashburne39a4f82015-08-28 13:38:21 -06002768 loader_find_layer_name_add_list(inst, name, type, search_list, layer_list);
Jon Ashburneb6d5682015-07-02 14:10:53 -06002769 name = next;
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07002770 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002771
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002772 return;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002773}
2774
Courtney Goeltzenleuchter7d0023c2015-06-08 15:09:22 -06002775void loader_deactivate_instance_layers(struct loader_instance *instance)
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002776{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002777 /* Create instance chain of enabled layers */
Courtney Goeltzenleuchter7d0023c2015-06-08 15:09:22 -06002778 for (uint32_t i = 0; i < instance->activated_layer_list.count; i++) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002779 struct loader_layer_properties *layer_prop = &instance->activated_layer_list.list[i];
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002780
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002781 loader_remove_layer_lib(instance, layer_prop);
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002782 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06002783 loader_destroy_layer_list(instance, &instance->activated_layer_list);
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002784}
2785
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002786VkResult loader_enable_instance_layers(
Jon Ashburnb82c1852015-08-11 14:49:54 -06002787 struct loader_instance *inst,
2788 const VkInstanceCreateInfo *pCreateInfo,
2789 const struct loader_layer_list *instance_layers)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002790{
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002791 VkResult err;
2792
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06002793 assert(inst && "Cannot have null instance");
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002794
Jon Ashburne39a4f82015-08-28 13:38:21 -06002795 if (!loader_init_layer_list(inst, &inst->activated_layer_list)) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002796 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Failed to alloc Instance activated layer list");
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002797 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002798 }
2799
Jon Ashburn0c26e712015-07-02 16:10:32 -06002800 /* Add any implicit layers first */
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002801 loader_add_layer_implicit(inst,
2802 VK_LAYER_TYPE_INSTANCE_IMPLICIT,
2803 &inst->activated_layer_list,
2804 instance_layers);
Jon Ashburn0c26e712015-07-02 16:10:32 -06002805
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002806 /* Add any layers specified via environment variable next */
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002807 loader_add_layer_env(inst,
2808 VK_LAYER_TYPE_INSTANCE_EXPLICIT,
2809 "VK_INSTANCE_LAYERS",
2810 &inst->activated_layer_list,
2811 instance_layers);
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002812
2813 /* Add layers specified by the application */
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002814 err = loader_add_layer_names_to_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002815 inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002816 &inst->activated_layer_list,
Jon Ashburnf19916e2016-01-11 13:12:43 -07002817 pCreateInfo->enabledLayerCount,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002818 pCreateInfo->ppEnabledLayerNames,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002819 instance_layers);
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002820
2821 return err;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002822}
2823
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002824/*
2825 * Given the list of layers to activate in the loader_instance
2826 * structure. This function will add a VkLayerInstanceCreateInfo
2827 * structure to the VkInstanceCreateInfo.pNext pointer.
2828 * Each activated layer will have it's own VkLayerInstanceLink
2829 * structure that tells the layer what Get*ProcAddr to call to
2830 * get function pointers to the next layer down.
2831 * Once the chain info has been created this function will
2832 * execute the CreateInstance call chain. Each layer will
2833 * then have an opportunity in it's CreateInstance function
2834 * to setup it's dispatch table when the lower layer returns
2835 * successfully.
2836 * Each layer can wrap or not-wrap the returned VkInstance object
2837 * as it sees fit.
2838 * The instance chain is terminated by a loader function
2839 * that will call CreateInstance on all available ICD's and
2840 * cache those VkInstance objects for future use.
2841 */
2842VkResult loader_create_instance_chain(const VkInstanceCreateInfo *pCreateInfo,
2843 const VkAllocationCallbacks* pAllocator,
Jon Ashburn373c1802016-01-20 08:08:25 -07002844 struct loader_instance *inst,
2845 VkInstance created_instance)
Jon Ashburn27cd5842015-05-12 17:26:48 -06002846{
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002847 uint32_t activated_layers = 0;
2848 VkLayerInstanceCreateInfo chain_info;
2849 VkLayerInstanceLink *layer_instance_link_info = NULL;
2850 VkInstanceCreateInfo loader_create_info;
2851 VkResult res;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002852
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002853 PFN_vkGetInstanceProcAddr nextGIPA = loader_gpa_instance_internal;
2854 PFN_vkGetInstanceProcAddr fpGIPA = loader_gpa_instance_internal;
Jon Ashburn27cd5842015-05-12 17:26:48 -06002855
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002856 memcpy(&loader_create_info, pCreateInfo, sizeof(VkInstanceCreateInfo));
Jon Ashburn27cd5842015-05-12 17:26:48 -06002857
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002858 if (inst->activated_layer_list.count > 0) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002859
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002860 chain_info.u.pLayerInfo = NULL;
2861 chain_info.pNext = pCreateInfo->pNext;
2862 chain_info.sType = VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO;
2863 chain_info.function = VK_LAYER_LINK_INFO;
2864 loader_create_info.pNext = &chain_info;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002865
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002866 layer_instance_link_info = loader_stack_alloc(sizeof(VkLayerInstanceLink)
2867 * inst->activated_layer_list.count);
2868 if (!layer_instance_link_info) {
2869 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Failed to alloc Instance objects for layer");
2870 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburn27cd5842015-05-12 17:26:48 -06002871 }
2872
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002873 /* Create instance chain of enabled layers */
2874 for (int32_t i = inst->activated_layer_list.count - 1; i >= 0; i--) {
2875 struct loader_layer_properties *layer_prop = &inst->activated_layer_list.list[i];
2876 loader_platform_dl_handle lib_handle;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002877
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002878 lib_handle = loader_add_layer_lib(inst, "instance", layer_prop);
2879 if (!lib_handle)
Courtney Goeltzenleuchter524b7e32016-01-14 16:06:06 -07002880 continue;
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002881 if ((fpGIPA = layer_prop->functions.get_instance_proc_addr) == NULL) {
2882 if (layer_prop->functions.str_gipa == NULL || strlen(layer_prop->functions.str_gipa) == 0) {
2883 fpGIPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetInstanceProcAddr");
2884 layer_prop->functions.get_instance_proc_addr = fpGIPA;
2885 } else
2886 fpGIPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gipa);
2887 if (!fpGIPA) {
2888 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Failed to find vkGetInstanceProcAddr in layer %s", layer_prop->lib_name);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002889 continue;
2890 }
2891 }
2892
2893 layer_instance_link_info[activated_layers].pNext = chain_info.u.pLayerInfo;
2894 layer_instance_link_info[activated_layers].pfnNextGetInstanceProcAddr = nextGIPA;
2895 chain_info.u.pLayerInfo = &layer_instance_link_info[activated_layers];
2896 nextGIPA = fpGIPA;
2897
2898 loader_log(inst, VK_DEBUG_REPORT_INFO_BIT_EXT, 0,
2899 "Insert instance layer %s (%s)",
2900 layer_prop->info.layerName,
2901 layer_prop->lib_name);
2902
2903 activated_layers++;
2904 }
Jon Ashburn27cd5842015-05-12 17:26:48 -06002905 }
2906
Jon Ashburn373c1802016-01-20 08:08:25 -07002907 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance) nextGIPA(created_instance, "vkCreateInstance");
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002908 if (fpCreateInstance) {
2909 VkLayerInstanceCreateInfo instance_create_info;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002910
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002911 instance_create_info.sType = VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO;
2912 instance_create_info.function = VK_LAYER_INSTANCE_INFO;
2913
2914 instance_create_info.u.instanceInfo.instance_info = inst;
2915 instance_create_info.u.instanceInfo.pfnNextGetInstanceProcAddr= nextGIPA;
2916
2917 instance_create_info.pNext = loader_create_info.pNext;
2918 loader_create_info.pNext = &instance_create_info;
2919
Jon Ashburn373c1802016-01-20 08:08:25 -07002920 res = fpCreateInstance(&loader_create_info, pAllocator, &created_instance);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002921 } else {
2922 // Couldn't find CreateInstance function!
2923 res = VK_ERROR_INITIALIZATION_FAILED;
2924 }
2925
2926 if (res != VK_SUCCESS) {
2927 // TODO: Need to clean up here
2928 } else {
Jon Ashburn373c1802016-01-20 08:08:25 -07002929 loader_init_instance_core_dispatch_table(inst->disp, nextGIPA, created_instance);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002930 }
2931
2932 return res;
Jon Ashburn27cd5842015-05-12 17:26:48 -06002933}
2934
Jon Ashburn5f556602016-01-12 09:55:14 -07002935void loader_activate_instance_layer_extensions(struct loader_instance *inst, VkInstance created_inst)
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002936{
2937
2938 loader_init_instance_extension_dispatch_table(inst->disp,
2939 inst->disp->GetInstanceProcAddr,
Jon Ashburn5f556602016-01-12 09:55:14 -07002940 created_inst);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002941}
2942
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002943static VkResult loader_enable_device_layers(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002944 const struct loader_instance *inst,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002945 struct loader_icd *icd,
Jon Ashburn471f44c2016-01-13 12:51:43 -07002946 struct loader_layer_list *activated_layer_list,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002947 const VkDeviceCreateInfo *pCreateInfo,
2948 const struct loader_layer_list *device_layers)
2949
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002950{
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002951 VkResult err;
2952
Jon Ashburn471f44c2016-01-13 12:51:43 -07002953 assert(activated_layer_list && "Cannot have null output layer list");
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002954
Jon Ashburn471f44c2016-01-13 12:51:43 -07002955 if (activated_layer_list->list == NULL || activated_layer_list->capacity == 0) {
2956 loader_init_layer_list(inst, activated_layer_list);
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002957 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002958
Jon Ashburn471f44c2016-01-13 12:51:43 -07002959 if (activated_layer_list->list == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002960 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Failed to alloc device activated layer list");
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002961 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002962 }
2963
Jon Ashburn0c26e712015-07-02 16:10:32 -06002964 /* Add any implicit layers first */
2965 loader_add_layer_implicit(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002966 inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002967 VK_LAYER_TYPE_DEVICE_IMPLICIT,
Jon Ashburn471f44c2016-01-13 12:51:43 -07002968 activated_layer_list,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002969 device_layers);
Jon Ashburn0c26e712015-07-02 16:10:32 -06002970
2971 /* Add any layers specified via environment variable next */
Jon Ashburneb6d5682015-07-02 14:10:53 -06002972 loader_add_layer_env(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002973 inst,
Jon Ashburnbd332cc2015-07-07 10:27:45 -06002974 VK_LAYER_TYPE_DEVICE_EXPLICIT,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002975 "VK_DEVICE_LAYERS",
Jon Ashburn471f44c2016-01-13 12:51:43 -07002976 activated_layer_list,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002977 device_layers);
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002978
2979 /* Add layers specified by the application */
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002980 err = loader_add_layer_names_to_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002981 inst,
Jon Ashburn471f44c2016-01-13 12:51:43 -07002982 activated_layer_list,
Jon Ashburnf19916e2016-01-11 13:12:43 -07002983 pCreateInfo->enabledLayerCount,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002984 pCreateInfo->ppEnabledLayerNames,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002985 device_layers);
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002986
2987 return err;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002988}
2989
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002990VkResult loader_create_device_terminator(
2991 VkPhysicalDevice physicalDevice,
2992 const VkDeviceCreateInfo* pCreateInfo,
2993 const VkAllocationCallbacks* pAllocator,
2994 VkDevice* pDevice)
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002995{
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002996 struct loader_physical_device *phys_dev;
2997 phys_dev = loader_get_physical_device(physicalDevice);
2998
2999 VkLayerDeviceCreateInfo *chain_info = (VkLayerDeviceCreateInfo *) pCreateInfo->pNext;
3000 while (chain_info && !(chain_info->sType == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO
3001 && chain_info->function == VK_LAYER_DEVICE_INFO)) {
3002 chain_info = (VkLayerDeviceCreateInfo *) chain_info->pNext;
3003 }
3004 assert(chain_info != NULL);
3005
3006 struct loader_device *dev = (struct loader_device *) chain_info->u.deviceInfo.device_info;
3007 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.deviceInfo.pfnNextGetInstanceProcAddr;
3008 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice) fpGetInstanceProcAddr(phys_dev->this_icd->instance, "vkCreateDevice");
3009 if (fpCreateDevice == NULL) {
3010 return VK_ERROR_INITIALIZATION_FAILED;
3011 }
3012
3013 VkDeviceCreateInfo localCreateInfo;
3014 memcpy(&localCreateInfo, pCreateInfo, sizeof(localCreateInfo));
Courtney Goeltzenleuchterb39ccd52016-01-15 14:15:00 -07003015 localCreateInfo.pNext = loader_strip_create_extensions(pCreateInfo->pNext);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003016 // ICDs do not support layers
3017 localCreateInfo.enabledLayerCount = 0;
3018 localCreateInfo.ppEnabledLayerNames = NULL;
3019
3020 VkDevice localDevice;
Courtney Goeltzenleuchter02f8df72016-01-15 14:15:24 -07003021 // TODO: Why does fpCreateDevice behave differently than this_icd->CreateDevice?
3022// VkResult res = fpCreateDevice(phys_dev->phys_dev, &localCreateInfo, pAllocator, &localDevice);
3023 VkResult res = phys_dev->this_icd->CreateDevice(phys_dev->phys_dev, &localCreateInfo, pAllocator, &localDevice);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003024
3025 if (res != VK_SUCCESS) {
3026 return res;
3027 }
3028
3029 *pDevice = localDevice;
3030
3031 /* Init dispatch pointer in new device object */
3032 loader_init_dispatch(*pDevice, &dev->loader_dispatch);
3033
3034 return res;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003035}
3036
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003037VkResult loader_create_device_chain(
3038 VkPhysicalDevice physicalDevice,
3039 const VkDeviceCreateInfo *pCreateInfo,
3040 const VkAllocationCallbacks* pAllocator,
3041 struct loader_instance *inst,
3042 struct loader_icd *icd,
3043 struct loader_device *dev)
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003044{
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003045 uint32_t activated_layers = 0;
3046 VkLayerDeviceLink *layer_device_link_info;
3047 VkLayerDeviceCreateInfo chain_info;
3048 VkLayerDeviceCreateInfo device_info;
3049 VkDeviceCreateInfo loader_create_info;
3050 VkResult res;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003051
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003052 PFN_vkGetDeviceProcAddr fpGDPA, nextGDPA = icd->GetDeviceProcAddr;
3053 PFN_vkGetInstanceProcAddr fpGIPA, nextGIPA = loader_gpa_instance_internal;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003054
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003055 memcpy(&loader_create_info, pCreateInfo, sizeof(VkDeviceCreateInfo));
3056
3057 chain_info.sType = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO;
3058 chain_info.function = VK_LAYER_LINK_INFO;
3059 chain_info.u.pLayerInfo = NULL;
3060 chain_info.pNext = pCreateInfo->pNext;
3061
3062 layer_device_link_info = loader_stack_alloc(sizeof(VkLayerDeviceLink)
3063 * dev->activated_layer_list.count);
3064 if (!layer_device_link_info) {
3065 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Failed to alloc Device objects for layer");
3066 return VK_ERROR_OUT_OF_HOST_MEMORY;
David Pinedoa0a8a242015-06-24 15:29:18 -06003067 }
Jon Ashburn94e70492015-06-10 10:13:10 -06003068
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003069 /*
3070 * This structure is used by loader_create_device_terminator
3071 * so that it can intialize the device dispatch table pointer
3072 * in the device object returned by the ICD. Without this
3073 * structure the code wouldn't know where the loader's device_info
3074 * structure is located.
3075 */
3076 device_info.sType = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO;
3077 device_info.function = VK_LAYER_DEVICE_INFO;
3078 device_info.pNext = &chain_info;
3079 device_info.u.deviceInfo.device_info = dev;
3080 device_info.u.deviceInfo.pfnNextGetInstanceProcAddr = icd->this_icd_lib->GetInstanceProcAddr;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003081
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003082 loader_create_info.pNext = &device_info;
Jon Ashburn94e70492015-06-10 10:13:10 -06003083
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003084 if (dev->activated_layer_list.count > 0) {
3085 /* Create instance chain of enabled layers */
3086 for (int32_t i = dev->activated_layer_list.count - 1; i >= 0; i--) {
3087 struct loader_layer_properties *layer_prop = &dev->activated_layer_list.list[i];
3088 loader_platform_dl_handle lib_handle;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003089
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003090 lib_handle = loader_add_layer_lib(inst, "device", layer_prop);
3091 if (!lib_handle)
Courtney Goeltzenleuchter524b7e32016-01-14 16:06:06 -07003092 continue;
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003093 if ((fpGIPA = layer_prop->functions.get_instance_proc_addr) == NULL) {
3094 if (layer_prop->functions.str_gipa == NULL || strlen(layer_prop->functions.str_gipa) == 0) {
3095 fpGIPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetInstanceProcAddr");
3096 layer_prop->functions.get_instance_proc_addr = fpGIPA;
3097 } else
3098 fpGIPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gipa);
3099 if (!fpGIPA) {
3100 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Failed to find vkGetInstanceProcAddr in layer %s", layer_prop->lib_name);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003101 continue;
3102 }
Jon Ashburn21c21ee2015-09-09 11:29:24 -06003103 }
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003104 if ((fpGDPA = layer_prop->functions.get_device_proc_addr) == NULL) {
3105 if (layer_prop->functions.str_gdpa == NULL || strlen(layer_prop->functions.str_gdpa) == 0) {
3106 fpGDPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetDeviceProcAddr");
3107 layer_prop->functions.get_device_proc_addr = fpGDPA;
3108 } else
3109 fpGDPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gdpa);
3110 if (!fpGDPA) {
3111 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Failed to find vkGetDeviceProcAddr in layer %s", layer_prop->lib_name);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003112 continue;
3113 }
3114 }
3115
3116 layer_device_link_info[activated_layers].pNext = chain_info.u.pLayerInfo;
3117 layer_device_link_info[activated_layers].pfnNextGetInstanceProcAddr = nextGIPA;
3118 layer_device_link_info[activated_layers].pfnNextGetDeviceProcAddr = nextGDPA;
3119 chain_info.u.pLayerInfo = &layer_device_link_info[activated_layers];
3120 nextGIPA = fpGIPA;
3121 nextGDPA = fpGDPA;
3122
3123 loader_log(inst, VK_DEBUG_REPORT_INFO_BIT_EXT, 0,
3124 "Insert device layer %s (%s)",
3125 layer_prop->info.layerName,
3126 layer_prop->lib_name);
3127
3128 activated_layers++;
Jon Ashburn94e70492015-06-10 10:13:10 -06003129 }
Jon Ashburn94e70492015-06-10 10:13:10 -06003130 }
3131
Jon Ashburn373c1802016-01-20 08:08:25 -07003132 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice) nextGIPA((VkInstance) inst, "vkCreateDevice");
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003133 if (fpCreateDevice) {
3134 res = fpCreateDevice(physicalDevice, &loader_create_info, pAllocator, &dev->device);
3135 } else {
3136 // Couldn't find CreateDevice function!
3137 return VK_ERROR_INITIALIZATION_FAILED;
3138 }
Jon Ashburn94e70492015-06-10 10:13:10 -06003139
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003140 /* Initialize device dispatch table */
3141 loader_init_device_dispatch_table(&dev->loader_dispatch,
3142 nextGDPA,
3143 dev->device);
3144
3145 return res;
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06003146}
Jon Ashburnd38bfb12014-10-14 19:15:22 -06003147
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003148VkResult loader_validate_layers(
3149 const uint32_t layer_count,
3150 const char * const *ppEnabledLayerNames,
Jon Ashburn3d002332015-08-20 16:35:30 -06003151 const struct loader_layer_list *list)
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06003152{
3153 struct loader_layer_properties *prop;
3154
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003155 for (uint32_t i = 0; i < layer_count; i++) {
Jon Ashburne13ecc92015-08-03 17:19:30 -06003156 prop = loader_get_layer_property(ppEnabledLayerNames[i],
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003157 list);
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06003158 if (!prop) {
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06003159 return VK_ERROR_LAYER_NOT_PRESENT;
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06003160 }
3161 }
3162
3163 return VK_SUCCESS;
3164}
3165
3166VkResult loader_validate_instance_extensions(
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003167 const struct loader_extension_list *icd_exts,
Jon Ashburnb82c1852015-08-11 14:49:54 -06003168 const struct loader_layer_list *instance_layer,
3169 const VkInstanceCreateInfo *pCreateInfo)
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06003170{
Jon Ashburn5c042ea2015-08-04 11:14:18 -06003171 VkExtensionProperties *extension_prop;
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003172 struct loader_layer_properties *layer_prop;
3173
Jon Ashburnf19916e2016-01-11 13:12:43 -07003174 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003175 extension_prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003176 icd_exts);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003177
3178 if (extension_prop) {
3179 continue;
3180 }
3181
3182 extension_prop = NULL;
3183
3184 /* Not in global list, search layer extension lists */
Jon Ashburnf19916e2016-01-11 13:12:43 -07003185 for (uint32_t j = 0; j < pCreateInfo->enabledLayerCount; j++) {
Jon Ashburne13ecc92015-08-03 17:19:30 -06003186 layer_prop = loader_get_layer_property(pCreateInfo->ppEnabledLayerNames[i],
Jon Ashburnb82c1852015-08-11 14:49:54 -06003187 instance_layer);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003188 if (!layer_prop) {
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003189 /* Should NOT get here, loader_validate_layers
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003190 * should have already filtered this case out.
3191 */
3192 continue;
3193 }
3194
3195 extension_prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
3196 &layer_prop->instance_extension_list);
3197 if (extension_prop) {
3198 /* Found the extension in one of the layers enabled by the app. */
3199 break;
3200 }
3201 }
3202
3203 if (!extension_prop) {
3204 /* Didn't find extension name in any of the global layers, error out */
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06003205 return VK_ERROR_EXTENSION_NOT_PRESENT;
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003206 }
3207 }
3208 return VK_SUCCESS;
3209}
3210
3211VkResult loader_validate_device_extensions(
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003212 struct loader_physical_device *phys_dev,
Jon Ashburn471f44c2016-01-13 12:51:43 -07003213 const struct loader_layer_list *activated_device_layers,
Jon Ashburnb82c1852015-08-11 14:49:54 -06003214 const VkDeviceCreateInfo *pCreateInfo)
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003215{
Jon Ashburn5c042ea2015-08-04 11:14:18 -06003216 VkExtensionProperties *extension_prop;
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003217 struct loader_layer_properties *layer_prop;
3218
Jon Ashburnf19916e2016-01-11 13:12:43 -07003219 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003220 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i];
3221 extension_prop = get_extension_property(extension_name,
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003222 &phys_dev->device_extension_cache);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003223
3224 if (extension_prop) {
3225 continue;
3226 }
3227
Jon Ashburn471f44c2016-01-13 12:51:43 -07003228 /* Not in global list, search activated layer extension lists */
3229 for (uint32_t j = 0; j < activated_device_layers->count; j++) {
3230 layer_prop = &activated_device_layers->list[j];
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003231
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07003232 extension_prop = get_dev_extension_property(extension_name,
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003233 &layer_prop->device_extension_list);
3234 if (extension_prop) {
3235 /* Found the extension in one of the layers enabled by the app. */
3236 break;
3237 }
3238 }
3239
3240 if (!extension_prop) {
3241 /* Didn't find extension name in any of the device layers, error out */
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06003242 return VK_ERROR_EXTENSION_NOT_PRESENT;
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003243 }
3244 }
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06003245 return VK_SUCCESS;
3246}
3247
Chia-I Wu9ab61502015-11-06 06:42:02 +08003248VKAPI_ATTR VkResult VKAPI_CALL loader_CreateInstance(
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003249 const VkInstanceCreateInfo* pCreateInfo,
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07003250 const VkAllocationCallbacks* pAllocator,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003251 VkInstance* pInstance)
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003252{
Jon Ashburn46888392015-01-29 15:45:51 -07003253 struct loader_icd *icd;
Jon Ashburn5c042ea2015-08-04 11:14:18 -06003254 VkExtensionProperties *prop;
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003255 char **filtered_extension_names = NULL;
3256 VkInstanceCreateInfo icd_create_info;
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06003257 VkResult res = VK_SUCCESS;
Jon Ashburn7e18de02015-11-19 09:29:51 -07003258 bool success = false;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003259
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003260 VkLayerInstanceCreateInfo *chain_info = (VkLayerInstanceCreateInfo *) pCreateInfo->pNext;
3261 while (chain_info && !(chain_info->sType == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO
3262 && chain_info->function == VK_LAYER_INSTANCE_INFO)) {
3263 chain_info = (VkLayerInstanceCreateInfo *) chain_info->pNext;
3264 }
3265 assert(chain_info != NULL);
3266
3267 struct loader_instance *ptr_instance = (struct loader_instance *) chain_info->u.instanceInfo.instance_info;
Tony Barbour3c78ff42015-12-04 13:24:39 -07003268 memcpy(&icd_create_info, pCreateInfo, sizeof(icd_create_info));
3269
Jon Ashburnf19916e2016-01-11 13:12:43 -07003270 icd_create_info.enabledLayerCount = 0;
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003271 icd_create_info.ppEnabledLayerNames = NULL;
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003272
Courtney Goeltzenleuchterb39ccd52016-01-15 14:15:00 -07003273 // strip off the VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO entries
3274 icd_create_info.pNext = loader_strip_create_extensions(pCreateInfo->pNext);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003275
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003276 /*
3277 * NOTE: Need to filter the extensions to only those
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003278 * supported by the ICD.
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003279 * No ICD will advertise support for layers. An ICD
3280 * library could support a layer, but it would be
3281 * independent of the actual ICD, just in the same library.
3282 */
Jon Ashburnf19916e2016-01-11 13:12:43 -07003283 filtered_extension_names = loader_stack_alloc(pCreateInfo->enabledExtensionCount * sizeof(char *));
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003284 if (!filtered_extension_names) {
3285 return VK_ERROR_OUT_OF_HOST_MEMORY;
3286 }
3287 icd_create_info.ppEnabledExtensionNames = (const char * const *) filtered_extension_names;
3288
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003289 for (uint32_t i = 0; i < ptr_instance->icd_libs.count; i++) {
3290 icd = loader_icd_add(ptr_instance, &ptr_instance->icd_libs.list[i]);
Jon Ashburn46888392015-01-29 15:45:51 -07003291 if (icd) {
Jon Ashburnf19916e2016-01-11 13:12:43 -07003292 icd_create_info.enabledExtensionCount = 0;
Courtney Goeltzenleuchter36eeb742015-12-21 16:41:47 -07003293 struct loader_extension_list icd_exts;
3294
3295 loader_log(ptr_instance, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Build ICD instance extension list");
3296 // traverse scanned icd list adding non-duplicate extensions to the list
3297 loader_init_generic_list(ptr_instance, (struct loader_generic_list *) &icd_exts,
3298 sizeof(VkExtensionProperties));
3299 loader_add_instance_extensions(ptr_instance,
3300 icd->this_icd_lib->EnumerateInstanceExtensionProperties,
3301 icd->this_icd_lib->lib_name,
3302 &icd_exts);
3303
Jon Ashburnf19916e2016-01-11 13:12:43 -07003304 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003305 prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
Courtney Goeltzenleuchter36eeb742015-12-21 16:41:47 -07003306 &icd_exts);
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003307 if (prop) {
Jon Ashburnf19916e2016-01-11 13:12:43 -07003308 filtered_extension_names[icd_create_info.enabledExtensionCount] = (char *) pCreateInfo->ppEnabledExtensionNames[i];
3309 icd_create_info.enabledExtensionCount++;
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003310 }
3311 }
3312
Courtney Goeltzenleuchter36eeb742015-12-21 16:41:47 -07003313 loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *) &icd_exts);
3314
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003315 res = ptr_instance->icd_libs.list[i].CreateInstance(&icd_create_info,
Chia-I Wuf7458c52015-10-26 21:10:41 +08003316 pAllocator,
Jon Ashburn3da71f22015-05-14 12:43:38 -06003317 &(icd->instance));
Jon Ashburn7e18de02015-11-19 09:29:51 -07003318 if (res == VK_SUCCESS)
3319 success = loader_icd_init_entrys(
Jon Ashburnc624c882015-07-16 10:17:29 -06003320 icd,
3321 icd->instance,
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003322 ptr_instance->icd_libs.list[i].GetInstanceProcAddr);
Jon Ashburnc624c882015-07-16 10:17:29 -06003323
3324 if (res != VK_SUCCESS || !success)
Jon Ashburn46888392015-01-29 15:45:51 -07003325 {
3326 ptr_instance->icds = ptr_instance->icds->next;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003327 loader_icd_destroy(ptr_instance, icd);
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07003328 loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburnc624c882015-07-16 10:17:29 -06003329 "ICD ignored: failed to CreateInstance and find entrypoints with ICD");
Jon Ashburn46888392015-01-29 15:45:51 -07003330 }
3331 }
Jon Ashburn46888392015-01-29 15:45:51 -07003332 }
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003333
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06003334 /*
3335 * If no ICDs were added to instance list and res is unchanged
3336 * from it's initial value, the loader was unable to find
3337 * a suitable ICD.
3338 */
Ian Elliotteb450762015-02-05 15:19:15 -07003339 if (ptr_instance->icds == NULL) {
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06003340 if (res == VK_SUCCESS) {
3341 return VK_ERROR_INCOMPATIBLE_DRIVER;
3342 } else {
3343 return res;
3344 }
Ian Elliotteb450762015-02-05 15:19:15 -07003345 }
Jon Ashburn46888392015-01-29 15:45:51 -07003346
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003347 *pInstance = (VkInstance) ptr_instance;
3348
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06003349 return VK_SUCCESS;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003350}
3351
Chia-I Wu9ab61502015-11-06 06:42:02 +08003352VKAPI_ATTR void VKAPI_CALL loader_DestroyInstance(
Chia-I Wuf7458c52015-10-26 21:10:41 +08003353 VkInstance instance,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003354 const VkAllocationCallbacks* pAllocator)
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003355{
Courtney Goeltzenleuchterdeceded2015-06-08 15:04:02 -06003356 struct loader_instance *ptr_instance = loader_instance(instance);
Jon Ashburn3da71f22015-05-14 12:43:38 -06003357 struct loader_icd *icds = ptr_instance->icds;
Jon Ashburna6fd2612015-06-16 14:43:19 -06003358 struct loader_icd *next_icd;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003359
3360 // Remove this instance from the list of instances:
3361 struct loader_instance *prev = NULL;
3362 struct loader_instance *next = loader.instances;
3363 while (next != NULL) {
3364 if (next == ptr_instance) {
3365 // Remove this instance from the list:
3366 if (prev)
3367 prev->next = next->next;
Jon Ashburnc5c49602015-02-03 09:26:59 -07003368 else
3369 loader.instances = next->next;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003370 break;
3371 }
3372 prev = next;
3373 next = next->next;
3374 }
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003375
Jon Ashburn3da71f22015-05-14 12:43:38 -06003376 while (icds) {
3377 if (icds->instance) {
Chia-I Wuf7458c52015-10-26 21:10:41 +08003378 icds->DestroyInstance(icds->instance, pAllocator);
Tony Barbourf20f87b2015-04-22 09:02:32 -06003379 }
Jon Ashburna6fd2612015-06-16 14:43:19 -06003380 next_icd = icds->next;
Jon Ashburn3da71f22015-05-14 12:43:38 -06003381 icds->instance = VK_NULL_HANDLE;
Jon Ashburna6fd2612015-06-16 14:43:19 -06003382 loader_icd_destroy(ptr_instance, icds);
3383
3384 icds = next_icd;
Jon Ashburn46888392015-01-29 15:45:51 -07003385 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06003386 loader_delete_layer_properties(ptr_instance, &ptr_instance->device_layer_list);
3387 loader_delete_layer_properties(ptr_instance, &ptr_instance->instance_layer_list);
3388 loader_scanned_icd_clear(ptr_instance, &ptr_instance->icd_libs);
Jon Ashburn6e6a2162015-12-10 08:51:10 -07003389 loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *)
3390 &ptr_instance->ext_list);
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003391 for (uint32_t i = 0; i < ptr_instance->total_gpu_count; i++)
Jon Ashburn6e6a2162015-12-10 08:51:10 -07003392 loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *)
3393 &ptr_instance->phys_devs[i].device_extension_cache);
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003394 loader_heap_free(ptr_instance, ptr_instance->phys_devs);
Jon Ashburnfc1031e2015-11-17 15:31:02 -07003395 loader_free_dev_ext_table(ptr_instance);
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003396}
3397
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003398VkResult loader_init_physical_device_info(struct loader_instance *ptr_instance)
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003399{
3400 struct loader_icd *icd;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003401 uint32_t i, j, idx, count = 0;
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06003402 VkResult res;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003403 struct loader_phys_dev_per_icd *phys_devs;
3404
3405 ptr_instance->total_gpu_count = 0;
3406 phys_devs = (struct loader_phys_dev_per_icd *) loader_stack_alloc(
3407 sizeof(struct loader_phys_dev_per_icd) *
3408 ptr_instance->total_icd_count);
3409 if (!phys_devs)
3410 return VK_ERROR_OUT_OF_HOST_MEMORY;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003411
3412 icd = ptr_instance->icds;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003413 for (i = 0; i < ptr_instance->total_icd_count; i++) {
3414 assert(icd);
3415 res = icd->EnumeratePhysicalDevices(icd->instance, &phys_devs[i].count, NULL);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003416 if (res != VK_SUCCESS)
3417 return res;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003418 count += phys_devs[i].count;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003419 icd = icd->next;
3420 }
3421
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003422 ptr_instance->phys_devs = (struct loader_physical_device *) loader_heap_alloc(
3423 ptr_instance,
3424 count * sizeof(struct loader_physical_device),
3425 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
3426 if (!ptr_instance->phys_devs)
3427 return VK_ERROR_OUT_OF_HOST_MEMORY;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003428
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003429 icd = ptr_instance->icds;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003430
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003431 struct loader_physical_device *inst_phys_devs = ptr_instance->phys_devs;
3432 idx = 0;
3433 for (i = 0; i < ptr_instance->total_icd_count; i++) {
3434 assert(icd);
3435
3436 phys_devs[i].phys_devs = (VkPhysicalDevice *) loader_stack_alloc(
3437 phys_devs[i].count * sizeof(VkPhysicalDevice));
3438 if (!phys_devs[i].phys_devs) {
Jon Ashburn093ce202015-11-02 17:59:02 -07003439 loader_heap_free(ptr_instance, ptr_instance->phys_devs);
3440 ptr_instance->phys_devs = NULL;
Jon Ashburn128f9422015-05-28 19:16:58 -06003441 return VK_ERROR_OUT_OF_HOST_MEMORY;
3442 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003443 res = icd->EnumeratePhysicalDevices(
3444 icd->instance,
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003445 &(phys_devs[i].count),
3446 phys_devs[i].phys_devs);
3447 if ((res == VK_SUCCESS)) {
3448 ptr_instance->total_gpu_count += phys_devs[i].count;
3449 for (j = 0; j < phys_devs[i].count; j++) {
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003450
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003451 // initialize the loader's physicalDevice object
3452 loader_set_dispatch((void *) &inst_phys_devs[idx], ptr_instance->disp);
3453 inst_phys_devs[idx].this_instance = ptr_instance;
3454 inst_phys_devs[idx].this_icd = icd;
3455 inst_phys_devs[idx].phys_dev = phys_devs[i].phys_devs[j];
Jon Ashburn00eb6c02015-11-02 17:40:01 -07003456 memset(&inst_phys_devs[idx].device_extension_cache, 0, sizeof(struct loader_extension_list));
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003457
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003458 idx++;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003459 }
Jon Ashburn093ce202015-11-02 17:59:02 -07003460 } else {
3461 loader_heap_free(ptr_instance, ptr_instance->phys_devs);
3462 ptr_instance->phys_devs = NULL;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003463 return res;
Jon Ashburn093ce202015-11-02 17:59:02 -07003464 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003465
3466 icd = icd->next;
3467 }
3468
3469 return VK_SUCCESS;
3470}
3471
Chia-I Wu9ab61502015-11-06 06:42:02 +08003472VKAPI_ATTR VkResult VKAPI_CALL loader_EnumeratePhysicalDevices(
Courtney Goeltzenleuchter5e41f1d2015-04-20 12:48:54 -06003473 VkInstance instance,
3474 uint32_t* pPhysicalDeviceCount,
3475 VkPhysicalDevice* pPhysicalDevices)
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003476{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003477 uint32_t i;
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003478 uint32_t copy_count = 0;
Jon Ashburn4c392fb2015-01-28 19:57:09 -07003479 struct loader_instance *ptr_instance = (struct loader_instance *) instance;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003480 VkResult res = VK_SUCCESS;
Jon Ashburn4c392fb2015-01-28 19:57:09 -07003481
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003482 if (ptr_instance->total_gpu_count == 0) {
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003483 res = loader_init_physical_device_info(ptr_instance);
Jon Ashburn4c392fb2015-01-28 19:57:09 -07003484 }
3485
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003486 *pPhysicalDeviceCount = ptr_instance->total_gpu_count;
3487 if (!pPhysicalDevices) {
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003488 return res;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003489 }
Jon Ashburn4c392fb2015-01-28 19:57:09 -07003490
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003491 copy_count = (ptr_instance->total_gpu_count < *pPhysicalDeviceCount) ? ptr_instance->total_gpu_count : *pPhysicalDeviceCount;
3492 for (i = 0; i < copy_count; i++) {
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003493 pPhysicalDevices[i] = (VkPhysicalDevice) &ptr_instance->phys_devs[i];
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003494 }
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003495 *pPhysicalDeviceCount = copy_count;
3496
3497 if (copy_count < ptr_instance->total_gpu_count) {
3498 return VK_INCOMPLETE;
3499 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003500
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003501 return res;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003502}
3503
Chia-I Wu9ab61502015-11-06 06:42:02 +08003504VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceProperties(
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003505 VkPhysicalDevice physicalDevice,
Tony Barbour59a47322015-06-24 16:06:58 -06003506 VkPhysicalDeviceProperties* pProperties)
Jon Ashburn3da71f22015-05-14 12:43:38 -06003507{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003508 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3509 struct loader_icd *icd = phys_dev->this_icd;
Jon Ashburn3da71f22015-05-14 12:43:38 -06003510
Tony Barbour59a47322015-06-24 16:06:58 -06003511 if (icd->GetPhysicalDeviceProperties)
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003512 icd->GetPhysicalDeviceProperties(phys_dev->phys_dev, pProperties);
Tony Barbour59a47322015-06-24 16:06:58 -06003513}
3514
Chia-I Wu9ab61502015-11-06 06:42:02 +08003515VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceQueueFamilyProperties (
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003516 VkPhysicalDevice physicalDevice,
Chia-I Wud50a7d72015-10-26 20:48:51 +08003517 uint32_t* pQueueFamilyPropertyCount,
Cody Northropd0802882015-08-03 17:04:53 -06003518 VkQueueFamilyProperties* pProperties)
Tony Barbour59a47322015-06-24 16:06:58 -06003519{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003520 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3521 struct loader_icd *icd = phys_dev->this_icd;
Tony Barbour59a47322015-06-24 16:06:58 -06003522
Cody Northropd0802882015-08-03 17:04:53 -06003523 if (icd->GetPhysicalDeviceQueueFamilyProperties)
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003524 icd->GetPhysicalDeviceQueueFamilyProperties(phys_dev->phys_dev, pQueueFamilyPropertyCount, pProperties);
Tony Barbour59a47322015-06-24 16:06:58 -06003525}
3526
Chia-I Wu9ab61502015-11-06 06:42:02 +08003527VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceMemoryProperties (
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003528 VkPhysicalDevice physicalDevice,
Tony Barbour59a47322015-06-24 16:06:58 -06003529 VkPhysicalDeviceMemoryProperties* pProperties)
3530{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003531 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3532 struct loader_icd *icd = phys_dev->this_icd;
Tony Barbour59a47322015-06-24 16:06:58 -06003533
3534 if (icd->GetPhysicalDeviceMemoryProperties)
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003535 icd->GetPhysicalDeviceMemoryProperties(phys_dev->phys_dev, pProperties);
Jon Ashburn3da71f22015-05-14 12:43:38 -06003536}
3537
Chia-I Wu9ab61502015-11-06 06:42:02 +08003538VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceFeatures(
Chris Forbesbc0bb772015-06-21 22:55:02 +12003539 VkPhysicalDevice physicalDevice,
3540 VkPhysicalDeviceFeatures* pFeatures)
3541{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003542 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3543 struct loader_icd *icd = phys_dev->this_icd;
Chris Forbesbc0bb772015-06-21 22:55:02 +12003544
3545 if (icd->GetPhysicalDeviceFeatures)
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003546 icd->GetPhysicalDeviceFeatures(phys_dev->phys_dev, pFeatures);
Chris Forbesbc0bb772015-06-21 22:55:02 +12003547}
3548
Chia-I Wu9ab61502015-11-06 06:42:02 +08003549VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceFormatProperties(
Chris Forbesbc0bb772015-06-21 22:55:02 +12003550 VkPhysicalDevice physicalDevice,
3551 VkFormat format,
3552 VkFormatProperties* pFormatInfo)
3553{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003554 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3555 struct loader_icd *icd = phys_dev->this_icd;
Chris Forbesbc0bb772015-06-21 22:55:02 +12003556
Courtney Goeltzenleuchter2caec862015-07-12 12:52:09 -06003557 if (icd->GetPhysicalDeviceFormatProperties)
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003558 icd->GetPhysicalDeviceFormatProperties(phys_dev->phys_dev, format, pFormatInfo);
Chris Forbesbc0bb772015-06-21 22:55:02 +12003559}
3560
Chia-I Wu9ab61502015-11-06 06:42:02 +08003561VKAPI_ATTR VkResult VKAPI_CALL loader_GetPhysicalDeviceImageFormatProperties(
Jon Ashburn754864f2015-07-23 18:49:07 -06003562 VkPhysicalDevice physicalDevice,
3563 VkFormat format,
3564 VkImageType type,
3565 VkImageTiling tiling,
3566 VkImageUsageFlags usage,
Courtney Goeltzenleuchtera22097a2015-09-10 13:44:12 -06003567 VkImageCreateFlags flags,
Jon Ashburn754864f2015-07-23 18:49:07 -06003568 VkImageFormatProperties* pImageFormatProperties)
3569{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003570 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3571 struct loader_icd *icd = phys_dev->this_icd;
Jon Ashburn754864f2015-07-23 18:49:07 -06003572
Chia-I Wu17241042015-10-31 00:31:16 +08003573 if (!icd->GetPhysicalDeviceImageFormatProperties)
3574 return VK_ERROR_INITIALIZATION_FAILED;
3575
3576 return icd->GetPhysicalDeviceImageFormatProperties(phys_dev->phys_dev, format,
3577 type, tiling, usage, flags, pImageFormatProperties);
Jon Ashburn754864f2015-07-23 18:49:07 -06003578}
3579
Chia-I Wu9ab61502015-11-06 06:42:02 +08003580VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceSparseImageFormatProperties(
Mark Lobodzinski16e8bef2015-07-03 15:58:09 -06003581 VkPhysicalDevice physicalDevice,
3582 VkFormat format,
3583 VkImageType type,
Chia-I Wu5c17c962015-10-31 00:31:16 +08003584 VkSampleCountFlagBits samples,
Mark Lobodzinski16e8bef2015-07-03 15:58:09 -06003585 VkImageUsageFlags usage,
3586 VkImageTiling tiling,
3587 uint32_t* pNumProperties,
3588 VkSparseImageFormatProperties* pProperties)
3589{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003590 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3591 struct loader_icd *icd = phys_dev->this_icd;
Mark Lobodzinski16e8bef2015-07-03 15:58:09 -06003592
3593 if (icd->GetPhysicalDeviceSparseImageFormatProperties)
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003594 icd->GetPhysicalDeviceSparseImageFormatProperties(phys_dev->phys_dev, format, type, samples, usage, tiling, pNumProperties, pProperties);
Mark Lobodzinski16e8bef2015-07-03 15:58:09 -06003595}
3596
Chia-I Wu9ab61502015-11-06 06:42:02 +08003597VKAPI_ATTR VkResult VKAPI_CALL loader_CreateDevice(
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003598 VkPhysicalDevice physicalDevice,
Jon Ashburn95a77ba2015-05-15 15:09:35 -06003599 const VkDeviceCreateInfo* pCreateInfo,
Jon Ashburn46674bf2015-12-11 09:41:34 -07003600 const VkAllocationCallbacks* pAllocator,
Jon Ashburn95a77ba2015-05-15 15:09:35 -06003601 VkDevice* pDevice)
3602{
Jon Ashburn46674bf2015-12-11 09:41:34 -07003603 struct loader_physical_device *phys_dev;
3604 struct loader_icd *icd;
Jon Ashburndc6fcad2015-06-10 10:06:06 -06003605 struct loader_device *dev;
Jon Ashburnfc1031e2015-11-17 15:31:02 -07003606 struct loader_instance *inst;
Jon Ashburn471f44c2016-01-13 12:51:43 -07003607 struct loader_layer_list activated_layer_list = {0};
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003608 VkDeviceCreateInfo device_create_info;
3609 char **filtered_extension_names = NULL;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003610 VkResult res;
Jon Ashburn95a77ba2015-05-15 15:09:35 -06003611
Chia-I Wu02124482015-11-06 06:42:02 +08003612 assert(pCreateInfo->queueCreateInfoCount >= 1);
Mark Lobodzinski0c29b922015-09-17 15:17:34 -06003613
Jon Ashburn46674bf2015-12-11 09:41:34 -07003614 //TODO this only works for one physical device per instance
3615 // once CreateDevice layer bootstrapping is done via DeviceCreateInfo
3616 // hopefully don't need this anymore in trampoline code
3617 phys_dev = loader_get_physical_device(physicalDevice);
3618 icd = phys_dev->this_icd;
Jon Ashburna4cf12b2015-10-26 16:54:51 -06003619 if (!icd)
3620 return VK_ERROR_INITIALIZATION_FAILED;
3621
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003622 inst = phys_dev->this_instance;
Jon Ashburna4cf12b2015-10-26 16:54:51 -06003623
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003624 if (!icd->CreateDevice) {
3625 return VK_ERROR_INITIALIZATION_FAILED;
Jon Ashburn95a77ba2015-05-15 15:09:35 -06003626 }
3627
Jon Ashburnb82c1852015-08-11 14:49:54 -06003628 /* validate any app enabled layers are available */
Jon Ashburnf19916e2016-01-11 13:12:43 -07003629 if (pCreateInfo->enabledLayerCount > 0) {
3630 res = loader_validate_layers(pCreateInfo->enabledLayerCount,
Jon Ashburnb82c1852015-08-11 14:49:54 -06003631 pCreateInfo->ppEnabledLayerNames,
Jon Ashburne39a4f82015-08-28 13:38:21 -06003632 &inst->device_layer_list);
Jon Ashburnb82c1852015-08-11 14:49:54 -06003633 if (res != VK_SUCCESS) {
3634 return res;
3635 }
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003636 }
3637
Jon Ashburn00eb6c02015-11-02 17:40:01 -07003638 /* Get the physical device extensions if they haven't been retrieved yet */
3639 if (phys_dev->device_extension_cache.capacity == 0) {
Jon Ashburn6e6a2162015-12-10 08:51:10 -07003640 if (!loader_init_generic_list(inst, (struct loader_generic_list *)
3641 &phys_dev->device_extension_cache,
3642 sizeof(VkExtensionProperties))) {
Jon Ashburn00eb6c02015-11-02 17:40:01 -07003643 return VK_ERROR_OUT_OF_HOST_MEMORY;
3644 }
Jon Ashburn471f44c2016-01-13 12:51:43 -07003645
Courtney Goeltzenleuchterf538ef72015-12-02 14:00:19 -07003646 res = loader_add_device_extensions(
Jon Ashburnb2b16fe2016-01-15 13:10:10 -07003647 inst, icd, phys_dev->phys_dev,
Jon Ashburn00eb6c02015-11-02 17:40:01 -07003648 phys_dev->this_icd->this_icd_lib->lib_name,
3649 &phys_dev->device_extension_cache);
3650 if (res != VK_SUCCESS) {
3651 return res;
3652 }
3653 }
Jon Ashburn471f44c2016-01-13 12:51:43 -07003654
3655 /* fetch a list of all layers activated, explicit and implicit */
3656 res = loader_enable_device_layers(inst, icd, &activated_layer_list, pCreateInfo, &inst->device_layer_list);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003657 if (res != VK_SUCCESS) {
3658 return res;
3659 }
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003660
Jon Ashburn471f44c2016-01-13 12:51:43 -07003661 /* make sure requested extensions to be enabled are supported */
3662 res = loader_validate_device_extensions(phys_dev, &activated_layer_list, pCreateInfo);
3663 if (res != VK_SUCCESS) {
3664 loader_destroy_generic_list(inst, (struct loader_generic_list *) &activated_layer_list);
3665 return res;
3666 }
3667
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003668 /*
3669 * NOTE: Need to filter the extensions to only those
3670 * supported by the ICD.
3671 * No ICD will advertise support for layers. An ICD
3672 * library could support a layer, but it would be
3673 * independent of the actual ICD, just in the same library.
3674 */
Jon Ashburnf19916e2016-01-11 13:12:43 -07003675 filtered_extension_names = loader_stack_alloc(pCreateInfo->enabledExtensionCount * sizeof(char *));
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003676 if (!filtered_extension_names) {
Jon Ashburn471f44c2016-01-13 12:51:43 -07003677 loader_destroy_generic_list(inst, (struct loader_generic_list *) &activated_layer_list);
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003678 return VK_ERROR_OUT_OF_HOST_MEMORY;
3679 }
3680
3681 /* Copy user's data */
3682 memcpy(&device_create_info, pCreateInfo, sizeof(VkDeviceCreateInfo));
3683
3684 /* ICD's do not use layers */
Jon Ashburnf19916e2016-01-11 13:12:43 -07003685 device_create_info.enabledLayerCount = 0;
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003686 device_create_info.ppEnabledLayerNames = NULL;
3687
Jon Ashburnf19916e2016-01-11 13:12:43 -07003688 device_create_info.enabledExtensionCount = 0;
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003689 device_create_info.ppEnabledExtensionNames = (const char * const *) filtered_extension_names;
3690
Jon Ashburnf19916e2016-01-11 13:12:43 -07003691 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003692 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i];
Jon Ashburn5c042ea2015-08-04 11:14:18 -06003693 VkExtensionProperties *prop = get_extension_property(extension_name,
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003694 &phys_dev->device_extension_cache);
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003695 if (prop) {
Jon Ashburnf19916e2016-01-11 13:12:43 -07003696 filtered_extension_names[device_create_info.enabledExtensionCount] = (char *) extension_name;
3697 device_create_info.enabledExtensionCount++;
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003698 }
3699 }
3700
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003701 dev = loader_add_logical_device(inst, &icd->logical_device_list);
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003702 if (dev == NULL) {
Jon Ashburn471f44c2016-01-13 12:51:43 -07003703 loader_destroy_generic_list(inst, (struct loader_generic_list *) &activated_layer_list);
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003704 return VK_ERROR_OUT_OF_HOST_MEMORY;
3705 }
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003706
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003707
Jon Ashburn471f44c2016-01-13 12:51:43 -07003708 /* move the locally filled layer list into the device, and pass ownership of the memory */
3709 dev->activated_layer_list.capacity = activated_layer_list.capacity;
3710 dev->activated_layer_list.count = activated_layer_list.count;
3711 dev->activated_layer_list.list = activated_layer_list.list;
3712 memset(&activated_layer_list, 0, sizeof(activated_layer_list));
3713
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003714 /* activate any layers on device chain which terminates with device*/
3715 res = loader_enable_device_layers(inst, icd, &dev->activated_layer_list, pCreateInfo, &inst->device_layer_list);
3716 if (res != VK_SUCCESS) {
3717 loader_destroy_logical_device(inst, dev);
3718 return res;
3719 }
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003720
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003721 res = loader_create_device_chain(physicalDevice, pCreateInfo, pAllocator, inst, icd, dev);
3722 if (res != VK_SUCCESS) {
3723 loader_destroy_logical_device(inst, dev);
3724 return res;
3725 }
3726
3727 *pDevice = dev->device;
Jon Ashburnfc1031e2015-11-17 15:31:02 -07003728
Jon Ashburn54978592015-12-11 10:45:00 -07003729 /* initialize any device extension dispatch entry's from the instance list*/
3730 loader_init_dispatch_dev_ext(inst, dev);
3731
Jon Ashburn232e3af2015-11-30 17:21:25 -07003732 /* initialize WSI device extensions as part of core dispatch since loader has
3733 * dedicated trampoline code for these*/
3734 loader_init_device_extension_dispatch_table(&dev->loader_dispatch,
3735 dev->loader_dispatch.core_dispatch.GetDeviceProcAddr,
3736 *pDevice);
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003737
Jon Ashburn95a77ba2015-05-15 15:09:35 -06003738 return res;
3739}
3740
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003741/**
3742 * Get an instance level or global level entry point address.
3743 * @param instance
3744 * @param pName
3745 * @return
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003746 * If instance == NULL returns a global level functions only
3747 * If instance is valid returns a trampoline entry point for all dispatchable Vulkan
3748 * functions both core and extensions.
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003749 */
Chia-I Wu9ab61502015-11-06 06:42:02 +08003750LOADER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char * pName)
Jon Ashburnb0fbe912015-05-06 10:15:07 -06003751{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003752
Jon Ashburn07daee72015-05-21 18:13:33 -06003753 void *addr;
Jon Ashburnb0fbe912015-05-06 10:15:07 -06003754
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003755 addr = globalGetProcAddr(pName);
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003756 if (instance == VK_NULL_HANDLE) {
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003757 // get entrypoint addresses that are global (no dispatchable object)
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003758
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003759 return addr;
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003760 } else {
3761 // if a global entrypoint return NULL
3762 if (addr)
3763 return NULL;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003764 }
3765
Jon Ashburne0e64572015-09-30 12:56:42 -06003766 struct loader_instance *ptr_instance = loader_get_instance(instance);
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003767 if (ptr_instance == NULL)
Jon Ashburn07daee72015-05-21 18:13:33 -06003768 return NULL;
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003769 // Return trampoline code for non-global entrypoints including any extensions.
3770 // Device extensions are returned if a layer or ICD supports the extension.
3771 // Instance extensions are returned if the extension is enabled and the loader
3772 // or someone else supports the extension
3773 return trampolineGetProcAddr(ptr_instance, pName);
Jon Ashburn07daee72015-05-21 18:13:33 -06003774
Jon Ashburnb0fbe912015-05-06 10:15:07 -06003775}
3776
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003777/**
3778 * Get a device level or global level entry point address.
3779 * @param device
3780 * @param pName
3781 * @return
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003782 * If device is valid, returns a device relative entry point for device level
3783 * entry points both core and extensions.
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003784 * Device relative means call down the device chain.
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003785 */
Chia-I Wu9ab61502015-11-06 06:42:02 +08003786LOADER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char * pName)
Courtney Goeltzenleuchter9ec39ac2015-06-22 17:45:21 -06003787{
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003788 void *addr;
Courtney Goeltzenleuchter9ec39ac2015-06-22 17:45:21 -06003789
Jon Ashburn3d526cb2015-04-13 18:10:06 -06003790 /* for entrypoints that loader must handle (ie non-dispatchable or create object)
3791 make sure the loader entrypoint is returned */
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003792 addr = loader_non_passthrough_gdpa(pName);
Ian Elliotte19c9152015-04-15 12:53:19 -06003793 if (addr) {
Jon Ashburn3d526cb2015-04-13 18:10:06 -06003794 return addr;
Ian Elliotte19c9152015-04-15 12:53:19 -06003795 }
Jon Ashburn3d526cb2015-04-13 18:10:06 -06003796
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003797 /* Although CreateDevice is on device chain it's dispatchable object isn't
3798 * a VkDevice or child of VkDevice so return NULL.
3799 */
3800 if (!strcmp(pName, "CreateDevice"))
3801 return NULL;
3802
Jon Ashburn3d526cb2015-04-13 18:10:06 -06003803 /* return the dispatch table entrypoint for the fastest case */
Jon Ashburn8d1b0b52015-05-18 13:20:15 -06003804 const VkLayerDispatchTable *disp_table = * (VkLayerDispatchTable **) device;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06003805 if (disp_table == NULL)
3806 return NULL;
3807
Jon Ashburn27cd5842015-05-12 17:26:48 -06003808 addr = loader_lookup_device_dispatch_table(disp_table, pName);
Chia-I Wuf46b81a2015-01-04 11:12:47 +08003809 if (addr)
3810 return addr;
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003811
3812 if (disp_table->GetDeviceProcAddr == NULL)
3813 return NULL;
3814 return disp_table->GetDeviceProcAddr(device, pName);
Jon Ashburnd38bfb12014-10-14 19:15:22 -06003815}
3816
Chia-I Wu9ab61502015-11-06 06:42:02 +08003817LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003818 const char* pLayerName,
Chia-I Wud50a7d72015-10-26 20:48:51 +08003819 uint32_t* pPropertyCount,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003820 VkExtensionProperties* pProperties)
3821{
Jon Ashburn432d2762015-09-18 12:53:16 -06003822 struct loader_extension_list *global_ext_list=NULL;
Jon Ashburnb82c1852015-08-11 14:49:54 -06003823 struct loader_layer_list instance_layers;
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003824 struct loader_extension_list icd_extensions;
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003825 struct loader_icd_libs icd_libs;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003826 uint32_t copy_size;
3827
Jon Ashburn87d6aa92015-08-28 15:19:27 -06003828 tls_instance = NULL;
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003829 memset(&icd_extensions, 0, sizeof(icd_extensions));
Mike Stroyan09c06c72015-10-01 15:23:48 -06003830 memset(&instance_layers, 0, sizeof(instance_layers));
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003831 loader_platform_thread_once(&once_init, loader_initialize);
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003832
Jon Ashburnb82c1852015-08-11 14:49:54 -06003833 /* get layer libraries if needed */
3834 if (pLayerName && strlen(pLayerName) != 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06003835 loader_layer_scan(NULL, &instance_layers, NULL);
Jon Ashburnb82c1852015-08-11 14:49:54 -06003836 for (uint32_t i = 0; i < instance_layers.count; i++) {
3837 struct loader_layer_properties *props = &instance_layers.list[i];
3838 if (strcmp(props->info.layerName, pLayerName) == 0) {
3839 global_ext_list = &props->instance_extension_list;
3840 }
3841 }
3842 }
3843 else {
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003844 /* Scan/discover all ICD libraries */
3845 memset(&icd_libs, 0 , sizeof(struct loader_icd_libs));
Jon Ashburne39a4f82015-08-28 13:38:21 -06003846 loader_icd_scan(NULL, &icd_libs);
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003847 /* get extensions from all ICD's, merge so no duplicates */
Jon Ashburne39a4f82015-08-28 13:38:21 -06003848 loader_get_icd_loader_instance_extensions(NULL, &icd_libs, &icd_extensions);
3849 loader_scanned_icd_clear(NULL, &icd_libs);
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003850 global_ext_list = &icd_extensions;
Jon Ashburnb82c1852015-08-11 14:49:54 -06003851 }
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003852
Jon Ashburnb82c1852015-08-11 14:49:54 -06003853 if (global_ext_list == NULL) {
Mike Stroyan09c06c72015-10-01 15:23:48 -06003854 loader_destroy_layer_list(NULL, &instance_layers);
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06003855 return VK_ERROR_LAYER_NOT_PRESENT;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003856 }
3857
3858 if (pProperties == NULL) {
Chia-I Wud50a7d72015-10-26 20:48:51 +08003859 *pPropertyCount = global_ext_list->count;
Mike Stroyan09c06c72015-10-01 15:23:48 -06003860 loader_destroy_layer_list(NULL, &instance_layers);
Jon Ashburn6e6a2162015-12-10 08:51:10 -07003861 loader_destroy_generic_list(NULL, (struct loader_generic_list *)
3862 &icd_extensions);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003863 return VK_SUCCESS;
3864 }
3865
Chia-I Wud50a7d72015-10-26 20:48:51 +08003866 copy_size = *pPropertyCount < global_ext_list->count ? *pPropertyCount : global_ext_list->count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003867 for (uint32_t i = 0; i < copy_size; i++) {
3868 memcpy(&pProperties[i],
Jon Ashburnb82c1852015-08-11 14:49:54 -06003869 &global_ext_list->list[i],
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003870 sizeof(VkExtensionProperties));
3871 }
Chia-I Wud50a7d72015-10-26 20:48:51 +08003872 *pPropertyCount = copy_size;
Jon Ashburn6e6a2162015-12-10 08:51:10 -07003873 loader_destroy_generic_list(NULL, (struct loader_generic_list *)
3874 &icd_extensions);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003875
Jon Ashburnb82c1852015-08-11 14:49:54 -06003876 if (copy_size < global_ext_list->count) {
Mike Stroyan09c06c72015-10-01 15:23:48 -06003877 loader_destroy_layer_list(NULL, &instance_layers);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003878 return VK_INCOMPLETE;
3879 }
3880
Mike Stroyan09c06c72015-10-01 15:23:48 -06003881 loader_destroy_layer_list(NULL, &instance_layers);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003882 return VK_SUCCESS;
3883}
3884
Chia-I Wu9ab61502015-11-06 06:42:02 +08003885LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(
Chia-I Wud50a7d72015-10-26 20:48:51 +08003886 uint32_t* pPropertyCount,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003887 VkLayerProperties* pProperties)
Tony Barbour59a47322015-06-24 16:06:58 -06003888{
Jon Ashburn6301a0f2015-05-29 13:15:39 -06003889
Jon Ashburnb82c1852015-08-11 14:49:54 -06003890 struct loader_layer_list instance_layer_list;
Jon Ashburn87d6aa92015-08-28 15:19:27 -06003891 tls_instance = NULL;
Jon Ashburnb82c1852015-08-11 14:49:54 -06003892
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003893 loader_platform_thread_once(&once_init, loader_initialize);
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07003894
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003895 uint32_t copy_size;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06003896
Jon Ashburnb82c1852015-08-11 14:49:54 -06003897 /* get layer libraries */
3898 memset(&instance_layer_list, 0, sizeof(instance_layer_list));
Jon Ashburne39a4f82015-08-28 13:38:21 -06003899 loader_layer_scan(NULL, &instance_layer_list, NULL);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003900
3901 if (pProperties == NULL) {
Chia-I Wud50a7d72015-10-26 20:48:51 +08003902 *pPropertyCount = instance_layer_list.count;
Jon Ashburne39a4f82015-08-28 13:38:21 -06003903 loader_destroy_layer_list(NULL, &instance_layer_list);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003904 return VK_SUCCESS;
3905 }
3906
Chia-I Wud50a7d72015-10-26 20:48:51 +08003907 copy_size = (*pPropertyCount < instance_layer_list.count) ? *pPropertyCount : instance_layer_list.count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003908 for (uint32_t i = 0; i < copy_size; i++) {
Jon Ashburnb82c1852015-08-11 14:49:54 -06003909 memcpy(&pProperties[i], &instance_layer_list.list[i].info, sizeof(VkLayerProperties));
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003910 }
Chia-I Wud50a7d72015-10-26 20:48:51 +08003911 *pPropertyCount = copy_size;
Jon Ashburne39a4f82015-08-28 13:38:21 -06003912 loader_destroy_layer_list(NULL, &instance_layer_list);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003913
Jon Ashburnb82c1852015-08-11 14:49:54 -06003914 if (copy_size < instance_layer_list.count) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003915 return VK_INCOMPLETE;
3916 }
Tony Barbour59a47322015-06-24 16:06:58 -06003917
3918 return VK_SUCCESS;
3919}
3920
Chia-I Wu9ab61502015-11-06 06:42:02 +08003921VKAPI_ATTR VkResult VKAPI_CALL loader_EnumerateDeviceExtensionProperties(
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003922 VkPhysicalDevice physicalDevice,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003923 const char* pLayerName,
Chia-I Wud50a7d72015-10-26 20:48:51 +08003924 uint32_t* pPropertyCount,
Tony Barbour59a47322015-06-24 16:06:58 -06003925 VkExtensionProperties* pProperties)
3926{
Jon Ashburna760a512015-12-14 08:52:14 -07003927 struct loader_physical_device *phys_dev;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003928 uint32_t copy_size;
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07003929
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003930 uint32_t count;
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07003931 struct loader_device_extension_list *dev_ext_list=NULL;
Jon Ashburn471f44c2016-01-13 12:51:43 -07003932 struct loader_layer_list implicit_layer_list;
3933
Jon Ashburna760a512015-12-14 08:52:14 -07003934 //TODO fix this aliases physical devices
3935 phys_dev = loader_get_physical_device(physicalDevice);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003936
Jon Ashburnb82c1852015-08-11 14:49:54 -06003937 /* get layer libraries if needed */
3938 if (pLayerName && strlen(pLayerName) != 0) {
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003939 for (uint32_t i = 0; i < phys_dev->this_instance->device_layer_list.count; i++) {
3940 struct loader_layer_properties *props = &phys_dev->this_instance->device_layer_list.list[i];
Jon Ashburnb82c1852015-08-11 14:49:54 -06003941 if (strcmp(props->info.layerName, pLayerName) == 0) {
3942 dev_ext_list = &props->device_extension_list;
3943 }
3944 }
Jon Ashburn471f44c2016-01-13 12:51:43 -07003945 count = (dev_ext_list == NULL) ? 0: dev_ext_list->count;
3946 if (pProperties == NULL) {
3947 *pPropertyCount = count;
3948 return VK_SUCCESS;
3949 }
3950
3951 copy_size = *pPropertyCount < count ? *pPropertyCount : count;
3952 for (uint32_t i = 0; i < copy_size; i++) {
3953 memcpy(&pProperties[i], &dev_ext_list->list[i].props,
3954 sizeof(VkExtensionProperties));
3955 }
3956 *pPropertyCount = copy_size;
3957
3958 if (copy_size < count) {
3959 return VK_INCOMPLETE;
3960 }
3961
3962 return VK_SUCCESS;
Jon Ashburnb82c1852015-08-11 14:49:54 -06003963 }
3964 else {
Jon Ashburn471f44c2016-01-13 12:51:43 -07003965 /* this case is during the call down the instance chain with pLayerName == NULL*/
Jon Ashburn00eb6c02015-11-02 17:40:01 -07003966 struct loader_icd *icd = phys_dev->this_icd;
Jon Ashburn471f44c2016-01-13 12:51:43 -07003967 uint32_t icd_ext_count = *pPropertyCount;
Jon Ashburn00eb6c02015-11-02 17:40:01 -07003968 VkResult res;
Jon Ashburn471f44c2016-01-13 12:51:43 -07003969 /* get device extensions */
3970 res = icd->EnumerateDeviceExtensionProperties(phys_dev->phys_dev, NULL, &icd_ext_count, pProperties);
3971 if (res != VK_SUCCESS)
3972 return res;
3973
3974 loader_init_layer_list(phys_dev->this_instance, &implicit_layer_list);
3975
3976 loader_add_layer_implicit(phys_dev->this_instance,
3977 VK_LAYER_TYPE_INSTANCE_IMPLICIT,
3978 &implicit_layer_list,
3979 &phys_dev->this_instance->instance_layer_list);
3980 /* we need to determine which implicit layers are active,
3981 * and then add their extensions. This can't be cached as
3982 * it depends on results of environment variables (which can change).
3983 */
3984 if (pProperties != NULL) {
Jon Ashburn00eb6c02015-11-02 17:40:01 -07003985 /* initialize dev_extension list within the physicalDevice object */
Courtney Goeltzenleuchterf538ef72015-12-02 14:00:19 -07003986 res = loader_init_device_extensions(phys_dev->this_instance,
Jon Ashburn471f44c2016-01-13 12:51:43 -07003987 phys_dev, icd_ext_count, pProperties,
3988 &phys_dev->device_extension_cache);
3989 if (res != VK_SUCCESS)
3990 return res;
3991
3992 /* we need to determine which implicit layers are active,
3993 * and then add their extensions. This can't be cached as
3994 * it depends on results of environment variables (which can change).
3995 */
3996 struct loader_extension_list all_exts = {0};
3997 loader_add_to_ext_list(phys_dev->this_instance, &all_exts,
3998 phys_dev->device_extension_cache.count,
3999 phys_dev->device_extension_cache.list);
4000
4001 loader_init_layer_list(phys_dev->this_instance, &implicit_layer_list);
4002
4003 loader_add_layer_implicit(phys_dev->this_instance,
4004 VK_LAYER_TYPE_INSTANCE_IMPLICIT,
4005 &implicit_layer_list,
4006 &phys_dev->this_instance->instance_layer_list);
4007
4008 for (uint32_t i = 0; i < implicit_layer_list.count; i++) {
4009 for (uint32_t j = 0; j < implicit_layer_list.list[i].device_extension_list.count; j++) {
4010 loader_add_to_ext_list(phys_dev->this_instance, &all_exts, 1,
4011 &implicit_layer_list.list[i].device_extension_list.list[j].props);
4012 }
4013 }
4014 uint32_t capacity = *pPropertyCount;
4015 VkExtensionProperties *props = pProperties;
4016
4017 for (uint32_t i = 0; i < all_exts.count && i < capacity; i++) {
4018 props[i] = all_exts.list[i];
4019 }
4020 /* wasn't enough space for the extensions, we did partial copy now return VK_INCOMPLETE */
4021 if (capacity < all_exts.count) {
4022 res = VK_INCOMPLETE;
4023 }
4024 else {
4025 *pPropertyCount = all_exts.count;
4026 }
4027 loader_destroy_generic_list(phys_dev->this_instance, (struct loader_generic_list *) &all_exts);
Jon Ashburn00eb6c02015-11-02 17:40:01 -07004028 }
Jon Ashburn471f44c2016-01-13 12:51:43 -07004029 else {
4030 /* just return the count; need to add in the count of implicit layer extensions
4031 * don't worry about duplicates being added in the count */
4032 *pPropertyCount = icd_ext_count;
4033
4034 for (uint32_t i = 0; i < implicit_layer_list.count; i++) {
4035 *pPropertyCount += implicit_layer_list.list[i].device_extension_list.count;
4036 }
4037 res = VK_SUCCESS;
4038
4039 }
4040
4041
4042 loader_destroy_generic_list(phys_dev->this_instance, (struct loader_generic_list *) &implicit_layer_list);
Jon Ashburn00eb6c02015-11-02 17:40:01 -07004043 return res;
Jon Ashburnb82c1852015-08-11 14:49:54 -06004044 }
4045
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06004046}
4047
Chia-I Wu9ab61502015-11-06 06:42:02 +08004048VKAPI_ATTR VkResult VKAPI_CALL loader_EnumerateDeviceLayerProperties(
Jon Ashburn24cd4be2015-11-01 14:04:06 -07004049 VkPhysicalDevice physicalDevice,
Chia-I Wud50a7d72015-10-26 20:48:51 +08004050 uint32_t* pPropertyCount,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06004051 VkLayerProperties* pProperties)
4052{
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06004053 uint32_t copy_size;
Jon Ashburna760a512015-12-14 08:52:14 -07004054 struct loader_physical_device *phys_dev;
4055 //TODO fix this, aliases physical devices
4056 phys_dev = loader_get_physical_device(physicalDevice);
Jon Ashburn24cd4be2015-11-01 14:04:06 -07004057 uint32_t count = phys_dev->this_instance->device_layer_list.count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06004058
4059 if (pProperties == NULL) {
Chia-I Wud50a7d72015-10-26 20:48:51 +08004060 *pPropertyCount = count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06004061 return VK_SUCCESS;
4062 }
4063
Chia-I Wud50a7d72015-10-26 20:48:51 +08004064 copy_size = (*pPropertyCount < count) ? *pPropertyCount : count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06004065 for (uint32_t i = 0; i < copy_size; i++) {
Jon Ashburn24cd4be2015-11-01 14:04:06 -07004066 memcpy(&pProperties[i], &(phys_dev->this_instance->device_layer_list.list[i].info), sizeof(VkLayerProperties));
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06004067 }
Chia-I Wud50a7d72015-10-26 20:48:51 +08004068 *pPropertyCount = copy_size;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06004069
4070 if (copy_size < count) {
4071 return VK_INCOMPLETE;
4072 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06004073
4074 return VK_SUCCESS;
Jon Ashburn95a77ba2015-05-15 15:09:35 -06004075}