blob: df720c64e86517bb08ee095d4aa96c5076747370 [file] [log] [blame]
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001/*
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08002 *
Courtney Goeltzenleuchterfcbe16f2015-10-29 13:50:34 -06003 * Copyright (C) 2015 Valve Corporation
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08004 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
Chia-I Wu701f3f62014-09-02 08:32:09 +080022 *
Courtney Goeltzenleuchter05559522015-10-30 11:14:30 -060023 * Author: Chia-I Wu <olvaffe@gmail.com>
24 * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
25 * Author: Ian Elliott <ian@LunarG.com>
26 * Author: Jon Ashburn <jon@lunarg.com>
27 *
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080028 */
Mark Lobodzinskifaa90812015-11-25 13:26:15 -070029
Jon Ashburn6b4d70c2014-10-22 18:13:16 -060030#define _GNU_SOURCE
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080031#include <stdio.h>
32#include <stdlib.h>
33#include <stdarg.h>
34#include <stdbool.h>
35#include <string.h>
36
Chia-I Wu13a61a52014-08-04 11:18:20 +080037#include <sys/types.h>
Johannes van Waveren9bd805012015-10-28 11:45:00 -050038#if defined(_WIN32)
Ian Elliott2d4ab1e2015-01-13 17:52:38 -070039#include "dirent_on_windows.h"
Johannes van Waveren9bd805012015-10-28 11:45:00 -050040#else // _WIN32
Chia-I Wu13a61a52014-08-04 11:18:20 +080041#include <dirent.h>
Johannes van Waveren9bd805012015-10-28 11:45:00 -050042#endif // _WIN32
Tobin Ehlisb835d1b2015-07-03 10:34:49 -060043#include "vk_loader_platform.h"
Chia-I Wu19300602014-08-04 08:03:57 +080044#include "loader.h"
Jon Ashburn27cd5842015-05-12 17:26:48 -060045#include "gpa_helper.h"
46#include "table_ops.h"
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -060047#include "debug_report.h"
Ian Elliott954fa342015-10-30 15:28:23 -060048#include "wsi.h"
David Pinedo9316d3b2015-11-06 12:54:48 -070049#include "vulkan/vk_icd.h"
Jon Ashburn2077e382015-06-29 11:25:34 -060050#include "cJSON.h"
Jon Ashburnfc1031e2015-11-17 15:31:02 -070051#include "murmurhash.h"
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080052
Courtney Goeltzenleuchtered488302015-06-01 14:09:34 -060053static loader_platform_dl_handle loader_add_layer_lib(
Jon Ashburne39a4f82015-08-28 13:38:21 -060054 const struct loader_instance *inst,
Courtney Goeltzenleuchtered488302015-06-01 14:09:34 -060055 const char *chain_type,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -060056 struct loader_layer_properties *layer_prop);
Courtney Goeltzenleuchtered488302015-06-01 14:09:34 -060057
58static void loader_remove_layer_lib(
59 struct loader_instance *inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -060060 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
Jon Ashburne39a4f82015-08-28 13:38:21 -060066static bool loader_init_ext_list(
67 const struct loader_instance *inst,
68 struct loader_extension_list *ext_info);
Courtney Goeltzenleuchter9ec39ac2015-06-22 17:45:21 -060069
Daniel Dadap00b4aba2015-09-30 11:50:51 -050070static int loader_platform_combine_path(char *dest, int len, ...);
71
Jon Ashburn24cd4be2015-11-01 14:04:06 -070072struct loader_phys_dev_per_icd {
73 uint32_t count;
74 VkPhysicalDevice *phys_devs;
75};
76
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -060077enum loader_debug {
Courtney Goeltzenleuchterf3387652015-07-08 18:41:08 -060078 LOADER_INFO_BIT = 0x01,
79 LOADER_WARN_BIT = 0x02,
80 LOADER_PERF_BIT = 0x04,
81 LOADER_ERROR_BIT = 0x08,
82 LOADER_DEBUG_BIT = 0x10,
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -060083};
84
85uint32_t g_loader_debug = 0;
86uint32_t g_loader_log_msgs = 0;
87
Jon Ashburn6301a0f2015-05-29 13:15:39 -060088//thread safety lock for accessing global data structures such as "loader"
89// all entrypoints on the instance chain need to be locked except GPA
Jon Ashburn2077e382015-06-29 11:25:34 -060090// additionally CreateDevice and DestroyDevice needs to be locked
Jon Ashburn6301a0f2015-05-29 13:15:39 -060091loader_platform_thread_mutex loader_lock;
Jon Ashburn6461ef22015-09-22 13:11:00 -060092loader_platform_thread_mutex loader_json_lock;
Jon Ashburn6301a0f2015-05-29 13:15:39 -060093
Ian Elliottd3ef02f2015-07-06 14:36:13 -060094// This table contains the loader's instance dispatch table, which contains
95// default functions if no instance layers are activated. This contains
96// pointers to "terminator functions".
Jon Ashburn6301a0f2015-05-29 13:15:39 -060097const VkLayerInstanceDispatchTable instance_disp = {
Jon Ashburn69e9ea22015-09-28 16:15:00 -060098 .GetInstanceProcAddr = vkGetInstanceProcAddr,
Jon Ashburn27cd5842015-05-12 17:26:48 -060099 .CreateInstance = loader_CreateInstance,
100 .DestroyInstance = loader_DestroyInstance,
101 .EnumeratePhysicalDevices = loader_EnumeratePhysicalDevices,
Chris Forbesbc0bb772015-06-21 22:55:02 +1200102 .GetPhysicalDeviceFeatures = loader_GetPhysicalDeviceFeatures,
Courtney Goeltzenleuchter2caec862015-07-12 12:52:09 -0600103 .GetPhysicalDeviceFormatProperties = loader_GetPhysicalDeviceFormatProperties,
Jon Ashburn754864f2015-07-23 18:49:07 -0600104 .GetPhysicalDeviceImageFormatProperties = loader_GetPhysicalDeviceImageFormatProperties,
Tony Barbour59a47322015-06-24 16:06:58 -0600105 .GetPhysicalDeviceProperties = loader_GetPhysicalDeviceProperties,
Cody Northropd0802882015-08-03 17:04:53 -0600106 .GetPhysicalDeviceQueueFamilyProperties = loader_GetPhysicalDeviceQueueFamilyProperties,
Tony Barbour59a47322015-06-24 16:06:58 -0600107 .GetPhysicalDeviceMemoryProperties = loader_GetPhysicalDeviceMemoryProperties,
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -0600108 .EnumerateDeviceExtensionProperties = loader_EnumerateDeviceExtensionProperties,
109 .EnumerateDeviceLayerProperties = loader_EnumerateDeviceLayerProperties,
Mark Lobodzinski16e8bef2015-07-03 15:58:09 -0600110 .GetPhysicalDeviceSparseImageFormatProperties = loader_GetPhysicalDeviceSparseImageFormatProperties,
Ian Elliottfb42cd72015-11-25 14:43:02 -0700111 .DestroySurfaceKHR = loader_DestroySurfaceKHR,
Ian Elliott7e40db92015-08-21 15:09:33 -0600112 .GetPhysicalDeviceSurfaceSupportKHR = loader_GetPhysicalDeviceSurfaceSupportKHR,
Ian Elliott486c5502015-11-19 16:05:09 -0700113 .GetPhysicalDeviceSurfaceCapabilitiesKHR = loader_GetPhysicalDeviceSurfaceCapabilitiesKHR,
114 .GetPhysicalDeviceSurfaceFormatsKHR = loader_GetPhysicalDeviceSurfaceFormatsKHR,
115 .GetPhysicalDeviceSurfacePresentModesKHR = loader_GetPhysicalDeviceSurfacePresentModesKHR,
Mark Lobodzinskifaa90812015-11-25 13:26:15 -0700116 .DbgCreateMsgCallback = loader_DbgCreateMsgCallback,
117 .DbgDestroyMsgCallback = loader_DbgDestroyMsgCallback,
Ian Elliottdb4300a2015-11-23 10:17:23 -0700118#ifdef VK_USE_PLATFORM_MIR_KHR
Jon Ashburnf72a04b2015-11-25 17:55:49 -0700119 .CreateMirSurfaceKHR = loader_CreateMirSurfaceKHR,
Ian Elliott919fa302015-11-24 15:39:10 -0700120 .GetPhysicalDeviceMirPresentationSupportKHR = loader_GetPhysicalDeviceMirPresentationSupportKHR,
Ian Elliottdb4300a2015-11-23 10:17:23 -0700121#endif
122#ifdef VK_USE_PLATFORM_WAYLAND_KHR
Jon Ashburnf72a04b2015-11-25 17:55:49 -0700123 .CreateWaylandSurfaceKHR = loader_CreateWaylandSurfaceKHR,
Ian Elliott919fa302015-11-24 15:39:10 -0700124 .GetPhysicalDeviceWaylandPresentationSupportKHR = loader_GetPhysicalDeviceWaylandPresentationSupportKHR,
Ian Elliottdb4300a2015-11-23 10:17:23 -0700125#endif
126#ifdef VK_USE_PLATFORM_WIN32_KHR
Jon Ashburnf72a04b2015-11-25 17:55:49 -0700127 .CreateWin32SurfaceKHR = loader_CreateWin32SurfaceKHR,
Ian Elliott919fa302015-11-24 15:39:10 -0700128 .GetPhysicalDeviceWin32PresentationSupportKHR = loader_GetPhysicalDeviceWin32PresentationSupportKHR,
Ian Elliottdb4300a2015-11-23 10:17:23 -0700129#endif
130#ifdef VK_USE_PLATFORM_XCB_KHR
Jon Ashburnf72a04b2015-11-25 17:55:49 -0700131 .CreateXcbSurfaceKHR = loader_CreateXcbSurfaceKHR,
Ian Elliott919fa302015-11-24 15:39:10 -0700132 .GetPhysicalDeviceXcbPresentationSupportKHR = loader_GetPhysicalDeviceXcbPresentationSupportKHR,
Ian Elliottdb4300a2015-11-23 10:17:23 -0700133#endif
134#ifdef VK_USE_PLATFORM_XLIB_KHR
Jon Ashburnf72a04b2015-11-25 17:55:49 -0700135 .CreateXlibSurfaceKHR = loader_CreateXlibSurfaceKHR,
Ian Elliott919fa302015-11-24 15:39:10 -0700136 .GetPhysicalDeviceXlibPresentationSupportKHR = loader_GetPhysicalDeviceXlibPresentationSupportKHR,
Ian Elliottdb4300a2015-11-23 10:17:23 -0700137#endif
Jon Ashburn27cd5842015-05-12 17:26:48 -0600138};
139
Jon Ashburn8810c5f2015-08-18 18:04:47 -0600140LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_init);
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700141
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600142void* loader_heap_alloc(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600143 const struct loader_instance *instance,
144 size_t size,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800145 VkSystemAllocationScope alloc_scope)
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600146{
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800147 if (instance && instance->alloc_callbacks.pfnAllocation) {
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600148 /* TODO: What should default alignment be? 1, 4, 8, other? */
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800149 return instance->alloc_callbacks.pfnAllocation(instance->alloc_callbacks.pUserData, size, 4, alloc_scope);
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600150 }
151 return malloc(size);
152}
153
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600154void loader_heap_free(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600155 const struct loader_instance *instance,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800156 void *pMemory)
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600157{
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800158 if (pMemory == NULL) return;
Jon Ashburneacfa3a2015-08-14 12:51:47 -0600159 if (instance && instance->alloc_callbacks.pfnFree) {
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800160 instance->alloc_callbacks.pfnFree(instance->alloc_callbacks.pUserData, pMemory);
Jon Ashburnd2c171b2015-08-13 08:28:48 -0600161 return;
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600162 }
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800163 free(pMemory);
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600164}
165
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600166void* loader_heap_realloc(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600167 const struct loader_instance *instance,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800168 void *pMemory,
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600169 size_t orig_size,
170 size_t size,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800171 VkSystemAllocationScope alloc_scope)
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600172{
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800173 if (pMemory == NULL || orig_size == 0)
Chia-I Wuf7458c52015-10-26 21:10:41 +0800174 return loader_heap_alloc(instance, size, alloc_scope);
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600175 if (size == 0) {
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800176 loader_heap_free(instance, pMemory);
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600177 return NULL;
178 }
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800179 if (instance && instance->alloc_callbacks.pfnAllocation) {
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600180 if (size <= orig_size) {
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800181 memset(((uint8_t *)pMemory) + size, 0, orig_size - size);
182 return pMemory;
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600183 }
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800184 void *new_ptr = instance->alloc_callbacks.pfnAllocation(instance->alloc_callbacks.pUserData, size, 4, alloc_scope);
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600185 if (!new_ptr)
186 return NULL;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800187 memcpy(new_ptr, pMemory, orig_size);
188 instance->alloc_callbacks.pfnFree(instance->alloc_callbacks.pUserData, pMemory);
Jon Ashburne3753b32015-10-21 16:09:27 -0600189 return new_ptr;
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600190 }
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800191 return realloc(pMemory, size);
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600192}
193
Jon Ashburn87d6aa92015-08-28 15:19:27 -0600194void *loader_tls_heap_alloc(size_t size)
195{
Chia-I Wucf804e82015-10-31 00:31:16 +0800196 return loader_heap_alloc(tls_instance, size, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
Jon Ashburn87d6aa92015-08-28 15:19:27 -0600197}
198
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800199void loader_tls_heap_free(void *pMemory)
Jon Ashburn87d6aa92015-08-28 15:19:27 -0600200{
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800201 loader_heap_free(tls_instance, pMemory);
Jon Ashburn87d6aa92015-08-28 15:19:27 -0600202}
203
Jon Ashburnffad94d2015-06-30 14:46:22 -0700204static void loader_log(VkFlags msg_type, int32_t msg_code,
205 const char *format, ...)
206{
Jon Ashburn86723b02015-07-31 15:47:59 -0600207 char msg[512];
Jon Ashburnffad94d2015-06-30 14:46:22 -0700208 va_list ap;
209 int ret;
210
211 if (!(msg_type & g_loader_log_msgs)) {
212 return;
213 }
214
215 va_start(ap, format);
216 ret = vsnprintf(msg, sizeof(msg), format, ap);
217 if ((ret >= (int) sizeof(msg)) || ret < 0) {
218 msg[sizeof(msg)-1] = '\0';
219 }
220 va_end(ap);
221
Ian Elliott4470a302015-02-17 10:33:47 -0700222#if defined(WIN32)
Jon Ashburnffad94d2015-06-30 14:46:22 -0700223 OutputDebugString(msg);
mschottb9cdb782015-07-22 14:11:29 +0200224 OutputDebugString("\n");
Jon Ashburnffad94d2015-06-30 14:46:22 -0700225#endif
226 fputs(msg, stderr);
227 fputc('\n', stderr);
228}
229
230#if defined(WIN32)
Tony Barbourea968902015-07-29 14:26:21 -0600231static char *loader_get_next_path(char *path);
Jon Ashburnffad94d2015-06-30 14:46:22 -0700232/**
233* Find the list of registry files (names within a key) in key "location".
234*
235* This function looks in the registry (hive = DEFAULT_VK_REGISTRY_HIVE) key as given in "location"
236* for a list or name/values which are added to a returned list (function return value).
237* The DWORD values within the key must be 0 or they are skipped.
Jon Ashburne39a4f82015-08-28 13:38:21 -0600238* Function return is a string with a ';' separated list of filenames.
Jon Ashburnffad94d2015-06-30 14:46:22 -0700239* Function return is NULL if no valid name/value pairs are found in the key,
240* or the key is not found.
241*
242* \returns
243* A string list of filenames as pointer.
244* When done using the returned string list, pointer should be freed.
245*/
Jon Ashburne39a4f82015-08-28 13:38:21 -0600246static char *loader_get_registry_files(const struct loader_instance *inst, char *location)
Jon Ashburnffad94d2015-06-30 14:46:22 -0700247{
248 LONG rtn_value;
249 HKEY hive, key;
Piers Daniell524ec732015-11-05 16:58:26 -0700250 DWORD access_flags;
Jon Ashburnffad94d2015-06-30 14:46:22 -0700251 char name[2048];
252 char *out = NULL;
Tony Barbourea968902015-07-29 14:26:21 -0600253 char *loc = location;
254 char *next;
Jon Ashburnffad94d2015-06-30 14:46:22 -0700255 DWORD idx = 0;
256 DWORD name_size = sizeof(name);
257 DWORD value;
258 DWORD total_size = 4096;
259 DWORD value_size = sizeof(value);
Tony Barbourea968902015-07-29 14:26:21 -0600260
261 while(*loc)
262 {
263 next = loader_get_next_path(loc);
264 hive = DEFAULT_VK_REGISTRY_HIVE;
Piers Daniell524ec732015-11-05 16:58:26 -0700265 access_flags = KEY_QUERY_VALUE;
Tony Barbourea968902015-07-29 14:26:21 -0600266 rtn_value = RegOpenKeyEx(hive, loc, 0, access_flags, &key);
267 if (rtn_value != ERROR_SUCCESS) {
268 // We didn't find the key. Try the 32-bit hive (where we've seen the
269 // key end up on some people's systems):
270 access_flags |= KEY_WOW64_32KEY;
271 rtn_value = RegOpenKeyEx(hive, loc, 0, access_flags, &key);
272 if (rtn_value != ERROR_SUCCESS) {
273 // We still couldn't find the key, so give up:
274 loc = next;
275 continue;
Jon Ashburnffad94d2015-06-30 14:46:22 -0700276 }
Jon Ashburnffad94d2015-06-30 14:46:22 -0700277 }
Tony Barbourea968902015-07-29 14:26:21 -0600278
Jon Ashburne39a4f82015-08-28 13:38:21 -0600279 while ((rtn_value = RegEnumValue(key, idx++, name, &name_size, NULL, NULL, (LPBYTE) &value, &value_size)) == ERROR_SUCCESS) {
Tony Barbourea968902015-07-29 14:26:21 -0600280 if (value_size == sizeof(value) && value == 0) {
281 if (out == NULL) {
Courtney Goeltzenleuchter2961e1c2015-11-02 17:43:04 -0700282 out = loader_heap_alloc(inst, total_size, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Tony Barbourea968902015-07-29 14:26:21 -0600283 out[0] = '\0';
284 }
285 else if (strlen(out) + name_size + 1 > total_size) {
Courtney Goeltzenleuchter2961e1c2015-11-02 17:43:04 -0700286 out = loader_heap_realloc(inst, out, total_size, total_size * 2, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Tony Barbourea968902015-07-29 14:26:21 -0600287 total_size *= 2;
288 }
289 if (out == NULL) {
290 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory, failed loader_get_registry_files");
291 return NULL;
292 }
293 if (strlen(out) == 0)
294 snprintf(out, name_size + 1, "%s", name);
295 else
296 snprintf(out + strlen(out), name_size + 2, "%c%s", PATH_SEPERATOR, name);
297 }
298 name_size = 2048;
299 }
300 loc = next;
Jon Ashburnffad94d2015-06-30 14:46:22 -0700301 }
Tony Barbourea968902015-07-29 14:26:21 -0600302
Jon Ashburnffad94d2015-06-30 14:46:22 -0700303 return out;
304}
305
Ian Elliott4470a302015-02-17 10:33:47 -0700306#endif // WIN32
307
Jon Ashburnc7237a72015-08-03 09:08:46 -0600308/**
Daniel Dadap00b4aba2015-09-30 11:50:51 -0500309 * Combine path elements, separating each element with the platform-specific
310 * directory separator, and save the combined string to a destination buffer,
311 * not exceeding the given length. Path elements are given as variadic args,
312 * with a NULL element terminating the list.
313 *
314 * \returns the total length of the combined string, not including an ASCII
315 * NUL termination character. This length may exceed the available storage:
316 * in this case, the written string will be truncated to avoid a buffer
317 * overrun, and the return value will greater than or equal to the storage
318 * size. A NULL argument may be provided as the destination buffer in order
319 * to determine the required string length without actually writing a string.
320 */
321
322static int loader_platform_combine_path(char *dest, int len, ...)
323{
324 int required_len = 0;
325 va_list ap;
326 const char *component;
327
328 va_start(ap, len);
329
330 while((component = va_arg(ap, const char *))) {
331 if (required_len > 0) {
332 // This path element is not the first non-empty element; prepend
333 // a directory separator if space allows
334 if (dest && required_len + 1 < len) {
335 snprintf(dest + required_len, len - required_len, "%c",
336 DIRECTORY_SYMBOL);
337 }
338 required_len++;
339 }
340
341 if (dest && required_len < len) {
342 strncpy(dest + required_len, component, len - required_len);
343 }
344 required_len += strlen(component);
345 }
346
347 va_end(ap);
348
349 // strncpy(3) won't add a NUL terminating byte in the event of truncation.
350 if (dest && required_len >= len) {
351 dest[len - 1] = '\0';
352 }
353
354 return required_len;
355}
356
357
358/**
Jon Ashburnc7237a72015-08-03 09:08:46 -0600359 * Given string of three part form "maj.min.pat" convert to a vulkan version
360 * number.
361 */
362static uint32_t loader_make_version(const char *vers_str)
363{
Jon Ashburn432d2762015-09-18 12:53:16 -0600364 uint32_t vers = 0, major=0, minor=0, patch=0;
Jon Ashburnc7237a72015-08-03 09:08:46 -0600365 char *minor_str= NULL;
366 char *patch_str = NULL;
367 char *cstr;
368 char *str;
369
370 if (!vers_str)
371 return vers;
372 cstr = loader_stack_alloc(strlen(vers_str) + 1);
373 strcpy(cstr, vers_str);
374 while ((str = strchr(cstr, '.')) != NULL) {
375 if (minor_str == NULL) {
376 minor_str = str + 1;
377 *str = '\0';
378 major = atoi(cstr);
379 }
380 else if (patch_str == NULL) {
381 patch_str = str + 1;
382 *str = '\0';
383 minor = atoi(minor_str);
384 }
385 else {
386 return vers;
387 }
388 cstr = str + 1;
389 }
390 patch = atoi(patch_str);
391
392 return VK_MAKE_VERSION(major, minor, patch);
393
394}
395
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600396bool compare_vk_extension_properties(const VkExtensionProperties *op1, const VkExtensionProperties *op2)
397{
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800398 return strcmp(op1->extensionName, op2->extensionName) == 0 ? true : false;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600399}
400
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -0600401/**
Jon Ashburnbd6c4882015-07-02 12:59:25 -0600402 * Search the given ext_array for an extension
403 * matching the given vk_ext_prop
404 */
405bool has_vk_extension_property_array(
406 const VkExtensionProperties *vk_ext_prop,
407 const uint32_t count,
408 const VkExtensionProperties *ext_array)
409{
410 for (uint32_t i = 0; i < count; i++) {
411 if (compare_vk_extension_properties(vk_ext_prop, &ext_array[i]))
412 return true;
413 }
414 return false;
415}
416
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -0600417/**
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600418 * Search the given ext_list for an extension
419 * matching the given vk_ext_prop
420 */
421bool has_vk_extension_property(
422 const VkExtensionProperties *vk_ext_prop,
423 const struct loader_extension_list *ext_list)
424{
425 for (uint32_t i = 0; i < ext_list->count; i++) {
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600426 if (compare_vk_extension_properties(&ext_list->list[i], vk_ext_prop))
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600427 return true;
428 }
429 return false;
430}
431
Jon Ashburnb2ef1372015-07-16 17:19:31 -0600432static inline bool loader_is_layer_type_device(const enum layer_type type) {
433 if ((type & VK_LAYER_TYPE_DEVICE_EXPLICIT) ||
434 (type & VK_LAYER_TYPE_DEVICE_IMPLICIT))
435 return true;
436 return false;
437}
438
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600439/*
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -0600440 * Search the given layer list for a layer matching the given layer name
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600441 */
Jon Ashburne13ecc92015-08-03 17:19:30 -0600442static struct loader_layer_properties *loader_get_layer_property(
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600443 const char *name,
444 const struct loader_layer_list *layer_list)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600445{
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600446 for (uint32_t i = 0; i < layer_list->count; i++) {
447 const VkLayerProperties *item = &layer_list->list[i].info;
448 if (strcmp(name, item->layerName) == 0)
449 return &layer_list->list[i];
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600450 }
451 return NULL;
452}
453
Jon Ashburne13ecc92015-08-03 17:19:30 -0600454/**
455 * Get the next unused layer property in the list. Init the property to zero.
456 */
457static struct loader_layer_properties *loader_get_next_layer_property(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600458 const struct loader_instance *inst,
Jon Ashburne13ecc92015-08-03 17:19:30 -0600459 struct loader_layer_list *layer_list)
460{
461 if (layer_list->capacity == 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600462 layer_list->list = loader_heap_alloc(inst,
463 sizeof(struct loader_layer_properties) * 64,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800464 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburne13ecc92015-08-03 17:19:30 -0600465 if (layer_list->list == NULL) {
466 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't add any layer properties to list");
467 return NULL;
468 }
469 memset(layer_list->list, 0, sizeof(struct loader_layer_properties) * 64);
470 layer_list->capacity = sizeof(struct loader_layer_properties) * 64;
471 }
472
473 // ensure enough room to add an entry
474 if ((layer_list->count + 1) * sizeof (struct loader_layer_properties)
475 > layer_list->capacity) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600476 layer_list->list = loader_heap_realloc(inst, layer_list->list,
477 layer_list->capacity,
478 layer_list->capacity * 2,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800479 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburne13ecc92015-08-03 17:19:30 -0600480 if (layer_list->list == NULL) {
481 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
482 "realloc failed for layer list");
483 }
484 layer_list->capacity *= 2;
485 }
486
487 layer_list->count++;
488 return &(layer_list->list[layer_list->count - 1]);
489}
490
491/**
492 * Remove all layer properties entrys from the list
493 */
Jon Ashburne39a4f82015-08-28 13:38:21 -0600494void loader_delete_layer_properties(
495 const struct loader_instance *inst,
496 struct loader_layer_list *layer_list)
Jon Ashburne13ecc92015-08-03 17:19:30 -0600497{
498 uint32_t i;
499
Jon Ashburnb82c1852015-08-11 14:49:54 -0600500 if (!layer_list)
501 return;
502
Jon Ashburne13ecc92015-08-03 17:19:30 -0600503 for (i = 0; i < layer_list->count; i++) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600504 loader_destroy_ext_list(inst, &layer_list->list[i].instance_extension_list);
505 loader_destroy_ext_list(inst, &layer_list->list[i].device_extension_list);
Jon Ashburne13ecc92015-08-03 17:19:30 -0600506 }
507 layer_list->count = 0;
508
Jon Ashburnb82c1852015-08-11 14:49:54 -0600509 if (layer_list->capacity > 0) {
510 layer_list->capacity = 0;
Jon Ashburne39a4f82015-08-28 13:38:21 -0600511 loader_heap_free(inst, layer_list->list);
Jon Ashburnb82c1852015-08-11 14:49:54 -0600512 }
Jon Ashburne13ecc92015-08-03 17:19:30 -0600513
514}
515
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600516static void loader_add_global_extensions(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600517 const struct loader_instance *inst,
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -0600518 const PFN_vkEnumerateInstanceExtensionProperties fp_get_props,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600519 const char *lib_name,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600520 struct loader_extension_list *ext_list)
521{
522 uint32_t i, count;
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600523 VkExtensionProperties *ext_props;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600524 VkResult res;
525
Courtney Goeltzenleuchter5c6cf472015-07-06 22:28:18 -0600526 if (!fp_get_props) {
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -0600527 /* No EnumerateInstanceExtensionProperties defined */
Courtney Goeltzenleuchter5c6cf472015-07-06 22:28:18 -0600528 return;
529 }
530
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600531 res = fp_get_props(NULL, &count, NULL);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600532 if (res != VK_SUCCESS) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600533 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Error getting global extension count from %s", lib_name);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600534 return;
535 }
Jon Ashburn953bb3c2015-06-10 16:11:42 -0600536
Courtney Goeltzenleuchter5c6cf472015-07-06 22:28:18 -0600537 if (count == 0) {
538 /* No ExtensionProperties to report */
539 return;
540 }
541
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600542 ext_props = loader_stack_alloc(count * sizeof(VkExtensionProperties));
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600543
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600544 res = fp_get_props(NULL, &count, ext_props);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600545 if (res != VK_SUCCESS) {
546 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Error getting global extensions from %s", lib_name);
547 return;
548 }
Tony Barbour59a47322015-06-24 16:06:58 -0600549
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600550 for (i = 0; i < count; i++) {
Courtney Goeltzenleuchter53043732015-07-12 13:20:05 -0600551 char spec_version[64];
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600552
553 snprintf(spec_version, sizeof(spec_version), "%d.%d.%d",
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600554 VK_MAJOR(ext_props[i].specVersion),
555 VK_MINOR(ext_props[i].specVersion),
556 VK_PATCH(ext_props[i].specVersion));
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600557 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Courtney Goeltzenleuchter53043732015-07-12 13:20:05 -0600558 "Global Extension: %s (%s) version %s",
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800559 ext_props[i].extensionName, lib_name, spec_version);
Jon Ashburne39a4f82015-08-28 13:38:21 -0600560 loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600561 }
562
563 return;
564}
565
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700566/*
567 * Initialize ext_list with the physical device extensions.
568 * The extension properties are passed as inputs in count and ext_props.
569 */
570static VkResult loader_init_physical_device_extensions(
571 const struct loader_instance *inst,
572 struct loader_physical_device *phys_dev,
573 uint32_t count,
574 VkExtensionProperties *ext_props,
575 struct loader_extension_list *ext_list)
576{
577 VkResult res;
578 uint32_t i;
579
580 if (!loader_init_ext_list(inst, ext_list)) {
581 return VK_ERROR_OUT_OF_HOST_MEMORY;
582 }
583
584 for (i = 0; i < count; i++) {
585 char spec_version[64];
586
587 snprintf(spec_version, sizeof (spec_version), "%d.%d.%d",
588 VK_MAJOR(ext_props[i].specVersion),
589 VK_MINOR(ext_props[i].specVersion),
590 VK_PATCH(ext_props[i].specVersion));
591 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
592 "PhysicalDevice Extension: %s (%s) version %s",
593 ext_props[i].extensionName, phys_dev->this_icd->this_icd_lib->lib_name, spec_version);
594 res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
595 if (res != VK_SUCCESS)
596 return res;
597 }
598
599 return VK_SUCCESS;
600}
601
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700602static VkResult loader_add_physical_device_extensions(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600603 const struct loader_instance *inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600604 VkPhysicalDevice physical_device,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600605 const char *lib_name,
606 struct loader_extension_list *ext_list)
607{
608 uint32_t i, count;
609 VkResult res;
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600610 VkExtensionProperties *ext_props;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600611
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700612 res = loader_EnumerateDeviceExtensionProperties(physical_device, NULL, &count, NULL);
613 if (res == VK_SUCCESS && count > 0) {
614 ext_props = loader_stack_alloc(count * sizeof (VkExtensionProperties));
615 if (!ext_props)
616 return VK_ERROR_OUT_OF_HOST_MEMORY;
617 res = loader_EnumerateDeviceExtensionProperties(physical_device, NULL, &count, ext_props);
618 if (res != VK_SUCCESS)
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700619 return res;
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700620 for (i = 0; i < count; i++) {
621 char spec_version[64];
622
623 snprintf(spec_version, sizeof (spec_version), "%d.%d.%d",
624 VK_MAJOR(ext_props[i].specVersion),
625 VK_MINOR(ext_props[i].specVersion),
626 VK_PATCH(ext_props[i].specVersion));
627 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
628 "PhysicalDevice Extension: %s (%s) version %s",
629 ext_props[i].extensionName, lib_name, spec_version);
630 res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
631 if (res != VK_SUCCESS)
632 return res;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600633 }
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700634 } else {
635 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Error getting physical device extension info count from library %s", lib_name);
636 return res;
637 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600638
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700639 return VK_SUCCESS;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600640}
641
Jon Ashburne39a4f82015-08-28 13:38:21 -0600642static bool loader_init_ext_list(const struct loader_instance *inst,
643 struct loader_extension_list *ext_info)
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600644{
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600645 ext_info->capacity = 32 * sizeof(VkExtensionProperties);
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800646 ext_info->list = loader_heap_alloc(inst, ext_info->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600647 if (ext_info->list == NULL) {
648 return false;
649 }
650 memset(ext_info->list, 0, ext_info->capacity);
651 ext_info->count = 0;
652 return true;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600653}
654
Jon Ashburne39a4f82015-08-28 13:38:21 -0600655void loader_destroy_ext_list(const struct loader_instance *inst,
656 struct loader_extension_list *ext_info)
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600657{
Jon Ashburne39a4f82015-08-28 13:38:21 -0600658 loader_heap_free(inst, ext_info->list);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600659 ext_info->count = 0;
660 ext_info->capacity = 0;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600661}
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600662
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600663/*
664 * Append non-duplicate extension properties defined in props
665 * to the given ext_list.
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700666 * Return
667 * Vk_SUCCESS on success
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600668 */
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700669VkResult loader_add_to_ext_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600670 const struct loader_instance *inst,
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600671 struct loader_extension_list *ext_list,
672 uint32_t prop_list_count,
673 const VkExtensionProperties *props)
674{
675 uint32_t i;
676 const VkExtensionProperties *cur_ext;
677
678 if (ext_list->list == NULL || ext_list->capacity == 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600679 loader_init_ext_list(inst, ext_list);
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600680 }
681
682 if (ext_list->list == NULL)
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700683 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600684
685 for (i = 0; i < prop_list_count; i++) {
686 cur_ext = &props[i];
687
688 // look for duplicates
689 if (has_vk_extension_property(cur_ext, ext_list)) {
690 continue;
691 }
692
693 // add to list at end
694 // check for enough capacity
695 if (ext_list->count * sizeof(VkExtensionProperties)
696 >= ext_list->capacity) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600697
698 ext_list->list = loader_heap_realloc(inst,
699 ext_list->list,
700 ext_list->capacity,
701 ext_list->capacity * 2,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800702 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700703
704 if (ext_list->list == NULL)
705 return VK_ERROR_OUT_OF_HOST_MEMORY;
706
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600707 // double capacity
708 ext_list->capacity *= 2;
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600709 }
710
711 memcpy(&ext_list->list[ext_list->count], cur_ext, sizeof(VkExtensionProperties));
712 ext_list->count++;
713 }
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700714 return VK_SUCCESS;
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600715}
716
Jon Ashburnbd6c4882015-07-02 12:59:25 -0600717/**
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600718 * Search the given search_list for any layers in the props list.
719 * Add these to the output layer_list. Don't add duplicates to the output layer_list.
Jon Ashburnbd6c4882015-07-02 12:59:25 -0600720 */
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -0600721static VkResult loader_add_layer_names_to_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600722 const struct loader_instance *inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600723 struct loader_layer_list *output_list,
724 uint32_t name_count,
725 const char * const *names,
726 const struct loader_layer_list *search_list)
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600727{
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600728 struct loader_layer_properties *layer_prop;
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -0600729 VkResult err = VK_SUCCESS;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600730
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600731 for (uint32_t i = 0; i < name_count; i++) {
732 const char *search_target = names[i];
Jon Ashburne13ecc92015-08-03 17:19:30 -0600733 layer_prop = loader_get_layer_property(search_target, search_list);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600734 if (!layer_prop) {
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -0600735 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Unable to find layer %s", search_target);
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -0600736 err = VK_ERROR_LAYER_NOT_PRESENT;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600737 continue;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600738 }
739
Jon Ashburne39a4f82015-08-28 13:38:21 -0600740 loader_add_to_layer_list(inst, output_list, 1, layer_prop);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600741 }
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -0600742
743 return err;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600744}
745
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600746
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600747/*
748 * Manage lists of VkLayerProperties
749 */
Jon Ashburne39a4f82015-08-28 13:38:21 -0600750static bool loader_init_layer_list(const struct loader_instance *inst,
751 struct loader_layer_list *list)
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600752{
753 list->capacity = 32 * sizeof(struct loader_layer_properties);
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800754 list->list = loader_heap_alloc(inst, list->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600755 if (list->list == NULL) {
756 return false;
757 }
758 memset(list->list, 0, list->capacity);
759 list->count = 0;
760 return true;
761}
762
Jon Ashburne39a4f82015-08-28 13:38:21 -0600763void loader_destroy_layer_list(const struct loader_instance *inst,
764 struct loader_layer_list *layer_list)
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600765{
Jon Ashburne39a4f82015-08-28 13:38:21 -0600766 loader_heap_free(inst, layer_list->list);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600767 layer_list->count = 0;
768 layer_list->capacity = 0;
769}
770
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600771/*
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600772 * Manage list of layer libraries (loader_lib_info)
773 */
Jon Ashburne39a4f82015-08-28 13:38:21 -0600774static bool loader_init_layer_library_list(const struct loader_instance *inst,
775 struct loader_layer_library_list *list)
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600776{
777 list->capacity = 32 * sizeof(struct loader_lib_info);
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800778 list->list = loader_heap_alloc(inst, list->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600779 if (list->list == NULL) {
780 return false;
781 }
782 memset(list->list, 0, list->capacity);
783 list->count = 0;
784 return true;
785}
786
Jon Ashburne39a4f82015-08-28 13:38:21 -0600787void loader_destroy_layer_library_list(const struct loader_instance *inst,
788 struct loader_layer_library_list *list)
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600789{
790 for (uint32_t i = 0; i < list->count; i++) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600791 loader_heap_free(inst, list->list[i].lib_name);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600792 }
Jon Ashburne39a4f82015-08-28 13:38:21 -0600793 loader_heap_free(inst, list->list);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600794 list->count = 0;
795 list->capacity = 0;
796}
797
798void loader_add_to_layer_library_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600799 const struct loader_instance *inst,
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600800 struct loader_layer_library_list *list,
801 uint32_t item_count,
802 const struct loader_lib_info *new_items)
803{
804 uint32_t i;
805 struct loader_lib_info *item;
806
807 if (list->list == NULL || list->capacity == 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600808 loader_init_layer_library_list(inst, list);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600809 }
810
811 if (list->list == NULL)
812 return;
813
814 for (i = 0; i < item_count; i++) {
815 item = (struct loader_lib_info *) &new_items[i];
816
817 // look for duplicates
818 for (uint32_t j = 0; j < list->count; j++) {
819 if (strcmp(list->list[i].lib_name, new_items->lib_name) == 0) {
820 continue;
821 }
822 }
823
824 // add to list at end
825 // check for enough capacity
826 if (list->count * sizeof(struct loader_lib_info)
827 >= list->capacity) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600828
829 list->list = loader_heap_realloc(inst,
830 list->list,
831 list->capacity,
832 list->capacity * 2,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800833 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600834 // double capacity
835 list->capacity *= 2;
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600836 }
837
838 memcpy(&list->list[list->count], item, sizeof(struct loader_lib_info));
839 list->count++;
840 }
841}
842
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600843
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600844/*
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600845 * Search the given layer list for a list
846 * matching the given VkLayerProperties
847 */
848bool has_vk_layer_property(
849 const VkLayerProperties *vk_layer_prop,
850 const struct loader_layer_list *list)
851{
852 for (uint32_t i = 0; i < list->count; i++) {
853 if (strcmp(vk_layer_prop->layerName, list->list[i].info.layerName) == 0)
854 return true;
855 }
856 return false;
857}
858
859/*
860 * Search the given layer list for a layer
861 * matching the given name
862 */
863bool has_layer_name(
864 const char *name,
865 const struct loader_layer_list *list)
866{
867 for (uint32_t i = 0; i < list->count; i++) {
868 if (strcmp(name, list->list[i].info.layerName) == 0)
869 return true;
870 }
871 return false;
872}
873
874/*
875 * Append non-duplicate layer properties defined in prop_list
876 * to the given layer_info list
877 */
878void loader_add_to_layer_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600879 const struct loader_instance *inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600880 struct loader_layer_list *list,
881 uint32_t prop_list_count,
882 const struct loader_layer_properties *props)
883{
884 uint32_t i;
885 struct loader_layer_properties *layer;
886
887 if (list->list == NULL || list->capacity == 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600888 loader_init_layer_list(inst, list);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600889 }
890
891 if (list->list == NULL)
892 return;
893
894 for (i = 0; i < prop_list_count; i++) {
895 layer = (struct loader_layer_properties *) &props[i];
896
897 // look for duplicates
898 if (has_vk_layer_property(&layer->info, list)) {
899 continue;
900 }
901
902 // add to list at end
903 // check for enough capacity
904 if (list->count * sizeof(struct loader_layer_properties)
905 >= list->capacity) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600906
907 list->list = loader_heap_realloc(inst,
908 list->list,
909 list->capacity,
910 list->capacity * 2,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800911 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600912 // double capacity
913 list->capacity *= 2;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600914 }
915
916 memcpy(&list->list[list->count], layer, sizeof(struct loader_layer_properties));
917 list->count++;
918 }
919}
920
Jon Ashburnbd332cc2015-07-07 10:27:45 -0600921/**
922 * Search the search_list for any layer with a name
923 * that matches the given name and a type that matches the given type
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600924 * Add all matching layers to the found_list
Jon Ashburnbd332cc2015-07-07 10:27:45 -0600925 * Do not add if found loader_layer_properties is already
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600926 * on the found_list.
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600927 */
Jon Ashburnbd6c4882015-07-02 12:59:25 -0600928static void loader_find_layer_name_add_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600929 const struct loader_instance *inst,
Jon Ashburnbd6c4882015-07-02 12:59:25 -0600930 const char *name,
Jon Ashburnbd332cc2015-07-07 10:27:45 -0600931 const enum layer_type type,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600932 const struct loader_layer_list *search_list,
933 struct loader_layer_list *found_list)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600934{
Jon Ashburn56151d62015-10-05 09:03:21 -0600935 bool found = false;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600936 for (uint32_t i = 0; i < search_list->count; i++) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600937 struct loader_layer_properties *layer_prop = &search_list->list[i];
Jon Ashburnbd332cc2015-07-07 10:27:45 -0600938 if (0 == strcmp(layer_prop->info.layerName, name) &&
939 (layer_prop->type & type)) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600940 /* Found a layer with the same name, add to found_list */
Jon Ashburne39a4f82015-08-28 13:38:21 -0600941 loader_add_to_layer_list(inst, found_list, 1, layer_prop);
Jon Ashburn56151d62015-10-05 09:03:21 -0600942 found = true;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600943 }
944 }
Jon Ashburn56151d62015-10-05 09:03:21 -0600945 if (!found) {
946 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Warning, couldn't find layer name %s to activate", name);
947 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600948}
949
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600950static VkExtensionProperties *get_extension_property(
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -0600951 const char *name,
952 const struct loader_extension_list *list)
Jon Ashburnfc2e38c2015-04-14 09:15:32 -0600953{
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -0600954 for (uint32_t i = 0; i < list->count; i++) {
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800955 if (strcmp(name, list->list[i].extensionName) == 0)
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -0600956 return &list->list[i];
Jon Ashburnfc2e38c2015-04-14 09:15:32 -0600957 }
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -0600958 return NULL;
Jon Ashburnfc2e38c2015-04-14 09:15:32 -0600959}
960
Jon Ashburnbd6c4882015-07-02 12:59:25 -0600961/*
962 * For global exenstions implemented within the loader (i.e. DEBUG_REPORT
963 * the extension must provide two entry points for the loader to use:
964 * - "trampoline" entry point - this is the address returned by GetProcAddr
965 * and will always do what's necessary to support a global call.
966 * - "terminator" function - this function will be put at the end of the
967 * instance chain and will contain the necessary logica to call / process
968 * the extension for the appropriate ICDs that are available.
969 * There is no generic mechanism for including these functions, the references
970 * must be placed into the appropriate loader entry points.
971 * GetInstanceProcAddr: call extension GetInstanceProcAddr to check for GetProcAddr requests
972 * loader_coalesce_extensions(void) - add extension records to the list of global
973 * extension available to the app.
974 * instance_disp - add function pointer for terminator function to this array.
975 * The extension itself should be in a separate file that will be
976 * linked directly with the loader.
977 */
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -0600978
Jon Ashburn8810c5f2015-08-18 18:04:47 -0600979void loader_get_icd_loader_instance_extensions(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600980 const struct loader_instance *inst,
Jon Ashburn8810c5f2015-08-18 18:04:47 -0600981 struct loader_icd_libs *icd_libs,
982 struct loader_extension_list *inst_exts)
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600983{
Jon Ashburn5c6a46f2015-08-14 14:49:22 -0600984 struct loader_extension_list icd_exts;
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -0600985 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, "Build ICD instance extension list");
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600986 // traverse scanned icd list adding non-duplicate extensions to the list
Jon Ashburn8810c5f2015-08-18 18:04:47 -0600987 for (uint32_t i = 0; i < icd_libs->count; i++) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600988 loader_init_ext_list(inst, &icd_exts);
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -0600989 loader_add_global_extensions(inst, icd_libs->list[i].EnumerateInstanceExtensionProperties,
Jon Ashburn8810c5f2015-08-18 18:04:47 -0600990 icd_libs->list[i].lib_name,
Jon Ashburn5c6a46f2015-08-14 14:49:22 -0600991 &icd_exts);
Jon Ashburne39a4f82015-08-28 13:38:21 -0600992 loader_add_to_ext_list(inst, inst_exts,
Jon Ashburn5c6a46f2015-08-14 14:49:22 -0600993 icd_exts.count,
994 icd_exts.list);
Jon Ashburne39a4f82015-08-28 13:38:21 -0600995 loader_destroy_ext_list(inst, &icd_exts);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600996 };
997
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600998 // Traverse loader's extensions, adding non-duplicate extensions to the list
Ian Elliott954fa342015-10-30 15:28:23 -0600999 wsi_add_instance_extensions(inst, inst_exts);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001000 debug_report_add_instance_extensions(inst, inst_exts);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001001}
1002
Jon Ashburne39a4f82015-08-28 13:38:21 -06001003struct loader_icd *loader_get_icd_and_device(const VkDevice device,
1004 struct loader_device **found_dev)
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001005{
1006 *found_dev = NULL;
1007 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
1008 for (struct loader_icd *icd = inst->icds; icd; icd = icd->next) {
1009 for (struct loader_device *dev = icd->logical_device_list; dev; dev = dev->next)
Jon Ashburne0e64572015-09-30 12:56:42 -06001010 /* Value comparison of device prevents object wrapping by layers */
1011 if (loader_get_dispatch(dev->device) == loader_get_dispatch(device)) {
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001012 *found_dev = dev;
1013 return icd;
1014 }
1015 }
1016 }
1017 return NULL;
1018}
1019
Jon Ashburne39a4f82015-08-28 13:38:21 -06001020static void loader_destroy_logical_device(const struct loader_instance *inst,
1021 struct loader_device *dev)
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001022{
Jon Ashburne39a4f82015-08-28 13:38:21 -06001023 loader_heap_free(inst, dev->app_extension_props);
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001024 if (dev->activated_layer_list.count)
Jon Ashburne39a4f82015-08-28 13:38:21 -06001025 loader_destroy_layer_list(inst, &dev->activated_layer_list);
1026 loader_heap_free(inst, dev);
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001027}
1028
Jon Ashburne39a4f82015-08-28 13:38:21 -06001029static struct loader_device *loader_add_logical_device(
1030 const struct loader_instance *inst,
1031 const VkDevice dev,
1032 struct loader_device **device_list)
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001033{
1034 struct loader_device *new_dev;
1035
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001036 new_dev = loader_heap_alloc(inst, sizeof(struct loader_device), VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001037 if (!new_dev) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06001038 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc struct laoder-device");
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001039 return NULL;
1040 }
1041
1042 memset(new_dev, 0, sizeof(struct loader_device));
1043
1044 new_dev->next = *device_list;
1045 new_dev->device = dev;
1046 *device_list = new_dev;
1047 return new_dev;
1048}
1049
Jon Ashburne39a4f82015-08-28 13:38:21 -06001050void loader_remove_logical_device(
1051 const struct loader_instance *inst,
Jon Ashburn781a7ae2015-11-19 15:43:26 -07001052 struct loader_icd *icd,
1053 struct loader_device *found_dev)
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001054{
Jon Ashburn781a7ae2015-11-19 15:43:26 -07001055 struct loader_device *dev, *prev_dev;
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001056
1057 if (!icd || !found_dev)
1058 return;
1059
1060 prev_dev = NULL;
1061 dev = icd->logical_device_list;
1062 while (dev && dev != found_dev) {
1063 prev_dev = dev;
1064 dev = dev->next;
1065 }
1066
1067 if (prev_dev)
1068 prev_dev->next = found_dev->next;
1069 else
1070 icd->logical_device_list = found_dev->next;
Jon Ashburne39a4f82015-08-28 13:38:21 -06001071 loader_destroy_logical_device(inst, found_dev);
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001072}
1073
1074
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001075static void loader_icd_destroy(
1076 struct loader_instance *ptr_inst,
1077 struct loader_icd *icd)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001078{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001079 ptr_inst->total_icd_count--;
Courtney Goeltzenleuchter1f157ac2015-06-14 19:57:15 -06001080 for (struct loader_device *dev = icd->logical_device_list; dev; ) {
1081 struct loader_device *next_dev = dev->next;
Jon Ashburne39a4f82015-08-28 13:38:21 -06001082 loader_destroy_logical_device(ptr_inst, dev);
Courtney Goeltzenleuchter1f157ac2015-06-14 19:57:15 -06001083 dev = next_dev;
1084 }
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001085
Jon Ashburne39a4f82015-08-28 13:38:21 -06001086 loader_heap_free(ptr_inst, icd);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001087}
1088
Jon Ashburne39a4f82015-08-28 13:38:21 -06001089static struct loader_icd * loader_icd_create(const struct loader_instance *inst)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001090{
1091 struct loader_icd *icd;
1092
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001093 icd = loader_heap_alloc(inst, sizeof(*icd), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001094 if (!icd)
1095 return NULL;
1096
Courtney Goeltzenleuchter55001bb2014-10-28 10:29:27 -06001097 memset(icd, 0, sizeof(*icd));
1098
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001099 return icd;
1100}
1101
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001102static struct loader_icd *loader_icd_add(
1103 struct loader_instance *ptr_inst,
Jon Ashburn3d002332015-08-20 16:35:30 -06001104 const struct loader_scanned_icds *icd_lib)
Chia-I Wu13a61a52014-08-04 11:18:20 +08001105{
1106 struct loader_icd *icd;
1107
Jon Ashburne39a4f82015-08-28 13:38:21 -06001108 icd = loader_icd_create(ptr_inst);
Chia-I Wu13a61a52014-08-04 11:18:20 +08001109 if (!icd)
1110 return NULL;
1111
Jon Ashburn3d002332015-08-20 16:35:30 -06001112 icd->this_icd_lib = icd_lib;
1113 icd->this_instance = ptr_inst;
1114
Chia-I Wu13a61a52014-08-04 11:18:20 +08001115 /* prepend to the list */
Jon Ashburn46888392015-01-29 15:45:51 -07001116 icd->next = ptr_inst->icds;
1117 ptr_inst->icds = icd;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001118 ptr_inst->total_icd_count++;
Chia-I Wu13a61a52014-08-04 11:18:20 +08001119
1120 return icd;
1121}
1122
Jon Ashburne39a4f82015-08-28 13:38:21 -06001123void loader_scanned_icd_clear(
1124 const struct loader_instance *inst,
1125 struct loader_icd_libs *icd_libs)
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001126{
1127 if (icd_libs->capacity == 0)
1128 return;
1129 for (uint32_t i = 0; i < icd_libs->count; i++) {
1130 loader_platform_close_library(icd_libs->list[i].handle);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001131 loader_heap_free(inst, icd_libs->list[i].lib_name);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001132 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06001133 loader_heap_free(inst, icd_libs->list);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001134 icd_libs->capacity = 0;
1135 icd_libs->count = 0;
1136 icd_libs->list = NULL;
1137}
1138
Jon Ashburne39a4f82015-08-28 13:38:21 -06001139static void loader_scanned_icd_init(const struct loader_instance *inst,
1140 struct loader_icd_libs *icd_libs)
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001141{
Jon Ashburne39a4f82015-08-28 13:38:21 -06001142 loader_scanned_icd_clear(inst, icd_libs);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001143 icd_libs->capacity = 8 * sizeof(struct loader_scanned_icds);
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001144 icd_libs->list = loader_heap_alloc(inst, icd_libs->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001145
1146}
1147
1148static void loader_scanned_icd_add(
Jon Ashburne39a4f82015-08-28 13:38:21 -06001149 const struct loader_instance *inst,
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001150 struct loader_icd_libs *icd_libs,
Jon Ashburn005617f2015-11-17 17:35:40 -07001151 const char *filename,
1152 uint32_t api_version)
Jon Ashburn46d1f582015-01-28 11:01:35 -07001153{
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001154 loader_platform_dl_handle handle;
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06001155 PFN_vkCreateInstance fp_create_inst;
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06001156 PFN_vkEnumerateInstanceExtensionProperties fp_get_global_ext_props;
Jon Ashburnc624c882015-07-16 10:17:29 -06001157 PFN_vkGetInstanceProcAddr fp_get_proc_addr;
Jon Ashburn46d1f582015-01-28 11:01:35 -07001158 struct loader_scanned_icds *new_node;
1159
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001160 /* TODO implement ref counting of libraries, for now this function leaves
1161 libraries open and the scanned_icd_clear closes them */
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001162 // Used to call: dlopen(filename, RTLD_LAZY);
1163 handle = loader_platform_open_library(filename);
Jon Ashburn46d1f582015-01-28 11:01:35 -07001164 if (!handle) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001165 loader_log(VK_DBG_REPORT_WARN_BIT, 0, loader_platform_open_library_error(filename));
Jon Ashburn46d1f582015-01-28 11:01:35 -07001166 return;
1167 }
1168
Jon Ashburnc624c882015-07-16 10:17:29 -06001169#define LOOKUP_LD(func_ptr, func) do { \
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -06001170 func_ptr = (PFN_vk ##func) loader_platform_get_proc_address(handle, "vk" #func); \
Jon Ashburn46d1f582015-01-28 11:01:35 -07001171 if (!func_ptr) { \
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001172 loader_log(VK_DBG_REPORT_WARN_BIT, 0, loader_platform_get_proc_address_error("vk" #func)); \
Jon Ashburn46d1f582015-01-28 11:01:35 -07001173 return; \
1174 } \
1175} while (0)
1176
Jon Ashburnc624c882015-07-16 10:17:29 -06001177 LOOKUP_LD(fp_get_proc_addr, GetInstanceProcAddr);
1178 LOOKUP_LD(fp_create_inst, CreateInstance);
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06001179 LOOKUP_LD(fp_get_global_ext_props, EnumerateInstanceExtensionProperties);
Jon Ashburnc624c882015-07-16 10:17:29 -06001180
1181#undef LOOKUP_LD
Jon Ashburn46d1f582015-01-28 11:01:35 -07001182
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001183 // check for enough capacity
1184 if ((icd_libs->count * sizeof(struct loader_scanned_icds)) >= icd_libs->capacity) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06001185
1186 icd_libs->list = loader_heap_realloc(inst,
1187 icd_libs->list,
1188 icd_libs->capacity,
1189 icd_libs->capacity * 2,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001190 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001191 // double capacity
1192 icd_libs->capacity *= 2;
Jon Ashburn46d1f582015-01-28 11:01:35 -07001193 }
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001194 new_node = &(icd_libs->list[icd_libs->count]);
Jon Ashburn46d1f582015-01-28 11:01:35 -07001195
1196 new_node->handle = handle;
Jon Ashburn005617f2015-11-17 17:35:40 -07001197 new_node->api_version = api_version;
Jon Ashburnc624c882015-07-16 10:17:29 -06001198 new_node->GetInstanceProcAddr = fp_get_proc_addr;
Jon Ashburn46888392015-01-29 15:45:51 -07001199 new_node->CreateInstance = fp_create_inst;
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06001200 new_node->EnumerateInstanceExtensionProperties = fp_get_global_ext_props;
Jon Ashburn46d1f582015-01-28 11:01:35 -07001201
Jon Ashburne39a4f82015-08-28 13:38:21 -06001202 new_node->lib_name = (char *) loader_heap_alloc(inst,
1203 strlen(filename) + 1,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001204 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001205 if (!new_node->lib_name) {
1206 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Out of memory can't add icd");
1207 return;
1208 }
1209 strcpy(new_node->lib_name, filename);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001210 icd_libs->count++;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001211}
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001212
Jon Ashburnc624c882015-07-16 10:17:29 -06001213static bool loader_icd_init_entrys(struct loader_icd *icd,
1214 VkInstance inst,
1215 const PFN_vkGetInstanceProcAddr fp_gipa)
Jon Ashburn3da71f22015-05-14 12:43:38 -06001216{
1217 /* initialize entrypoint function pointers */
1218
Jon Ashburnc624c882015-07-16 10:17:29 -06001219 #define LOOKUP_GIPA(func, required) do { \
1220 icd->func = (PFN_vk ##func) fp_gipa(inst, "vk" #func); \
1221 if (!icd->func && required) { \
1222 loader_log(VK_DBG_REPORT_WARN_BIT, 0, \
1223 loader_platform_get_proc_address_error("vk" #func)); \
1224 return false; \
1225 } \
Jon Ashburn3da71f22015-05-14 12:43:38 -06001226 } while (0)
1227
Jon Ashburnc624c882015-07-16 10:17:29 -06001228 LOOKUP_GIPA(GetDeviceProcAddr, true);
1229 LOOKUP_GIPA(DestroyInstance, true);
1230 LOOKUP_GIPA(EnumeratePhysicalDevices, true);
1231 LOOKUP_GIPA(GetPhysicalDeviceFeatures, true);
1232 LOOKUP_GIPA(GetPhysicalDeviceFormatProperties, true);
Jon Ashburn754864f2015-07-23 18:49:07 -06001233 LOOKUP_GIPA(GetPhysicalDeviceImageFormatProperties, true);
Jon Ashburnc624c882015-07-16 10:17:29 -06001234 LOOKUP_GIPA(CreateDevice, true);
1235 LOOKUP_GIPA(GetPhysicalDeviceProperties, true);
1236 LOOKUP_GIPA(GetPhysicalDeviceMemoryProperties, true);
Cody Northropd0802882015-08-03 17:04:53 -06001237 LOOKUP_GIPA(GetPhysicalDeviceQueueFamilyProperties, true);
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06001238 LOOKUP_GIPA(EnumerateDeviceExtensionProperties, true);
Jon Ashburnc624c882015-07-16 10:17:29 -06001239 LOOKUP_GIPA(GetPhysicalDeviceSparseImageFormatProperties, true);
1240 LOOKUP_GIPA(DbgCreateMsgCallback, false);
1241 LOOKUP_GIPA(DbgDestroyMsgCallback, false);
Ian Elliott7e40db92015-08-21 15:09:33 -06001242 LOOKUP_GIPA(GetPhysicalDeviceSurfaceSupportKHR, false);
Ian Elliott486c5502015-11-19 16:05:09 -07001243 LOOKUP_GIPA(GetPhysicalDeviceSurfaceCapabilitiesKHR, false);
1244 LOOKUP_GIPA(GetPhysicalDeviceSurfaceFormatsKHR, false);
1245 LOOKUP_GIPA(GetPhysicalDeviceSurfacePresentModesKHR, false);
Ian Elliott919fa302015-11-24 15:39:10 -07001246#ifdef VK_USE_PLATFORM_WIN32_KHR
1247 LOOKUP_GIPA(GetPhysicalDeviceWin32PresentationSupportKHR, false);
1248#endif
1249#ifdef VK_USE_PLATFORM_XCB_KHR
1250 LOOKUP_GIPA(GetPhysicalDeviceXcbPresentationSupportKHR, false);
1251#endif
Jon Ashburn3da71f22015-05-14 12:43:38 -06001252
Jon Ashburnc624c882015-07-16 10:17:29 -06001253#undef LOOKUP_GIPA
Ian Elliottd3ef02f2015-07-06 14:36:13 -06001254
Jon Ashburnc624c882015-07-16 10:17:29 -06001255 return true;
Jon Ashburn3da71f22015-05-14 12:43:38 -06001256}
1257
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001258static void loader_debug_init(void)
1259{
1260 const char *env;
1261
1262 if (g_loader_debug > 0)
1263 return;
1264
1265 g_loader_debug = 0;
1266
1267 /* parse comma-separated debug options */
Courtney Goeltzenleuchterfce60db2015-07-29 09:08:22 -06001268 env = getenv("VK_LOADER_DEBUG");
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001269 while (env) {
1270 const char *p = strchr(env, ',');
1271 size_t len;
1272
1273 if (p)
1274 len = p - env;
1275 else
1276 len = strlen(env);
1277
1278 if (len > 0) {
1279 if (strncmp(env, "warn", len) == 0) {
1280 g_loader_debug |= LOADER_WARN_BIT;
1281 g_loader_log_msgs |= VK_DBG_REPORT_WARN_BIT;
1282 } else if (strncmp(env, "info", len) == 0) {
1283 g_loader_debug |= LOADER_INFO_BIT;
1284 g_loader_log_msgs |= VK_DBG_REPORT_INFO_BIT;
1285 } else if (strncmp(env, "perf", len) == 0) {
1286 g_loader_debug |= LOADER_PERF_BIT;
1287 g_loader_log_msgs |= VK_DBG_REPORT_PERF_WARN_BIT;
1288 } else if (strncmp(env, "error", len) == 0) {
1289 g_loader_debug |= LOADER_ERROR_BIT;
1290 g_loader_log_msgs |= VK_DBG_REPORT_ERROR_BIT;
1291 } else if (strncmp(env, "debug", len) == 0) {
1292 g_loader_debug |= LOADER_DEBUG_BIT;
1293 g_loader_log_msgs |= VK_DBG_REPORT_DEBUG_BIT;
1294 }
1295 }
1296
1297 if (!p)
1298 break;
1299
1300 env = p + 1;
1301 }
1302}
1303
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001304void loader_initialize(void)
1305{
Jon Ashburn6461ef22015-09-22 13:11:00 -06001306 // initialize mutexs
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001307 loader_platform_thread_create_mutex(&loader_lock);
Jon Ashburn6461ef22015-09-22 13:11:00 -06001308 loader_platform_thread_create_mutex(&loader_json_lock);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001309
1310 // initialize logging
1311 loader_debug_init();
Jon Ashburn87d6aa92015-08-28 15:19:27 -06001312
1313 // initial cJSON to use alloc callbacks
1314 cJSON_Hooks alloc_fns = {
1315 .malloc_fn = loader_tls_heap_alloc,
1316 .free_fn = loader_tls_heap_free,
1317 };
1318 cJSON_InitHooks(&alloc_fns);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001319}
1320
Jon Ashburn2077e382015-06-29 11:25:34 -06001321struct loader_manifest_files {
1322 uint32_t count;
1323 char **filename_list;
1324};
1325
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06001326/**
Jon Ashburn2077e382015-06-29 11:25:34 -06001327 * Get next file or dirname given a string list or registry key path
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06001328 *
1329 * \returns
Jon Ashburn2077e382015-06-29 11:25:34 -06001330 * A pointer to first char in the next path.
1331 * The next path (or NULL) in the list is returned in next_path.
1332 * Note: input string is modified in some cases. PASS IN A COPY!
1333 */
Jon Ashburn2077e382015-06-29 11:25:34 -06001334static char *loader_get_next_path(char *path)
1335{
1336 uint32_t len;
1337 char *next;
1338
1339 if (path == NULL)
1340 return NULL;
1341 next = strchr(path, PATH_SEPERATOR);
1342 if (next == NULL) {
1343 len = (uint32_t) strlen(path);
1344 next = path + len;
1345 }
1346 else {
1347 *next = '\0';
1348 next++;
1349 }
1350
1351 return next;
1352}
1353
1354/**
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001355 * Given a path which is absolute or relative, expand the path if relative or
1356 * leave the path unmodified if absolute. The base path to prepend to relative
1357 * paths is given in rel_base.
Jon Ashburn15315172015-07-07 15:06:25 -06001358 *
1359 * \returns
1360 * A string in out_fullpath of the full absolute path
Jon Ashburn15315172015-07-07 15:06:25 -06001361 */
1362static void loader_expand_path(const char *path,
1363 const char *rel_base,
1364 size_t out_size,
1365 char *out_fullpath)
1366{
1367 if (loader_platform_is_path_absolute(path)) {
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001368 // do not prepend a base to an absolute path
1369 rel_base = "";
Jon Ashburn15315172015-07-07 15:06:25 -06001370 }
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001371
1372 loader_platform_combine_path(out_fullpath, out_size, rel_base, path, NULL);
Jon Ashburn15315172015-07-07 15:06:25 -06001373}
1374
1375/**
Jon Ashburn2077e382015-06-29 11:25:34 -06001376 * Given a filename (file) and a list of paths (dir), try to find an existing
1377 * file in the paths. If filename already is a path then no
1378 * searching in the given paths.
1379 *
1380 * \returns
1381 * A string in out_fullpath of either the full path or file.
Jon Ashburn2077e382015-06-29 11:25:34 -06001382 */
1383static void loader_get_fullpath(const char *file,
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001384 const char *dirs,
Jon Ashburn2077e382015-06-29 11:25:34 -06001385 size_t out_size,
1386 char *out_fullpath)
1387{
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001388 if (!loader_platform_is_path(file) && *dirs) {
1389 char *dirs_copy, *dir, *next_dir;
1390
1391 dirs_copy = loader_stack_alloc(strlen(dirs) + 1);
1392 strcpy(dirs_copy, dirs);
1393
1394 //find if file exists after prepending paths in given list
1395 for (dir = dirs_copy;
1396 *dir && (next_dir = loader_get_next_path(dir));
1397 dir = next_dir) {
1398 loader_platform_combine_path(out_fullpath, out_size, dir, file, NULL);
Jon Ashburn2077e382015-06-29 11:25:34 -06001399 if (loader_platform_file_exists(out_fullpath)) {
1400 return;
1401 }
Jon Ashburn2077e382015-06-29 11:25:34 -06001402 }
1403 }
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001404
Jon Ashburn2077e382015-06-29 11:25:34 -06001405 snprintf(out_fullpath, out_size, "%s", file);
1406}
1407
1408/**
1409 * Read a JSON file into a buffer.
1410 *
1411 * \returns
1412 * A pointer to a cJSON object representing the JSON parse tree.
1413 * This returned buffer should be freed by caller.
1414 */
1415static cJSON *loader_get_json(const char *filename)
1416{
1417 FILE *file;
1418 char *json_buf;
1419 cJSON *json;
1420 uint64_t len;
1421 file = fopen(filename,"rb");
Jon Ashburnaa4ea472015-08-27 08:30:50 -06001422 if (!file) {
1423 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Couldn't open JSON file %s", filename);
1424 return NULL;
1425 }
Jon Ashburn2077e382015-06-29 11:25:34 -06001426 fseek(file, 0, SEEK_END);
1427 len = ftell(file);
1428 fseek(file, 0, SEEK_SET);
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -06001429 json_buf = (char*) loader_stack_alloc(len+1);
Jon Ashburn2077e382015-06-29 11:25:34 -06001430 if (json_buf == NULL) {
1431 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get JSON file");
1432 fclose(file);
1433 return NULL;
1434 }
1435 if (fread(json_buf, sizeof(char), len, file) != len) {
1436 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "fread failed can't get JSON file");
1437 fclose(file);
1438 return NULL;
1439 }
1440 fclose(file);
1441 json_buf[len] = '\0';
1442
1443 //parse text from file
1444 json = cJSON_Parse(json_buf);
1445 if (json == NULL)
1446 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Can't parse JSON file %s", filename);
1447 return json;
1448}
1449
1450/**
Jon Ashburn3d002332015-08-20 16:35:30 -06001451 * Do a deep copy of the loader_layer_properties structure.
1452 */
1453static void loader_copy_layer_properties(
Jon Ashburne39a4f82015-08-28 13:38:21 -06001454 const struct loader_instance *inst,
Jon Ashburn3d002332015-08-20 16:35:30 -06001455 struct loader_layer_properties *dst,
1456 struct loader_layer_properties *src)
1457{
1458 memcpy(dst, src, sizeof (*src));
Jon Ashburne39a4f82015-08-28 13:38:21 -06001459 dst->instance_extension_list.list = loader_heap_alloc(
1460 inst,
1461 sizeof(VkExtensionProperties) *
1462 src->instance_extension_list.count,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001463 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001464 dst->instance_extension_list.capacity = sizeof(VkExtensionProperties) *
1465 src->instance_extension_list.count;
1466 memcpy(dst->instance_extension_list.list, src->instance_extension_list.list,
1467 dst->instance_extension_list.capacity);
1468 dst->device_extension_list.list = loader_heap_alloc(
1469 inst,
1470 sizeof(VkExtensionProperties) *
1471 src->device_extension_list.count,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001472 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001473 dst->device_extension_list.capacity = sizeof(VkExtensionProperties) *
1474 src->device_extension_list.count;
1475 memcpy(dst->device_extension_list.list, src->device_extension_list.list,
1476 dst->device_extension_list.capacity);
Jon Ashburn3d002332015-08-20 16:35:30 -06001477}
1478
1479/**
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001480 * Given a cJSON struct (json) of the top level JSON object from layer manifest
1481 * file, add entry to the layer_list.
Jon Ashburne13ecc92015-08-03 17:19:30 -06001482 * Fill out the layer_properties in this list entry from the input cJSON object.
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001483 *
1484 * \returns
1485 * void
1486 * layer_list has a new entry and initialized accordingly.
1487 * If the json input object does not have all the required fields no entry
1488 * is added to the list.
1489 */
Jon Ashburne39a4f82015-08-28 13:38:21 -06001490static void loader_add_layer_properties(const struct loader_instance *inst,
1491 struct loader_layer_list *layer_instance_list,
Jon Ashburnb2ef1372015-07-16 17:19:31 -06001492 struct loader_layer_list *layer_device_list,
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001493 cJSON *json,
1494 bool is_implicit,
1495 char *filename)
1496{
1497 /* Fields in layer manifest file that are required:
1498 * (required) “file_format_version”
1499 * following are required in the "layer" object:
1500 * (required) "name"
1501 * (required) "type"
1502 * (required) “library_path”
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001503 * (required) “api_version”
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001504 * (required) “implementation_version”
1505 * (required) “description”
1506 * (required for implicit layers) “disable_environment”
1507 *
1508 * First get all required items and if any missing abort
1509 */
1510
1511 cJSON *item, *layer_node, *ext_item;
1512 char *temp;
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001513 char *name, *type, *library_path, *api_version;
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001514 char *implementation_version, *description;
1515 cJSON *disable_environment;
1516 int i;
Jon Ashburn5c042ea2015-08-04 11:14:18 -06001517 VkExtensionProperties ext_prop;
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001518 item = cJSON_GetObjectItem(json, "file_format_version");
1519 if (item == NULL) {
1520 return;
1521 }
1522 char *file_vers = cJSON_PrintUnformatted(item);
1523 loader_log(VK_DBG_REPORT_INFO_BIT, 0, "Found manifest file %s, version %s",
1524 filename, file_vers);
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001525 if (strcmp(file_vers, "\"1.0.0\"") != 0)
1526 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Unexpected manifest file version (expected 1.0.0), may cause errors");
Jon Ashburn87d6aa92015-08-28 15:19:27 -06001527 loader_tls_heap_free(file_vers);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001528
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001529 layer_node = cJSON_GetObjectItem(json, "layer");
1530 if (layer_node == NULL) {
1531 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"layer\" object in manifest JSON file, skipping");
1532 return;
1533 }
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001534
1535 // loop through all "layer" objects in the file
1536 do {
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001537#define GET_JSON_OBJECT(node, var) { \
1538 var = cJSON_GetObjectItem(node, #var); \
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001539 if (var == NULL) { \
1540 layer_node = layer_node->next; \
1541 continue; \
1542 } \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001543 }
1544#define GET_JSON_ITEM(node, var) { \
1545 item = cJSON_GetObjectItem(node, #var); \
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001546 if (item == NULL) { \
1547 layer_node = layer_node->next; \
1548 continue; \
1549 } \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001550 temp = cJSON_Print(item); \
1551 temp[strlen(temp) - 1] = '\0'; \
Jon Ashburnf73e9212015-08-04 10:22:33 -06001552 var = loader_stack_alloc(strlen(temp) + 1); \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001553 strcpy(var, &temp[1]); \
Jon Ashburn87d6aa92015-08-28 15:19:27 -06001554 loader_tls_heap_free(temp); \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001555 }
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001556 GET_JSON_ITEM(layer_node, name)
1557 GET_JSON_ITEM(layer_node, type)
1558 GET_JSON_ITEM(layer_node, library_path)
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001559 GET_JSON_ITEM(layer_node, api_version)
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001560 GET_JSON_ITEM(layer_node, implementation_version)
1561 GET_JSON_ITEM(layer_node, description)
1562 if (is_implicit) {
1563 GET_JSON_OBJECT(layer_node, disable_environment)
1564 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001565#undef GET_JSON_ITEM
1566#undef GET_JSON_OBJECT
1567
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001568 // add list entry
Jon Ashburn432d2762015-09-18 12:53:16 -06001569 struct loader_layer_properties *props=NULL;
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001570 if (!strcmp(type, "DEVICE")) {
1571 if (layer_device_list == NULL) {
1572 layer_node = layer_node->next;
1573 continue;
1574 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06001575 props = loader_get_next_layer_property(inst, layer_device_list);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001576 props->type = (is_implicit) ? VK_LAYER_TYPE_DEVICE_IMPLICIT : VK_LAYER_TYPE_DEVICE_EXPLICIT;
1577 }
1578 if (!strcmp(type, "INSTANCE")) {
1579 if (layer_instance_list == NULL) {
1580 layer_node = layer_node->next;
1581 continue;
1582 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06001583 props = loader_get_next_layer_property(inst, layer_instance_list);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001584 props->type = (is_implicit) ? VK_LAYER_TYPE_INSTANCE_IMPLICIT : VK_LAYER_TYPE_INSTANCE_EXPLICIT;
1585 }
1586 if (!strcmp(type, "GLOBAL")) {
1587 if (layer_instance_list != NULL)
Jon Ashburne39a4f82015-08-28 13:38:21 -06001588 props = loader_get_next_layer_property(inst, layer_instance_list);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001589 else if (layer_device_list != NULL)
Jon Ashburne39a4f82015-08-28 13:38:21 -06001590 props = loader_get_next_layer_property(inst, layer_device_list);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001591 else {
1592 layer_node = layer_node->next;
1593 continue;
1594 }
1595 props->type = (is_implicit) ? VK_LAYER_TYPE_GLOBAL_IMPLICIT : VK_LAYER_TYPE_GLOBAL_EXPLICIT;
1596 }
Jon Ashburnb2ef1372015-07-16 17:19:31 -06001597
Jon Ashburn432d2762015-09-18 12:53:16 -06001598 if (props == NULL) {
1599 layer_node = layer_node->next;
1600 continue;
1601 }
1602
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001603 strncpy(props->info.layerName, name, sizeof (props->info.layerName));
1604 props->info.layerName[sizeof (props->info.layerName) - 1] = '\0';
Jon Ashburn15315172015-07-07 15:06:25 -06001605
Jon Ashburn3d002332015-08-20 16:35:30 -06001606 char *fullpath = props->lib_name;
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001607 char *rel_base;
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001608 if (loader_platform_is_path(filename)) {
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001609 // a relative or absolute path
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001610 char *name_copy = loader_stack_alloc(strlen(filename) + 1);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001611 strcpy(name_copy, filename);
1612 rel_base = loader_platform_dirname(name_copy);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001613 loader_expand_path(library_path, rel_base, MAX_STRING_SIZE, fullpath);
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001614 } else {
1615 // a filename which is assumed in a system directory
1616 loader_get_fullpath(library_path, DEFAULT_VK_LAYERS_PATH, MAX_STRING_SIZE, fullpath);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001617 }
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001618 props->info.specVersion = loader_make_version(api_version);
1619 props->info.implementationVersion = atoi(implementation_version);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001620 strncpy((char *) props->info.description, description, sizeof (props->info.description));
1621 props->info.description[sizeof (props->info.description) - 1] = '\0';
1622 if (is_implicit) {
1623 strncpy(props->disable_env_var.name, disable_environment->child->string, sizeof (props->disable_env_var.name));
1624 props->disable_env_var.name[sizeof (props->disable_env_var.name) - 1] = '\0';
1625 strncpy(props->disable_env_var.value, disable_environment->child->valuestring, sizeof (props->disable_env_var.value));
1626 props->disable_env_var.value[sizeof (props->disable_env_var.value) - 1] = '\0';
1627 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001628
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001629 /**
1630 * Now get all optional items and objects and put in list:
1631 * functions
1632 * instance_extensions
1633 * device_extensions
1634 * enable_environment (implicit layers only)
1635 */
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001636#define GET_JSON_OBJECT(node, var) { \
1637 var = cJSON_GetObjectItem(node, #var); \
1638 }
1639#define GET_JSON_ITEM(node, var) { \
1640 item = cJSON_GetObjectItem(node, #var); \
Jon Ashburn21c21ee2015-09-09 11:29:24 -06001641 if (item != NULL) { \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001642 temp = cJSON_Print(item); \
Jon Ashburn21c21ee2015-09-09 11:29:24 -06001643 temp[strlen(temp) - 1] = '\0'; \
1644 var = loader_stack_alloc(strlen(temp) + 1);\
1645 strcpy(var, &temp[1]); \
1646 loader_tls_heap_free(temp); \
1647 } \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001648 }
1649
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001650 cJSON *instance_extensions, *device_extensions, *functions, *enable_environment;
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001651 char *vkGetInstanceProcAddr = NULL, *vkGetDeviceProcAddr = NULL, *spec_version=NULL;
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001652 GET_JSON_OBJECT(layer_node, functions)
1653 if (functions != NULL) {
1654 GET_JSON_ITEM(functions, vkGetInstanceProcAddr)
1655 GET_JSON_ITEM(functions, vkGetDeviceProcAddr)
Jon Ashburn21c21ee2015-09-09 11:29:24 -06001656 if (vkGetInstanceProcAddr != NULL)
1657 strncpy(props->functions.str_gipa, vkGetInstanceProcAddr, sizeof (props->functions.str_gipa));
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001658 props->functions.str_gipa[sizeof (props->functions.str_gipa) - 1] = '\0';
Jon Ashburn21c21ee2015-09-09 11:29:24 -06001659 if (vkGetDeviceProcAddr != NULL)
1660 strncpy(props->functions.str_gdpa, vkGetDeviceProcAddr, sizeof (props->functions.str_gdpa));
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001661 props->functions.str_gdpa[sizeof (props->functions.str_gdpa) - 1] = '\0';
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001662 }
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001663 GET_JSON_OBJECT(layer_node, instance_extensions)
1664 if (instance_extensions != NULL) {
1665 int count = cJSON_GetArraySize(instance_extensions);
1666 for (i = 0; i < count; i++) {
1667 ext_item = cJSON_GetArrayItem(instance_extensions, i);
1668 GET_JSON_ITEM(ext_item, name)
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001669 GET_JSON_ITEM(ext_item, spec_version)
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001670 strncpy(ext_prop.extensionName, name, sizeof (ext_prop.extensionName));
1671 ext_prop.extensionName[sizeof (ext_prop.extensionName) - 1] = '\0';
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001672 ext_prop.specVersion = atoi(spec_version);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001673 loader_add_to_ext_list(inst, &props->instance_extension_list, 1, &ext_prop);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001674 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001675 }
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001676 GET_JSON_OBJECT(layer_node, device_extensions)
1677 if (device_extensions != NULL) {
1678 int count = cJSON_GetArraySize(device_extensions);
1679 for (i = 0; i < count; i++) {
1680 ext_item = cJSON_GetArrayItem(device_extensions, i);
1681 GET_JSON_ITEM(ext_item, name);
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001682 GET_JSON_ITEM(ext_item, spec_version);
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001683 strncpy(ext_prop.extensionName, name, sizeof (ext_prop.extensionName));
1684 ext_prop.extensionName[sizeof (ext_prop.extensionName) - 1] = '\0';
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001685 ext_prop.specVersion = atoi(spec_version);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001686 loader_add_to_ext_list(inst, &props->device_extension_list, 1, &ext_prop);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001687 }
1688 }
1689 if (is_implicit) {
1690 GET_JSON_OBJECT(layer_node, enable_environment)
1691 strncpy(props->enable_env_var.name, enable_environment->child->string, sizeof (props->enable_env_var.name));
1692 props->enable_env_var.name[sizeof (props->enable_env_var.name) - 1] = '\0';
1693 strncpy(props->enable_env_var.value, enable_environment->child->valuestring, sizeof (props->enable_env_var.value));
1694 props->enable_env_var.value[sizeof (props->enable_env_var.value) - 1] = '\0';
1695 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001696#undef GET_JSON_ITEM
1697#undef GET_JSON_OBJECT
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001698 // for global layers need to add them to both device and instance list
1699 if (!strcmp(type, "GLOBAL")) {
1700 struct loader_layer_properties *dev_props;
1701 if (layer_instance_list == NULL || layer_device_list == NULL) {
1702 layer_node = layer_node->next;
1703 continue;
1704 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06001705 dev_props = loader_get_next_layer_property(inst, layer_device_list);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001706 //copy into device layer list
Jon Ashburne39a4f82015-08-28 13:38:21 -06001707 loader_copy_layer_properties(inst, dev_props, props);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001708 }
1709 layer_node = layer_node->next;
1710 } while (layer_node != NULL);
1711 return;
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001712}
1713
1714/**
Jon Ashburn2077e382015-06-29 11:25:34 -06001715 * Find the Vulkan library manifest files.
1716 *
1717 * This function scans the location or env_override directories/files
1718 * for a list of JSON manifest files. If env_override is non-NULL
1719 * and has a valid value. Then the location is ignored. Otherwise
1720 * location is used to look for manifest files. The location
1721 * is interpreted as Registry path on Windows and a directory path(s)
1722 * on Linux.
1723 *
1724 * \returns
1725 * A string list of manifest files to be opened in out_files param.
1726 * List has a pointer to string for each manifest filename.
1727 * When done using the list in out_files, pointers should be freed.
Jon Ashburnffad94d2015-06-30 14:46:22 -07001728 * Location or override string lists can be either files or directories as follows:
1729 * | location | override
1730 * --------------------------------
1731 * Win ICD | files | files
1732 * Win Layer | files | dirs
1733 * Linux ICD | dirs | files
1734 * Linux Layer| dirs | dirs
Jon Ashburn2077e382015-06-29 11:25:34 -06001735 */
Jon Ashburne39a4f82015-08-28 13:38:21 -06001736static void loader_get_manifest_files(const struct loader_instance *inst,
1737 const char *env_override,
Jon Ashburnffad94d2015-06-30 14:46:22 -07001738 bool is_layer,
1739 const char *location,
1740 struct loader_manifest_files *out_files)
Jon Ashburn2077e382015-06-29 11:25:34 -06001741{
1742 char *override = NULL;
1743 char *loc;
1744 char *file, *next_file, *name;
1745 size_t alloced_count = 64;
1746 char full_path[2048];
1747 DIR *sysdir = NULL;
Jon Ashburnffad94d2015-06-30 14:46:22 -07001748 bool list_is_dirs = false;
Jon Ashburn2077e382015-06-29 11:25:34 -06001749 struct dirent *dent;
1750
1751 out_files->count = 0;
1752 out_files->filename_list = NULL;
1753
Jon Ashburn2077e382015-06-29 11:25:34 -06001754 if (env_override != NULL && (override = getenv(env_override))) {
Johannes van Waveren9bd805012015-10-28 11:45:00 -05001755#if !defined(_WIN32)
Jon Ashburn2077e382015-06-29 11:25:34 -06001756 if (geteuid() != getuid()) {
Jon Ashburnffad94d2015-06-30 14:46:22 -07001757 /* Don't allow setuid apps to use the env var: */
Jon Ashburn2077e382015-06-29 11:25:34 -06001758 override = NULL;
1759 }
1760#endif
1761 }
1762
1763 if (location == NULL) {
1764 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
Jon Ashburnffad94d2015-06-30 14:46:22 -07001765 "Can't get manifest files with NULL location, env_override=%s",
1766 env_override);
Jon Ashburn2077e382015-06-29 11:25:34 -06001767 return;
1768 }
1769
Johannes van Waveren9bd805012015-10-28 11:45:00 -05001770#if defined(_WIN32)
Jon Ashburnffad94d2015-06-30 14:46:22 -07001771 list_is_dirs = (is_layer && override != NULL) ? true : false;
Johannes van Waveren9bd805012015-10-28 11:45:00 -05001772#else
1773 list_is_dirs = (override == NULL || is_layer) ? true : false;
Jon Ashburnffad94d2015-06-30 14:46:22 -07001774#endif
Jon Ashburn2077e382015-06-29 11:25:34 -06001775 // Make a copy of the input we are using so it is not modified
Jon Ashburnffad94d2015-06-30 14:46:22 -07001776 // Also handle getting the location(s) from registry on Windows
1777 if (override == NULL) {
Jon Ashburn3b78e462015-07-31 10:11:24 -06001778 loc = loader_stack_alloc(strlen(location) + 1);
Jon Ashburnffad94d2015-06-30 14:46:22 -07001779 if (loc == NULL) {
1780 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files");
1781 return;
1782 }
1783 strcpy(loc, location);
Johannes van Waveren9bd805012015-10-28 11:45:00 -05001784#if defined(_WIN32)
Jon Ashburn480a50a2015-08-28 14:58:46 -07001785 loc = loader_get_registry_files(inst, loc);
Jon Ashburn24265ac2015-07-31 09:33:21 -06001786 if (loc == NULL) {
1787 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Registry lookup failed can't get manifest files");
1788 return;
1789 }
Jon Ashburnffad94d2015-06-30 14:46:22 -07001790#endif
Jon Ashburn2077e382015-06-29 11:25:34 -06001791 }
Jon Ashburnffad94d2015-06-30 14:46:22 -07001792 else {
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -06001793 loc = loader_stack_alloc(strlen(override) + 1);
Jon Ashburnffad94d2015-06-30 14:46:22 -07001794 if (loc == NULL) {
1795 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files");
1796 return;
1797 }
1798 strcpy(loc, override);
1799 }
Jon Ashburn2077e382015-06-29 11:25:34 -06001800
Liam Middlebrook9b14e892015-07-23 18:32:20 -07001801 // Print out the paths being searched if debugging is enabled
Jon Ashburn46e20d82015-07-31 09:41:31 -06001802 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, "Searching the following paths for manifest files: %s\n", loc);
Liam Middlebrook9b14e892015-07-23 18:32:20 -07001803
Jon Ashburn2077e382015-06-29 11:25:34 -06001804 file = loc;
1805 while (*file) {
1806 next_file = loader_get_next_path(file);
Jon Ashburnffad94d2015-06-30 14:46:22 -07001807 if (list_is_dirs) {
Jon Ashburn2077e382015-06-29 11:25:34 -06001808 sysdir = opendir(file);
1809 name = NULL;
1810 if (sysdir) {
1811 dent = readdir(sysdir);
1812 if (dent == NULL)
1813 break;
1814 name = &(dent->d_name[0]);
1815 loader_get_fullpath(name, file, sizeof(full_path), full_path);
1816 name = full_path;
1817 }
1818 }
1819 else {
Johannes van Waveren9bd805012015-10-28 11:45:00 -05001820#if defined(_WIN32)
1821 name = file;
1822#else
Jon Ashburnffad94d2015-06-30 14:46:22 -07001823 // only Linux has relative paths
Jon Ashburn2077e382015-06-29 11:25:34 -06001824 char *dir;
1825 // make a copy of location so it isn't modified
Jason Ekstrandcc7550e2015-10-10 08:33:37 -07001826 dir = loader_stack_alloc(strlen(loc) + 1);
Jon Ashburn2077e382015-06-29 11:25:34 -06001827 if (dir == NULL) {
1828 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files");
1829 return;
1830 }
Jason Ekstrandcc7550e2015-10-10 08:33:37 -07001831 strcpy(dir, loc);
Jon Ashburn2077e382015-06-29 11:25:34 -06001832
1833 loader_get_fullpath(file, dir, sizeof(full_path), full_path);
1834
1835 name = full_path;
Jon Ashburnffad94d2015-06-30 14:46:22 -07001836#endif
Jon Ashburn2077e382015-06-29 11:25:34 -06001837 }
1838 while (name) {
1839 /* Look for files ending with ".json" suffix */
1840 uint32_t nlen = (uint32_t) strlen(name);
1841 const char *suf = name + nlen - 5;
1842 if ((nlen > 5) && !strncmp(suf, ".json", 5)) {
1843 if (out_files->count == 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06001844 out_files->filename_list = loader_heap_alloc(inst,
1845 alloced_count * sizeof(char *),
Chia-I Wucf804e82015-10-31 00:31:16 +08001846 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
Jon Ashburn2077e382015-06-29 11:25:34 -06001847 }
1848 else if (out_files->count == alloced_count) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06001849 out_files->filename_list = loader_heap_realloc(inst,
1850 out_files->filename_list,
1851 alloced_count * sizeof(char *),
1852 alloced_count * sizeof(char *) * 2,
Chia-I Wucf804e82015-10-31 00:31:16 +08001853 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
Jon Ashburn2077e382015-06-29 11:25:34 -06001854 alloced_count *= 2;
1855 }
1856 if (out_files->filename_list == NULL) {
1857 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't alloc manifest file list");
1858 return;
1859 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06001860 out_files->filename_list[out_files->count] = loader_heap_alloc(
1861 inst,
1862 strlen(name) + 1,
Chia-I Wucf804e82015-10-31 00:31:16 +08001863 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
Jon Ashburn2077e382015-06-29 11:25:34 -06001864 if (out_files->filename_list[out_files->count] == NULL) {
1865 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files");
1866 return;
1867 }
1868 strcpy(out_files->filename_list[out_files->count], name);
1869 out_files->count++;
Jon Ashburnf70f3612015-07-02 10:08:47 -06001870 } else if (!list_is_dirs) {
1871 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Skipping manifest file %s, file name must end in .json", name);
Jon Ashburn2077e382015-06-29 11:25:34 -06001872 }
Jon Ashburnffad94d2015-06-30 14:46:22 -07001873 if (list_is_dirs) {
Jon Ashburn2077e382015-06-29 11:25:34 -06001874 dent = readdir(sysdir);
1875 if (dent == NULL)
1876 break;
1877 name = &(dent->d_name[0]);
1878 loader_get_fullpath(name, file, sizeof(full_path), full_path);
1879 name = full_path;
1880 }
1881 else {
1882 break;
1883 }
1884 }
1885 if (sysdir)
1886 closedir(sysdir);
1887 file = next_file;
1888 }
1889 return;
1890}
1891
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001892void loader_init_icd_lib_list()
1893{
1894
1895}
1896
1897void loader_destroy_icd_lib_list()
1898{
1899
1900}
Jon Ashburn2077e382015-06-29 11:25:34 -06001901/**
1902 * Try to find the Vulkan ICD driver(s).
1903 *
1904 * This function scans the default system loader path(s) or path
1905 * specified by the \c VK_ICD_FILENAMES environment variable in
1906 * order to find loadable VK ICDs manifest files. From these
1907 * manifest files it finds the ICD libraries.
1908 *
1909 * \returns
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001910 * a list of icds that were discovered
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06001911 */
Jon Ashburne39a4f82015-08-28 13:38:21 -06001912void loader_icd_scan(
1913 const struct loader_instance *inst,
1914 struct loader_icd_libs *icds)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001915{
Jon Ashburn2077e382015-06-29 11:25:34 -06001916 char *file_str;
1917 struct loader_manifest_files manifest_files;
1918
Jon Ashburne39a4f82015-08-28 13:38:21 -06001919 loader_scanned_icd_init(inst, icds);
Jon Ashburn2077e382015-06-29 11:25:34 -06001920 // Get a list of manifest files for ICDs
Jon Ashburne39a4f82015-08-28 13:38:21 -06001921 loader_get_manifest_files(inst, "VK_ICD_FILENAMES", false,
1922 DEFAULT_VK_DRIVERS_INFO, &manifest_files);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001923 if (manifest_files.count == 0)
1924 return;
Jon Ashburn6461ef22015-09-22 13:11:00 -06001925 loader_platform_thread_lock_mutex(&loader_json_lock);
Jon Ashburn2077e382015-06-29 11:25:34 -06001926 for (uint32_t i = 0; i < manifest_files.count; i++) {
1927 file_str = manifest_files.filename_list[i];
1928 if (file_str == NULL)
1929 continue;
1930
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001931 cJSON *json;
Jon Ashburn2077e382015-06-29 11:25:34 -06001932 json = loader_get_json(file_str);
Jon Ashburnaa4ea472015-08-27 08:30:50 -06001933 if (!json)
1934 continue;
Jon Ashburn005617f2015-11-17 17:35:40 -07001935 cJSON *item, *itemICD;
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001936 item = cJSON_GetObjectItem(json, "file_format_version");
Jon Ashburn6461ef22015-09-22 13:11:00 -06001937 if (item == NULL) {
1938 loader_platform_thread_unlock_mutex(&loader_json_lock);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001939 return;
Jon Ashburn6461ef22015-09-22 13:11:00 -06001940 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001941 char *file_vers = cJSON_Print(item);
1942 loader_log(VK_DBG_REPORT_INFO_BIT, 0, "Found manifest file %s, version %s",
1943 file_str, file_vers);
1944 if (strcmp(file_vers, "\"1.0.0\"") != 0)
1945 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Unexpected manifest file version (expected 1.0.0), may cause errors");
Jon Ashburn87d6aa92015-08-28 15:19:27 -06001946 loader_tls_heap_free(file_vers);
Jon Ashburn005617f2015-11-17 17:35:40 -07001947 itemICD = cJSON_GetObjectItem(json, "ICD");
1948 if (itemICD != NULL) {
1949 item = cJSON_GetObjectItem(itemICD, "library_path");
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001950 if (item != NULL) {
Jon Ashburn86251302015-08-25 16:48:24 -06001951 char *temp= cJSON_Print(item);
1952 if (!temp || strlen(temp) == 0) {
1953 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"library_path\" in ICD JSON file %s, skipping", file_str);
Jon Ashburn87d6aa92015-08-28 15:19:27 -06001954 loader_tls_heap_free(temp);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001955 loader_heap_free(inst, file_str);
Jon Ashburn86251302015-08-25 16:48:24 -06001956 cJSON_Delete(json);
1957 continue;
Jon Ashburn2077e382015-06-29 11:25:34 -06001958 }
Jon Ashburn86251302015-08-25 16:48:24 -06001959 //strip out extra quotes
1960 temp[strlen(temp) - 1] = '\0';
1961 char *library_path = loader_stack_alloc(strlen(temp) + 1);
1962 strcpy(library_path, &temp[1]);
Jon Ashburn87d6aa92015-08-28 15:19:27 -06001963 loader_tls_heap_free(temp);
Jon Ashburn86251302015-08-25 16:48:24 -06001964 if (!library_path || strlen(library_path) == 0) {
1965 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"library_path\" in ICD JSON file %s, skipping", file_str);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001966 loader_heap_free(inst, file_str);
Jon Ashburn86251302015-08-25 16:48:24 -06001967 cJSON_Delete(json);
1968 continue;
1969 }
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001970 char fullpath[MAX_STRING_SIZE];
Jon Ashburn86251302015-08-25 16:48:24 -06001971 // Print out the paths being searched if debugging is enabled
1972 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, "Searching for ICD drivers named %s default dir %s\n", library_path, DEFAULT_VK_DRIVERS_PATH);
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001973 if (loader_platform_is_path(library_path)) {
Jon Ashburn86251302015-08-25 16:48:24 -06001974 // a relative or absolute path
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001975 char *name_copy = loader_stack_alloc(strlen(file_str) + 1);
1976 char *rel_base;
Jon Ashburn86251302015-08-25 16:48:24 -06001977 strcpy(name_copy, file_str);
1978 rel_base = loader_platform_dirname(name_copy);
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001979 loader_expand_path(library_path, rel_base, sizeof(fullpath), fullpath);
1980 } else {
1981 // a filename which is assumed in a system directory
1982 loader_get_fullpath(library_path, DEFAULT_VK_DRIVERS_PATH, sizeof(fullpath), fullpath);
Jon Ashburn86251302015-08-25 16:48:24 -06001983 }
Jon Ashburn005617f2015-11-17 17:35:40 -07001984
1985 uint32_t vers = 0;
1986 item = cJSON_GetObjectItem(itemICD, "api_version");
1987 if (item != NULL) {
1988 temp= cJSON_Print(item);
1989 vers = loader_make_version(temp);
1990 loader_tls_heap_free(temp);
1991 }
1992 loader_scanned_icd_add(inst, icds, fullpath, vers);
Jon Ashburn2077e382015-06-29 11:25:34 -06001993 }
Jon Ashburn005617f2015-11-17 17:35:40 -07001994 else
1995 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"library_path\" object in ICD JSON file %s, skipping", file_str);
Jon Ashburn2077e382015-06-29 11:25:34 -06001996 }
1997 else
1998 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"ICD\" object in ICD JSON file %s, skipping", file_str);
1999
Jon Ashburne39a4f82015-08-28 13:38:21 -06002000 loader_heap_free(inst, file_str);
Jon Ashburn2077e382015-06-29 11:25:34 -06002001 cJSON_Delete(json);
2002 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06002003 loader_heap_free(inst, manifest_files.filename_list);
Jon Ashburn6461ef22015-09-22 13:11:00 -06002004 loader_platform_thread_unlock_mutex(&loader_json_lock);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08002005}
2006
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002007
Jon Ashburne39a4f82015-08-28 13:38:21 -06002008void loader_layer_scan(
2009 const struct loader_instance *inst,
2010 struct loader_layer_list *instance_layers,
2011 struct loader_layer_list *device_layers)
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002012{
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002013 char *file_str;
2014 struct loader_manifest_files manifest_files;
2015 cJSON *json;
2016 uint32_t i;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002017
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002018 // Get a list of manifest files for layers
Jon Ashburne39a4f82015-08-28 13:38:21 -06002019 loader_get_manifest_files(inst, LAYERS_PATH_ENV, true, DEFAULT_VK_LAYERS_INFO,
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002020 &manifest_files);
2021 if (manifest_files.count == 0)
Courtney Goeltzenleuchter57985ce2014-12-01 09:29:42 -07002022 return;
Jon Ashburn90c6a0e2015-06-04 15:30:58 -06002023
Jon Ashburne13ecc92015-08-03 17:19:30 -06002024#if 0 //TODO
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002025 /**
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -06002026 * We need a list of the layer libraries, not just a list of
2027 * the layer properties (a layer library could expose more than
2028 * one layer property). This list of scanned layers would be
2029 * used to check for global and physicaldevice layer properties.
2030 */
2031 if (!loader_init_layer_library_list(&loader.scanned_layer_libraries)) {
2032 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
Jon Ashburne39a4f82015-08-28 13:38:21 -06002033 "Alloc for layer list failed: %s line: %d", __FILE__, __LINE__);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -06002034 return;
Jon Ashburn5ef20602015-07-02 09:40:15 -06002035 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002036#endif
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002037
Jon Ashburne13ecc92015-08-03 17:19:30 -06002038 /* cleanup any previously scanned libraries */
Jon Ashburne39a4f82015-08-28 13:38:21 -06002039 loader_delete_layer_properties(inst, instance_layers);
2040 loader_delete_layer_properties(inst, device_layers);
Jon Ashburnb2ef1372015-07-16 17:19:31 -06002041
Jon Ashburn6461ef22015-09-22 13:11:00 -06002042 loader_platform_thread_lock_mutex(&loader_json_lock);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002043 for (i = 0; i < manifest_files.count; i++) {
2044 file_str = manifest_files.filename_list[i];
2045 if (file_str == NULL)
2046 continue;
Courtney Goeltzenleuchtera9e4af42015-06-01 14:49:17 -06002047
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002048 // parse file into JSON struct
2049 json = loader_get_json(file_str);
2050 if (!json) {
2051 continue;
2052 }
Jon Ashburne13ecc92015-08-03 17:19:30 -06002053
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002054 //TODO pass in implicit versus explicit bool
Jon Ashburnb2ef1372015-07-16 17:19:31 -06002055 //TODO error if device layers expose instance_extensions
2056 //TODO error if instance layers expose device extensions
Jon Ashburne39a4f82015-08-28 13:38:21 -06002057 loader_add_layer_properties(inst,
2058 instance_layers,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002059 device_layers,
Jon Ashburnb2ef1372015-07-16 17:19:31 -06002060 json,
2061 false,
2062 file_str);
2063
Jon Ashburne39a4f82015-08-28 13:38:21 -06002064 loader_heap_free(inst, file_str);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002065 cJSON_Delete(json);
2066 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06002067 loader_heap_free(inst, manifest_files.filename_list);
Jon Ashburn6461ef22015-09-22 13:11:00 -06002068 loader_platform_thread_unlock_mutex(&loader_json_lock);
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002069}
2070
Chia-I Wu9ab61502015-11-06 06:42:02 +08002071static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL loader_gpa_instance_internal(VkInstance inst, const char * pName)
Jon Ashburn27cd5842015-05-12 17:26:48 -06002072{
2073 // inst is not wrapped
2074 if (inst == VK_NULL_HANDLE) {
2075 return NULL;
2076 }
2077 VkLayerInstanceDispatchTable* disp_table = * (VkLayerInstanceDispatchTable **) inst;
2078 void *addr;
2079
Jon Ashburn8fd08252015-05-28 16:25:02 -06002080 if (!strcmp(pName, "vkGetInstanceProcAddr"))
2081 return (void *) loader_gpa_instance_internal;
2082
Jon Ashburn27cd5842015-05-12 17:26:48 -06002083 if (disp_table == NULL)
2084 return NULL;
2085
2086 addr = loader_lookup_instance_dispatch_table(disp_table, pName);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002087 if (addr) {
Jon Ashburn27cd5842015-05-12 17:26:48 -06002088 return addr;
Jon Ashburn3d526cb2015-04-13 18:10:06 -06002089 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002090
2091 if (disp_table->GetInstanceProcAddr == NULL) {
2092 return NULL;
2093 }
2094 return disp_table->GetInstanceProcAddr(inst, pName);
Jon Ashburn3d526cb2015-04-13 18:10:06 -06002095}
2096
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002097/**
2098 * Initialize device_ext dispatch table entry as follows:
2099 * If dev == NULL find all logical devices created within this instance and
2100 * init the entry (given by idx) in the ext dispatch table.
2101 * If dev != NULL only initialize the entry in the given dev's dispatch table.
2102 * The initialization value is gotten by calling down the device chain with GDPA.
2103 * If GDPA returns NULL then don't initialize the dispatch table entry.
2104 */
2105static void loader_init_dispatch_dev_ext_entry(struct loader_instance *inst,
2106 struct loader_device *dev,
2107 uint32_t idx,
2108 const char *funcName)
2109
2110 {
2111 void *gdpa_value;
2112 if (dev != NULL) {
2113 gdpa_value = dev->loader_dispatch.core_dispatch.GetDeviceProcAddr(
2114 dev->device, funcName);
2115 if (gdpa_value != NULL)
2116 dev->loader_dispatch.ext_dispatch.DevExt[idx] = (PFN_vkDevExt) gdpa_value;
2117 } else {
2118 for (uint32_t i = 0; i < inst->total_icd_count; i++) {
2119 struct loader_icd *icd = &inst->icds[i];
2120 struct loader_device *dev = icd->logical_device_list;
2121 while (dev) {
2122 gdpa_value = dev->loader_dispatch.core_dispatch.GetDeviceProcAddr(
2123 dev->device, funcName);
2124 if (gdpa_value != NULL)
2125 dev->loader_dispatch.ext_dispatch.DevExt[idx] =
2126 (PFN_vkDevExt) gdpa_value;
2127 dev = dev->next;
2128 }
2129 }
2130 }
2131
2132}
2133
2134/**
2135 * Find all dev extension in the hash table and initialize the dispatch table
2136 * for dev for each of those extension entrypoints found in hash table.
2137
2138 */
2139static void loader_init_dispatch_dev_ext(struct loader_instance *inst,
2140 struct loader_device *dev)
2141{
2142 for (uint32_t i = 0; i < MAX_NUM_DEV_EXTS; i++) {
2143 if (inst->disp_hash[i].func_name != NULL)
2144 loader_init_dispatch_dev_ext_entry(inst, dev, i,
2145 inst->disp_hash[i].func_name);
2146 }
2147}
2148
2149static bool loader_check_icds_for_address(struct loader_instance *inst,
2150 const char *funcName)
2151{
2152 struct loader_icd *icd;
2153 icd = inst->icds;
2154 while (icd) {
2155 if (icd->this_icd_lib->GetInstanceProcAddr(icd->instance, funcName))
2156 // this icd supports funcName
2157 return true;
2158 icd = icd->next;
2159 }
2160
2161 return false;
2162}
2163
2164static void loader_free_dev_ext_table(struct loader_instance *inst)
2165{
2166 for (uint32_t i = 0; i < MAX_NUM_DEV_EXTS; i++) {
2167 loader_heap_free(inst, inst->disp_hash[i].func_name);
2168 loader_heap_free(inst, inst->disp_hash[i].list.index);
2169
2170 }
2171 memset(inst->disp_hash, 0, sizeof(inst->disp_hash));
2172}
2173
2174static bool loader_add_dev_ext_table(struct loader_instance *inst,
2175 uint32_t *ptr_idx,
2176 const char *funcName)
2177{
2178 uint32_t i;
2179 uint32_t idx = *ptr_idx;
2180 struct loader_dispatch_hash_list *list = &inst->disp_hash[idx].list;
2181
2182 if (!inst->disp_hash[idx].func_name) {
2183 // no entry here at this idx, so use it
2184 assert(list->capacity == 0);
2185 inst->disp_hash[idx].func_name = (char *) loader_heap_alloc(inst,
2186 strlen(funcName) + 1,
2187 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
2188 if (inst->disp_hash[idx].func_name == NULL) {
2189 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
2190 "loader_add_dev_ext_table() can't allocate memory for func_name");
2191 return false;
2192 }
2193 strncpy(inst->disp_hash[idx].func_name, funcName, strlen(funcName) + 1);
2194 return true;
2195 }
2196
2197 // check for enough capacity
2198 if (list->capacity == 0) {
2199 list->index = loader_heap_alloc(inst, 8 * sizeof(*(list->index)),
2200 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
2201 if (list->index == NULL) {
2202 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
2203 "loader_add_dev_ext_table() can't allocate list memory");
2204 return false;
2205 }
2206 list->capacity = 8 * sizeof(*(list->index));
2207 } else if (list->capacity < (list->count + 1) * sizeof(*(list->index))) {
2208 list->index = loader_heap_realloc(inst, list->index, list->capacity,
2209 list->capacity * 2,
2210 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
2211 if (list->index == NULL) {
2212 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
2213 "loader_add_dev_ext_table() can't reallocate list memory");
2214 return false;
2215 }
2216 list->capacity *= 2;
2217 }
2218
2219 //find an unused index in the hash table and use it
2220 i = (idx + 1) % MAX_NUM_DEV_EXTS;
2221 do {
2222 if (!inst->disp_hash[i].func_name) {
2223 assert(inst->disp_hash[i].list.capacity == 0);
2224 inst->disp_hash[i].func_name = (char *) loader_heap_alloc(inst,
2225 strlen(funcName) + 1,
2226 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
2227 if (inst->disp_hash[i].func_name == NULL) {
2228 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
2229 "loader_add_dev_ext_table() can't rallocate func_name memory");
2230 return false;
2231 }
2232 strncpy(inst->disp_hash[i].func_name, funcName, strlen(funcName) + 1);
2233 list->index[list->count] = i;
2234 list->count++;
2235 *ptr_idx = i;
2236 return true;
2237 }
2238 i = (i + 1) % MAX_NUM_DEV_EXTS;
2239 } while (i != idx);
2240
2241 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
2242 "loader_add_dev_ext_table() couldn't insert into hash table; is it full?");
2243 return false;
2244}
2245
2246static bool loader_name_in_dev_ext_table(struct loader_instance *inst,
2247 uint32_t *idx,
2248 const char *funcName)
2249{
2250 uint32_t alt_idx;
2251 if (inst->disp_hash[*idx].func_name && !strcmp(
2252 inst->disp_hash[*idx].func_name,
2253 funcName))
2254 return true;
2255
2256 // funcName wasn't at the primary spot in the hash table
2257 // search the list of secondary locations (shallow search, not deep search)
2258 for (uint32_t i = 0; i < inst->disp_hash[*idx].list.count; i++) {
2259 alt_idx = inst->disp_hash[*idx].list.index[i];
2260 if (!strcmp(inst->disp_hash[*idx].func_name, funcName)) {
2261 *idx = alt_idx;
2262 return true;
2263 }
2264 }
2265
2266 return false;
2267}
2268
2269/**
2270 * This function returns generic trampoline code address for unknown entry points.
2271 * Presumably, these unknown entry points (as given by funcName) are device
2272 * extension entrypoints. A hash table is used to keep a list of unknown entry
2273 * points and their mapping to the device extension dispatch table
2274 * (struct loader_dev_ext_dispatch_table).
2275 * \returns
2276 * For a given entry point string (funcName), if an existing mapping is found the
2277 * trampoline address for that mapping is returned. Otherwise, this unknown entry point
2278 * has not been seen yet. Next check if a layer or ICD supports it. If so then a
2279 * new entry in the hash table is initialized and that trampoline address for
2280 * the new entry is returned. Null is returned if the hash table is full or
2281 * if no discovered layer or ICD returns a non-NULL GetProcAddr for it.
2282 */
2283void *loader_dev_ext_gpa(struct loader_instance *inst,
2284 const char *funcName)
2285{
2286 uint32_t idx;
2287 uint32_t seed = 0;
2288
2289 idx = murmurhash(funcName, strlen(funcName), seed) % MAX_NUM_DEV_EXTS;
2290
2291 if (loader_name_in_dev_ext_table(inst, &idx, funcName))
2292 // found funcName already in hash
2293 return loader_get_dev_ext_trampoline(idx);
2294
2295 // Check if funcName is supported in either ICDs or a layer library
2296 if (!loader_check_icds_for_address(inst, funcName)) {
2297 // TODO Add check in layer libraries for support of address
2298 // if support found in layers continue on
2299 return NULL;
2300 }
2301
2302 if (loader_add_dev_ext_table(inst, &idx, funcName)) {
2303 // successfully added new table entry
2304 // init any dev dispatch table entrys as needed
2305 loader_init_dispatch_dev_ext_entry(inst, NULL, idx, funcName);
2306 return loader_get_dev_ext_trampoline(idx);
2307 }
2308
2309 return NULL;
2310}
2311
Jon Ashburne0e64572015-09-30 12:56:42 -06002312struct loader_instance *loader_get_instance(const VkInstance instance)
2313{
2314 /* look up the loader_instance in our list by comparing dispatch tables, as
2315 * there is no guarantee the instance is still a loader_instance* after any
2316 * layers which wrap the instance object.
2317 */
2318 const VkLayerInstanceDispatchTable *disp;
2319 struct loader_instance *ptr_instance = NULL;
2320 disp = loader_get_instance_dispatch(instance);
2321 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
2322 if (inst->disp == disp) {
2323 ptr_instance = inst;
2324 break;
2325 }
2326 }
2327 return ptr_instance;
2328}
2329
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002330static loader_platform_dl_handle loader_add_layer_lib(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002331 const struct loader_instance *inst,
Jon Ashburn4f67d742015-05-27 13:19:22 -06002332 const char *chain_type,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002333 struct loader_layer_properties *layer_prop)
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002334{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002335 struct loader_lib_info *new_layer_lib_list, *my_lib;
Jon Ashburne39a4f82015-08-28 13:38:21 -06002336 size_t new_alloc_size;
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -06002337 /*
2338 * TODO: We can now track this information in the
2339 * scanned_layer_libraries list.
2340 */
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002341 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) {
Jon Ashburn3d002332015-08-20 16:35:30 -06002342 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, layer_prop->lib_name) == 0) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002343 /* Have already loaded this library, just increment ref count */
2344 loader.loaded_layer_lib_list[i].ref_count++;
Courtney Goeltzenleuchterca8c81a2015-06-14 11:59:07 -06002345 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002346 "%s Chain: Increment layer reference count for layer library %s",
Jon Ashburn3d002332015-08-20 16:35:30 -06002347 chain_type, layer_prop->lib_name);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002348 return loader.loaded_layer_lib_list[i].lib_handle;
2349 }
2350 }
2351
2352 /* Haven't seen this library so load it */
Jon Ashburne39a4f82015-08-28 13:38:21 -06002353 new_alloc_size = 0;
2354 if (loader.loaded_layer_lib_capacity == 0)
2355 new_alloc_size = 8 * sizeof(struct loader_lib_info);
2356 else if (loader.loaded_layer_lib_capacity <= loader.loaded_layer_lib_count *
2357 sizeof(struct loader_lib_info))
2358 new_alloc_size = loader.loaded_layer_lib_capacity * 2;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002359
Jon Ashburne39a4f82015-08-28 13:38:21 -06002360 if (new_alloc_size) {
2361 new_layer_lib_list = loader_heap_realloc(
2362 inst, loader.loaded_layer_lib_list,
2363 loader.loaded_layer_lib_capacity,
2364 new_alloc_size,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002365 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburne39a4f82015-08-28 13:38:21 -06002366 if (!new_layer_lib_list) {
2367 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "loader: realloc failed in loader_add_layer_lib");
2368 return NULL;
2369 }
2370 loader.loaded_layer_lib_capacity = new_alloc_size;
2371 } else
2372 new_layer_lib_list = loader.loaded_layer_lib_list;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002373 my_lib = &new_layer_lib_list[loader.loaded_layer_lib_count];
2374
Jon Ashburn3d002332015-08-20 16:35:30 -06002375 strncpy(my_lib->lib_name, layer_prop->lib_name, sizeof(my_lib->lib_name));
2376 my_lib->lib_name[sizeof(my_lib->lib_name) - 1] = '\0';
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002377 my_lib->ref_count = 0;
2378 my_lib->lib_handle = NULL;
2379
2380 if ((my_lib->lib_handle = loader_platform_open_library(my_lib->lib_name)) == NULL) {
2381 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
2382 loader_platform_open_library_error(my_lib->lib_name));
2383 return NULL;
2384 } else {
Courtney Goeltzenleuchterca8c81a2015-06-14 11:59:07 -06002385 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002386 "Chain: %s: Loading layer library %s",
Jon Ashburn3d002332015-08-20 16:35:30 -06002387 chain_type, layer_prop->lib_name);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002388 }
2389 loader.loaded_layer_lib_count++;
2390 loader.loaded_layer_lib_list = new_layer_lib_list;
2391 my_lib->ref_count++;
2392
2393 return my_lib->lib_handle;
2394}
2395
2396static void loader_remove_layer_lib(
2397 struct loader_instance *inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002398 struct loader_layer_properties *layer_prop)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002399{
2400 uint32_t idx;
Tony Barbourb5d2c942015-07-14 13:34:05 -06002401 struct loader_lib_info *new_layer_lib_list, *my_lib = NULL;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002402
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002403 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) {
Jon Ashburn3d002332015-08-20 16:35:30 -06002404 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, layer_prop->lib_name) == 0) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002405 /* found matching library */
2406 idx = i;
2407 my_lib = &loader.loaded_layer_lib_list[i];
2408 break;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002409 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002410 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002411
Tony Barbourb5d2c942015-07-14 13:34:05 -06002412 if (my_lib) {
2413 my_lib->ref_count--;
2414 if (my_lib->ref_count > 0) {
2415 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Jon Ashburn3d002332015-08-20 16:35:30 -06002416 "Decrement reference count for layer library %s", layer_prop->lib_name);
Tony Barbourb5d2c942015-07-14 13:34:05 -06002417 return;
2418 }
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07002419 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002420 loader_platform_close_library(my_lib->lib_handle);
Courtney Goeltzenleuchterca8c81a2015-06-14 11:59:07 -06002421 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Jon Ashburn3d002332015-08-20 16:35:30 -06002422 "Unloading layer library %s", layer_prop->lib_name);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002423
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002424 /* Need to remove unused library from list */
Jon Ashburne39a4f82015-08-28 13:38:21 -06002425 new_layer_lib_list = loader_heap_alloc(inst,
2426 loader.loaded_layer_lib_capacity,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002427 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002428 if (!new_layer_lib_list) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06002429 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "loader: heap alloc failed loader_remove_layer_library");
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002430 return;
2431 }
2432
2433 if (idx > 0) {
2434 /* Copy records before idx */
2435 memcpy(new_layer_lib_list, &loader.loaded_layer_lib_list[0],
2436 sizeof(struct loader_lib_info) * idx);
2437 }
2438 if (idx < (loader.loaded_layer_lib_count - 1)) {
2439 /* Copy records after idx */
2440 memcpy(&new_layer_lib_list[idx], &loader.loaded_layer_lib_list[idx+1],
2441 sizeof(struct loader_lib_info) * (loader.loaded_layer_lib_count - idx - 1));
2442 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002443
Jon Ashburne39a4f82015-08-28 13:38:21 -06002444 loader_heap_free(inst, loader.loaded_layer_lib_list);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002445 loader.loaded_layer_lib_count--;
2446 loader.loaded_layer_lib_list = new_layer_lib_list;
Jon Ashburnb8358052014-11-18 09:06:04 -07002447}
2448
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002449
2450/**
2451 * Go through the search_list and find any layers which match type. If layer
2452 * type match is found in then add it to ext_list.
2453 */
2454//TODO need to handle implict layer enable env var and disable env var
Jon Ashburn0c26e712015-07-02 16:10:32 -06002455static void loader_add_layer_implicit(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002456 const struct loader_instance *inst,
Jon Ashburn0c26e712015-07-02 16:10:32 -06002457 const enum layer_type type,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002458 struct loader_layer_list *list,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002459 const struct loader_layer_list *search_list)
Jon Ashburn0c26e712015-07-02 16:10:32 -06002460{
2461 uint32_t i;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002462 for (i = 0; i < search_list->count; i++) {
2463 const struct loader_layer_properties *prop = &search_list->list[i];
Jon Ashburn0c26e712015-07-02 16:10:32 -06002464 if (prop->type & type) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002465 /* Found an layer with the same type, add to layer_list */
Jon Ashburne39a4f82015-08-28 13:38:21 -06002466 loader_add_to_layer_list(inst, list, 1, prop);
Jon Ashburn0c26e712015-07-02 16:10:32 -06002467 }
2468 }
2469
2470}
2471
2472/**
2473 * Get the layer name(s) from the env_name environment variable. If layer
Jon Ashburnbd332cc2015-07-07 10:27:45 -06002474 * is found in search_list then add it to layer_list. But only add it to
2475 * layer_list if type matches.
Jon Ashburn0c26e712015-07-02 16:10:32 -06002476 */
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002477static void loader_add_layer_env(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002478 const struct loader_instance *inst,
Jon Ashburnbd332cc2015-07-07 10:27:45 -06002479 const enum layer_type type,
Jon Ashburneb6d5682015-07-02 14:10:53 -06002480 const char *env_name,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002481 struct loader_layer_list *layer_list,
2482 const struct loader_layer_list *search_list)
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002483{
Ian Elliott4470a302015-02-17 10:33:47 -07002484 char *layerEnv;
Jon Ashburneb6d5682015-07-02 14:10:53 -06002485 char *next, *name;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002486
Jon Ashburneb6d5682015-07-02 14:10:53 -06002487 layerEnv = getenv(env_name);
Ian Elliott4470a302015-02-17 10:33:47 -07002488 if (layerEnv == NULL) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002489 return;
Ian Elliott4470a302015-02-17 10:33:47 -07002490 }
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -06002491 name = loader_stack_alloc(strlen(layerEnv) + 1);
Jon Ashburneb6d5682015-07-02 14:10:53 -06002492 if (name == NULL) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002493 return;
Ian Elliott4470a302015-02-17 10:33:47 -07002494 }
Jon Ashburneb6d5682015-07-02 14:10:53 -06002495 strcpy(name, layerEnv);
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002496
Jon Ashburneb6d5682015-07-02 14:10:53 -06002497 while (name && *name ) {
2498 next = loader_get_next_path(name);
Jon Ashburne39a4f82015-08-28 13:38:21 -06002499 loader_find_layer_name_add_list(inst, name, type, search_list, layer_list);
Jon Ashburneb6d5682015-07-02 14:10:53 -06002500 name = next;
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07002501 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002502
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002503 return;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002504}
2505
Courtney Goeltzenleuchter7d0023c2015-06-08 15:09:22 -06002506void loader_deactivate_instance_layers(struct loader_instance *instance)
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002507{
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002508 if (!instance->activated_layer_list.count) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002509 return;
2510 }
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002511
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002512 /* Create instance chain of enabled layers */
Courtney Goeltzenleuchter7d0023c2015-06-08 15:09:22 -06002513 for (uint32_t i = 0; i < instance->activated_layer_list.count; i++) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002514 struct loader_layer_properties *layer_prop = &instance->activated_layer_list.list[i];
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002515
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002516 loader_remove_layer_lib(instance, layer_prop);
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002517 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06002518 loader_destroy_layer_list(instance, &instance->activated_layer_list);
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002519}
2520
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002521VkResult loader_enable_instance_layers(
Jon Ashburnb82c1852015-08-11 14:49:54 -06002522 struct loader_instance *inst,
2523 const VkInstanceCreateInfo *pCreateInfo,
2524 const struct loader_layer_list *instance_layers)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002525{
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002526 VkResult err;
2527
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06002528 assert(inst && "Cannot have null instance");
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002529
Jon Ashburne39a4f82015-08-28 13:38:21 -06002530 if (!loader_init_layer_list(inst, &inst->activated_layer_list)) {
2531 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc Instance activated layer list");
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002532 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002533 }
2534
Jon Ashburn0c26e712015-07-02 16:10:32 -06002535 /* Add any implicit layers first */
2536 loader_add_layer_implicit(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002537 inst,
Jon Ashburn0c26e712015-07-02 16:10:32 -06002538 VK_LAYER_TYPE_INSTANCE_IMPLICIT,
2539 &inst->activated_layer_list,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002540 instance_layers);
Jon Ashburn0c26e712015-07-02 16:10:32 -06002541
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002542 /* Add any layers specified via environment variable next */
Jon Ashburneb6d5682015-07-02 14:10:53 -06002543 loader_add_layer_env(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002544 inst,
Jon Ashburnbd332cc2015-07-07 10:27:45 -06002545 VK_LAYER_TYPE_INSTANCE_EXPLICIT,
Jon Ashburneb6d5682015-07-02 14:10:53 -06002546 "VK_INSTANCE_LAYERS",
2547 &inst->activated_layer_list,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002548 instance_layers);
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002549
2550 /* Add layers specified by the application */
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002551 err = loader_add_layer_names_to_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002552 inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002553 &inst->activated_layer_list,
Chia-I Wud50a7d72015-10-26 20:48:51 +08002554 pCreateInfo->enabledLayerNameCount,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002555 pCreateInfo->ppEnabledLayerNames,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002556 instance_layers);
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002557
2558 return err;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002559}
2560
Jon Ashburn27cd5842015-05-12 17:26:48 -06002561uint32_t loader_activate_instance_layers(struct loader_instance *inst)
2562{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002563 uint32_t layer_idx;
Jon Ashburn128f9422015-05-28 19:16:58 -06002564 VkBaseLayerObject *wrappedInstance;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002565
David Pinedoa0a8a242015-06-24 15:29:18 -06002566 if (inst == NULL) {
Jon Ashburn27cd5842015-05-12 17:26:48 -06002567 return 0;
David Pinedoa0a8a242015-06-24 15:29:18 -06002568 }
Jon Ashburn27cd5842015-05-12 17:26:48 -06002569
2570 // NOTE inst is unwrapped at this point in time
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002571 void* baseObj = (void*) inst;
2572 void* nextObj = (void*) inst;
Jon Ashburn27cd5842015-05-12 17:26:48 -06002573 VkBaseLayerObject *nextInstObj;
2574 PFN_vkGetInstanceProcAddr nextGPA = loader_gpa_instance_internal;
2575
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002576 if (!inst->activated_layer_list.count) {
Courtney Goeltzenleuchtered1a8dd2015-08-07 09:53:18 -06002577 loader_init_instance_core_dispatch_table(inst->disp, nextGPA, (VkInstance) nextObj, (VkInstance) baseObj);
Jon Ashburn27cd5842015-05-12 17:26:48 -06002578 return 0;
2579 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002580
Courtney Goeltzenleuchter6f460c52015-07-06 09:04:55 -06002581 wrappedInstance = loader_stack_alloc(sizeof(VkBaseLayerObject)
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002582 * inst->activated_layer_list.count);
Jon Ashburn128f9422015-05-28 19:16:58 -06002583 if (!wrappedInstance) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06002584 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc Instance objects for layer");
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002585 return 0;
2586 }
2587
2588 /* Create instance chain of enabled layers */
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002589 layer_idx = inst->activated_layer_list.count - 1;
Courtney Goeltzenleuchter0f1d8eb2015-06-07 17:28:17 -06002590 for (int32_t i = inst->activated_layer_list.count - 1; i >= 0; i--) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002591 struct loader_layer_properties *layer_prop = &inst->activated_layer_list.list[i];
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002592 loader_platform_dl_handle lib_handle;
2593
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002594 /*
Courtney Goeltzenleuchteree3b16a2015-06-01 14:12:42 -06002595 * Note: An extension's Get*ProcAddr should not return a function pointer for
2596 * any extension entry points until the extension has been enabled.
2597 * To do this requires a different behavior from Get*ProcAddr functions implemented
2598 * in layers.
2599 * The very first call to a layer will be it's Get*ProcAddr function requesting
Tobin Ehlis1cb7f572015-10-06 09:09:24 -06002600 * the layer's vkGet*ProcAddr. The layer should initialize its internal dispatch table
Courtney Goeltzenleuchteree3b16a2015-06-01 14:12:42 -06002601 * with the wrapped object given (either Instance or Device) and return the layer's
2602 * Get*ProcAddr function. The layer should also use this opportunity to record the
2603 * baseObject so that it can find the correct local dispatch table on future calls.
2604 * Subsequent calls to Get*ProcAddr, CreateInstance, CreateDevice
2605 * will not use a wrapped object and must look up their local dispatch table from
2606 * the given baseObject.
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002607 */
Jon Ashburn128f9422015-05-28 19:16:58 -06002608 nextInstObj = (wrappedInstance + layer_idx);
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002609 nextInstObj->pGPA = (PFN_vkGPA) nextGPA;
Jon Ashburn27cd5842015-05-12 17:26:48 -06002610 nextInstObj->baseObject = baseObj;
2611 nextInstObj->nextObject = nextObj;
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002612 nextObj = (void*) nextInstObj;
Jon Ashburn27cd5842015-05-12 17:26:48 -06002613
Jon Ashburne39a4f82015-08-28 13:38:21 -06002614 lib_handle = loader_add_layer_lib(inst, "instance", layer_prop);
Jon Ashburnf72a04b2015-11-25 17:55:49 -07002615 if (!lib_handle)
2616 continue; // TODO what should we do in this case
Jon Ashburn21c21ee2015-09-09 11:29:24 -06002617 if ((nextGPA = layer_prop->functions.get_instance_proc_addr) == NULL) {
2618 if (layer_prop->functions.str_gipa == NULL || strlen(layer_prop->functions.str_gipa) == 0) {
2619 nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetInstanceProcAddr");
2620 layer_prop->functions.get_instance_proc_addr = nextGPA;
2621 } else
2622 nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gipa);
2623 if (!nextGPA) {
2624 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to find vkGetInstanceProcAddr in layer %s", layer_prop->lib_name);
Courtney Goeltzenleuchtera9e4af42015-06-01 14:49:17 -06002625
Jon Ashburn21c21ee2015-09-09 11:29:24 -06002626 /* TODO: Should we return nextObj, nextGPA to previous? or decrement layer_list count*/
2627 continue;
2628 }
Jon Ashburn27cd5842015-05-12 17:26:48 -06002629 }
2630
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002631 loader_log(VK_DBG_REPORT_INFO_BIT, 0,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002632 "Insert instance layer %s (%s)",
2633 layer_prop->info.layerName,
Jon Ashburn3d002332015-08-20 16:35:30 -06002634 layer_prop->lib_name);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002635
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002636 layer_idx--;
Jon Ashburn27cd5842015-05-12 17:26:48 -06002637 }
2638
Jon Ashburn8fd08252015-05-28 16:25:02 -06002639 loader_init_instance_core_dispatch_table(inst->disp, nextGPA, (VkInstance) nextObj, (VkInstance) baseObj);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002640
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002641 return inst->activated_layer_list.count;
Jon Ashburn27cd5842015-05-12 17:26:48 -06002642}
2643
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002644void loader_activate_instance_layer_extensions(struct loader_instance *inst)
2645{
2646
2647 loader_init_instance_extension_dispatch_table(inst->disp,
2648 inst->disp->GetInstanceProcAddr,
Jon Ashburn128f9422015-05-28 19:16:58 -06002649 (VkInstance) inst);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002650}
2651
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002652static VkResult loader_enable_device_layers(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002653 const struct loader_instance *inst,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002654 struct loader_icd *icd,
2655 struct loader_device *dev,
2656 const VkDeviceCreateInfo *pCreateInfo,
2657 const struct loader_layer_list *device_layers)
2658
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002659{
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002660 VkResult err;
2661
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06002662 assert(dev && "Cannot have null device");
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002663
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002664 if (dev->activated_layer_list.list == NULL || dev->activated_layer_list.capacity == 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06002665 loader_init_layer_list(inst, &dev->activated_layer_list);
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002666 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002667
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002668 if (dev->activated_layer_list.list == NULL) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06002669 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc device activated layer list");
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002670 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002671 }
2672
Jon Ashburn0c26e712015-07-02 16:10:32 -06002673 /* Add any implicit layers first */
2674 loader_add_layer_implicit(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002675 inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002676 VK_LAYER_TYPE_DEVICE_IMPLICIT,
2677 &dev->activated_layer_list,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002678 device_layers);
Jon Ashburn0c26e712015-07-02 16:10:32 -06002679
2680 /* Add any layers specified via environment variable next */
Jon Ashburneb6d5682015-07-02 14:10:53 -06002681 loader_add_layer_env(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002682 inst,
Jon Ashburnbd332cc2015-07-07 10:27:45 -06002683 VK_LAYER_TYPE_DEVICE_EXPLICIT,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002684 "VK_DEVICE_LAYERS",
2685 &dev->activated_layer_list,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002686 device_layers);
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002687
2688 /* Add layers specified by the application */
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002689 err = loader_add_layer_names_to_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002690 inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002691 &dev->activated_layer_list,
Chia-I Wud50a7d72015-10-26 20:48:51 +08002692 pCreateInfo->enabledLayerNameCount,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002693 pCreateInfo->ppEnabledLayerNames,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002694 device_layers);
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002695
2696 return err;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002697}
2698
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002699/*
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06002700 * This function terminates the device chain for CreateDevice.
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002701 * CreateDevice is a special case and so the loader call's
2702 * the ICD's CreateDevice before creating the chain. Since
2703 * we can't call CreateDevice twice we must terminate the
2704 * device chain with something else.
2705 */
Chia-I Wu9ab61502015-11-06 06:42:02 +08002706static VKAPI_ATTR VkResult VKAPI_CALL scratch_vkCreateDevice(
Jon Ashburn24cd4be2015-11-01 14:04:06 -07002707 VkPhysicalDevice physicalDevice,
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002708 const VkDeviceCreateInfo *pCreateInfo,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002709 const VkAllocationCallbacks* pAllocator,
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002710 VkDevice *pDevice)
2711{
2712 return VK_SUCCESS;
2713}
2714
Chia-I Wu9ab61502015-11-06 06:42:02 +08002715static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL loader_GetDeviceChainProcAddr(VkDevice device, const char * name)
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002716{
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002717 if (!strcmp(name, "vkGetDeviceProcAddr"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06002718 return (PFN_vkVoidFunction) loader_GetDeviceChainProcAddr;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002719 if (!strcmp(name, "vkCreateDevice"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06002720 return (PFN_vkVoidFunction) scratch_vkCreateDevice;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002721
Courtney Goeltzenleuchter3e029d12015-06-29 16:09:23 -06002722 struct loader_device *found_dev;
2723 struct loader_icd *icd = loader_get_icd_and_device(device, &found_dev);
2724 return icd->GetDeviceProcAddr(device, name);
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002725}
2726
Jon Ashburndc6fcad2015-06-10 10:06:06 -06002727static uint32_t loader_activate_device_layers(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002728 const struct loader_instance *inst,
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002729 struct loader_device *dev,
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -06002730 VkDevice device)
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002731{
David Pinedoa0a8a242015-06-24 15:29:18 -06002732 if (!dev) {
Jon Ashburndc6fcad2015-06-10 10:06:06 -06002733 return 0;
David Pinedoa0a8a242015-06-24 15:29:18 -06002734 }
Jon Ashburn94e70492015-06-10 10:13:10 -06002735
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002736 /* activate any layer libraries */
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002737 void* nextObj = (void*) device;
2738 void* baseObj = nextObj;
Jon Ashburn94e70492015-06-10 10:13:10 -06002739 VkBaseLayerObject *nextGpuObj;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002740 PFN_vkGetDeviceProcAddr nextGPA = loader_GetDeviceChainProcAddr;
Jon Ashburn94e70492015-06-10 10:13:10 -06002741 VkBaseLayerObject *wrappedGpus;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002742
Courtney Goeltzenleuchtered1a8dd2015-08-07 09:53:18 -06002743 if (!dev->activated_layer_list.count) {
2744 loader_init_device_dispatch_table(&dev->loader_dispatch, nextGPA,
2745 (VkDevice) nextObj, (VkDevice) baseObj);
Jon Ashburn94e70492015-06-10 10:13:10 -06002746 return 0;
Courtney Goeltzenleuchtered1a8dd2015-08-07 09:53:18 -06002747 }
Jon Ashburn94e70492015-06-10 10:13:10 -06002748
Jon Ashburne39a4f82015-08-28 13:38:21 -06002749 wrappedGpus = loader_heap_alloc(inst,
2750 sizeof (VkBaseLayerObject) * dev->activated_layer_list.count,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002751 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn94e70492015-06-10 10:13:10 -06002752 if (!wrappedGpus) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06002753 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc Gpu objects for layer");
Jon Ashburn94e70492015-06-10 10:13:10 -06002754 return 0;
2755 }
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002756
Jon Ashburn94e70492015-06-10 10:13:10 -06002757 for (int32_t i = dev->activated_layer_list.count - 1; i >= 0; i--) {
2758
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002759 struct loader_layer_properties *layer_prop = &dev->activated_layer_list.list[i];
Jon Ashburn94e70492015-06-10 10:13:10 -06002760 loader_platform_dl_handle lib_handle;
2761
Jon Ashburn94e70492015-06-10 10:13:10 -06002762 nextGpuObj = (wrappedGpus + i);
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002763 nextGpuObj->pGPA = (PFN_vkGPA)nextGPA;
Jon Ashburn94e70492015-06-10 10:13:10 -06002764 nextGpuObj->baseObject = baseObj;
2765 nextGpuObj->nextObject = nextObj;
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002766 nextObj = (void*) nextGpuObj;
Jon Ashburn94e70492015-06-10 10:13:10 -06002767
Jon Ashburne39a4f82015-08-28 13:38:21 -06002768 lib_handle = loader_add_layer_lib(inst, "device", layer_prop);
Jon Ashburn21c21ee2015-09-09 11:29:24 -06002769 if ((nextGPA = layer_prop->functions.get_device_proc_addr) == NULL) {
2770 if (layer_prop->functions.str_gdpa == NULL || strlen(layer_prop->functions.str_gdpa) == 0) {
2771 nextGPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetDeviceProcAddr");
2772 layer_prop->functions.get_device_proc_addr = nextGPA;
2773 } else
2774 nextGPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gdpa);
2775 if (!nextGPA) {
2776 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to find vkGetDeviceProcAddr in layer %s", layer_prop->lib_name);
2777 continue;
2778 }
Jon Ashburn94e70492015-06-10 10:13:10 -06002779 }
2780
2781 loader_log(VK_DBG_REPORT_INFO_BIT, 0,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002782 "Insert device layer library %s (%s)",
2783 layer_prop->info.layerName,
Jon Ashburn3d002332015-08-20 16:35:30 -06002784 layer_prop->lib_name);
Jon Ashburn94e70492015-06-10 10:13:10 -06002785
2786 }
2787
2788 loader_init_device_dispatch_table(&dev->loader_dispatch, nextGPA,
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002789 (VkDevice) nextObj, (VkDevice) baseObj);
Jon Ashburne39a4f82015-08-28 13:38:21 -06002790 loader_heap_free(inst, wrappedGpus);
Jon Ashburn94e70492015-06-10 10:13:10 -06002791
Jon Ashburndc6fcad2015-06-10 10:06:06 -06002792 return dev->activated_layer_list.count;
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002793}
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002794
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002795VkResult loader_validate_layers(
2796 const uint32_t layer_count,
2797 const char * const *ppEnabledLayerNames,
Jon Ashburn3d002332015-08-20 16:35:30 -06002798 const struct loader_layer_list *list)
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06002799{
2800 struct loader_layer_properties *prop;
2801
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002802 for (uint32_t i = 0; i < layer_count; i++) {
Jon Ashburne13ecc92015-08-03 17:19:30 -06002803 prop = loader_get_layer_property(ppEnabledLayerNames[i],
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002804 list);
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06002805 if (!prop) {
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06002806 return VK_ERROR_LAYER_NOT_PRESENT;
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06002807 }
2808 }
2809
2810 return VK_SUCCESS;
2811}
2812
2813VkResult loader_validate_instance_extensions(
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06002814 const struct loader_extension_list *icd_exts,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002815 const struct loader_layer_list *instance_layer,
2816 const VkInstanceCreateInfo *pCreateInfo)
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06002817{
Jon Ashburn5c042ea2015-08-04 11:14:18 -06002818 VkExtensionProperties *extension_prop;
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002819 struct loader_layer_properties *layer_prop;
2820
Chia-I Wud50a7d72015-10-26 20:48:51 +08002821 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) {
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002822 extension_prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06002823 icd_exts);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002824
2825 if (extension_prop) {
2826 continue;
2827 }
2828
2829 extension_prop = NULL;
2830
2831 /* Not in global list, search layer extension lists */
Chia-I Wud50a7d72015-10-26 20:48:51 +08002832 for (uint32_t j = 0; j < pCreateInfo->enabledLayerNameCount; j++) {
Jon Ashburne13ecc92015-08-03 17:19:30 -06002833 layer_prop = loader_get_layer_property(pCreateInfo->ppEnabledLayerNames[i],
Jon Ashburnb82c1852015-08-11 14:49:54 -06002834 instance_layer);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002835 if (!layer_prop) {
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06002836 /* Should NOT get here, loader_validate_layers
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002837 * should have already filtered this case out.
2838 */
2839 continue;
2840 }
2841
2842 extension_prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
2843 &layer_prop->instance_extension_list);
2844 if (extension_prop) {
2845 /* Found the extension in one of the layers enabled by the app. */
2846 break;
2847 }
2848 }
2849
2850 if (!extension_prop) {
2851 /* Didn't find extension name in any of the global layers, error out */
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06002852 return VK_ERROR_EXTENSION_NOT_PRESENT;
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002853 }
2854 }
2855 return VK_SUCCESS;
2856}
2857
2858VkResult loader_validate_device_extensions(
Jon Ashburn24cd4be2015-11-01 14:04:06 -07002859 struct loader_physical_device *phys_dev,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002860 const struct loader_layer_list *device_layer,
2861 const VkDeviceCreateInfo *pCreateInfo)
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002862{
Jon Ashburn5c042ea2015-08-04 11:14:18 -06002863 VkExtensionProperties *extension_prop;
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002864 struct loader_layer_properties *layer_prop;
2865
Chia-I Wud50a7d72015-10-26 20:48:51 +08002866 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) {
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002867 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i];
2868 extension_prop = get_extension_property(extension_name,
Jon Ashburn24cd4be2015-11-01 14:04:06 -07002869 &phys_dev->device_extension_cache);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002870
2871 if (extension_prop) {
2872 continue;
2873 }
2874
2875 /* Not in global list, search layer extension lists */
Chia-I Wud50a7d72015-10-26 20:48:51 +08002876 for (uint32_t j = 0; j < pCreateInfo->enabledLayerNameCount; j++) {
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002877 const char *layer_name = pCreateInfo->ppEnabledLayerNames[j];
Jon Ashburne13ecc92015-08-03 17:19:30 -06002878 layer_prop = loader_get_layer_property(layer_name,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002879 device_layer);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002880
2881 if (!layer_prop) {
2882 /* Should NOT get here, loader_validate_instance_layers
2883 * should have already filtered this case out.
2884 */
2885 continue;
2886 }
2887
2888 extension_prop = get_extension_property(extension_name,
2889 &layer_prop->device_extension_list);
2890 if (extension_prop) {
2891 /* Found the extension in one of the layers enabled by the app. */
2892 break;
2893 }
2894 }
2895
2896 if (!extension_prop) {
2897 /* Didn't find extension name in any of the device layers, error out */
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06002898 return VK_ERROR_EXTENSION_NOT_PRESENT;
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002899 }
2900 }
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06002901 return VK_SUCCESS;
2902}
2903
Chia-I Wu9ab61502015-11-06 06:42:02 +08002904VKAPI_ATTR VkResult VKAPI_CALL loader_CreateInstance(
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002905 const VkInstanceCreateInfo* pCreateInfo,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002906 const VkAllocationCallbacks* pAllocator,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002907 VkInstance* pInstance)
Jon Ashburn1beab2d2015-01-26 14:51:40 -07002908{
Jon Ashburneed0c002015-05-21 17:42:17 -06002909 struct loader_instance *ptr_instance = *(struct loader_instance **) pInstance;
Jon Ashburn46888392015-01-29 15:45:51 -07002910 struct loader_icd *icd;
Jon Ashburn5c042ea2015-08-04 11:14:18 -06002911 VkExtensionProperties *prop;
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06002912 char **filtered_extension_names = NULL;
2913 VkInstanceCreateInfo icd_create_info;
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002914 VkResult res = VK_SUCCESS;
Jon Ashburn7e18de02015-11-19 09:29:51 -07002915 bool success = false;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07002916
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06002917 icd_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
Chia-I Wud50a7d72015-10-26 20:48:51 +08002918 icd_create_info.enabledLayerNameCount = 0;
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06002919 icd_create_info.ppEnabledLayerNames = NULL;
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002920 icd_create_info.pApplicationInfo = pCreateInfo->pApplicationInfo;
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06002921 icd_create_info.pNext = pCreateInfo->pNext;
2922
2923 /*
2924 * NOTE: Need to filter the extensions to only those
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002925 * supported by the ICD.
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06002926 * No ICD will advertise support for layers. An ICD
2927 * library could support a layer, but it would be
2928 * independent of the actual ICD, just in the same library.
2929 */
Chia-I Wud50a7d72015-10-26 20:48:51 +08002930 filtered_extension_names = loader_stack_alloc(pCreateInfo->enabledExtensionNameCount * sizeof(char *));
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06002931 if (!filtered_extension_names) {
2932 return VK_ERROR_OUT_OF_HOST_MEMORY;
2933 }
2934 icd_create_info.ppEnabledExtensionNames = (const char * const *) filtered_extension_names;
2935
Jon Ashburn8810c5f2015-08-18 18:04:47 -06002936 for (uint32_t i = 0; i < ptr_instance->icd_libs.count; i++) {
2937 icd = loader_icd_add(ptr_instance, &ptr_instance->icd_libs.list[i]);
Jon Ashburn46888392015-01-29 15:45:51 -07002938 if (icd) {
Chia-I Wud50a7d72015-10-26 20:48:51 +08002939 icd_create_info.enabledExtensionNameCount = 0;
2940 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) {
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06002941 prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
Jon Ashburn5c6a46f2015-08-14 14:49:22 -06002942 &ptr_instance->ext_list);
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06002943 if (prop) {
Chia-I Wud50a7d72015-10-26 20:48:51 +08002944 filtered_extension_names[icd_create_info.enabledExtensionNameCount] = (char *) pCreateInfo->ppEnabledExtensionNames[i];
2945 icd_create_info.enabledExtensionNameCount++;
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06002946 }
2947 }
2948
Jon Ashburn8810c5f2015-08-18 18:04:47 -06002949 res = ptr_instance->icd_libs.list[i].CreateInstance(&icd_create_info,
Chia-I Wuf7458c52015-10-26 21:10:41 +08002950 pAllocator,
Jon Ashburn3da71f22015-05-14 12:43:38 -06002951 &(icd->instance));
Jon Ashburn7e18de02015-11-19 09:29:51 -07002952 if (res == VK_SUCCESS)
2953 success = loader_icd_init_entrys(
Jon Ashburnc624c882015-07-16 10:17:29 -06002954 icd,
2955 icd->instance,
Jon Ashburn8810c5f2015-08-18 18:04:47 -06002956 ptr_instance->icd_libs.list[i].GetInstanceProcAddr);
Jon Ashburnc624c882015-07-16 10:17:29 -06002957
2958 if (res != VK_SUCCESS || !success)
Jon Ashburn46888392015-01-29 15:45:51 -07002959 {
2960 ptr_instance->icds = ptr_instance->icds->next;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002961 loader_icd_destroy(ptr_instance, icd);
Jon Ashburn3da71f22015-05-14 12:43:38 -06002962 icd->instance = VK_NULL_HANDLE;
Jon Ashburnc624c882015-07-16 10:17:29 -06002963 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
2964 "ICD ignored: failed to CreateInstance and find entrypoints with ICD");
Jon Ashburn46888392015-01-29 15:45:51 -07002965 }
2966 }
Jon Ashburn46888392015-01-29 15:45:51 -07002967 }
Jon Ashburn1beab2d2015-01-26 14:51:40 -07002968
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002969 /*
2970 * If no ICDs were added to instance list and res is unchanged
2971 * from it's initial value, the loader was unable to find
2972 * a suitable ICD.
2973 */
Ian Elliotteb450762015-02-05 15:19:15 -07002974 if (ptr_instance->icds == NULL) {
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002975 if (res == VK_SUCCESS) {
2976 return VK_ERROR_INCOMPATIBLE_DRIVER;
2977 } else {
2978 return res;
2979 }
Ian Elliotteb450762015-02-05 15:19:15 -07002980 }
Jon Ashburn46888392015-01-29 15:45:51 -07002981
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002982 return VK_SUCCESS;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07002983}
2984
Chia-I Wu9ab61502015-11-06 06:42:02 +08002985VKAPI_ATTR void VKAPI_CALL loader_DestroyInstance(
Chia-I Wuf7458c52015-10-26 21:10:41 +08002986 VkInstance instance,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002987 const VkAllocationCallbacks* pAllocator)
Jon Ashburn1beab2d2015-01-26 14:51:40 -07002988{
Courtney Goeltzenleuchterdeceded2015-06-08 15:04:02 -06002989 struct loader_instance *ptr_instance = loader_instance(instance);
Jon Ashburn3da71f22015-05-14 12:43:38 -06002990 struct loader_icd *icds = ptr_instance->icds;
Jon Ashburna6fd2612015-06-16 14:43:19 -06002991 struct loader_icd *next_icd;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07002992
2993 // Remove this instance from the list of instances:
2994 struct loader_instance *prev = NULL;
2995 struct loader_instance *next = loader.instances;
2996 while (next != NULL) {
2997 if (next == ptr_instance) {
2998 // Remove this instance from the list:
2999 if (prev)
3000 prev->next = next->next;
Jon Ashburnc5c49602015-02-03 09:26:59 -07003001 else
3002 loader.instances = next->next;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003003 break;
3004 }
3005 prev = next;
3006 next = next->next;
3007 }
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003008
Jon Ashburn3da71f22015-05-14 12:43:38 -06003009 while (icds) {
3010 if (icds->instance) {
Chia-I Wuf7458c52015-10-26 21:10:41 +08003011 icds->DestroyInstance(icds->instance, pAllocator);
Tony Barbourf20f87b2015-04-22 09:02:32 -06003012 }
Jon Ashburna6fd2612015-06-16 14:43:19 -06003013 next_icd = icds->next;
Jon Ashburn3da71f22015-05-14 12:43:38 -06003014 icds->instance = VK_NULL_HANDLE;
Jon Ashburna6fd2612015-06-16 14:43:19 -06003015 loader_icd_destroy(ptr_instance, icds);
3016
3017 icds = next_icd;
Jon Ashburn46888392015-01-29 15:45:51 -07003018 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06003019 loader_delete_layer_properties(ptr_instance, &ptr_instance->device_layer_list);
3020 loader_delete_layer_properties(ptr_instance, &ptr_instance->instance_layer_list);
3021 loader_scanned_icd_clear(ptr_instance, &ptr_instance->icd_libs);
3022 loader_destroy_ext_list(ptr_instance, &ptr_instance->ext_list);
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003023 for (uint32_t i = 0; i < ptr_instance->total_gpu_count; i++)
3024 loader_destroy_ext_list(ptr_instance, &ptr_instance->phys_devs[i].device_extension_cache);
3025 loader_heap_free(ptr_instance, ptr_instance->phys_devs);
Jon Ashburnfc1031e2015-11-17 15:31:02 -07003026 loader_free_dev_ext_table(ptr_instance);
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003027}
3028
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003029VkResult loader_init_physical_device_info(struct loader_instance *ptr_instance)
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003030{
3031 struct loader_icd *icd;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003032 uint32_t i, j, idx, count = 0;
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06003033 VkResult res;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003034 struct loader_phys_dev_per_icd *phys_devs;
3035
3036 ptr_instance->total_gpu_count = 0;
3037 phys_devs = (struct loader_phys_dev_per_icd *) loader_stack_alloc(
3038 sizeof(struct loader_phys_dev_per_icd) *
3039 ptr_instance->total_icd_count);
3040 if (!phys_devs)
3041 return VK_ERROR_OUT_OF_HOST_MEMORY;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003042
3043 icd = ptr_instance->icds;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003044 for (i = 0; i < ptr_instance->total_icd_count; i++) {
3045 assert(icd);
3046 res = icd->EnumeratePhysicalDevices(icd->instance, &phys_devs[i].count, NULL);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003047 if (res != VK_SUCCESS)
3048 return res;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003049 count += phys_devs[i].count;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003050 icd = icd->next;
3051 }
3052
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003053 ptr_instance->phys_devs = (struct loader_physical_device *) loader_heap_alloc(
3054 ptr_instance,
3055 count * sizeof(struct loader_physical_device),
3056 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
3057 if (!ptr_instance->phys_devs)
3058 return VK_ERROR_OUT_OF_HOST_MEMORY;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003059
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003060 icd = ptr_instance->icds;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003061
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003062 struct loader_physical_device *inst_phys_devs = ptr_instance->phys_devs;
3063 idx = 0;
3064 for (i = 0; i < ptr_instance->total_icd_count; i++) {
3065 assert(icd);
3066
3067 phys_devs[i].phys_devs = (VkPhysicalDevice *) loader_stack_alloc(
3068 phys_devs[i].count * sizeof(VkPhysicalDevice));
3069 if (!phys_devs[i].phys_devs) {
Jon Ashburn093ce202015-11-02 17:59:02 -07003070 loader_heap_free(ptr_instance, ptr_instance->phys_devs);
3071 ptr_instance->phys_devs = NULL;
Jon Ashburn128f9422015-05-28 19:16:58 -06003072 return VK_ERROR_OUT_OF_HOST_MEMORY;
3073 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003074 res = icd->EnumeratePhysicalDevices(
3075 icd->instance,
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003076 &(phys_devs[i].count),
3077 phys_devs[i].phys_devs);
3078 if ((res == VK_SUCCESS)) {
3079 ptr_instance->total_gpu_count += phys_devs[i].count;
3080 for (j = 0; j < phys_devs[i].count; j++) {
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003081
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003082 // initialize the loader's physicalDevice object
3083 loader_set_dispatch((void *) &inst_phys_devs[idx], ptr_instance->disp);
3084 inst_phys_devs[idx].this_instance = ptr_instance;
3085 inst_phys_devs[idx].this_icd = icd;
3086 inst_phys_devs[idx].phys_dev = phys_devs[i].phys_devs[j];
Jon Ashburn00eb6c02015-11-02 17:40:01 -07003087 memset(&inst_phys_devs[idx].device_extension_cache, 0, sizeof(struct loader_extension_list));
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003088
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003089 idx++;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003090 }
Jon Ashburn093ce202015-11-02 17:59:02 -07003091 } else {
3092 loader_heap_free(ptr_instance, ptr_instance->phys_devs);
3093 ptr_instance->phys_devs = NULL;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003094 return res;
Jon Ashburn093ce202015-11-02 17:59:02 -07003095 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003096
3097 icd = icd->next;
3098 }
3099
3100 return VK_SUCCESS;
3101}
3102
Chia-I Wu9ab61502015-11-06 06:42:02 +08003103VKAPI_ATTR VkResult VKAPI_CALL loader_EnumeratePhysicalDevices(
Courtney Goeltzenleuchter5e41f1d2015-04-20 12:48:54 -06003104 VkInstance instance,
3105 uint32_t* pPhysicalDeviceCount,
3106 VkPhysicalDevice* pPhysicalDevices)
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003107{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003108 uint32_t i;
Jon Ashburn4c392fb2015-01-28 19:57:09 -07003109 struct loader_instance *ptr_instance = (struct loader_instance *) instance;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003110 VkResult res = VK_SUCCESS;
Jon Ashburn4c392fb2015-01-28 19:57:09 -07003111
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003112 if (ptr_instance->total_gpu_count == 0) {
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003113 res = loader_init_physical_device_info(ptr_instance);
Jon Ashburn4c392fb2015-01-28 19:57:09 -07003114 }
3115
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003116 *pPhysicalDeviceCount = ptr_instance->total_gpu_count;
3117 if (!pPhysicalDevices) {
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003118 return res;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003119 }
Jon Ashburn4c392fb2015-01-28 19:57:09 -07003120
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003121 for (i = 0; i < ptr_instance->total_gpu_count; i++) {
3122 pPhysicalDevices[i] = (VkPhysicalDevice) &ptr_instance->phys_devs[i];
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003123 }
3124
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003125 return res;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003126}
3127
Chia-I Wu9ab61502015-11-06 06:42:02 +08003128VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceProperties(
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003129 VkPhysicalDevice physicalDevice,
Tony Barbour59a47322015-06-24 16:06:58 -06003130 VkPhysicalDeviceProperties* pProperties)
Jon Ashburn3da71f22015-05-14 12:43:38 -06003131{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003132 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3133 struct loader_icd *icd = phys_dev->this_icd;
Jon Ashburn3da71f22015-05-14 12:43:38 -06003134
Tony Barbour59a47322015-06-24 16:06:58 -06003135 if (icd->GetPhysicalDeviceProperties)
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003136 icd->GetPhysicalDeviceProperties(phys_dev->phys_dev, pProperties);
Tony Barbour59a47322015-06-24 16:06:58 -06003137}
3138
Chia-I Wu9ab61502015-11-06 06:42:02 +08003139VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceQueueFamilyProperties (
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003140 VkPhysicalDevice physicalDevice,
Chia-I Wud50a7d72015-10-26 20:48:51 +08003141 uint32_t* pQueueFamilyPropertyCount,
Cody Northropd0802882015-08-03 17:04:53 -06003142 VkQueueFamilyProperties* pProperties)
Tony Barbour59a47322015-06-24 16:06:58 -06003143{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003144 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3145 struct loader_icd *icd = phys_dev->this_icd;
Tony Barbour59a47322015-06-24 16:06:58 -06003146
Cody Northropd0802882015-08-03 17:04:53 -06003147 if (icd->GetPhysicalDeviceQueueFamilyProperties)
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003148 icd->GetPhysicalDeviceQueueFamilyProperties(phys_dev->phys_dev, pQueueFamilyPropertyCount, pProperties);
Tony Barbour59a47322015-06-24 16:06:58 -06003149}
3150
Chia-I Wu9ab61502015-11-06 06:42:02 +08003151VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceMemoryProperties (
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003152 VkPhysicalDevice physicalDevice,
Tony Barbour59a47322015-06-24 16:06:58 -06003153 VkPhysicalDeviceMemoryProperties* pProperties)
3154{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003155 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3156 struct loader_icd *icd = phys_dev->this_icd;
Tony Barbour59a47322015-06-24 16:06:58 -06003157
3158 if (icd->GetPhysicalDeviceMemoryProperties)
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003159 icd->GetPhysicalDeviceMemoryProperties(phys_dev->phys_dev, pProperties);
Jon Ashburn3da71f22015-05-14 12:43:38 -06003160}
3161
Chia-I Wu9ab61502015-11-06 06:42:02 +08003162VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceFeatures(
Chris Forbesbc0bb772015-06-21 22:55:02 +12003163 VkPhysicalDevice physicalDevice,
3164 VkPhysicalDeviceFeatures* pFeatures)
3165{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003166 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3167 struct loader_icd *icd = phys_dev->this_icd;
Chris Forbesbc0bb772015-06-21 22:55:02 +12003168
3169 if (icd->GetPhysicalDeviceFeatures)
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003170 icd->GetPhysicalDeviceFeatures(phys_dev->phys_dev, pFeatures);
Chris Forbesbc0bb772015-06-21 22:55:02 +12003171}
3172
Chia-I Wu9ab61502015-11-06 06:42:02 +08003173VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceFormatProperties(
Chris Forbesbc0bb772015-06-21 22:55:02 +12003174 VkPhysicalDevice physicalDevice,
3175 VkFormat format,
3176 VkFormatProperties* pFormatInfo)
3177{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003178 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3179 struct loader_icd *icd = phys_dev->this_icd;
Chris Forbesbc0bb772015-06-21 22:55:02 +12003180
Courtney Goeltzenleuchter2caec862015-07-12 12:52:09 -06003181 if (icd->GetPhysicalDeviceFormatProperties)
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003182 icd->GetPhysicalDeviceFormatProperties(phys_dev->phys_dev, format, pFormatInfo);
Chris Forbesbc0bb772015-06-21 22:55:02 +12003183}
3184
Chia-I Wu9ab61502015-11-06 06:42:02 +08003185VKAPI_ATTR VkResult VKAPI_CALL loader_GetPhysicalDeviceImageFormatProperties(
Jon Ashburn754864f2015-07-23 18:49:07 -06003186 VkPhysicalDevice physicalDevice,
3187 VkFormat format,
3188 VkImageType type,
3189 VkImageTiling tiling,
3190 VkImageUsageFlags usage,
Courtney Goeltzenleuchtera22097a2015-09-10 13:44:12 -06003191 VkImageCreateFlags flags,
Jon Ashburn754864f2015-07-23 18:49:07 -06003192 VkImageFormatProperties* pImageFormatProperties)
3193{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003194 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3195 struct loader_icd *icd = phys_dev->this_icd;
Jon Ashburn754864f2015-07-23 18:49:07 -06003196
Chia-I Wu17241042015-10-31 00:31:16 +08003197 if (!icd->GetPhysicalDeviceImageFormatProperties)
3198 return VK_ERROR_INITIALIZATION_FAILED;
3199
3200 return icd->GetPhysicalDeviceImageFormatProperties(phys_dev->phys_dev, format,
3201 type, tiling, usage, flags, pImageFormatProperties);
Jon Ashburn754864f2015-07-23 18:49:07 -06003202}
3203
Chia-I Wu9ab61502015-11-06 06:42:02 +08003204VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceSparseImageFormatProperties(
Mark Lobodzinski16e8bef2015-07-03 15:58:09 -06003205 VkPhysicalDevice physicalDevice,
3206 VkFormat format,
3207 VkImageType type,
Chia-I Wu5c17c962015-10-31 00:31:16 +08003208 VkSampleCountFlagBits samples,
Mark Lobodzinski16e8bef2015-07-03 15:58:09 -06003209 VkImageUsageFlags usage,
3210 VkImageTiling tiling,
3211 uint32_t* pNumProperties,
3212 VkSparseImageFormatProperties* pProperties)
3213{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003214 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3215 struct loader_icd *icd = phys_dev->this_icd;
Mark Lobodzinski16e8bef2015-07-03 15:58:09 -06003216
3217 if (icd->GetPhysicalDeviceSparseImageFormatProperties)
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003218 icd->GetPhysicalDeviceSparseImageFormatProperties(phys_dev->phys_dev, format, type, samples, usage, tiling, pNumProperties, pProperties);
Mark Lobodzinski16e8bef2015-07-03 15:58:09 -06003219}
3220
Chia-I Wu9ab61502015-11-06 06:42:02 +08003221VKAPI_ATTR VkResult VKAPI_CALL loader_CreateDevice(
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003222 VkPhysicalDevice physicalDevice,
Jon Ashburn95a77ba2015-05-15 15:09:35 -06003223 const VkDeviceCreateInfo* pCreateInfo,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003224 const VkAllocationCallbacks* pAllocator,
Jon Ashburn95a77ba2015-05-15 15:09:35 -06003225 VkDevice* pDevice)
3226{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003227 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3228 struct loader_icd *icd = phys_dev->this_icd;
Jon Ashburndc6fcad2015-06-10 10:06:06 -06003229 struct loader_device *dev;
Jon Ashburnfc1031e2015-11-17 15:31:02 -07003230 struct loader_instance *inst;
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003231 VkDeviceCreateInfo device_create_info;
3232 char **filtered_extension_names = NULL;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003233 VkResult res;
Jon Ashburn95a77ba2015-05-15 15:09:35 -06003234
Chia-I Wu02124482015-11-06 06:42:02 +08003235 assert(pCreateInfo->queueCreateInfoCount >= 1);
Mark Lobodzinski0c29b922015-09-17 15:17:34 -06003236
Jon Ashburna4cf12b2015-10-26 16:54:51 -06003237 if (!icd)
3238 return VK_ERROR_INITIALIZATION_FAILED;
3239
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003240 inst = phys_dev->this_instance;
Jon Ashburna4cf12b2015-10-26 16:54:51 -06003241
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003242 if (!icd->CreateDevice) {
3243 return VK_ERROR_INITIALIZATION_FAILED;
Jon Ashburn95a77ba2015-05-15 15:09:35 -06003244 }
3245
Jon Ashburnb82c1852015-08-11 14:49:54 -06003246 /* validate any app enabled layers are available */
Chia-I Wud50a7d72015-10-26 20:48:51 +08003247 if (pCreateInfo->enabledLayerNameCount > 0) {
3248 res = loader_validate_layers(pCreateInfo->enabledLayerNameCount,
Jon Ashburnb82c1852015-08-11 14:49:54 -06003249 pCreateInfo->ppEnabledLayerNames,
Jon Ashburne39a4f82015-08-28 13:38:21 -06003250 &inst->device_layer_list);
Jon Ashburnb82c1852015-08-11 14:49:54 -06003251 if (res != VK_SUCCESS) {
3252 return res;
3253 }
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003254 }
3255
Jon Ashburn00eb6c02015-11-02 17:40:01 -07003256 /* Get the physical device extensions if they haven't been retrieved yet */
3257 if (phys_dev->device_extension_cache.capacity == 0) {
3258 if (!loader_init_ext_list(inst, &phys_dev->device_extension_cache)) {
3259 return VK_ERROR_OUT_OF_HOST_MEMORY;
3260 }
3261 res = loader_add_physical_device_extensions(
3262 inst, physicalDevice,
3263 phys_dev->this_icd->this_icd_lib->lib_name,
3264 &phys_dev->device_extension_cache);
3265 if (res != VK_SUCCESS) {
3266 return res;
3267 }
3268 }
3269 /* make sure requested extensions to be enabled are supported */
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003270 res = loader_validate_device_extensions(phys_dev, &inst->device_layer_list, pCreateInfo);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003271 if (res != VK_SUCCESS) {
3272 return res;
3273 }
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003274
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003275 /*
3276 * NOTE: Need to filter the extensions to only those
3277 * supported by the ICD.
3278 * No ICD will advertise support for layers. An ICD
3279 * library could support a layer, but it would be
3280 * independent of the actual ICD, just in the same library.
3281 */
Chia-I Wud50a7d72015-10-26 20:48:51 +08003282 filtered_extension_names = loader_stack_alloc(pCreateInfo->enabledExtensionNameCount * sizeof(char *));
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003283 if (!filtered_extension_names) {
3284 return VK_ERROR_OUT_OF_HOST_MEMORY;
3285 }
3286
3287 /* Copy user's data */
3288 memcpy(&device_create_info, pCreateInfo, sizeof(VkDeviceCreateInfo));
3289
3290 /* ICD's do not use layers */
Chia-I Wud50a7d72015-10-26 20:48:51 +08003291 device_create_info.enabledLayerNameCount = 0;
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003292 device_create_info.ppEnabledLayerNames = NULL;
3293
Chia-I Wud50a7d72015-10-26 20:48:51 +08003294 device_create_info.enabledExtensionNameCount = 0;
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003295 device_create_info.ppEnabledExtensionNames = (const char * const *) filtered_extension_names;
3296
Chia-I Wud50a7d72015-10-26 20:48:51 +08003297 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) {
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003298 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i];
Jon Ashburn5c042ea2015-08-04 11:14:18 -06003299 VkExtensionProperties *prop = get_extension_property(extension_name,
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003300 &phys_dev->device_extension_cache);
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003301 if (prop) {
Chia-I Wud50a7d72015-10-26 20:48:51 +08003302 filtered_extension_names[device_create_info.enabledExtensionNameCount] = (char *) extension_name;
3303 device_create_info.enabledExtensionNameCount++;
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003304 }
3305 }
3306
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003307 // since physicalDevice object maybe wrapped by a layer need to get unwrapped version
Jon Ashburne0e64572015-09-30 12:56:42 -06003308 // we haven't yet called down the chain for the layer to unwrap the object
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003309 res = icd->CreateDevice(phys_dev->phys_dev, pCreateInfo, pAllocator, pDevice);
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003310 if (res != VK_SUCCESS) {
3311 return res;
3312 }
3313
Jon Ashburne39a4f82015-08-28 13:38:21 -06003314 dev = loader_add_logical_device(inst, *pDevice, &icd->logical_device_list);
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003315 if (dev == NULL) {
3316 return VK_ERROR_OUT_OF_HOST_MEMORY;
3317 }
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003318
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003319 loader_init_dispatch(*pDevice, &dev->loader_dispatch);
3320
Jon Ashburnb82c1852015-08-11 14:49:54 -06003321 /* activate any layers on device chain which terminates with device*/
Jon Ashburne39a4f82015-08-28 13:38:21 -06003322 res = loader_enable_device_layers(inst, icd, dev, pCreateInfo, &inst->device_layer_list);
Jon Ashburnb82c1852015-08-11 14:49:54 -06003323 if (res != VK_SUCCESS) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06003324 loader_destroy_logical_device(inst, dev);
Jon Ashburnb82c1852015-08-11 14:49:54 -06003325 return res;
3326 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06003327 loader_activate_device_layers(inst, dev, *pDevice);
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003328
Jon Ashburnfc1031e2015-11-17 15:31:02 -07003329 /* initialize any device extension dispatch entry's from the instance list*/
3330 loader_init_dispatch_dev_ext(inst, dev);
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003331
Jon Ashburnfc1031e2015-11-17 15:31:02 -07003332 /* finally can call down the chain */
3333 res = dev->loader_dispatch.core_dispatch.CreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
3334
3335 dev->loader_dispatch.core_dispatch.CreateDevice = icd->CreateDevice;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003336
Jon Ashburn95a77ba2015-05-15 15:09:35 -06003337 return res;
3338}
3339
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003340/**
3341 * Get an instance level or global level entry point address.
3342 * @param instance
3343 * @param pName
3344 * @return
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003345 * If instance == NULL returns a global level functions only
3346 * If instance is valid returns a trampoline entry point for all dispatchable Vulkan
3347 * functions both core and extensions.
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003348 */
Chia-I Wu9ab61502015-11-06 06:42:02 +08003349LOADER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char * pName)
Jon Ashburnb0fbe912015-05-06 10:15:07 -06003350{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003351
Jon Ashburn07daee72015-05-21 18:13:33 -06003352 void *addr;
Jon Ashburnb0fbe912015-05-06 10:15:07 -06003353
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003354 addr = globalGetProcAddr(pName);
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003355 if (instance == VK_NULL_HANDLE) {
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003356 // get entrypoint addresses that are global (no dispatchable object)
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003357
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003358 return addr;
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003359 } else {
3360 // if a global entrypoint return NULL
3361 if (addr)
3362 return NULL;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003363 }
3364
Jon Ashburne0e64572015-09-30 12:56:42 -06003365 struct loader_instance *ptr_instance = loader_get_instance(instance);
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003366 if (ptr_instance == NULL)
Jon Ashburn07daee72015-05-21 18:13:33 -06003367 return NULL;
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003368 // Return trampoline code for non-global entrypoints including any extensions.
3369 // Device extensions are returned if a layer or ICD supports the extension.
3370 // Instance extensions are returned if the extension is enabled and the loader
3371 // or someone else supports the extension
3372 return trampolineGetProcAddr(ptr_instance, pName);
Jon Ashburn07daee72015-05-21 18:13:33 -06003373
Jon Ashburnb0fbe912015-05-06 10:15:07 -06003374}
3375
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003376/**
3377 * Get a device level or global level entry point address.
3378 * @param device
3379 * @param pName
3380 * @return
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003381 * If device is valid, returns a device relative entry point for device level
3382 * entry points both core and extensions.
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003383 * Device relative means call down the device chain.
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003384 */
Chia-I Wu9ab61502015-11-06 06:42:02 +08003385LOADER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char * pName)
Courtney Goeltzenleuchter9ec39ac2015-06-22 17:45:21 -06003386{
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003387 void *addr;
Courtney Goeltzenleuchter9ec39ac2015-06-22 17:45:21 -06003388
Jon Ashburn3d526cb2015-04-13 18:10:06 -06003389 /* for entrypoints that loader must handle (ie non-dispatchable or create object)
3390 make sure the loader entrypoint is returned */
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003391 addr = loader_non_passthrough_gdpa(pName);
Ian Elliotte19c9152015-04-15 12:53:19 -06003392 if (addr) {
Jon Ashburn3d526cb2015-04-13 18:10:06 -06003393 return addr;
Ian Elliotte19c9152015-04-15 12:53:19 -06003394 }
Jon Ashburn3d526cb2015-04-13 18:10:06 -06003395
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003396 /* Although CreateDevice is on device chain it's dispatchable object isn't
3397 * a VkDevice or child of VkDevice so return NULL.
3398 */
3399 if (!strcmp(pName, "CreateDevice"))
3400 return NULL;
3401
Jon Ashburn3d526cb2015-04-13 18:10:06 -06003402 /* return the dispatch table entrypoint for the fastest case */
Jon Ashburn8d1b0b52015-05-18 13:20:15 -06003403 const VkLayerDispatchTable *disp_table = * (VkLayerDispatchTable **) device;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06003404 if (disp_table == NULL)
3405 return NULL;
3406
Jon Ashburn27cd5842015-05-12 17:26:48 -06003407 addr = loader_lookup_device_dispatch_table(disp_table, pName);
Chia-I Wuf46b81a2015-01-04 11:12:47 +08003408 if (addr)
3409 return addr;
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003410
3411 if (disp_table->GetDeviceProcAddr == NULL)
3412 return NULL;
3413 return disp_table->GetDeviceProcAddr(device, pName);
Jon Ashburnd38bfb12014-10-14 19:15:22 -06003414}
3415
Chia-I Wu9ab61502015-11-06 06:42:02 +08003416LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003417 const char* pLayerName,
Chia-I Wud50a7d72015-10-26 20:48:51 +08003418 uint32_t* pPropertyCount,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003419 VkExtensionProperties* pProperties)
3420{
Jon Ashburn432d2762015-09-18 12:53:16 -06003421 struct loader_extension_list *global_ext_list=NULL;
Jon Ashburnb82c1852015-08-11 14:49:54 -06003422 struct loader_layer_list instance_layers;
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003423 struct loader_extension_list icd_extensions;
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003424 struct loader_icd_libs icd_libs;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003425 uint32_t copy_size;
3426
Jon Ashburn87d6aa92015-08-28 15:19:27 -06003427 tls_instance = NULL;
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003428 memset(&icd_extensions, 0, sizeof(icd_extensions));
Mike Stroyan09c06c72015-10-01 15:23:48 -06003429 memset(&instance_layers, 0, sizeof(instance_layers));
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003430 loader_platform_thread_once(&once_init, loader_initialize);
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003431
Jon Ashburnb82c1852015-08-11 14:49:54 -06003432 /* get layer libraries if needed */
3433 if (pLayerName && strlen(pLayerName) != 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06003434 loader_layer_scan(NULL, &instance_layers, NULL);
Jon Ashburnb82c1852015-08-11 14:49:54 -06003435 for (uint32_t i = 0; i < instance_layers.count; i++) {
3436 struct loader_layer_properties *props = &instance_layers.list[i];
3437 if (strcmp(props->info.layerName, pLayerName) == 0) {
3438 global_ext_list = &props->instance_extension_list;
3439 }
3440 }
3441 }
3442 else {
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003443 /* Scan/discover all ICD libraries */
3444 memset(&icd_libs, 0 , sizeof(struct loader_icd_libs));
Jon Ashburne39a4f82015-08-28 13:38:21 -06003445 loader_icd_scan(NULL, &icd_libs);
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003446 /* get extensions from all ICD's, merge so no duplicates */
Jon Ashburne39a4f82015-08-28 13:38:21 -06003447 loader_get_icd_loader_instance_extensions(NULL, &icd_libs, &icd_extensions);
3448 loader_scanned_icd_clear(NULL, &icd_libs);
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003449 global_ext_list = &icd_extensions;
Jon Ashburnb82c1852015-08-11 14:49:54 -06003450 }
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003451
Jon Ashburnb82c1852015-08-11 14:49:54 -06003452 if (global_ext_list == NULL) {
Mike Stroyan09c06c72015-10-01 15:23:48 -06003453 loader_destroy_layer_list(NULL, &instance_layers);
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06003454 return VK_ERROR_LAYER_NOT_PRESENT;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003455 }
3456
3457 if (pProperties == NULL) {
Chia-I Wud50a7d72015-10-26 20:48:51 +08003458 *pPropertyCount = global_ext_list->count;
Mike Stroyan09c06c72015-10-01 15:23:48 -06003459 loader_destroy_layer_list(NULL, &instance_layers);
Jon Ashburne39a4f82015-08-28 13:38:21 -06003460 loader_destroy_ext_list(NULL, &icd_extensions);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003461 return VK_SUCCESS;
3462 }
3463
Chia-I Wud50a7d72015-10-26 20:48:51 +08003464 copy_size = *pPropertyCount < global_ext_list->count ? *pPropertyCount : global_ext_list->count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003465 for (uint32_t i = 0; i < copy_size; i++) {
3466 memcpy(&pProperties[i],
Jon Ashburnb82c1852015-08-11 14:49:54 -06003467 &global_ext_list->list[i],
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003468 sizeof(VkExtensionProperties));
3469 }
Chia-I Wud50a7d72015-10-26 20:48:51 +08003470 *pPropertyCount = copy_size;
Jon Ashburne39a4f82015-08-28 13:38:21 -06003471 loader_destroy_ext_list(NULL, &icd_extensions);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003472
Jon Ashburnb82c1852015-08-11 14:49:54 -06003473 if (copy_size < global_ext_list->count) {
Mike Stroyan09c06c72015-10-01 15:23:48 -06003474 loader_destroy_layer_list(NULL, &instance_layers);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003475 return VK_INCOMPLETE;
3476 }
3477
Mike Stroyan09c06c72015-10-01 15:23:48 -06003478 loader_destroy_layer_list(NULL, &instance_layers);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003479 return VK_SUCCESS;
3480}
3481
Chia-I Wu9ab61502015-11-06 06:42:02 +08003482LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(
Chia-I Wud50a7d72015-10-26 20:48:51 +08003483 uint32_t* pPropertyCount,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003484 VkLayerProperties* pProperties)
Tony Barbour59a47322015-06-24 16:06:58 -06003485{
Jon Ashburn6301a0f2015-05-29 13:15:39 -06003486
Jon Ashburnb82c1852015-08-11 14:49:54 -06003487 struct loader_layer_list instance_layer_list;
Jon Ashburn87d6aa92015-08-28 15:19:27 -06003488 tls_instance = NULL;
Jon Ashburnb82c1852015-08-11 14:49:54 -06003489
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003490 loader_platform_thread_once(&once_init, loader_initialize);
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07003491
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003492 uint32_t copy_size;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06003493
Jon Ashburnb82c1852015-08-11 14:49:54 -06003494 /* get layer libraries */
3495 memset(&instance_layer_list, 0, sizeof(instance_layer_list));
Jon Ashburne39a4f82015-08-28 13:38:21 -06003496 loader_layer_scan(NULL, &instance_layer_list, NULL);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003497
3498 if (pProperties == NULL) {
Chia-I Wud50a7d72015-10-26 20:48:51 +08003499 *pPropertyCount = instance_layer_list.count;
Jon Ashburne39a4f82015-08-28 13:38:21 -06003500 loader_destroy_layer_list(NULL, &instance_layer_list);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003501 return VK_SUCCESS;
3502 }
3503
Chia-I Wud50a7d72015-10-26 20:48:51 +08003504 copy_size = (*pPropertyCount < instance_layer_list.count) ? *pPropertyCount : instance_layer_list.count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003505 for (uint32_t i = 0; i < copy_size; i++) {
Jon Ashburnb82c1852015-08-11 14:49:54 -06003506 memcpy(&pProperties[i], &instance_layer_list.list[i].info, sizeof(VkLayerProperties));
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003507 }
Chia-I Wud50a7d72015-10-26 20:48:51 +08003508 *pPropertyCount = copy_size;
Jon Ashburne39a4f82015-08-28 13:38:21 -06003509 loader_destroy_layer_list(NULL, &instance_layer_list);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003510
Jon Ashburnb82c1852015-08-11 14:49:54 -06003511 if (copy_size < instance_layer_list.count) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003512 return VK_INCOMPLETE;
3513 }
Tony Barbour59a47322015-06-24 16:06:58 -06003514
3515 return VK_SUCCESS;
3516}
3517
Chia-I Wu9ab61502015-11-06 06:42:02 +08003518VKAPI_ATTR VkResult VKAPI_CALL loader_EnumerateDeviceExtensionProperties(
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003519 VkPhysicalDevice physicalDevice,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003520 const char* pLayerName,
Chia-I Wud50a7d72015-10-26 20:48:51 +08003521 uint32_t* pPropertyCount,
Tony Barbour59a47322015-06-24 16:06:58 -06003522 VkExtensionProperties* pProperties)
3523{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003524 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003525 uint32_t copy_size;
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07003526
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003527 uint32_t count;
Jon Ashburn432d2762015-09-18 12:53:16 -06003528 struct loader_extension_list *dev_ext_list=NULL;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003529
Jon Ashburnb82c1852015-08-11 14:49:54 -06003530 /* get layer libraries if needed */
3531 if (pLayerName && strlen(pLayerName) != 0) {
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003532 for (uint32_t i = 0; i < phys_dev->this_instance->device_layer_list.count; i++) {
3533 struct loader_layer_properties *props = &phys_dev->this_instance->device_layer_list.list[i];
Jon Ashburnb82c1852015-08-11 14:49:54 -06003534 if (strcmp(props->info.layerName, pLayerName) == 0) {
3535 dev_ext_list = &props->device_extension_list;
3536 }
3537 }
3538 }
3539 else {
Jon Ashburn00eb6c02015-11-02 17:40:01 -07003540 /* this case is during the call down the instance chain */
3541 struct loader_icd *icd = phys_dev->this_icd;
3542 VkResult res;
3543 res = icd->EnumerateDeviceExtensionProperties(phys_dev->phys_dev, NULL, pPropertyCount, pProperties);
3544 if (pProperties != NULL && res == VK_SUCCESS) {
3545 /* initialize dev_extension list within the physicalDevice object */
3546 res = loader_init_physical_device_extensions(phys_dev->this_instance,
3547 phys_dev, *pPropertyCount, pProperties,
3548 &phys_dev->device_extension_cache);
3549 }
3550 return res;
Jon Ashburnb82c1852015-08-11 14:49:54 -06003551 }
3552
Jon Ashburn432d2762015-09-18 12:53:16 -06003553 count = (dev_ext_list == NULL) ? 0: dev_ext_list->count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003554 if (pProperties == NULL) {
Chia-I Wud50a7d72015-10-26 20:48:51 +08003555 *pPropertyCount = count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003556 return VK_SUCCESS;
3557 }
3558
Chia-I Wud50a7d72015-10-26 20:48:51 +08003559 copy_size = *pPropertyCount < count ? *pPropertyCount : count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003560 for (uint32_t i = 0; i < copy_size; i++) {
3561 memcpy(&pProperties[i],
Jon Ashburnb82c1852015-08-11 14:49:54 -06003562 &dev_ext_list->list[i],
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003563 sizeof(VkExtensionProperties));
3564 }
Chia-I Wud50a7d72015-10-26 20:48:51 +08003565 *pPropertyCount = copy_size;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003566
3567 if (copy_size < count) {
3568 return VK_INCOMPLETE;
3569 }
3570
3571 return VK_SUCCESS;
3572}
3573
Chia-I Wu9ab61502015-11-06 06:42:02 +08003574VKAPI_ATTR VkResult VKAPI_CALL loader_EnumerateDeviceLayerProperties(
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003575 VkPhysicalDevice physicalDevice,
Chia-I Wud50a7d72015-10-26 20:48:51 +08003576 uint32_t* pPropertyCount,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003577 VkLayerProperties* pProperties)
3578{
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003579 uint32_t copy_size;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003580 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003581
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003582 uint32_t count = phys_dev->this_instance->device_layer_list.count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003583
3584 if (pProperties == NULL) {
Chia-I Wud50a7d72015-10-26 20:48:51 +08003585 *pPropertyCount = count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003586 return VK_SUCCESS;
3587 }
3588
Chia-I Wud50a7d72015-10-26 20:48:51 +08003589 copy_size = (*pPropertyCount < count) ? *pPropertyCount : count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003590 for (uint32_t i = 0; i < copy_size; i++) {
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003591 memcpy(&pProperties[i], &(phys_dev->this_instance->device_layer_list.list[i].info), sizeof(VkLayerProperties));
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003592 }
Chia-I Wud50a7d72015-10-26 20:48:51 +08003593 *pPropertyCount = copy_size;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003594
3595 if (copy_size < count) {
3596 return VK_INCOMPLETE;
3597 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003598
3599 return VK_SUCCESS;
Jon Ashburn95a77ba2015-05-15 15:09:35 -06003600}