blob: 81233e892758b3079d881ea8d280a5bd9ea8cd6e [file] [log] [blame]
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001/*
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08002 *
Jon Ashburn23d36b12016-02-02 17:47:28 -07003 * Copyright (c) 2014-2016 The Khronos Group Inc.
4 * Copyright (c) 2014-2016 Valve Corporation
5 * Copyright (c) 2014-2016 LunarG, Inc.
Courtney Goeltzenleuchterf821dad2015-12-02 14:53:22 -07006 * Copyright (C) 2015 Google Inc.
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08007 *
Jon Ashburn23d36b12016-02-02 17:47:28 -07008 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and/or associated documentation files (the "Materials"), to
10 * deal in the Materials without restriction, including without limitation the
11 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
12 * sell copies of the Materials, and to permit persons to whom the Materials are
13 * furnished to do so, subject to the following conditions:
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080014 *
Jon Ashburn23d36b12016-02-02 17:47:28 -070015 * The above copyright notice(s) and this permission notice shall be included in
16 * all copies or substantial portions of the Materials.
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080017 *
Jon Ashburn23d36b12016-02-02 17:47:28 -070018 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080019 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Jon Ashburn23d36b12016-02-02 17:47:28 -070020 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
Chia-I Wu701f3f62014-09-02 08:32:09 +080021 *
Jon Ashburn23d36b12016-02-02 17:47:28 -070022 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
23 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE
25 * USE OR OTHER DEALINGS IN THE MATERIALS.
26 *
Courtney Goeltzenleuchter05559522015-10-30 11:14:30 -060027 * Author: Jon Ashburn <jon@lunarg.com>
Jon Ashburn23d36b12016-02-02 17:47:28 -070028 * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
Courtney Goeltzenleuchter05559522015-10-30 11:14:30 -060029 *
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080030 */
Mark Lobodzinskifaa90812015-11-25 13:26:15 -070031
Jon Ashburn6b4d70c2014-10-22 18:13:16 -060032#define _GNU_SOURCE
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080033#include <stdio.h>
34#include <stdlib.h>
35#include <stdarg.h>
36#include <stdbool.h>
37#include <string.h>
38
Chia-I Wu13a61a52014-08-04 11:18:20 +080039#include <sys/types.h>
Johannes van Waveren9bd805012015-10-28 11:45:00 -050040#if defined(_WIN32)
Ian Elliott2d4ab1e2015-01-13 17:52:38 -070041#include "dirent_on_windows.h"
Johannes van Waveren9bd805012015-10-28 11:45:00 -050042#else // _WIN32
Chia-I Wu13a61a52014-08-04 11:18:20 +080043#include <dirent.h>
Johannes van Waveren9bd805012015-10-28 11:45:00 -050044#endif // _WIN32
Tobin Ehlisb835d1b2015-07-03 10:34:49 -060045#include "vk_loader_platform.h"
Chia-I Wu19300602014-08-04 08:03:57 +080046#include "loader.h"
Jon Ashburn27cd5842015-05-12 17:26:48 -060047#include "gpa_helper.h"
48#include "table_ops.h"
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -060049#include "debug_report.h"
Ian Elliott954fa342015-10-30 15:28:23 -060050#include "wsi.h"
David Pinedo9316d3b2015-11-06 12:54:48 -070051#include "vulkan/vk_icd.h"
Jon Ashburn2077e382015-06-29 11:25:34 -060052#include "cJSON.h"
Jon Ashburnfc1031e2015-11-17 15:31:02 -070053#include "murmurhash.h"
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080054
Jon Ashburn23d36b12016-02-02 17:47:28 -070055static loader_platform_dl_handle
56loader_add_layer_lib(const struct loader_instance *inst, const char *chain_type,
57 struct loader_layer_properties *layer_prop);
Courtney Goeltzenleuchtered488302015-06-01 14:09:34 -060058
Jon Ashburn23d36b12016-02-02 17:47:28 -070059static void loader_remove_layer_lib(struct loader_instance *inst,
60 struct loader_layer_properties *layer_prop);
Courtney Goeltzenleuchtered488302015-06-01 14:09:34 -060061
Jon Ashburn27cd5842015-05-12 17:26:48 -060062struct loader_struct loader = {0};
Jon Ashburn87d6aa92015-08-28 15:19:27 -060063// TLS for instance for alloc/free callbacks
64THREAD_LOCAL_DECL struct loader_instance *tls_instance;
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080065
Courtney Goeltzenleuchter0ef13a02015-12-16 16:19:46 -070066static size_t loader_platform_combine_path(char *dest, size_t len, ...);
Daniel Dadap00b4aba2015-09-30 11:50:51 -050067
Jon Ashburn24cd4be2015-11-01 14:04:06 -070068struct loader_phys_dev_per_icd {
69 uint32_t count;
70 VkPhysicalDevice *phys_devs;
Jon Ashburn014438f2016-03-01 19:51:07 -070071 struct loader_icd *this_icd;
Jon Ashburn24cd4be2015-11-01 14:04:06 -070072};
73
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -060074enum loader_debug {
Jon Ashburn23d36b12016-02-02 17:47:28 -070075 LOADER_INFO_BIT = 0x01,
76 LOADER_WARN_BIT = 0x02,
77 LOADER_PERF_BIT = 0x04,
78 LOADER_ERROR_BIT = 0x08,
79 LOADER_DEBUG_BIT = 0x10,
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -060080};
81
82uint32_t g_loader_debug = 0;
83uint32_t g_loader_log_msgs = 0;
84
Jon Ashburn23d36b12016-02-02 17:47:28 -070085// thread safety lock for accessing global data structures such as "loader"
Jon Ashburn6301a0f2015-05-29 13:15:39 -060086// all entrypoints on the instance chain need to be locked except GPA
Jon Ashburn2077e382015-06-29 11:25:34 -060087// additionally CreateDevice and DestroyDevice needs to be locked
Jon Ashburn6301a0f2015-05-29 13:15:39 -060088loader_platform_thread_mutex loader_lock;
Jon Ashburn6461ef22015-09-22 13:11:00 -060089loader_platform_thread_mutex loader_json_lock;
Jon Ashburn6301a0f2015-05-29 13:15:39 -060090
Jon Ashburn86a527a2016-02-10 20:59:26 -070091const char *std_validation_str = "VK_LAYER_LUNARG_standard_validation";
92
Ian Elliottd3ef02f2015-07-06 14:36:13 -060093// This table contains the loader's instance dispatch table, which contains
94// default functions if no instance layers are activated. This contains
95// pointers to "terminator functions".
Jon Ashburn6301a0f2015-05-29 13:15:39 -060096const VkLayerInstanceDispatchTable instance_disp = {
Jon Ashburn69e9ea22015-09-28 16:15:00 -060097 .GetInstanceProcAddr = vkGetInstanceProcAddr,
Jon Ashburn1530c342016-02-26 13:14:27 -070098 .DestroyInstance = terminator_DestroyInstance,
99 .EnumeratePhysicalDevices = terminator_EnumeratePhysicalDevices,
100 .GetPhysicalDeviceFeatures = terminator_GetPhysicalDeviceFeatures,
Jon Ashburn23d36b12016-02-02 17:47:28 -0700101 .GetPhysicalDeviceFormatProperties =
Jon Ashburn1530c342016-02-26 13:14:27 -0700102 terminator_GetPhysicalDeviceFormatProperties,
Jon Ashburn23d36b12016-02-02 17:47:28 -0700103 .GetPhysicalDeviceImageFormatProperties =
Jon Ashburn1530c342016-02-26 13:14:27 -0700104 terminator_GetPhysicalDeviceImageFormatProperties,
105 .GetPhysicalDeviceProperties = terminator_GetPhysicalDeviceProperties,
Jon Ashburn23d36b12016-02-02 17:47:28 -0700106 .GetPhysicalDeviceQueueFamilyProperties =
Jon Ashburn1530c342016-02-26 13:14:27 -0700107 terminator_GetPhysicalDeviceQueueFamilyProperties,
Jon Ashburn23d36b12016-02-02 17:47:28 -0700108 .GetPhysicalDeviceMemoryProperties =
Jon Ashburn1530c342016-02-26 13:14:27 -0700109 terminator_GetPhysicalDeviceMemoryProperties,
Jon Ashburn23d36b12016-02-02 17:47:28 -0700110 .EnumerateDeviceExtensionProperties =
Jon Ashburn1530c342016-02-26 13:14:27 -0700111 terminator_EnumerateDeviceExtensionProperties,
112 .EnumerateDeviceLayerProperties = terminator_EnumerateDeviceLayerProperties,
Jon Ashburn23d36b12016-02-02 17:47:28 -0700113 .GetPhysicalDeviceSparseImageFormatProperties =
Jon Ashburn1530c342016-02-26 13:14:27 -0700114 terminator_GetPhysicalDeviceSparseImageFormatProperties,
115 .DestroySurfaceKHR = terminator_DestroySurfaceKHR,
Jon Ashburn23d36b12016-02-02 17:47:28 -0700116 .GetPhysicalDeviceSurfaceSupportKHR =
Jon Ashburn1530c342016-02-26 13:14:27 -0700117 terminator_GetPhysicalDeviceSurfaceSupportKHR,
Jon Ashburn23d36b12016-02-02 17:47:28 -0700118 .GetPhysicalDeviceSurfaceCapabilitiesKHR =
Jon Ashburn1530c342016-02-26 13:14:27 -0700119 terminator_GetPhysicalDeviceSurfaceCapabilitiesKHR,
Jon Ashburn23d36b12016-02-02 17:47:28 -0700120 .GetPhysicalDeviceSurfaceFormatsKHR =
Jon Ashburn1530c342016-02-26 13:14:27 -0700121 terminator_GetPhysicalDeviceSurfaceFormatsKHR,
Jon Ashburn23d36b12016-02-02 17:47:28 -0700122 .GetPhysicalDeviceSurfacePresentModesKHR =
Jon Ashburn1530c342016-02-26 13:14:27 -0700123 terminator_GetPhysicalDeviceSurfacePresentModesKHR,
124 .CreateDebugReportCallbackEXT = terminator_CreateDebugReportCallback,
125 .DestroyDebugReportCallbackEXT = terminator_DestroyDebugReportCallback,
126 .DebugReportMessageEXT = terminator_DebugReportMessage,
Ian Elliottdb4300a2015-11-23 10:17:23 -0700127#ifdef VK_USE_PLATFORM_MIR_KHR
Jon Ashburn1530c342016-02-26 13:14:27 -0700128 .CreateMirSurfaceKHR = terminator_CreateMirSurfaceKHR,
Jon Ashburn23d36b12016-02-02 17:47:28 -0700129 .GetPhysicalDeviceMirPresentationSupportKHR =
Jon Ashburn1530c342016-02-26 13:14:27 -0700130 terminator_GetPhysicalDeviceMirPresentationSupportKHR,
Ian Elliottdb4300a2015-11-23 10:17:23 -0700131#endif
132#ifdef VK_USE_PLATFORM_WAYLAND_KHR
Jon Ashburn1530c342016-02-26 13:14:27 -0700133 .CreateWaylandSurfaceKHR = terminator_CreateWaylandSurfaceKHR,
Jon Ashburn23d36b12016-02-02 17:47:28 -0700134 .GetPhysicalDeviceWaylandPresentationSupportKHR =
Jon Ashburn1530c342016-02-26 13:14:27 -0700135 terminator_GetPhysicalDeviceWaylandPresentationSupportKHR,
Ian Elliottdb4300a2015-11-23 10:17:23 -0700136#endif
137#ifdef VK_USE_PLATFORM_WIN32_KHR
Jon Ashburn1530c342016-02-26 13:14:27 -0700138 .CreateWin32SurfaceKHR = terminator_CreateWin32SurfaceKHR,
Jon Ashburn23d36b12016-02-02 17:47:28 -0700139 .GetPhysicalDeviceWin32PresentationSupportKHR =
Jon Ashburn1530c342016-02-26 13:14:27 -0700140 terminator_GetPhysicalDeviceWin32PresentationSupportKHR,
Ian Elliottdb4300a2015-11-23 10:17:23 -0700141#endif
142#ifdef VK_USE_PLATFORM_XCB_KHR
Jon Ashburn1530c342016-02-26 13:14:27 -0700143 .CreateXcbSurfaceKHR = terminator_CreateXcbSurfaceKHR,
Jon Ashburn23d36b12016-02-02 17:47:28 -0700144 .GetPhysicalDeviceXcbPresentationSupportKHR =
Jon Ashburn1530c342016-02-26 13:14:27 -0700145 terminator_GetPhysicalDeviceXcbPresentationSupportKHR,
Ian Elliottdb4300a2015-11-23 10:17:23 -0700146#endif
147#ifdef VK_USE_PLATFORM_XLIB_KHR
Jon Ashburn1530c342016-02-26 13:14:27 -0700148 .CreateXlibSurfaceKHR = terminator_CreateXlibSurfaceKHR,
Jon Ashburn23d36b12016-02-02 17:47:28 -0700149 .GetPhysicalDeviceXlibPresentationSupportKHR =
Jon Ashburn1530c342016-02-26 13:14:27 -0700150 terminator_GetPhysicalDeviceXlibPresentationSupportKHR,
Ian Elliottdb4300a2015-11-23 10:17:23 -0700151#endif
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -0700152#ifdef VK_USE_PLATFORM_ANDROID_KHR
Jon Ashburn1530c342016-02-26 13:14:27 -0700153 .CreateAndroidSurfaceKHR = terminator_CreateAndroidSurfaceKHR,
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -0700154#endif
Jon Ashburn27cd5842015-05-12 17:26:48 -0600155};
156
Jon Ashburn8810c5f2015-08-18 18:04:47 -0600157LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_init);
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700158
Jon Ashburn23d36b12016-02-02 17:47:28 -0700159void *loader_heap_alloc(const struct loader_instance *instance, size_t size,
160 VkSystemAllocationScope alloc_scope) {
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800161 if (instance && instance->alloc_callbacks.pfnAllocation) {
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600162 /* TODO: What should default alignment be? 1, 4, 8, other? */
Jon Ashburn23d36b12016-02-02 17:47:28 -0700163 return instance->alloc_callbacks.pfnAllocation(
164 instance->alloc_callbacks.pUserData, size, sizeof(int),
165 alloc_scope);
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600166 }
167 return malloc(size);
168}
169
Jon Ashburn23d36b12016-02-02 17:47:28 -0700170void loader_heap_free(const struct loader_instance *instance, void *pMemory) {
171 if (pMemory == NULL)
172 return;
Jon Ashburneacfa3a2015-08-14 12:51:47 -0600173 if (instance && instance->alloc_callbacks.pfnFree) {
Jon Ashburn23d36b12016-02-02 17:47:28 -0700174 instance->alloc_callbacks.pfnFree(instance->alloc_callbacks.pUserData,
175 pMemory);
Jon Ashburnd2c171b2015-08-13 08:28:48 -0600176 return;
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600177 }
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800178 free(pMemory);
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600179}
180
Jon Ashburn23d36b12016-02-02 17:47:28 -0700181void *loader_heap_realloc(const struct loader_instance *instance, void *pMemory,
182 size_t orig_size, size_t size,
183 VkSystemAllocationScope alloc_scope) {
184 if (pMemory == NULL || orig_size == 0)
Chia-I Wuf7458c52015-10-26 21:10:41 +0800185 return loader_heap_alloc(instance, size, alloc_scope);
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600186 if (size == 0) {
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800187 loader_heap_free(instance, pMemory);
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600188 return NULL;
189 }
Jon Ashburn23d36b12016-02-02 17:47:28 -0700190 // TODO use the callback realloc function
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800191 if (instance && instance->alloc_callbacks.pfnAllocation) {
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600192 if (size <= orig_size) {
Jon Ashburn23d36b12016-02-02 17:47:28 -0700193 memset(((uint8_t *)pMemory) + size, 0, orig_size - size);
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800194 return pMemory;
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600195 }
Jon Ashburn6a118ae2016-01-07 15:21:14 -0700196 /* TODO: What should default alignment be? 1, 4, 8, other? */
Jon Ashburn23d36b12016-02-02 17:47:28 -0700197 void *new_ptr = instance->alloc_callbacks.pfnAllocation(
198 instance->alloc_callbacks.pUserData, size, sizeof(int),
199 alloc_scope);
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600200 if (!new_ptr)
201 return NULL;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800202 memcpy(new_ptr, pMemory, orig_size);
Jon Ashburn23d36b12016-02-02 17:47:28 -0700203 instance->alloc_callbacks.pfnFree(instance->alloc_callbacks.pUserData,
204 pMemory);
Jon Ashburnccd00a62016-01-27 10:56:10 -0700205 return new_ptr;
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600206 }
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800207 return realloc(pMemory, size);
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600208}
209
Jon Ashburn23d36b12016-02-02 17:47:28 -0700210void *loader_tls_heap_alloc(size_t size) {
211 return loader_heap_alloc(tls_instance, size,
212 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
Jon Ashburn87d6aa92015-08-28 15:19:27 -0600213}
214
Jon Ashburn23d36b12016-02-02 17:47:28 -0700215void loader_tls_heap_free(void *pMemory) {
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800216 loader_heap_free(tls_instance, pMemory);
Jon Ashburn87d6aa92015-08-28 15:19:27 -0600217}
218
Jon Ashburn2e37d752016-02-12 08:20:06 -0700219void loader_log(const struct loader_instance *inst, VkFlags msg_type,
Jon Ashburn1530c342016-02-26 13:14:27 -0700220 int32_t msg_code, const char *format, ...) {
Jon Ashburn86723b02015-07-31 15:47:59 -0600221 char msg[512];
Jon Ashburnffad94d2015-06-30 14:46:22 -0700222 va_list ap;
223 int ret;
224
Jon Ashburnffad94d2015-06-30 14:46:22 -0700225 va_start(ap, format);
226 ret = vsnprintf(msg, sizeof(msg), format, ap);
Jon Ashburn23d36b12016-02-02 17:47:28 -0700227 if ((ret >= (int)sizeof(msg)) || ret < 0) {
228 msg[sizeof(msg) - 1] = '\0';
Jon Ashburnffad94d2015-06-30 14:46:22 -0700229 }
230 va_end(ap);
231
Courtney Goeltzenleuchter73477392015-12-03 13:48:01 -0700232 if (inst) {
Jon Ashburn23d36b12016-02-02 17:47:28 -0700233 util_DebugReportMessage(inst, msg_type,
234 VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
235 (uint64_t)inst, 0, msg_code, "loader", msg);
Courtney Goeltzenleuchter73477392015-12-03 13:48:01 -0700236 }
237
238 if (!(msg_type & g_loader_log_msgs)) {
239 return;
240 }
241
Ian Elliott4470a302015-02-17 10:33:47 -0700242#if defined(WIN32)
Jon Ashburnffad94d2015-06-30 14:46:22 -0700243 OutputDebugString(msg);
mschottb9cdb782015-07-22 14:11:29 +0200244 OutputDebugString("\n");
Jon Ashburnffad94d2015-06-30 14:46:22 -0700245#endif
246 fputs(msg, stderr);
247 fputc('\n', stderr);
248}
249
250#if defined(WIN32)
Tony Barbourea968902015-07-29 14:26:21 -0600251static char *loader_get_next_path(char *path);
Jon Ashburnffad94d2015-06-30 14:46:22 -0700252/**
253* Find the list of registry files (names within a key) in key "location".
254*
Jon Ashburn23d36b12016-02-02 17:47:28 -0700255* This function looks in the registry (hive = DEFAULT_VK_REGISTRY_HIVE) key as
256*given in "location"
257* for a list or name/values which are added to a returned list (function return
258*value).
Jon Ashburnffad94d2015-06-30 14:46:22 -0700259* The DWORD values within the key must be 0 or they are skipped.
Jon Ashburne39a4f82015-08-28 13:38:21 -0600260* Function return is a string with a ';' separated list of filenames.
Jon Ashburnffad94d2015-06-30 14:46:22 -0700261* Function return is NULL if no valid name/value pairs are found in the key,
262* or the key is not found.
263*
264* \returns
265* A string list of filenames as pointer.
266* When done using the returned string list, pointer should be freed.
267*/
Jon Ashburn23d36b12016-02-02 17:47:28 -0700268static char *loader_get_registry_files(const struct loader_instance *inst,
269 char *location) {
Jon Ashburnffad94d2015-06-30 14:46:22 -0700270 LONG rtn_value;
271 HKEY hive, key;
Piers Daniell524ec732015-11-05 16:58:26 -0700272 DWORD access_flags;
Jon Ashburnffad94d2015-06-30 14:46:22 -0700273 char name[2048];
274 char *out = NULL;
Tony Barbourea968902015-07-29 14:26:21 -0600275 char *loc = location;
276 char *next;
Jon Ashburnffad94d2015-06-30 14:46:22 -0700277 DWORD idx = 0;
278 DWORD name_size = sizeof(name);
279 DWORD value;
280 DWORD total_size = 4096;
281 DWORD value_size = sizeof(value);
Tony Barbourea968902015-07-29 14:26:21 -0600282
Jon Ashburn23d36b12016-02-02 17:47:28 -0700283 while (*loc) {
Tony Barbourea968902015-07-29 14:26:21 -0600284 next = loader_get_next_path(loc);
285 hive = DEFAULT_VK_REGISTRY_HIVE;
Piers Daniell524ec732015-11-05 16:58:26 -0700286 access_flags = KEY_QUERY_VALUE;
Tony Barbourea968902015-07-29 14:26:21 -0600287 rtn_value = RegOpenKeyEx(hive, loc, 0, access_flags, &key);
288 if (rtn_value != ERROR_SUCCESS) {
Mark Young93ecb1d2016-01-13 13:47:16 -0700289 // We still couldn't find the key, so give up:
290 loc = next;
291 continue;
Jon Ashburnffad94d2015-06-30 14:46:22 -0700292 }
Tony Barbourea968902015-07-29 14:26:21 -0600293
Jon Ashburn23d36b12016-02-02 17:47:28 -0700294 while ((rtn_value = RegEnumValue(key, idx++, name, &name_size, NULL,
295 NULL, (LPBYTE)&value, &value_size)) ==
296 ERROR_SUCCESS) {
Tony Barbourea968902015-07-29 14:26:21 -0600297 if (value_size == sizeof(value) && value == 0) {
298 if (out == NULL) {
Jon Ashburn23d36b12016-02-02 17:47:28 -0700299 out = loader_heap_alloc(
300 inst, total_size, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Tony Barbourea968902015-07-29 14:26:21 -0600301 out[0] = '\0';
Jon Ashburn23d36b12016-02-02 17:47:28 -0700302 } else if (strlen(out) + name_size + 1 > total_size) {
303 out = loader_heap_realloc(
304 inst, out, total_size, total_size * 2,
305 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Tony Barbourea968902015-07-29 14:26:21 -0600306 total_size *= 2;
307 }
308 if (out == NULL) {
Jon Ashburn23d36b12016-02-02 17:47:28 -0700309 loader_log(
310 inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
311 "Out of memory, failed loader_get_registry_files");
Tony Barbourea968902015-07-29 14:26:21 -0600312 return NULL;
313 }
314 if (strlen(out) == 0)
Jon Ashburn23d36b12016-02-02 17:47:28 -0700315 snprintf(out, name_size + 1, "%s", name);
Tony Barbourea968902015-07-29 14:26:21 -0600316 else
Jon Ashburn23d36b12016-02-02 17:47:28 -0700317 snprintf(out + strlen(out), name_size + 2, "%c%s",
318 PATH_SEPERATOR, name);
Tony Barbourea968902015-07-29 14:26:21 -0600319 }
320 name_size = 2048;
321 }
322 loc = next;
Jon Ashburnffad94d2015-06-30 14:46:22 -0700323 }
Tony Barbourea968902015-07-29 14:26:21 -0600324
Jon Ashburnffad94d2015-06-30 14:46:22 -0700325 return out;
326}
327
Ian Elliott4470a302015-02-17 10:33:47 -0700328#endif // WIN32
329
Jon Ashburnc7237a72015-08-03 09:08:46 -0600330/**
Daniel Dadap00b4aba2015-09-30 11:50:51 -0500331 * Combine path elements, separating each element with the platform-specific
332 * directory separator, and save the combined string to a destination buffer,
333 * not exceeding the given length. Path elements are given as variadic args,
334 * with a NULL element terminating the list.
335 *
336 * \returns the total length of the combined string, not including an ASCII
337 * NUL termination character. This length may exceed the available storage:
338 * in this case, the written string will be truncated to avoid a buffer
339 * overrun, and the return value will greater than or equal to the storage
340 * size. A NULL argument may be provided as the destination buffer in order
341 * to determine the required string length without actually writing a string.
342 */
343
Jon Ashburn23d36b12016-02-02 17:47:28 -0700344static size_t loader_platform_combine_path(char *dest, size_t len, ...) {
Courtney Goeltzenleuchter0ef13a02015-12-16 16:19:46 -0700345 size_t required_len = 0;
Daniel Dadap00b4aba2015-09-30 11:50:51 -0500346 va_list ap;
347 const char *component;
348
349 va_start(ap, len);
350
Jon Ashburn23d36b12016-02-02 17:47:28 -0700351 while ((component = va_arg(ap, const char *))) {
Daniel Dadap00b4aba2015-09-30 11:50:51 -0500352 if (required_len > 0) {
353 // This path element is not the first non-empty element; prepend
354 // a directory separator if space allows
355 if (dest && required_len + 1 < len) {
356 snprintf(dest + required_len, len - required_len, "%c",
357 DIRECTORY_SYMBOL);
358 }
359 required_len++;
360 }
361
362 if (dest && required_len < len) {
363 strncpy(dest + required_len, component, len - required_len);
364 }
365 required_len += strlen(component);
366 }
367
368 va_end(ap);
369
370 // strncpy(3) won't add a NUL terminating byte in the event of truncation.
371 if (dest && required_len >= len) {
372 dest[len - 1] = '\0';
373 }
374
375 return required_len;
376}
377
Daniel Dadap00b4aba2015-09-30 11:50:51 -0500378/**
Jon Ashburnc7237a72015-08-03 09:08:46 -0600379 * Given string of three part form "maj.min.pat" convert to a vulkan version
380 * number.
381 */
Jon Ashburn23d36b12016-02-02 17:47:28 -0700382static uint32_t loader_make_version(const char *vers_str) {
383 uint32_t vers = 0, major = 0, minor = 0, patch = 0;
384 char *minor_str = NULL;
Jon Ashburnc7237a72015-08-03 09:08:46 -0600385 char *patch_str = NULL;
386 char *cstr;
387 char *str;
388
389 if (!vers_str)
390 return vers;
391 cstr = loader_stack_alloc(strlen(vers_str) + 1);
392 strcpy(cstr, vers_str);
393 while ((str = strchr(cstr, '.')) != NULL) {
394 if (minor_str == NULL) {
395 minor_str = str + 1;
396 *str = '\0';
397 major = atoi(cstr);
Jon Ashburn23d36b12016-02-02 17:47:28 -0700398 } else if (patch_str == NULL) {
Jon Ashburnc7237a72015-08-03 09:08:46 -0600399 patch_str = str + 1;
400 *str = '\0';
401 minor = atoi(minor_str);
Jon Ashburn23d36b12016-02-02 17:47:28 -0700402 } else {
Jon Ashburnc7237a72015-08-03 09:08:46 -0600403 return vers;
404 }
405 cstr = str + 1;
406 }
407 patch = atoi(patch_str);
408
409 return VK_MAKE_VERSION(major, minor, patch);
Jon Ashburnc7237a72015-08-03 09:08:46 -0600410}
411
Jon Ashburn23d36b12016-02-02 17:47:28 -0700412bool compare_vk_extension_properties(const VkExtensionProperties *op1,
413 const VkExtensionProperties *op2) {
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800414 return strcmp(op1->extensionName, op2->extensionName) == 0 ? true : false;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600415}
416
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -0600417/**
Jon Ashburnbd6c4882015-07-02 12:59:25 -0600418 * Search the given ext_array for an extension
419 * matching the given vk_ext_prop
420 */
Jon Ashburn23d36b12016-02-02 17:47:28 -0700421bool has_vk_extension_property_array(const VkExtensionProperties *vk_ext_prop,
422 const uint32_t count,
423 const VkExtensionProperties *ext_array) {
Jon Ashburnbd6c4882015-07-02 12:59:25 -0600424 for (uint32_t i = 0; i < count; i++) {
425 if (compare_vk_extension_properties(vk_ext_prop, &ext_array[i]))
426 return true;
427 }
428 return false;
429}
430
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -0600431/**
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600432 * Search the given ext_list for an extension
433 * matching the given vk_ext_prop
434 */
Jon Ashburn23d36b12016-02-02 17:47:28 -0700435bool has_vk_extension_property(const VkExtensionProperties *vk_ext_prop,
436 const struct loader_extension_list *ext_list) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600437 for (uint32_t i = 0; i < ext_list->count; i++) {
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600438 if (compare_vk_extension_properties(&ext_list->list[i], vk_ext_prop))
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600439 return true;
440 }
441 return false;
442}
443
Jon Ashburnb2ef1372015-07-16 17:19:31 -0600444static inline bool loader_is_layer_type_device(const enum layer_type type) {
445 if ((type & VK_LAYER_TYPE_DEVICE_EXPLICIT) ||
Jon Ashburn23d36b12016-02-02 17:47:28 -0700446 (type & VK_LAYER_TYPE_DEVICE_IMPLICIT))
Jon Ashburnb2ef1372015-07-16 17:19:31 -0600447 return true;
448 return false;
449}
450
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600451/*
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -0600452 * Search the given layer list for a layer matching the given layer name
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600453 */
Jon Ashburn23d36b12016-02-02 17:47:28 -0700454static struct loader_layer_properties *
455loader_get_layer_property(const char *name,
456 const struct loader_layer_list *layer_list) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600457 for (uint32_t i = 0; i < layer_list->count; i++) {
458 const VkLayerProperties *item = &layer_list->list[i].info;
459 if (strcmp(name, item->layerName) == 0)
460 return &layer_list->list[i];
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600461 }
462 return NULL;
463}
464
Jon Ashburne13ecc92015-08-03 17:19:30 -0600465/**
466 * Get the next unused layer property in the list. Init the property to zero.
467 */
Jon Ashburn23d36b12016-02-02 17:47:28 -0700468static struct loader_layer_properties *
469loader_get_next_layer_property(const struct loader_instance *inst,
470 struct loader_layer_list *layer_list) {
Jon Ashburne13ecc92015-08-03 17:19:30 -0600471 if (layer_list->capacity == 0) {
Jon Ashburn23d36b12016-02-02 17:47:28 -0700472 layer_list->list =
473 loader_heap_alloc(inst, sizeof(struct loader_layer_properties) * 64,
474 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburne13ecc92015-08-03 17:19:30 -0600475 if (layer_list->list == NULL) {
Jon Ashburn23d36b12016-02-02 17:47:28 -0700476 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
477 "Out of memory can't add any layer properties to list");
Jon Ashburne13ecc92015-08-03 17:19:30 -0600478 return NULL;
479 }
Jon Ashburn23d36b12016-02-02 17:47:28 -0700480 memset(layer_list->list, 0,
481 sizeof(struct loader_layer_properties) * 64);
Jon Ashburne13ecc92015-08-03 17:19:30 -0600482 layer_list->capacity = sizeof(struct loader_layer_properties) * 64;
483 }
484
485 // ensure enough room to add an entry
Jon Ashburn23d36b12016-02-02 17:47:28 -0700486 if ((layer_list->count + 1) * sizeof(struct loader_layer_properties) >
487 layer_list->capacity) {
488 layer_list->list = loader_heap_realloc(
489 inst, layer_list->list, layer_list->capacity,
490 layer_list->capacity * 2, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburne13ecc92015-08-03 17:19:30 -0600491 if (layer_list->list == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700492 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburn23d36b12016-02-02 17:47:28 -0700493 "realloc failed for layer list");
Jon Ashburne13ecc92015-08-03 17:19:30 -0600494 }
495 layer_list->capacity *= 2;
496 }
497
498 layer_list->count++;
499 return &(layer_list->list[layer_list->count - 1]);
500}
501
502/**
503 * Remove all layer properties entrys from the list
504 */
Jon Ashburn23d36b12016-02-02 17:47:28 -0700505void loader_delete_layer_properties(const struct loader_instance *inst,
506 struct loader_layer_list *layer_list) {
Jon Ashburn39fbd4e2015-12-10 18:17:34 -0700507 uint32_t i, j;
508 struct loader_device_extension_list *dev_ext_list;
Jon Ashburnb82c1852015-08-11 14:49:54 -0600509 if (!layer_list)
510 return;
511
Jon Ashburne13ecc92015-08-03 17:19:30 -0600512 for (i = 0; i < layer_list->count; i++) {
Jon Ashburn23d36b12016-02-02 17:47:28 -0700513 loader_destroy_generic_list(
514 inst, (struct loader_generic_list *)&layer_list->list[i]
515 .instance_extension_list);
Jon Ashburn39fbd4e2015-12-10 18:17:34 -0700516 dev_ext_list = &layer_list->list[i].device_extension_list;
Jon Ashburn23d36b12016-02-02 17:47:28 -0700517 if (dev_ext_list->capacity > 0 &&
518 dev_ext_list->list->entrypoint_count > 0) {
519 for (j = 0; j < dev_ext_list->list->entrypoint_count; j++) {
Jon Ashburn39fbd4e2015-12-10 18:17:34 -0700520 loader_heap_free(inst, dev_ext_list->list->entrypoints[j]);
521 }
522 loader_heap_free(inst, dev_ext_list->list->entrypoints);
523 }
Jon Ashburn23d36b12016-02-02 17:47:28 -0700524 loader_destroy_generic_list(inst,
525 (struct loader_generic_list *)dev_ext_list);
Jon Ashburne13ecc92015-08-03 17:19:30 -0600526 }
527 layer_list->count = 0;
528
Jon Ashburnb82c1852015-08-11 14:49:54 -0600529 if (layer_list->capacity > 0) {
530 layer_list->capacity = 0;
Jon Ashburne39a4f82015-08-28 13:38:21 -0600531 loader_heap_free(inst, layer_list->list);
Jon Ashburnb82c1852015-08-11 14:49:54 -0600532 }
Jon Ashburne13ecc92015-08-03 17:19:30 -0600533}
534
Courtney Goeltzenleuchterf538ef72015-12-02 14:00:19 -0700535static void loader_add_instance_extensions(
Jon Ashburn23d36b12016-02-02 17:47:28 -0700536 const struct loader_instance *inst,
537 const PFN_vkEnumerateInstanceExtensionProperties fp_get_props,
538 const char *lib_name, struct loader_extension_list *ext_list) {
Courtney Goeltzenleuchter36eeb742015-12-21 16:41:47 -0700539 uint32_t i, count = 0;
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600540 VkExtensionProperties *ext_props;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600541 VkResult res;
542
Courtney Goeltzenleuchter5c6cf472015-07-06 22:28:18 -0600543 if (!fp_get_props) {
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -0600544 /* No EnumerateInstanceExtensionProperties defined */
Courtney Goeltzenleuchter5c6cf472015-07-06 22:28:18 -0600545 return;
546 }
547
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600548 res = fp_get_props(NULL, &count, NULL);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600549 if (res != VK_SUCCESS) {
Mark Lobodzinski510e20d2016-02-11 09:26:16 -0700550 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
Jon Ashburn23d36b12016-02-02 17:47:28 -0700551 "Error getting Instance extension count from %s", lib_name);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600552 return;
553 }
Jon Ashburn953bb3c2015-06-10 16:11:42 -0600554
Courtney Goeltzenleuchter5c6cf472015-07-06 22:28:18 -0600555 if (count == 0) {
556 /* No ExtensionProperties to report */
557 return;
558 }
559
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600560 ext_props = loader_stack_alloc(count * sizeof(VkExtensionProperties));
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600561
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600562 res = fp_get_props(NULL, &count, ext_props);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600563 if (res != VK_SUCCESS) {
Mark Lobodzinski510e20d2016-02-11 09:26:16 -0700564 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
Jon Ashburn23d36b12016-02-02 17:47:28 -0700565 "Error getting Instance extensions from %s", lib_name);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600566 return;
567 }
Tony Barbour59a47322015-06-24 16:06:58 -0600568
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600569 for (i = 0; i < count; i++) {
Courtney Goeltzenleuchter53043732015-07-12 13:20:05 -0600570 char spec_version[64];
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600571
572 snprintf(spec_version, sizeof(spec_version), "%d.%d.%d",
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600573 VK_MAJOR(ext_props[i].specVersion),
574 VK_MINOR(ext_props[i].specVersion),
575 VK_PATCH(ext_props[i].specVersion));
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700576 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
Courtney Goeltzenleuchterf538ef72015-12-02 14:00:19 -0700577 "Instance Extension: %s (%s) version %s",
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800578 ext_props[i].extensionName, lib_name, spec_version);
Jon Ashburne39a4f82015-08-28 13:38:21 -0600579 loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600580 }
581
582 return;
583}
584
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700585/*
586 * Initialize ext_list with the physical device extensions.
587 * The extension properties are passed as inputs in count and ext_props.
588 */
Jon Ashburn23d36b12016-02-02 17:47:28 -0700589static VkResult
590loader_init_device_extensions(const struct loader_instance *inst,
591 struct loader_physical_device *phys_dev,
592 uint32_t count, VkExtensionProperties *ext_props,
593 struct loader_extension_list *ext_list) {
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700594 VkResult res;
595 uint32_t i;
596
Jon Ashburn23d36b12016-02-02 17:47:28 -0700597 if (!loader_init_generic_list(inst, (struct loader_generic_list *)ext_list,
Jon Ashburn6e6a2162015-12-10 08:51:10 -0700598 sizeof(VkExtensionProperties))) {
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700599 return VK_ERROR_OUT_OF_HOST_MEMORY;
600 }
601
602 for (i = 0; i < count; i++) {
603 char spec_version[64];
604
Jon Ashburn23d36b12016-02-02 17:47:28 -0700605 snprintf(spec_version, sizeof(spec_version), "%d.%d.%d",
606 VK_MAJOR(ext_props[i].specVersion),
607 VK_MINOR(ext_props[i].specVersion),
608 VK_PATCH(ext_props[i].specVersion));
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700609 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
Jon Ashburn23d36b12016-02-02 17:47:28 -0700610 "Device Extension: %s (%s) version %s",
611 ext_props[i].extensionName,
612 phys_dev->this_icd->this_icd_lib->lib_name, spec_version);
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700613 res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
614 if (res != VK_SUCCESS)
615 return res;
616 }
617
618 return VK_SUCCESS;
619}
620
Jon Ashburn1530c342016-02-26 13:14:27 -0700621VkResult loader_add_device_extensions(const struct loader_instance *inst,
622 struct loader_icd *icd,
623 VkPhysicalDevice physical_device,
624 const char *lib_name,
625 struct loader_extension_list *ext_list) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600626 uint32_t i, count;
627 VkResult res;
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600628 VkExtensionProperties *ext_props;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600629
Jon Ashburn23d36b12016-02-02 17:47:28 -0700630 res = icd->EnumerateDeviceExtensionProperties(physical_device, NULL, &count,
631 NULL);
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700632 if (res == VK_SUCCESS && count > 0) {
Jon Ashburn23d36b12016-02-02 17:47:28 -0700633 ext_props = loader_stack_alloc(count * sizeof(VkExtensionProperties));
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700634 if (!ext_props)
635 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburn23d36b12016-02-02 17:47:28 -0700636 res = icd->EnumerateDeviceExtensionProperties(physical_device, NULL,
637 &count, ext_props);
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700638 if (res != VK_SUCCESS)
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700639 return res;
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700640 for (i = 0; i < count; i++) {
641 char spec_version[64];
642
Jon Ashburn23d36b12016-02-02 17:47:28 -0700643 snprintf(spec_version, sizeof(spec_version), "%d.%d.%d",
644 VK_MAJOR(ext_props[i].specVersion),
645 VK_MINOR(ext_props[i].specVersion),
646 VK_PATCH(ext_props[i].specVersion));
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700647 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
Jon Ashburn23d36b12016-02-02 17:47:28 -0700648 "Device Extension: %s (%s) version %s",
649 ext_props[i].extensionName, lib_name, spec_version);
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700650 res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
651 if (res != VK_SUCCESS)
652 return res;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600653 }
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700654 } else {
Jon Ashburn23d36b12016-02-02 17:47:28 -0700655 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
656 "Error getting physical device extension info count from "
657 "library %s",
658 lib_name);
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700659 return res;
660 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600661
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700662 return VK_SUCCESS;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600663}
664
Jon Ashburn1530c342016-02-26 13:14:27 -0700665bool loader_init_generic_list(const struct loader_instance *inst,
666 struct loader_generic_list *list_info,
667 size_t element_size) {
Jon Ashburn6e6a2162015-12-10 08:51:10 -0700668 list_info->capacity = 32 * element_size;
Jon Ashburn23d36b12016-02-02 17:47:28 -0700669 list_info->list = loader_heap_alloc(inst, list_info->capacity,
670 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn6e6a2162015-12-10 08:51:10 -0700671 if (list_info->list == NULL) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600672 return false;
673 }
Jon Ashburn6e6a2162015-12-10 08:51:10 -0700674 memset(list_info->list, 0, list_info->capacity);
675 list_info->count = 0;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600676 return true;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600677}
678
Jon Ashburn6e6a2162015-12-10 08:51:10 -0700679void loader_destroy_generic_list(const struct loader_instance *inst,
Jon Ashburn23d36b12016-02-02 17:47:28 -0700680 struct loader_generic_list *list) {
Jon Ashburn6e6a2162015-12-10 08:51:10 -0700681 loader_heap_free(inst, list->list);
682 list->count = 0;
683 list->capacity = 0;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600684}
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600685
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600686/*
687 * Append non-duplicate extension properties defined in props
688 * to the given ext_list.
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700689 * Return
690 * Vk_SUCCESS on success
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600691 */
Jon Ashburn23d36b12016-02-02 17:47:28 -0700692VkResult loader_add_to_ext_list(const struct loader_instance *inst,
693 struct loader_extension_list *ext_list,
694 uint32_t prop_list_count,
695 const VkExtensionProperties *props) {
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600696 uint32_t i;
697 const VkExtensionProperties *cur_ext;
698
699 if (ext_list->list == NULL || ext_list->capacity == 0) {
Jon Ashburn23d36b12016-02-02 17:47:28 -0700700 loader_init_generic_list(inst, (struct loader_generic_list *)ext_list,
Jon Ashburn6e6a2162015-12-10 08:51:10 -0700701 sizeof(VkExtensionProperties));
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600702 }
703
704 if (ext_list->list == NULL)
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700705 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600706
707 for (i = 0; i < prop_list_count; i++) {
708 cur_ext = &props[i];
709
710 // look for duplicates
711 if (has_vk_extension_property(cur_ext, ext_list)) {
712 continue;
713 }
714
715 // add to list at end
716 // check for enough capacity
Jon Ashburn23d36b12016-02-02 17:47:28 -0700717 if (ext_list->count * sizeof(VkExtensionProperties) >=
718 ext_list->capacity) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600719
Jon Ashburn23d36b12016-02-02 17:47:28 -0700720 ext_list->list = loader_heap_realloc(
721 inst, ext_list->list, ext_list->capacity,
722 ext_list->capacity * 2, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700723
724 if (ext_list->list == NULL)
725 return VK_ERROR_OUT_OF_HOST_MEMORY;
726
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600727 // double capacity
728 ext_list->capacity *= 2;
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600729 }
730
Jon Ashburn23d36b12016-02-02 17:47:28 -0700731 memcpy(&ext_list->list[ext_list->count], cur_ext,
732 sizeof(VkExtensionProperties));
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600733 ext_list->count++;
734 }
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700735 return VK_SUCCESS;
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600736}
737
Jon Ashburn39fbd4e2015-12-10 18:17:34 -0700738/*
739 * Append one extension property defined in props with entrypoints
740 * defined in entrys to the given ext_list.
741 * Return
742 * Vk_SUCCESS on success
743 */
Jon Ashburn23d36b12016-02-02 17:47:28 -0700744VkResult
745loader_add_to_dev_ext_list(const struct loader_instance *inst,
746 struct loader_device_extension_list *ext_list,
747 const VkExtensionProperties *props,
748 uint32_t entry_count, char **entrys) {
Jon Ashburn39fbd4e2015-12-10 18:17:34 -0700749 uint32_t idx;
750 if (ext_list->list == NULL || ext_list->capacity == 0) {
Jon Ashburn23d36b12016-02-02 17:47:28 -0700751 loader_init_generic_list(inst, (struct loader_generic_list *)ext_list,
Jon Ashburn39fbd4e2015-12-10 18:17:34 -0700752 sizeof(struct loader_dev_ext_props));
753 }
754
755 if (ext_list->list == NULL)
756 return VK_ERROR_OUT_OF_HOST_MEMORY;
757
Jon Ashburn23d36b12016-02-02 17:47:28 -0700758 idx = ext_list->count;
Jon Ashburn39fbd4e2015-12-10 18:17:34 -0700759 // add to list at end
760 // check for enough capacity
Jon Ashburn23d36b12016-02-02 17:47:28 -0700761 if (idx * sizeof(struct loader_dev_ext_props) >= ext_list->capacity) {
Jon Ashburn39fbd4e2015-12-10 18:17:34 -0700762
Jon Ashburn23d36b12016-02-02 17:47:28 -0700763 ext_list->list = loader_heap_realloc(
764 inst, ext_list->list, ext_list->capacity, ext_list->capacity * 2,
765 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn39fbd4e2015-12-10 18:17:34 -0700766
767 if (ext_list->list == NULL)
768 return VK_ERROR_OUT_OF_HOST_MEMORY;
769
770 // double capacity
771 ext_list->capacity *= 2;
772 }
773
Jon Ashburn23d36b12016-02-02 17:47:28 -0700774 memcpy(&ext_list->list[idx].props, props,
775 sizeof(struct loader_dev_ext_props));
Jon Ashburn39fbd4e2015-12-10 18:17:34 -0700776 ext_list->list[idx].entrypoint_count = entry_count;
Jon Ashburn23d36b12016-02-02 17:47:28 -0700777 ext_list->list[idx].entrypoints =
778 loader_heap_alloc(inst, sizeof(char *) * entry_count,
779 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn39fbd4e2015-12-10 18:17:34 -0700780 if (ext_list->list[idx].entrypoints == NULL)
781 return VK_ERROR_OUT_OF_HOST_MEMORY;
782 for (uint32_t i = 0; i < entry_count; i++) {
Jon Ashburn23d36b12016-02-02 17:47:28 -0700783 ext_list->list[idx].entrypoints[i] = loader_heap_alloc(
784 inst, strlen(entrys[i]) + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn39fbd4e2015-12-10 18:17:34 -0700785 if (ext_list->list[idx].entrypoints[i] == NULL)
786 return VK_ERROR_OUT_OF_HOST_MEMORY;
787 strcpy(ext_list->list[idx].entrypoints[i], entrys[i]);
788 }
789 ext_list->count++;
790
791 return VK_SUCCESS;
792}
793
Jon Ashburnbd6c4882015-07-02 12:59:25 -0600794/**
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600795 * Search the given search_list for any layers in the props list.
Jon Ashburn23d36b12016-02-02 17:47:28 -0700796 * Add these to the output layer_list. Don't add duplicates to the output
797 * layer_list.
Jon Ashburnbd6c4882015-07-02 12:59:25 -0600798 */
Jon Ashburn23d36b12016-02-02 17:47:28 -0700799static VkResult
800loader_add_layer_names_to_list(const struct loader_instance *inst,
801 struct loader_layer_list *output_list,
802 uint32_t name_count, const char *const *names,
803 const struct loader_layer_list *search_list) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600804 struct loader_layer_properties *layer_prop;
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -0600805 VkResult err = VK_SUCCESS;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600806
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600807 for (uint32_t i = 0; i < name_count; i++) {
808 const char *search_target = names[i];
Jon Ashburne13ecc92015-08-03 17:19:30 -0600809 layer_prop = loader_get_layer_property(search_target, search_list);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600810 if (!layer_prop) {
Jon Ashburn23d36b12016-02-02 17:47:28 -0700811 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
812 "Unable to find layer %s", search_target);
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -0600813 err = VK_ERROR_LAYER_NOT_PRESENT;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600814 continue;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600815 }
816
Jon Ashburne39a4f82015-08-28 13:38:21 -0600817 loader_add_to_layer_list(inst, output_list, 1, layer_prop);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600818 }
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -0600819
820 return err;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600821}
822
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600823/*
824 * Manage lists of VkLayerProperties
825 */
Jon Ashburne39a4f82015-08-28 13:38:21 -0600826static bool loader_init_layer_list(const struct loader_instance *inst,
Jon Ashburn23d36b12016-02-02 17:47:28 -0700827 struct loader_layer_list *list) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600828 list->capacity = 32 * sizeof(struct loader_layer_properties);
Jon Ashburn23d36b12016-02-02 17:47:28 -0700829 list->list = loader_heap_alloc(inst, list->capacity,
830 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600831 if (list->list == NULL) {
832 return false;
833 }
834 memset(list->list, 0, list->capacity);
835 list->count = 0;
836 return true;
837}
838
Jon Ashburne39a4f82015-08-28 13:38:21 -0600839void loader_destroy_layer_list(const struct loader_instance *inst,
Jon Ashburn23d36b12016-02-02 17:47:28 -0700840 struct loader_layer_list *layer_list) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600841 loader_heap_free(inst, layer_list->list);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600842 layer_list->count = 0;
843 layer_list->capacity = 0;
844}
845
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600846/*
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600847 * Manage list of layer libraries (loader_lib_info)
848 */
Jon Ashburn23d36b12016-02-02 17:47:28 -0700849static bool
850loader_init_layer_library_list(const struct loader_instance *inst,
851 struct loader_layer_library_list *list) {
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600852 list->capacity = 32 * sizeof(struct loader_lib_info);
Jon Ashburn23d36b12016-02-02 17:47:28 -0700853 list->list = loader_heap_alloc(inst, list->capacity,
854 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600855 if (list->list == NULL) {
856 return false;
857 }
858 memset(list->list, 0, list->capacity);
859 list->count = 0;
860 return true;
861}
862
Jon Ashburne39a4f82015-08-28 13:38:21 -0600863void loader_destroy_layer_library_list(const struct loader_instance *inst,
Jon Ashburn23d36b12016-02-02 17:47:28 -0700864 struct loader_layer_library_list *list) {
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600865 for (uint32_t i = 0; i < list->count; i++) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600866 loader_heap_free(inst, list->list[i].lib_name);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600867 }
Jon Ashburne39a4f82015-08-28 13:38:21 -0600868 loader_heap_free(inst, list->list);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600869 list->count = 0;
870 list->capacity = 0;
871}
872
Jon Ashburn23d36b12016-02-02 17:47:28 -0700873void loader_add_to_layer_library_list(const struct loader_instance *inst,
874 struct loader_layer_library_list *list,
875 uint32_t item_count,
876 const struct loader_lib_info *new_items) {
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600877 uint32_t i;
878 struct loader_lib_info *item;
879
880 if (list->list == NULL || list->capacity == 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600881 loader_init_layer_library_list(inst, list);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600882 }
883
884 if (list->list == NULL)
885 return;
886
887 for (i = 0; i < item_count; i++) {
Jon Ashburn23d36b12016-02-02 17:47:28 -0700888 item = (struct loader_lib_info *)&new_items[i];
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600889
890 // look for duplicates
891 for (uint32_t j = 0; j < list->count; j++) {
892 if (strcmp(list->list[i].lib_name, new_items->lib_name) == 0) {
893 continue;
894 }
895 }
896
897 // add to list at end
898 // check for enough capacity
Jon Ashburn23d36b12016-02-02 17:47:28 -0700899 if (list->count * sizeof(struct loader_lib_info) >= list->capacity) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600900
Jon Ashburn23d36b12016-02-02 17:47:28 -0700901 list->list = loader_heap_realloc(
902 inst, list->list, list->capacity, list->capacity * 2,
903 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600904 // double capacity
905 list->capacity *= 2;
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600906 }
907
908 memcpy(&list->list[list->count], item, sizeof(struct loader_lib_info));
909 list->count++;
910 }
911}
912
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600913/*
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600914 * Search the given layer list for a list
915 * matching the given VkLayerProperties
916 */
Jon Ashburn23d36b12016-02-02 17:47:28 -0700917bool has_vk_layer_property(const VkLayerProperties *vk_layer_prop,
918 const struct loader_layer_list *list) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600919 for (uint32_t i = 0; i < list->count; i++) {
920 if (strcmp(vk_layer_prop->layerName, list->list[i].info.layerName) == 0)
921 return true;
922 }
923 return false;
924}
925
926/*
927 * Search the given layer list for a layer
928 * matching the given name
929 */
Jon Ashburn23d36b12016-02-02 17:47:28 -0700930bool has_layer_name(const char *name, const struct loader_layer_list *list) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600931 for (uint32_t i = 0; i < list->count; i++) {
932 if (strcmp(name, list->list[i].info.layerName) == 0)
933 return true;
934 }
935 return false;
936}
937
938/*
939 * Append non-duplicate layer properties defined in prop_list
940 * to the given layer_info list
941 */
Jon Ashburn23d36b12016-02-02 17:47:28 -0700942void loader_add_to_layer_list(const struct loader_instance *inst,
943 struct loader_layer_list *list,
944 uint32_t prop_list_count,
945 const struct loader_layer_properties *props) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600946 uint32_t i;
947 struct loader_layer_properties *layer;
948
949 if (list->list == NULL || list->capacity == 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600950 loader_init_layer_list(inst, list);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600951 }
952
953 if (list->list == NULL)
954 return;
955
956 for (i = 0; i < prop_list_count; i++) {
Jon Ashburn23d36b12016-02-02 17:47:28 -0700957 layer = (struct loader_layer_properties *)&props[i];
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600958
959 // look for duplicates
960 if (has_vk_layer_property(&layer->info, list)) {
961 continue;
962 }
963
964 // add to list at end
965 // check for enough capacity
Jon Ashburn23d36b12016-02-02 17:47:28 -0700966 if (list->count * sizeof(struct loader_layer_properties) >=
967 list->capacity) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600968
Jon Ashburn23d36b12016-02-02 17:47:28 -0700969 list->list = loader_heap_realloc(
970 inst, list->list, list->capacity, list->capacity * 2,
971 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600972 // double capacity
973 list->capacity *= 2;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600974 }
975
Jon Ashburn23d36b12016-02-02 17:47:28 -0700976 memcpy(&list->list[list->count], layer,
977 sizeof(struct loader_layer_properties));
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600978 list->count++;
979 }
980}
981
Jon Ashburnbd332cc2015-07-07 10:27:45 -0600982/**
983 * Search the search_list for any layer with a name
984 * that matches the given name and a type that matches the given type
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600985 * Add all matching layers to the found_list
Jon Ashburnbd332cc2015-07-07 10:27:45 -0600986 * Do not add if found loader_layer_properties is already
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600987 * on the found_list.
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600988 */
Jon Ashburn23d36b12016-02-02 17:47:28 -0700989static void
990loader_find_layer_name_add_list(const struct loader_instance *inst,
991 const char *name, const enum layer_type type,
992 const struct loader_layer_list *search_list,
993 struct loader_layer_list *found_list) {
Jon Ashburn56151d62015-10-05 09:03:21 -0600994 bool found = false;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600995 for (uint32_t i = 0; i < search_list->count; i++) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600996 struct loader_layer_properties *layer_prop = &search_list->list[i];
Jon Ashburnbd332cc2015-07-07 10:27:45 -0600997 if (0 == strcmp(layer_prop->info.layerName, name) &&
Jon Ashburn23d36b12016-02-02 17:47:28 -0700998 (layer_prop->type & type)) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600999 /* Found a layer with the same name, add to found_list */
Jon Ashburne39a4f82015-08-28 13:38:21 -06001000 loader_add_to_layer_list(inst, found_list, 1, layer_prop);
Jon Ashburn56151d62015-10-05 09:03:21 -06001001 found = true;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001002 }
1003 }
Jon Ashburn56151d62015-10-05 09:03:21 -06001004 if (!found) {
Mark Lobodzinski510e20d2016-02-11 09:26:16 -07001005 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
Jon Ashburn23d36b12016-02-02 17:47:28 -07001006 "Warning, couldn't find layer name %s to activate", name);
Jon Ashburn56151d62015-10-05 09:03:21 -06001007 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001008}
1009
Jon Ashburn23d36b12016-02-02 17:47:28 -07001010static VkExtensionProperties *
1011get_extension_property(const char *name,
1012 const struct loader_extension_list *list) {
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06001013 for (uint32_t i = 0; i < list->count; i++) {
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001014 if (strcmp(name, list->list[i].extensionName) == 0)
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06001015 return &list->list[i];
Jon Ashburnfc2e38c2015-04-14 09:15:32 -06001016 }
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06001017 return NULL;
Jon Ashburnfc2e38c2015-04-14 09:15:32 -06001018}
1019
Jon Ashburn23d36b12016-02-02 17:47:28 -07001020static VkExtensionProperties *
1021get_dev_extension_property(const char *name,
1022 const struct loader_device_extension_list *list) {
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001023 for (uint32_t i = 0; i < list->count; i++) {
1024 if (strcmp(name, list->list[i].props.extensionName) == 0)
1025 return &list->list[i].props;
1026 }
1027 return NULL;
1028}
1029
Jon Ashburnbd6c4882015-07-02 12:59:25 -06001030/*
Courtney Goeltzenleuchterb39ccd52016-01-15 14:15:00 -07001031 * This function will return the pNext pointer of any
1032 * CreateInfo extensions that are not loader extensions.
1033 * This is used to skip past the loader extensions prepended
1034 * to the list during CreateInstance and CreateDevice.
1035 */
Jon Ashburn23d36b12016-02-02 17:47:28 -07001036void *loader_strip_create_extensions(const void *pNext) {
1037 VkLayerInstanceCreateInfo *create_info = (VkLayerInstanceCreateInfo *)pNext;
Courtney Goeltzenleuchterb39ccd52016-01-15 14:15:00 -07001038
Jon Ashburn23d36b12016-02-02 17:47:28 -07001039 while (
1040 create_info &&
1041 (create_info->sType == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO ||
1042 create_info->sType == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO)) {
1043 create_info = (VkLayerInstanceCreateInfo *)create_info->pNext;
Courtney Goeltzenleuchterb39ccd52016-01-15 14:15:00 -07001044 }
1045
1046 return create_info;
1047}
1048
1049/*
Courtney Goeltzenleuchterf538ef72015-12-02 14:00:19 -07001050 * For Instance extensions implemented within the loader (i.e. DEBUG_REPORT
Jon Ashburnbd6c4882015-07-02 12:59:25 -06001051 * the extension must provide two entry points for the loader to use:
1052 * - "trampoline" entry point - this is the address returned by GetProcAddr
1053 * and will always do what's necessary to support a global call.
1054 * - "terminator" function - this function will be put at the end of the
Jon Ashburn232e3af2015-11-30 17:21:25 -07001055 * instance chain and will contain the necessary logic to call / process
Jon Ashburnbd6c4882015-07-02 12:59:25 -06001056 * the extension for the appropriate ICDs that are available.
1057 * There is no generic mechanism for including these functions, the references
1058 * must be placed into the appropriate loader entry points.
Jon Ashburn23d36b12016-02-02 17:47:28 -07001059 * GetInstanceProcAddr: call extension GetInstanceProcAddr to check for
1060 * GetProcAddr requests
1061 * loader_coalesce_extensions(void) - add extension records to the list of
1062 * global
Jon Ashburnbd6c4882015-07-02 12:59:25 -06001063 * extension available to the app.
1064 * instance_disp - add function pointer for terminator function to this array.
1065 * The extension itself should be in a separate file that will be
1066 * linked directly with the loader.
1067 */
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06001068
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001069void loader_get_icd_loader_instance_extensions(
Jon Ashburn23d36b12016-02-02 17:47:28 -07001070 const struct loader_instance *inst, struct loader_icd_libs *icd_libs,
1071 struct loader_extension_list *inst_exts) {
Jon Ashburn5c6a46f2015-08-14 14:49:22 -06001072 struct loader_extension_list icd_exts;
Jon Ashburn23d36b12016-02-02 17:47:28 -07001073 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
1074 "Build ICD instance extension list");
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001075 // traverse scanned icd list adding non-duplicate extensions to the list
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001076 for (uint32_t i = 0; i < icd_libs->count; i++) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07001077 loader_init_generic_list(inst, (struct loader_generic_list *)&icd_exts,
Jon Ashburn6e6a2162015-12-10 08:51:10 -07001078 sizeof(VkExtensionProperties));
Jon Ashburn23d36b12016-02-02 17:47:28 -07001079 loader_add_instance_extensions(
1080 inst, icd_libs->list[i].EnumerateInstanceExtensionProperties,
1081 icd_libs->list[i].lib_name, &icd_exts);
1082 loader_add_to_ext_list(inst, inst_exts, icd_exts.count, icd_exts.list);
1083 loader_destroy_generic_list(inst,
1084 (struct loader_generic_list *)&icd_exts);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001085 };
1086
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001087 // Traverse loader's extensions, adding non-duplicate extensions to the list
Ian Elliott954fa342015-10-30 15:28:23 -06001088 wsi_add_instance_extensions(inst, inst_exts);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001089 debug_report_add_instance_extensions(inst, inst_exts);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001090}
1091
Jon Ashburne39a4f82015-08-28 13:38:21 -06001092struct loader_icd *loader_get_icd_and_device(const VkDevice device,
Jon Ashburn23d36b12016-02-02 17:47:28 -07001093 struct loader_device **found_dev) {
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001094 *found_dev = NULL;
Jon Ashburn23d36b12016-02-02 17:47:28 -07001095 for (struct loader_instance *inst = loader.instances; inst;
1096 inst = inst->next) {
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001097 for (struct loader_icd *icd = inst->icds; icd; icd = icd->next) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07001098 for (struct loader_device *dev = icd->logical_device_list; dev;
1099 dev = dev->next)
1100 /* Value comparison of device prevents object wrapping by layers
1101 */
1102 if (loader_get_dispatch(dev->device) ==
1103 loader_get_dispatch(device)) {
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001104 *found_dev = dev;
1105 return icd;
1106 }
1107 }
1108 }
1109 return NULL;
1110}
1111
Jon Ashburne39a4f82015-08-28 13:38:21 -06001112static void loader_destroy_logical_device(const struct loader_instance *inst,
Jon Ashburn23d36b12016-02-02 17:47:28 -07001113 struct loader_device *dev) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06001114 loader_heap_free(inst, dev->app_extension_props);
BogDan Vatra9ef09832016-01-04 14:05:49 +02001115 loader_destroy_layer_list(inst, &dev->activated_layer_list);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001116 loader_heap_free(inst, dev);
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001117}
1118
Jon Ashburn1530c342016-02-26 13:14:27 -07001119struct loader_device *
Jon Ashburn23d36b12016-02-02 17:47:28 -07001120loader_add_logical_device(const struct loader_instance *inst,
1121 struct loader_device **device_list) {
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001122 struct loader_device *new_dev;
1123
Jon Ashburn23d36b12016-02-02 17:47:28 -07001124 new_dev = loader_heap_alloc(inst, sizeof(struct loader_device),
1125 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001126 if (!new_dev) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07001127 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
1128 "Failed to alloc struct loader-device");
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001129 return NULL;
1130 }
1131
1132 memset(new_dev, 0, sizeof(struct loader_device));
1133
1134 new_dev->next = *device_list;
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001135 *device_list = new_dev;
1136 return new_dev;
1137}
1138
Jon Ashburn23d36b12016-02-02 17:47:28 -07001139void loader_remove_logical_device(const struct loader_instance *inst,
1140 struct loader_icd *icd,
1141 struct loader_device *found_dev) {
Jon Ashburn781a7ae2015-11-19 15:43:26 -07001142 struct loader_device *dev, *prev_dev;
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001143
1144 if (!icd || !found_dev)
1145 return;
1146
1147 prev_dev = NULL;
1148 dev = icd->logical_device_list;
1149 while (dev && dev != found_dev) {
1150 prev_dev = dev;
1151 dev = dev->next;
1152 }
1153
1154 if (prev_dev)
1155 prev_dev->next = found_dev->next;
1156 else
1157 icd->logical_device_list = found_dev->next;
Jon Ashburne39a4f82015-08-28 13:38:21 -06001158 loader_destroy_logical_device(inst, found_dev);
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001159}
1160
Jon Ashburn23d36b12016-02-02 17:47:28 -07001161static void loader_icd_destroy(struct loader_instance *ptr_inst,
1162 struct loader_icd *icd) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001163 ptr_inst->total_icd_count--;
Jon Ashburn23d36b12016-02-02 17:47:28 -07001164 for (struct loader_device *dev = icd->logical_device_list; dev;) {
Courtney Goeltzenleuchter1f157ac2015-06-14 19:57:15 -06001165 struct loader_device *next_dev = dev->next;
Jon Ashburne39a4f82015-08-28 13:38:21 -06001166 loader_destroy_logical_device(ptr_inst, dev);
Courtney Goeltzenleuchter1f157ac2015-06-14 19:57:15 -06001167 dev = next_dev;
1168 }
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001169
Jon Ashburne39a4f82015-08-28 13:38:21 -06001170 loader_heap_free(ptr_inst, icd);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001171}
1172
Jon Ashburn23d36b12016-02-02 17:47:28 -07001173static struct loader_icd *
1174loader_icd_create(const struct loader_instance *inst) {
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001175 struct loader_icd *icd;
1176
Jon Ashburn23d36b12016-02-02 17:47:28 -07001177 icd = loader_heap_alloc(inst, sizeof(*icd),
1178 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001179 if (!icd)
1180 return NULL;
1181
Courtney Goeltzenleuchter55001bb2014-10-28 10:29:27 -06001182 memset(icd, 0, sizeof(*icd));
1183
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001184 return icd;
1185}
1186
Jon Ashburn23d36b12016-02-02 17:47:28 -07001187static struct loader_icd *
1188loader_icd_add(struct loader_instance *ptr_inst,
1189 const struct loader_scanned_icds *icd_lib) {
Chia-I Wu13a61a52014-08-04 11:18:20 +08001190 struct loader_icd *icd;
1191
Jon Ashburne39a4f82015-08-28 13:38:21 -06001192 icd = loader_icd_create(ptr_inst);
Chia-I Wu13a61a52014-08-04 11:18:20 +08001193 if (!icd)
1194 return NULL;
1195
Jon Ashburn3d002332015-08-20 16:35:30 -06001196 icd->this_icd_lib = icd_lib;
1197 icd->this_instance = ptr_inst;
1198
Chia-I Wu13a61a52014-08-04 11:18:20 +08001199 /* prepend to the list */
Jon Ashburn46888392015-01-29 15:45:51 -07001200 icd->next = ptr_inst->icds;
1201 ptr_inst->icds = icd;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001202 ptr_inst->total_icd_count++;
Chia-I Wu13a61a52014-08-04 11:18:20 +08001203
1204 return icd;
1205}
1206
Jon Ashburn23d36b12016-02-02 17:47:28 -07001207void loader_scanned_icd_clear(const struct loader_instance *inst,
1208 struct loader_icd_libs *icd_libs) {
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001209 if (icd_libs->capacity == 0)
1210 return;
1211 for (uint32_t i = 0; i < icd_libs->count; i++) {
1212 loader_platform_close_library(icd_libs->list[i].handle);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001213 loader_heap_free(inst, icd_libs->list[i].lib_name);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001214 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06001215 loader_heap_free(inst, icd_libs->list);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001216 icd_libs->capacity = 0;
1217 icd_libs->count = 0;
1218 icd_libs->list = NULL;
1219}
1220
Jon Ashburne39a4f82015-08-28 13:38:21 -06001221static void loader_scanned_icd_init(const struct loader_instance *inst,
Jon Ashburn23d36b12016-02-02 17:47:28 -07001222 struct loader_icd_libs *icd_libs) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06001223 loader_scanned_icd_clear(inst, icd_libs);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001224 icd_libs->capacity = 8 * sizeof(struct loader_scanned_icds);
Jon Ashburn23d36b12016-02-02 17:47:28 -07001225 icd_libs->list = loader_heap_alloc(inst, icd_libs->capacity,
1226 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001227}
1228
Jon Ashburn23d36b12016-02-02 17:47:28 -07001229static void loader_scanned_icd_add(const struct loader_instance *inst,
1230 struct loader_icd_libs *icd_libs,
1231 const char *filename, uint32_t api_version) {
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001232 loader_platform_dl_handle handle;
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06001233 PFN_vkCreateInstance fp_create_inst;
Jon Ashburnfd4d09d2016-01-07 09:44:27 -07001234 PFN_vkEnumerateInstanceExtensionProperties fp_get_inst_ext_props;
Jon Ashburnc624c882015-07-16 10:17:29 -06001235 PFN_vkGetInstanceProcAddr fp_get_proc_addr;
Jon Ashburn46d1f582015-01-28 11:01:35 -07001236 struct loader_scanned_icds *new_node;
1237
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001238 /* TODO implement ref counting of libraries, for now this function leaves
1239 libraries open and the scanned_icd_clear closes them */
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001240 // Used to call: dlopen(filename, RTLD_LAZY);
1241 handle = loader_platform_open_library(filename);
Jon Ashburn46d1f582015-01-28 11:01:35 -07001242 if (!handle) {
Mark Lobodzinski510e20d2016-02-11 09:26:16 -07001243 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
Jon Ashburn23d36b12016-02-02 17:47:28 -07001244 loader_platform_open_library_error(filename));
Jon Ashburn46d1f582015-01-28 11:01:35 -07001245 return;
1246 }
1247
Jon Ashburn23d36b12016-02-02 17:47:28 -07001248 fp_get_proc_addr =
1249 loader_platform_get_proc_address(handle, "vk_icdGetInstanceProcAddr");
Jon Ashburnfd4d09d2016-01-07 09:44:27 -07001250 if (!fp_get_proc_addr) {
Jon Ashburn69a5f7a2016-01-11 14:41:35 -07001251 // Use deprecated interface
Jon Ashburn23d36b12016-02-02 17:47:28 -07001252 fp_get_proc_addr =
1253 loader_platform_get_proc_address(handle, "vkGetInstanceProcAddr");
Jon Ashburnfd4d09d2016-01-07 09:44:27 -07001254 if (!fp_get_proc_addr) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07001255 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
1256 loader_platform_get_proc_address_error(
1257 "vk_icdGetInstanceProcAddr"));
Jon Ashburnfd4d09d2016-01-07 09:44:27 -07001258 return;
1259 } else {
Mark Lobodzinski510e20d2016-02-11 09:26:16 -07001260 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
Jon Ashburn23d36b12016-02-02 17:47:28 -07001261 "Using deprecated ICD interface of "
1262 "vkGetInstanceProcAddr instead of "
1263 "vk_icdGetInstanceProcAddr");
Jon Ashburnfd4d09d2016-01-07 09:44:27 -07001264 }
Jon Ashburn23d36b12016-02-02 17:47:28 -07001265 fp_create_inst =
1266 loader_platform_get_proc_address(handle, "vkCreateInstance");
Jon Ashburn69a5f7a2016-01-11 14:41:35 -07001267 if (!fp_create_inst) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07001268 loader_log(
1269 inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
1270 "Couldn't get vkCreateInstance via dlsym/loadlibrary from ICD");
Jon Ashburn69a5f7a2016-01-11 14:41:35 -07001271 return;
1272 }
Jon Ashburn23d36b12016-02-02 17:47:28 -07001273 fp_get_inst_ext_props = loader_platform_get_proc_address(
1274 handle, "vkEnumerateInstanceExtensionProperties");
Jon Ashburn69a5f7a2016-01-11 14:41:35 -07001275 if (!fp_get_inst_ext_props) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07001276 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
1277 "Couldn't get vkEnumerateInstanceExtensionProperties "
1278 "via dlsym/loadlibrary from ICD");
Jon Ashburn69a5f7a2016-01-11 14:41:35 -07001279 return;
1280 }
Jon Ashburn23d36b12016-02-02 17:47:28 -07001281 } else {
Jon Ashburn69a5f7a2016-01-11 14:41:35 -07001282 // Use newer interface
Jon Ashburn23d36b12016-02-02 17:47:28 -07001283 fp_create_inst =
1284 (PFN_vkCreateInstance)fp_get_proc_addr(NULL, "vkCreateInstance");
Jon Ashburn69a5f7a2016-01-11 14:41:35 -07001285 if (!fp_create_inst) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07001286 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
1287 "Couldn't get vkCreateInstance via "
1288 "vk_icdGetInstanceProcAddr from ICD");
Jon Ashburn69a5f7a2016-01-11 14:41:35 -07001289 return;
1290 }
Jon Ashburn23d36b12016-02-02 17:47:28 -07001291 fp_get_inst_ext_props =
1292 (PFN_vkEnumerateInstanceExtensionProperties)fp_get_proc_addr(
1293 NULL, "vkEnumerateInstanceExtensionProperties");
Jon Ashburn69a5f7a2016-01-11 14:41:35 -07001294 if (!fp_get_inst_ext_props) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07001295 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
1296 "Couldn't get vkEnumerateInstanceExtensionProperties "
1297 "via vk_icdGetInstanceProcAddr from ICD");
Jon Ashburn69a5f7a2016-01-11 14:41:35 -07001298 return;
1299 }
Jon Ashburnfd4d09d2016-01-07 09:44:27 -07001300 }
Jon Ashburn46d1f582015-01-28 11:01:35 -07001301
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001302 // check for enough capacity
Jon Ashburn23d36b12016-02-02 17:47:28 -07001303 if ((icd_libs->count * sizeof(struct loader_scanned_icds)) >=
1304 icd_libs->capacity) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06001305
Jon Ashburn23d36b12016-02-02 17:47:28 -07001306 icd_libs->list = loader_heap_realloc(
1307 inst, icd_libs->list, icd_libs->capacity, icd_libs->capacity * 2,
1308 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
1309 // double capacity
1310 icd_libs->capacity *= 2;
Jon Ashburn46d1f582015-01-28 11:01:35 -07001311 }
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001312 new_node = &(icd_libs->list[icd_libs->count]);
Jon Ashburn46d1f582015-01-28 11:01:35 -07001313
1314 new_node->handle = handle;
Jon Ashburn005617f2015-11-17 17:35:40 -07001315 new_node->api_version = api_version;
Jon Ashburnc624c882015-07-16 10:17:29 -06001316 new_node->GetInstanceProcAddr = fp_get_proc_addr;
Jon Ashburnfd4d09d2016-01-07 09:44:27 -07001317 new_node->EnumerateInstanceExtensionProperties = fp_get_inst_ext_props;
Jon Ashburn46888392015-01-29 15:45:51 -07001318 new_node->CreateInstance = fp_create_inst;
Jon Ashburn46d1f582015-01-28 11:01:35 -07001319
Jon Ashburn23d36b12016-02-02 17:47:28 -07001320 new_node->lib_name = (char *)loader_heap_alloc(
1321 inst, strlen(filename) + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001322 if (!new_node->lib_name) {
Mark Lobodzinski510e20d2016-02-11 09:26:16 -07001323 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
Jon Ashburn23d36b12016-02-02 17:47:28 -07001324 "Out of memory can't add icd");
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001325 return;
1326 }
1327 strcpy(new_node->lib_name, filename);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001328 icd_libs->count++;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001329}
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001330
Jon Ashburn23d36b12016-02-02 17:47:28 -07001331static bool loader_icd_init_entrys(struct loader_icd *icd, VkInstance inst,
1332 const PFN_vkGetInstanceProcAddr fp_gipa) {
1333/* initialize entrypoint function pointers */
Jon Ashburn3da71f22015-05-14 12:43:38 -06001334
Jon Ashburn23d36b12016-02-02 17:47:28 -07001335#define LOOKUP_GIPA(func, required) \
1336 do { \
1337 icd->func = (PFN_vk##func)fp_gipa(inst, "vk" #func); \
1338 if (!icd->func && required) { \
1339 loader_log((struct loader_instance *)inst, \
Jon Ashburn1530c342016-02-26 13:14:27 -07001340 VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, \
Jon Ashburn23d36b12016-02-02 17:47:28 -07001341 loader_platform_get_proc_address_error("vk" #func)); \
1342 return false; \
1343 } \
Jon Ashburn3da71f22015-05-14 12:43:38 -06001344 } while (0)
1345
Jon Ashburnc624c882015-07-16 10:17:29 -06001346 LOOKUP_GIPA(GetDeviceProcAddr, true);
1347 LOOKUP_GIPA(DestroyInstance, true);
1348 LOOKUP_GIPA(EnumeratePhysicalDevices, true);
1349 LOOKUP_GIPA(GetPhysicalDeviceFeatures, true);
1350 LOOKUP_GIPA(GetPhysicalDeviceFormatProperties, true);
Jon Ashburn754864f2015-07-23 18:49:07 -06001351 LOOKUP_GIPA(GetPhysicalDeviceImageFormatProperties, true);
Jon Ashburnc624c882015-07-16 10:17:29 -06001352 LOOKUP_GIPA(CreateDevice, true);
1353 LOOKUP_GIPA(GetPhysicalDeviceProperties, true);
1354 LOOKUP_GIPA(GetPhysicalDeviceMemoryProperties, true);
Cody Northropd0802882015-08-03 17:04:53 -06001355 LOOKUP_GIPA(GetPhysicalDeviceQueueFamilyProperties, true);
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06001356 LOOKUP_GIPA(EnumerateDeviceExtensionProperties, true);
Jon Ashburnc624c882015-07-16 10:17:29 -06001357 LOOKUP_GIPA(GetPhysicalDeviceSparseImageFormatProperties, true);
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001358 LOOKUP_GIPA(CreateDebugReportCallbackEXT, false);
1359 LOOKUP_GIPA(DestroyDebugReportCallbackEXT, false);
Ian Elliott7e40db92015-08-21 15:09:33 -06001360 LOOKUP_GIPA(GetPhysicalDeviceSurfaceSupportKHR, false);
Ian Elliott486c5502015-11-19 16:05:09 -07001361 LOOKUP_GIPA(GetPhysicalDeviceSurfaceCapabilitiesKHR, false);
1362 LOOKUP_GIPA(GetPhysicalDeviceSurfaceFormatsKHR, false);
1363 LOOKUP_GIPA(GetPhysicalDeviceSurfacePresentModesKHR, false);
Ian Elliott919fa302015-11-24 15:39:10 -07001364#ifdef VK_USE_PLATFORM_WIN32_KHR
1365 LOOKUP_GIPA(GetPhysicalDeviceWin32PresentationSupportKHR, false);
1366#endif
1367#ifdef VK_USE_PLATFORM_XCB_KHR
1368 LOOKUP_GIPA(GetPhysicalDeviceXcbPresentationSupportKHR, false);
1369#endif
Jason Ekstranda5ebe8a2016-02-12 17:25:03 -08001370#ifdef VK_USE_PLATFORM_WAYLAND_KHR
1371 LOOKUP_GIPA(GetPhysicalDeviceWaylandPresentationSupportKHR, false);
1372#endif
Jon Ashburn3da71f22015-05-14 12:43:38 -06001373
Jon Ashburnc624c882015-07-16 10:17:29 -06001374#undef LOOKUP_GIPA
Ian Elliottd3ef02f2015-07-06 14:36:13 -06001375
Jon Ashburnc624c882015-07-16 10:17:29 -06001376 return true;
Jon Ashburn3da71f22015-05-14 12:43:38 -06001377}
1378
Jon Ashburn23d36b12016-02-02 17:47:28 -07001379static void loader_debug_init(void) {
Jon Ashburn38a497f2016-01-04 14:01:38 -07001380 const char *env, *orig;
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001381
1382 if (g_loader_debug > 0)
1383 return;
1384
1385 g_loader_debug = 0;
1386
1387 /* parse comma-separated debug options */
Jon Ashburn38a497f2016-01-04 14:01:38 -07001388 orig = env = loader_getenv("VK_LOADER_DEBUG");
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001389 while (env) {
1390 const char *p = strchr(env, ',');
1391 size_t len;
1392
1393 if (p)
1394 len = p - env;
1395 else
1396 len = strlen(env);
1397
1398 if (len > 0) {
Michael Worcester25c73e72015-12-10 18:06:24 +00001399 if (strncmp(env, "all", len) == 0) {
1400 g_loader_debug = ~0u;
1401 g_loader_log_msgs = ~0u;
1402 } else if (strncmp(env, "warn", len) == 0) {
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001403 g_loader_debug |= LOADER_WARN_BIT;
Mark Lobodzinski510e20d2016-02-11 09:26:16 -07001404 g_loader_log_msgs |= VK_DEBUG_REPORT_WARNING_BIT_EXT;
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001405 } else if (strncmp(env, "info", len) == 0) {
1406 g_loader_debug |= LOADER_INFO_BIT;
Mark Lobodzinski510e20d2016-02-11 09:26:16 -07001407 g_loader_log_msgs |= VK_DEBUG_REPORT_INFORMATION_BIT_EXT;
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001408 } else if (strncmp(env, "perf", len) == 0) {
1409 g_loader_debug |= LOADER_PERF_BIT;
Jon Ashburn1530c342016-02-26 13:14:27 -07001410 g_loader_log_msgs |=
1411 VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001412 } else if (strncmp(env, "error", len) == 0) {
1413 g_loader_debug |= LOADER_ERROR_BIT;
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001414 g_loader_log_msgs |= VK_DEBUG_REPORT_ERROR_BIT_EXT;
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001415 } else if (strncmp(env, "debug", len) == 0) {
1416 g_loader_debug |= LOADER_DEBUG_BIT;
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001417 g_loader_log_msgs |= VK_DEBUG_REPORT_DEBUG_BIT_EXT;
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001418 }
1419 }
1420
1421 if (!p)
1422 break;
1423
1424 env = p + 1;
1425 }
Jon Ashburn38a497f2016-01-04 14:01:38 -07001426
1427 loader_free_getenv(orig);
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001428}
1429
Jon Ashburn23d36b12016-02-02 17:47:28 -07001430void loader_initialize(void) {
Jon Ashburn6461ef22015-09-22 13:11:00 -06001431 // initialize mutexs
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001432 loader_platform_thread_create_mutex(&loader_lock);
Jon Ashburn6461ef22015-09-22 13:11:00 -06001433 loader_platform_thread_create_mutex(&loader_json_lock);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001434
1435 // initialize logging
1436 loader_debug_init();
Jon Ashburn87d6aa92015-08-28 15:19:27 -06001437
1438 // initial cJSON to use alloc callbacks
1439 cJSON_Hooks alloc_fns = {
Jon Ashburn23d36b12016-02-02 17:47:28 -07001440 .malloc_fn = loader_tls_heap_alloc, .free_fn = loader_tls_heap_free,
Jon Ashburn87d6aa92015-08-28 15:19:27 -06001441 };
1442 cJSON_InitHooks(&alloc_fns);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001443}
1444
Jon Ashburn2077e382015-06-29 11:25:34 -06001445struct loader_manifest_files {
1446 uint32_t count;
1447 char **filename_list;
1448};
1449
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06001450/**
Jon Ashburn2077e382015-06-29 11:25:34 -06001451 * Get next file or dirname given a string list or registry key path
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06001452 *
1453 * \returns
Jon Ashburn2077e382015-06-29 11:25:34 -06001454 * A pointer to first char in the next path.
1455 * The next path (or NULL) in the list is returned in next_path.
1456 * Note: input string is modified in some cases. PASS IN A COPY!
1457 */
Jon Ashburn23d36b12016-02-02 17:47:28 -07001458static char *loader_get_next_path(char *path) {
Jon Ashburn2077e382015-06-29 11:25:34 -06001459 uint32_t len;
1460 char *next;
1461
1462 if (path == NULL)
1463 return NULL;
1464 next = strchr(path, PATH_SEPERATOR);
1465 if (next == NULL) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07001466 len = (uint32_t)strlen(path);
Jon Ashburn2077e382015-06-29 11:25:34 -06001467 next = path + len;
Jon Ashburn23d36b12016-02-02 17:47:28 -07001468 } else {
Jon Ashburn2077e382015-06-29 11:25:34 -06001469 *next = '\0';
1470 next++;
1471 }
1472
1473 return next;
1474}
1475
1476/**
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001477 * Given a path which is absolute or relative, expand the path if relative or
1478 * leave the path unmodified if absolute. The base path to prepend to relative
1479 * paths is given in rel_base.
Jon Ashburn15315172015-07-07 15:06:25 -06001480 *
1481 * \returns
1482 * A string in out_fullpath of the full absolute path
Jon Ashburn15315172015-07-07 15:06:25 -06001483 */
Jon Ashburn23d36b12016-02-02 17:47:28 -07001484static void loader_expand_path(const char *path, const char *rel_base,
1485 size_t out_size, char *out_fullpath) {
Jon Ashburn15315172015-07-07 15:06:25 -06001486 if (loader_platform_is_path_absolute(path)) {
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001487 // do not prepend a base to an absolute path
1488 rel_base = "";
Jon Ashburn15315172015-07-07 15:06:25 -06001489 }
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001490
1491 loader_platform_combine_path(out_fullpath, out_size, rel_base, path, NULL);
Jon Ashburn15315172015-07-07 15:06:25 -06001492}
1493
1494/**
Jon Ashburn2077e382015-06-29 11:25:34 -06001495 * Given a filename (file) and a list of paths (dir), try to find an existing
1496 * file in the paths. If filename already is a path then no
1497 * searching in the given paths.
1498 *
1499 * \returns
1500 * A string in out_fullpath of either the full path or file.
Jon Ashburn2077e382015-06-29 11:25:34 -06001501 */
Jon Ashburn23d36b12016-02-02 17:47:28 -07001502static void loader_get_fullpath(const char *file, const char *dirs,
1503 size_t out_size, char *out_fullpath) {
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001504 if (!loader_platform_is_path(file) && *dirs) {
1505 char *dirs_copy, *dir, *next_dir;
1506
1507 dirs_copy = loader_stack_alloc(strlen(dirs) + 1);
1508 strcpy(dirs_copy, dirs);
1509
Jon Ashburn23d36b12016-02-02 17:47:28 -07001510 // find if file exists after prepending paths in given list
1511 for (dir = dirs_copy; *dir && (next_dir = loader_get_next_path(dir));
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001512 dir = next_dir) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07001513 loader_platform_combine_path(out_fullpath, out_size, dir, file,
1514 NULL);
Jon Ashburn2077e382015-06-29 11:25:34 -06001515 if (loader_platform_file_exists(out_fullpath)) {
1516 return;
1517 }
Jon Ashburn2077e382015-06-29 11:25:34 -06001518 }
1519 }
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001520
Jon Ashburn2077e382015-06-29 11:25:34 -06001521 snprintf(out_fullpath, out_size, "%s", file);
1522}
1523
1524/**
1525 * Read a JSON file into a buffer.
1526 *
1527 * \returns
1528 * A pointer to a cJSON object representing the JSON parse tree.
1529 * This returned buffer should be freed by caller.
1530 */
Jon Ashburn23d36b12016-02-02 17:47:28 -07001531static cJSON *loader_get_json(const struct loader_instance *inst,
1532 const char *filename) {
Jon Ashburn2077e382015-06-29 11:25:34 -06001533 FILE *file;
1534 char *json_buf;
1535 cJSON *json;
Mark Young93ecb1d2016-01-13 13:47:16 -07001536 size_t len;
Jon Ashburn23d36b12016-02-02 17:47:28 -07001537 file = fopen(filename, "rb");
Jon Ashburnaa4ea472015-08-27 08:30:50 -06001538 if (!file) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07001539 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
1540 "Couldn't open JSON file %s", filename);
Jon Ashburnaa4ea472015-08-27 08:30:50 -06001541 return NULL;
1542 }
Jon Ashburn2077e382015-06-29 11:25:34 -06001543 fseek(file, 0, SEEK_END);
1544 len = ftell(file);
1545 fseek(file, 0, SEEK_SET);
Jon Ashburn23d36b12016-02-02 17:47:28 -07001546 json_buf = (char *)loader_stack_alloc(len + 1);
Jon Ashburn2077e382015-06-29 11:25:34 -06001547 if (json_buf == NULL) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07001548 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
1549 "Out of memory can't get JSON file");
Jon Ashburn2077e382015-06-29 11:25:34 -06001550 fclose(file);
1551 return NULL;
1552 }
1553 if (fread(json_buf, sizeof(char), len, file) != len) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07001554 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
1555 "fread failed can't get JSON file");
Jon Ashburn2077e382015-06-29 11:25:34 -06001556 fclose(file);
1557 return NULL;
1558 }
1559 fclose(file);
1560 json_buf[len] = '\0';
1561
Jon Ashburn23d36b12016-02-02 17:47:28 -07001562 // parse text from file
Jon Ashburn2077e382015-06-29 11:25:34 -06001563 json = cJSON_Parse(json_buf);
1564 if (json == NULL)
Jon Ashburn23d36b12016-02-02 17:47:28 -07001565 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
1566 "Can't parse JSON file %s", filename);
Jon Ashburn2077e382015-06-29 11:25:34 -06001567 return json;
1568}
1569
1570/**
Jon Ashburn3d002332015-08-20 16:35:30 -06001571 * Do a deep copy of the loader_layer_properties structure.
1572 */
Jon Ashburn23d36b12016-02-02 17:47:28 -07001573static void loader_copy_layer_properties(const struct loader_instance *inst,
1574 struct loader_layer_properties *dst,
1575 struct loader_layer_properties *src) {
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001576 uint32_t cnt, i;
Jon Ashburn23d36b12016-02-02 17:47:28 -07001577 memcpy(dst, src, sizeof(*src));
1578 dst->instance_extension_list.list =
1579 loader_heap_alloc(inst, sizeof(VkExtensionProperties) *
1580 src->instance_extension_list.count,
1581 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
1582 dst->instance_extension_list.capacity =
1583 sizeof(VkExtensionProperties) * src->instance_extension_list.count;
Jon Ashburne39a4f82015-08-28 13:38:21 -06001584 memcpy(dst->instance_extension_list.list, src->instance_extension_list.list,
Jon Ashburn23d36b12016-02-02 17:47:28 -07001585 dst->instance_extension_list.capacity);
1586 dst->device_extension_list.list =
1587 loader_heap_alloc(inst, sizeof(struct loader_dev_ext_props) *
1588 src->device_extension_list.count,
1589 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001590
Jon Ashburn23d36b12016-02-02 17:47:28 -07001591 dst->device_extension_list.capacity =
1592 sizeof(struct loader_dev_ext_props) * src->device_extension_list.count;
Jon Ashburne39a4f82015-08-28 13:38:21 -06001593 memcpy(dst->device_extension_list.list, src->device_extension_list.list,
Jon Ashburn23d36b12016-02-02 17:47:28 -07001594 dst->device_extension_list.capacity);
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001595 if (src->device_extension_list.count > 0 &&
Jon Ashburn23d36b12016-02-02 17:47:28 -07001596 src->device_extension_list.list->entrypoint_count > 0) {
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001597 cnt = src->device_extension_list.list->entrypoint_count;
1598 dst->device_extension_list.list->entrypoints = loader_heap_alloc(
Jon Ashburn23d36b12016-02-02 17:47:28 -07001599 inst, sizeof(char *) * cnt, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001600 for (i = 0; i < cnt; i++) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07001601 dst->device_extension_list.list->entrypoints[i] = loader_heap_alloc(
1602 inst,
1603 strlen(src->device_extension_list.list->entrypoints[i]) + 1,
1604 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001605 strcpy(dst->device_extension_list.list->entrypoints[i],
1606 src->device_extension_list.list->entrypoints[i]);
1607 }
1608 }
Jon Ashburn3d002332015-08-20 16:35:30 -06001609}
1610
Jon Ashburn86a527a2016-02-10 20:59:26 -07001611static bool
1612loader_find_layer_name_list(const char *name,
1613 const struct loader_layer_list *layer_list) {
1614 if (!layer_list)
1615 return false;
1616 for (uint32_t j = 0; j < layer_list->count; j++)
1617 if (!strcmp(name, layer_list->list[j].info.layerName))
1618 return true;
1619 return false;
1620}
1621
1622static bool loader_find_layer_name(const char *name, uint32_t layer_count,
1623 const char **layer_list) {
1624 if (!layer_list)
1625 return false;
1626 for (uint32_t j = 0; j < layer_count; j++)
1627 if (!strcmp(name, layer_list[j]))
1628 return true;
1629 return false;
1630}
1631
1632static bool loader_find_layer_name_array(
1633 const char *name, uint32_t layer_count,
1634 const char layer_list[][VK_MAX_EXTENSION_NAME_SIZE]) {
1635 if (!layer_list)
1636 return false;
1637 for (uint32_t j = 0; j < layer_count; j++)
1638 if (!strcmp(name, layer_list[j]))
1639 return true;
1640 return false;
1641}
1642
1643/**
1644 * Searches through an array of layer names (ppp_layer_names) looking for a
1645 * layer key_name.
1646 * If not found then simply returns updating nothing.
1647 * Otherwise, it uses expand_count, expand_names adding them to layer names.
1648 * Any duplicate (pre-existing) exapand_names in layer names are removed.
1649 * Expand names are added to the back/end of the list of layer names.
1650 * @param inst
1651 * @param layer_count
1652 * @param ppp_layer_names
1653 */
1654void loader_expand_layer_names(
1655 const struct loader_instance *inst, const char *key_name,
1656 uint32_t expand_count,
1657 const char expand_names[][VK_MAX_EXTENSION_NAME_SIZE],
1658 uint32_t *layer_count, char ***ppp_layer_names) {
Jon Ashburn71483442016-02-11 18:59:43 -07001659 char **pp_layer_names, **pp_src_layers = *ppp_layer_names;
1660
Jon Ashburn86a527a2016-02-10 20:59:26 -07001661 if (!loader_find_layer_name(key_name, *layer_count,
Jon Ashburn71483442016-02-11 18:59:43 -07001662 (const char **)pp_src_layers))
Jon Ashburn86a527a2016-02-10 20:59:26 -07001663 return; // didn't find the key_name in the list
1664
Jon Ashburn71483442016-02-11 18:59:43 -07001665 // since the total number of layers may expand, allocate new memory for the
1666 // array of pointers
1667 pp_layer_names =
1668 loader_heap_alloc(inst, (expand_count + *layer_count) * sizeof(char *),
1669 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
1670
Jon Ashburn86a527a2016-02-10 20:59:26 -07001671 loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
1672 "Found meta layer %s, replacing with actual layer group",
1673 key_name);
1674 // In place removal of any expand_names found in layer_name (remove
1675 // duplicates)
1676 // Also remove the key_name
1677 uint32_t src_idx, dst_idx, cnt = *layer_count;
1678 for (src_idx = 0; src_idx < *layer_count; src_idx++) {
Jon Ashburn71483442016-02-11 18:59:43 -07001679 if (loader_find_layer_name_array(pp_src_layers[src_idx], expand_count,
Jon Ashburn86a527a2016-02-10 20:59:26 -07001680 expand_names)) {
Jon Ashburn71483442016-02-11 18:59:43 -07001681 pp_src_layers[src_idx] = NULL;
Jon Ashburn86a527a2016-02-10 20:59:26 -07001682 cnt--;
Jon Ashburn71483442016-02-11 18:59:43 -07001683 } else if (!strcmp(pp_src_layers[src_idx], key_name)) {
1684 pp_src_layers[src_idx] = NULL;
Jon Ashburn86a527a2016-02-10 20:59:26 -07001685 cnt--;
1686 }
Jon Ashburn71483442016-02-11 18:59:43 -07001687 pp_layer_names[src_idx] = pp_src_layers[src_idx];
Jon Ashburn86a527a2016-02-10 20:59:26 -07001688 }
1689 for (dst_idx = 0; dst_idx < cnt; dst_idx++) {
1690 if (pp_layer_names[dst_idx] == NULL) {
1691 src_idx = dst_idx + 1;
Jon Ashburn71483442016-02-11 18:59:43 -07001692 while (src_idx < *layer_count && pp_src_layers[src_idx] == NULL)
Jon Ashburn86a527a2016-02-10 20:59:26 -07001693 src_idx++;
Jon Ashburn71483442016-02-11 18:59:43 -07001694 if (src_idx < *layer_count && pp_src_layers[src_idx] != NULL)
1695 pp_layer_names[dst_idx] = pp_src_layers[src_idx];
Jon Ashburn86a527a2016-02-10 20:59:26 -07001696 }
1697 }
1698
1699 // Add the expand_names to layer_names
1700 src_idx = 0;
1701 for (dst_idx = cnt; dst_idx < cnt + expand_count; dst_idx++) {
1702 pp_layer_names[dst_idx] = (char *)&expand_names[src_idx++][0];
1703 }
1704 *layer_count = expand_count + cnt;
Jon Ashburn71483442016-02-11 18:59:43 -07001705 *ppp_layer_names = pp_layer_names;
Jon Ashburn86a527a2016-02-10 20:59:26 -07001706 return;
1707}
1708
1709/**
1710 * Restores the layer name list and count into the pCreatInfo structure.
1711 * If is_device == tru then pCreateInfo is a device structure else an instance
1712 * structure.
1713 * @param layer_count
1714 * @param layer_names
1715 * @param pCreateInfo
1716 */
Jon Ashburn71483442016-02-11 18:59:43 -07001717void loader_unexpand_dev_layer_names(const struct loader_instance *inst,
1718 uint32_t layer_count, char **layer_names,
1719 char **layer_ptr,
Jon Ashburn86a527a2016-02-10 20:59:26 -07001720 const VkDeviceCreateInfo *pCreateInfo) {
1721 uint32_t *p_cnt = (uint32_t *)&pCreateInfo->enabledLayerCount;
1722 *p_cnt = layer_count;
1723
Jon Ashburn71483442016-02-11 18:59:43 -07001724 char ***p_ptr = (char ***)&pCreateInfo->ppEnabledLayerNames;
1725 if ((char **)pCreateInfo->ppEnabledLayerNames != layer_ptr)
1726 loader_heap_free(inst, (void *)pCreateInfo->ppEnabledLayerNames);
1727 *p_ptr = layer_ptr;
Jon Ashburn86a527a2016-02-10 20:59:26 -07001728 for (uint32_t i = 0; i < layer_count; i++) {
1729 char **pp_str = (char **)&pCreateInfo->ppEnabledLayerNames[i];
1730 *pp_str = layer_names[i];
1731 }
1732}
1733
Jon Ashburn71483442016-02-11 18:59:43 -07001734void loader_unexpand_inst_layer_names(const struct loader_instance *inst,
1735 uint32_t layer_count, char **layer_names,
1736 char **layer_ptr,
Jon Ashburn86a527a2016-02-10 20:59:26 -07001737 const VkInstanceCreateInfo *pCreateInfo) {
1738 uint32_t *p_cnt = (uint32_t *)&pCreateInfo->enabledLayerCount;
1739 *p_cnt = layer_count;
1740
Jon Ashburn71483442016-02-11 18:59:43 -07001741 char ***p_ptr = (char ***)&pCreateInfo->ppEnabledLayerNames;
1742 if ((char **)pCreateInfo->ppEnabledLayerNames != layer_ptr)
1743 loader_heap_free(inst, (void *)pCreateInfo->ppEnabledLayerNames);
1744 *p_ptr = layer_ptr;
Jon Ashburn86a527a2016-02-10 20:59:26 -07001745 for (uint32_t i = 0; i < layer_count; i++) {
1746 char **pp_str = (char **)&pCreateInfo->ppEnabledLayerNames[i];
1747 *pp_str = layer_names[i];
1748 }
1749}
1750
1751/**
1752 * Searches through the existing instance and device layer lists looking for
1753 * the set of required layer names. If found then it adds a meta property to the
1754 * layer list.
1755 * Assumes the required layers are the same for both instance and device lists.
1756 * @param inst
1757 * @param layer_count number of layers in layer_names
1758 * @param layer_names array of required layer names
1759 * @param layer_instance_list
1760 * @param layer_device_list
1761 */
1762static void loader_add_layer_property_meta(
1763 const struct loader_instance *inst, uint32_t layer_count,
1764 const char layer_names[][VK_MAX_EXTENSION_NAME_SIZE],
1765 struct loader_layer_list *layer_instance_list,
1766 struct loader_layer_list *layer_device_list) {
1767 uint32_t i, j;
1768 bool found;
1769 struct loader_layer_list *layer_list;
1770
Jon Ashburn888c0502016-02-19 15:22:10 -07001771 if (0 == layer_count || (!layer_instance_list && !layer_device_list))
1772 return;
1773 if ((layer_instance_list && (layer_count > layer_instance_list->count)) &&
1774 (layer_device_list && (layer_count > layer_device_list->count)))
Jon Ashburn86a527a2016-02-10 20:59:26 -07001775 return;
1776
1777 for (j = 0; j < 2; j++) {
1778 if (j == 0)
1779 layer_list = layer_instance_list;
1780 else
1781 layer_list = layer_device_list;
1782 found = true;
Jon Ashburn888c0502016-02-19 15:22:10 -07001783 if (layer_list == NULL)
1784 continue;
Jon Ashburn86a527a2016-02-10 20:59:26 -07001785 for (i = 0; i < layer_count; i++) {
1786 if (loader_find_layer_name_list(layer_names[i], layer_list))
1787 continue;
1788 found = false;
1789 break;
1790 }
1791
1792 struct loader_layer_properties *props;
1793 if (found) {
1794 props = loader_get_next_layer_property(inst, layer_list);
1795 props->type = VK_LAYER_TYPE_META_EXPLICT;
1796 strncpy(props->info.description, "LunarG Standard Validation Layer",
1797 sizeof(props->info.description));
1798 props->info.implementationVersion = 1;
1799 strncpy(props->info.layerName, std_validation_str,
1800 sizeof(props->info.layerName));
1801 // TODO what about specVersion? for now insert loader's built
1802 // version
1803 props->info.specVersion = VK_API_VERSION;
1804 }
1805 }
1806}
1807
Jon Ashburn3d002332015-08-20 16:35:30 -06001808/**
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001809 * Given a cJSON struct (json) of the top level JSON object from layer manifest
1810 * file, add entry to the layer_list.
Jon Ashburne13ecc92015-08-03 17:19:30 -06001811 * Fill out the layer_properties in this list entry from the input cJSON object.
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001812 *
1813 * \returns
1814 * void
1815 * layer_list has a new entry and initialized accordingly.
1816 * If the json input object does not have all the required fields no entry
1817 * is added to the list.
1818 */
Jon Ashburn23d36b12016-02-02 17:47:28 -07001819static void
1820loader_add_layer_properties(const struct loader_instance *inst,
1821 struct loader_layer_list *layer_instance_list,
1822 struct loader_layer_list *layer_device_list,
1823 cJSON *json, bool is_implicit, char *filename) {
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001824 /* Fields in layer manifest file that are required:
1825 * (required) “file_format_version”
1826 * following are required in the "layer" object:
1827 * (required) "name"
1828 * (required) "type"
1829 * (required) “library_path”
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001830 * (required) “api_version”
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001831 * (required) “implementation_version”
1832 * (required) “description”
1833 * (required for implicit layers) “disable_environment”
1834 *
1835 * First get all required items and if any missing abort
1836 */
1837
1838 cJSON *item, *layer_node, *ext_item;
1839 char *temp;
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001840 char *name, *type, *library_path, *api_version;
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001841 char *implementation_version, *description;
Karl Schultz2558bd32016-02-24 14:39:39 -07001842 cJSON *disable_environment = NULL;
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001843 int i, j;
Jon Ashburn5c042ea2015-08-04 11:14:18 -06001844 VkExtensionProperties ext_prop;
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001845 item = cJSON_GetObjectItem(json, "file_format_version");
1846 if (item == NULL) {
1847 return;
1848 }
1849 char *file_vers = cJSON_PrintUnformatted(item);
Mark Lobodzinski510e20d2016-02-11 09:26:16 -07001850 loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
Jon Ashburn23d36b12016-02-02 17:47:28 -07001851 "Found manifest file %s, version %s", filename, file_vers);
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001852 if (strcmp(file_vers, "\"1.0.0\"") != 0)
Mark Lobodzinski510e20d2016-02-11 09:26:16 -07001853 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
Jon Ashburn23d36b12016-02-02 17:47:28 -07001854 "Unexpected manifest file version (expected 1.0.0), may "
1855 "cause errors");
Jon Ashburn87d6aa92015-08-28 15:19:27 -06001856 loader_tls_heap_free(file_vers);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001857
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001858 layer_node = cJSON_GetObjectItem(json, "layer");
1859 if (layer_node == NULL) {
Mark Lobodzinski510e20d2016-02-11 09:26:16 -07001860 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
Jon Ashburn23d36b12016-02-02 17:47:28 -07001861 "Can't find \"layer\" object in manifest JSON file, "
1862 "skipping this file");
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001863 return;
1864 }
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001865
1866 // loop through all "layer" objects in the file
1867 do {
Jon Ashburn23d36b12016-02-02 17:47:28 -07001868#define GET_JSON_OBJECT(node, var) \
1869 { \
1870 var = cJSON_GetObjectItem(node, #var); \
1871 if (var == NULL) { \
1872 layer_node = layer_node->next; \
Jon Ashburn1530c342016-02-26 13:14:27 -07001873 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, \
Jon Ashburn23d36b12016-02-02 17:47:28 -07001874 "Didn't find required layer object %s in manifest " \
1875 "JSON file, skipping this layer", \
1876 #var); \
1877 continue; \
1878 } \
1879 }
1880#define GET_JSON_ITEM(node, var) \
1881 { \
1882 item = cJSON_GetObjectItem(node, #var); \
1883 if (item == NULL) { \
1884 layer_node = layer_node->next; \
Jon Ashburn1530c342016-02-26 13:14:27 -07001885 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, \
Jon Ashburn23d36b12016-02-02 17:47:28 -07001886 "Didn't find required layer value %s in manifest JSON " \
1887 "file, skipping this layer", \
1888 #var); \
1889 continue; \
1890 } \
1891 temp = cJSON_Print(item); \
1892 temp[strlen(temp) - 1] = '\0'; \
1893 var = loader_stack_alloc(strlen(temp) + 1); \
1894 strcpy(var, &temp[1]); \
1895 loader_tls_heap_free(temp); \
1896 }
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001897 GET_JSON_ITEM(layer_node, name)
1898 GET_JSON_ITEM(layer_node, type)
1899 GET_JSON_ITEM(layer_node, library_path)
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001900 GET_JSON_ITEM(layer_node, api_version)
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001901 GET_JSON_ITEM(layer_node, implementation_version)
1902 GET_JSON_ITEM(layer_node, description)
1903 if (is_implicit) {
1904 GET_JSON_OBJECT(layer_node, disable_environment)
1905 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001906#undef GET_JSON_ITEM
1907#undef GET_JSON_OBJECT
1908
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001909 // add list entry
Jon Ashburn23d36b12016-02-02 17:47:28 -07001910 struct loader_layer_properties *props = NULL;
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001911 if (!strcmp(type, "DEVICE")) {
1912 if (layer_device_list == NULL) {
1913 layer_node = layer_node->next;
1914 continue;
1915 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06001916 props = loader_get_next_layer_property(inst, layer_device_list);
Jon Ashburn23d36b12016-02-02 17:47:28 -07001917 props->type = (is_implicit) ? VK_LAYER_TYPE_DEVICE_IMPLICIT
1918 : VK_LAYER_TYPE_DEVICE_EXPLICIT;
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001919 }
1920 if (!strcmp(type, "INSTANCE")) {
1921 if (layer_instance_list == NULL) {
1922 layer_node = layer_node->next;
1923 continue;
1924 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06001925 props = loader_get_next_layer_property(inst, layer_instance_list);
Jon Ashburn23d36b12016-02-02 17:47:28 -07001926 props->type = (is_implicit) ? VK_LAYER_TYPE_INSTANCE_IMPLICIT
1927 : VK_LAYER_TYPE_INSTANCE_EXPLICIT;
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001928 }
1929 if (!strcmp(type, "GLOBAL")) {
1930 if (layer_instance_list != NULL)
Jon Ashburn23d36b12016-02-02 17:47:28 -07001931 props =
1932 loader_get_next_layer_property(inst, layer_instance_list);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001933 else if (layer_device_list != NULL)
Jon Ashburne39a4f82015-08-28 13:38:21 -06001934 props = loader_get_next_layer_property(inst, layer_device_list);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001935 else {
1936 layer_node = layer_node->next;
1937 continue;
1938 }
Jon Ashburn23d36b12016-02-02 17:47:28 -07001939 props->type = (is_implicit) ? VK_LAYER_TYPE_GLOBAL_IMPLICIT
1940 : VK_LAYER_TYPE_GLOBAL_EXPLICIT;
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001941 }
Jon Ashburnb2ef1372015-07-16 17:19:31 -06001942
Jon Ashburn432d2762015-09-18 12:53:16 -06001943 if (props == NULL) {
1944 layer_node = layer_node->next;
1945 continue;
1946 }
1947
Jon Ashburn23d36b12016-02-02 17:47:28 -07001948 strncpy(props->info.layerName, name, sizeof(props->info.layerName));
1949 props->info.layerName[sizeof(props->info.layerName) - 1] = '\0';
Jon Ashburn15315172015-07-07 15:06:25 -06001950
Jon Ashburn3d002332015-08-20 16:35:30 -06001951 char *fullpath = props->lib_name;
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001952 char *rel_base;
Jon Ashburn6e08ebd2015-12-01 17:11:02 -07001953 if (loader_platform_is_path(library_path)) {
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001954 // a relative or absolute path
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001955 char *name_copy = loader_stack_alloc(strlen(filename) + 1);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001956 strcpy(name_copy, filename);
1957 rel_base = loader_platform_dirname(name_copy);
Jon Ashburn23d36b12016-02-02 17:47:28 -07001958 loader_expand_path(library_path, rel_base, MAX_STRING_SIZE,
1959 fullpath);
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001960 } else {
1961 // a filename which is assumed in a system directory
Jon Ashburn23d36b12016-02-02 17:47:28 -07001962 loader_get_fullpath(library_path, DEFAULT_VK_LAYERS_PATH,
1963 MAX_STRING_SIZE, fullpath);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001964 }
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001965 props->info.specVersion = loader_make_version(api_version);
1966 props->info.implementationVersion = atoi(implementation_version);
Jon Ashburn23d36b12016-02-02 17:47:28 -07001967 strncpy((char *)props->info.description, description,
1968 sizeof(props->info.description));
1969 props->info.description[sizeof(props->info.description) - 1] = '\0';
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001970 if (is_implicit) {
Jon Ashburn1c385f22016-02-12 14:46:41 -07001971 if (!disable_environment || !disable_environment->child) {
Jon Ashburn1530c342016-02-26 13:14:27 -07001972 loader_log(
1973 inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
1974 "Didn't find required layer child value disable_environment"
1975 "in manifest JSON file, skipping this layer");
Jon Ashburn1c385f22016-02-12 14:46:41 -07001976 layer_node = layer_node->next;
1977 continue;
1978 }
Jon Ashburn23d36b12016-02-02 17:47:28 -07001979 strncpy(props->disable_env_var.name,
1980 disable_environment->child->string,
1981 sizeof(props->disable_env_var.name));
1982 props->disable_env_var
1983 .name[sizeof(props->disable_env_var.name) - 1] = '\0';
1984 strncpy(props->disable_env_var.value,
1985 disable_environment->child->valuestring,
1986 sizeof(props->disable_env_var.value));
1987 props->disable_env_var
1988 .value[sizeof(props->disable_env_var.value) - 1] = '\0';
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001989 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001990
Jon Ashburn23d36b12016-02-02 17:47:28 -07001991/**
1992 * Now get all optional items and objects and put in list:
1993 * functions
1994 * instance_extensions
1995 * device_extensions
1996 * enable_environment (implicit layers only)
1997 */
1998#define GET_JSON_OBJECT(node, var) \
1999 { var = cJSON_GetObjectItem(node, #var); }
2000#define GET_JSON_ITEM(node, var) \
2001 { \
2002 item = cJSON_GetObjectItem(node, #var); \
2003 if (item != NULL) { \
2004 temp = cJSON_Print(item); \
2005 temp[strlen(temp) - 1] = '\0'; \
2006 var = loader_stack_alloc(strlen(temp) + 1); \
2007 strcpy(var, &temp[1]); \
2008 loader_tls_heap_free(temp); \
2009 } \
2010 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002011
Jon Ashburn23d36b12016-02-02 17:47:28 -07002012 cJSON *instance_extensions, *device_extensions, *functions,
2013 *enable_environment;
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07002014 cJSON *entrypoints;
2015 char *vkGetInstanceProcAddr, *vkGetDeviceProcAddr, *spec_version;
2016 char **entry_array;
2017 vkGetInstanceProcAddr = NULL;
2018 vkGetDeviceProcAddr = NULL;
2019 spec_version = NULL;
2020 entrypoints = NULL;
2021 entry_array = NULL;
2022 /**
2023 * functions
2024 * vkGetInstanceProcAddr
2025 * vkGetDeviceProcAddr
2026 */
Jon Ashburnfb8ac012015-08-12 16:39:32 -06002027 GET_JSON_OBJECT(layer_node, functions)
2028 if (functions != NULL) {
2029 GET_JSON_ITEM(functions, vkGetInstanceProcAddr)
2030 GET_JSON_ITEM(functions, vkGetDeviceProcAddr)
Jon Ashburn21c21ee2015-09-09 11:29:24 -06002031 if (vkGetInstanceProcAddr != NULL)
Jon Ashburn23d36b12016-02-02 17:47:28 -07002032 strncpy(props->functions.str_gipa, vkGetInstanceProcAddr,
2033 sizeof(props->functions.str_gipa));
2034 props->functions.str_gipa[sizeof(props->functions.str_gipa) - 1] =
2035 '\0';
Jon Ashburn21c21ee2015-09-09 11:29:24 -06002036 if (vkGetDeviceProcAddr != NULL)
Jon Ashburn23d36b12016-02-02 17:47:28 -07002037 strncpy(props->functions.str_gdpa, vkGetDeviceProcAddr,
2038 sizeof(props->functions.str_gdpa));
2039 props->functions.str_gdpa[sizeof(props->functions.str_gdpa) - 1] =
2040 '\0';
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002041 }
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07002042 /**
2043 * instance_extensions
2044 * array of
2045 * name
2046 * spec_version
2047 */
Jon Ashburnfb8ac012015-08-12 16:39:32 -06002048 GET_JSON_OBJECT(layer_node, instance_extensions)
2049 if (instance_extensions != NULL) {
2050 int count = cJSON_GetArraySize(instance_extensions);
2051 for (i = 0; i < count; i++) {
2052 ext_item = cJSON_GetArrayItem(instance_extensions, i);
2053 GET_JSON_ITEM(ext_item, name)
Jon Ashburnf2a944f2015-11-18 16:46:48 -07002054 GET_JSON_ITEM(ext_item, spec_version)
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07002055 if (name != NULL) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07002056 strncpy(ext_prop.extensionName, name,
2057 sizeof(ext_prop.extensionName));
2058 ext_prop.extensionName[sizeof(ext_prop.extensionName) - 1] =
2059 '\0';
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07002060 }
Jon Ashburnf2a944f2015-11-18 16:46:48 -07002061 ext_prop.specVersion = atoi(spec_version);
Jon Ashburn23d36b12016-02-02 17:47:28 -07002062 loader_add_to_ext_list(inst, &props->instance_extension_list, 1,
2063 &ext_prop);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06002064 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002065 }
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07002066 /**
2067 * device_extensions
2068 * array of
2069 * name
2070 * spec_version
2071 * entrypoints
2072 */
Jon Ashburnfb8ac012015-08-12 16:39:32 -06002073 GET_JSON_OBJECT(layer_node, device_extensions)
2074 if (device_extensions != NULL) {
2075 int count = cJSON_GetArraySize(device_extensions);
2076 for (i = 0; i < count; i++) {
2077 ext_item = cJSON_GetArrayItem(device_extensions, i);
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07002078 GET_JSON_ITEM(ext_item, name)
2079 GET_JSON_ITEM(ext_item, spec_version)
2080 if (name != NULL) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07002081 strncpy(ext_prop.extensionName, name,
2082 sizeof(ext_prop.extensionName));
2083 ext_prop.extensionName[sizeof(ext_prop.extensionName) - 1] =
2084 '\0';
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07002085 }
Jon Ashburnf2a944f2015-11-18 16:46:48 -07002086 ext_prop.specVersion = atoi(spec_version);
Jon Ashburn23d36b12016-02-02 17:47:28 -07002087 // entrypoints = cJSON_GetObjectItem(ext_item, "entrypoints");
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07002088 GET_JSON_OBJECT(ext_item, entrypoints)
2089 int entry_count;
Courtney Goeltzenleuchter89f8f362016-02-05 13:09:59 -07002090 if (entrypoints == NULL) {
Jon Ashburnf2b4e382016-02-10 20:50:19 -07002091 loader_add_to_dev_ext_list(inst,
2092 &props->device_extension_list,
Courtney Goeltzenleuchter89f8f362016-02-05 13:09:59 -07002093 &ext_prop, 0, NULL);
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07002094 continue;
Courtney Goeltzenleuchter89f8f362016-02-05 13:09:59 -07002095 }
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07002096 entry_count = cJSON_GetArraySize(entrypoints);
2097 if (entry_count)
Jon Ashburn23d36b12016-02-02 17:47:28 -07002098 entry_array = (char **)loader_stack_alloc(sizeof(char *) *
2099 entry_count);
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07002100 for (j = 0; j < entry_count; j++) {
2101 ext_item = cJSON_GetArrayItem(entrypoints, j);
2102 if (ext_item != NULL) {
2103 temp = cJSON_Print(ext_item);
2104 temp[strlen(temp) - 1] = '\0';
2105 entry_array[j] = loader_stack_alloc(strlen(temp) + 1);
2106 strcpy(entry_array[j], &temp[1]);
2107 loader_tls_heap_free(temp);
Jon Ashburn6e6a2162015-12-10 08:51:10 -07002108 }
2109 }
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07002110 loader_add_to_dev_ext_list(inst, &props->device_extension_list,
Jon Ashburn23d36b12016-02-02 17:47:28 -07002111 &ext_prop, entry_count, entry_array);
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07002112 }
2113 }
Jon Ashburnfb8ac012015-08-12 16:39:32 -06002114 if (is_implicit) {
2115 GET_JSON_OBJECT(layer_node, enable_environment)
Jon Ashburn075ce432015-12-17 17:38:24 -07002116
2117 // enable_environment is optional
2118 if (enable_environment) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07002119 strncpy(props->enable_env_var.name,
2120 enable_environment->child->string,
2121 sizeof(props->enable_env_var.name));
2122 props->enable_env_var
2123 .name[sizeof(props->enable_env_var.name) - 1] = '\0';
2124 strncpy(props->enable_env_var.value,
2125 enable_environment->child->valuestring,
2126 sizeof(props->enable_env_var.value));
2127 props->enable_env_var
2128 .value[sizeof(props->enable_env_var.value) - 1] = '\0';
Jon Ashburn075ce432015-12-17 17:38:24 -07002129 }
Jon Ashburnfb8ac012015-08-12 16:39:32 -06002130 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002131#undef GET_JSON_ITEM
2132#undef GET_JSON_OBJECT
Jon Ashburnfb8ac012015-08-12 16:39:32 -06002133 // for global layers need to add them to both device and instance list
2134 if (!strcmp(type, "GLOBAL")) {
2135 struct loader_layer_properties *dev_props;
2136 if (layer_instance_list == NULL || layer_device_list == NULL) {
2137 layer_node = layer_node->next;
2138 continue;
2139 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06002140 dev_props = loader_get_next_layer_property(inst, layer_device_list);
Jon Ashburn23d36b12016-02-02 17:47:28 -07002141 // copy into device layer list
Jon Ashburne39a4f82015-08-28 13:38:21 -06002142 loader_copy_layer_properties(inst, dev_props, props);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06002143 }
2144 layer_node = layer_node->next;
2145 } while (layer_node != NULL);
2146 return;
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002147}
2148
2149/**
Jon Ashburn2077e382015-06-29 11:25:34 -06002150 * Find the Vulkan library manifest files.
2151 *
Jon Ashburnb6822212016-02-16 15:34:16 -07002152 * This function scans the "location" or "env_override" directories/files
Jon Ashburn2077e382015-06-29 11:25:34 -06002153 * for a list of JSON manifest files. If env_override is non-NULL
2154 * and has a valid value. Then the location is ignored. Otherwise
2155 * location is used to look for manifest files. The location
2156 * is interpreted as Registry path on Windows and a directory path(s)
Jon Ashburnb6822212016-02-16 15:34:16 -07002157 * on Linux. "home_location" is an additional directory in the users home
2158 * directory to look at. It is exapanded into the dir path $HOME/home_location.
2159 * This "home_location" is only used on Linux.
Jon Ashburn2077e382015-06-29 11:25:34 -06002160 *
2161 * \returns
2162 * A string list of manifest files to be opened in out_files param.
2163 * List has a pointer to string for each manifest filename.
2164 * When done using the list in out_files, pointers should be freed.
Jon Ashburn23d36b12016-02-02 17:47:28 -07002165 * Location or override string lists can be either files or directories as
2166 *follows:
Jon Ashburnffad94d2015-06-30 14:46:22 -07002167 * | location | override
2168 * --------------------------------
2169 * Win ICD | files | files
2170 * Win Layer | files | dirs
2171 * Linux ICD | dirs | files
2172 * Linux Layer| dirs | dirs
Jon Ashburn2077e382015-06-29 11:25:34 -06002173 */
Jon Ashburne39a4f82015-08-28 13:38:21 -06002174static void loader_get_manifest_files(const struct loader_instance *inst,
Jon Ashburn23d36b12016-02-02 17:47:28 -07002175 const char *env_override, bool is_layer,
Jon Ashburnffad94d2015-06-30 14:46:22 -07002176 const char *location,
Jon Ashburnb6822212016-02-16 15:34:16 -07002177 const char *home_location,
Jon Ashburn23d36b12016-02-02 17:47:28 -07002178 struct loader_manifest_files *out_files) {
Jon Ashburn2077e382015-06-29 11:25:34 -06002179 char *override = NULL;
2180 char *loc;
2181 char *file, *next_file, *name;
2182 size_t alloced_count = 64;
2183 char full_path[2048];
2184 DIR *sysdir = NULL;
Jon Ashburnffad94d2015-06-30 14:46:22 -07002185 bool list_is_dirs = false;
Jon Ashburn2077e382015-06-29 11:25:34 -06002186 struct dirent *dent;
2187
2188 out_files->count = 0;
2189 out_files->filename_list = NULL;
2190
Jon Ashburn38a497f2016-01-04 14:01:38 -07002191 if (env_override != NULL && (override = loader_getenv(env_override))) {
Johannes van Waveren9bd805012015-10-28 11:45:00 -05002192#if !defined(_WIN32)
Jon Ashburn2077e382015-06-29 11:25:34 -06002193 if (geteuid() != getuid()) {
Jon Ashburnffad94d2015-06-30 14:46:22 -07002194 /* Don't allow setuid apps to use the env var: */
Jon Ashburn38a497f2016-01-04 14:01:38 -07002195 loader_free_getenv(override);
Jon Ashburn2077e382015-06-29 11:25:34 -06002196 override = NULL;
2197 }
2198#endif
2199 }
2200
Jon Ashburnb6822212016-02-16 15:34:16 -07002201#if !defined(_WIN32)
2202 if (location == NULL && home_location == NULL) {
2203#else
2204 home_location = NULL;
Jon Ashburn2077e382015-06-29 11:25:34 -06002205 if (location == NULL) {
Jon Ashburnb6822212016-02-16 15:34:16 -07002206#endif
Jon Ashburn23d36b12016-02-02 17:47:28 -07002207 loader_log(
2208 inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburnffad94d2015-06-30 14:46:22 -07002209 "Can't get manifest files with NULL location, env_override=%s",
2210 env_override);
Jon Ashburn2077e382015-06-29 11:25:34 -06002211 return;
2212 }
2213
Johannes van Waveren9bd805012015-10-28 11:45:00 -05002214#if defined(_WIN32)
Jon Ashburnffad94d2015-06-30 14:46:22 -07002215 list_is_dirs = (is_layer && override != NULL) ? true : false;
Johannes van Waveren9bd805012015-10-28 11:45:00 -05002216#else
2217 list_is_dirs = (override == NULL || is_layer) ? true : false;
Jon Ashburnffad94d2015-06-30 14:46:22 -07002218#endif
Jon Ashburn2077e382015-06-29 11:25:34 -06002219 // Make a copy of the input we are using so it is not modified
Jon Ashburnffad94d2015-06-30 14:46:22 -07002220 // Also handle getting the location(s) from registry on Windows
2221 if (override == NULL) {
Jon Ashburn3b78e462015-07-31 10:11:24 -06002222 loc = loader_stack_alloc(strlen(location) + 1);
Jon Ashburnffad94d2015-06-30 14:46:22 -07002223 if (loc == NULL) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07002224 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
2225 "Out of memory can't get manifest files");
Jon Ashburnffad94d2015-06-30 14:46:22 -07002226 return;
2227 }
2228 strcpy(loc, location);
Johannes van Waveren9bd805012015-10-28 11:45:00 -05002229#if defined(_WIN32)
Jon Ashburn480a50a2015-08-28 14:58:46 -07002230 loc = loader_get_registry_files(inst, loc);
Jon Ashburn24265ac2015-07-31 09:33:21 -06002231 if (loc == NULL) {
Mark Lobodzinski510e20d2016-02-11 09:26:16 -07002232 if (!is_layer) {
2233 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
2234 "Registry lookup failed can't get ICD manifest "
2235 "files, do you have a Vulkan driver installed");
2236 } else {
2237 // warning only for layers
2238 loader_log(
2239 inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
2240 "Registry lookup failed can't get layer manifest files");
2241 }
Jon Ashburn24265ac2015-07-31 09:33:21 -06002242 return;
2243 }
Jon Ashburnffad94d2015-06-30 14:46:22 -07002244#endif
Jon Ashburn23d36b12016-02-02 17:47:28 -07002245 } else {
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -06002246 loc = loader_stack_alloc(strlen(override) + 1);
Jon Ashburnffad94d2015-06-30 14:46:22 -07002247 if (loc == NULL) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07002248 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
2249 "Out of memory can't get manifest files");
Jon Ashburnffad94d2015-06-30 14:46:22 -07002250 return;
2251 }
2252 strcpy(loc, override);
Jon Ashburn38a497f2016-01-04 14:01:38 -07002253 loader_free_getenv(override);
Jon Ashburnffad94d2015-06-30 14:46:22 -07002254 }
Jon Ashburn2077e382015-06-29 11:25:34 -06002255
Liam Middlebrook9b14e892015-07-23 18:32:20 -07002256 // Print out the paths being searched if debugging is enabled
Jon Ashburn23d36b12016-02-02 17:47:28 -07002257 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
2258 "Searching the following paths for manifest files: %s\n", loc);
Liam Middlebrook9b14e892015-07-23 18:32:20 -07002259
Jon Ashburn2077e382015-06-29 11:25:34 -06002260 file = loc;
2261 while (*file) {
2262 next_file = loader_get_next_path(file);
Jon Ashburnffad94d2015-06-30 14:46:22 -07002263 if (list_is_dirs) {
Jon Ashburn2077e382015-06-29 11:25:34 -06002264 sysdir = opendir(file);
2265 name = NULL;
2266 if (sysdir) {
2267 dent = readdir(sysdir);
2268 if (dent == NULL)
2269 break;
2270 name = &(dent->d_name[0]);
2271 loader_get_fullpath(name, file, sizeof(full_path), full_path);
2272 name = full_path;
2273 }
Jon Ashburn23d36b12016-02-02 17:47:28 -07002274 } else {
Johannes van Waveren9bd805012015-10-28 11:45:00 -05002275#if defined(_WIN32)
2276 name = file;
2277#else
Jon Ashburnffad94d2015-06-30 14:46:22 -07002278 // only Linux has relative paths
Jon Ashburn2077e382015-06-29 11:25:34 -06002279 char *dir;
2280 // make a copy of location so it isn't modified
Jason Ekstrandcc7550e2015-10-10 08:33:37 -07002281 dir = loader_stack_alloc(strlen(loc) + 1);
Jon Ashburn2077e382015-06-29 11:25:34 -06002282 if (dir == NULL) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07002283 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
2284 "Out of memory can't get manifest files");
Jon Ashburn2077e382015-06-29 11:25:34 -06002285 return;
2286 }
Jason Ekstrandcc7550e2015-10-10 08:33:37 -07002287 strcpy(dir, loc);
Jon Ashburn2077e382015-06-29 11:25:34 -06002288
2289 loader_get_fullpath(file, dir, sizeof(full_path), full_path);
2290
2291 name = full_path;
Jon Ashburnffad94d2015-06-30 14:46:22 -07002292#endif
Jon Ashburn2077e382015-06-29 11:25:34 -06002293 }
2294 while (name) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07002295 /* Look for files ending with ".json" suffix */
2296 uint32_t nlen = (uint32_t)strlen(name);
2297 const char *suf = name + nlen - 5;
2298 if ((nlen > 5) && !strncmp(suf, ".json", 5)) {
2299 if (out_files->count == 0) {
2300 out_files->filename_list =
2301 loader_heap_alloc(inst, alloced_count * sizeof(char *),
2302 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
2303 } else if (out_files->count == alloced_count) {
2304 out_files->filename_list =
2305 loader_heap_realloc(inst, out_files->filename_list,
2306 alloced_count * sizeof(char *),
2307 alloced_count * sizeof(char *) * 2,
2308 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
2309 alloced_count *= 2;
Jon Ashburn2077e382015-06-29 11:25:34 -06002310 }
Jon Ashburn23d36b12016-02-02 17:47:28 -07002311 if (out_files->filename_list == NULL) {
2312 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
2313 "Out of memory can't alloc manifest file list");
2314 return;
Jon Ashburn2077e382015-06-29 11:25:34 -06002315 }
Jon Ashburn23d36b12016-02-02 17:47:28 -07002316 out_files->filename_list[out_files->count] = loader_heap_alloc(
2317 inst, strlen(name) + 1, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
2318 if (out_files->filename_list[out_files->count] == NULL) {
2319 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
2320 "Out of memory can't get manifest files");
2321 return;
2322 }
2323 strcpy(out_files->filename_list[out_files->count], name);
2324 out_files->count++;
2325 } else if (!list_is_dirs) {
2326 loader_log(
Mark Lobodzinski510e20d2016-02-11 09:26:16 -07002327 inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
Jon Ashburn23d36b12016-02-02 17:47:28 -07002328 "Skipping manifest file %s, file name must end in .json",
2329 name);
2330 }
2331 if (list_is_dirs) {
2332 dent = readdir(sysdir);
2333 if (dent == NULL)
Jon Ashburn2077e382015-06-29 11:25:34 -06002334 break;
Jon Ashburn23d36b12016-02-02 17:47:28 -07002335 name = &(dent->d_name[0]);
2336 loader_get_fullpath(name, file, sizeof(full_path), full_path);
2337 name = full_path;
2338 } else {
2339 break;
2340 }
Jon Ashburn2077e382015-06-29 11:25:34 -06002341 }
2342 if (sysdir)
2343 closedir(sysdir);
2344 file = next_file;
Jon Ashburn67e262e2016-02-18 12:45:39 -07002345#if !defined(_WIN32)
Jon Ashburn1530c342016-02-26 13:14:27 -07002346 if (home_location != NULL &&
2347 (next_file == NULL || *next_file == '\0') && override == NULL) {
Jon Ashburn67e262e2016-02-18 12:45:39 -07002348 char *home = secure_getenv("HOME");
2349 if (home != NULL) {
2350 size_t len;
2351 char *home_loc = loader_stack_alloc(strlen(home) + 2 +
2352 strlen(home_location));
2353 if (home_loc == NULL) {
2354 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburn1530c342016-02-26 13:14:27 -07002355 "Out of memory can't get manifest files");
Jon Ashburn67e262e2016-02-18 12:45:39 -07002356 return;
2357 }
2358 strcpy(home_loc, home);
2359 // Add directory separator if needed
2360 if (home_location[0] != DIRECTORY_SYMBOL) {
2361 len = strlen(home_loc);
2362 home_loc[len] = DIRECTORY_SYMBOL;
Jon Ashburn1530c342016-02-26 13:14:27 -07002363 home_loc[len + 1] = '\0';
Jon Ashburn67e262e2016-02-18 12:45:39 -07002364 }
2365 strcat(home_loc, home_location);
2366 file = home_loc;
2367 next_file = loader_get_next_path(file);
2368 home_location = NULL;
2369
Jon Ashburn1530c342016-02-26 13:14:27 -07002370 loader_log(
2371 inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
2372 "Searching the following paths for manifest files: %s\n",
2373 home_loc);
Jon Ashburn67e262e2016-02-18 12:45:39 -07002374 list_is_dirs = true;
2375 }
2376 }
2377#endif
Jon Ashburn2077e382015-06-29 11:25:34 -06002378 }
2379 return;
2380}
2381
Jon Ashburn23d36b12016-02-02 17:47:28 -07002382void loader_init_icd_lib_list() {}
Jon Ashburn8810c5f2015-08-18 18:04:47 -06002383
Jon Ashburn23d36b12016-02-02 17:47:28 -07002384void loader_destroy_icd_lib_list() {}
Jon Ashburn2077e382015-06-29 11:25:34 -06002385/**
2386 * Try to find the Vulkan ICD driver(s).
2387 *
2388 * This function scans the default system loader path(s) or path
2389 * specified by the \c VK_ICD_FILENAMES environment variable in
2390 * order to find loadable VK ICDs manifest files. From these
2391 * manifest files it finds the ICD libraries.
2392 *
2393 * \returns
Jon Ashburn8810c5f2015-08-18 18:04:47 -06002394 * a list of icds that were discovered
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06002395 */
Jon Ashburn23d36b12016-02-02 17:47:28 -07002396void loader_icd_scan(const struct loader_instance *inst,
2397 struct loader_icd_libs *icds) {
Jon Ashburn2077e382015-06-29 11:25:34 -06002398 char *file_str;
2399 struct loader_manifest_files manifest_files;
2400
Jon Ashburne39a4f82015-08-28 13:38:21 -06002401 loader_scanned_icd_init(inst, icds);
Jon Ashburn2077e382015-06-29 11:25:34 -06002402 // Get a list of manifest files for ICDs
Jon Ashburne39a4f82015-08-28 13:38:21 -06002403 loader_get_manifest_files(inst, "VK_ICD_FILENAMES", false,
Jon Ashburnb6822212016-02-16 15:34:16 -07002404 DEFAULT_VK_DRIVERS_INFO, HOME_VK_DRIVERS_INFO,
2405 &manifest_files);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002406 if (manifest_files.count == 0)
2407 return;
Jon Ashburn6461ef22015-09-22 13:11:00 -06002408 loader_platform_thread_lock_mutex(&loader_json_lock);
Jon Ashburn2077e382015-06-29 11:25:34 -06002409 for (uint32_t i = 0; i < manifest_files.count; i++) {
2410 file_str = manifest_files.filename_list[i];
2411 if (file_str == NULL)
2412 continue;
2413
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002414 cJSON *json;
Courtney Goeltzenleuchter73477392015-12-03 13:48:01 -07002415 json = loader_get_json(inst, file_str);
Jon Ashburnaa4ea472015-08-27 08:30:50 -06002416 if (!json)
2417 continue;
Jon Ashburn005617f2015-11-17 17:35:40 -07002418 cJSON *item, *itemICD;
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002419 item = cJSON_GetObjectItem(json, "file_format_version");
Jon Ashburn6461ef22015-09-22 13:11:00 -06002420 if (item == NULL) {
2421 loader_platform_thread_unlock_mutex(&loader_json_lock);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002422 return;
Jon Ashburn6461ef22015-09-22 13:11:00 -06002423 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002424 char *file_vers = cJSON_Print(item);
Mark Lobodzinski510e20d2016-02-11 09:26:16 -07002425 loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
Jon Ashburn23d36b12016-02-02 17:47:28 -07002426 "Found manifest file %s, version %s", file_str, file_vers);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002427 if (strcmp(file_vers, "\"1.0.0\"") != 0)
Mark Lobodzinski510e20d2016-02-11 09:26:16 -07002428 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
Jon Ashburn23d36b12016-02-02 17:47:28 -07002429 "Unexpected manifest file version (expected 1.0.0), may "
2430 "cause errors");
Jon Ashburn87d6aa92015-08-28 15:19:27 -06002431 loader_tls_heap_free(file_vers);
Jon Ashburn005617f2015-11-17 17:35:40 -07002432 itemICD = cJSON_GetObjectItem(json, "ICD");
2433 if (itemICD != NULL) {
2434 item = cJSON_GetObjectItem(itemICD, "library_path");
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002435 if (item != NULL) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07002436 char *temp = cJSON_Print(item);
Jon Ashburn86251302015-08-25 16:48:24 -06002437 if (!temp || strlen(temp) == 0) {
Mark Lobodzinski510e20d2016-02-11 09:26:16 -07002438 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
Jon Ashburn23d36b12016-02-02 17:47:28 -07002439 "Can't find \"library_path\" in ICD JSON file "
2440 "%s, skipping",
2441 file_str);
Jon Ashburn87d6aa92015-08-28 15:19:27 -06002442 loader_tls_heap_free(temp);
Jon Ashburne39a4f82015-08-28 13:38:21 -06002443 loader_heap_free(inst, file_str);
Jon Ashburn86251302015-08-25 16:48:24 -06002444 cJSON_Delete(json);
2445 continue;
Jon Ashburn2077e382015-06-29 11:25:34 -06002446 }
Jon Ashburn23d36b12016-02-02 17:47:28 -07002447 // strip out extra quotes
Jon Ashburn86251302015-08-25 16:48:24 -06002448 temp[strlen(temp) - 1] = '\0';
2449 char *library_path = loader_stack_alloc(strlen(temp) + 1);
2450 strcpy(library_path, &temp[1]);
Jon Ashburn87d6aa92015-08-28 15:19:27 -06002451 loader_tls_heap_free(temp);
Jon Ashburn86251302015-08-25 16:48:24 -06002452 if (!library_path || strlen(library_path) == 0) {
Mark Lobodzinski510e20d2016-02-11 09:26:16 -07002453 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
Jon Ashburn23d36b12016-02-02 17:47:28 -07002454 "Can't find \"library_path\" in ICD JSON file "
2455 "%s, skipping",
2456 file_str);
Jon Ashburne39a4f82015-08-28 13:38:21 -06002457 loader_heap_free(inst, file_str);
Jon Ashburn86251302015-08-25 16:48:24 -06002458 cJSON_Delete(json);
2459 continue;
2460 }
Daniel Dadap00b4aba2015-09-30 11:50:51 -05002461 char fullpath[MAX_STRING_SIZE];
Jon Ashburn86251302015-08-25 16:48:24 -06002462 // Print out the paths being searched if debugging is enabled
Jon Ashburn23d36b12016-02-02 17:47:28 -07002463 loader_log(
2464 inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
2465 "Searching for ICD drivers named %s default dir %s\n",
2466 library_path, DEFAULT_VK_DRIVERS_PATH);
Daniel Dadap00b4aba2015-09-30 11:50:51 -05002467 if (loader_platform_is_path(library_path)) {
Jon Ashburn86251302015-08-25 16:48:24 -06002468 // a relative or absolute path
Daniel Dadap00b4aba2015-09-30 11:50:51 -05002469 char *name_copy = loader_stack_alloc(strlen(file_str) + 1);
2470 char *rel_base;
Jon Ashburn86251302015-08-25 16:48:24 -06002471 strcpy(name_copy, file_str);
2472 rel_base = loader_platform_dirname(name_copy);
Jon Ashburn23d36b12016-02-02 17:47:28 -07002473 loader_expand_path(library_path, rel_base, sizeof(fullpath),
2474 fullpath);
Daniel Dadap00b4aba2015-09-30 11:50:51 -05002475 } else {
2476 // a filename which is assumed in a system directory
Jon Ashburn23d36b12016-02-02 17:47:28 -07002477 loader_get_fullpath(library_path, DEFAULT_VK_DRIVERS_PATH,
2478 sizeof(fullpath), fullpath);
Jon Ashburn86251302015-08-25 16:48:24 -06002479 }
Jon Ashburn005617f2015-11-17 17:35:40 -07002480
2481 uint32_t vers = 0;
2482 item = cJSON_GetObjectItem(itemICD, "api_version");
2483 if (item != NULL) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07002484 temp = cJSON_Print(item);
Jon Ashburn005617f2015-11-17 17:35:40 -07002485 vers = loader_make_version(temp);
2486 loader_tls_heap_free(temp);
2487 }
2488 loader_scanned_icd_add(inst, icds, fullpath, vers);
Jon Ashburn23d36b12016-02-02 17:47:28 -07002489 } else
Mark Lobodzinski510e20d2016-02-11 09:26:16 -07002490 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
Jon Ashburn23d36b12016-02-02 17:47:28 -07002491 "Can't find \"library_path\" object in ICD JSON "
2492 "file %s, skipping",
2493 file_str);
2494 } else
2495 loader_log(
Mark Lobodzinski510e20d2016-02-11 09:26:16 -07002496 inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
Jon Ashburn23d36b12016-02-02 17:47:28 -07002497 "Can't find \"ICD\" object in ICD JSON file %s, skipping",
2498 file_str);
Jon Ashburn2077e382015-06-29 11:25:34 -06002499
Jon Ashburne39a4f82015-08-28 13:38:21 -06002500 loader_heap_free(inst, file_str);
Jon Ashburn2077e382015-06-29 11:25:34 -06002501 cJSON_Delete(json);
2502 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06002503 loader_heap_free(inst, manifest_files.filename_list);
Jon Ashburn6461ef22015-09-22 13:11:00 -06002504 loader_platform_thread_unlock_mutex(&loader_json_lock);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08002505}
2506
Jon Ashburn23d36b12016-02-02 17:47:28 -07002507void loader_layer_scan(const struct loader_instance *inst,
Jon Ashburne39a4f82015-08-28 13:38:21 -06002508 struct loader_layer_list *instance_layers,
Jon Ashburn23d36b12016-02-02 17:47:28 -07002509 struct loader_layer_list *device_layers) {
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002510 char *file_str;
Jon Ashburn23d36b12016-02-02 17:47:28 -07002511 struct loader_manifest_files
2512 manifest_files[2]; // [0] = explicit, [1] = implicit
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002513 cJSON *json;
2514 uint32_t i;
Jon Ashburn075ce432015-12-17 17:38:24 -07002515 uint32_t implicit;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002516
Jon Ashburn86a527a2016-02-10 20:59:26 -07002517 // Get a list of manifest files for explicit layers
Jon Ashburn23d36b12016-02-02 17:47:28 -07002518 loader_get_manifest_files(inst, LAYERS_PATH_ENV, true,
Jon Ashburnb6822212016-02-16 15:34:16 -07002519 DEFAULT_VK_ELAYERS_INFO, HOME_VK_ELAYERS_INFO,
2520 &manifest_files[0]);
Jon Ashburn23d36b12016-02-02 17:47:28 -07002521 // Pass NULL for environment variable override - implicit layers are not
2522 // overridden by LAYERS_PATH_ENV
Jon Ashburnb1a03e02015-12-24 13:58:35 -07002523 loader_get_manifest_files(inst, NULL, true, DEFAULT_VK_ILAYERS_INFO,
Jon Ashburnb6822212016-02-16 15:34:16 -07002524 HOME_VK_ILAYERS_INFO, &manifest_files[1]);
Jon Ashburn075ce432015-12-17 17:38:24 -07002525 if (manifest_files[0].count == 0 && manifest_files[1].count == 0)
Courtney Goeltzenleuchter57985ce2014-12-01 09:29:42 -07002526 return;
Jon Ashburn90c6a0e2015-06-04 15:30:58 -06002527
Jon Ashburn23d36b12016-02-02 17:47:28 -07002528#if 0 // TODO
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002529 /**
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -06002530 * We need a list of the layer libraries, not just a list of
2531 * the layer properties (a layer library could expose more than
2532 * one layer property). This list of scanned layers would be
2533 * used to check for global and physicaldevice layer properties.
2534 */
2535 if (!loader_init_layer_library_list(&loader.scanned_layer_libraries)) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002536 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburne39a4f82015-08-28 13:38:21 -06002537 "Alloc for layer list failed: %s line: %d", __FILE__, __LINE__);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -06002538 return;
Jon Ashburn5ef20602015-07-02 09:40:15 -06002539 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002540#endif
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002541
Jon Ashburne13ecc92015-08-03 17:19:30 -06002542 /* cleanup any previously scanned libraries */
Jon Ashburne39a4f82015-08-28 13:38:21 -06002543 loader_delete_layer_properties(inst, instance_layers);
2544 loader_delete_layer_properties(inst, device_layers);
Jon Ashburnb2ef1372015-07-16 17:19:31 -06002545
Jon Ashburn6461ef22015-09-22 13:11:00 -06002546 loader_platform_thread_lock_mutex(&loader_json_lock);
Jon Ashburn075ce432015-12-17 17:38:24 -07002547 for (implicit = 0; implicit < 2; implicit++) {
2548 for (i = 0; i < manifest_files[implicit].count; i++) {
2549 file_str = manifest_files[implicit].filename_list[i];
2550 if (file_str == NULL)
2551 continue;
Courtney Goeltzenleuchtera9e4af42015-06-01 14:49:17 -06002552
Jon Ashburn075ce432015-12-17 17:38:24 -07002553 // parse file into JSON struct
2554 json = loader_get_json(inst, file_str);
2555 if (!json) {
2556 continue;
2557 }
2558
Jon Ashburn23d36b12016-02-02 17:47:28 -07002559 // TODO error if device layers expose instance_extensions
2560 // TODO error if instance layers expose device extensions
2561 loader_add_layer_properties(inst, instance_layers, device_layers,
2562 json, (implicit == 1), file_str);
Jon Ashburn075ce432015-12-17 17:38:24 -07002563
2564 loader_heap_free(inst, file_str);
2565 cJSON_Delete(json);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002566 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002567 }
Jon Ashburn075ce432015-12-17 17:38:24 -07002568 if (manifest_files[0].count != 0)
2569 loader_heap_free(inst, manifest_files[0].filename_list);
2570
2571 if (manifest_files[1].count != 0)
2572 loader_heap_free(inst, manifest_files[1].filename_list);
Jon Ashburn86a527a2016-02-10 20:59:26 -07002573
2574 // add a meta layer for validation if the validation layers are all present
2575 loader_add_layer_property_meta(
2576 inst, sizeof(std_validation_names) / sizeof(std_validation_names[0]),
2577 std_validation_names, instance_layers, device_layers);
2578
Jon Ashburn6461ef22015-09-22 13:11:00 -06002579 loader_platform_thread_unlock_mutex(&loader_json_lock);
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002580}
2581
Jon Ashburn23d36b12016-02-02 17:47:28 -07002582static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
2583loader_gpa_instance_internal(VkInstance inst, const char *pName) {
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002584 if (!strcmp(pName, "vkGetInstanceProcAddr"))
Jon Ashburn23d36b12016-02-02 17:47:28 -07002585 return (void *)loader_gpa_instance_internal;
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002586 if (!strcmp(pName, "vkCreateInstance"))
Jon Ashburn1530c342016-02-26 13:14:27 -07002587 return (void *)terminator_CreateInstance;
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002588 if (!strcmp(pName, "vkCreateDevice"))
Jon Ashburn1530c342016-02-26 13:14:27 -07002589 return (void *)terminator_CreateDevice;
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002590
Jon Ashburn27cd5842015-05-12 17:26:48 -06002591 // inst is not wrapped
2592 if (inst == VK_NULL_HANDLE) {
2593 return NULL;
2594 }
Jon Ashburn23d36b12016-02-02 17:47:28 -07002595 VkLayerInstanceDispatchTable *disp_table =
2596 *(VkLayerInstanceDispatchTable **)inst;
Jon Ashburn27cd5842015-05-12 17:26:48 -06002597 void *addr;
2598
2599 if (disp_table == NULL)
2600 return NULL;
2601
2602 addr = loader_lookup_instance_dispatch_table(disp_table, pName);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002603 if (addr) {
Jon Ashburn27cd5842015-05-12 17:26:48 -06002604 return addr;
Jon Ashburn3d526cb2015-04-13 18:10:06 -06002605 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002606
2607 if (disp_table->GetInstanceProcAddr == NULL) {
2608 return NULL;
2609 }
2610 return disp_table->GetInstanceProcAddr(inst, pName);
Jon Ashburn3d526cb2015-04-13 18:10:06 -06002611}
2612
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002613/**
2614 * Initialize device_ext dispatch table entry as follows:
2615 * If dev == NULL find all logical devices created within this instance and
2616 * init the entry (given by idx) in the ext dispatch table.
2617 * If dev != NULL only initialize the entry in the given dev's dispatch table.
Jon Ashburn23d36b12016-02-02 17:47:28 -07002618 * The initialization value is gotten by calling down the device chain with
2619 * GDPA.
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002620 * If GDPA returns NULL then don't initialize the dispatch table entry.
2621 */
2622static void loader_init_dispatch_dev_ext_entry(struct loader_instance *inst,
Jon Ashburn23d36b12016-02-02 17:47:28 -07002623 struct loader_device *dev,
2624 uint32_t idx,
2625 const char *funcName)
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002626
Jon Ashburn23d36b12016-02-02 17:47:28 -07002627{
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002628 void *gdpa_value;
2629 if (dev != NULL) {
2630 gdpa_value = dev->loader_dispatch.core_dispatch.GetDeviceProcAddr(
Jon Ashburn23d36b12016-02-02 17:47:28 -07002631 dev->device, funcName);
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002632 if (gdpa_value != NULL)
Jon Ashburn23d36b12016-02-02 17:47:28 -07002633 dev->loader_dispatch.ext_dispatch.DevExt[idx] =
2634 (PFN_vkDevExt)gdpa_value;
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002635 } else {
2636 for (uint32_t i = 0; i < inst->total_icd_count; i++) {
2637 struct loader_icd *icd = &inst->icds[i];
Karl Schultz2558bd32016-02-24 14:39:39 -07002638 struct loader_device *ldev = icd->logical_device_list;
2639 while (ldev) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07002640 gdpa_value =
Karl Schultz2558bd32016-02-24 14:39:39 -07002641 ldev->loader_dispatch.core_dispatch.GetDeviceProcAddr(
2642 ldev->device, funcName);
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002643 if (gdpa_value != NULL)
Karl Schultz2558bd32016-02-24 14:39:39 -07002644 ldev->loader_dispatch.ext_dispatch.DevExt[idx] =
Jon Ashburn23d36b12016-02-02 17:47:28 -07002645 (PFN_vkDevExt)gdpa_value;
Karl Schultz2558bd32016-02-24 14:39:39 -07002646 ldev = ldev->next;
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002647 }
2648 }
2649 }
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002650}
2651
2652/**
2653 * Find all dev extension in the hash table and initialize the dispatch table
2654 * for dev for each of those extension entrypoints found in hash table.
2655
2656 */
Jon Ashburn1530c342016-02-26 13:14:27 -07002657void loader_init_dispatch_dev_ext(struct loader_instance *inst,
2658 struct loader_device *dev) {
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002659 for (uint32_t i = 0; i < MAX_NUM_DEV_EXTS; i++) {
2660 if (inst->disp_hash[i].func_name != NULL)
2661 loader_init_dispatch_dev_ext_entry(inst, dev, i,
2662 inst->disp_hash[i].func_name);
2663 }
2664}
2665
2666static bool loader_check_icds_for_address(struct loader_instance *inst,
Jon Ashburn23d36b12016-02-02 17:47:28 -07002667 const char *funcName) {
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002668 struct loader_icd *icd;
2669 icd = inst->icds;
2670 while (icd) {
2671 if (icd->this_icd_lib->GetInstanceProcAddr(icd->instance, funcName))
2672 // this icd supports funcName
2673 return true;
2674 icd = icd->next;
2675 }
2676
2677 return false;
2678}
2679
Jon Ashburn23d36b12016-02-02 17:47:28 -07002680static void loader_free_dev_ext_table(struct loader_instance *inst) {
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002681 for (uint32_t i = 0; i < MAX_NUM_DEV_EXTS; i++) {
2682 loader_heap_free(inst, inst->disp_hash[i].func_name);
2683 loader_heap_free(inst, inst->disp_hash[i].list.index);
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002684 }
2685 memset(inst->disp_hash, 0, sizeof(inst->disp_hash));
2686}
2687
2688static bool loader_add_dev_ext_table(struct loader_instance *inst,
Jon Ashburn23d36b12016-02-02 17:47:28 -07002689 uint32_t *ptr_idx, const char *funcName) {
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002690 uint32_t i;
2691 uint32_t idx = *ptr_idx;
2692 struct loader_dispatch_hash_list *list = &inst->disp_hash[idx].list;
2693
2694 if (!inst->disp_hash[idx].func_name) {
2695 // no entry here at this idx, so use it
2696 assert(list->capacity == 0);
Jon Ashburn23d36b12016-02-02 17:47:28 -07002697 inst->disp_hash[idx].func_name = (char *)loader_heap_alloc(
2698 inst, strlen(funcName) + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002699 if (inst->disp_hash[idx].func_name == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002700 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburn23d36b12016-02-02 17:47:28 -07002701 "loader_add_dev_ext_table() can't allocate memory for "
2702 "func_name");
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002703 return false;
2704 }
2705 strncpy(inst->disp_hash[idx].func_name, funcName, strlen(funcName) + 1);
2706 return true;
2707 }
2708
2709 // check for enough capacity
2710 if (list->capacity == 0) {
2711 list->index = loader_heap_alloc(inst, 8 * sizeof(*(list->index)),
2712 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
2713 if (list->index == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002714 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002715 "loader_add_dev_ext_table() can't allocate list memory");
2716 return false;
2717 }
2718 list->capacity = 8 * sizeof(*(list->index));
2719 } else if (list->capacity < (list->count + 1) * sizeof(*(list->index))) {
2720 list->index = loader_heap_realloc(inst, list->index, list->capacity,
Jon Ashburn23d36b12016-02-02 17:47:28 -07002721 list->capacity * 2,
2722 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002723 if (list->index == NULL) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07002724 loader_log(
2725 inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
2726 "loader_add_dev_ext_table() can't reallocate list memory");
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002727 return false;
2728 }
2729 list->capacity *= 2;
2730 }
2731
Jon Ashburn23d36b12016-02-02 17:47:28 -07002732 // find an unused index in the hash table and use it
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002733 i = (idx + 1) % MAX_NUM_DEV_EXTS;
2734 do {
2735 if (!inst->disp_hash[i].func_name) {
2736 assert(inst->disp_hash[i].list.capacity == 0);
Jon Ashburn23d36b12016-02-02 17:47:28 -07002737 inst->disp_hash[i].func_name =
2738 (char *)loader_heap_alloc(inst, strlen(funcName) + 1,
2739 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002740 if (inst->disp_hash[i].func_name == NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002741 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburn23d36b12016-02-02 17:47:28 -07002742 "loader_add_dev_ext_table() can't rallocate "
2743 "func_name memory");
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002744 return false;
2745 }
Jon Ashburn23d36b12016-02-02 17:47:28 -07002746 strncpy(inst->disp_hash[i].func_name, funcName,
2747 strlen(funcName) + 1);
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002748 list->index[list->count] = i;
2749 list->count++;
2750 *ptr_idx = i;
2751 return true;
2752 }
2753 i = (i + 1) % MAX_NUM_DEV_EXTS;
2754 } while (i != idx);
2755
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002756 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburn23d36b12016-02-02 17:47:28 -07002757 "loader_add_dev_ext_table() couldn't insert into hash table; is "
2758 "it full?");
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002759 return false;
2760}
2761
2762static bool loader_name_in_dev_ext_table(struct loader_instance *inst,
Jon Ashburn23d36b12016-02-02 17:47:28 -07002763 uint32_t *idx, const char *funcName) {
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002764 uint32_t alt_idx;
Jon Ashburn23d36b12016-02-02 17:47:28 -07002765 if (inst->disp_hash[*idx].func_name &&
2766 !strcmp(inst->disp_hash[*idx].func_name, funcName))
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002767 return true;
2768
2769 // funcName wasn't at the primary spot in the hash table
2770 // search the list of secondary locations (shallow search, not deep search)
2771 for (uint32_t i = 0; i < inst->disp_hash[*idx].list.count; i++) {
2772 alt_idx = inst->disp_hash[*idx].list.index[i];
2773 if (!strcmp(inst->disp_hash[*idx].func_name, funcName)) {
2774 *idx = alt_idx;
2775 return true;
2776 }
2777 }
2778
2779 return false;
2780}
2781
2782/**
Jon Ashburn23d36b12016-02-02 17:47:28 -07002783 * This function returns generic trampoline code address for unknown entry
2784 * points.
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002785 * Presumably, these unknown entry points (as given by funcName) are device
2786 * extension entrypoints. A hash table is used to keep a list of unknown entry
2787 * points and their mapping to the device extension dispatch table
2788 * (struct loader_dev_ext_dispatch_table).
2789 * \returns
Jon Ashburn23d36b12016-02-02 17:47:28 -07002790 * For a given entry point string (funcName), if an existing mapping is found
2791 * the
2792 * trampoline address for that mapping is returned. Otherwise, this unknown
2793 * entry point
2794 * has not been seen yet. Next check if a layer or ICD supports it. If so then
2795 * a
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002796 * new entry in the hash table is initialized and that trampoline address for
2797 * the new entry is returned. Null is returned if the hash table is full or
2798 * if no discovered layer or ICD returns a non-NULL GetProcAddr for it.
2799 */
Jon Ashburn23d36b12016-02-02 17:47:28 -07002800void *loader_dev_ext_gpa(struct loader_instance *inst, const char *funcName) {
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002801 uint32_t idx;
2802 uint32_t seed = 0;
2803
2804 idx = murmurhash(funcName, strlen(funcName), seed) % MAX_NUM_DEV_EXTS;
2805
2806 if (loader_name_in_dev_ext_table(inst, &idx, funcName))
2807 // found funcName already in hash
2808 return loader_get_dev_ext_trampoline(idx);
2809
2810 // Check if funcName is supported in either ICDs or a layer library
2811 if (!loader_check_icds_for_address(inst, funcName)) {
2812 // TODO Add check in layer libraries for support of address
2813 // if support found in layers continue on
2814 return NULL;
2815 }
2816
2817 if (loader_add_dev_ext_table(inst, &idx, funcName)) {
2818 // successfully added new table entry
2819 // init any dev dispatch table entrys as needed
2820 loader_init_dispatch_dev_ext_entry(inst, NULL, idx, funcName);
2821 return loader_get_dev_ext_trampoline(idx);
2822 }
2823
2824 return NULL;
2825}
2826
Jon Ashburn23d36b12016-02-02 17:47:28 -07002827struct loader_instance *loader_get_instance(const VkInstance instance) {
Jon Ashburne0e64572015-09-30 12:56:42 -06002828 /* look up the loader_instance in our list by comparing dispatch tables, as
2829 * there is no guarantee the instance is still a loader_instance* after any
2830 * layers which wrap the instance object.
2831 */
2832 const VkLayerInstanceDispatchTable *disp;
2833 struct loader_instance *ptr_instance = NULL;
2834 disp = loader_get_instance_dispatch(instance);
Jon Ashburn23d36b12016-02-02 17:47:28 -07002835 for (struct loader_instance *inst = loader.instances; inst;
2836 inst = inst->next) {
Jon Ashburne0e64572015-09-30 12:56:42 -06002837 if (inst->disp == disp) {
2838 ptr_instance = inst;
2839 break;
2840 }
2841 }
2842 return ptr_instance;
2843}
2844
Jon Ashburn23d36b12016-02-02 17:47:28 -07002845static loader_platform_dl_handle
2846loader_add_layer_lib(const struct loader_instance *inst, const char *chain_type,
2847 struct loader_layer_properties *layer_prop) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002848 struct loader_lib_info *new_layer_lib_list, *my_lib;
Jon Ashburne39a4f82015-08-28 13:38:21 -06002849 size_t new_alloc_size;
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -06002850 /*
2851 * TODO: We can now track this information in the
2852 * scanned_layer_libraries list.
2853 */
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002854 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07002855 if (strcmp(loader.loaded_layer_lib_list[i].lib_name,
2856 layer_prop->lib_name) == 0) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002857 /* Have already loaded this library, just increment ref count */
2858 loader.loaded_layer_lib_list[i].ref_count++;
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002859 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
Jon Ashburn23d36b12016-02-02 17:47:28 -07002860 "%s Chain: Increment layer reference count for layer "
2861 "library %s",
Jon Ashburn3d002332015-08-20 16:35:30 -06002862 chain_type, layer_prop->lib_name);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002863 return loader.loaded_layer_lib_list[i].lib_handle;
2864 }
2865 }
2866
2867 /* Haven't seen this library so load it */
Jon Ashburne39a4f82015-08-28 13:38:21 -06002868 new_alloc_size = 0;
2869 if (loader.loaded_layer_lib_capacity == 0)
2870 new_alloc_size = 8 * sizeof(struct loader_lib_info);
Jon Ashburn23d36b12016-02-02 17:47:28 -07002871 else if (loader.loaded_layer_lib_capacity <=
2872 loader.loaded_layer_lib_count * sizeof(struct loader_lib_info))
Jon Ashburne39a4f82015-08-28 13:38:21 -06002873 new_alloc_size = loader.loaded_layer_lib_capacity * 2;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002874
Jon Ashburne39a4f82015-08-28 13:38:21 -06002875 if (new_alloc_size) {
2876 new_layer_lib_list = loader_heap_realloc(
Jon Ashburn23d36b12016-02-02 17:47:28 -07002877 inst, loader.loaded_layer_lib_list,
2878 loader.loaded_layer_lib_capacity, new_alloc_size,
2879 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburne39a4f82015-08-28 13:38:21 -06002880 if (!new_layer_lib_list) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07002881 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
2882 "loader: realloc failed in loader_add_layer_lib");
Jon Ashburne39a4f82015-08-28 13:38:21 -06002883 return NULL;
2884 }
2885 loader.loaded_layer_lib_capacity = new_alloc_size;
Courtney Goeltzenleuchter54ce81a2015-12-09 12:26:34 -07002886 loader.loaded_layer_lib_list = new_layer_lib_list;
Jon Ashburne39a4f82015-08-28 13:38:21 -06002887 } else
2888 new_layer_lib_list = loader.loaded_layer_lib_list;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002889 my_lib = &new_layer_lib_list[loader.loaded_layer_lib_count];
2890
Jon Ashburn3d002332015-08-20 16:35:30 -06002891 strncpy(my_lib->lib_name, layer_prop->lib_name, sizeof(my_lib->lib_name));
2892 my_lib->lib_name[sizeof(my_lib->lib_name) - 1] = '\0';
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002893 my_lib->ref_count = 0;
2894 my_lib->lib_handle = NULL;
2895
Jon Ashburn23d36b12016-02-02 17:47:28 -07002896 if ((my_lib->lib_handle = loader_platform_open_library(my_lib->lib_name)) ==
2897 NULL) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002898 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002899 loader_platform_open_library_error(my_lib->lib_name));
2900 return NULL;
2901 } else {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002902 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
Jon Ashburn23d36b12016-02-02 17:47:28 -07002903 "Chain: %s: Loading layer library %s", chain_type,
2904 layer_prop->lib_name);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002905 }
2906 loader.loaded_layer_lib_count++;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002907 my_lib->ref_count++;
2908
2909 return my_lib->lib_handle;
2910}
2911
Jon Ashburn23d36b12016-02-02 17:47:28 -07002912static void
2913loader_remove_layer_lib(struct loader_instance *inst,
2914 struct loader_layer_properties *layer_prop) {
Courtney Goeltzenleuchter80bfd0e2015-12-17 09:51:22 -07002915 uint32_t idx = loader.loaded_layer_lib_count;
Tony Barbourb5d2c942015-07-14 13:34:05 -06002916 struct loader_lib_info *new_layer_lib_list, *my_lib = NULL;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002917
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002918 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07002919 if (strcmp(loader.loaded_layer_lib_list[i].lib_name,
2920 layer_prop->lib_name) == 0) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002921 /* found matching library */
2922 idx = i;
2923 my_lib = &loader.loaded_layer_lib_list[i];
2924 break;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002925 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002926 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002927
Courtney Goeltzenleuchter80bfd0e2015-12-17 09:51:22 -07002928 if (idx == loader.loaded_layer_lib_count) {
Jon Ashburn6766ae92015-12-17 14:30:21 -07002929 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Courtney Goeltzenleuchter80bfd0e2015-12-17 09:51:22 -07002930 "Unable to unref library %s", layer_prop->lib_name);
2931 return;
2932 }
2933
Tony Barbourb5d2c942015-07-14 13:34:05 -06002934 if (my_lib) {
2935 my_lib->ref_count--;
2936 if (my_lib->ref_count > 0) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002937 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
Jon Ashburn23d36b12016-02-02 17:47:28 -07002938 "Decrement reference count for layer library %s",
2939 layer_prop->lib_name);
Tony Barbourb5d2c942015-07-14 13:34:05 -06002940 return;
2941 }
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07002942 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002943 loader_platform_close_library(my_lib->lib_handle);
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07002944 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
Jon Ashburn3d002332015-08-20 16:35:30 -06002945 "Unloading layer library %s", layer_prop->lib_name);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002946
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002947 /* Need to remove unused library from list */
Jon Ashburn23d36b12016-02-02 17:47:28 -07002948 new_layer_lib_list =
2949 loader_heap_alloc(inst, loader.loaded_layer_lib_capacity,
2950 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002951 if (!new_layer_lib_list) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07002952 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
2953 "loader: heap alloc failed loader_remove_layer_library");
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002954 return;
2955 }
2956
2957 if (idx > 0) {
2958 /* Copy records before idx */
2959 memcpy(new_layer_lib_list, &loader.loaded_layer_lib_list[0],
2960 sizeof(struct loader_lib_info) * idx);
2961 }
2962 if (idx < (loader.loaded_layer_lib_count - 1)) {
2963 /* Copy records after idx */
Jon Ashburn23d36b12016-02-02 17:47:28 -07002964 memcpy(&new_layer_lib_list[idx], &loader.loaded_layer_lib_list[idx + 1],
2965 sizeof(struct loader_lib_info) *
2966 (loader.loaded_layer_lib_count - idx - 1));
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002967 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002968
Jon Ashburne39a4f82015-08-28 13:38:21 -06002969 loader_heap_free(inst, loader.loaded_layer_lib_list);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002970 loader.loaded_layer_lib_count--;
2971 loader.loaded_layer_lib_list = new_layer_lib_list;
Jon Ashburnb8358052014-11-18 09:06:04 -07002972}
2973
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002974/**
2975 * Go through the search_list and find any layers which match type. If layer
2976 * type match is found in then add it to ext_list.
2977 */
Jon Ashburn23d36b12016-02-02 17:47:28 -07002978static void
2979loader_add_layer_implicit(const struct loader_instance *inst,
2980 const enum layer_type type,
2981 struct loader_layer_list *list,
2982 const struct loader_layer_list *search_list) {
Jon Ashburn075ce432015-12-17 17:38:24 -07002983 bool enable;
2984 char *env_value;
Jon Ashburn0c26e712015-07-02 16:10:32 -06002985 uint32_t i;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002986 for (i = 0; i < search_list->count; i++) {
2987 const struct loader_layer_properties *prop = &search_list->list[i];
Jon Ashburn0c26e712015-07-02 16:10:32 -06002988 if (prop->type & type) {
Jon Ashburn075ce432015-12-17 17:38:24 -07002989 /* Found an implicit layer, see if it should be enabled */
2990 enable = false;
2991
Jon Ashburn23d36b12016-02-02 17:47:28 -07002992 // if no enable_environment variable is specified, this implicit
2993 // layer
Jon Ashburn075ce432015-12-17 17:38:24 -07002994 // should always be enabled. Otherwise check if the variable is set
2995 if (prop->enable_env_var.name[0] == 0) {
2996 enable = true;
2997 } else {
Jon Ashburn38a497f2016-01-04 14:01:38 -07002998 env_value = loader_getenv(prop->enable_env_var.name);
Jon Ashburn075ce432015-12-17 17:38:24 -07002999 if (env_value && !strcmp(prop->enable_env_var.value, env_value))
3000 enable = true;
Jon Ashburn38a497f2016-01-04 14:01:38 -07003001 loader_free_getenv(env_value);
Jon Ashburn075ce432015-12-17 17:38:24 -07003002 }
3003
3004 // disable_environment has priority, i.e. if both enable and disable
Jon Ashburn23d36b12016-02-02 17:47:28 -07003005 // environment variables are set, the layer is disabled. Implicit
3006 // layers
Jon Ashburn075ce432015-12-17 17:38:24 -07003007 // are required to have a disable_environment variables
Jon Ashburn38a497f2016-01-04 14:01:38 -07003008 env_value = loader_getenv(prop->disable_env_var.name);
Jon Ashburn075ce432015-12-17 17:38:24 -07003009 if (env_value)
3010 enable = false;
Jon Ashburn38a497f2016-01-04 14:01:38 -07003011 loader_free_getenv(env_value);
Jon Ashburn075ce432015-12-17 17:38:24 -07003012
3013 if (enable)
3014 loader_add_to_layer_list(inst, list, 1, prop);
Jon Ashburn0c26e712015-07-02 16:10:32 -06003015 }
3016 }
Jon Ashburn0c26e712015-07-02 16:10:32 -06003017}
3018
3019/**
3020 * Get the layer name(s) from the env_name environment variable. If layer
Jon Ashburnbd332cc2015-07-07 10:27:45 -06003021 * is found in search_list then add it to layer_list. But only add it to
3022 * layer_list if type matches.
Jon Ashburn0c26e712015-07-02 16:10:32 -06003023 */
Jon Ashburn23d36b12016-02-02 17:47:28 -07003024static void loader_add_layer_env(const struct loader_instance *inst,
3025 const enum layer_type type,
3026 const char *env_name,
3027 struct loader_layer_list *layer_list,
3028 const struct loader_layer_list *search_list) {
Ian Elliott4470a302015-02-17 10:33:47 -07003029 char *layerEnv;
Jon Ashburneb6d5682015-07-02 14:10:53 -06003030 char *next, *name;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06003031
Jon Ashburn38a497f2016-01-04 14:01:38 -07003032 layerEnv = loader_getenv(env_name);
Ian Elliott4470a302015-02-17 10:33:47 -07003033 if (layerEnv == NULL) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003034 return;
Ian Elliott4470a302015-02-17 10:33:47 -07003035 }
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -06003036 name = loader_stack_alloc(strlen(layerEnv) + 1);
Jon Ashburneb6d5682015-07-02 14:10:53 -06003037 if (name == NULL) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003038 return;
Ian Elliott4470a302015-02-17 10:33:47 -07003039 }
Jon Ashburneb6d5682015-07-02 14:10:53 -06003040 strcpy(name, layerEnv);
Jon Ashburnd38bfb12014-10-14 19:15:22 -06003041
Jon Ashburn38a497f2016-01-04 14:01:38 -07003042 loader_free_getenv(layerEnv);
3043
Jon Ashburn23d36b12016-02-02 17:47:28 -07003044 while (name && *name) {
Jon Ashburneb6d5682015-07-02 14:10:53 -06003045 next = loader_get_next_path(name);
Jon Ashburn71483442016-02-11 18:59:43 -07003046 if (!strcmp(std_validation_str, name)) {
3047 /* add meta list of layers
3048 don't attempt to remove duplicate layers already added by app or
3049 env var
3050 */
3051 loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
3052 "Expanding meta layer %s found in environment variable",
3053 std_validation_str);
3054 for (uint32_t i = 0; i < sizeof(std_validation_names) /
3055 sizeof(std_validation_names[0]);
3056 i++) {
3057 loader_find_layer_name_add_list(inst, std_validation_names[i],
3058 type, search_list, layer_list);
3059 }
3060 } else {
3061 loader_find_layer_name_add_list(inst, name, type, search_list,
3062 layer_list);
3063 }
Jon Ashburneb6d5682015-07-02 14:10:53 -06003064 name = next;
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07003065 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -06003066
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003067 return;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06003068}
3069
Jon Ashburn23d36b12016-02-02 17:47:28 -07003070void loader_deactivate_instance_layers(struct loader_instance *instance) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003071 /* Create instance chain of enabled layers */
Courtney Goeltzenleuchter7d0023c2015-06-08 15:09:22 -06003072 for (uint32_t i = 0; i < instance->activated_layer_list.count; i++) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07003073 struct loader_layer_properties *layer_prop =
3074 &instance->activated_layer_list.list[i];
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003075
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003076 loader_remove_layer_lib(instance, layer_prop);
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06003077 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06003078 loader_destroy_layer_list(instance, &instance->activated_layer_list);
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06003079}
3080
Jon Ashburn23d36b12016-02-02 17:47:28 -07003081VkResult
3082loader_enable_instance_layers(struct loader_instance *inst,
3083 const VkInstanceCreateInfo *pCreateInfo,
3084 const struct loader_layer_list *instance_layers) {
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06003085 VkResult err;
3086
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06003087 assert(inst && "Cannot have null instance");
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003088
Jon Ashburne39a4f82015-08-28 13:38:21 -06003089 if (!loader_init_layer_list(inst, &inst->activated_layer_list)) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07003090 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
3091 "Failed to alloc Instance activated layer list");
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06003092 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburnbd6c4882015-07-02 12:59:25 -06003093 }
3094
Jon Ashburn0c26e712015-07-02 16:10:32 -06003095 /* Add any implicit layers first */
Jon Ashburn23d36b12016-02-02 17:47:28 -07003096 loader_add_layer_implicit(inst, VK_LAYER_TYPE_INSTANCE_IMPLICIT,
3097 &inst->activated_layer_list, instance_layers);
Jon Ashburn0c26e712015-07-02 16:10:32 -06003098
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06003099 /* Add any layers specified via environment variable next */
Jon Ashburn23d36b12016-02-02 17:47:28 -07003100 loader_add_layer_env(inst, VK_LAYER_TYPE_INSTANCE_EXPLICIT,
3101 "VK_INSTANCE_LAYERS", &inst->activated_layer_list,
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003102 instance_layers);
Jon Ashburnbd6c4882015-07-02 12:59:25 -06003103
3104 /* Add layers specified by the application */
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06003105 err = loader_add_layer_names_to_list(
Jon Ashburn23d36b12016-02-02 17:47:28 -07003106 inst, &inst->activated_layer_list, pCreateInfo->enabledLayerCount,
3107 pCreateInfo->ppEnabledLayerNames, instance_layers);
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06003108
3109 return err;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003110}
3111
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003112/*
3113 * Given the list of layers to activate in the loader_instance
3114 * structure. This function will add a VkLayerInstanceCreateInfo
3115 * structure to the VkInstanceCreateInfo.pNext pointer.
3116 * Each activated layer will have it's own VkLayerInstanceLink
3117 * structure that tells the layer what Get*ProcAddr to call to
3118 * get function pointers to the next layer down.
3119 * Once the chain info has been created this function will
3120 * execute the CreateInstance call chain. Each layer will
3121 * then have an opportunity in it's CreateInstance function
3122 * to setup it's dispatch table when the lower layer returns
3123 * successfully.
3124 * Each layer can wrap or not-wrap the returned VkInstance object
3125 * as it sees fit.
3126 * The instance chain is terminated by a loader function
3127 * that will call CreateInstance on all available ICD's and
3128 * cache those VkInstance objects for future use.
3129 */
3130VkResult loader_create_instance_chain(const VkInstanceCreateInfo *pCreateInfo,
Jon Ashburn23d36b12016-02-02 17:47:28 -07003131 const VkAllocationCallbacks *pAllocator,
Jon Ashburn373c1802016-01-20 08:08:25 -07003132 struct loader_instance *inst,
Jon Ashburn6e0a2132016-02-03 12:37:30 -07003133 VkInstance *created_instance) {
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003134 uint32_t activated_layers = 0;
3135 VkLayerInstanceCreateInfo chain_info;
3136 VkLayerInstanceLink *layer_instance_link_info = NULL;
3137 VkInstanceCreateInfo loader_create_info;
3138 VkResult res;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003139
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003140 PFN_vkGetInstanceProcAddr nextGIPA = loader_gpa_instance_internal;
3141 PFN_vkGetInstanceProcAddr fpGIPA = loader_gpa_instance_internal;
Jon Ashburn27cd5842015-05-12 17:26:48 -06003142
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003143 memcpy(&loader_create_info, pCreateInfo, sizeof(VkInstanceCreateInfo));
Jon Ashburn27cd5842015-05-12 17:26:48 -06003144
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003145 if (inst->activated_layer_list.count > 0) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003146
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003147 chain_info.u.pLayerInfo = NULL;
3148 chain_info.pNext = pCreateInfo->pNext;
3149 chain_info.sType = VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO;
3150 chain_info.function = VK_LAYER_LINK_INFO;
3151 loader_create_info.pNext = &chain_info;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003152
Jon Ashburn23d36b12016-02-02 17:47:28 -07003153 layer_instance_link_info = loader_stack_alloc(
3154 sizeof(VkLayerInstanceLink) * inst->activated_layer_list.count);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003155 if (!layer_instance_link_info) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07003156 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
3157 "Failed to alloc Instance objects for layer");
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003158 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburn27cd5842015-05-12 17:26:48 -06003159 }
3160
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003161 /* Create instance chain of enabled layers */
3162 for (int32_t i = inst->activated_layer_list.count - 1; i >= 0; i--) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07003163 struct loader_layer_properties *layer_prop =
3164 &inst->activated_layer_list.list[i];
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003165 loader_platform_dl_handle lib_handle;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003166
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003167 lib_handle = loader_add_layer_lib(inst, "instance", layer_prop);
3168 if (!lib_handle)
Courtney Goeltzenleuchter524b7e32016-01-14 16:06:06 -07003169 continue;
Jon Ashburn23d36b12016-02-02 17:47:28 -07003170 if ((fpGIPA = layer_prop->functions.get_instance_proc_addr) ==
3171 NULL) {
3172 if (layer_prop->functions.str_gipa == NULL ||
3173 strlen(layer_prop->functions.str_gipa) == 0) {
3174 fpGIPA = (PFN_vkGetInstanceProcAddr)
3175 loader_platform_get_proc_address(
3176 lib_handle, "vkGetInstanceProcAddr");
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003177 layer_prop->functions.get_instance_proc_addr = fpGIPA;
3178 } else
Jon Ashburn23d36b12016-02-02 17:47:28 -07003179 fpGIPA = (PFN_vkGetInstanceProcAddr)
3180 loader_platform_get_proc_address(
3181 lib_handle, layer_prop->functions.str_gipa);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003182 if (!fpGIPA) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07003183 loader_log(
3184 inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
3185 "Failed to find vkGetInstanceProcAddr in layer %s",
3186 layer_prop->lib_name);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003187 continue;
3188 }
3189 }
3190
Jon Ashburn23d36b12016-02-02 17:47:28 -07003191 layer_instance_link_info[activated_layers].pNext =
3192 chain_info.u.pLayerInfo;
3193 layer_instance_link_info[activated_layers]
3194 .pfnNextGetInstanceProcAddr = nextGIPA;
3195 chain_info.u.pLayerInfo =
3196 &layer_instance_link_info[activated_layers];
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003197 nextGIPA = fpGIPA;
3198
Mark Lobodzinski510e20d2016-02-11 09:26:16 -07003199 loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
Jon Ashburn23d36b12016-02-02 17:47:28 -07003200 "Insert instance layer %s (%s)",
3201 layer_prop->info.layerName, layer_prop->lib_name);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003202
3203 activated_layers++;
3204 }
Jon Ashburn27cd5842015-05-12 17:26:48 -06003205 }
3206
Jon Ashburn23d36b12016-02-02 17:47:28 -07003207 PFN_vkCreateInstance fpCreateInstance =
Jon Ashburn6e0a2132016-02-03 12:37:30 -07003208 (PFN_vkCreateInstance)nextGIPA(*created_instance, "vkCreateInstance");
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003209 if (fpCreateInstance) {
3210 VkLayerInstanceCreateInfo instance_create_info;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003211
Jon Ashburn23d36b12016-02-02 17:47:28 -07003212 instance_create_info.sType =
3213 VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO;
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003214 instance_create_info.function = VK_LAYER_INSTANCE_INFO;
3215
3216 instance_create_info.u.instanceInfo.instance_info = inst;
Jon Ashburn23d36b12016-02-02 17:47:28 -07003217 instance_create_info.u.instanceInfo.pfnNextGetInstanceProcAddr =
3218 nextGIPA;
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003219
3220 instance_create_info.pNext = loader_create_info.pNext;
3221 loader_create_info.pNext = &instance_create_info;
3222
Jon Ashburnf2b4e382016-02-10 20:50:19 -07003223 res =
3224 fpCreateInstance(&loader_create_info, pAllocator, created_instance);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003225 } else {
3226 // Couldn't find CreateInstance function!
3227 res = VK_ERROR_INITIALIZATION_FAILED;
3228 }
3229
3230 if (res != VK_SUCCESS) {
3231 // TODO: Need to clean up here
3232 } else {
Jon Ashburn23d36b12016-02-02 17:47:28 -07003233 loader_init_instance_core_dispatch_table(inst->disp, nextGIPA,
Jon Ashburn6e0a2132016-02-03 12:37:30 -07003234 *created_instance);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003235 }
3236
3237 return res;
Jon Ashburn27cd5842015-05-12 17:26:48 -06003238}
3239
Jon Ashburn23d36b12016-02-02 17:47:28 -07003240void loader_activate_instance_layer_extensions(struct loader_instance *inst,
3241 VkInstance created_inst) {
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003242
Jon Ashburn23d36b12016-02-02 17:47:28 -07003243 loader_init_instance_extension_dispatch_table(
3244 inst->disp, inst->disp->GetInstanceProcAddr, created_inst);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003245}
3246
Jon Ashburn1530c342016-02-26 13:14:27 -07003247VkResult
Jon Ashburn23d36b12016-02-02 17:47:28 -07003248loader_enable_device_layers(const struct loader_instance *inst,
3249 struct loader_icd *icd,
3250 struct loader_layer_list *activated_layer_list,
3251 const VkDeviceCreateInfo *pCreateInfo,
3252 const struct loader_layer_list *device_layers)
Jon Ashburnb82c1852015-08-11 14:49:54 -06003253
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003254{
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06003255 VkResult err;
3256
Jon Ashburn471f44c2016-01-13 12:51:43 -07003257 assert(activated_layer_list && "Cannot have null output layer list");
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003258
Jon Ashburn23d36b12016-02-02 17:47:28 -07003259 if (activated_layer_list->list == NULL ||
3260 activated_layer_list->capacity == 0) {
Jon Ashburn471f44c2016-01-13 12:51:43 -07003261 loader_init_layer_list(inst, activated_layer_list);
Jon Ashburnbd6c4882015-07-02 12:59:25 -06003262 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003263
Jon Ashburn471f44c2016-01-13 12:51:43 -07003264 if (activated_layer_list->list == NULL) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07003265 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
3266 "Failed to alloc device activated layer list");
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06003267 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburnbd6c4882015-07-02 12:59:25 -06003268 }
3269
Jon Ashburn0c26e712015-07-02 16:10:32 -06003270 /* Add any implicit layers first */
Jon Ashburn23d36b12016-02-02 17:47:28 -07003271 loader_add_layer_implicit(inst, VK_LAYER_TYPE_DEVICE_IMPLICIT,
3272 activated_layer_list, device_layers);
Jon Ashburn0c26e712015-07-02 16:10:32 -06003273
3274 /* Add any layers specified via environment variable next */
Jon Ashburn23d36b12016-02-02 17:47:28 -07003275 loader_add_layer_env(inst, VK_LAYER_TYPE_DEVICE_EXPLICIT,
3276 "VK_DEVICE_LAYERS", activated_layer_list,
3277 device_layers);
Jon Ashburnbd6c4882015-07-02 12:59:25 -06003278
3279 /* Add layers specified by the application */
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06003280 err = loader_add_layer_names_to_list(
Jon Ashburn23d36b12016-02-02 17:47:28 -07003281 inst, activated_layer_list, pCreateInfo->enabledLayerCount,
3282 pCreateInfo->ppEnabledLayerNames, device_layers);
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06003283
3284 return err;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003285}
3286
Jon Ashburn014438f2016-03-01 19:51:07 -07003287VkResult loader_create_device_chain(const struct loader_physical_device *pd,
Jon Ashburn23d36b12016-02-02 17:47:28 -07003288 const VkDeviceCreateInfo *pCreateInfo,
3289 const VkAllocationCallbacks *pAllocator,
Jon Ashburn014438f2016-03-01 19:51:07 -07003290 const struct loader_instance *inst,
Jon Ashburn23d36b12016-02-02 17:47:28 -07003291 struct loader_icd *icd,
3292 struct loader_device *dev) {
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003293 uint32_t activated_layers = 0;
3294 VkLayerDeviceLink *layer_device_link_info;
3295 VkLayerDeviceCreateInfo chain_info;
3296 VkLayerDeviceCreateInfo device_info;
3297 VkDeviceCreateInfo loader_create_info;
3298 VkResult res;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003299
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003300 PFN_vkGetDeviceProcAddr fpGDPA, nextGDPA = icd->GetDeviceProcAddr;
3301 PFN_vkGetInstanceProcAddr fpGIPA, nextGIPA = loader_gpa_instance_internal;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003302
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003303 memcpy(&loader_create_info, pCreateInfo, sizeof(VkDeviceCreateInfo));
3304
3305 chain_info.sType = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO;
3306 chain_info.function = VK_LAYER_LINK_INFO;
3307 chain_info.u.pLayerInfo = NULL;
3308 chain_info.pNext = pCreateInfo->pNext;
3309
Jon Ashburn23d36b12016-02-02 17:47:28 -07003310 layer_device_link_info = loader_stack_alloc(
3311 sizeof(VkLayerDeviceLink) * dev->activated_layer_list.count);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003312 if (!layer_device_link_info) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07003313 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
3314 "Failed to alloc Device objects for layer");
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003315 return VK_ERROR_OUT_OF_HOST_MEMORY;
David Pinedoa0a8a242015-06-24 15:29:18 -06003316 }
Jon Ashburn94e70492015-06-10 10:13:10 -06003317
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003318 /*
3319 * This structure is used by loader_create_device_terminator
3320 * so that it can intialize the device dispatch table pointer
3321 * in the device object returned by the ICD. Without this
3322 * structure the code wouldn't know where the loader's device_info
3323 * structure is located.
3324 */
3325 device_info.sType = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO;
3326 device_info.function = VK_LAYER_DEVICE_INFO;
3327 device_info.pNext = &chain_info;
3328 device_info.u.deviceInfo.device_info = dev;
Jon Ashburn23d36b12016-02-02 17:47:28 -07003329 device_info.u.deviceInfo.pfnNextGetInstanceProcAddr =
3330 icd->this_icd_lib->GetInstanceProcAddr;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003331
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003332 loader_create_info.pNext = &device_info;
Jon Ashburn94e70492015-06-10 10:13:10 -06003333
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003334 if (dev->activated_layer_list.count > 0) {
3335 /* Create instance chain of enabled layers */
3336 for (int32_t i = dev->activated_layer_list.count - 1; i >= 0; i--) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07003337 struct loader_layer_properties *layer_prop =
3338 &dev->activated_layer_list.list[i];
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003339 loader_platform_dl_handle lib_handle;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003340
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003341 lib_handle = loader_add_layer_lib(inst, "device", layer_prop);
3342 if (!lib_handle)
Courtney Goeltzenleuchter524b7e32016-01-14 16:06:06 -07003343 continue;
Jon Ashburn23d36b12016-02-02 17:47:28 -07003344 if ((fpGIPA = layer_prop->functions.get_instance_proc_addr) ==
3345 NULL) {
3346 if (layer_prop->functions.str_gipa == NULL ||
3347 strlen(layer_prop->functions.str_gipa) == 0) {
3348 fpGIPA = (PFN_vkGetInstanceProcAddr)
3349 loader_platform_get_proc_address(
3350 lib_handle, "vkGetInstanceProcAddr");
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003351 layer_prop->functions.get_instance_proc_addr = fpGIPA;
3352 } else
Jon Ashburn23d36b12016-02-02 17:47:28 -07003353 fpGIPA = (PFN_vkGetInstanceProcAddr)
3354 loader_platform_get_proc_address(
3355 lib_handle, layer_prop->functions.str_gipa);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003356 if (!fpGIPA) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07003357 loader_log(
3358 inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
3359 "Failed to find vkGetInstanceProcAddr in layer %s",
3360 layer_prop->lib_name);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003361 continue;
3362 }
Jon Ashburn21c21ee2015-09-09 11:29:24 -06003363 }
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003364 if ((fpGDPA = layer_prop->functions.get_device_proc_addr) == NULL) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07003365 if (layer_prop->functions.str_gdpa == NULL ||
3366 strlen(layer_prop->functions.str_gdpa) == 0) {
3367 fpGDPA = (PFN_vkGetDeviceProcAddr)
3368 loader_platform_get_proc_address(lib_handle,
3369 "vkGetDeviceProcAddr");
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003370 layer_prop->functions.get_device_proc_addr = fpGDPA;
3371 } else
Jon Ashburn23d36b12016-02-02 17:47:28 -07003372 fpGDPA = (PFN_vkGetDeviceProcAddr)
3373 loader_platform_get_proc_address(
3374 lib_handle, layer_prop->functions.str_gdpa);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003375 if (!fpGDPA) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07003376 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
3377 "Failed to find vkGetDeviceProcAddr in layer %s",
3378 layer_prop->lib_name);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003379 continue;
3380 }
3381 }
3382
Jon Ashburn23d36b12016-02-02 17:47:28 -07003383 layer_device_link_info[activated_layers].pNext =
3384 chain_info.u.pLayerInfo;
3385 layer_device_link_info[activated_layers]
3386 .pfnNextGetInstanceProcAddr = nextGIPA;
3387 layer_device_link_info[activated_layers].pfnNextGetDeviceProcAddr =
3388 nextGDPA;
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003389 chain_info.u.pLayerInfo = &layer_device_link_info[activated_layers];
3390 nextGIPA = fpGIPA;
3391 nextGDPA = fpGDPA;
3392
Mark Lobodzinski510e20d2016-02-11 09:26:16 -07003393 loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003394 "Insert device layer %s (%s)",
Jon Ashburn23d36b12016-02-02 17:47:28 -07003395 layer_prop->info.layerName, layer_prop->lib_name);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003396
3397 activated_layers++;
Jon Ashburn94e70492015-06-10 10:13:10 -06003398 }
Jon Ashburn94e70492015-06-10 10:13:10 -06003399 }
3400
Jon Ashburn23d36b12016-02-02 17:47:28 -07003401 PFN_vkCreateDevice fpCreateDevice =
3402 (PFN_vkCreateDevice)nextGIPA((VkInstance)inst, "vkCreateDevice");
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003403 if (fpCreateDevice) {
Jon Ashburn014438f2016-03-01 19:51:07 -07003404 res = fpCreateDevice(pd->phys_dev, &loader_create_info, pAllocator,
Jon Ashburn23d36b12016-02-02 17:47:28 -07003405 &dev->device);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003406 } else {
3407 // Couldn't find CreateDevice function!
3408 return VK_ERROR_INITIALIZATION_FAILED;
3409 }
Jon Ashburn94e70492015-06-10 10:13:10 -06003410
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003411 /* Initialize device dispatch table */
Jon Ashburn23d36b12016-02-02 17:47:28 -07003412 loader_init_device_dispatch_table(&dev->loader_dispatch, nextGDPA,
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003413 dev->device);
3414
3415 return res;
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06003416}
Jon Ashburnd38bfb12014-10-14 19:15:22 -06003417
Mark Lobodzinskie9f09ef2016-02-02 18:53:34 -07003418VkResult loader_validate_layers(const struct loader_instance *inst,
3419 const uint32_t layer_count,
Jon Ashburn23d36b12016-02-02 17:47:28 -07003420 const char *const *ppEnabledLayerNames,
3421 const struct loader_layer_list *list) {
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06003422 struct loader_layer_properties *prop;
3423
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003424 for (uint32_t i = 0; i < layer_count; i++) {
Jon Ashburnf2b4e382016-02-10 20:50:19 -07003425 VkStringErrorFlags result =
3426 vk_string_validate(MaxLoaderStringLength, ppEnabledLayerNames[i]);
Mark Lobodzinskie9f09ef2016-02-02 18:53:34 -07003427 if (result != VK_STRING_ERROR_NONE) {
3428 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburnf2b4e382016-02-10 20:50:19 -07003429 "Loader: Device ppEnabledLayerNames contains string "
3430 "that is too long or is badly formed");
Mark Lobodzinskie9f09ef2016-02-02 18:53:34 -07003431 return VK_ERROR_LAYER_NOT_PRESENT;
3432 }
3433
Jon Ashburn23d36b12016-02-02 17:47:28 -07003434 prop = loader_get_layer_property(ppEnabledLayerNames[i], list);
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06003435 if (!prop) {
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06003436 return VK_ERROR_LAYER_NOT_PRESENT;
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06003437 }
3438 }
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06003439 return VK_SUCCESS;
3440}
3441
3442VkResult loader_validate_instance_extensions(
Mark Lobodzinskie9f09ef2016-02-02 18:53:34 -07003443 const struct loader_instance *inst,
Jon Ashburn23d36b12016-02-02 17:47:28 -07003444 const struct loader_extension_list *icd_exts,
3445 const struct loader_layer_list *instance_layer,
3446 const VkInstanceCreateInfo *pCreateInfo) {
Mark Lobodzinskie9f09ef2016-02-02 18:53:34 -07003447
Jon Ashburn5c042ea2015-08-04 11:14:18 -06003448 VkExtensionProperties *extension_prop;
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003449 struct loader_layer_properties *layer_prop;
3450
Jon Ashburnf19916e2016-01-11 13:12:43 -07003451 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
Jon Ashburnf2b4e382016-02-10 20:50:19 -07003452 VkStringErrorFlags result = vk_string_validate(
3453 MaxLoaderStringLength, pCreateInfo->ppEnabledExtensionNames[i]);
Mark Lobodzinskie9f09ef2016-02-02 18:53:34 -07003454 if (result != VK_STRING_ERROR_NONE) {
3455 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburnf2b4e382016-02-10 20:50:19 -07003456 "Loader: Instance ppEnabledExtensionNames contains "
3457 "string that is too long or is badly formed");
Mark Lobodzinskie9f09ef2016-02-02 18:53:34 -07003458 return VK_ERROR_EXTENSION_NOT_PRESENT;
3459 }
3460
Jon Ashburn23d36b12016-02-02 17:47:28 -07003461 extension_prop = get_extension_property(
3462 pCreateInfo->ppEnabledExtensionNames[i], icd_exts);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003463
3464 if (extension_prop) {
3465 continue;
3466 }
3467
3468 extension_prop = NULL;
3469
3470 /* Not in global list, search layer extension lists */
Jon Ashburnf19916e2016-01-11 13:12:43 -07003471 for (uint32_t j = 0; j < pCreateInfo->enabledLayerCount; j++) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07003472 layer_prop = loader_get_layer_property(
3473 pCreateInfo->ppEnabledLayerNames[i], instance_layer);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003474 if (!layer_prop) {
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003475 /* Should NOT get here, loader_validate_layers
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003476 * should have already filtered this case out.
3477 */
3478 continue;
3479 }
3480
Jon Ashburn23d36b12016-02-02 17:47:28 -07003481 extension_prop =
3482 get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
3483 &layer_prop->instance_extension_list);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003484 if (extension_prop) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07003485 /* Found the extension in one of the layers enabled by the app.
3486 */
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003487 break;
3488 }
3489 }
3490
3491 if (!extension_prop) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07003492 /* Didn't find extension name in any of the global layers, error out
3493 */
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06003494 return VK_ERROR_EXTENSION_NOT_PRESENT;
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003495 }
3496 }
3497 return VK_SUCCESS;
3498}
3499
3500VkResult loader_validate_device_extensions(
Jon Ashburn23d36b12016-02-02 17:47:28 -07003501 struct loader_physical_device *phys_dev,
3502 const struct loader_layer_list *activated_device_layers,
Jon Ashburn014438f2016-03-01 19:51:07 -07003503 const struct loader_extension_list *icd_exts,
Jon Ashburn23d36b12016-02-02 17:47:28 -07003504 const VkDeviceCreateInfo *pCreateInfo) {
Jon Ashburn5c042ea2015-08-04 11:14:18 -06003505 VkExtensionProperties *extension_prop;
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003506 struct loader_layer_properties *layer_prop;
3507
Jon Ashburnf19916e2016-01-11 13:12:43 -07003508 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
Mark Lobodzinskie9f09ef2016-02-02 18:53:34 -07003509
Jon Ashburnf2b4e382016-02-10 20:50:19 -07003510 VkStringErrorFlags result = vk_string_validate(
3511 MaxLoaderStringLength, pCreateInfo->ppEnabledExtensionNames[i]);
Mark Lobodzinskie9f09ef2016-02-02 18:53:34 -07003512 if (result != VK_STRING_ERROR_NONE) {
Jon Ashburn014438f2016-03-01 19:51:07 -07003513 loader_log(phys_dev->this_icd->this_instance,
3514 VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
3515 "Loader: Device ppEnabledExtensionNames contains "
3516 "string that is too long or is badly formed");
Mark Lobodzinskie9f09ef2016-02-02 18:53:34 -07003517 return VK_ERROR_EXTENSION_NOT_PRESENT;
3518 }
3519
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003520 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i];
Jon Ashburn014438f2016-03-01 19:51:07 -07003521 extension_prop = get_extension_property(extension_name, icd_exts);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003522
3523 if (extension_prop) {
3524 continue;
3525 }
3526
Jon Ashburn471f44c2016-01-13 12:51:43 -07003527 /* Not in global list, search activated layer extension lists */
3528 for (uint32_t j = 0; j < activated_device_layers->count; j++) {
3529 layer_prop = &activated_device_layers->list[j];
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003530
Jon Ashburn23d36b12016-02-02 17:47:28 -07003531 extension_prop = get_dev_extension_property(
3532 extension_name, &layer_prop->device_extension_list);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003533 if (extension_prop) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07003534 /* Found the extension in one of the layers enabled by the app.
3535 */
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003536 break;
3537 }
3538 }
3539
3540 if (!extension_prop) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07003541 /* Didn't find extension name in any of the device layers, error out
3542 */
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06003543 return VK_ERROR_EXTENSION_NOT_PRESENT;
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003544 }
3545 }
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06003546 return VK_SUCCESS;
3547}
3548
Jon Ashburn1530c342016-02-26 13:14:27 -07003549/**
3550 * Terminator functions for the Instance chain
3551 * All named terminator_<Vulakn API name>
3552 */
Jon Ashburn23d36b12016-02-02 17:47:28 -07003553VKAPI_ATTR VkResult VKAPI_CALL
Jon Ashburn1530c342016-02-26 13:14:27 -07003554terminator_CreateInstance(const VkInstanceCreateInfo *pCreateInfo,
3555 const VkAllocationCallbacks *pAllocator,
3556 VkInstance *pInstance) {
Jon Ashburn46888392015-01-29 15:45:51 -07003557 struct loader_icd *icd;
Jon Ashburn5c042ea2015-08-04 11:14:18 -06003558 VkExtensionProperties *prop;
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003559 char **filtered_extension_names = NULL;
3560 VkInstanceCreateInfo icd_create_info;
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06003561 VkResult res = VK_SUCCESS;
Jon Ashburn7e18de02015-11-19 09:29:51 -07003562 bool success = false;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003563
Jon Ashburn23d36b12016-02-02 17:47:28 -07003564 VkLayerInstanceCreateInfo *chain_info =
3565 (VkLayerInstanceCreateInfo *)pCreateInfo->pNext;
3566 while (
3567 chain_info &&
3568 !(chain_info->sType == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO &&
3569 chain_info->function == VK_LAYER_INSTANCE_INFO)) {
3570 chain_info = (VkLayerInstanceCreateInfo *)chain_info->pNext;
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003571 }
3572 assert(chain_info != NULL);
3573
Jon Ashburn23d36b12016-02-02 17:47:28 -07003574 struct loader_instance *ptr_instance =
3575 (struct loader_instance *)chain_info->u.instanceInfo.instance_info;
Tony Barbour3c78ff42015-12-04 13:24:39 -07003576 memcpy(&icd_create_info, pCreateInfo, sizeof(icd_create_info));
3577
Jon Ashburnf19916e2016-01-11 13:12:43 -07003578 icd_create_info.enabledLayerCount = 0;
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003579 icd_create_info.ppEnabledLayerNames = NULL;
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003580
Courtney Goeltzenleuchterb39ccd52016-01-15 14:15:00 -07003581 // strip off the VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO entries
3582 icd_create_info.pNext = loader_strip_create_extensions(pCreateInfo->pNext);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003583
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003584 /*
3585 * NOTE: Need to filter the extensions to only those
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003586 * supported by the ICD.
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003587 * No ICD will advertise support for layers. An ICD
3588 * library could support a layer, but it would be
3589 * independent of the actual ICD, just in the same library.
3590 */
Jon Ashburn23d36b12016-02-02 17:47:28 -07003591 filtered_extension_names =
3592 loader_stack_alloc(pCreateInfo->enabledExtensionCount * sizeof(char *));
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003593 if (!filtered_extension_names) {
3594 return VK_ERROR_OUT_OF_HOST_MEMORY;
3595 }
Jon Ashburn23d36b12016-02-02 17:47:28 -07003596 icd_create_info.ppEnabledExtensionNames =
3597 (const char *const *)filtered_extension_names;
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003598
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003599 for (uint32_t i = 0; i < ptr_instance->icd_libs.count; i++) {
3600 icd = loader_icd_add(ptr_instance, &ptr_instance->icd_libs.list[i]);
Jon Ashburn46888392015-01-29 15:45:51 -07003601 if (icd) {
Jon Ashburnf19916e2016-01-11 13:12:43 -07003602 icd_create_info.enabledExtensionCount = 0;
Courtney Goeltzenleuchter36eeb742015-12-21 16:41:47 -07003603 struct loader_extension_list icd_exts;
3604
Jon Ashburn23d36b12016-02-02 17:47:28 -07003605 loader_log(ptr_instance, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
3606 "Build ICD instance extension list");
3607 // traverse scanned icd list adding non-duplicate extensions to the
3608 // list
3609 loader_init_generic_list(ptr_instance,
3610 (struct loader_generic_list *)&icd_exts,
Courtney Goeltzenleuchter36eeb742015-12-21 16:41:47 -07003611 sizeof(VkExtensionProperties));
Jon Ashburn23d36b12016-02-02 17:47:28 -07003612 loader_add_instance_extensions(
3613 ptr_instance,
3614 icd->this_icd_lib->EnumerateInstanceExtensionProperties,
3615 icd->this_icd_lib->lib_name, &icd_exts);
Courtney Goeltzenleuchter36eeb742015-12-21 16:41:47 -07003616
Karl Schultz2558bd32016-02-24 14:39:39 -07003617 for (uint32_t j = 0; j < pCreateInfo->enabledExtensionCount; j++) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07003618 prop = get_extension_property(
Karl Schultz2558bd32016-02-24 14:39:39 -07003619 pCreateInfo->ppEnabledExtensionNames[j], &icd_exts);
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003620 if (prop) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07003621 filtered_extension_names[icd_create_info
3622 .enabledExtensionCount] =
Karl Schultz2558bd32016-02-24 14:39:39 -07003623 (char *)pCreateInfo->ppEnabledExtensionNames[j];
Jon Ashburnf19916e2016-01-11 13:12:43 -07003624 icd_create_info.enabledExtensionCount++;
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003625 }
3626 }
3627
Jon Ashburn23d36b12016-02-02 17:47:28 -07003628 loader_destroy_generic_list(
3629 ptr_instance, (struct loader_generic_list *)&icd_exts);
Courtney Goeltzenleuchter36eeb742015-12-21 16:41:47 -07003630
Jon Ashburn23d36b12016-02-02 17:47:28 -07003631 res = ptr_instance->icd_libs.list[i].CreateInstance(
3632 &icd_create_info, pAllocator, &(icd->instance));
Jon Ashburn7e18de02015-11-19 09:29:51 -07003633 if (res == VK_SUCCESS)
3634 success = loader_icd_init_entrys(
Jon Ashburn23d36b12016-02-02 17:47:28 -07003635 icd, icd->instance,
3636 ptr_instance->icd_libs.list[i].GetInstanceProcAddr);
Jon Ashburnc624c882015-07-16 10:17:29 -06003637
Jon Ashburn23d36b12016-02-02 17:47:28 -07003638 if (res != VK_SUCCESS || !success) {
Jon Ashburn46888392015-01-29 15:45:51 -07003639 ptr_instance->icds = ptr_instance->icds->next;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003640 loader_icd_destroy(ptr_instance, icd);
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07003641 loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburn23d36b12016-02-02 17:47:28 -07003642 "ICD ignored: failed to CreateInstance and find "
3643 "entrypoints with ICD");
Jon Ashburn46888392015-01-29 15:45:51 -07003644 }
3645 }
Jon Ashburn46888392015-01-29 15:45:51 -07003646 }
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003647
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06003648 /*
3649 * If no ICDs were added to instance list and res is unchanged
3650 * from it's initial value, the loader was unable to find
3651 * a suitable ICD.
3652 */
Ian Elliotteb450762015-02-05 15:19:15 -07003653 if (ptr_instance->icds == NULL) {
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06003654 if (res == VK_SUCCESS) {
3655 return VK_ERROR_INCOMPATIBLE_DRIVER;
3656 } else {
3657 return res;
3658 }
Ian Elliotteb450762015-02-05 15:19:15 -07003659 }
Jon Ashburn46888392015-01-29 15:45:51 -07003660
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06003661 return VK_SUCCESS;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003662}
3663
Jon Ashburn23d36b12016-02-02 17:47:28 -07003664VKAPI_ATTR void VKAPI_CALL
Jon Ashburn1530c342016-02-26 13:14:27 -07003665terminator_DestroyInstance(VkInstance instance,
3666 const VkAllocationCallbacks *pAllocator) {
Courtney Goeltzenleuchterdeceded2015-06-08 15:04:02 -06003667 struct loader_instance *ptr_instance = loader_instance(instance);
Jon Ashburn3da71f22015-05-14 12:43:38 -06003668 struct loader_icd *icds = ptr_instance->icds;
Jon Ashburna6fd2612015-06-16 14:43:19 -06003669 struct loader_icd *next_icd;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003670
3671 // Remove this instance from the list of instances:
3672 struct loader_instance *prev = NULL;
3673 struct loader_instance *next = loader.instances;
3674 while (next != NULL) {
3675 if (next == ptr_instance) {
3676 // Remove this instance from the list:
3677 if (prev)
3678 prev->next = next->next;
Jon Ashburnc5c49602015-02-03 09:26:59 -07003679 else
3680 loader.instances = next->next;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003681 break;
3682 }
3683 prev = next;
3684 next = next->next;
3685 }
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003686
Jon Ashburn3da71f22015-05-14 12:43:38 -06003687 while (icds) {
3688 if (icds->instance) {
Chia-I Wuf7458c52015-10-26 21:10:41 +08003689 icds->DestroyInstance(icds->instance, pAllocator);
Tony Barbourf20f87b2015-04-22 09:02:32 -06003690 }
Jon Ashburna6fd2612015-06-16 14:43:19 -06003691 next_icd = icds->next;
Jon Ashburn3da71f22015-05-14 12:43:38 -06003692 icds->instance = VK_NULL_HANDLE;
Jon Ashburna6fd2612015-06-16 14:43:19 -06003693 loader_icd_destroy(ptr_instance, icds);
3694
3695 icds = next_icd;
Jon Ashburn46888392015-01-29 15:45:51 -07003696 }
Jon Ashburn23d36b12016-02-02 17:47:28 -07003697 loader_delete_layer_properties(ptr_instance,
3698 &ptr_instance->device_layer_list);
3699 loader_delete_layer_properties(ptr_instance,
3700 &ptr_instance->instance_layer_list);
Jon Ashburne39a4f82015-08-28 13:38:21 -06003701 loader_scanned_icd_clear(ptr_instance, &ptr_instance->icd_libs);
Jon Ashburn23d36b12016-02-02 17:47:28 -07003702 loader_destroy_generic_list(
3703 ptr_instance, (struct loader_generic_list *)&ptr_instance->ext_list);
Jon Ashburn014438f2016-03-01 19:51:07 -07003704 if (ptr_instance->phys_devs_term)
3705 loader_heap_free(ptr_instance, ptr_instance->phys_devs_term);
Jon Ashburnfc1031e2015-11-17 15:31:02 -07003706 loader_free_dev_ext_table(ptr_instance);
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003707}
3708
Jon Ashburn1530c342016-02-26 13:14:27 -07003709VKAPI_ATTR VkResult VKAPI_CALL
3710terminator_CreateDevice(VkPhysicalDevice physicalDevice,
3711 const VkDeviceCreateInfo *pCreateInfo,
3712 const VkAllocationCallbacks *pAllocator,
3713 VkDevice *pDevice) {
3714 struct loader_physical_device *phys_dev;
Jon Ashburn014438f2016-03-01 19:51:07 -07003715 phys_dev = (struct loader_physical_device *)physicalDevice;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003716
Jon Ashburn1530c342016-02-26 13:14:27 -07003717 VkLayerDeviceCreateInfo *chain_info =
3718 (VkLayerDeviceCreateInfo *)pCreateInfo->pNext;
3719 while (chain_info &&
3720 !(chain_info->sType == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO &&
3721 chain_info->function == VK_LAYER_DEVICE_INFO)) {
3722 chain_info = (VkLayerDeviceCreateInfo *)chain_info->pNext;
3723 }
3724 assert(chain_info != NULL);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003725
Jon Ashburn1530c342016-02-26 13:14:27 -07003726 struct loader_device *dev =
3727 (struct loader_device *)chain_info->u.deviceInfo.device_info;
3728 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr =
3729 chain_info->u.deviceInfo.pfnNextGetInstanceProcAddr;
3730 PFN_vkCreateDevice fpCreateDevice =
3731 (PFN_vkCreateDevice)fpGetInstanceProcAddr(phys_dev->this_icd->instance,
3732 "vkCreateDevice");
3733 if (fpCreateDevice == NULL) {
3734 return VK_ERROR_INITIALIZATION_FAILED;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003735 }
3736
Jon Ashburn1530c342016-02-26 13:14:27 -07003737 VkDeviceCreateInfo localCreateInfo;
3738 memcpy(&localCreateInfo, pCreateInfo, sizeof(localCreateInfo));
3739 localCreateInfo.pNext = loader_strip_create_extensions(pCreateInfo->pNext);
3740
3741 /*
3742 * NOTE: Need to filter the extensions to only those
3743 * supported by the ICD.
3744 * No ICD will advertise support for layers. An ICD
3745 * library could support a layer, but it would be
3746 * independent of the actual ICD, just in the same library.
3747 */
3748 char **filtered_extension_names = NULL;
3749 filtered_extension_names =
3750 loader_stack_alloc(pCreateInfo->enabledExtensionCount * sizeof(char *));
3751 if (!filtered_extension_names) {
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003752 return VK_ERROR_OUT_OF_HOST_MEMORY;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003753 }
3754
Jon Ashburn1530c342016-02-26 13:14:27 -07003755 localCreateInfo.enabledLayerCount = 0;
3756 localCreateInfo.ppEnabledLayerNames = NULL;
3757
3758 localCreateInfo.enabledExtensionCount = 0;
3759 localCreateInfo.ppEnabledExtensionNames =
3760 (const char *const *)filtered_extension_names;
3761
Jon Ashburn014438f2016-03-01 19:51:07 -07003762 /* Get the physical device (ICD) extensions */
3763 struct loader_extension_list icd_exts;
3764 VkResult res;
3765 if (!loader_init_generic_list(phys_dev->this_icd->this_instance,
3766 (struct loader_generic_list *)&icd_exts,
3767 sizeof(VkExtensionProperties))) {
3768 return VK_ERROR_OUT_OF_HOST_MEMORY;
3769 }
3770
3771 res = loader_add_device_extensions(
3772 phys_dev->this_icd->this_instance, phys_dev->this_icd,
3773 phys_dev->phys_dev, phys_dev->this_icd->this_icd_lib->lib_name,
3774 &icd_exts);
3775 if (res != VK_SUCCESS) {
3776 return res;
3777 }
3778
Jon Ashburn1530c342016-02-26 13:14:27 -07003779 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
3780 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i];
Jon Ashburn014438f2016-03-01 19:51:07 -07003781 VkExtensionProperties *prop =
3782 get_extension_property(extension_name, &icd_exts);
Jon Ashburn1530c342016-02-26 13:14:27 -07003783 if (prop) {
3784 filtered_extension_names[localCreateInfo.enabledExtensionCount] =
3785 (char *)extension_name;
3786 localCreateInfo.enabledExtensionCount++;
3787 }
3788 }
3789
3790 VkDevice localDevice;
3791 // TODO: Why does fpCreateDevice behave differently than
3792 // this_icd->CreateDevice?
3793 // VkResult res = fpCreateDevice(phys_dev->phys_dev, &localCreateInfo,
3794 // pAllocator, &localDevice);
Jon Ashburn014438f2016-03-01 19:51:07 -07003795 res = phys_dev->this_icd->CreateDevice(phys_dev->phys_dev, &localCreateInfo,
3796 pAllocator, &localDevice);
Jon Ashburn1530c342016-02-26 13:14:27 -07003797
3798 if (res != VK_SUCCESS) {
3799 return res;
3800 }
3801
3802 *pDevice = localDevice;
3803
3804 /* Init dispatch pointer in new device object */
3805 loader_init_dispatch(*pDevice, &dev->loader_dispatch);
3806
3807 return res;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003808}
3809
Jon Ashburn23d36b12016-02-02 17:47:28 -07003810VKAPI_ATTR VkResult VKAPI_CALL
Jon Ashburn1530c342016-02-26 13:14:27 -07003811terminator_EnumeratePhysicalDevices(VkInstance instance,
3812 uint32_t *pPhysicalDeviceCount,
3813 VkPhysicalDevice *pPhysicalDevices) {
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003814 uint32_t i;
Jon Ashburn014438f2016-03-01 19:51:07 -07003815 struct loader_instance *inst = (struct loader_instance *)instance;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003816 VkResult res = VK_SUCCESS;
Jon Ashburn4c392fb2015-01-28 19:57:09 -07003817
Jon Ashburn014438f2016-03-01 19:51:07 -07003818 struct loader_icd *icd;
3819 struct loader_phys_dev_per_icd *phys_devs;
3820
3821 inst->total_gpu_count = 0;
3822 phys_devs = (struct loader_phys_dev_per_icd *)loader_stack_alloc(
3823 sizeof(struct loader_phys_dev_per_icd) * inst->total_icd_count);
3824 if (!phys_devs)
3825 return VK_ERROR_OUT_OF_HOST_MEMORY;
3826
3827 icd = inst->icds;
3828 for (i = 0; i < inst->total_icd_count; i++) {
3829 assert(icd);
3830 res = icd->EnumeratePhysicalDevices(icd->instance, &phys_devs[i].count,
3831 NULL);
3832 if (res != VK_SUCCESS)
3833 return res;
3834 icd = icd->next;
Jon Ashburn4c392fb2015-01-28 19:57:09 -07003835 }
3836
Jon Ashburn014438f2016-03-01 19:51:07 -07003837 icd = inst->icds;
3838 for (i = 0; i < inst->total_icd_count; i++) {
3839 assert(icd);
3840 phys_devs[i].phys_devs = (VkPhysicalDevice *)loader_stack_alloc(
3841 phys_devs[i].count * sizeof(VkPhysicalDevice));
3842 if (!phys_devs[i].phys_devs) {
3843 return VK_ERROR_OUT_OF_HOST_MEMORY;
3844 }
3845 res = icd->EnumeratePhysicalDevices(
3846 icd->instance, &(phys_devs[i].count), phys_devs[i].phys_devs);
3847 if ((res == VK_SUCCESS)) {
3848 inst->total_gpu_count += phys_devs[i].count;
3849 } else {
3850 return res;
3851 }
3852 phys_devs[i].this_icd = icd;
3853 icd = icd->next;
3854 }
3855
3856 *pPhysicalDeviceCount = inst->total_gpu_count;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003857 if (!pPhysicalDevices) {
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003858 return res;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003859 }
Jon Ashburn4c392fb2015-01-28 19:57:09 -07003860
Jon Ashburn014438f2016-03-01 19:51:07 -07003861 /* Initialize the output pPhysicalDevices with wrapped loader terminator
3862 * physicalDevice objects; save this list of wrapped objects in instance
3863 * struct for later cleanup and use by trampoline code */
3864 uint32_t j, idx = 0;
3865 uint32_t copy_count = 0;
3866
3867 copy_count = (inst->total_gpu_count < *pPhysicalDeviceCount)
3868 ? inst->total_gpu_count
Jon Ashburn23d36b12016-02-02 17:47:28 -07003869 : *pPhysicalDeviceCount;
Jon Ashburn014438f2016-03-01 19:51:07 -07003870
3871 // phys_devs_term is used to pass the "this_icd" info to trampoline code
3872 if (inst->phys_devs_term)
3873 loader_heap_free(inst, inst->phys_devs_term);
3874 inst->phys_devs_term = loader_heap_alloc(
3875 inst, sizeof(struct loader_physical_device) * copy_count,
3876 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
3877 if (!inst->phys_devs_term)
3878 return VK_ERROR_OUT_OF_HOST_MEMORY;
3879
3880 for (i = 0; idx < copy_count && i < inst->total_icd_count; i++) {
3881 for (j = 0; j < phys_devs[i].count && idx < copy_count; j++) {
3882 loader_set_dispatch((void *)&inst->phys_devs_term[idx], inst->disp);
3883 inst->phys_devs_term[idx].this_icd = phys_devs[i].this_icd;
3884 inst->phys_devs_term[idx].phys_dev = phys_devs[i].phys_devs[j];
3885 pPhysicalDevices[idx] =
3886 (VkPhysicalDevice)&inst->phys_devs_term[idx];
3887 idx++;
3888 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003889 }
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003890 *pPhysicalDeviceCount = copy_count;
3891
Jon Ashburn014438f2016-03-01 19:51:07 -07003892 if (copy_count < inst->total_gpu_count) {
3893 inst->total_gpu_count = copy_count;
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07003894 return VK_INCOMPLETE;
3895 }
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003896 return res;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003897}
3898
Jon Ashburn1530c342016-02-26 13:14:27 -07003899VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceProperties(
3900 VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties *pProperties) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07003901 struct loader_physical_device *phys_dev =
3902 (struct loader_physical_device *)physicalDevice;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003903 struct loader_icd *icd = phys_dev->this_icd;
Jon Ashburn3da71f22015-05-14 12:43:38 -06003904
Tony Barbour59a47322015-06-24 16:06:58 -06003905 if (icd->GetPhysicalDeviceProperties)
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003906 icd->GetPhysicalDeviceProperties(phys_dev->phys_dev, pProperties);
Tony Barbour59a47322015-06-24 16:06:58 -06003907}
3908
Jon Ashburn1530c342016-02-26 13:14:27 -07003909VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceQueueFamilyProperties(
Jon Ashburn23d36b12016-02-02 17:47:28 -07003910 VkPhysicalDevice physicalDevice, uint32_t *pQueueFamilyPropertyCount,
3911 VkQueueFamilyProperties *pProperties) {
3912 struct loader_physical_device *phys_dev =
3913 (struct loader_physical_device *)physicalDevice;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003914 struct loader_icd *icd = phys_dev->this_icd;
Tony Barbour59a47322015-06-24 16:06:58 -06003915
Cody Northropd0802882015-08-03 17:04:53 -06003916 if (icd->GetPhysicalDeviceQueueFamilyProperties)
Jon Ashburn23d36b12016-02-02 17:47:28 -07003917 icd->GetPhysicalDeviceQueueFamilyProperties(
3918 phys_dev->phys_dev, pQueueFamilyPropertyCount, pProperties);
Tony Barbour59a47322015-06-24 16:06:58 -06003919}
3920
Jon Ashburn1530c342016-02-26 13:14:27 -07003921VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceMemoryProperties(
Jon Ashburn23d36b12016-02-02 17:47:28 -07003922 VkPhysicalDevice physicalDevice,
3923 VkPhysicalDeviceMemoryProperties *pProperties) {
3924 struct loader_physical_device *phys_dev =
3925 (struct loader_physical_device *)physicalDevice;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003926 struct loader_icd *icd = phys_dev->this_icd;
Tony Barbour59a47322015-06-24 16:06:58 -06003927
3928 if (icd->GetPhysicalDeviceMemoryProperties)
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003929 icd->GetPhysicalDeviceMemoryProperties(phys_dev->phys_dev, pProperties);
Jon Ashburn3da71f22015-05-14 12:43:38 -06003930}
3931
Jon Ashburn23d36b12016-02-02 17:47:28 -07003932VKAPI_ATTR void VKAPI_CALL
Jon Ashburn1530c342016-02-26 13:14:27 -07003933terminator_GetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice,
3934 VkPhysicalDeviceFeatures *pFeatures) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07003935 struct loader_physical_device *phys_dev =
3936 (struct loader_physical_device *)physicalDevice;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003937 struct loader_icd *icd = phys_dev->this_icd;
Chris Forbesbc0bb772015-06-21 22:55:02 +12003938
3939 if (icd->GetPhysicalDeviceFeatures)
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003940 icd->GetPhysicalDeviceFeatures(phys_dev->phys_dev, pFeatures);
Chris Forbesbc0bb772015-06-21 22:55:02 +12003941}
3942
Jon Ashburn23d36b12016-02-02 17:47:28 -07003943VKAPI_ATTR void VKAPI_CALL
Jon Ashburn1530c342016-02-26 13:14:27 -07003944terminator_GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice,
3945 VkFormat format,
3946 VkFormatProperties *pFormatInfo) {
Jon Ashburn23d36b12016-02-02 17:47:28 -07003947 struct loader_physical_device *phys_dev =
3948 (struct loader_physical_device *)physicalDevice;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003949 struct loader_icd *icd = phys_dev->this_icd;
Chris Forbesbc0bb772015-06-21 22:55:02 +12003950
Courtney Goeltzenleuchter2caec862015-07-12 12:52:09 -06003951 if (icd->GetPhysicalDeviceFormatProperties)
Jon Ashburn23d36b12016-02-02 17:47:28 -07003952 icd->GetPhysicalDeviceFormatProperties(phys_dev->phys_dev, format,
3953 pFormatInfo);
Chris Forbesbc0bb772015-06-21 22:55:02 +12003954}
3955
Jon Ashburn1530c342016-02-26 13:14:27 -07003956VKAPI_ATTR VkResult VKAPI_CALL
3957terminator_GetPhysicalDeviceImageFormatProperties(
Jon Ashburn23d36b12016-02-02 17:47:28 -07003958 VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type,
3959 VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags,
3960 VkImageFormatProperties *pImageFormatProperties) {
3961 struct loader_physical_device *phys_dev =
3962 (struct loader_physical_device *)physicalDevice;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003963 struct loader_icd *icd = phys_dev->this_icd;
Jon Ashburn754864f2015-07-23 18:49:07 -06003964
Chia-I Wu17241042015-10-31 00:31:16 +08003965 if (!icd->GetPhysicalDeviceImageFormatProperties)
3966 return VK_ERROR_INITIALIZATION_FAILED;
3967
Jon Ashburn23d36b12016-02-02 17:47:28 -07003968 return icd->GetPhysicalDeviceImageFormatProperties(
3969 phys_dev->phys_dev, format, type, tiling, usage, flags,
3970 pImageFormatProperties);
Jon Ashburn754864f2015-07-23 18:49:07 -06003971}
3972
Jon Ashburn1530c342016-02-26 13:14:27 -07003973VKAPI_ATTR void VKAPI_CALL
3974terminator_GetPhysicalDeviceSparseImageFormatProperties(
Jon Ashburn23d36b12016-02-02 17:47:28 -07003975 VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type,
3976 VkSampleCountFlagBits samples, VkImageUsageFlags usage,
3977 VkImageTiling tiling, uint32_t *pNumProperties,
3978 VkSparseImageFormatProperties *pProperties) {
3979 struct loader_physical_device *phys_dev =
3980 (struct loader_physical_device *)physicalDevice;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003981 struct loader_icd *icd = phys_dev->this_icd;
Mark Lobodzinski16e8bef2015-07-03 15:58:09 -06003982
3983 if (icd->GetPhysicalDeviceSparseImageFormatProperties)
Jon Ashburn23d36b12016-02-02 17:47:28 -07003984 icd->GetPhysicalDeviceSparseImageFormatProperties(
3985 phys_dev->phys_dev, format, type, samples, usage, tiling,
3986 pNumProperties, pProperties);
Mark Lobodzinski16e8bef2015-07-03 15:58:09 -06003987}
3988
Jon Ashburn1530c342016-02-26 13:14:27 -07003989VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateDeviceExtensionProperties(
3990 VkPhysicalDevice physicalDevice, const char *pLayerName,
3991 uint32_t *pPropertyCount, VkExtensionProperties *pProperties) {
Jon Ashburna760a512015-12-14 08:52:14 -07003992 struct loader_physical_device *phys_dev;
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07003993
Jon Ashburn471f44c2016-01-13 12:51:43 -07003994 struct loader_layer_list implicit_layer_list;
3995
Jon Ashburndc5d9202016-02-29 13:00:51 -07003996 assert(pLayerName == NULL || strlen(pLayerName) == 0);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003997
Jon Ashburndc5d9202016-02-29 13:00:51 -07003998 /* Any layer or trampoline wrapping should be removed at this point in time
3999 * can just cast to the expected type for VkPhysicalDevice. */
Jon Ashburn014438f2016-03-01 19:51:07 -07004000 phys_dev = (struct loader_physical_device *)physicalDevice;
Jon Ashburn471f44c2016-01-13 12:51:43 -07004001
Jon Ashburndc5d9202016-02-29 13:00:51 -07004002 /* this case is during the call down the instance chain with pLayerName
4003 * == NULL*/
4004 struct loader_icd *icd = phys_dev->this_icd;
4005 uint32_t icd_ext_count = *pPropertyCount;
4006 VkResult res;
Jon Ashburn471f44c2016-01-13 12:51:43 -07004007
Jon Ashburndc5d9202016-02-29 13:00:51 -07004008 /* get device extensions */
Jon Ashburn014438f2016-03-01 19:51:07 -07004009 res = icd->EnumerateDeviceExtensionProperties(phys_dev->phys_dev, NULL,
4010 &icd_ext_count, pProperties);
Jon Ashburndc5d9202016-02-29 13:00:51 -07004011 if (res != VK_SUCCESS)
4012 return res;
Jon Ashburn23d36b12016-02-02 17:47:28 -07004013
Jon Ashburn014438f2016-03-01 19:51:07 -07004014 loader_init_layer_list(icd->this_instance, &implicit_layer_list);
Jon Ashburn471f44c2016-01-13 12:51:43 -07004015
Jon Ashburndc5d9202016-02-29 13:00:51 -07004016 loader_add_layer_implicit(
Jon Ashburn014438f2016-03-01 19:51:07 -07004017 icd->this_instance, VK_LAYER_TYPE_INSTANCE_IMPLICIT,
4018 &implicit_layer_list, &icd->this_instance->instance_layer_list);
Jon Ashburndc5d9202016-02-29 13:00:51 -07004019 /* we need to determine which implicit layers are active,
4020 * and then add their extensions. This can't be cached as
4021 * it depends on results of environment variables (which can change).
4022 */
4023 if (pProperties != NULL) {
Jon Ashburn014438f2016-03-01 19:51:07 -07004024 struct loader_extension_list icd_exts;
Jon Ashburndc5d9202016-02-29 13:00:51 -07004025 /* initialize dev_extension list within the physicalDevice object */
Jon Ashburn014438f2016-03-01 19:51:07 -07004026 res = loader_init_device_extensions(icd->this_instance, phys_dev,
4027 icd_ext_count, pProperties,
4028 &icd_exts);
Jon Ashburndc5d9202016-02-29 13:00:51 -07004029 if (res != VK_SUCCESS)
4030 return res;
Jon Ashburn471f44c2016-01-13 12:51:43 -07004031
Jon Ashburndc5d9202016-02-29 13:00:51 -07004032 /* we need to determine which implicit layers are active,
4033 * and then add their extensions. This can't be cached as
4034 * it depends on results of environment variables (which can
4035 * change).
4036 */
4037 struct loader_extension_list all_exts = {0};
Jon Ashburn014438f2016-03-01 19:51:07 -07004038 loader_add_to_ext_list(icd->this_instance, &all_exts, icd_exts.count,
4039 icd_exts.list);
Jon Ashburn471f44c2016-01-13 12:51:43 -07004040
Jon Ashburn014438f2016-03-01 19:51:07 -07004041 loader_init_layer_list(icd->this_instance, &implicit_layer_list);
Jon Ashburn471f44c2016-01-13 12:51:43 -07004042
Jon Ashburndc5d9202016-02-29 13:00:51 -07004043 loader_add_layer_implicit(
Jon Ashburn014438f2016-03-01 19:51:07 -07004044 icd->this_instance, VK_LAYER_TYPE_INSTANCE_IMPLICIT,
4045 &implicit_layer_list, &icd->this_instance->instance_layer_list);
Jon Ashburn471f44c2016-01-13 12:51:43 -07004046
Jon Ashburndc5d9202016-02-29 13:00:51 -07004047 for (uint32_t i = 0; i < implicit_layer_list.count; i++) {
4048 for (uint32_t j = 0;
Jon Ashburn014438f2016-03-01 19:51:07 -07004049 j < implicit_layer_list.list[i].device_extension_list.count;
4050 j++) {
4051 loader_add_to_ext_list(icd->this_instance, &all_exts, 1,
4052 &implicit_layer_list.list[i]
4053 .device_extension_list.list[j]
4054 .props);
Jon Ashburn471f44c2016-01-13 12:51:43 -07004055 }
Jon Ashburn471f44c2016-01-13 12:51:43 -07004056 }
Jon Ashburndc5d9202016-02-29 13:00:51 -07004057 uint32_t capacity = *pPropertyCount;
4058 VkExtensionProperties *props = pProperties;
Jon Ashburn471f44c2016-01-13 12:51:43 -07004059
Jon Ashburndc5d9202016-02-29 13:00:51 -07004060 for (uint32_t i = 0; i < all_exts.count && i < capacity; i++) {
4061 props[i] = all_exts.list[i];
4062 }
4063 /* wasn't enough space for the extensions, we did partial copy now
4064 * return VK_INCOMPLETE */
4065 if (capacity < all_exts.count) {
4066 res = VK_INCOMPLETE;
4067 } else {
4068 *pPropertyCount = all_exts.count;
4069 }
Jon Ashburn014438f2016-03-01 19:51:07 -07004070 loader_destroy_generic_list(icd->this_instance,
4071 (struct loader_generic_list *)&all_exts);
Jon Ashburndc5d9202016-02-29 13:00:51 -07004072 } else {
4073 /* just return the count; need to add in the count of implicit layer
4074 * extensions
4075 * don't worry about duplicates being added in the count */
4076 *pPropertyCount = icd_ext_count;
4077
4078 for (uint32_t i = 0; i < implicit_layer_list.count; i++) {
4079 *pPropertyCount +=
Jon Ashburn014438f2016-03-01 19:51:07 -07004080 implicit_layer_list.list[i].device_extension_list.count;
Jon Ashburndc5d9202016-02-29 13:00:51 -07004081 }
4082 res = VK_SUCCESS;
Jon Ashburnb82c1852015-08-11 14:49:54 -06004083 }
Jon Ashburndc5d9202016-02-29 13:00:51 -07004084
4085 loader_destroy_generic_list(
Jon Ashburn014438f2016-03-01 19:51:07 -07004086 icd->this_instance, (struct loader_generic_list *)&implicit_layer_list);
Jon Ashburndc5d9202016-02-29 13:00:51 -07004087 return res;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06004088}
4089
Jon Ashburn23d36b12016-02-02 17:47:28 -07004090VKAPI_ATTR VkResult VKAPI_CALL
Jon Ashburn1530c342016-02-26 13:14:27 -07004091terminator_EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice,
4092 uint32_t *pPropertyCount,
4093 VkLayerProperties *pProperties) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06004094
Jon Ashburndc5d9202016-02-29 13:00:51 -07004095 // should never get here this call isn't dispatched down the chain
4096 return VK_ERROR_INITIALIZATION_FAILED;
Jon Ashburn95a77ba2015-05-15 15:09:35 -06004097}
Mark Lobodzinskie9f09ef2016-02-02 18:53:34 -07004098
Jon Ashburnf2b4e382016-02-10 20:50:19 -07004099VkStringErrorFlags vk_string_validate(const int max_length, const char *utf8) {
Mark Lobodzinskie9f09ef2016-02-02 18:53:34 -07004100 VkStringErrorFlags result = VK_STRING_ERROR_NONE;
Karl Schultz2558bd32016-02-24 14:39:39 -07004101 int num_char_bytes = 0;
Jon Ashburnf2b4e382016-02-10 20:50:19 -07004102 int i, j;
Mark Lobodzinskie9f09ef2016-02-02 18:53:34 -07004103
Jon Ashburnf2b4e382016-02-10 20:50:19 -07004104 for (i = 0; i < max_length; i++) {
Mark Lobodzinskie9f09ef2016-02-02 18:53:34 -07004105 if (utf8[i] == 0) {
4106 break;
Mark Lobodzinski36b4de22016-02-12 11:30:14 -07004107 } else if ((utf8[i] >= 0x20) && (utf8[i] < 0x7f)) {
Mark Lobodzinskie9f09ef2016-02-02 18:53:34 -07004108 num_char_bytes = 0;
Jon Ashburnf2b4e382016-02-10 20:50:19 -07004109 } else if ((utf8[i] & UTF8_ONE_BYTE_MASK) == UTF8_ONE_BYTE_CODE) {
Mark Lobodzinskie9f09ef2016-02-02 18:53:34 -07004110 num_char_bytes = 1;
Jon Ashburnf2b4e382016-02-10 20:50:19 -07004111 } else if ((utf8[i] & UTF8_TWO_BYTE_MASK) == UTF8_TWO_BYTE_CODE) {
Mark Lobodzinskie9f09ef2016-02-02 18:53:34 -07004112 num_char_bytes = 2;
4113 } else if ((utf8[i] & UTF8_THREE_BYTE_MASK) == UTF8_THREE_BYTE_CODE) {
4114 num_char_bytes = 3;
4115 } else {
4116 result = VK_STRING_ERROR_BAD_DATA;
4117 }
4118
4119 // Validate the following num_char_bytes of data
4120 for (j = 0; (j < num_char_bytes) && (i < max_length); j++) {
4121 if (++i == max_length) {
4122 result |= VK_STRING_ERROR_LENGTH;
4123 break;
4124 }
4125 if ((utf8[i] & UTF8_DATA_BYTE_MASK) != UTF8_DATA_BYTE_CODE) {
4126 result |= VK_STRING_ERROR_BAD_DATA;
4127 }
4128 }
4129 }
4130 return result;
4131}