blob: 544b6af1429ca83ecde3dd4e851de2a6e445d9ad [file] [log] [blame]
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001/*
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08002 *
Courtney Goeltzenleuchter8a17da52015-10-29 13:50:34 -06003 * Copyright (C) 2015 Valve Corporation
Courtney Goeltzenleuchterebbb96d2015-12-02 14:53:22 -07004 * Copyright (C) 2015 Google Inc.
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08005 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
Chia-I Wu44e42362014-09-02 08:32:09 +080023 *
Courtney Goeltzenleuchter96cd7952015-10-30 11:14:30 -060024 * Author: Chia-I Wu <olvaffe@gmail.com>
25 * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
26 * Author: Ian Elliott <ian@LunarG.com>
27 * Author: Jon Ashburn <jon@lunarg.com>
28 *
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080029 */
Mark Lobodzinski28214d92015-11-25 13:26:15 -070030
Jon Ashburn183dfd02014-10-22 18:13:16 -060031#define _GNU_SOURCE
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080032#include <stdio.h>
33#include <stdlib.h>
34#include <stdarg.h>
35#include <stdbool.h>
36#include <string.h>
37
Chia-I Wu894a1172014-08-04 11:18:20 +080038#include <sys/types.h>
Johannes van Waverena6ce7b72015-10-28 11:45:00 -050039#if defined(_WIN32)
Ian Elliott81ac44c2015-01-13 17:52:38 -070040#include "dirent_on_windows.h"
Johannes van Waverena6ce7b72015-10-28 11:45:00 -050041#else // _WIN32
Chia-I Wu894a1172014-08-04 11:18:20 +080042#include <dirent.h>
Johannes van Waverena6ce7b72015-10-28 11:45:00 -050043#endif // _WIN32
Tobin Ehlis7a51d902015-07-03 10:34:49 -060044#include "vk_loader_platform.h"
Chia-I Wu468e3c32014-08-04 08:03:57 +080045#include "loader.h"
Jon Ashburnfce93d92015-05-12 17:26:48 -060046#include "gpa_helper.h"
47#include "table_ops.h"
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -060048#include "debug_report.h"
Ian Elliotta81e8ac2015-10-30 15:28:23 -060049#include "wsi.h"
David Pinedo329ca9e2015-11-06 12:54:48 -070050#include "vulkan/vk_icd.h"
Jon Ashburnffd5d672015-06-29 11:25:34 -060051#include "cJSON.h"
Jon Ashburn429e19f2015-11-17 15:31:02 -070052#include "murmurhash.h"
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080053
Courtney Goeltzenleuchter71cd74d2015-06-01 14:09:34 -060054static loader_platform_dl_handle loader_add_layer_lib(
Jon Ashburne58f1a32015-08-28 13:38:21 -060055 const struct loader_instance *inst,
Courtney Goeltzenleuchter71cd74d2015-06-01 14:09:34 -060056 const char *chain_type,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -060057 struct loader_layer_properties *layer_prop);
Courtney Goeltzenleuchter71cd74d2015-06-01 14:09:34 -060058
59static void loader_remove_layer_lib(
60 struct loader_instance *inst,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -060061 struct loader_layer_properties *layer_prop);
Courtney Goeltzenleuchter71cd74d2015-06-01 14:09:34 -060062
Jon Ashburnfce93d92015-05-12 17:26:48 -060063struct loader_struct loader = {0};
Jon Ashburn413d6582015-08-28 15:19:27 -060064// TLS for instance for alloc/free callbacks
65THREAD_LOCAL_DECL struct loader_instance *tls_instance;
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080066
Jon Ashburn8f6be302015-12-10 08:51:10 -070067static bool loader_init_generic_list(
Jon Ashburne58f1a32015-08-28 13:38:21 -060068 const struct loader_instance *inst,
Jon Ashburn8f6be302015-12-10 08:51:10 -070069 struct loader_generic_list *list_info,
70 size_t element_size);
Courtney Goeltzenleuchter9a4f38c2015-06-22 17:45:21 -060071
Courtney Goeltzenleuchtere728d122015-12-16 16:19:46 -070072static size_t loader_platform_combine_path(char *dest, size_t len, ...);
Daniel Dadap2e13fca2015-09-30 11:50:51 -050073
Jon Ashburn251258f2015-11-01 14:04:06 -070074struct loader_phys_dev_per_icd {
75 uint32_t count;
76 VkPhysicalDevice *phys_devs;
77};
78
Courtney Goeltzenleuchter8b253f92015-06-08 15:11:18 -060079enum loader_debug {
Courtney Goeltzenleuchter1d4c50f2015-07-08 18:41:08 -060080 LOADER_INFO_BIT = 0x01,
81 LOADER_WARN_BIT = 0x02,
82 LOADER_PERF_BIT = 0x04,
83 LOADER_ERROR_BIT = 0x08,
84 LOADER_DEBUG_BIT = 0x10,
Courtney Goeltzenleuchter8b253f92015-06-08 15:11:18 -060085};
86
87uint32_t g_loader_debug = 0;
88uint32_t g_loader_log_msgs = 0;
89
Jon Ashburnb40f2562015-05-29 13:15:39 -060090//thread safety lock for accessing global data structures such as "loader"
91// all entrypoints on the instance chain need to be locked except GPA
Jon Ashburnffd5d672015-06-29 11:25:34 -060092// additionally CreateDevice and DestroyDevice needs to be locked
Jon Ashburnb40f2562015-05-29 13:15:39 -060093loader_platform_thread_mutex loader_lock;
Jon Ashburnd02fc2c2015-09-22 13:11:00 -060094loader_platform_thread_mutex loader_json_lock;
Jon Ashburnb40f2562015-05-29 13:15:39 -060095
Ian Elliott1d73e662015-07-06 14:36:13 -060096// This table contains the loader's instance dispatch table, which contains
97// default functions if no instance layers are activated. This contains
98// pointers to "terminator functions".
Jon Ashburnb40f2562015-05-29 13:15:39 -060099const VkLayerInstanceDispatchTable instance_disp = {
Jon Ashburn8aa75cb2015-09-28 16:15:00 -0600100 .GetInstanceProcAddr = vkGetInstanceProcAddr,
Jon Ashburnfce93d92015-05-12 17:26:48 -0600101 .CreateInstance = loader_CreateInstance,
102 .DestroyInstance = loader_DestroyInstance,
103 .EnumeratePhysicalDevices = loader_EnumeratePhysicalDevices,
Chris Forbesd7576302015-06-21 22:55:02 +1200104 .GetPhysicalDeviceFeatures = loader_GetPhysicalDeviceFeatures,
Courtney Goeltzenleuchter4da96aa2015-07-12 12:52:09 -0600105 .GetPhysicalDeviceFormatProperties = loader_GetPhysicalDeviceFormatProperties,
Jon Ashburn4e189562015-07-23 18:49:07 -0600106 .GetPhysicalDeviceImageFormatProperties = loader_GetPhysicalDeviceImageFormatProperties,
Tony Barbour426b9052015-06-24 16:06:58 -0600107 .GetPhysicalDeviceProperties = loader_GetPhysicalDeviceProperties,
Cody Northropef72e2a2015-08-03 17:04:53 -0600108 .GetPhysicalDeviceQueueFamilyProperties = loader_GetPhysicalDeviceQueueFamilyProperties,
Tony Barbour426b9052015-06-24 16:06:58 -0600109 .GetPhysicalDeviceMemoryProperties = loader_GetPhysicalDeviceMemoryProperties,
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -0600110 .EnumerateDeviceExtensionProperties = loader_EnumerateDeviceExtensionProperties,
111 .EnumerateDeviceLayerProperties = loader_EnumerateDeviceLayerProperties,
Mark Lobodzinski83d4e6a2015-07-03 15:58:09 -0600112 .GetPhysicalDeviceSparseImageFormatProperties = loader_GetPhysicalDeviceSparseImageFormatProperties,
Ian Elliott7b9f7822015-11-25 14:43:02 -0700113 .DestroySurfaceKHR = loader_DestroySurfaceKHR,
Ian Elliott338dedb2015-08-21 15:09:33 -0600114 .GetPhysicalDeviceSurfaceSupportKHR = loader_GetPhysicalDeviceSurfaceSupportKHR,
Ian Elliott8cda1802015-11-19 16:05:09 -0700115 .GetPhysicalDeviceSurfaceCapabilitiesKHR = loader_GetPhysicalDeviceSurfaceCapabilitiesKHR,
116 .GetPhysicalDeviceSurfaceFormatsKHR = loader_GetPhysicalDeviceSurfaceFormatsKHR,
117 .GetPhysicalDeviceSurfacePresentModesKHR = loader_GetPhysicalDeviceSurfacePresentModesKHR,
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -0700118 .CreateDebugReportCallbackEXT = loader_CreateDebugReportCallback,
119 .DestroyDebugReportCallbackEXT = loader_DestroyDebugReportCallback,
120 .DebugReportMessageEXT = loader_DebugReportMessage,
Ian Elliott40c4a1f2015-11-23 10:17:23 -0700121#ifdef VK_USE_PLATFORM_MIR_KHR
Jon Ashburn25a158f2015-11-25 17:55:49 -0700122 .CreateMirSurfaceKHR = loader_CreateMirSurfaceKHR,
Ian Elliott4e309e92015-11-24 15:39:10 -0700123 .GetPhysicalDeviceMirPresentationSupportKHR = loader_GetPhysicalDeviceMirPresentationSupportKHR,
Ian Elliott40c4a1f2015-11-23 10:17:23 -0700124#endif
125#ifdef VK_USE_PLATFORM_WAYLAND_KHR
Jon Ashburn25a158f2015-11-25 17:55:49 -0700126 .CreateWaylandSurfaceKHR = loader_CreateWaylandSurfaceKHR,
Ian Elliott4e309e92015-11-24 15:39:10 -0700127 .GetPhysicalDeviceWaylandPresentationSupportKHR = loader_GetPhysicalDeviceWaylandPresentationSupportKHR,
Ian Elliott40c4a1f2015-11-23 10:17:23 -0700128#endif
129#ifdef VK_USE_PLATFORM_WIN32_KHR
Jon Ashburn25a158f2015-11-25 17:55:49 -0700130 .CreateWin32SurfaceKHR = loader_CreateWin32SurfaceKHR,
Ian Elliott4e309e92015-11-24 15:39:10 -0700131 .GetPhysicalDeviceWin32PresentationSupportKHR = loader_GetPhysicalDeviceWin32PresentationSupportKHR,
Ian Elliott40c4a1f2015-11-23 10:17:23 -0700132#endif
133#ifdef VK_USE_PLATFORM_XCB_KHR
Jon Ashburn25a158f2015-11-25 17:55:49 -0700134 .CreateXcbSurfaceKHR = loader_CreateXcbSurfaceKHR,
Ian Elliott4e309e92015-11-24 15:39:10 -0700135 .GetPhysicalDeviceXcbPresentationSupportKHR = loader_GetPhysicalDeviceXcbPresentationSupportKHR,
Ian Elliott40c4a1f2015-11-23 10:17:23 -0700136#endif
137#ifdef VK_USE_PLATFORM_XLIB_KHR
Jon Ashburn25a158f2015-11-25 17:55:49 -0700138 .CreateXlibSurfaceKHR = loader_CreateXlibSurfaceKHR,
Ian Elliott4e309e92015-11-24 15:39:10 -0700139 .GetPhysicalDeviceXlibPresentationSupportKHR = loader_GetPhysicalDeviceXlibPresentationSupportKHR,
Ian Elliott40c4a1f2015-11-23 10:17:23 -0700140#endif
Mark Lobodzinskib3e934d2015-12-10 16:25:21 -0700141#ifdef VK_USE_PLATFORM_ANDROID_KHR
142 .CreateAndroidSurfaceKHR = loader_CreateAndroidSurfaceKHR,
143#endif
Jon Ashburnfce93d92015-05-12 17:26:48 -0600144};
145
Jon Ashburn754f1992015-08-18 18:04:47 -0600146LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_init);
Ian Elliott81ac44c2015-01-13 17:52:38 -0700147
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600148void* loader_heap_alloc(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600149 const struct loader_instance *instance,
150 size_t size,
Jon Ashburn738136f2015-12-10 18:17:34 -0700151 VkSystemAllocationScope alloc_scope)
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600152{
Chia-I Wu1f851912015-10-27 18:04:07 +0800153 if (instance && instance->alloc_callbacks.pfnAllocation) {
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600154 /* TODO: What should default alignment be? 1, 4, 8, other? */
Chia-I Wu1f851912015-10-27 18:04:07 +0800155 return instance->alloc_callbacks.pfnAllocation(instance->alloc_callbacks.pUserData, size, 4, alloc_scope);
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600156 }
157 return malloc(size);
158}
159
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600160void loader_heap_free(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600161 const struct loader_instance *instance,
Chia-I Wu1f851912015-10-27 18:04:07 +0800162 void *pMemory)
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600163{
Chia-I Wu1f851912015-10-27 18:04:07 +0800164 if (pMemory == NULL) return;
Jon Ashburncfe4e682015-08-14 12:51:47 -0600165 if (instance && instance->alloc_callbacks.pfnFree) {
Chia-I Wu1f851912015-10-27 18:04:07 +0800166 instance->alloc_callbacks.pfnFree(instance->alloc_callbacks.pUserData, pMemory);
Jon Ashburnfab6ee22015-08-13 08:28:48 -0600167 return;
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600168 }
Chia-I Wu1f851912015-10-27 18:04:07 +0800169 free(pMemory);
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600170}
171
Jon Ashburne5e60df2015-08-27 15:23:52 -0600172void* loader_heap_realloc(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600173 const struct loader_instance *instance,
Chia-I Wu1f851912015-10-27 18:04:07 +0800174 void *pMemory,
Jon Ashburne5e60df2015-08-27 15:23:52 -0600175 size_t orig_size,
176 size_t size,
Chia-I Wu1f851912015-10-27 18:04:07 +0800177 VkSystemAllocationScope alloc_scope)
Jon Ashburne5e60df2015-08-27 15:23:52 -0600178{
Chia-I Wu1f851912015-10-27 18:04:07 +0800179 if (pMemory == NULL || orig_size == 0)
Chia-I Wu69f40122015-10-26 21:10:41 +0800180 return loader_heap_alloc(instance, size, alloc_scope);
Jon Ashburne5e60df2015-08-27 15:23:52 -0600181 if (size == 0) {
Chia-I Wu1f851912015-10-27 18:04:07 +0800182 loader_heap_free(instance, pMemory);
Jon Ashburne5e60df2015-08-27 15:23:52 -0600183 return NULL;
184 }
Chia-I Wu1f851912015-10-27 18:04:07 +0800185 if (instance && instance->alloc_callbacks.pfnAllocation) {
Jon Ashburne5e60df2015-08-27 15:23:52 -0600186 if (size <= orig_size) {
Chia-I Wu1f851912015-10-27 18:04:07 +0800187 memset(((uint8_t *)pMemory) + size, 0, orig_size - size);
188 return pMemory;
Jon Ashburne5e60df2015-08-27 15:23:52 -0600189 }
Chia-I Wu1f851912015-10-27 18:04:07 +0800190 void *new_ptr = instance->alloc_callbacks.pfnAllocation(instance->alloc_callbacks.pUserData, size, 4, alloc_scope);
Jon Ashburne5e60df2015-08-27 15:23:52 -0600191 if (!new_ptr)
192 return NULL;
Chia-I Wu1f851912015-10-27 18:04:07 +0800193 memcpy(new_ptr, pMemory, orig_size);
194 instance->alloc_callbacks.pfnFree(instance->alloc_callbacks.pUserData, pMemory);
Jon Ashburn37984152015-10-21 16:09:27 -0600195 return new_ptr;
Jon Ashburne5e60df2015-08-27 15:23:52 -0600196 }
Chia-I Wu1f851912015-10-27 18:04:07 +0800197 return realloc(pMemory, size);
Jon Ashburne5e60df2015-08-27 15:23:52 -0600198}
199
Jon Ashburn413d6582015-08-28 15:19:27 -0600200void *loader_tls_heap_alloc(size_t size)
201{
Chia-I Wu5eca31f2015-10-31 00:31:16 +0800202 return loader_heap_alloc(tls_instance, size, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
Jon Ashburn413d6582015-08-28 15:19:27 -0600203}
204
Chia-I Wu1f851912015-10-27 18:04:07 +0800205void loader_tls_heap_free(void *pMemory)
Jon Ashburn413d6582015-08-28 15:19:27 -0600206{
Chia-I Wu1f851912015-10-27 18:04:07 +0800207 loader_heap_free(tls_instance, pMemory);
Jon Ashburn413d6582015-08-28 15:19:27 -0600208}
209
Courtney Goeltzenleuchter05525da2015-12-03 13:48:01 -0700210static void loader_log(const struct loader_instance *inst, VkFlags msg_type, int32_t msg_code,
Jon Ashburnee33ae72015-06-30 14:46:22 -0700211 const char *format, ...)
212{
Jon Ashburn2b779162015-07-31 15:47:59 -0600213 char msg[512];
Jon Ashburnee33ae72015-06-30 14:46:22 -0700214 va_list ap;
215 int ret;
216
Jon Ashburnee33ae72015-06-30 14:46:22 -0700217 va_start(ap, format);
218 ret = vsnprintf(msg, sizeof(msg), format, ap);
219 if ((ret >= (int) sizeof(msg)) || ret < 0) {
220 msg[sizeof(msg)-1] = '\0';
221 }
222 va_end(ap);
223
Courtney Goeltzenleuchter05525da2015-12-03 13:48:01 -0700224 if (inst) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -0700225 util_DebugReportMessage(inst, msg_type, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, (uint64_t) inst, 0, msg_code, "loader", msg);
Courtney Goeltzenleuchter05525da2015-12-03 13:48:01 -0700226 }
227
228 if (!(msg_type & g_loader_log_msgs)) {
229 return;
230 }
231
Ian Elliott225188f2015-02-17 10:33:47 -0700232#if defined(WIN32)
Jon Ashburnee33ae72015-06-30 14:46:22 -0700233 OutputDebugString(msg);
mschott632564c2015-07-22 14:11:29 +0200234 OutputDebugString("\n");
Jon Ashburnee33ae72015-06-30 14:46:22 -0700235#endif
236 fputs(msg, stderr);
237 fputc('\n', stderr);
238}
239
240#if defined(WIN32)
Tony Barbour76096e62015-07-29 14:26:21 -0600241static char *loader_get_next_path(char *path);
Jon Ashburnee33ae72015-06-30 14:46:22 -0700242/**
243* Find the list of registry files (names within a key) in key "location".
244*
245* This function looks in the registry (hive = DEFAULT_VK_REGISTRY_HIVE) key as given in "location"
246* for a list or name/values which are added to a returned list (function return value).
247* The DWORD values within the key must be 0 or they are skipped.
Jon Ashburne58f1a32015-08-28 13:38:21 -0600248* Function return is a string with a ';' separated list of filenames.
Jon Ashburnee33ae72015-06-30 14:46:22 -0700249* Function return is NULL if no valid name/value pairs are found in the key,
250* or the key is not found.
251*
252* \returns
253* A string list of filenames as pointer.
254* When done using the returned string list, pointer should be freed.
255*/
Jon Ashburne58f1a32015-08-28 13:38:21 -0600256static char *loader_get_registry_files(const struct loader_instance *inst, char *location)
Jon Ashburnee33ae72015-06-30 14:46:22 -0700257{
258 LONG rtn_value;
259 HKEY hive, key;
Piers Daniellb1f6f6d2015-11-05 16:58:26 -0700260 DWORD access_flags;
Jon Ashburnee33ae72015-06-30 14:46:22 -0700261 char name[2048];
262 char *out = NULL;
Tony Barbour76096e62015-07-29 14:26:21 -0600263 char *loc = location;
264 char *next;
Jon Ashburnee33ae72015-06-30 14:46:22 -0700265 DWORD idx = 0;
266 DWORD name_size = sizeof(name);
267 DWORD value;
268 DWORD total_size = 4096;
269 DWORD value_size = sizeof(value);
Tony Barbour76096e62015-07-29 14:26:21 -0600270
271 while(*loc)
272 {
273 next = loader_get_next_path(loc);
274 hive = DEFAULT_VK_REGISTRY_HIVE;
Piers Daniellb1f6f6d2015-11-05 16:58:26 -0700275 access_flags = KEY_QUERY_VALUE;
Tony Barbour76096e62015-07-29 14:26:21 -0600276 rtn_value = RegOpenKeyEx(hive, loc, 0, access_flags, &key);
277 if (rtn_value != ERROR_SUCCESS) {
278 // We didn't find the key. Try the 32-bit hive (where we've seen the
279 // key end up on some people's systems):
280 access_flags |= KEY_WOW64_32KEY;
281 rtn_value = RegOpenKeyEx(hive, loc, 0, access_flags, &key);
282 if (rtn_value != ERROR_SUCCESS) {
283 // We still couldn't find the key, so give up:
284 loc = next;
285 continue;
Jon Ashburnee33ae72015-06-30 14:46:22 -0700286 }
Jon Ashburnee33ae72015-06-30 14:46:22 -0700287 }
Tony Barbour76096e62015-07-29 14:26:21 -0600288
Jon Ashburne58f1a32015-08-28 13:38:21 -0600289 while ((rtn_value = RegEnumValue(key, idx++, name, &name_size, NULL, NULL, (LPBYTE) &value, &value_size)) == ERROR_SUCCESS) {
Tony Barbour76096e62015-07-29 14:26:21 -0600290 if (value_size == sizeof(value) && value == 0) {
291 if (out == NULL) {
Courtney Goeltzenleuchterbed84552015-11-02 17:43:04 -0700292 out = loader_heap_alloc(inst, total_size, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Tony Barbour76096e62015-07-29 14:26:21 -0600293 out[0] = '\0';
294 }
295 else if (strlen(out) + name_size + 1 > total_size) {
Courtney Goeltzenleuchterbed84552015-11-02 17:43:04 -0700296 out = loader_heap_realloc(inst, out, total_size, total_size * 2, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Tony Barbour76096e62015-07-29 14:26:21 -0600297 total_size *= 2;
298 }
299 if (out == NULL) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -0700300 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Out of memory, failed loader_get_registry_files");
Tony Barbour76096e62015-07-29 14:26:21 -0600301 return NULL;
302 }
303 if (strlen(out) == 0)
304 snprintf(out, name_size + 1, "%s", name);
305 else
306 snprintf(out + strlen(out), name_size + 2, "%c%s", PATH_SEPERATOR, name);
307 }
308 name_size = 2048;
309 }
310 loc = next;
Jon Ashburnee33ae72015-06-30 14:46:22 -0700311 }
Tony Barbour76096e62015-07-29 14:26:21 -0600312
Jon Ashburnee33ae72015-06-30 14:46:22 -0700313 return out;
314}
315
Ian Elliott225188f2015-02-17 10:33:47 -0700316#endif // WIN32
317
Jon Ashburn4b7f35f2015-08-03 09:08:46 -0600318/**
Daniel Dadap2e13fca2015-09-30 11:50:51 -0500319 * Combine path elements, separating each element with the platform-specific
320 * directory separator, and save the combined string to a destination buffer,
321 * not exceeding the given length. Path elements are given as variadic args,
322 * with a NULL element terminating the list.
323 *
324 * \returns the total length of the combined string, not including an ASCII
325 * NUL termination character. This length may exceed the available storage:
326 * in this case, the written string will be truncated to avoid a buffer
327 * overrun, and the return value will greater than or equal to the storage
328 * size. A NULL argument may be provided as the destination buffer in order
329 * to determine the required string length without actually writing a string.
330 */
331
Courtney Goeltzenleuchtere728d122015-12-16 16:19:46 -0700332static size_t loader_platform_combine_path(char *dest, size_t len, ...)
Daniel Dadap2e13fca2015-09-30 11:50:51 -0500333{
Courtney Goeltzenleuchtere728d122015-12-16 16:19:46 -0700334 size_t required_len = 0;
Daniel Dadap2e13fca2015-09-30 11:50:51 -0500335 va_list ap;
336 const char *component;
337
338 va_start(ap, len);
339
340 while((component = va_arg(ap, const char *))) {
341 if (required_len > 0) {
342 // This path element is not the first non-empty element; prepend
343 // a directory separator if space allows
344 if (dest && required_len + 1 < len) {
345 snprintf(dest + required_len, len - required_len, "%c",
346 DIRECTORY_SYMBOL);
347 }
348 required_len++;
349 }
350
351 if (dest && required_len < len) {
352 strncpy(dest + required_len, component, len - required_len);
353 }
354 required_len += strlen(component);
355 }
356
357 va_end(ap);
358
359 // strncpy(3) won't add a NUL terminating byte in the event of truncation.
360 if (dest && required_len >= len) {
361 dest[len - 1] = '\0';
362 }
363
364 return required_len;
365}
366
367
368/**
Jon Ashburn4b7f35f2015-08-03 09:08:46 -0600369 * Given string of three part form "maj.min.pat" convert to a vulkan version
370 * number.
371 */
372static uint32_t loader_make_version(const char *vers_str)
373{
Jon Ashburnb8605fe2015-09-18 12:53:16 -0600374 uint32_t vers = 0, major=0, minor=0, patch=0;
Jon Ashburn4b7f35f2015-08-03 09:08:46 -0600375 char *minor_str= NULL;
376 char *patch_str = NULL;
377 char *cstr;
378 char *str;
379
380 if (!vers_str)
381 return vers;
382 cstr = loader_stack_alloc(strlen(vers_str) + 1);
383 strcpy(cstr, vers_str);
384 while ((str = strchr(cstr, '.')) != NULL) {
385 if (minor_str == NULL) {
386 minor_str = str + 1;
387 *str = '\0';
388 major = atoi(cstr);
389 }
390 else if (patch_str == NULL) {
391 patch_str = str + 1;
392 *str = '\0';
393 minor = atoi(minor_str);
394 }
395 else {
396 return vers;
397 }
398 cstr = str + 1;
399 }
400 patch = atoi(patch_str);
401
402 return VK_MAKE_VERSION(major, minor, patch);
403
404}
405
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600406bool compare_vk_extension_properties(const VkExtensionProperties *op1, const VkExtensionProperties *op2)
407{
Chia-I Wu1f851912015-10-27 18:04:07 +0800408 return strcmp(op1->extensionName, op2->extensionName) == 0 ? true : false;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600409}
410
Jon Ashburn1b111de2015-07-06 15:40:35 -0600411/**
Jon Ashburn60378412015-07-02 12:59:25 -0600412 * Search the given ext_array for an extension
413 * matching the given vk_ext_prop
414 */
415bool has_vk_extension_property_array(
416 const VkExtensionProperties *vk_ext_prop,
417 const uint32_t count,
418 const VkExtensionProperties *ext_array)
419{
420 for (uint32_t i = 0; i < count; i++) {
421 if (compare_vk_extension_properties(vk_ext_prop, &ext_array[i]))
422 return true;
423 }
424 return false;
425}
426
Jon Ashburn1b111de2015-07-06 15:40:35 -0600427/**
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600428 * Search the given ext_list for an extension
429 * matching the given vk_ext_prop
430 */
431bool has_vk_extension_property(
432 const VkExtensionProperties *vk_ext_prop,
433 const struct loader_extension_list *ext_list)
434{
435 for (uint32_t i = 0; i < ext_list->count; i++) {
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600436 if (compare_vk_extension_properties(&ext_list->list[i], vk_ext_prop))
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600437 return true;
438 }
439 return false;
440}
441
Jon Ashburn0bf6a182015-07-16 17:19:31 -0600442static inline bool loader_is_layer_type_device(const enum layer_type type) {
443 if ((type & VK_LAYER_TYPE_DEVICE_EXPLICIT) ||
444 (type & VK_LAYER_TYPE_DEVICE_IMPLICIT))
445 return true;
446 return false;
447}
448
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600449/*
Jon Ashburn1b111de2015-07-06 15:40:35 -0600450 * Search the given layer list for a layer matching the given layer name
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600451 */
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600452static struct loader_layer_properties *loader_get_layer_property(
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600453 const char *name,
454 const struct loader_layer_list *layer_list)
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600455{
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600456 for (uint32_t i = 0; i < layer_list->count; i++) {
457 const VkLayerProperties *item = &layer_list->list[i].info;
458 if (strcmp(name, item->layerName) == 0)
459 return &layer_list->list[i];
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600460 }
461 return NULL;
462}
463
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600464/**
465 * Get the next unused layer property in the list. Init the property to zero.
466 */
467static struct loader_layer_properties *loader_get_next_layer_property(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600468 const struct loader_instance *inst,
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600469 struct loader_layer_list *layer_list)
470{
471 if (layer_list->capacity == 0) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600472 layer_list->list = loader_heap_alloc(inst,
473 sizeof(struct loader_layer_properties) * 64,
Chia-I Wu1f851912015-10-27 18:04:07 +0800474 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600475 if (layer_list->list == NULL) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -0700476 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Out of memory can't add any layer properties to list");
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600477 return NULL;
478 }
479 memset(layer_list->list, 0, sizeof(struct loader_layer_properties) * 64);
480 layer_list->capacity = sizeof(struct loader_layer_properties) * 64;
481 }
482
483 // ensure enough room to add an entry
484 if ((layer_list->count + 1) * sizeof (struct loader_layer_properties)
485 > layer_list->capacity) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600486 layer_list->list = loader_heap_realloc(inst, layer_list->list,
487 layer_list->capacity,
488 layer_list->capacity * 2,
Chia-I Wu1f851912015-10-27 18:04:07 +0800489 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600490 if (layer_list->list == NULL) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -0700491 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600492 "realloc failed for layer list");
493 }
494 layer_list->capacity *= 2;
495 }
496
497 layer_list->count++;
498 return &(layer_list->list[layer_list->count - 1]);
499}
500
501/**
502 * Remove all layer properties entrys from the list
503 */
Jon Ashburne58f1a32015-08-28 13:38:21 -0600504void loader_delete_layer_properties(
505 const struct loader_instance *inst,
506 struct loader_layer_list *layer_list)
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600507{
Jon Ashburn738136f2015-12-10 18:17:34 -0700508 uint32_t i, j;
509 struct loader_device_extension_list *dev_ext_list;
Jon Ashburn182b8302015-08-11 14:49:54 -0600510 if (!layer_list)
511 return;
512
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600513 for (i = 0; i < layer_list->count; i++) {
Jon Ashburn8f6be302015-12-10 08:51:10 -0700514 loader_destroy_generic_list(inst, (struct loader_generic_list *)
515 &layer_list->list[i].instance_extension_list);
Jon Ashburn738136f2015-12-10 18:17:34 -0700516 dev_ext_list = &layer_list->list[i].device_extension_list;
517 if (dev_ext_list->capacity > 0 && dev_ext_list->list->entrypoint_count > 0) {
518 for (j= 0; j < dev_ext_list->list->entrypoint_count; j++) {
519 loader_heap_free(inst, dev_ext_list->list->entrypoints[j]);
520 }
521 loader_heap_free(inst, dev_ext_list->list->entrypoints);
522 }
Jon Ashburn8f6be302015-12-10 08:51:10 -0700523 loader_destroy_generic_list(inst, (struct loader_generic_list *)
Jon Ashburn738136f2015-12-10 18:17:34 -0700524 dev_ext_list);
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600525 }
526 layer_list->count = 0;
527
Jon Ashburn182b8302015-08-11 14:49:54 -0600528 if (layer_list->capacity > 0) {
529 layer_list->capacity = 0;
Jon Ashburne58f1a32015-08-28 13:38:21 -0600530 loader_heap_free(inst, layer_list->list);
Jon Ashburn182b8302015-08-11 14:49:54 -0600531 }
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600532
533}
534
Courtney Goeltzenleuchter03c80a62015-12-02 14:00:19 -0700535static void loader_add_instance_extensions(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600536 const struct loader_instance *inst,
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -0600537 const PFN_vkEnumerateInstanceExtensionProperties fp_get_props,
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600538 const char *lib_name,
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600539 struct loader_extension_list *ext_list)
540{
Courtney Goeltzenleuchterf843d2d2015-12-21 16:41:47 -0700541 uint32_t i, count = 0;
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600542 VkExtensionProperties *ext_props;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600543 VkResult res;
544
Courtney Goeltzenleuchteraa9faab2015-07-06 22:28:18 -0600545 if (!fp_get_props) {
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -0600546 /* No EnumerateInstanceExtensionProperties defined */
Courtney Goeltzenleuchteraa9faab2015-07-06 22:28:18 -0600547 return;
548 }
549
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600550 res = fp_get_props(NULL, &count, NULL);
Jon Ashburneb2728b2015-04-10 14:33:07 -0600551 if (res != VK_SUCCESS) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -0700552 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0, "Error getting Instance extension count from %s", lib_name);
Jon Ashburneb2728b2015-04-10 14:33:07 -0600553 return;
554 }
Jon Ashburn60699262015-06-10 16:11:42 -0600555
Courtney Goeltzenleuchteraa9faab2015-07-06 22:28:18 -0600556 if (count == 0) {
557 /* No ExtensionProperties to report */
558 return;
559 }
560
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600561 ext_props = loader_stack_alloc(count * sizeof(VkExtensionProperties));
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600562
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600563 res = fp_get_props(NULL, &count, ext_props);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600564 if (res != VK_SUCCESS) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -0700565 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0, "Error getting Instance extensions from %s", lib_name);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600566 return;
567 }
Tony Barbour426b9052015-06-24 16:06:58 -0600568
Jon Ashburneb2728b2015-04-10 14:33:07 -0600569 for (i = 0; i < count; i++) {
Courtney Goeltzenleuchter73a21d32015-07-12 13:20:05 -0600570 char spec_version[64];
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600571
572 snprintf(spec_version, sizeof(spec_version), "%d.%d.%d",
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600573 VK_MAJOR(ext_props[i].specVersion),
574 VK_MINOR(ext_props[i].specVersion),
575 VK_PATCH(ext_props[i].specVersion));
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -0700576 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
Courtney Goeltzenleuchter03c80a62015-12-02 14:00:19 -0700577 "Instance Extension: %s (%s) version %s",
Chia-I Wu1f851912015-10-27 18:04:07 +0800578 ext_props[i].extensionName, lib_name, spec_version);
Jon Ashburne58f1a32015-08-28 13:38:21 -0600579 loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600580 }
581
582 return;
583}
584
Jon Ashburndb5a5bc2015-11-02 17:40:01 -0700585/*
586 * Initialize ext_list with the physical device extensions.
587 * The extension properties are passed as inputs in count and ext_props.
588 */
Courtney Goeltzenleuchter03c80a62015-12-02 14:00:19 -0700589static VkResult loader_init_device_extensions(
Jon Ashburndb5a5bc2015-11-02 17:40:01 -0700590 const struct loader_instance *inst,
591 struct loader_physical_device *phys_dev,
592 uint32_t count,
593 VkExtensionProperties *ext_props,
594 struct loader_extension_list *ext_list)
595{
596 VkResult res;
597 uint32_t i;
598
Jon Ashburn8f6be302015-12-10 08:51:10 -0700599 if (!loader_init_generic_list(inst, (struct loader_generic_list *) ext_list,
600 sizeof(VkExtensionProperties))) {
Jon Ashburndb5a5bc2015-11-02 17:40:01 -0700601 return VK_ERROR_OUT_OF_HOST_MEMORY;
602 }
603
604 for (i = 0; i < count; i++) {
605 char spec_version[64];
606
607 snprintf(spec_version, sizeof (spec_version), "%d.%d.%d",
608 VK_MAJOR(ext_props[i].specVersion),
609 VK_MINOR(ext_props[i].specVersion),
610 VK_PATCH(ext_props[i].specVersion));
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -0700611 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
Courtney Goeltzenleuchter03c80a62015-12-02 14:00:19 -0700612 "Device Extension: %s (%s) version %s",
Jon Ashburndb5a5bc2015-11-02 17:40:01 -0700613 ext_props[i].extensionName, phys_dev->this_icd->this_icd_lib->lib_name, spec_version);
614 res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
615 if (res != VK_SUCCESS)
616 return res;
617 }
618
619 return VK_SUCCESS;
620}
621
Courtney Goeltzenleuchter03c80a62015-12-02 14:00:19 -0700622static VkResult loader_add_device_extensions(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600623 const struct loader_instance *inst,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600624 VkPhysicalDevice physical_device,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600625 const char *lib_name,
626 struct loader_extension_list *ext_list)
627{
628 uint32_t i, count;
629 VkResult res;
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600630 VkExtensionProperties *ext_props;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600631
Jon Ashburndb5a5bc2015-11-02 17:40:01 -0700632 res = loader_EnumerateDeviceExtensionProperties(physical_device, NULL, &count, NULL);
633 if (res == VK_SUCCESS && count > 0) {
634 ext_props = loader_stack_alloc(count * sizeof (VkExtensionProperties));
635 if (!ext_props)
636 return VK_ERROR_OUT_OF_HOST_MEMORY;
637 res = loader_EnumerateDeviceExtensionProperties(physical_device, NULL, &count, ext_props);
638 if (res != VK_SUCCESS)
Jon Ashburn251258f2015-11-01 14:04:06 -0700639 return res;
Jon Ashburndb5a5bc2015-11-02 17:40:01 -0700640 for (i = 0; i < count; i++) {
641 char spec_version[64];
642
643 snprintf(spec_version, sizeof (spec_version), "%d.%d.%d",
644 VK_MAJOR(ext_props[i].specVersion),
645 VK_MINOR(ext_props[i].specVersion),
646 VK_PATCH(ext_props[i].specVersion));
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -0700647 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
Courtney Goeltzenleuchter03c80a62015-12-02 14:00:19 -0700648 "Device Extension: %s (%s) version %s",
Jon Ashburndb5a5bc2015-11-02 17:40:01 -0700649 ext_props[i].extensionName, lib_name, spec_version);
650 res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
651 if (res != VK_SUCCESS)
652 return res;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600653 }
Jon Ashburndb5a5bc2015-11-02 17:40:01 -0700654 } else {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -0700655 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Error getting physical device extension info count from library %s", lib_name);
Jon Ashburndb5a5bc2015-11-02 17:40:01 -0700656 return res;
657 }
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600658
Jon Ashburn251258f2015-11-01 14:04:06 -0700659 return VK_SUCCESS;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600660}
661
Jon Ashburn8f6be302015-12-10 08:51:10 -0700662static bool loader_init_generic_list(const struct loader_instance *inst,
663 struct loader_generic_list *list_info,
664 size_t element_size)
Jon Ashburneb2728b2015-04-10 14:33:07 -0600665{
Jon Ashburn8f6be302015-12-10 08:51:10 -0700666 list_info->capacity = 32 * element_size;
667 list_info->list = loader_heap_alloc(inst, list_info->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
668 if (list_info->list == NULL) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600669 return false;
670 }
Jon Ashburn8f6be302015-12-10 08:51:10 -0700671 memset(list_info->list, 0, list_info->capacity);
672 list_info->count = 0;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600673 return true;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600674}
675
Jon Ashburn8f6be302015-12-10 08:51:10 -0700676void loader_destroy_generic_list(const struct loader_instance *inst,
677 struct loader_generic_list *list)
Jon Ashburneb2728b2015-04-10 14:33:07 -0600678{
Jon Ashburn8f6be302015-12-10 08:51:10 -0700679 loader_heap_free(inst, list->list);
680 list->count = 0;
681 list->capacity = 0;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600682}
Jon Ashburneb2728b2015-04-10 14:33:07 -0600683
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600684/*
685 * Append non-duplicate extension properties defined in props
686 * to the given ext_list.
Jon Ashburn251258f2015-11-01 14:04:06 -0700687 * Return
688 * Vk_SUCCESS on success
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600689 */
Jon Ashburn251258f2015-11-01 14:04:06 -0700690VkResult loader_add_to_ext_list(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600691 const struct loader_instance *inst,
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600692 struct loader_extension_list *ext_list,
693 uint32_t prop_list_count,
694 const VkExtensionProperties *props)
695{
696 uint32_t i;
697 const VkExtensionProperties *cur_ext;
698
699 if (ext_list->list == NULL || ext_list->capacity == 0) {
Jon Ashburn8f6be302015-12-10 08:51:10 -0700700 loader_init_generic_list(inst, (struct loader_generic_list *) ext_list,
701 sizeof(VkExtensionProperties));
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600702 }
703
704 if (ext_list->list == NULL)
Jon Ashburn251258f2015-11-01 14:04:06 -0700705 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600706
707 for (i = 0; i < prop_list_count; i++) {
708 cur_ext = &props[i];
709
710 // look for duplicates
711 if (has_vk_extension_property(cur_ext, ext_list)) {
712 continue;
713 }
714
715 // add to list at end
716 // check for enough capacity
717 if (ext_list->count * sizeof(VkExtensionProperties)
718 >= ext_list->capacity) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600719
720 ext_list->list = loader_heap_realloc(inst,
721 ext_list->list,
722 ext_list->capacity,
723 ext_list->capacity * 2,
Chia-I Wu1f851912015-10-27 18:04:07 +0800724 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn251258f2015-11-01 14:04:06 -0700725
726 if (ext_list->list == NULL)
727 return VK_ERROR_OUT_OF_HOST_MEMORY;
728
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600729 // double capacity
730 ext_list->capacity *= 2;
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600731 }
732
733 memcpy(&ext_list->list[ext_list->count], cur_ext, sizeof(VkExtensionProperties));
734 ext_list->count++;
735 }
Jon Ashburn251258f2015-11-01 14:04:06 -0700736 return VK_SUCCESS;
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600737}
738
Jon Ashburn738136f2015-12-10 18:17:34 -0700739/*
740 * Append one extension property defined in props with entrypoints
741 * defined in entrys to the given ext_list.
742 * Return
743 * Vk_SUCCESS on success
744 */
745VkResult loader_add_to_dev_ext_list(
746 const struct loader_instance *inst,
747 struct loader_device_extension_list *ext_list,
748 const VkExtensionProperties *props,
749 uint32_t entry_count,
750 char **entrys)
751{
752 uint32_t idx;
753 if (ext_list->list == NULL || ext_list->capacity == 0) {
754 loader_init_generic_list(inst, (struct loader_generic_list *) ext_list,
755 sizeof(struct loader_dev_ext_props));
756 }
757
758 if (ext_list->list == NULL)
759 return VK_ERROR_OUT_OF_HOST_MEMORY;
760
761 idx =ext_list->count;
762 // add to list at end
763 // check for enough capacity
764 if (idx * sizeof (struct loader_dev_ext_props)
765 >= ext_list->capacity) {
766
767 ext_list->list = loader_heap_realloc(inst,
768 ext_list->list,
769 ext_list->capacity,
770 ext_list->capacity * 2,
771 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
772
773 if (ext_list->list == NULL)
774 return VK_ERROR_OUT_OF_HOST_MEMORY;
775
776 // double capacity
777 ext_list->capacity *= 2;
778 }
779
780 memcpy(&ext_list->list[idx].props, props, sizeof(struct loader_dev_ext_props));
781 ext_list->list[idx].entrypoint_count = entry_count;
782 ext_list->list[idx].entrypoints = loader_heap_alloc(inst,
783 sizeof(char *) * entry_count,
784 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
785 if (ext_list->list[idx].entrypoints == NULL)
786 return VK_ERROR_OUT_OF_HOST_MEMORY;
787 for (uint32_t i = 0; i < entry_count; i++) {
788 ext_list->list[idx].entrypoints[i] = loader_heap_alloc(inst,
789 strlen(entrys[i]) + 1,
790 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
791 if (ext_list->list[idx].entrypoints[i] == NULL)
792 return VK_ERROR_OUT_OF_HOST_MEMORY;
793 strcpy(ext_list->list[idx].entrypoints[i], entrys[i]);
794 }
795 ext_list->count++;
796
797 return VK_SUCCESS;
798}
799
Jon Ashburn60378412015-07-02 12:59:25 -0600800/**
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600801 * Search the given search_list for any layers in the props list.
802 * Add these to the output layer_list. Don't add duplicates to the output layer_list.
Jon Ashburn60378412015-07-02 12:59:25 -0600803 */
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -0600804static VkResult loader_add_layer_names_to_list(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600805 const struct loader_instance *inst,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600806 struct loader_layer_list *output_list,
807 uint32_t name_count,
808 const char * const *names,
809 const struct loader_layer_list *search_list)
Jon Ashburneb2728b2015-04-10 14:33:07 -0600810{
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600811 struct loader_layer_properties *layer_prop;
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -0600812 VkResult err = VK_SUCCESS;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600813
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600814 for (uint32_t i = 0; i < name_count; i++) {
815 const char *search_target = names[i];
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600816 layer_prop = loader_get_layer_property(search_target, search_list);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600817 if (!layer_prop) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -0700818 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Unable to find layer %s", search_target);
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -0600819 err = VK_ERROR_LAYER_NOT_PRESENT;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600820 continue;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600821 }
822
Jon Ashburne58f1a32015-08-28 13:38:21 -0600823 loader_add_to_layer_list(inst, output_list, 1, layer_prop);
Jon Ashburneb2728b2015-04-10 14:33:07 -0600824 }
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -0600825
826 return err;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600827}
828
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600829
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600830/*
831 * Manage lists of VkLayerProperties
832 */
Jon Ashburne58f1a32015-08-28 13:38:21 -0600833static bool loader_init_layer_list(const struct loader_instance *inst,
834 struct loader_layer_list *list)
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600835{
836 list->capacity = 32 * sizeof(struct loader_layer_properties);
Chia-I Wu1f851912015-10-27 18:04:07 +0800837 list->list = loader_heap_alloc(inst, list->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600838 if (list->list == NULL) {
839 return false;
840 }
841 memset(list->list, 0, list->capacity);
842 list->count = 0;
843 return true;
844}
845
Jon Ashburne58f1a32015-08-28 13:38:21 -0600846void loader_destroy_layer_list(const struct loader_instance *inst,
847 struct loader_layer_list *layer_list)
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600848{
Jon Ashburne58f1a32015-08-28 13:38:21 -0600849 loader_heap_free(inst, layer_list->list);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600850 layer_list->count = 0;
851 layer_list->capacity = 0;
852}
853
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600854/*
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600855 * Manage list of layer libraries (loader_lib_info)
856 */
Jon Ashburne58f1a32015-08-28 13:38:21 -0600857static bool loader_init_layer_library_list(const struct loader_instance *inst,
858 struct loader_layer_library_list *list)
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600859{
860 list->capacity = 32 * sizeof(struct loader_lib_info);
Chia-I Wu1f851912015-10-27 18:04:07 +0800861 list->list = loader_heap_alloc(inst, list->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600862 if (list->list == NULL) {
863 return false;
864 }
865 memset(list->list, 0, list->capacity);
866 list->count = 0;
867 return true;
868}
869
Jon Ashburne58f1a32015-08-28 13:38:21 -0600870void loader_destroy_layer_library_list(const struct loader_instance *inst,
871 struct loader_layer_library_list *list)
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600872{
873 for (uint32_t i = 0; i < list->count; i++) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600874 loader_heap_free(inst, list->list[i].lib_name);
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600875 }
Jon Ashburne58f1a32015-08-28 13:38:21 -0600876 loader_heap_free(inst, list->list);
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600877 list->count = 0;
878 list->capacity = 0;
879}
880
881void loader_add_to_layer_library_list(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600882 const struct loader_instance *inst,
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600883 struct loader_layer_library_list *list,
884 uint32_t item_count,
885 const struct loader_lib_info *new_items)
886{
887 uint32_t i;
888 struct loader_lib_info *item;
889
890 if (list->list == NULL || list->capacity == 0) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600891 loader_init_layer_library_list(inst, list);
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600892 }
893
894 if (list->list == NULL)
895 return;
896
897 for (i = 0; i < item_count; i++) {
898 item = (struct loader_lib_info *) &new_items[i];
899
900 // look for duplicates
901 for (uint32_t j = 0; j < list->count; j++) {
902 if (strcmp(list->list[i].lib_name, new_items->lib_name) == 0) {
903 continue;
904 }
905 }
906
907 // add to list at end
908 // check for enough capacity
909 if (list->count * sizeof(struct loader_lib_info)
910 >= list->capacity) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600911
912 list->list = loader_heap_realloc(inst,
913 list->list,
914 list->capacity,
915 list->capacity * 2,
Chia-I Wu1f851912015-10-27 18:04:07 +0800916 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600917 // double capacity
918 list->capacity *= 2;
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600919 }
920
921 memcpy(&list->list[list->count], item, sizeof(struct loader_lib_info));
922 list->count++;
923 }
924}
925
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600926
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600927/*
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600928 * Search the given layer list for a list
929 * matching the given VkLayerProperties
930 */
931bool has_vk_layer_property(
932 const VkLayerProperties *vk_layer_prop,
933 const struct loader_layer_list *list)
934{
935 for (uint32_t i = 0; i < list->count; i++) {
936 if (strcmp(vk_layer_prop->layerName, list->list[i].info.layerName) == 0)
937 return true;
938 }
939 return false;
940}
941
942/*
943 * Search the given layer list for a layer
944 * matching the given name
945 */
946bool has_layer_name(
947 const char *name,
948 const struct loader_layer_list *list)
949{
950 for (uint32_t i = 0; i < list->count; i++) {
951 if (strcmp(name, list->list[i].info.layerName) == 0)
952 return true;
953 }
954 return false;
955}
956
957/*
958 * Append non-duplicate layer properties defined in prop_list
959 * to the given layer_info list
960 */
961void loader_add_to_layer_list(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600962 const struct loader_instance *inst,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600963 struct loader_layer_list *list,
964 uint32_t prop_list_count,
965 const struct loader_layer_properties *props)
966{
967 uint32_t i;
968 struct loader_layer_properties *layer;
969
970 if (list->list == NULL || list->capacity == 0) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600971 loader_init_layer_list(inst, list);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600972 }
973
974 if (list->list == NULL)
975 return;
976
977 for (i = 0; i < prop_list_count; i++) {
978 layer = (struct loader_layer_properties *) &props[i];
979
980 // look for duplicates
981 if (has_vk_layer_property(&layer->info, list)) {
982 continue;
983 }
984
985 // add to list at end
986 // check for enough capacity
987 if (list->count * sizeof(struct loader_layer_properties)
988 >= list->capacity) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600989
990 list->list = loader_heap_realloc(inst,
991 list->list,
992 list->capacity,
993 list->capacity * 2,
Chia-I Wu1f851912015-10-27 18:04:07 +0800994 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600995 // double capacity
996 list->capacity *= 2;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600997 }
998
999 memcpy(&list->list[list->count], layer, sizeof(struct loader_layer_properties));
1000 list->count++;
1001 }
1002}
1003
Jon Ashburnf2ddb732015-07-07 10:27:45 -06001004/**
1005 * Search the search_list for any layer with a name
1006 * that matches the given name and a type that matches the given type
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06001007 * Add all matching layers to the found_list
Jon Ashburnf2ddb732015-07-07 10:27:45 -06001008 * Do not add if found loader_layer_properties is already
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06001009 * on the found_list.
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001010 */
Jon Ashburn60378412015-07-02 12:59:25 -06001011static void loader_find_layer_name_add_list(
Jon Ashburne58f1a32015-08-28 13:38:21 -06001012 const struct loader_instance *inst,
Jon Ashburn60378412015-07-02 12:59:25 -06001013 const char *name,
Jon Ashburnf2ddb732015-07-07 10:27:45 -06001014 const enum layer_type type,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06001015 const struct loader_layer_list *search_list,
1016 struct loader_layer_list *found_list)
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001017{
Jon Ashburn87c8fe92015-10-05 09:03:21 -06001018 bool found = false;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001019 for (uint32_t i = 0; i < search_list->count; i++) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06001020 struct loader_layer_properties *layer_prop = &search_list->list[i];
Jon Ashburnf2ddb732015-07-07 10:27:45 -06001021 if (0 == strcmp(layer_prop->info.layerName, name) &&
1022 (layer_prop->type & type)) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06001023 /* Found a layer with the same name, add to found_list */
Jon Ashburne58f1a32015-08-28 13:38:21 -06001024 loader_add_to_layer_list(inst, found_list, 1, layer_prop);
Jon Ashburn87c8fe92015-10-05 09:03:21 -06001025 found = true;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001026 }
1027 }
Jon Ashburn87c8fe92015-10-05 09:03:21 -06001028 if (!found) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001029 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0, "Warning, couldn't find layer name %s to activate", name);
Jon Ashburn87c8fe92015-10-05 09:03:21 -06001030 }
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001031}
1032
Jon Ashburnc4748dc2015-08-04 11:14:18 -06001033static VkExtensionProperties *get_extension_property(
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06001034 const char *name,
1035 const struct loader_extension_list *list)
Jon Ashburn42e41032015-04-14 09:15:32 -06001036{
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06001037 for (uint32_t i = 0; i < list->count; i++) {
Chia-I Wu1f851912015-10-27 18:04:07 +08001038 if (strcmp(name, list->list[i].extensionName) == 0)
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06001039 return &list->list[i];
Jon Ashburn42e41032015-04-14 09:15:32 -06001040 }
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06001041 return NULL;
Jon Ashburn42e41032015-04-14 09:15:32 -06001042}
1043
Jon Ashburn738136f2015-12-10 18:17:34 -07001044static VkExtensionProperties *get_dev_extension_property(
1045 const char *name,
1046 const struct loader_device_extension_list *list)
1047{
1048 for (uint32_t i = 0; i < list->count; i++) {
1049 if (strcmp(name, list->list[i].props.extensionName) == 0)
1050 return &list->list[i].props;
1051 }
1052 return NULL;
1053}
1054
Jon Ashburn60378412015-07-02 12:59:25 -06001055/*
Courtney Goeltzenleuchter03c80a62015-12-02 14:00:19 -07001056 * For Instance extensions implemented within the loader (i.e. DEBUG_REPORT
Jon Ashburn60378412015-07-02 12:59:25 -06001057 * the extension must provide two entry points for the loader to use:
1058 * - "trampoline" entry point - this is the address returned by GetProcAddr
1059 * and will always do what's necessary to support a global call.
1060 * - "terminator" function - this function will be put at the end of the
Jon Ashburn2818eb72015-11-30 17:21:25 -07001061 * instance chain and will contain the necessary logic to call / process
Jon Ashburn60378412015-07-02 12:59:25 -06001062 * the extension for the appropriate ICDs that are available.
1063 * There is no generic mechanism for including these functions, the references
1064 * must be placed into the appropriate loader entry points.
1065 * GetInstanceProcAddr: call extension GetInstanceProcAddr to check for GetProcAddr requests
1066 * loader_coalesce_extensions(void) - add extension records to the list of global
1067 * extension available to the app.
1068 * instance_disp - add function pointer for terminator function to this array.
1069 * The extension itself should be in a separate file that will be
1070 * linked directly with the loader.
1071 */
Jon Ashburnc1d1eb72015-08-14 11:57:54 -06001072
Jon Ashburn754f1992015-08-18 18:04:47 -06001073void loader_get_icd_loader_instance_extensions(
Jon Ashburne58f1a32015-08-28 13:38:21 -06001074 const struct loader_instance *inst,
Jon Ashburn754f1992015-08-18 18:04:47 -06001075 struct loader_icd_libs *icd_libs,
1076 struct loader_extension_list *inst_exts)
Jon Ashburneb2728b2015-04-10 14:33:07 -06001077{
Jon Ashburn85f98072015-08-14 14:49:22 -06001078 struct loader_extension_list icd_exts;
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001079 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Build ICD instance extension list");
Jon Ashburneb2728b2015-04-10 14:33:07 -06001080 // traverse scanned icd list adding non-duplicate extensions to the list
Jon Ashburn754f1992015-08-18 18:04:47 -06001081 for (uint32_t i = 0; i < icd_libs->count; i++) {
Jon Ashburn8f6be302015-12-10 08:51:10 -07001082 loader_init_generic_list(inst, (struct loader_generic_list *) &icd_exts,
1083 sizeof(VkExtensionProperties));
Courtney Goeltzenleuchter03c80a62015-12-02 14:00:19 -07001084 loader_add_instance_extensions(inst, icd_libs->list[i].EnumerateInstanceExtensionProperties,
Jon Ashburn754f1992015-08-18 18:04:47 -06001085 icd_libs->list[i].lib_name,
Jon Ashburn85f98072015-08-14 14:49:22 -06001086 &icd_exts);
Jon Ashburne58f1a32015-08-28 13:38:21 -06001087 loader_add_to_ext_list(inst, inst_exts,
Jon Ashburn85f98072015-08-14 14:49:22 -06001088 icd_exts.count,
1089 icd_exts.list);
Jon Ashburn8f6be302015-12-10 08:51:10 -07001090 loader_destroy_generic_list(inst, (struct loader_generic_list *) &icd_exts);
Jon Ashburneb2728b2015-04-10 14:33:07 -06001091 };
1092
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001093 // Traverse loader's extensions, adding non-duplicate extensions to the list
Ian Elliotta81e8ac2015-10-30 15:28:23 -06001094 wsi_add_instance_extensions(inst, inst_exts);
Jon Ashburne58f1a32015-08-28 13:38:21 -06001095 debug_report_add_instance_extensions(inst, inst_exts);
Jon Ashburneb2728b2015-04-10 14:33:07 -06001096}
1097
Jon Ashburnba1f24e2015-12-11 09:41:34 -07001098struct loader_physical_device *loader_get_physical_device(const VkPhysicalDevice physdev)
1099{
1100 uint32_t i;
1101 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
1102 for (i = 0; i < inst->total_gpu_count; i++) {
1103 //TODO this aliases physDevices within instances, need for this
1104 // function to go away
1105 if (inst->phys_devs[i].disp == loader_get_instance_dispatch(physdev)) {
1106 return &inst->phys_devs[i];
1107 }
1108 }
1109 }
1110 return NULL;
1111}
1112
Jon Ashburne58f1a32015-08-28 13:38:21 -06001113struct loader_icd *loader_get_icd_and_device(const VkDevice device,
1114 struct loader_device **found_dev)
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06001115{
1116 *found_dev = NULL;
1117 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
1118 for (struct loader_icd *icd = inst->icds; icd; icd = icd->next) {
1119 for (struct loader_device *dev = icd->logical_device_list; dev; dev = dev->next)
Jon Ashburn0c5eea22015-09-30 12:56:42 -06001120 /* Value comparison of device prevents object wrapping by layers */
1121 if (loader_get_dispatch(dev->device) == loader_get_dispatch(device)) {
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06001122 *found_dev = dev;
1123 return icd;
1124 }
1125 }
1126 }
1127 return NULL;
1128}
1129
Jon Ashburne58f1a32015-08-28 13:38:21 -06001130static void loader_destroy_logical_device(const struct loader_instance *inst,
1131 struct loader_device *dev)
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06001132{
Jon Ashburne58f1a32015-08-28 13:38:21 -06001133 loader_heap_free(inst, dev->app_extension_props);
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06001134 if (dev->activated_layer_list.count)
Jon Ashburne58f1a32015-08-28 13:38:21 -06001135 loader_destroy_layer_list(inst, &dev->activated_layer_list);
1136 loader_heap_free(inst, dev);
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06001137}
1138
Jon Ashburne58f1a32015-08-28 13:38:21 -06001139static struct loader_device *loader_add_logical_device(
1140 const struct loader_instance *inst,
1141 const VkDevice dev,
1142 struct loader_device **device_list)
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06001143{
1144 struct loader_device *new_dev;
1145
Chia-I Wu1f851912015-10-27 18:04:07 +08001146 new_dev = loader_heap_alloc(inst, sizeof(struct loader_device), VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06001147 if (!new_dev) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001148 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Failed to alloc struct laoder-device");
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06001149 return NULL;
1150 }
1151
1152 memset(new_dev, 0, sizeof(struct loader_device));
1153
1154 new_dev->next = *device_list;
1155 new_dev->device = dev;
1156 *device_list = new_dev;
1157 return new_dev;
1158}
1159
Jon Ashburne58f1a32015-08-28 13:38:21 -06001160void loader_remove_logical_device(
1161 const struct loader_instance *inst,
Jon Ashburndbf8cee2015-11-19 15:43:26 -07001162 struct loader_icd *icd,
1163 struct loader_device *found_dev)
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06001164{
Jon Ashburndbf8cee2015-11-19 15:43:26 -07001165 struct loader_device *dev, *prev_dev;
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06001166
1167 if (!icd || !found_dev)
1168 return;
1169
1170 prev_dev = NULL;
1171 dev = icd->logical_device_list;
1172 while (dev && dev != found_dev) {
1173 prev_dev = dev;
1174 dev = dev->next;
1175 }
1176
1177 if (prev_dev)
1178 prev_dev->next = found_dev->next;
1179 else
1180 icd->logical_device_list = found_dev->next;
Jon Ashburne58f1a32015-08-28 13:38:21 -06001181 loader_destroy_logical_device(inst, found_dev);
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06001182}
1183
1184
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001185static void loader_icd_destroy(
1186 struct loader_instance *ptr_inst,
1187 struct loader_icd *icd)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001188{
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001189 ptr_inst->total_icd_count--;
Courtney Goeltzenleuchter6b70e362015-06-14 19:57:15 -06001190 for (struct loader_device *dev = icd->logical_device_list; dev; ) {
1191 struct loader_device *next_dev = dev->next;
Jon Ashburne58f1a32015-08-28 13:38:21 -06001192 loader_destroy_logical_device(ptr_inst, dev);
Courtney Goeltzenleuchter6b70e362015-06-14 19:57:15 -06001193 dev = next_dev;
1194 }
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06001195
Jon Ashburne58f1a32015-08-28 13:38:21 -06001196 loader_heap_free(ptr_inst, icd);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001197}
1198
Jon Ashburne58f1a32015-08-28 13:38:21 -06001199static struct loader_icd * loader_icd_create(const struct loader_instance *inst)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001200{
1201 struct loader_icd *icd;
1202
Chia-I Wu1f851912015-10-27 18:04:07 +08001203 icd = loader_heap_alloc(inst, sizeof(*icd), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001204 if (!icd)
1205 return NULL;
1206
Courtney Goeltzenleuchter6f928162014-10-28 10:29:27 -06001207 memset(icd, 0, sizeof(*icd));
1208
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001209 return icd;
1210}
1211
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001212static struct loader_icd *loader_icd_add(
1213 struct loader_instance *ptr_inst,
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06001214 const struct loader_scanned_icds *icd_lib)
Chia-I Wu894a1172014-08-04 11:18:20 +08001215{
1216 struct loader_icd *icd;
1217
Jon Ashburne58f1a32015-08-28 13:38:21 -06001218 icd = loader_icd_create(ptr_inst);
Chia-I Wu894a1172014-08-04 11:18:20 +08001219 if (!icd)
1220 return NULL;
1221
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06001222 icd->this_icd_lib = icd_lib;
1223 icd->this_instance = ptr_inst;
1224
Chia-I Wu894a1172014-08-04 11:18:20 +08001225 /* prepend to the list */
Jon Ashburn3336df82015-01-29 15:45:51 -07001226 icd->next = ptr_inst->icds;
1227 ptr_inst->icds = icd;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001228 ptr_inst->total_icd_count++;
Chia-I Wu894a1172014-08-04 11:18:20 +08001229
1230 return icd;
1231}
1232
Jon Ashburne58f1a32015-08-28 13:38:21 -06001233void loader_scanned_icd_clear(
1234 const struct loader_instance *inst,
1235 struct loader_icd_libs *icd_libs)
Jon Ashburn754f1992015-08-18 18:04:47 -06001236{
1237 if (icd_libs->capacity == 0)
1238 return;
1239 for (uint32_t i = 0; i < icd_libs->count; i++) {
1240 loader_platform_close_library(icd_libs->list[i].handle);
Jon Ashburne58f1a32015-08-28 13:38:21 -06001241 loader_heap_free(inst, icd_libs->list[i].lib_name);
Jon Ashburn754f1992015-08-18 18:04:47 -06001242 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06001243 loader_heap_free(inst, icd_libs->list);
Jon Ashburn754f1992015-08-18 18:04:47 -06001244 icd_libs->capacity = 0;
1245 icd_libs->count = 0;
1246 icd_libs->list = NULL;
1247}
1248
Jon Ashburne58f1a32015-08-28 13:38:21 -06001249static void loader_scanned_icd_init(const struct loader_instance *inst,
1250 struct loader_icd_libs *icd_libs)
Jon Ashburn754f1992015-08-18 18:04:47 -06001251{
Jon Ashburne58f1a32015-08-28 13:38:21 -06001252 loader_scanned_icd_clear(inst, icd_libs);
Jon Ashburn754f1992015-08-18 18:04:47 -06001253 icd_libs->capacity = 8 * sizeof(struct loader_scanned_icds);
Chia-I Wu1f851912015-10-27 18:04:07 +08001254 icd_libs->list = loader_heap_alloc(inst, icd_libs->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn754f1992015-08-18 18:04:47 -06001255
1256}
1257
1258static void loader_scanned_icd_add(
Jon Ashburne58f1a32015-08-28 13:38:21 -06001259 const struct loader_instance *inst,
Jon Ashburn754f1992015-08-18 18:04:47 -06001260 struct loader_icd_libs *icd_libs,
Jon Ashburn0083b222015-11-17 17:35:40 -07001261 const char *filename,
1262 uint32_t api_version)
Jon Ashburn14275da2015-01-28 11:01:35 -07001263{
Ian Elliott81ac44c2015-01-13 17:52:38 -07001264 loader_platform_dl_handle handle;
Tony Barbourde4124d2015-07-03 10:33:54 -06001265 PFN_vkCreateInstance fp_create_inst;
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -06001266 PFN_vkEnumerateInstanceExtensionProperties fp_get_global_ext_props;
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001267 PFN_vkGetInstanceProcAddr fp_get_proc_addr;
Jon Ashburn14275da2015-01-28 11:01:35 -07001268 struct loader_scanned_icds *new_node;
1269
Jon Ashburn754f1992015-08-18 18:04:47 -06001270 /* TODO implement ref counting of libraries, for now this function leaves
1271 libraries open and the scanned_icd_clear closes them */
Ian Elliott81ac44c2015-01-13 17:52:38 -07001272 // Used to call: dlopen(filename, RTLD_LAZY);
1273 handle = loader_platform_open_library(filename);
Jon Ashburn14275da2015-01-28 11:01:35 -07001274 if (!handle) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001275 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0, loader_platform_open_library_error(filename));
Jon Ashburn14275da2015-01-28 11:01:35 -07001276 return;
1277 }
1278
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001279#define LOOKUP_LD(func_ptr, func) do { \
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -06001280 func_ptr = (PFN_vk ##func) loader_platform_get_proc_address(handle, "vk" #func); \
Jon Ashburn14275da2015-01-28 11:01:35 -07001281 if (!func_ptr) { \
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001282 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0, loader_platform_get_proc_address_error("vk" #func)); \
Jon Ashburn14275da2015-01-28 11:01:35 -07001283 return; \
1284 } \
1285} while (0)
1286
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001287 LOOKUP_LD(fp_get_proc_addr, GetInstanceProcAddr);
1288 LOOKUP_LD(fp_create_inst, CreateInstance);
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -06001289 LOOKUP_LD(fp_get_global_ext_props, EnumerateInstanceExtensionProperties);
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001290
1291#undef LOOKUP_LD
Jon Ashburn14275da2015-01-28 11:01:35 -07001292
Jon Ashburn754f1992015-08-18 18:04:47 -06001293 // check for enough capacity
1294 if ((icd_libs->count * sizeof(struct loader_scanned_icds)) >= icd_libs->capacity) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06001295
1296 icd_libs->list = loader_heap_realloc(inst,
1297 icd_libs->list,
1298 icd_libs->capacity,
1299 icd_libs->capacity * 2,
Chia-I Wu1f851912015-10-27 18:04:07 +08001300 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn754f1992015-08-18 18:04:47 -06001301 // double capacity
1302 icd_libs->capacity *= 2;
Jon Ashburn14275da2015-01-28 11:01:35 -07001303 }
Jon Ashburn754f1992015-08-18 18:04:47 -06001304 new_node = &(icd_libs->list[icd_libs->count]);
Jon Ashburn14275da2015-01-28 11:01:35 -07001305
1306 new_node->handle = handle;
Jon Ashburn0083b222015-11-17 17:35:40 -07001307 new_node->api_version = api_version;
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001308 new_node->GetInstanceProcAddr = fp_get_proc_addr;
Jon Ashburn3336df82015-01-29 15:45:51 -07001309 new_node->CreateInstance = fp_create_inst;
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -06001310 new_node->EnumerateInstanceExtensionProperties = fp_get_global_ext_props;
Jon Ashburn14275da2015-01-28 11:01:35 -07001311
Jon Ashburne58f1a32015-08-28 13:38:21 -06001312 new_node->lib_name = (char *) loader_heap_alloc(inst,
1313 strlen(filename) + 1,
Chia-I Wu1f851912015-10-27 18:04:07 +08001314 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001315 if (!new_node->lib_name) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001316 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0, "Out of memory can't add icd");
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001317 return;
1318 }
1319 strcpy(new_node->lib_name, filename);
Jon Ashburn754f1992015-08-18 18:04:47 -06001320 icd_libs->count++;
Jon Ashburneb2728b2015-04-10 14:33:07 -06001321}
Ian Elliott81ac44c2015-01-13 17:52:38 -07001322
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001323static bool loader_icd_init_entrys(struct loader_icd *icd,
1324 VkInstance inst,
1325 const PFN_vkGetInstanceProcAddr fp_gipa)
Jon Ashburn0dd356d2015-05-14 12:43:38 -06001326{
1327 /* initialize entrypoint function pointers */
1328
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001329 #define LOOKUP_GIPA(func, required) do { \
1330 icd->func = (PFN_vk ##func) fp_gipa(inst, "vk" #func); \
1331 if (!icd->func && required) { \
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001332 loader_log((struct loader_instance *) inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0, \
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001333 loader_platform_get_proc_address_error("vk" #func)); \
1334 return false; \
1335 } \
Jon Ashburn0dd356d2015-05-14 12:43:38 -06001336 } while (0)
1337
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001338 LOOKUP_GIPA(GetDeviceProcAddr, true);
1339 LOOKUP_GIPA(DestroyInstance, true);
1340 LOOKUP_GIPA(EnumeratePhysicalDevices, true);
1341 LOOKUP_GIPA(GetPhysicalDeviceFeatures, true);
1342 LOOKUP_GIPA(GetPhysicalDeviceFormatProperties, true);
Jon Ashburn4e189562015-07-23 18:49:07 -06001343 LOOKUP_GIPA(GetPhysicalDeviceImageFormatProperties, true);
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001344 LOOKUP_GIPA(CreateDevice, true);
1345 LOOKUP_GIPA(GetPhysicalDeviceProperties, true);
1346 LOOKUP_GIPA(GetPhysicalDeviceMemoryProperties, true);
Cody Northropef72e2a2015-08-03 17:04:53 -06001347 LOOKUP_GIPA(GetPhysicalDeviceQueueFamilyProperties, true);
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -06001348 LOOKUP_GIPA(EnumerateDeviceExtensionProperties, true);
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001349 LOOKUP_GIPA(GetPhysicalDeviceSparseImageFormatProperties, true);
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001350 LOOKUP_GIPA(CreateDebugReportCallbackEXT, false);
1351 LOOKUP_GIPA(DestroyDebugReportCallbackEXT, false);
Ian Elliott338dedb2015-08-21 15:09:33 -06001352 LOOKUP_GIPA(GetPhysicalDeviceSurfaceSupportKHR, false);
Ian Elliott8cda1802015-11-19 16:05:09 -07001353 LOOKUP_GIPA(GetPhysicalDeviceSurfaceCapabilitiesKHR, false);
1354 LOOKUP_GIPA(GetPhysicalDeviceSurfaceFormatsKHR, false);
1355 LOOKUP_GIPA(GetPhysicalDeviceSurfacePresentModesKHR, false);
Ian Elliott4e309e92015-11-24 15:39:10 -07001356#ifdef VK_USE_PLATFORM_WIN32_KHR
1357 LOOKUP_GIPA(GetPhysicalDeviceWin32PresentationSupportKHR, false);
1358#endif
1359#ifdef VK_USE_PLATFORM_XCB_KHR
1360 LOOKUP_GIPA(GetPhysicalDeviceXcbPresentationSupportKHR, false);
1361#endif
Jon Ashburn0dd356d2015-05-14 12:43:38 -06001362
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001363#undef LOOKUP_GIPA
Ian Elliott1d73e662015-07-06 14:36:13 -06001364
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001365 return true;
Jon Ashburn0dd356d2015-05-14 12:43:38 -06001366}
1367
Courtney Goeltzenleuchter8b253f92015-06-08 15:11:18 -06001368static void loader_debug_init(void)
1369{
1370 const char *env;
1371
1372 if (g_loader_debug > 0)
1373 return;
1374
1375 g_loader_debug = 0;
1376
1377 /* parse comma-separated debug options */
Courtney Goeltzenleuchter893f2872015-07-29 09:08:22 -06001378 env = getenv("VK_LOADER_DEBUG");
Courtney Goeltzenleuchter8b253f92015-06-08 15:11:18 -06001379 while (env) {
1380 const char *p = strchr(env, ',');
1381 size_t len;
1382
1383 if (p)
1384 len = p - env;
1385 else
1386 len = strlen(env);
1387
1388 if (len > 0) {
Michael Worcesterc21f5ad2015-12-10 18:06:24 +00001389 if (strncmp(env, "all", len) == 0) {
1390 g_loader_debug = ~0u;
1391 g_loader_log_msgs = ~0u;
1392 } else if (strncmp(env, "warn", len) == 0) {
Courtney Goeltzenleuchter8b253f92015-06-08 15:11:18 -06001393 g_loader_debug |= LOADER_WARN_BIT;
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001394 g_loader_log_msgs |= VK_DEBUG_REPORT_WARN_BIT_EXT;
Courtney Goeltzenleuchter8b253f92015-06-08 15:11:18 -06001395 } else if (strncmp(env, "info", len) == 0) {
1396 g_loader_debug |= LOADER_INFO_BIT;
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001397 g_loader_log_msgs |= VK_DEBUG_REPORT_INFO_BIT_EXT;
Courtney Goeltzenleuchter8b253f92015-06-08 15:11:18 -06001398 } else if (strncmp(env, "perf", len) == 0) {
1399 g_loader_debug |= LOADER_PERF_BIT;
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001400 g_loader_log_msgs |= VK_DEBUG_REPORT_PERF_WARN_BIT_EXT;
Courtney Goeltzenleuchter8b253f92015-06-08 15:11:18 -06001401 } else if (strncmp(env, "error", len) == 0) {
1402 g_loader_debug |= LOADER_ERROR_BIT;
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001403 g_loader_log_msgs |= VK_DEBUG_REPORT_ERROR_BIT_EXT;
Courtney Goeltzenleuchter8b253f92015-06-08 15:11:18 -06001404 } else if (strncmp(env, "debug", len) == 0) {
1405 g_loader_debug |= LOADER_DEBUG_BIT;
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001406 g_loader_log_msgs |= VK_DEBUG_REPORT_DEBUG_BIT_EXT;
Courtney Goeltzenleuchter8b253f92015-06-08 15:11:18 -06001407 }
1408 }
1409
1410 if (!p)
1411 break;
1412
1413 env = p + 1;
1414 }
1415}
1416
Jon Ashburn754f1992015-08-18 18:04:47 -06001417void loader_initialize(void)
1418{
Jon Ashburnd02fc2c2015-09-22 13:11:00 -06001419 // initialize mutexs
Jon Ashburn754f1992015-08-18 18:04:47 -06001420 loader_platform_thread_create_mutex(&loader_lock);
Jon Ashburnd02fc2c2015-09-22 13:11:00 -06001421 loader_platform_thread_create_mutex(&loader_json_lock);
Jon Ashburn754f1992015-08-18 18:04:47 -06001422
1423 // initialize logging
1424 loader_debug_init();
Jon Ashburn413d6582015-08-28 15:19:27 -06001425
1426 // initial cJSON to use alloc callbacks
1427 cJSON_Hooks alloc_fns = {
1428 .malloc_fn = loader_tls_heap_alloc,
1429 .free_fn = loader_tls_heap_free,
1430 };
1431 cJSON_InitHooks(&alloc_fns);
Jon Ashburn754f1992015-08-18 18:04:47 -06001432}
1433
Jon Ashburnffd5d672015-06-29 11:25:34 -06001434struct loader_manifest_files {
1435 uint32_t count;
1436 char **filename_list;
1437};
1438
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06001439/**
Jon Ashburnffd5d672015-06-29 11:25:34 -06001440 * Get next file or dirname given a string list or registry key path
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06001441 *
1442 * \returns
Jon Ashburnffd5d672015-06-29 11:25:34 -06001443 * A pointer to first char in the next path.
1444 * The next path (or NULL) in the list is returned in next_path.
1445 * Note: input string is modified in some cases. PASS IN A COPY!
1446 */
Jon Ashburnffd5d672015-06-29 11:25:34 -06001447static char *loader_get_next_path(char *path)
1448{
1449 uint32_t len;
1450 char *next;
1451
1452 if (path == NULL)
1453 return NULL;
1454 next = strchr(path, PATH_SEPERATOR);
1455 if (next == NULL) {
1456 len = (uint32_t) strlen(path);
1457 next = path + len;
1458 }
1459 else {
1460 *next = '\0';
1461 next++;
1462 }
1463
1464 return next;
1465}
1466
1467/**
Daniel Dadap2e13fca2015-09-30 11:50:51 -05001468 * Given a path which is absolute or relative, expand the path if relative or
1469 * leave the path unmodified if absolute. The base path to prepend to relative
1470 * paths is given in rel_base.
Jon Ashburn38144502015-07-07 15:06:25 -06001471 *
1472 * \returns
1473 * A string in out_fullpath of the full absolute path
Jon Ashburn38144502015-07-07 15:06:25 -06001474 */
1475static void loader_expand_path(const char *path,
1476 const char *rel_base,
1477 size_t out_size,
1478 char *out_fullpath)
1479{
1480 if (loader_platform_is_path_absolute(path)) {
Daniel Dadap2e13fca2015-09-30 11:50:51 -05001481 // do not prepend a base to an absolute path
1482 rel_base = "";
Jon Ashburn38144502015-07-07 15:06:25 -06001483 }
Daniel Dadap2e13fca2015-09-30 11:50:51 -05001484
1485 loader_platform_combine_path(out_fullpath, out_size, rel_base, path, NULL);
Jon Ashburn38144502015-07-07 15:06:25 -06001486}
1487
1488/**
Jon Ashburnffd5d672015-06-29 11:25:34 -06001489 * Given a filename (file) and a list of paths (dir), try to find an existing
1490 * file in the paths. If filename already is a path then no
1491 * searching in the given paths.
1492 *
1493 * \returns
1494 * A string in out_fullpath of either the full path or file.
Jon Ashburnffd5d672015-06-29 11:25:34 -06001495 */
1496static void loader_get_fullpath(const char *file,
Daniel Dadap2e13fca2015-09-30 11:50:51 -05001497 const char *dirs,
Jon Ashburnffd5d672015-06-29 11:25:34 -06001498 size_t out_size,
1499 char *out_fullpath)
1500{
Daniel Dadap2e13fca2015-09-30 11:50:51 -05001501 if (!loader_platform_is_path(file) && *dirs) {
1502 char *dirs_copy, *dir, *next_dir;
1503
1504 dirs_copy = loader_stack_alloc(strlen(dirs) + 1);
1505 strcpy(dirs_copy, dirs);
1506
1507 //find if file exists after prepending paths in given list
1508 for (dir = dirs_copy;
1509 *dir && (next_dir = loader_get_next_path(dir));
1510 dir = next_dir) {
1511 loader_platform_combine_path(out_fullpath, out_size, dir, file, NULL);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001512 if (loader_platform_file_exists(out_fullpath)) {
1513 return;
1514 }
Jon Ashburnffd5d672015-06-29 11:25:34 -06001515 }
1516 }
Daniel Dadap2e13fca2015-09-30 11:50:51 -05001517
Jon Ashburnffd5d672015-06-29 11:25:34 -06001518 snprintf(out_fullpath, out_size, "%s", file);
1519}
1520
1521/**
1522 * Read a JSON file into a buffer.
1523 *
1524 * \returns
1525 * A pointer to a cJSON object representing the JSON parse tree.
1526 * This returned buffer should be freed by caller.
1527 */
Courtney Goeltzenleuchter05525da2015-12-03 13:48:01 -07001528static cJSON *loader_get_json(const struct loader_instance *inst, const char *filename)
Jon Ashburnffd5d672015-06-29 11:25:34 -06001529{
1530 FILE *file;
1531 char *json_buf;
1532 cJSON *json;
1533 uint64_t len;
1534 file = fopen(filename,"rb");
Jon Ashburna01fb3e2015-08-27 08:30:50 -06001535 if (!file) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001536 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Couldn't open JSON file %s", filename);
Jon Ashburna01fb3e2015-08-27 08:30:50 -06001537 return NULL;
1538 }
Jon Ashburnffd5d672015-06-29 11:25:34 -06001539 fseek(file, 0, SEEK_END);
1540 len = ftell(file);
1541 fseek(file, 0, SEEK_SET);
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -06001542 json_buf = (char*) loader_stack_alloc(len+1);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001543 if (json_buf == NULL) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001544 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Out of memory can't get JSON file");
Jon Ashburnffd5d672015-06-29 11:25:34 -06001545 fclose(file);
1546 return NULL;
1547 }
1548 if (fread(json_buf, sizeof(char), len, file) != len) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001549 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "fread failed can't get JSON file");
Jon Ashburnffd5d672015-06-29 11:25:34 -06001550 fclose(file);
1551 return NULL;
1552 }
1553 fclose(file);
1554 json_buf[len] = '\0';
1555
1556 //parse text from file
1557 json = cJSON_Parse(json_buf);
1558 if (json == NULL)
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001559 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Can't parse JSON file %s", filename);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001560 return json;
1561}
1562
1563/**
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06001564 * Do a deep copy of the loader_layer_properties structure.
1565 */
1566static void loader_copy_layer_properties(
Jon Ashburne58f1a32015-08-28 13:38:21 -06001567 const struct loader_instance *inst,
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06001568 struct loader_layer_properties *dst,
1569 struct loader_layer_properties *src)
1570{
Jon Ashburn738136f2015-12-10 18:17:34 -07001571 uint32_t cnt, i;
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06001572 memcpy(dst, src, sizeof (*src));
Jon Ashburne58f1a32015-08-28 13:38:21 -06001573 dst->instance_extension_list.list = loader_heap_alloc(
1574 inst,
1575 sizeof(VkExtensionProperties) *
1576 src->instance_extension_list.count,
Chia-I Wu1f851912015-10-27 18:04:07 +08001577 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburne58f1a32015-08-28 13:38:21 -06001578 dst->instance_extension_list.capacity = sizeof(VkExtensionProperties) *
1579 src->instance_extension_list.count;
1580 memcpy(dst->instance_extension_list.list, src->instance_extension_list.list,
1581 dst->instance_extension_list.capacity);
1582 dst->device_extension_list.list = loader_heap_alloc(
1583 inst,
Jon Ashburn738136f2015-12-10 18:17:34 -07001584 sizeof(struct loader_dev_ext_props) *
Jon Ashburne58f1a32015-08-28 13:38:21 -06001585 src->device_extension_list.count,
Chia-I Wu1f851912015-10-27 18:04:07 +08001586 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn738136f2015-12-10 18:17:34 -07001587
1588 dst->device_extension_list.capacity = sizeof(struct loader_dev_ext_props) *
Jon Ashburne58f1a32015-08-28 13:38:21 -06001589 src->device_extension_list.count;
1590 memcpy(dst->device_extension_list.list, src->device_extension_list.list,
1591 dst->device_extension_list.capacity);
Jon Ashburn738136f2015-12-10 18:17:34 -07001592 if (src->device_extension_list.count > 0 &&
1593 src->device_extension_list.list->entrypoint_count > 0) {
1594 cnt = src->device_extension_list.list->entrypoint_count;
1595 dst->device_extension_list.list->entrypoints = loader_heap_alloc(
1596 inst,
1597 sizeof(char *) * cnt,
1598 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
1599 for (i = 0; i < cnt; i++) {
1600 dst->device_extension_list.list->entrypoints[i] = loader_heap_alloc(
1601 inst,
1602 strlen(src->device_extension_list.list->entrypoints[i]) + 1,
1603 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
1604 strcpy(dst->device_extension_list.list->entrypoints[i],
1605 src->device_extension_list.list->entrypoints[i]);
1606 }
1607 }
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06001608}
1609
1610/**
Jon Ashburn1b111de2015-07-06 15:40:35 -06001611 * Given a cJSON struct (json) of the top level JSON object from layer manifest
1612 * file, add entry to the layer_list.
Jon Ashburn8e4fab42015-08-03 17:19:30 -06001613 * Fill out the layer_properties in this list entry from the input cJSON object.
Jon Ashburn1b111de2015-07-06 15:40:35 -06001614 *
1615 * \returns
1616 * void
1617 * layer_list has a new entry and initialized accordingly.
1618 * If the json input object does not have all the required fields no entry
1619 * is added to the list.
1620 */
Jon Ashburne58f1a32015-08-28 13:38:21 -06001621static void loader_add_layer_properties(const struct loader_instance *inst,
1622 struct loader_layer_list *layer_instance_list,
Jon Ashburn0bf6a182015-07-16 17:19:31 -06001623 struct loader_layer_list *layer_device_list,
Jon Ashburn1b111de2015-07-06 15:40:35 -06001624 cJSON *json,
1625 bool is_implicit,
1626 char *filename)
1627{
1628 /* Fields in layer manifest file that are required:
1629 * (required) “file_format_version”
1630 * following are required in the "layer" object:
1631 * (required) "name"
1632 * (required) "type"
1633 * (required) “library_path”
Jon Ashburn44fe0062015-11-18 16:46:48 -07001634 * (required) “api_version”
Jon Ashburn1b111de2015-07-06 15:40:35 -06001635 * (required) “implementation_version”
1636 * (required) “description”
1637 * (required for implicit layers) “disable_environment”
1638 *
1639 * First get all required items and if any missing abort
1640 */
1641
1642 cJSON *item, *layer_node, *ext_item;
1643 char *temp;
Jon Ashburn44fe0062015-11-18 16:46:48 -07001644 char *name, *type, *library_path, *api_version;
Jon Ashburn1b111de2015-07-06 15:40:35 -06001645 char *implementation_version, *description;
1646 cJSON *disable_environment;
Jon Ashburn738136f2015-12-10 18:17:34 -07001647 int i, j;
Jon Ashburnc4748dc2015-08-04 11:14:18 -06001648 VkExtensionProperties ext_prop;
Jon Ashburn1b111de2015-07-06 15:40:35 -06001649 item = cJSON_GetObjectItem(json, "file_format_version");
1650 if (item == NULL) {
1651 return;
1652 }
1653 char *file_vers = cJSON_PrintUnformatted(item);
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001654 loader_log(inst, VK_DEBUG_REPORT_INFO_BIT_EXT, 0, "Found manifest file %s, version %s",
Jon Ashburn1b111de2015-07-06 15:40:35 -06001655 filename, file_vers);
Jon Ashburn44fe0062015-11-18 16:46:48 -07001656 if (strcmp(file_vers, "\"1.0.0\"") != 0)
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001657 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0, "Unexpected manifest file version (expected 1.0.0), may cause errors");
Jon Ashburn413d6582015-08-28 15:19:27 -06001658 loader_tls_heap_free(file_vers);
Jon Ashburn1b111de2015-07-06 15:40:35 -06001659
Jon Ashburn1b111de2015-07-06 15:40:35 -06001660 layer_node = cJSON_GetObjectItem(json, "layer");
1661 if (layer_node == NULL) {
Jon Ashburnd2c905c2015-12-17 17:38:24 -07001662 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0, "Can't find \"layer\" object in manifest JSON file, skipping this file");
Jon Ashburn1b111de2015-07-06 15:40:35 -06001663 return;
1664 }
Jon Ashburn082569b2015-08-12 16:39:32 -06001665
1666 // loop through all "layer" objects in the file
1667 do {
Jon Ashburn1b111de2015-07-06 15:40:35 -06001668#define GET_JSON_OBJECT(node, var) { \
1669 var = cJSON_GetObjectItem(node, #var); \
Jon Ashburn082569b2015-08-12 16:39:32 -06001670 if (var == NULL) { \
1671 layer_node = layer_node->next; \
Jon Ashburnd2c905c2015-12-17 17:38:24 -07001672 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0,\
1673 "Didn't find required layer object %s in manifest JSON file, skipping this layer",\
1674 #var); \
Jon Ashburn082569b2015-08-12 16:39:32 -06001675 continue; \
1676 } \
Jon Ashburn1b111de2015-07-06 15:40:35 -06001677 }
1678#define GET_JSON_ITEM(node, var) { \
1679 item = cJSON_GetObjectItem(node, #var); \
Jon Ashburn082569b2015-08-12 16:39:32 -06001680 if (item == NULL) { \
1681 layer_node = layer_node->next; \
Jon Ashburnd2c905c2015-12-17 17:38:24 -07001682 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0,\
1683 "Didn't find required layer value %s in manifest JSON file, skipping this layer",\
1684 #var); \
Jon Ashburn082569b2015-08-12 16:39:32 -06001685 continue; \
1686 } \
Jon Ashburn1b111de2015-07-06 15:40:35 -06001687 temp = cJSON_Print(item); \
1688 temp[strlen(temp) - 1] = '\0'; \
Jon Ashburn0b728052015-08-04 10:22:33 -06001689 var = loader_stack_alloc(strlen(temp) + 1); \
Jon Ashburn1b111de2015-07-06 15:40:35 -06001690 strcpy(var, &temp[1]); \
Jon Ashburn413d6582015-08-28 15:19:27 -06001691 loader_tls_heap_free(temp); \
Jon Ashburn1b111de2015-07-06 15:40:35 -06001692 }
Jon Ashburn082569b2015-08-12 16:39:32 -06001693 GET_JSON_ITEM(layer_node, name)
1694 GET_JSON_ITEM(layer_node, type)
1695 GET_JSON_ITEM(layer_node, library_path)
Jon Ashburn44fe0062015-11-18 16:46:48 -07001696 GET_JSON_ITEM(layer_node, api_version)
Jon Ashburn082569b2015-08-12 16:39:32 -06001697 GET_JSON_ITEM(layer_node, implementation_version)
1698 GET_JSON_ITEM(layer_node, description)
1699 if (is_implicit) {
1700 GET_JSON_OBJECT(layer_node, disable_environment)
1701 }
Jon Ashburn1b111de2015-07-06 15:40:35 -06001702#undef GET_JSON_ITEM
1703#undef GET_JSON_OBJECT
1704
Jon Ashburn082569b2015-08-12 16:39:32 -06001705 // add list entry
Jon Ashburnb8605fe2015-09-18 12:53:16 -06001706 struct loader_layer_properties *props=NULL;
Jon Ashburn082569b2015-08-12 16:39:32 -06001707 if (!strcmp(type, "DEVICE")) {
1708 if (layer_device_list == NULL) {
1709 layer_node = layer_node->next;
1710 continue;
1711 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06001712 props = loader_get_next_layer_property(inst, layer_device_list);
Jon Ashburn082569b2015-08-12 16:39:32 -06001713 props->type = (is_implicit) ? VK_LAYER_TYPE_DEVICE_IMPLICIT : VK_LAYER_TYPE_DEVICE_EXPLICIT;
1714 }
1715 if (!strcmp(type, "INSTANCE")) {
1716 if (layer_instance_list == NULL) {
1717 layer_node = layer_node->next;
1718 continue;
1719 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06001720 props = loader_get_next_layer_property(inst, layer_instance_list);
Jon Ashburn082569b2015-08-12 16:39:32 -06001721 props->type = (is_implicit) ? VK_LAYER_TYPE_INSTANCE_IMPLICIT : VK_LAYER_TYPE_INSTANCE_EXPLICIT;
1722 }
1723 if (!strcmp(type, "GLOBAL")) {
1724 if (layer_instance_list != NULL)
Jon Ashburne58f1a32015-08-28 13:38:21 -06001725 props = loader_get_next_layer_property(inst, layer_instance_list);
Jon Ashburn082569b2015-08-12 16:39:32 -06001726 else if (layer_device_list != NULL)
Jon Ashburne58f1a32015-08-28 13:38:21 -06001727 props = loader_get_next_layer_property(inst, layer_device_list);
Jon Ashburn082569b2015-08-12 16:39:32 -06001728 else {
1729 layer_node = layer_node->next;
1730 continue;
1731 }
1732 props->type = (is_implicit) ? VK_LAYER_TYPE_GLOBAL_IMPLICIT : VK_LAYER_TYPE_GLOBAL_EXPLICIT;
1733 }
Jon Ashburn0bf6a182015-07-16 17:19:31 -06001734
Jon Ashburnb8605fe2015-09-18 12:53:16 -06001735 if (props == NULL) {
1736 layer_node = layer_node->next;
1737 continue;
1738 }
1739
Jon Ashburn082569b2015-08-12 16:39:32 -06001740 strncpy(props->info.layerName, name, sizeof (props->info.layerName));
1741 props->info.layerName[sizeof (props->info.layerName) - 1] = '\0';
Jon Ashburn38144502015-07-07 15:06:25 -06001742
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06001743 char *fullpath = props->lib_name;
Jon Ashburn082569b2015-08-12 16:39:32 -06001744 char *rel_base;
Jon Ashburnfc8f38d2015-12-01 17:11:02 -07001745 if (loader_platform_is_path(library_path)) {
Jon Ashburn082569b2015-08-12 16:39:32 -06001746 // a relative or absolute path
Daniel Dadap2e13fca2015-09-30 11:50:51 -05001747 char *name_copy = loader_stack_alloc(strlen(filename) + 1);
Jon Ashburn082569b2015-08-12 16:39:32 -06001748 strcpy(name_copy, filename);
1749 rel_base = loader_platform_dirname(name_copy);
Jon Ashburn082569b2015-08-12 16:39:32 -06001750 loader_expand_path(library_path, rel_base, MAX_STRING_SIZE, fullpath);
Daniel Dadap2e13fca2015-09-30 11:50:51 -05001751 } else {
1752 // a filename which is assumed in a system directory
1753 loader_get_fullpath(library_path, DEFAULT_VK_LAYERS_PATH, MAX_STRING_SIZE, fullpath);
Jon Ashburn082569b2015-08-12 16:39:32 -06001754 }
Jon Ashburn44fe0062015-11-18 16:46:48 -07001755 props->info.specVersion = loader_make_version(api_version);
1756 props->info.implementationVersion = atoi(implementation_version);
Jon Ashburn082569b2015-08-12 16:39:32 -06001757 strncpy((char *) props->info.description, description, sizeof (props->info.description));
1758 props->info.description[sizeof (props->info.description) - 1] = '\0';
1759 if (is_implicit) {
1760 strncpy(props->disable_env_var.name, disable_environment->child->string, sizeof (props->disable_env_var.name));
1761 props->disable_env_var.name[sizeof (props->disable_env_var.name) - 1] = '\0';
1762 strncpy(props->disable_env_var.value, disable_environment->child->valuestring, sizeof (props->disable_env_var.value));
1763 props->disable_env_var.value[sizeof (props->disable_env_var.value) - 1] = '\0';
1764 }
Jon Ashburn1b111de2015-07-06 15:40:35 -06001765
Jon Ashburn082569b2015-08-12 16:39:32 -06001766 /**
1767 * Now get all optional items and objects and put in list:
1768 * functions
1769 * instance_extensions
1770 * device_extensions
1771 * enable_environment (implicit layers only)
1772 */
Jon Ashburn1b111de2015-07-06 15:40:35 -06001773#define GET_JSON_OBJECT(node, var) { \
1774 var = cJSON_GetObjectItem(node, #var); \
1775 }
1776#define GET_JSON_ITEM(node, var) { \
1777 item = cJSON_GetObjectItem(node, #var); \
Jon Ashburn2db08042015-09-09 11:29:24 -06001778 if (item != NULL) { \
Jon Ashburn1b111de2015-07-06 15:40:35 -06001779 temp = cJSON_Print(item); \
Jon Ashburn2db08042015-09-09 11:29:24 -06001780 temp[strlen(temp) - 1] = '\0'; \
1781 var = loader_stack_alloc(strlen(temp) + 1);\
1782 strcpy(var, &temp[1]); \
1783 loader_tls_heap_free(temp); \
1784 } \
Jon Ashburn1b111de2015-07-06 15:40:35 -06001785 }
1786
Jon Ashburn082569b2015-08-12 16:39:32 -06001787 cJSON *instance_extensions, *device_extensions, *functions, *enable_environment;
Jon Ashburn738136f2015-12-10 18:17:34 -07001788 cJSON *entrypoints;
1789 char *vkGetInstanceProcAddr, *vkGetDeviceProcAddr, *spec_version;
1790 char **entry_array;
1791 vkGetInstanceProcAddr = NULL;
1792 vkGetDeviceProcAddr = NULL;
1793 spec_version = NULL;
1794 entrypoints = NULL;
1795 entry_array = NULL;
1796 /**
1797 * functions
1798 * vkGetInstanceProcAddr
1799 * vkGetDeviceProcAddr
1800 */
Jon Ashburn082569b2015-08-12 16:39:32 -06001801 GET_JSON_OBJECT(layer_node, functions)
1802 if (functions != NULL) {
1803 GET_JSON_ITEM(functions, vkGetInstanceProcAddr)
1804 GET_JSON_ITEM(functions, vkGetDeviceProcAddr)
Jon Ashburn2db08042015-09-09 11:29:24 -06001805 if (vkGetInstanceProcAddr != NULL)
1806 strncpy(props->functions.str_gipa, vkGetInstanceProcAddr, sizeof (props->functions.str_gipa));
Jon Ashburn082569b2015-08-12 16:39:32 -06001807 props->functions.str_gipa[sizeof (props->functions.str_gipa) - 1] = '\0';
Jon Ashburn2db08042015-09-09 11:29:24 -06001808 if (vkGetDeviceProcAddr != NULL)
1809 strncpy(props->functions.str_gdpa, vkGetDeviceProcAddr, sizeof (props->functions.str_gdpa));
Jon Ashburn082569b2015-08-12 16:39:32 -06001810 props->functions.str_gdpa[sizeof (props->functions.str_gdpa) - 1] = '\0';
Jon Ashburn1b111de2015-07-06 15:40:35 -06001811 }
Jon Ashburn738136f2015-12-10 18:17:34 -07001812 /**
1813 * instance_extensions
1814 * array of
1815 * name
1816 * spec_version
1817 */
Jon Ashburn082569b2015-08-12 16:39:32 -06001818 GET_JSON_OBJECT(layer_node, instance_extensions)
1819 if (instance_extensions != NULL) {
1820 int count = cJSON_GetArraySize(instance_extensions);
1821 for (i = 0; i < count; i++) {
1822 ext_item = cJSON_GetArrayItem(instance_extensions, i);
1823 GET_JSON_ITEM(ext_item, name)
Jon Ashburn44fe0062015-11-18 16:46:48 -07001824 GET_JSON_ITEM(ext_item, spec_version)
Jon Ashburn738136f2015-12-10 18:17:34 -07001825 if (name != NULL) {
Jon Ashburn8f6be302015-12-10 08:51:10 -07001826 strncpy(ext_prop.extensionName, name, sizeof (ext_prop.extensionName));
1827 ext_prop.extensionName[sizeof (ext_prop.extensionName) - 1] = '\0';
Jon Ashburn738136f2015-12-10 18:17:34 -07001828 }
Jon Ashburn44fe0062015-11-18 16:46:48 -07001829 ext_prop.specVersion = atoi(spec_version);
Jon Ashburne58f1a32015-08-28 13:38:21 -06001830 loader_add_to_ext_list(inst, &props->instance_extension_list, 1, &ext_prop);
Jon Ashburn082569b2015-08-12 16:39:32 -06001831 }
Jon Ashburn1b111de2015-07-06 15:40:35 -06001832 }
Jon Ashburn738136f2015-12-10 18:17:34 -07001833 /**
1834 * device_extensions
1835 * array of
1836 * name
1837 * spec_version
1838 * entrypoints
1839 */
Jon Ashburn082569b2015-08-12 16:39:32 -06001840 GET_JSON_OBJECT(layer_node, device_extensions)
1841 if (device_extensions != NULL) {
1842 int count = cJSON_GetArraySize(device_extensions);
1843 for (i = 0; i < count; i++) {
1844 ext_item = cJSON_GetArrayItem(device_extensions, i);
Jon Ashburn738136f2015-12-10 18:17:34 -07001845 GET_JSON_ITEM(ext_item, name)
1846 GET_JSON_ITEM(ext_item, spec_version)
1847 if (name != NULL) {
Jon Ashburn8f6be302015-12-10 08:51:10 -07001848 strncpy(ext_prop.extensionName, name, sizeof (ext_prop.extensionName));
1849 ext_prop.extensionName[sizeof (ext_prop.extensionName) - 1] = '\0';
Jon Ashburn738136f2015-12-10 18:17:34 -07001850 }
Jon Ashburn44fe0062015-11-18 16:46:48 -07001851 ext_prop.specVersion = atoi(spec_version);
Jon Ashburn738136f2015-12-10 18:17:34 -07001852 //entrypoints = cJSON_GetObjectItem(ext_item, "entrypoints");
1853 GET_JSON_OBJECT(ext_item, entrypoints)
1854 int entry_count;
1855 if (entrypoints == NULL)
1856 continue;
1857 entry_count = cJSON_GetArraySize(entrypoints);
1858 if (entry_count)
1859 entry_array = (char **) loader_stack_alloc(sizeof(char *) * entry_count);
1860 for (j = 0; j < entry_count; j++) {
1861 ext_item = cJSON_GetArrayItem(entrypoints, j);
1862 if (ext_item != NULL) {
1863 temp = cJSON_Print(ext_item);
1864 temp[strlen(temp) - 1] = '\0';
1865 entry_array[j] = loader_stack_alloc(strlen(temp) + 1);
1866 strcpy(entry_array[j], &temp[1]);
1867 loader_tls_heap_free(temp);
Jon Ashburn8f6be302015-12-10 08:51:10 -07001868 }
1869 }
Jon Ashburn738136f2015-12-10 18:17:34 -07001870 loader_add_to_dev_ext_list(inst, &props->device_extension_list,
1871 &ext_prop, entry_count, entry_array);
1872 }
1873 }
Jon Ashburn082569b2015-08-12 16:39:32 -06001874 if (is_implicit) {
1875 GET_JSON_OBJECT(layer_node, enable_environment)
Jon Ashburnd2c905c2015-12-17 17:38:24 -07001876
1877 // enable_environment is optional
1878 if (enable_environment) {
1879 strncpy(props->enable_env_var.name, enable_environment->child->string, sizeof (props->enable_env_var.name));
1880 props->enable_env_var.name[sizeof (props->enable_env_var.name) - 1] = '\0';
1881 strncpy(props->enable_env_var.value, enable_environment->child->valuestring, sizeof (props->enable_env_var.value));
1882 props->enable_env_var.value[sizeof (props->enable_env_var.value) - 1] = '\0';
1883 }
Jon Ashburn082569b2015-08-12 16:39:32 -06001884 }
Jon Ashburn1b111de2015-07-06 15:40:35 -06001885#undef GET_JSON_ITEM
1886#undef GET_JSON_OBJECT
Jon Ashburn082569b2015-08-12 16:39:32 -06001887 // for global layers need to add them to both device and instance list
1888 if (!strcmp(type, "GLOBAL")) {
1889 struct loader_layer_properties *dev_props;
1890 if (layer_instance_list == NULL || layer_device_list == NULL) {
1891 layer_node = layer_node->next;
1892 continue;
1893 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06001894 dev_props = loader_get_next_layer_property(inst, layer_device_list);
Jon Ashburn082569b2015-08-12 16:39:32 -06001895 //copy into device layer list
Jon Ashburne58f1a32015-08-28 13:38:21 -06001896 loader_copy_layer_properties(inst, dev_props, props);
Jon Ashburn082569b2015-08-12 16:39:32 -06001897 }
1898 layer_node = layer_node->next;
1899 } while (layer_node != NULL);
1900 return;
Jon Ashburn1b111de2015-07-06 15:40:35 -06001901}
1902
1903/**
Jon Ashburnffd5d672015-06-29 11:25:34 -06001904 * Find the Vulkan library manifest files.
1905 *
1906 * This function scans the location or env_override directories/files
1907 * for a list of JSON manifest files. If env_override is non-NULL
1908 * and has a valid value. Then the location is ignored. Otherwise
1909 * location is used to look for manifest files. The location
1910 * is interpreted as Registry path on Windows and a directory path(s)
1911 * on Linux.
1912 *
1913 * \returns
1914 * A string list of manifest files to be opened in out_files param.
1915 * List has a pointer to string for each manifest filename.
1916 * When done using the list in out_files, pointers should be freed.
Jon Ashburnee33ae72015-06-30 14:46:22 -07001917 * Location or override string lists can be either files or directories as follows:
1918 * | location | override
1919 * --------------------------------
1920 * Win ICD | files | files
1921 * Win Layer | files | dirs
1922 * Linux ICD | dirs | files
1923 * Linux Layer| dirs | dirs
Jon Ashburnffd5d672015-06-29 11:25:34 -06001924 */
Jon Ashburne58f1a32015-08-28 13:38:21 -06001925static void loader_get_manifest_files(const struct loader_instance *inst,
1926 const char *env_override,
Jon Ashburnee33ae72015-06-30 14:46:22 -07001927 bool is_layer,
1928 const char *location,
1929 struct loader_manifest_files *out_files)
Jon Ashburnffd5d672015-06-29 11:25:34 -06001930{
1931 char *override = NULL;
1932 char *loc;
1933 char *file, *next_file, *name;
1934 size_t alloced_count = 64;
1935 char full_path[2048];
1936 DIR *sysdir = NULL;
Jon Ashburnee33ae72015-06-30 14:46:22 -07001937 bool list_is_dirs = false;
Jon Ashburnffd5d672015-06-29 11:25:34 -06001938 struct dirent *dent;
1939
1940 out_files->count = 0;
1941 out_files->filename_list = NULL;
1942
Jon Ashburnffd5d672015-06-29 11:25:34 -06001943 if (env_override != NULL && (override = getenv(env_override))) {
Johannes van Waverena6ce7b72015-10-28 11:45:00 -05001944#if !defined(_WIN32)
Jon Ashburnffd5d672015-06-29 11:25:34 -06001945 if (geteuid() != getuid()) {
Jon Ashburnee33ae72015-06-30 14:46:22 -07001946 /* Don't allow setuid apps to use the env var: */
Jon Ashburnffd5d672015-06-29 11:25:34 -06001947 override = NULL;
1948 }
1949#endif
1950 }
1951
1952 if (location == NULL) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001953 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburnee33ae72015-06-30 14:46:22 -07001954 "Can't get manifest files with NULL location, env_override=%s",
1955 env_override);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001956 return;
1957 }
1958
Johannes van Waverena6ce7b72015-10-28 11:45:00 -05001959#if defined(_WIN32)
Jon Ashburnee33ae72015-06-30 14:46:22 -07001960 list_is_dirs = (is_layer && override != NULL) ? true : false;
Johannes van Waverena6ce7b72015-10-28 11:45:00 -05001961#else
1962 list_is_dirs = (override == NULL || is_layer) ? true : false;
Jon Ashburnee33ae72015-06-30 14:46:22 -07001963#endif
Jon Ashburnffd5d672015-06-29 11:25:34 -06001964 // Make a copy of the input we are using so it is not modified
Jon Ashburnee33ae72015-06-30 14:46:22 -07001965 // Also handle getting the location(s) from registry on Windows
1966 if (override == NULL) {
Jon Ashburncdc9f0a2015-07-31 10:11:24 -06001967 loc = loader_stack_alloc(strlen(location) + 1);
Jon Ashburnee33ae72015-06-30 14:46:22 -07001968 if (loc == NULL) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001969 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Out of memory can't get manifest files");
Jon Ashburnee33ae72015-06-30 14:46:22 -07001970 return;
1971 }
1972 strcpy(loc, location);
Johannes van Waverena6ce7b72015-10-28 11:45:00 -05001973#if defined(_WIN32)
Jon Ashburn6fb9a532015-08-28 14:58:46 -07001974 loc = loader_get_registry_files(inst, loc);
Jon Ashburnc1381ed2015-07-31 09:33:21 -06001975 if (loc == NULL) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001976 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Registry lookup failed can't get manifest files");
Jon Ashburnc1381ed2015-07-31 09:33:21 -06001977 return;
1978 }
Jon Ashburnee33ae72015-06-30 14:46:22 -07001979#endif
Jon Ashburnffd5d672015-06-29 11:25:34 -06001980 }
Jon Ashburnee33ae72015-06-30 14:46:22 -07001981 else {
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -06001982 loc = loader_stack_alloc(strlen(override) + 1);
Jon Ashburnee33ae72015-06-30 14:46:22 -07001983 if (loc == NULL) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001984 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Out of memory can't get manifest files");
Jon Ashburnee33ae72015-06-30 14:46:22 -07001985 return;
1986 }
1987 strcpy(loc, override);
1988 }
Jon Ashburnffd5d672015-06-29 11:25:34 -06001989
Liam Middlebrookf2a6ec42015-07-23 18:32:20 -07001990 // Print out the paths being searched if debugging is enabled
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001991 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Searching the following paths for manifest files: %s\n", loc);
Liam Middlebrookf2a6ec42015-07-23 18:32:20 -07001992
Jon Ashburnffd5d672015-06-29 11:25:34 -06001993 file = loc;
1994 while (*file) {
1995 next_file = loader_get_next_path(file);
Jon Ashburnee33ae72015-06-30 14:46:22 -07001996 if (list_is_dirs) {
Jon Ashburnffd5d672015-06-29 11:25:34 -06001997 sysdir = opendir(file);
1998 name = NULL;
1999 if (sysdir) {
2000 dent = readdir(sysdir);
2001 if (dent == NULL)
2002 break;
2003 name = &(dent->d_name[0]);
2004 loader_get_fullpath(name, file, sizeof(full_path), full_path);
2005 name = full_path;
2006 }
2007 }
2008 else {
Johannes van Waverena6ce7b72015-10-28 11:45:00 -05002009#if defined(_WIN32)
2010 name = file;
2011#else
Jon Ashburnee33ae72015-06-30 14:46:22 -07002012 // only Linux has relative paths
Jon Ashburnffd5d672015-06-29 11:25:34 -06002013 char *dir;
2014 // make a copy of location so it isn't modified
Jason Ekstrand35fa1a12015-10-10 08:33:37 -07002015 dir = loader_stack_alloc(strlen(loc) + 1);
Jon Ashburnffd5d672015-06-29 11:25:34 -06002016 if (dir == NULL) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002017 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Out of memory can't get manifest files");
Jon Ashburnffd5d672015-06-29 11:25:34 -06002018 return;
2019 }
Jason Ekstrand35fa1a12015-10-10 08:33:37 -07002020 strcpy(dir, loc);
Jon Ashburnffd5d672015-06-29 11:25:34 -06002021
2022 loader_get_fullpath(file, dir, sizeof(full_path), full_path);
2023
2024 name = full_path;
Jon Ashburnee33ae72015-06-30 14:46:22 -07002025#endif
Jon Ashburnffd5d672015-06-29 11:25:34 -06002026 }
2027 while (name) {
2028 /* Look for files ending with ".json" suffix */
2029 uint32_t nlen = (uint32_t) strlen(name);
2030 const char *suf = name + nlen - 5;
2031 if ((nlen > 5) && !strncmp(suf, ".json", 5)) {
2032 if (out_files->count == 0) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06002033 out_files->filename_list = loader_heap_alloc(inst,
2034 alloced_count * sizeof(char *),
Chia-I Wu5eca31f2015-10-31 00:31:16 +08002035 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
Jon Ashburnffd5d672015-06-29 11:25:34 -06002036 }
2037 else if (out_files->count == alloced_count) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06002038 out_files->filename_list = loader_heap_realloc(inst,
2039 out_files->filename_list,
2040 alloced_count * sizeof(char *),
2041 alloced_count * sizeof(char *) * 2,
Chia-I Wu5eca31f2015-10-31 00:31:16 +08002042 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
Jon Ashburnffd5d672015-06-29 11:25:34 -06002043 alloced_count *= 2;
2044 }
2045 if (out_files->filename_list == NULL) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002046 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Out of memory can't alloc manifest file list");
Jon Ashburnffd5d672015-06-29 11:25:34 -06002047 return;
2048 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06002049 out_files->filename_list[out_files->count] = loader_heap_alloc(
2050 inst,
2051 strlen(name) + 1,
Chia-I Wu5eca31f2015-10-31 00:31:16 +08002052 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
Jon Ashburnffd5d672015-06-29 11:25:34 -06002053 if (out_files->filename_list[out_files->count] == NULL) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002054 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Out of memory can't get manifest files");
Jon Ashburnffd5d672015-06-29 11:25:34 -06002055 return;
2056 }
2057 strcpy(out_files->filename_list[out_files->count], name);
2058 out_files->count++;
Jon Ashburnc5662f62015-07-02 10:08:47 -06002059 } else if (!list_is_dirs) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002060 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0, "Skipping manifest file %s, file name must end in .json", name);
Jon Ashburnffd5d672015-06-29 11:25:34 -06002061 }
Jon Ashburnee33ae72015-06-30 14:46:22 -07002062 if (list_is_dirs) {
Jon Ashburnffd5d672015-06-29 11:25:34 -06002063 dent = readdir(sysdir);
2064 if (dent == NULL)
2065 break;
2066 name = &(dent->d_name[0]);
2067 loader_get_fullpath(name, file, sizeof(full_path), full_path);
2068 name = full_path;
2069 }
2070 else {
2071 break;
2072 }
2073 }
2074 if (sysdir)
2075 closedir(sysdir);
2076 file = next_file;
2077 }
2078 return;
2079}
2080
Jon Ashburn754f1992015-08-18 18:04:47 -06002081void loader_init_icd_lib_list()
2082{
2083
2084}
2085
2086void loader_destroy_icd_lib_list()
2087{
2088
2089}
Jon Ashburnffd5d672015-06-29 11:25:34 -06002090/**
2091 * Try to find the Vulkan ICD driver(s).
2092 *
2093 * This function scans the default system loader path(s) or path
2094 * specified by the \c VK_ICD_FILENAMES environment variable in
2095 * order to find loadable VK ICDs manifest files. From these
2096 * manifest files it finds the ICD libraries.
2097 *
2098 * \returns
Jon Ashburn754f1992015-08-18 18:04:47 -06002099 * a list of icds that were discovered
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06002100 */
Jon Ashburne58f1a32015-08-28 13:38:21 -06002101void loader_icd_scan(
2102 const struct loader_instance *inst,
2103 struct loader_icd_libs *icds)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08002104{
Jon Ashburnffd5d672015-06-29 11:25:34 -06002105 char *file_str;
2106 struct loader_manifest_files manifest_files;
2107
Jon Ashburne58f1a32015-08-28 13:38:21 -06002108 loader_scanned_icd_init(inst, icds);
Jon Ashburnffd5d672015-06-29 11:25:34 -06002109 // Get a list of manifest files for ICDs
Jon Ashburne58f1a32015-08-28 13:38:21 -06002110 loader_get_manifest_files(inst, "VK_ICD_FILENAMES", false,
2111 DEFAULT_VK_DRIVERS_INFO, &manifest_files);
Jon Ashburn1b111de2015-07-06 15:40:35 -06002112 if (manifest_files.count == 0)
2113 return;
Jon Ashburnd02fc2c2015-09-22 13:11:00 -06002114 loader_platform_thread_lock_mutex(&loader_json_lock);
Jon Ashburnffd5d672015-06-29 11:25:34 -06002115 for (uint32_t i = 0; i < manifest_files.count; i++) {
2116 file_str = manifest_files.filename_list[i];
2117 if (file_str == NULL)
2118 continue;
2119
Jon Ashburn1b111de2015-07-06 15:40:35 -06002120 cJSON *json;
Courtney Goeltzenleuchter05525da2015-12-03 13:48:01 -07002121 json = loader_get_json(inst, file_str);
Jon Ashburna01fb3e2015-08-27 08:30:50 -06002122 if (!json)
2123 continue;
Jon Ashburn0083b222015-11-17 17:35:40 -07002124 cJSON *item, *itemICD;
Jon Ashburn1b111de2015-07-06 15:40:35 -06002125 item = cJSON_GetObjectItem(json, "file_format_version");
Jon Ashburnd02fc2c2015-09-22 13:11:00 -06002126 if (item == NULL) {
2127 loader_platform_thread_unlock_mutex(&loader_json_lock);
Jon Ashburn1b111de2015-07-06 15:40:35 -06002128 return;
Jon Ashburnd02fc2c2015-09-22 13:11:00 -06002129 }
Jon Ashburn1b111de2015-07-06 15:40:35 -06002130 char *file_vers = cJSON_Print(item);
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002131 loader_log(inst, VK_DEBUG_REPORT_INFO_BIT_EXT, 0, "Found manifest file %s, version %s",
Jon Ashburn1b111de2015-07-06 15:40:35 -06002132 file_str, file_vers);
2133 if (strcmp(file_vers, "\"1.0.0\"") != 0)
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002134 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0, "Unexpected manifest file version (expected 1.0.0), may cause errors");
Jon Ashburn413d6582015-08-28 15:19:27 -06002135 loader_tls_heap_free(file_vers);
Jon Ashburn0083b222015-11-17 17:35:40 -07002136 itemICD = cJSON_GetObjectItem(json, "ICD");
2137 if (itemICD != NULL) {
2138 item = cJSON_GetObjectItem(itemICD, "library_path");
Jon Ashburn1b111de2015-07-06 15:40:35 -06002139 if (item != NULL) {
Jon Ashburn10442c12015-08-25 16:48:24 -06002140 char *temp= cJSON_Print(item);
2141 if (!temp || strlen(temp) == 0) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002142 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0, "Can't find \"library_path\" in ICD JSON file %s, skipping", file_str);
Jon Ashburn413d6582015-08-28 15:19:27 -06002143 loader_tls_heap_free(temp);
Jon Ashburne58f1a32015-08-28 13:38:21 -06002144 loader_heap_free(inst, file_str);
Jon Ashburn10442c12015-08-25 16:48:24 -06002145 cJSON_Delete(json);
2146 continue;
Jon Ashburnffd5d672015-06-29 11:25:34 -06002147 }
Jon Ashburn10442c12015-08-25 16:48:24 -06002148 //strip out extra quotes
2149 temp[strlen(temp) - 1] = '\0';
2150 char *library_path = loader_stack_alloc(strlen(temp) + 1);
2151 strcpy(library_path, &temp[1]);
Jon Ashburn413d6582015-08-28 15:19:27 -06002152 loader_tls_heap_free(temp);
Jon Ashburn10442c12015-08-25 16:48:24 -06002153 if (!library_path || strlen(library_path) == 0) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002154 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0, "Can't find \"library_path\" in ICD JSON file %s, skipping", file_str);
Jon Ashburne58f1a32015-08-28 13:38:21 -06002155 loader_heap_free(inst, file_str);
Jon Ashburn10442c12015-08-25 16:48:24 -06002156 cJSON_Delete(json);
2157 continue;
2158 }
Daniel Dadap2e13fca2015-09-30 11:50:51 -05002159 char fullpath[MAX_STRING_SIZE];
Jon Ashburn10442c12015-08-25 16:48:24 -06002160 // Print out the paths being searched if debugging is enabled
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002161 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Searching for ICD drivers named %s default dir %s\n", library_path, DEFAULT_VK_DRIVERS_PATH);
Daniel Dadap2e13fca2015-09-30 11:50:51 -05002162 if (loader_platform_is_path(library_path)) {
Jon Ashburn10442c12015-08-25 16:48:24 -06002163 // a relative or absolute path
Daniel Dadap2e13fca2015-09-30 11:50:51 -05002164 char *name_copy = loader_stack_alloc(strlen(file_str) + 1);
2165 char *rel_base;
Jon Ashburn10442c12015-08-25 16:48:24 -06002166 strcpy(name_copy, file_str);
2167 rel_base = loader_platform_dirname(name_copy);
Daniel Dadap2e13fca2015-09-30 11:50:51 -05002168 loader_expand_path(library_path, rel_base, sizeof(fullpath), fullpath);
2169 } else {
2170 // a filename which is assumed in a system directory
2171 loader_get_fullpath(library_path, DEFAULT_VK_DRIVERS_PATH, sizeof(fullpath), fullpath);
Jon Ashburn10442c12015-08-25 16:48:24 -06002172 }
Jon Ashburn0083b222015-11-17 17:35:40 -07002173
2174 uint32_t vers = 0;
2175 item = cJSON_GetObjectItem(itemICD, "api_version");
2176 if (item != NULL) {
2177 temp= cJSON_Print(item);
2178 vers = loader_make_version(temp);
2179 loader_tls_heap_free(temp);
2180 }
2181 loader_scanned_icd_add(inst, icds, fullpath, vers);
Jon Ashburnffd5d672015-06-29 11:25:34 -06002182 }
Jon Ashburn0083b222015-11-17 17:35:40 -07002183 else
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002184 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0, "Can't find \"library_path\" object in ICD JSON file %s, skipping", file_str);
Jon Ashburnffd5d672015-06-29 11:25:34 -06002185 }
2186 else
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002187 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0, "Can't find \"ICD\" object in ICD JSON file %s, skipping", file_str);
Jon Ashburnffd5d672015-06-29 11:25:34 -06002188
Jon Ashburne58f1a32015-08-28 13:38:21 -06002189 loader_heap_free(inst, file_str);
Jon Ashburnffd5d672015-06-29 11:25:34 -06002190 cJSON_Delete(json);
2191 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06002192 loader_heap_free(inst, manifest_files.filename_list);
Jon Ashburnd02fc2c2015-09-22 13:11:00 -06002193 loader_platform_thread_unlock_mutex(&loader_json_lock);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08002194}
2195
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002196
Jon Ashburne58f1a32015-08-28 13:38:21 -06002197void loader_layer_scan(
2198 const struct loader_instance *inst,
2199 struct loader_layer_list *instance_layers,
2200 struct loader_layer_list *device_layers)
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002201{
Jon Ashburn1b111de2015-07-06 15:40:35 -06002202 char *file_str;
Jon Ashburnd2c905c2015-12-17 17:38:24 -07002203 struct loader_manifest_files manifest_files[2]; // [0] = explicit, [1] = implicit
Jon Ashburn1b111de2015-07-06 15:40:35 -06002204 cJSON *json;
2205 uint32_t i;
Jon Ashburnd2c905c2015-12-17 17:38:24 -07002206 uint32_t implicit;
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002207
Jon Ashburn1b111de2015-07-06 15:40:35 -06002208 // Get a list of manifest files for layers
Jon Ashburnd2c905c2015-12-17 17:38:24 -07002209 loader_get_manifest_files(inst, LAYERS_PATH_ENV, true, DEFAULT_VK_ELAYERS_INFO,
2210 &manifest_files[0]);
2211 loader_get_manifest_files(inst, LAYERS_PATH_ENV, true, DEFAULT_VK_ILAYERS_INFO,
2212 &manifest_files[1]);
2213 if (manifest_files[0].count == 0 && manifest_files[1].count == 0)
Courtney Goeltzenleuchterbce445a2014-12-01 09:29:42 -07002214 return;
Jon Ashburn0dcd6192015-06-04 15:30:58 -06002215
Jon Ashburn8e4fab42015-08-03 17:19:30 -06002216#if 0 //TODO
Jon Ashburn1b111de2015-07-06 15:40:35 -06002217 /**
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -06002218 * We need a list of the layer libraries, not just a list of
2219 * the layer properties (a layer library could expose more than
2220 * one layer property). This list of scanned layers would be
2221 * used to check for global and physicaldevice layer properties.
2222 */
2223 if (!loader_init_layer_library_list(&loader.scanned_layer_libraries)) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002224 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburne58f1a32015-08-28 13:38:21 -06002225 "Alloc for layer list failed: %s line: %d", __FILE__, __LINE__);
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -06002226 return;
Jon Ashburn68a63922015-07-02 09:40:15 -06002227 }
Jon Ashburn1b111de2015-07-06 15:40:35 -06002228#endif
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002229
Jon Ashburn8e4fab42015-08-03 17:19:30 -06002230 /* cleanup any previously scanned libraries */
Jon Ashburne58f1a32015-08-28 13:38:21 -06002231 loader_delete_layer_properties(inst, instance_layers);
2232 loader_delete_layer_properties(inst, device_layers);
Jon Ashburn0bf6a182015-07-16 17:19:31 -06002233
Jon Ashburnd02fc2c2015-09-22 13:11:00 -06002234 loader_platform_thread_lock_mutex(&loader_json_lock);
Jon Ashburnd2c905c2015-12-17 17:38:24 -07002235 for (implicit = 0; implicit < 2; implicit++) {
2236 for (i = 0; i < manifest_files[implicit].count; i++) {
2237 file_str = manifest_files[implicit].filename_list[i];
2238 if (file_str == NULL)
2239 continue;
Courtney Goeltzenleuchteraa685052015-06-01 14:49:17 -06002240
Jon Ashburnd2c905c2015-12-17 17:38:24 -07002241 // parse file into JSON struct
2242 json = loader_get_json(inst, file_str);
2243 if (!json) {
2244 continue;
2245 }
2246
2247 //TODO error if device layers expose instance_extensions
2248 //TODO error if instance layers expose device extensions
2249 loader_add_layer_properties(inst,
2250 instance_layers,
2251 device_layers,
2252 json,
2253 (implicit == 1),
2254 file_str);
2255
2256 loader_heap_free(inst, file_str);
2257 cJSON_Delete(json);
Jon Ashburn1b111de2015-07-06 15:40:35 -06002258 }
Jon Ashburn1b111de2015-07-06 15:40:35 -06002259 }
Jon Ashburnd2c905c2015-12-17 17:38:24 -07002260 if (manifest_files[0].count != 0)
2261 loader_heap_free(inst, manifest_files[0].filename_list);
2262
2263 if (manifest_files[1].count != 0)
2264 loader_heap_free(inst, manifest_files[1].filename_list);
Jon Ashburnd02fc2c2015-09-22 13:11:00 -06002265 loader_platform_thread_unlock_mutex(&loader_json_lock);
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002266}
2267
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +08002268static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL loader_gpa_instance_internal(VkInstance inst, const char * pName)
Jon Ashburnfce93d92015-05-12 17:26:48 -06002269{
2270 // inst is not wrapped
2271 if (inst == VK_NULL_HANDLE) {
2272 return NULL;
2273 }
2274 VkLayerInstanceDispatchTable* disp_table = * (VkLayerInstanceDispatchTable **) inst;
2275 void *addr;
2276
Jon Ashburn4f2575f2015-05-28 16:25:02 -06002277 if (!strcmp(pName, "vkGetInstanceProcAddr"))
2278 return (void *) loader_gpa_instance_internal;
2279
Jon Ashburnfce93d92015-05-12 17:26:48 -06002280 if (disp_table == NULL)
2281 return NULL;
2282
2283 addr = loader_lookup_instance_dispatch_table(disp_table, pName);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002284 if (addr) {
Jon Ashburnfce93d92015-05-12 17:26:48 -06002285 return addr;
Jon Ashburne18431b2015-04-13 18:10:06 -06002286 }
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002287
2288 if (disp_table->GetInstanceProcAddr == NULL) {
2289 return NULL;
2290 }
2291 return disp_table->GetInstanceProcAddr(inst, pName);
Jon Ashburne18431b2015-04-13 18:10:06 -06002292}
2293
Jon Ashburn429e19f2015-11-17 15:31:02 -07002294/**
2295 * Initialize device_ext dispatch table entry as follows:
2296 * If dev == NULL find all logical devices created within this instance and
2297 * init the entry (given by idx) in the ext dispatch table.
2298 * If dev != NULL only initialize the entry in the given dev's dispatch table.
2299 * The initialization value is gotten by calling down the device chain with GDPA.
2300 * If GDPA returns NULL then don't initialize the dispatch table entry.
2301 */
2302static void loader_init_dispatch_dev_ext_entry(struct loader_instance *inst,
2303 struct loader_device *dev,
2304 uint32_t idx,
2305 const char *funcName)
2306
2307 {
2308 void *gdpa_value;
2309 if (dev != NULL) {
2310 gdpa_value = dev->loader_dispatch.core_dispatch.GetDeviceProcAddr(
2311 dev->device, funcName);
2312 if (gdpa_value != NULL)
2313 dev->loader_dispatch.ext_dispatch.DevExt[idx] = (PFN_vkDevExt) gdpa_value;
2314 } else {
2315 for (uint32_t i = 0; i < inst->total_icd_count; i++) {
2316 struct loader_icd *icd = &inst->icds[i];
2317 struct loader_device *dev = icd->logical_device_list;
2318 while (dev) {
2319 gdpa_value = dev->loader_dispatch.core_dispatch.GetDeviceProcAddr(
2320 dev->device, funcName);
2321 if (gdpa_value != NULL)
2322 dev->loader_dispatch.ext_dispatch.DevExt[idx] =
2323 (PFN_vkDevExt) gdpa_value;
2324 dev = dev->next;
2325 }
2326 }
2327 }
2328
2329}
2330
2331/**
2332 * Find all dev extension in the hash table and initialize the dispatch table
2333 * for dev for each of those extension entrypoints found in hash table.
2334
2335 */
2336static void loader_init_dispatch_dev_ext(struct loader_instance *inst,
2337 struct loader_device *dev)
2338{
2339 for (uint32_t i = 0; i < MAX_NUM_DEV_EXTS; i++) {
2340 if (inst->disp_hash[i].func_name != NULL)
2341 loader_init_dispatch_dev_ext_entry(inst, dev, i,
2342 inst->disp_hash[i].func_name);
2343 }
2344}
2345
2346static bool loader_check_icds_for_address(struct loader_instance *inst,
2347 const char *funcName)
2348{
2349 struct loader_icd *icd;
2350 icd = inst->icds;
2351 while (icd) {
2352 if (icd->this_icd_lib->GetInstanceProcAddr(icd->instance, funcName))
2353 // this icd supports funcName
2354 return true;
2355 icd = icd->next;
2356 }
2357
2358 return false;
2359}
2360
2361static void loader_free_dev_ext_table(struct loader_instance *inst)
2362{
2363 for (uint32_t i = 0; i < MAX_NUM_DEV_EXTS; i++) {
2364 loader_heap_free(inst, inst->disp_hash[i].func_name);
2365 loader_heap_free(inst, inst->disp_hash[i].list.index);
2366
2367 }
2368 memset(inst->disp_hash, 0, sizeof(inst->disp_hash));
2369}
2370
2371static bool loader_add_dev_ext_table(struct loader_instance *inst,
2372 uint32_t *ptr_idx,
2373 const char *funcName)
2374{
2375 uint32_t i;
2376 uint32_t idx = *ptr_idx;
2377 struct loader_dispatch_hash_list *list = &inst->disp_hash[idx].list;
2378
2379 if (!inst->disp_hash[idx].func_name) {
2380 // no entry here at this idx, so use it
2381 assert(list->capacity == 0);
2382 inst->disp_hash[idx].func_name = (char *) loader_heap_alloc(inst,
2383 strlen(funcName) + 1,
2384 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
2385 if (inst->disp_hash[idx].func_name == NULL) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002386 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburn429e19f2015-11-17 15:31:02 -07002387 "loader_add_dev_ext_table() can't allocate memory for func_name");
2388 return false;
2389 }
2390 strncpy(inst->disp_hash[idx].func_name, funcName, strlen(funcName) + 1);
2391 return true;
2392 }
2393
2394 // check for enough capacity
2395 if (list->capacity == 0) {
2396 list->index = loader_heap_alloc(inst, 8 * sizeof(*(list->index)),
2397 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
2398 if (list->index == NULL) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002399 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburn429e19f2015-11-17 15:31:02 -07002400 "loader_add_dev_ext_table() can't allocate list memory");
2401 return false;
2402 }
2403 list->capacity = 8 * sizeof(*(list->index));
2404 } else if (list->capacity < (list->count + 1) * sizeof(*(list->index))) {
2405 list->index = loader_heap_realloc(inst, list->index, list->capacity,
2406 list->capacity * 2,
2407 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
2408 if (list->index == NULL) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002409 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburn429e19f2015-11-17 15:31:02 -07002410 "loader_add_dev_ext_table() can't reallocate list memory");
2411 return false;
2412 }
2413 list->capacity *= 2;
2414 }
2415
2416 //find an unused index in the hash table and use it
2417 i = (idx + 1) % MAX_NUM_DEV_EXTS;
2418 do {
2419 if (!inst->disp_hash[i].func_name) {
2420 assert(inst->disp_hash[i].list.capacity == 0);
2421 inst->disp_hash[i].func_name = (char *) loader_heap_alloc(inst,
2422 strlen(funcName) + 1,
2423 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
2424 if (inst->disp_hash[i].func_name == NULL) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002425 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburn429e19f2015-11-17 15:31:02 -07002426 "loader_add_dev_ext_table() can't rallocate func_name memory");
2427 return false;
2428 }
2429 strncpy(inst->disp_hash[i].func_name, funcName, strlen(funcName) + 1);
2430 list->index[list->count] = i;
2431 list->count++;
2432 *ptr_idx = i;
2433 return true;
2434 }
2435 i = (i + 1) % MAX_NUM_DEV_EXTS;
2436 } while (i != idx);
2437
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002438 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburn429e19f2015-11-17 15:31:02 -07002439 "loader_add_dev_ext_table() couldn't insert into hash table; is it full?");
2440 return false;
2441}
2442
2443static bool loader_name_in_dev_ext_table(struct loader_instance *inst,
2444 uint32_t *idx,
2445 const char *funcName)
2446{
2447 uint32_t alt_idx;
2448 if (inst->disp_hash[*idx].func_name && !strcmp(
2449 inst->disp_hash[*idx].func_name,
2450 funcName))
2451 return true;
2452
2453 // funcName wasn't at the primary spot in the hash table
2454 // search the list of secondary locations (shallow search, not deep search)
2455 for (uint32_t i = 0; i < inst->disp_hash[*idx].list.count; i++) {
2456 alt_idx = inst->disp_hash[*idx].list.index[i];
2457 if (!strcmp(inst->disp_hash[*idx].func_name, funcName)) {
2458 *idx = alt_idx;
2459 return true;
2460 }
2461 }
2462
2463 return false;
2464}
2465
2466/**
2467 * This function returns generic trampoline code address for unknown entry points.
2468 * Presumably, these unknown entry points (as given by funcName) are device
2469 * extension entrypoints. A hash table is used to keep a list of unknown entry
2470 * points and their mapping to the device extension dispatch table
2471 * (struct loader_dev_ext_dispatch_table).
2472 * \returns
2473 * For a given entry point string (funcName), if an existing mapping is found the
2474 * trampoline address for that mapping is returned. Otherwise, this unknown entry point
2475 * has not been seen yet. Next check if a layer or ICD supports it. If so then a
2476 * new entry in the hash table is initialized and that trampoline address for
2477 * the new entry is returned. Null is returned if the hash table is full or
2478 * if no discovered layer or ICD returns a non-NULL GetProcAddr for it.
2479 */
2480void *loader_dev_ext_gpa(struct loader_instance *inst,
2481 const char *funcName)
2482{
2483 uint32_t idx;
2484 uint32_t seed = 0;
2485
2486 idx = murmurhash(funcName, strlen(funcName), seed) % MAX_NUM_DEV_EXTS;
2487
2488 if (loader_name_in_dev_ext_table(inst, &idx, funcName))
2489 // found funcName already in hash
2490 return loader_get_dev_ext_trampoline(idx);
2491
2492 // Check if funcName is supported in either ICDs or a layer library
2493 if (!loader_check_icds_for_address(inst, funcName)) {
2494 // TODO Add check in layer libraries for support of address
2495 // if support found in layers continue on
2496 return NULL;
2497 }
2498
2499 if (loader_add_dev_ext_table(inst, &idx, funcName)) {
2500 // successfully added new table entry
2501 // init any dev dispatch table entrys as needed
2502 loader_init_dispatch_dev_ext_entry(inst, NULL, idx, funcName);
2503 return loader_get_dev_ext_trampoline(idx);
2504 }
2505
2506 return NULL;
2507}
2508
Jon Ashburn0c5eea22015-09-30 12:56:42 -06002509struct loader_instance *loader_get_instance(const VkInstance instance)
2510{
2511 /* look up the loader_instance in our list by comparing dispatch tables, as
2512 * there is no guarantee the instance is still a loader_instance* after any
2513 * layers which wrap the instance object.
2514 */
2515 const VkLayerInstanceDispatchTable *disp;
2516 struct loader_instance *ptr_instance = NULL;
2517 disp = loader_get_instance_dispatch(instance);
2518 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
2519 if (inst->disp == disp) {
2520 ptr_instance = inst;
2521 break;
2522 }
2523 }
2524 return ptr_instance;
2525}
2526
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002527static loader_platform_dl_handle loader_add_layer_lib(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002528 const struct loader_instance *inst,
Jon Ashburn9a9de1f2015-05-27 13:19:22 -06002529 const char *chain_type,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002530 struct loader_layer_properties *layer_prop)
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002531{
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002532 struct loader_lib_info *new_layer_lib_list, *my_lib;
Jon Ashburne58f1a32015-08-28 13:38:21 -06002533 size_t new_alloc_size;
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -06002534 /*
2535 * TODO: We can now track this information in the
2536 * scanned_layer_libraries list.
2537 */
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002538 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) {
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002539 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, layer_prop->lib_name) == 0) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002540 /* Have already loaded this library, just increment ref count */
2541 loader.loaded_layer_lib_list[i].ref_count++;
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002542 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002543 "%s Chain: Increment layer reference count for layer library %s",
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002544 chain_type, layer_prop->lib_name);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002545 return loader.loaded_layer_lib_list[i].lib_handle;
2546 }
2547 }
2548
2549 /* Haven't seen this library so load it */
Jon Ashburne58f1a32015-08-28 13:38:21 -06002550 new_alloc_size = 0;
2551 if (loader.loaded_layer_lib_capacity == 0)
2552 new_alloc_size = 8 * sizeof(struct loader_lib_info);
2553 else if (loader.loaded_layer_lib_capacity <= loader.loaded_layer_lib_count *
2554 sizeof(struct loader_lib_info))
2555 new_alloc_size = loader.loaded_layer_lib_capacity * 2;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002556
Jon Ashburne58f1a32015-08-28 13:38:21 -06002557 if (new_alloc_size) {
2558 new_layer_lib_list = loader_heap_realloc(
2559 inst, loader.loaded_layer_lib_list,
2560 loader.loaded_layer_lib_capacity,
2561 new_alloc_size,
Chia-I Wu1f851912015-10-27 18:04:07 +08002562 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburne58f1a32015-08-28 13:38:21 -06002563 if (!new_layer_lib_list) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002564 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "loader: realloc failed in loader_add_layer_lib");
Jon Ashburne58f1a32015-08-28 13:38:21 -06002565 return NULL;
2566 }
2567 loader.loaded_layer_lib_capacity = new_alloc_size;
Courtney Goeltzenleuchter65e31cc2015-12-09 12:26:34 -07002568 loader.loaded_layer_lib_list = new_layer_lib_list;
Jon Ashburne58f1a32015-08-28 13:38:21 -06002569 } else
2570 new_layer_lib_list = loader.loaded_layer_lib_list;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002571 my_lib = &new_layer_lib_list[loader.loaded_layer_lib_count];
2572
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002573 strncpy(my_lib->lib_name, layer_prop->lib_name, sizeof(my_lib->lib_name));
2574 my_lib->lib_name[sizeof(my_lib->lib_name) - 1] = '\0';
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002575 my_lib->ref_count = 0;
2576 my_lib->lib_handle = NULL;
2577
2578 if ((my_lib->lib_handle = loader_platform_open_library(my_lib->lib_name)) == NULL) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002579 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002580 loader_platform_open_library_error(my_lib->lib_name));
2581 return NULL;
2582 } else {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002583 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002584 "Chain: %s: Loading layer library %s",
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002585 chain_type, layer_prop->lib_name);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002586 }
2587 loader.loaded_layer_lib_count++;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002588 my_lib->ref_count++;
2589
2590 return my_lib->lib_handle;
2591}
2592
2593static void loader_remove_layer_lib(
2594 struct loader_instance *inst,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002595 struct loader_layer_properties *layer_prop)
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002596{
Courtney Goeltzenleuchter46724972015-12-17 09:51:22 -07002597 uint32_t idx = loader.loaded_layer_lib_count;
Tony Barbour9687cb12015-07-14 13:34:05 -06002598 struct loader_lib_info *new_layer_lib_list, *my_lib = NULL;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002599
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002600 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) {
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002601 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, layer_prop->lib_name) == 0) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002602 /* found matching library */
2603 idx = i;
2604 my_lib = &loader.loaded_layer_lib_list[i];
2605 break;
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002606 }
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002607 }
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002608
Courtney Goeltzenleuchter46724972015-12-17 09:51:22 -07002609 if (idx == loader.loaded_layer_lib_count) {
Jon Ashburndb68e4b2015-12-17 14:30:21 -07002610 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Courtney Goeltzenleuchter46724972015-12-17 09:51:22 -07002611 "Unable to unref library %s", layer_prop->lib_name);
2612 return;
2613 }
2614
Tony Barbour9687cb12015-07-14 13:34:05 -06002615 if (my_lib) {
2616 my_lib->ref_count--;
2617 if (my_lib->ref_count > 0) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002618 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002619 "Decrement reference count for layer library %s", layer_prop->lib_name);
Tony Barbour9687cb12015-07-14 13:34:05 -06002620 return;
2621 }
Courtney Goeltzenleuchter0199e952015-02-27 15:19:33 -07002622 }
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002623 loader_platform_close_library(my_lib->lib_handle);
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002624 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002625 "Unloading layer library %s", layer_prop->lib_name);
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002626
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002627 /* Need to remove unused library from list */
Jon Ashburne58f1a32015-08-28 13:38:21 -06002628 new_layer_lib_list = loader_heap_alloc(inst,
2629 loader.loaded_layer_lib_capacity,
Chia-I Wu1f851912015-10-27 18:04:07 +08002630 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002631 if (!new_layer_lib_list) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002632 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "loader: heap alloc failed loader_remove_layer_library");
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002633 return;
2634 }
2635
2636 if (idx > 0) {
2637 /* Copy records before idx */
2638 memcpy(new_layer_lib_list, &loader.loaded_layer_lib_list[0],
2639 sizeof(struct loader_lib_info) * idx);
2640 }
2641 if (idx < (loader.loaded_layer_lib_count - 1)) {
2642 /* Copy records after idx */
2643 memcpy(&new_layer_lib_list[idx], &loader.loaded_layer_lib_list[idx+1],
2644 sizeof(struct loader_lib_info) * (loader.loaded_layer_lib_count - idx - 1));
2645 }
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002646
Jon Ashburne58f1a32015-08-28 13:38:21 -06002647 loader_heap_free(inst, loader.loaded_layer_lib_list);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002648 loader.loaded_layer_lib_count--;
2649 loader.loaded_layer_lib_list = new_layer_lib_list;
Jon Ashburnead95c52014-11-18 09:06:04 -07002650}
2651
Jon Ashburn1b111de2015-07-06 15:40:35 -06002652
2653/**
2654 * Go through the search_list and find any layers which match type. If layer
2655 * type match is found in then add it to ext_list.
2656 */
Jon Ashburn535bd002015-07-02 16:10:32 -06002657static void loader_add_layer_implicit(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002658 const struct loader_instance *inst,
Jon Ashburn535bd002015-07-02 16:10:32 -06002659 const enum layer_type type,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002660 struct loader_layer_list *list,
Jon Ashburn182b8302015-08-11 14:49:54 -06002661 const struct loader_layer_list *search_list)
Jon Ashburn535bd002015-07-02 16:10:32 -06002662{
Jon Ashburnd2c905c2015-12-17 17:38:24 -07002663 bool enable;
2664 char *env_value;
Jon Ashburn535bd002015-07-02 16:10:32 -06002665 uint32_t i;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002666 for (i = 0; i < search_list->count; i++) {
2667 const struct loader_layer_properties *prop = &search_list->list[i];
Jon Ashburn535bd002015-07-02 16:10:32 -06002668 if (prop->type & type) {
Jon Ashburnd2c905c2015-12-17 17:38:24 -07002669 /* Found an implicit layer, see if it should be enabled */
2670 enable = false;
2671
2672 // if no enable_environment variable is specified, this implicit layer
2673 // should always be enabled. Otherwise check if the variable is set
2674 if (prop->enable_env_var.name[0] == 0) {
2675 enable = true;
2676 } else {
2677 env_value = getenv(prop->enable_env_var.name);
2678 if (env_value && !strcmp(prop->enable_env_var.value, env_value))
2679 enable = true;
2680 }
2681
2682 // disable_environment has priority, i.e. if both enable and disable
2683 // environment variables are set, the layer is disabled. Implicit layers
2684 // are required to have a disable_environment variables
2685 env_value = getenv(prop->disable_env_var.name);
2686 if (env_value)
2687 enable = false;
2688
2689 if (enable)
2690 loader_add_to_layer_list(inst, list, 1, prop);
Jon Ashburn535bd002015-07-02 16:10:32 -06002691 }
2692 }
2693
2694}
2695
2696/**
2697 * Get the layer name(s) from the env_name environment variable. If layer
Jon Ashburnf2ddb732015-07-07 10:27:45 -06002698 * is found in search_list then add it to layer_list. But only add it to
2699 * layer_list if type matches.
Jon Ashburn535bd002015-07-02 16:10:32 -06002700 */
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002701static void loader_add_layer_env(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002702 const struct loader_instance *inst,
Jon Ashburnf2ddb732015-07-07 10:27:45 -06002703 const enum layer_type type,
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002704 const char *env_name,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002705 struct loader_layer_list *layer_list,
2706 const struct loader_layer_list *search_list)
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002707{
Ian Elliott225188f2015-02-17 10:33:47 -07002708 char *layerEnv;
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002709 char *next, *name;
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002710
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002711 layerEnv = getenv(env_name);
Ian Elliott225188f2015-02-17 10:33:47 -07002712 if (layerEnv == NULL) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002713 return;
Ian Elliott225188f2015-02-17 10:33:47 -07002714 }
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -06002715 name = loader_stack_alloc(strlen(layerEnv) + 1);
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002716 if (name == NULL) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002717 return;
Ian Elliott225188f2015-02-17 10:33:47 -07002718 }
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002719 strcpy(name, layerEnv);
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002720
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002721 while (name && *name ) {
2722 next = loader_get_next_path(name);
Jon Ashburne58f1a32015-08-28 13:38:21 -06002723 loader_find_layer_name_add_list(inst, name, type, search_list, layer_list);
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002724 name = next;
Courtney Goeltzenleuchter0199e952015-02-27 15:19:33 -07002725 }
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002726
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002727 return;
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002728}
2729
Courtney Goeltzenleuchter3d8dc1f2015-06-08 15:09:22 -06002730void loader_deactivate_instance_layers(struct loader_instance *instance)
Jon Ashburn183dfd02014-10-22 18:13:16 -06002731{
Jon Ashburn60378412015-07-02 12:59:25 -06002732 if (!instance->activated_layer_list.count) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002733 return;
2734 }
Jon Ashburn183dfd02014-10-22 18:13:16 -06002735
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002736 /* Create instance chain of enabled layers */
Courtney Goeltzenleuchter3d8dc1f2015-06-08 15:09:22 -06002737 for (uint32_t i = 0; i < instance->activated_layer_list.count; i++) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002738 struct loader_layer_properties *layer_prop = &instance->activated_layer_list.list[i];
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002739
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002740 loader_remove_layer_lib(instance, layer_prop);
Jon Ashburn183dfd02014-10-22 18:13:16 -06002741 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06002742 loader_destroy_layer_list(instance, &instance->activated_layer_list);
Jon Ashburn183dfd02014-10-22 18:13:16 -06002743}
2744
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002745VkResult loader_enable_instance_layers(
Jon Ashburn182b8302015-08-11 14:49:54 -06002746 struct loader_instance *inst,
2747 const VkInstanceCreateInfo *pCreateInfo,
2748 const struct loader_layer_list *instance_layers)
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002749{
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002750 VkResult err;
2751
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -06002752 assert(inst && "Cannot have null instance");
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002753
Jon Ashburne58f1a32015-08-28 13:38:21 -06002754 if (!loader_init_layer_list(inst, &inst->activated_layer_list)) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002755 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Failed to alloc Instance activated layer list");
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002756 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburn60378412015-07-02 12:59:25 -06002757 }
2758
Jon Ashburn535bd002015-07-02 16:10:32 -06002759 /* Add any implicit layers first */
2760 loader_add_layer_implicit(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002761 inst,
Jon Ashburn535bd002015-07-02 16:10:32 -06002762 VK_LAYER_TYPE_INSTANCE_IMPLICIT,
2763 &inst->activated_layer_list,
Jon Ashburn182b8302015-08-11 14:49:54 -06002764 instance_layers);
Jon Ashburn535bd002015-07-02 16:10:32 -06002765
Jon Ashburn1b111de2015-07-06 15:40:35 -06002766 /* Add any layers specified via environment variable next */
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002767 loader_add_layer_env(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002768 inst,
Jon Ashburnf2ddb732015-07-07 10:27:45 -06002769 VK_LAYER_TYPE_INSTANCE_EXPLICIT,
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002770 "VK_INSTANCE_LAYERS",
2771 &inst->activated_layer_list,
Jon Ashburn182b8302015-08-11 14:49:54 -06002772 instance_layers);
Jon Ashburn60378412015-07-02 12:59:25 -06002773
2774 /* Add layers specified by the application */
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002775 err = loader_add_layer_names_to_list(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002776 inst,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002777 &inst->activated_layer_list,
Chia-I Wu763a7492015-10-26 20:48:51 +08002778 pCreateInfo->enabledLayerNameCount,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002779 pCreateInfo->ppEnabledLayerNames,
Jon Ashburn182b8302015-08-11 14:49:54 -06002780 instance_layers);
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002781
2782 return err;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002783}
2784
Jon Ashburnfce93d92015-05-12 17:26:48 -06002785uint32_t loader_activate_instance_layers(struct loader_instance *inst)
2786{
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002787 uint32_t layer_idx;
Jon Ashburnd5df54d2015-05-28 19:16:58 -06002788 VkBaseLayerObject *wrappedInstance;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002789
David Pinedo0fab78b2015-06-24 15:29:18 -06002790 if (inst == NULL) {
Jon Ashburnfce93d92015-05-12 17:26:48 -06002791 return 0;
David Pinedo0fab78b2015-06-24 15:29:18 -06002792 }
Jon Ashburnfce93d92015-05-12 17:26:48 -06002793
2794 // NOTE inst is unwrapped at this point in time
Tony Barbourde4124d2015-07-03 10:33:54 -06002795 void* baseObj = (void*) inst;
2796 void* nextObj = (void*) inst;
Jon Ashburnfce93d92015-05-12 17:26:48 -06002797 VkBaseLayerObject *nextInstObj;
2798 PFN_vkGetInstanceProcAddr nextGPA = loader_gpa_instance_internal;
2799
Jon Ashburn60378412015-07-02 12:59:25 -06002800 if (!inst->activated_layer_list.count) {
Courtney Goeltzenleuchter33243142015-08-07 09:53:18 -06002801 loader_init_instance_core_dispatch_table(inst->disp, nextGPA, (VkInstance) nextObj, (VkInstance) baseObj);
Jon Ashburnfce93d92015-05-12 17:26:48 -06002802 return 0;
2803 }
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002804
Courtney Goeltzenleuchter0248b992015-07-06 09:04:55 -06002805 wrappedInstance = loader_stack_alloc(sizeof(VkBaseLayerObject)
Jon Ashburn60378412015-07-02 12:59:25 -06002806 * inst->activated_layer_list.count);
Jon Ashburnd5df54d2015-05-28 19:16:58 -06002807 if (!wrappedInstance) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002808 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Failed to alloc Instance objects for layer");
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002809 return 0;
2810 }
2811
2812 /* Create instance chain of enabled layers */
Jon Ashburn60378412015-07-02 12:59:25 -06002813 layer_idx = inst->activated_layer_list.count - 1;
Courtney Goeltzenleuchterf4b430e2015-06-07 17:28:17 -06002814 for (int32_t i = inst->activated_layer_list.count - 1; i >= 0; i--) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002815 struct loader_layer_properties *layer_prop = &inst->activated_layer_list.list[i];
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002816 loader_platform_dl_handle lib_handle;
2817
Jon Ashburn60378412015-07-02 12:59:25 -06002818 /*
Courtney Goeltzenleuchterc27292a2015-06-01 14:12:42 -06002819 * Note: An extension's Get*ProcAddr should not return a function pointer for
2820 * any extension entry points until the extension has been enabled.
2821 * To do this requires a different behavior from Get*ProcAddr functions implemented
2822 * in layers.
2823 * The very first call to a layer will be it's Get*ProcAddr function requesting
Tobin Ehlis84492ee2015-10-06 09:09:24 -06002824 * the layer's vkGet*ProcAddr. The layer should initialize its internal dispatch table
Courtney Goeltzenleuchterc27292a2015-06-01 14:12:42 -06002825 * with the wrapped object given (either Instance or Device) and return the layer's
2826 * Get*ProcAddr function. The layer should also use this opportunity to record the
2827 * baseObject so that it can find the correct local dispatch table on future calls.
2828 * Subsequent calls to Get*ProcAddr, CreateInstance, CreateDevice
2829 * will not use a wrapped object and must look up their local dispatch table from
2830 * the given baseObject.
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002831 */
Jon Ashburnd5df54d2015-05-28 19:16:58 -06002832 nextInstObj = (wrappedInstance + layer_idx);
Tony Barbourde4124d2015-07-03 10:33:54 -06002833 nextInstObj->pGPA = (PFN_vkGPA) nextGPA;
Jon Ashburnfce93d92015-05-12 17:26:48 -06002834 nextInstObj->baseObject = baseObj;
2835 nextInstObj->nextObject = nextObj;
Tony Barbourde4124d2015-07-03 10:33:54 -06002836 nextObj = (void*) nextInstObj;
Jon Ashburnfce93d92015-05-12 17:26:48 -06002837
Jon Ashburne58f1a32015-08-28 13:38:21 -06002838 lib_handle = loader_add_layer_lib(inst, "instance", layer_prop);
Jon Ashburn25a158f2015-11-25 17:55:49 -07002839 if (!lib_handle)
2840 continue; // TODO what should we do in this case
Jon Ashburn2db08042015-09-09 11:29:24 -06002841 if ((nextGPA = layer_prop->functions.get_instance_proc_addr) == NULL) {
2842 if (layer_prop->functions.str_gipa == NULL || strlen(layer_prop->functions.str_gipa) == 0) {
2843 nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetInstanceProcAddr");
2844 layer_prop->functions.get_instance_proc_addr = nextGPA;
2845 } else
2846 nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gipa);
2847 if (!nextGPA) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002848 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Failed to find vkGetInstanceProcAddr in layer %s", layer_prop->lib_name);
Courtney Goeltzenleuchteraa685052015-06-01 14:49:17 -06002849
Jon Ashburn2db08042015-09-09 11:29:24 -06002850 /* TODO: Should we return nextObj, nextGPA to previous? or decrement layer_list count*/
2851 continue;
2852 }
Jon Ashburnfce93d92015-05-12 17:26:48 -06002853 }
2854
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002855 loader_log(inst, VK_DEBUG_REPORT_INFO_BIT_EXT, 0,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002856 "Insert instance layer %s (%s)",
2857 layer_prop->info.layerName,
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002858 layer_prop->lib_name);
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002859
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002860 layer_idx--;
Jon Ashburnfce93d92015-05-12 17:26:48 -06002861 }
2862
Jon Ashburn4f2575f2015-05-28 16:25:02 -06002863 loader_init_instance_core_dispatch_table(inst->disp, nextGPA, (VkInstance) nextObj, (VkInstance) baseObj);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002864
Jon Ashburn60378412015-07-02 12:59:25 -06002865 return inst->activated_layer_list.count;
Jon Ashburnfce93d92015-05-12 17:26:48 -06002866}
2867
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002868void loader_activate_instance_layer_extensions(struct loader_instance *inst)
2869{
2870
2871 loader_init_instance_extension_dispatch_table(inst->disp,
2872 inst->disp->GetInstanceProcAddr,
Jon Ashburnd5df54d2015-05-28 19:16:58 -06002873 (VkInstance) inst);
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002874}
2875
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002876static VkResult loader_enable_device_layers(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002877 const struct loader_instance *inst,
Jon Ashburn182b8302015-08-11 14:49:54 -06002878 struct loader_icd *icd,
2879 struct loader_device *dev,
2880 const VkDeviceCreateInfo *pCreateInfo,
2881 const struct loader_layer_list *device_layers)
2882
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002883{
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002884 VkResult err;
2885
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -06002886 assert(dev && "Cannot have null device");
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002887
Jon Ashburn60378412015-07-02 12:59:25 -06002888 if (dev->activated_layer_list.list == NULL || dev->activated_layer_list.capacity == 0) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06002889 loader_init_layer_list(inst, &dev->activated_layer_list);
Jon Ashburn60378412015-07-02 12:59:25 -06002890 }
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002891
Jon Ashburn60378412015-07-02 12:59:25 -06002892 if (dev->activated_layer_list.list == NULL) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002893 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Failed to alloc device activated layer list");
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002894 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburn60378412015-07-02 12:59:25 -06002895 }
2896
Jon Ashburn535bd002015-07-02 16:10:32 -06002897 /* Add any implicit layers first */
2898 loader_add_layer_implicit(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002899 inst,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002900 VK_LAYER_TYPE_DEVICE_IMPLICIT,
2901 &dev->activated_layer_list,
Jon Ashburn182b8302015-08-11 14:49:54 -06002902 device_layers);
Jon Ashburn535bd002015-07-02 16:10:32 -06002903
2904 /* Add any layers specified via environment variable next */
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002905 loader_add_layer_env(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002906 inst,
Jon Ashburnf2ddb732015-07-07 10:27:45 -06002907 VK_LAYER_TYPE_DEVICE_EXPLICIT,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002908 "VK_DEVICE_LAYERS",
2909 &dev->activated_layer_list,
Jon Ashburn182b8302015-08-11 14:49:54 -06002910 device_layers);
Jon Ashburn60378412015-07-02 12:59:25 -06002911
2912 /* Add layers specified by the application */
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002913 err = loader_add_layer_names_to_list(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002914 inst,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002915 &dev->activated_layer_list,
Chia-I Wu763a7492015-10-26 20:48:51 +08002916 pCreateInfo->enabledLayerNameCount,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002917 pCreateInfo->ppEnabledLayerNames,
Jon Ashburn182b8302015-08-11 14:49:54 -06002918 device_layers);
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002919
2920 return err;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002921}
2922
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002923/*
Jon Ashburnc1d1eb72015-08-14 11:57:54 -06002924 * This function terminates the device chain for CreateDevice.
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002925 * CreateDevice is a special case and so the loader call's
2926 * the ICD's CreateDevice before creating the chain. Since
2927 * we can't call CreateDevice twice we must terminate the
2928 * device chain with something else.
2929 */
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +08002930static VKAPI_ATTR VkResult VKAPI_CALL scratch_vkCreateDevice(
Jon Ashburn251258f2015-11-01 14:04:06 -07002931 VkPhysicalDevice physicalDevice,
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002932 const VkDeviceCreateInfo *pCreateInfo,
Chia-I Wu1f851912015-10-27 18:04:07 +08002933 const VkAllocationCallbacks* pAllocator,
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002934 VkDevice *pDevice)
2935{
2936 return VK_SUCCESS;
2937}
2938
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +08002939static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL loader_GetDeviceChainProcAddr(VkDevice device, const char * name)
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002940{
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002941 if (!strcmp(name, "vkGetDeviceProcAddr"))
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -06002942 return (PFN_vkVoidFunction) loader_GetDeviceChainProcAddr;
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002943 if (!strcmp(name, "vkCreateDevice"))
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -06002944 return (PFN_vkVoidFunction) scratch_vkCreateDevice;
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002945
Courtney Goeltzenleuchtere76db422015-06-29 16:09:23 -06002946 struct loader_device *found_dev;
2947 struct loader_icd *icd = loader_get_icd_and_device(device, &found_dev);
2948 return icd->GetDeviceProcAddr(device, name);
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002949}
2950
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06002951static uint32_t loader_activate_device_layers(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002952 const struct loader_instance *inst,
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002953 struct loader_device *dev,
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -06002954 VkDevice device)
Jon Ashburn183dfd02014-10-22 18:13:16 -06002955{
David Pinedo0fab78b2015-06-24 15:29:18 -06002956 if (!dev) {
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06002957 return 0;
David Pinedo0fab78b2015-06-24 15:29:18 -06002958 }
Jon Ashburn612539f2015-06-10 10:13:10 -06002959
Jon Ashburn183dfd02014-10-22 18:13:16 -06002960 /* activate any layer libraries */
Tony Barbourde4124d2015-07-03 10:33:54 -06002961 void* nextObj = (void*) device;
2962 void* baseObj = nextObj;
Jon Ashburn612539f2015-06-10 10:13:10 -06002963 VkBaseLayerObject *nextGpuObj;
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002964 PFN_vkGetDeviceProcAddr nextGPA = loader_GetDeviceChainProcAddr;
Jon Ashburn612539f2015-06-10 10:13:10 -06002965 VkBaseLayerObject *wrappedGpus;
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002966
Courtney Goeltzenleuchter33243142015-08-07 09:53:18 -06002967 if (!dev->activated_layer_list.count) {
2968 loader_init_device_dispatch_table(&dev->loader_dispatch, nextGPA,
2969 (VkDevice) nextObj, (VkDevice) baseObj);
Jon Ashburn612539f2015-06-10 10:13:10 -06002970 return 0;
Courtney Goeltzenleuchter33243142015-08-07 09:53:18 -06002971 }
Jon Ashburn612539f2015-06-10 10:13:10 -06002972
Jon Ashburne58f1a32015-08-28 13:38:21 -06002973 wrappedGpus = loader_heap_alloc(inst,
2974 sizeof (VkBaseLayerObject) * dev->activated_layer_list.count,
Chia-I Wu1f851912015-10-27 18:04:07 +08002975 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn612539f2015-06-10 10:13:10 -06002976 if (!wrappedGpus) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002977 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Failed to alloc Gpu objects for layer");
Jon Ashburn612539f2015-06-10 10:13:10 -06002978 return 0;
2979 }
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002980
Jon Ashburn612539f2015-06-10 10:13:10 -06002981 for (int32_t i = dev->activated_layer_list.count - 1; i >= 0; i--) {
2982
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002983 struct loader_layer_properties *layer_prop = &dev->activated_layer_list.list[i];
Jon Ashburn612539f2015-06-10 10:13:10 -06002984 loader_platform_dl_handle lib_handle;
2985
Jon Ashburn612539f2015-06-10 10:13:10 -06002986 nextGpuObj = (wrappedGpus + i);
Tony Barbourde4124d2015-07-03 10:33:54 -06002987 nextGpuObj->pGPA = (PFN_vkGPA)nextGPA;
Jon Ashburn612539f2015-06-10 10:13:10 -06002988 nextGpuObj->baseObject = baseObj;
2989 nextGpuObj->nextObject = nextObj;
Tony Barbourde4124d2015-07-03 10:33:54 -06002990 nextObj = (void*) nextGpuObj;
Jon Ashburn612539f2015-06-10 10:13:10 -06002991
Jon Ashburne58f1a32015-08-28 13:38:21 -06002992 lib_handle = loader_add_layer_lib(inst, "device", layer_prop);
Jon Ashburn2db08042015-09-09 11:29:24 -06002993 if ((nextGPA = layer_prop->functions.get_device_proc_addr) == NULL) {
2994 if (layer_prop->functions.str_gdpa == NULL || strlen(layer_prop->functions.str_gdpa) == 0) {
2995 nextGPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetDeviceProcAddr");
2996 layer_prop->functions.get_device_proc_addr = nextGPA;
2997 } else
2998 nextGPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gdpa);
2999 if (!nextGPA) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07003000 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Failed to find vkGetDeviceProcAddr in layer %s", layer_prop->lib_name);
Jon Ashburn2db08042015-09-09 11:29:24 -06003001 continue;
3002 }
Jon Ashburn612539f2015-06-10 10:13:10 -06003003 }
3004
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07003005 loader_log(inst, VK_DEBUG_REPORT_INFO_BIT_EXT, 0,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003006 "Insert device layer library %s (%s)",
3007 layer_prop->info.layerName,
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06003008 layer_prop->lib_name);
Jon Ashburn612539f2015-06-10 10:13:10 -06003009
3010 }
3011
3012 loader_init_device_dispatch_table(&dev->loader_dispatch, nextGPA,
Tony Barbourde4124d2015-07-03 10:33:54 -06003013 (VkDevice) nextObj, (VkDevice) baseObj);
Jon Ashburne58f1a32015-08-28 13:38:21 -06003014 loader_heap_free(inst, wrappedGpus);
Jon Ashburn612539f2015-06-10 10:13:10 -06003015
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06003016 return dev->activated_layer_list.count;
Jon Ashburn183dfd02014-10-22 18:13:16 -06003017}
Jon Ashburnd43f9b62014-10-14 19:15:22 -06003018
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06003019VkResult loader_validate_layers(
3020 const uint32_t layer_count,
3021 const char * const *ppEnabledLayerNames,
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06003022 const struct loader_layer_list *list)
Courtney Goeltzenleuchter5d9f29b2015-07-06 17:45:08 -06003023{
3024 struct loader_layer_properties *prop;
3025
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06003026 for (uint32_t i = 0; i < layer_count; i++) {
Jon Ashburn8e4fab42015-08-03 17:19:30 -06003027 prop = loader_get_layer_property(ppEnabledLayerNames[i],
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06003028 list);
Courtney Goeltzenleuchter5d9f29b2015-07-06 17:45:08 -06003029 if (!prop) {
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -06003030 return VK_ERROR_LAYER_NOT_PRESENT;
Courtney Goeltzenleuchter5d9f29b2015-07-06 17:45:08 -06003031 }
3032 }
3033
3034 return VK_SUCCESS;
3035}
3036
3037VkResult loader_validate_instance_extensions(
Jon Ashburnc1d1eb72015-08-14 11:57:54 -06003038 const struct loader_extension_list *icd_exts,
Jon Ashburn182b8302015-08-11 14:49:54 -06003039 const struct loader_layer_list *instance_layer,
3040 const VkInstanceCreateInfo *pCreateInfo)
Courtney Goeltzenleuchter5d9f29b2015-07-06 17:45:08 -06003041{
Jon Ashburnc4748dc2015-08-04 11:14:18 -06003042 VkExtensionProperties *extension_prop;
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06003043 struct loader_layer_properties *layer_prop;
3044
Chia-I Wu763a7492015-10-26 20:48:51 +08003045 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) {
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06003046 extension_prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
Jon Ashburnc1d1eb72015-08-14 11:57:54 -06003047 icd_exts);
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06003048
3049 if (extension_prop) {
3050 continue;
3051 }
3052
3053 extension_prop = NULL;
3054
3055 /* Not in global list, search layer extension lists */
Chia-I Wu763a7492015-10-26 20:48:51 +08003056 for (uint32_t j = 0; j < pCreateInfo->enabledLayerNameCount; j++) {
Jon Ashburn8e4fab42015-08-03 17:19:30 -06003057 layer_prop = loader_get_layer_property(pCreateInfo->ppEnabledLayerNames[i],
Jon Ashburn182b8302015-08-11 14:49:54 -06003058 instance_layer);
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06003059 if (!layer_prop) {
Courtney Goeltzenleuchter91371ff2015-07-06 20:46:50 -06003060 /* Should NOT get here, loader_validate_layers
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06003061 * should have already filtered this case out.
3062 */
3063 continue;
3064 }
3065
3066 extension_prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
3067 &layer_prop->instance_extension_list);
3068 if (extension_prop) {
3069 /* Found the extension in one of the layers enabled by the app. */
3070 break;
3071 }
3072 }
3073
3074 if (!extension_prop) {
3075 /* Didn't find extension name in any of the global layers, error out */
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -06003076 return VK_ERROR_EXTENSION_NOT_PRESENT;
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06003077 }
3078 }
3079 return VK_SUCCESS;
3080}
3081
3082VkResult loader_validate_device_extensions(
Jon Ashburn251258f2015-11-01 14:04:06 -07003083 struct loader_physical_device *phys_dev,
Jon Ashburn182b8302015-08-11 14:49:54 -06003084 const struct loader_layer_list *device_layer,
3085 const VkDeviceCreateInfo *pCreateInfo)
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06003086{
Jon Ashburnc4748dc2015-08-04 11:14:18 -06003087 VkExtensionProperties *extension_prop;
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06003088 struct loader_layer_properties *layer_prop;
3089
Chia-I Wu763a7492015-10-26 20:48:51 +08003090 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) {
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06003091 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i];
3092 extension_prop = get_extension_property(extension_name,
Jon Ashburn251258f2015-11-01 14:04:06 -07003093 &phys_dev->device_extension_cache);
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06003094
3095 if (extension_prop) {
3096 continue;
3097 }
3098
3099 /* Not in global list, search layer extension lists */
Chia-I Wu763a7492015-10-26 20:48:51 +08003100 for (uint32_t j = 0; j < pCreateInfo->enabledLayerNameCount; j++) {
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06003101 const char *layer_name = pCreateInfo->ppEnabledLayerNames[j];
Jon Ashburn8e4fab42015-08-03 17:19:30 -06003102 layer_prop = loader_get_layer_property(layer_name,
Jon Ashburn182b8302015-08-11 14:49:54 -06003103 device_layer);
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06003104
3105 if (!layer_prop) {
3106 /* Should NOT get here, loader_validate_instance_layers
3107 * should have already filtered this case out.
3108 */
3109 continue;
3110 }
3111
Jon Ashburn738136f2015-12-10 18:17:34 -07003112 extension_prop = get_dev_extension_property(extension_name,
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06003113 &layer_prop->device_extension_list);
3114 if (extension_prop) {
3115 /* Found the extension in one of the layers enabled by the app. */
3116 break;
3117 }
3118 }
3119
3120 if (!extension_prop) {
3121 /* Didn't find extension name in any of the device layers, error out */
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -06003122 return VK_ERROR_EXTENSION_NOT_PRESENT;
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06003123 }
3124 }
Courtney Goeltzenleuchter5d9f29b2015-07-06 17:45:08 -06003125 return VK_SUCCESS;
3126}
3127
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +08003128VKAPI_ATTR VkResult VKAPI_CALL loader_CreateInstance(
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06003129 const VkInstanceCreateInfo* pCreateInfo,
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07003130 const VkAllocationCallbacks* pAllocator,
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06003131 VkInstance* pInstance)
Jon Ashburn349508d2015-01-26 14:51:40 -07003132{
Jon Ashburna179dcf2015-05-21 17:42:17 -06003133 struct loader_instance *ptr_instance = *(struct loader_instance **) pInstance;
Jon Ashburn3336df82015-01-29 15:45:51 -07003134 struct loader_icd *icd;
Jon Ashburnc4748dc2015-08-04 11:14:18 -06003135 VkExtensionProperties *prop;
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06003136 char **filtered_extension_names = NULL;
3137 VkInstanceCreateInfo icd_create_info;
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06003138 VkResult res = VK_SUCCESS;
Jon Ashburn2869bc72015-11-19 09:29:51 -07003139 bool success = false;
Jon Ashburn349508d2015-01-26 14:51:40 -07003140
Tony Barbour809d5d32015-12-04 13:24:39 -07003141 memcpy(&icd_create_info, pCreateInfo, sizeof(icd_create_info));
3142
Chia-I Wu763a7492015-10-26 20:48:51 +08003143 icd_create_info.enabledLayerNameCount = 0;
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06003144 icd_create_info.ppEnabledLayerNames = NULL;
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06003145
3146 /*
3147 * NOTE: Need to filter the extensions to only those
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06003148 * supported by the ICD.
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06003149 * No ICD will advertise support for layers. An ICD
3150 * library could support a layer, but it would be
3151 * independent of the actual ICD, just in the same library.
3152 */
Chia-I Wu763a7492015-10-26 20:48:51 +08003153 filtered_extension_names = loader_stack_alloc(pCreateInfo->enabledExtensionNameCount * sizeof(char *));
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06003154 if (!filtered_extension_names) {
3155 return VK_ERROR_OUT_OF_HOST_MEMORY;
3156 }
3157 icd_create_info.ppEnabledExtensionNames = (const char * const *) filtered_extension_names;
3158
Jon Ashburn754f1992015-08-18 18:04:47 -06003159 for (uint32_t i = 0; i < ptr_instance->icd_libs.count; i++) {
3160 icd = loader_icd_add(ptr_instance, &ptr_instance->icd_libs.list[i]);
Jon Ashburn3336df82015-01-29 15:45:51 -07003161 if (icd) {
Chia-I Wu763a7492015-10-26 20:48:51 +08003162 icd_create_info.enabledExtensionNameCount = 0;
Courtney Goeltzenleuchterf843d2d2015-12-21 16:41:47 -07003163 struct loader_extension_list icd_exts;
3164
3165 loader_log(ptr_instance, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Build ICD instance extension list");
3166 // traverse scanned icd list adding non-duplicate extensions to the list
3167 loader_init_generic_list(ptr_instance, (struct loader_generic_list *) &icd_exts,
3168 sizeof(VkExtensionProperties));
3169 loader_add_instance_extensions(ptr_instance,
3170 icd->this_icd_lib->EnumerateInstanceExtensionProperties,
3171 icd->this_icd_lib->lib_name,
3172 &icd_exts);
3173
Chia-I Wu763a7492015-10-26 20:48:51 +08003174 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) {
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06003175 prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
Courtney Goeltzenleuchterf843d2d2015-12-21 16:41:47 -07003176 &icd_exts);
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06003177 if (prop) {
Chia-I Wu763a7492015-10-26 20:48:51 +08003178 filtered_extension_names[icd_create_info.enabledExtensionNameCount] = (char *) pCreateInfo->ppEnabledExtensionNames[i];
3179 icd_create_info.enabledExtensionNameCount++;
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06003180 }
3181 }
3182
Courtney Goeltzenleuchterf843d2d2015-12-21 16:41:47 -07003183 loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *) &icd_exts);
3184
Jon Ashburn754f1992015-08-18 18:04:47 -06003185 res = ptr_instance->icd_libs.list[i].CreateInstance(&icd_create_info,
Chia-I Wu69f40122015-10-26 21:10:41 +08003186 pAllocator,
Jon Ashburn0dd356d2015-05-14 12:43:38 -06003187 &(icd->instance));
Jon Ashburn2869bc72015-11-19 09:29:51 -07003188 if (res == VK_SUCCESS)
3189 success = loader_icd_init_entrys(
Jon Ashburnce7e3d92015-07-16 10:17:29 -06003190 icd,
3191 icd->instance,
Jon Ashburn754f1992015-08-18 18:04:47 -06003192 ptr_instance->icd_libs.list[i].GetInstanceProcAddr);
Jon Ashburnce7e3d92015-07-16 10:17:29 -06003193
3194 if (res != VK_SUCCESS || !success)
Jon Ashburn3336df82015-01-29 15:45:51 -07003195 {
3196 ptr_instance->icds = ptr_instance->icds->next;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06003197 loader_icd_destroy(ptr_instance, icd);
Jon Ashburn0dd356d2015-05-14 12:43:38 -06003198 icd->instance = VK_NULL_HANDLE;
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07003199 loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburnce7e3d92015-07-16 10:17:29 -06003200 "ICD ignored: failed to CreateInstance and find entrypoints with ICD");
Jon Ashburn3336df82015-01-29 15:45:51 -07003201 }
3202 }
Jon Ashburn3336df82015-01-29 15:45:51 -07003203 }
Jon Ashburn349508d2015-01-26 14:51:40 -07003204
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06003205 /*
3206 * If no ICDs were added to instance list and res is unchanged
3207 * from it's initial value, the loader was unable to find
3208 * a suitable ICD.
3209 */
Ian Elliott617fdec2015-02-05 15:19:15 -07003210 if (ptr_instance->icds == NULL) {
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06003211 if (res == VK_SUCCESS) {
3212 return VK_ERROR_INCOMPATIBLE_DRIVER;
3213 } else {
3214 return res;
3215 }
Ian Elliott617fdec2015-02-05 15:19:15 -07003216 }
Jon Ashburn3336df82015-01-29 15:45:51 -07003217
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06003218 return VK_SUCCESS;
Jon Ashburn349508d2015-01-26 14:51:40 -07003219}
3220
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +08003221VKAPI_ATTR void VKAPI_CALL loader_DestroyInstance(
Chia-I Wu69f40122015-10-26 21:10:41 +08003222 VkInstance instance,
Chia-I Wu1f851912015-10-27 18:04:07 +08003223 const VkAllocationCallbacks* pAllocator)
Jon Ashburn349508d2015-01-26 14:51:40 -07003224{
Courtney Goeltzenleuchter8afefb52015-06-08 15:04:02 -06003225 struct loader_instance *ptr_instance = loader_instance(instance);
Jon Ashburn0dd356d2015-05-14 12:43:38 -06003226 struct loader_icd *icds = ptr_instance->icds;
Jon Ashburn16a16d62015-06-16 14:43:19 -06003227 struct loader_icd *next_icd;
Jon Ashburn349508d2015-01-26 14:51:40 -07003228
3229 // Remove this instance from the list of instances:
3230 struct loader_instance *prev = NULL;
3231 struct loader_instance *next = loader.instances;
3232 while (next != NULL) {
3233 if (next == ptr_instance) {
3234 // Remove this instance from the list:
3235 if (prev)
3236 prev->next = next->next;
Jon Ashburn2cabd252015-02-03 09:26:59 -07003237 else
3238 loader.instances = next->next;
Jon Ashburn349508d2015-01-26 14:51:40 -07003239 break;
3240 }
3241 prev = next;
3242 next = next->next;
3243 }
Jon Ashburn349508d2015-01-26 14:51:40 -07003244
Jon Ashburn0dd356d2015-05-14 12:43:38 -06003245 while (icds) {
3246 if (icds->instance) {
Chia-I Wu69f40122015-10-26 21:10:41 +08003247 icds->DestroyInstance(icds->instance, pAllocator);
Tony Barbour22a30862015-04-22 09:02:32 -06003248 }
Jon Ashburn16a16d62015-06-16 14:43:19 -06003249 next_icd = icds->next;
Jon Ashburn0dd356d2015-05-14 12:43:38 -06003250 icds->instance = VK_NULL_HANDLE;
Jon Ashburn16a16d62015-06-16 14:43:19 -06003251 loader_icd_destroy(ptr_instance, icds);
3252
3253 icds = next_icd;
Jon Ashburn3336df82015-01-29 15:45:51 -07003254 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06003255 loader_delete_layer_properties(ptr_instance, &ptr_instance->device_layer_list);
3256 loader_delete_layer_properties(ptr_instance, &ptr_instance->instance_layer_list);
3257 loader_scanned_icd_clear(ptr_instance, &ptr_instance->icd_libs);
Jon Ashburn8f6be302015-12-10 08:51:10 -07003258 loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *)
3259 &ptr_instance->ext_list);
Jon Ashburn251258f2015-11-01 14:04:06 -07003260 for (uint32_t i = 0; i < ptr_instance->total_gpu_count; i++)
Jon Ashburn8f6be302015-12-10 08:51:10 -07003261 loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *)
3262 &ptr_instance->phys_devs[i].device_extension_cache);
Jon Ashburn251258f2015-11-01 14:04:06 -07003263 loader_heap_free(ptr_instance, ptr_instance->phys_devs);
Jon Ashburn429e19f2015-11-17 15:31:02 -07003264 loader_free_dev_ext_table(ptr_instance);
Jon Ashburn349508d2015-01-26 14:51:40 -07003265}
3266
Jon Ashburn251258f2015-11-01 14:04:06 -07003267VkResult loader_init_physical_device_info(struct loader_instance *ptr_instance)
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003268{
3269 struct loader_icd *icd;
Jon Ashburn251258f2015-11-01 14:04:06 -07003270 uint32_t i, j, idx, count = 0;
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -06003271 VkResult res;
Jon Ashburn251258f2015-11-01 14:04:06 -07003272 struct loader_phys_dev_per_icd *phys_devs;
3273
3274 ptr_instance->total_gpu_count = 0;
3275 phys_devs = (struct loader_phys_dev_per_icd *) loader_stack_alloc(
3276 sizeof(struct loader_phys_dev_per_icd) *
3277 ptr_instance->total_icd_count);
3278 if (!phys_devs)
3279 return VK_ERROR_OUT_OF_HOST_MEMORY;
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003280
3281 icd = ptr_instance->icds;
Jon Ashburn251258f2015-11-01 14:04:06 -07003282 for (i = 0; i < ptr_instance->total_icd_count; i++) {
3283 assert(icd);
3284 res = icd->EnumeratePhysicalDevices(icd->instance, &phys_devs[i].count, NULL);
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003285 if (res != VK_SUCCESS)
3286 return res;
Jon Ashburn251258f2015-11-01 14:04:06 -07003287 count += phys_devs[i].count;
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003288 icd = icd->next;
3289 }
3290
Jon Ashburn251258f2015-11-01 14:04:06 -07003291 ptr_instance->phys_devs = (struct loader_physical_device *) loader_heap_alloc(
3292 ptr_instance,
3293 count * sizeof(struct loader_physical_device),
3294 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
3295 if (!ptr_instance->phys_devs)
3296 return VK_ERROR_OUT_OF_HOST_MEMORY;
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003297
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003298 icd = ptr_instance->icds;
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003299
Jon Ashburn251258f2015-11-01 14:04:06 -07003300 struct loader_physical_device *inst_phys_devs = ptr_instance->phys_devs;
3301 idx = 0;
3302 for (i = 0; i < ptr_instance->total_icd_count; i++) {
3303 assert(icd);
3304
3305 phys_devs[i].phys_devs = (VkPhysicalDevice *) loader_stack_alloc(
3306 phys_devs[i].count * sizeof(VkPhysicalDevice));
3307 if (!phys_devs[i].phys_devs) {
Jon Ashburna8ca5c42015-11-02 17:59:02 -07003308 loader_heap_free(ptr_instance, ptr_instance->phys_devs);
3309 ptr_instance->phys_devs = NULL;
Jon Ashburnd5df54d2015-05-28 19:16:58 -06003310 return VK_ERROR_OUT_OF_HOST_MEMORY;
3311 }
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003312 res = icd->EnumeratePhysicalDevices(
3313 icd->instance,
Jon Ashburn251258f2015-11-01 14:04:06 -07003314 &(phys_devs[i].count),
3315 phys_devs[i].phys_devs);
3316 if ((res == VK_SUCCESS)) {
3317 ptr_instance->total_gpu_count += phys_devs[i].count;
3318 for (j = 0; j < phys_devs[i].count; j++) {
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003319
Jon Ashburn251258f2015-11-01 14:04:06 -07003320 // initialize the loader's physicalDevice object
3321 loader_set_dispatch((void *) &inst_phys_devs[idx], ptr_instance->disp);
3322 inst_phys_devs[idx].this_instance = ptr_instance;
3323 inst_phys_devs[idx].this_icd = icd;
3324 inst_phys_devs[idx].phys_dev = phys_devs[i].phys_devs[j];
Jon Ashburndb5a5bc2015-11-02 17:40:01 -07003325 memset(&inst_phys_devs[idx].device_extension_cache, 0, sizeof(struct loader_extension_list));
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003326
Jon Ashburn251258f2015-11-01 14:04:06 -07003327 idx++;
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003328 }
Jon Ashburna8ca5c42015-11-02 17:59:02 -07003329 } else {
3330 loader_heap_free(ptr_instance, ptr_instance->phys_devs);
3331 ptr_instance->phys_devs = NULL;
Jon Ashburn251258f2015-11-01 14:04:06 -07003332 return res;
Jon Ashburna8ca5c42015-11-02 17:59:02 -07003333 }
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003334
3335 icd = icd->next;
3336 }
3337
3338 return VK_SUCCESS;
3339}
3340
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +08003341VKAPI_ATTR VkResult VKAPI_CALL loader_EnumeratePhysicalDevices(
Courtney Goeltzenleuchter9f530cb2015-04-20 12:48:54 -06003342 VkInstance instance,
3343 uint32_t* pPhysicalDeviceCount,
3344 VkPhysicalDevice* pPhysicalDevices)
Jon Ashburn349508d2015-01-26 14:51:40 -07003345{
Jon Ashburn251258f2015-11-01 14:04:06 -07003346 uint32_t i;
Jon Ashburnb048a9b2015-01-28 19:57:09 -07003347 struct loader_instance *ptr_instance = (struct loader_instance *) instance;
Jon Ashburn251258f2015-11-01 14:04:06 -07003348 VkResult res = VK_SUCCESS;
Jon Ashburnb048a9b2015-01-28 19:57:09 -07003349
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003350 if (ptr_instance->total_gpu_count == 0) {
Jon Ashburn251258f2015-11-01 14:04:06 -07003351 res = loader_init_physical_device_info(ptr_instance);
Jon Ashburnb048a9b2015-01-28 19:57:09 -07003352 }
3353
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003354 *pPhysicalDeviceCount = ptr_instance->total_gpu_count;
3355 if (!pPhysicalDevices) {
Jon Ashburn251258f2015-11-01 14:04:06 -07003356 return res;
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003357 }
Jon Ashburnb048a9b2015-01-28 19:57:09 -07003358
Jon Ashburn251258f2015-11-01 14:04:06 -07003359 for (i = 0; i < ptr_instance->total_gpu_count; i++) {
3360 pPhysicalDevices[i] = (VkPhysicalDevice) &ptr_instance->phys_devs[i];
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003361 }
3362
Jon Ashburn251258f2015-11-01 14:04:06 -07003363 return res;
Jon Ashburn349508d2015-01-26 14:51:40 -07003364}
3365
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +08003366VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceProperties(
Jon Ashburn251258f2015-11-01 14:04:06 -07003367 VkPhysicalDevice physicalDevice,
Tony Barbour426b9052015-06-24 16:06:58 -06003368 VkPhysicalDeviceProperties* pProperties)
Jon Ashburn0dd356d2015-05-14 12:43:38 -06003369{
Jon Ashburn251258f2015-11-01 14:04:06 -07003370 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3371 struct loader_icd *icd = phys_dev->this_icd;
Jon Ashburn0dd356d2015-05-14 12:43:38 -06003372
Tony Barbour426b9052015-06-24 16:06:58 -06003373 if (icd->GetPhysicalDeviceProperties)
Jon Ashburn251258f2015-11-01 14:04:06 -07003374 icd->GetPhysicalDeviceProperties(phys_dev->phys_dev, pProperties);
Tony Barbour426b9052015-06-24 16:06:58 -06003375}
3376
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +08003377VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceQueueFamilyProperties (
Jon Ashburn251258f2015-11-01 14:04:06 -07003378 VkPhysicalDevice physicalDevice,
Chia-I Wu763a7492015-10-26 20:48:51 +08003379 uint32_t* pQueueFamilyPropertyCount,
Cody Northropef72e2a2015-08-03 17:04:53 -06003380 VkQueueFamilyProperties* pProperties)
Tony Barbour426b9052015-06-24 16:06:58 -06003381{
Jon Ashburn251258f2015-11-01 14:04:06 -07003382 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3383 struct loader_icd *icd = phys_dev->this_icd;
Tony Barbour426b9052015-06-24 16:06:58 -06003384
Cody Northropef72e2a2015-08-03 17:04:53 -06003385 if (icd->GetPhysicalDeviceQueueFamilyProperties)
Jon Ashburn251258f2015-11-01 14:04:06 -07003386 icd->GetPhysicalDeviceQueueFamilyProperties(phys_dev->phys_dev, pQueueFamilyPropertyCount, pProperties);
Tony Barbour426b9052015-06-24 16:06:58 -06003387}
3388
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +08003389VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceMemoryProperties (
Jon Ashburn251258f2015-11-01 14:04:06 -07003390 VkPhysicalDevice physicalDevice,
Tony Barbour426b9052015-06-24 16:06:58 -06003391 VkPhysicalDeviceMemoryProperties* pProperties)
3392{
Jon Ashburn251258f2015-11-01 14:04:06 -07003393 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3394 struct loader_icd *icd = phys_dev->this_icd;
Tony Barbour426b9052015-06-24 16:06:58 -06003395
3396 if (icd->GetPhysicalDeviceMemoryProperties)
Jon Ashburn251258f2015-11-01 14:04:06 -07003397 icd->GetPhysicalDeviceMemoryProperties(phys_dev->phys_dev, pProperties);
Jon Ashburn0dd356d2015-05-14 12:43:38 -06003398}
3399
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +08003400VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceFeatures(
Chris Forbesd7576302015-06-21 22:55:02 +12003401 VkPhysicalDevice physicalDevice,
3402 VkPhysicalDeviceFeatures* pFeatures)
3403{
Jon Ashburn251258f2015-11-01 14:04:06 -07003404 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3405 struct loader_icd *icd = phys_dev->this_icd;
Chris Forbesd7576302015-06-21 22:55:02 +12003406
3407 if (icd->GetPhysicalDeviceFeatures)
Jon Ashburn251258f2015-11-01 14:04:06 -07003408 icd->GetPhysicalDeviceFeatures(phys_dev->phys_dev, pFeatures);
Chris Forbesd7576302015-06-21 22:55:02 +12003409}
3410
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +08003411VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceFormatProperties(
Chris Forbesd7576302015-06-21 22:55:02 +12003412 VkPhysicalDevice physicalDevice,
3413 VkFormat format,
3414 VkFormatProperties* pFormatInfo)
3415{
Jon Ashburn251258f2015-11-01 14:04:06 -07003416 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3417 struct loader_icd *icd = phys_dev->this_icd;
Chris Forbesd7576302015-06-21 22:55:02 +12003418
Courtney Goeltzenleuchter4da96aa2015-07-12 12:52:09 -06003419 if (icd->GetPhysicalDeviceFormatProperties)
Jon Ashburn251258f2015-11-01 14:04:06 -07003420 icd->GetPhysicalDeviceFormatProperties(phys_dev->phys_dev, format, pFormatInfo);
Chris Forbesd7576302015-06-21 22:55:02 +12003421}
3422
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +08003423VKAPI_ATTR VkResult VKAPI_CALL loader_GetPhysicalDeviceImageFormatProperties(
Jon Ashburn4e189562015-07-23 18:49:07 -06003424 VkPhysicalDevice physicalDevice,
3425 VkFormat format,
3426 VkImageType type,
3427 VkImageTiling tiling,
3428 VkImageUsageFlags usage,
Courtney Goeltzenleuchter83c95f82015-09-10 13:44:12 -06003429 VkImageCreateFlags flags,
Jon Ashburn4e189562015-07-23 18:49:07 -06003430 VkImageFormatProperties* pImageFormatProperties)
3431{
Jon Ashburn251258f2015-11-01 14:04:06 -07003432 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3433 struct loader_icd *icd = phys_dev->this_icd;
Jon Ashburn4e189562015-07-23 18:49:07 -06003434
Chia-I Wu5202c542015-10-31 00:31:16 +08003435 if (!icd->GetPhysicalDeviceImageFormatProperties)
3436 return VK_ERROR_INITIALIZATION_FAILED;
3437
3438 return icd->GetPhysicalDeviceImageFormatProperties(phys_dev->phys_dev, format,
3439 type, tiling, usage, flags, pImageFormatProperties);
Jon Ashburn4e189562015-07-23 18:49:07 -06003440}
3441
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +08003442VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceSparseImageFormatProperties(
Mark Lobodzinski83d4e6a2015-07-03 15:58:09 -06003443 VkPhysicalDevice physicalDevice,
3444 VkFormat format,
3445 VkImageType type,
Chia-I Wu3138d6a2015-10-31 00:31:16 +08003446 VkSampleCountFlagBits samples,
Mark Lobodzinski83d4e6a2015-07-03 15:58:09 -06003447 VkImageUsageFlags usage,
3448 VkImageTiling tiling,
3449 uint32_t* pNumProperties,
3450 VkSparseImageFormatProperties* pProperties)
3451{
Jon Ashburn251258f2015-11-01 14:04:06 -07003452 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3453 struct loader_icd *icd = phys_dev->this_icd;
Mark Lobodzinski83d4e6a2015-07-03 15:58:09 -06003454
3455 if (icd->GetPhysicalDeviceSparseImageFormatProperties)
Jon Ashburn251258f2015-11-01 14:04:06 -07003456 icd->GetPhysicalDeviceSparseImageFormatProperties(phys_dev->phys_dev, format, type, samples, usage, tiling, pNumProperties, pProperties);
Mark Lobodzinski83d4e6a2015-07-03 15:58:09 -06003457}
3458
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +08003459VKAPI_ATTR VkResult VKAPI_CALL loader_CreateDevice(
Jon Ashburn251258f2015-11-01 14:04:06 -07003460 VkPhysicalDevice physicalDevice,
Jon Ashburn2666e2f2015-05-15 15:09:35 -06003461 const VkDeviceCreateInfo* pCreateInfo,
Jon Ashburnba1f24e2015-12-11 09:41:34 -07003462 const VkAllocationCallbacks* pAllocator,
Jon Ashburn2666e2f2015-05-15 15:09:35 -06003463 VkDevice* pDevice)
3464{
Jon Ashburnba1f24e2015-12-11 09:41:34 -07003465 struct loader_physical_device *phys_dev;
3466 struct loader_icd *icd;
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06003467 struct loader_device *dev;
Jon Ashburn429e19f2015-11-17 15:31:02 -07003468 struct loader_instance *inst;
Courtney Goeltzenleuchter91371ff2015-07-06 20:46:50 -06003469 VkDeviceCreateInfo device_create_info;
3470 char **filtered_extension_names = NULL;
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06003471 VkResult res;
Jon Ashburn2666e2f2015-05-15 15:09:35 -06003472
Chia-I Wu045654f2015-11-06 06:42:02 +08003473 assert(pCreateInfo->queueCreateInfoCount >= 1);
Mark Lobodzinski5ea338c2015-09-17 15:17:34 -06003474
Jon Ashburnba1f24e2015-12-11 09:41:34 -07003475 //TODO this only works for one physical device per instance
3476 // once CreateDevice layer bootstrapping is done via DeviceCreateInfo
3477 // hopefully don't need this anymore in trampoline code
3478 phys_dev = loader_get_physical_device(physicalDevice);
3479 icd = phys_dev->this_icd;
Jon Ashburn6853e7e2015-10-26 16:54:51 -06003480 if (!icd)
3481 return VK_ERROR_INITIALIZATION_FAILED;
3482
Jon Ashburn251258f2015-11-01 14:04:06 -07003483 inst = phys_dev->this_instance;
Jon Ashburn6853e7e2015-10-26 16:54:51 -06003484
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06003485 if (!icd->CreateDevice) {
3486 return VK_ERROR_INITIALIZATION_FAILED;
Jon Ashburn2666e2f2015-05-15 15:09:35 -06003487 }
3488
Jon Ashburn182b8302015-08-11 14:49:54 -06003489 /* validate any app enabled layers are available */
Chia-I Wu763a7492015-10-26 20:48:51 +08003490 if (pCreateInfo->enabledLayerNameCount > 0) {
3491 res = loader_validate_layers(pCreateInfo->enabledLayerNameCount,
Jon Ashburn182b8302015-08-11 14:49:54 -06003492 pCreateInfo->ppEnabledLayerNames,
Jon Ashburne58f1a32015-08-28 13:38:21 -06003493 &inst->device_layer_list);
Jon Ashburn182b8302015-08-11 14:49:54 -06003494 if (res != VK_SUCCESS) {
3495 return res;
3496 }
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06003497 }
3498
Jon Ashburndb5a5bc2015-11-02 17:40:01 -07003499 /* Get the physical device extensions if they haven't been retrieved yet */
3500 if (phys_dev->device_extension_cache.capacity == 0) {
Jon Ashburn8f6be302015-12-10 08:51:10 -07003501 if (!loader_init_generic_list(inst, (struct loader_generic_list *)
3502 &phys_dev->device_extension_cache,
3503 sizeof(VkExtensionProperties))) {
Jon Ashburndb5a5bc2015-11-02 17:40:01 -07003504 return VK_ERROR_OUT_OF_HOST_MEMORY;
3505 }
Courtney Goeltzenleuchter03c80a62015-12-02 14:00:19 -07003506 res = loader_add_device_extensions(
Jon Ashburndb5a5bc2015-11-02 17:40:01 -07003507 inst, physicalDevice,
3508 phys_dev->this_icd->this_icd_lib->lib_name,
3509 &phys_dev->device_extension_cache);
3510 if (res != VK_SUCCESS) {
3511 return res;
3512 }
3513 }
3514 /* make sure requested extensions to be enabled are supported */
Jon Ashburn251258f2015-11-01 14:04:06 -07003515 res = loader_validate_device_extensions(phys_dev, &inst->device_layer_list, pCreateInfo);
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06003516 if (res != VK_SUCCESS) {
3517 return res;
3518 }
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003519
Courtney Goeltzenleuchter91371ff2015-07-06 20:46:50 -06003520 /*
3521 * NOTE: Need to filter the extensions to only those
3522 * supported by the ICD.
3523 * No ICD will advertise support for layers. An ICD
3524 * library could support a layer, but it would be
3525 * independent of the actual ICD, just in the same library.
3526 */
Chia-I Wu763a7492015-10-26 20:48:51 +08003527 filtered_extension_names = loader_stack_alloc(pCreateInfo->enabledExtensionNameCount * sizeof(char *));
Courtney Goeltzenleuchter91371ff2015-07-06 20:46:50 -06003528 if (!filtered_extension_names) {
3529 return VK_ERROR_OUT_OF_HOST_MEMORY;
3530 }
3531
3532 /* Copy user's data */
3533 memcpy(&device_create_info, pCreateInfo, sizeof(VkDeviceCreateInfo));
3534
3535 /* ICD's do not use layers */
Chia-I Wu763a7492015-10-26 20:48:51 +08003536 device_create_info.enabledLayerNameCount = 0;
Courtney Goeltzenleuchter91371ff2015-07-06 20:46:50 -06003537 device_create_info.ppEnabledLayerNames = NULL;
3538
Chia-I Wu763a7492015-10-26 20:48:51 +08003539 device_create_info.enabledExtensionNameCount = 0;
Courtney Goeltzenleuchter91371ff2015-07-06 20:46:50 -06003540 device_create_info.ppEnabledExtensionNames = (const char * const *) filtered_extension_names;
3541
Chia-I Wu763a7492015-10-26 20:48:51 +08003542 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) {
Courtney Goeltzenleuchter91371ff2015-07-06 20:46:50 -06003543 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i];
Jon Ashburnc4748dc2015-08-04 11:14:18 -06003544 VkExtensionProperties *prop = get_extension_property(extension_name,
Jon Ashburn251258f2015-11-01 14:04:06 -07003545 &phys_dev->device_extension_cache);
Courtney Goeltzenleuchter91371ff2015-07-06 20:46:50 -06003546 if (prop) {
Chia-I Wu763a7492015-10-26 20:48:51 +08003547 filtered_extension_names[device_create_info.enabledExtensionNameCount] = (char *) extension_name;
3548 device_create_info.enabledExtensionNameCount++;
Courtney Goeltzenleuchter91371ff2015-07-06 20:46:50 -06003549 }
3550 }
3551
Jon Ashburn251258f2015-11-01 14:04:06 -07003552 // since physicalDevice object maybe wrapped by a layer need to get unwrapped version
Jon Ashburn0c5eea22015-09-30 12:56:42 -06003553 // we haven't yet called down the chain for the layer to unwrap the object
Jon Ashburn59d7b682015-12-24 10:50:08 -07003554 res = icd->CreateDevice(phys_dev->phys_dev, &device_create_info, pAllocator, pDevice);
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06003555 if (res != VK_SUCCESS) {
3556 return res;
3557 }
3558
Jon Ashburne58f1a32015-08-28 13:38:21 -06003559 dev = loader_add_logical_device(inst, *pDevice, &icd->logical_device_list);
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06003560 if (dev == NULL) {
3561 return VK_ERROR_OUT_OF_HOST_MEMORY;
3562 }
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06003563
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06003564 loader_init_dispatch(*pDevice, &dev->loader_dispatch);
3565
Jon Ashburn182b8302015-08-11 14:49:54 -06003566 /* activate any layers on device chain which terminates with device*/
Jon Ashburne58f1a32015-08-28 13:38:21 -06003567 res = loader_enable_device_layers(inst, icd, dev, pCreateInfo, &inst->device_layer_list);
Jon Ashburn182b8302015-08-11 14:49:54 -06003568 if (res != VK_SUCCESS) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06003569 loader_destroy_logical_device(inst, dev);
Jon Ashburn182b8302015-08-11 14:49:54 -06003570 return res;
3571 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06003572 loader_activate_device_layers(inst, dev, *pDevice);
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06003573
Jon Ashburn429e19f2015-11-17 15:31:02 -07003574 /* finally can call down the chain */
3575 res = dev->loader_dispatch.core_dispatch.CreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
3576
Jon Ashburnbbad5a62015-12-11 10:45:00 -07003577 /* initialize any device extension dispatch entry's from the instance list*/
3578 loader_init_dispatch_dev_ext(inst, dev);
3579
Jon Ashburn2818eb72015-11-30 17:21:25 -07003580 /* initialize WSI device extensions as part of core dispatch since loader has
3581 * dedicated trampoline code for these*/
3582 loader_init_device_extension_dispatch_table(&dev->loader_dispatch,
3583 dev->loader_dispatch.core_dispatch.GetDeviceProcAddr,
3584 *pDevice);
Jon Ashburn429e19f2015-11-17 15:31:02 -07003585 dev->loader_dispatch.core_dispatch.CreateDevice = icd->CreateDevice;
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06003586
Jon Ashburn2666e2f2015-05-15 15:09:35 -06003587 return res;
3588}
3589
Jon Ashburn8aa75cb2015-09-28 16:15:00 -06003590/**
3591 * Get an instance level or global level entry point address.
3592 * @param instance
3593 * @param pName
3594 * @return
Jon Ashburn99456002015-11-06 11:02:40 -07003595 * If instance == NULL returns a global level functions only
3596 * If instance is valid returns a trampoline entry point for all dispatchable Vulkan
3597 * functions both core and extensions.
Jon Ashburn8aa75cb2015-09-28 16:15:00 -06003598 */
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +08003599LOADER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char * pName)
Jon Ashburn53c16772015-05-06 10:15:07 -06003600{
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06003601
Jon Ashburncedc15f2015-05-21 18:13:33 -06003602 void *addr;
Jon Ashburn53c16772015-05-06 10:15:07 -06003603
Jon Ashburn99456002015-11-06 11:02:40 -07003604 addr = globalGetProcAddr(pName);
Jon Ashburn8aa75cb2015-09-28 16:15:00 -06003605 if (instance == VK_NULL_HANDLE) {
Jon Ashburn99456002015-11-06 11:02:40 -07003606 // get entrypoint addresses that are global (no dispatchable object)
Jon Ashburn8aa75cb2015-09-28 16:15:00 -06003607
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06003608 return addr;
Jon Ashburn99456002015-11-06 11:02:40 -07003609 } else {
3610 // if a global entrypoint return NULL
3611 if (addr)
3612 return NULL;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06003613 }
3614
Jon Ashburn0c5eea22015-09-30 12:56:42 -06003615 struct loader_instance *ptr_instance = loader_get_instance(instance);
Jon Ashburn99456002015-11-06 11:02:40 -07003616 if (ptr_instance == NULL)
Jon Ashburncedc15f2015-05-21 18:13:33 -06003617 return NULL;
Jon Ashburn99456002015-11-06 11:02:40 -07003618 // Return trampoline code for non-global entrypoints including any extensions.
3619 // Device extensions are returned if a layer or ICD supports the extension.
3620 // Instance extensions are returned if the extension is enabled and the loader
3621 // or someone else supports the extension
3622 return trampolineGetProcAddr(ptr_instance, pName);
Jon Ashburncedc15f2015-05-21 18:13:33 -06003623
Jon Ashburn53c16772015-05-06 10:15:07 -06003624}
3625
Jon Ashburn8aa75cb2015-09-28 16:15:00 -06003626/**
3627 * Get a device level or global level entry point address.
3628 * @param device
3629 * @param pName
3630 * @return
Jon Ashburn8aa75cb2015-09-28 16:15:00 -06003631 * If device is valid, returns a device relative entry point for device level
3632 * entry points both core and extensions.
Jon Ashburn99456002015-11-06 11:02:40 -07003633 * Device relative means call down the device chain.
Jon Ashburn8aa75cb2015-09-28 16:15:00 -06003634 */
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +08003635LOADER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char * pName)
Courtney Goeltzenleuchter9a4f38c2015-06-22 17:45:21 -06003636{
Jon Ashburn8aa75cb2015-09-28 16:15:00 -06003637 void *addr;
Courtney Goeltzenleuchter9a4f38c2015-06-22 17:45:21 -06003638
Jon Ashburne18431b2015-04-13 18:10:06 -06003639 /* for entrypoints that loader must handle (ie non-dispatchable or create object)
3640 make sure the loader entrypoint is returned */
Jon Ashburn8aa75cb2015-09-28 16:15:00 -06003641 addr = loader_non_passthrough_gdpa(pName);
Ian Elliottfdf00b62015-04-15 12:53:19 -06003642 if (addr) {
Jon Ashburne18431b2015-04-13 18:10:06 -06003643 return addr;
Ian Elliottfdf00b62015-04-15 12:53:19 -06003644 }
Jon Ashburne18431b2015-04-13 18:10:06 -06003645
Jon Ashburn99456002015-11-06 11:02:40 -07003646 /* Although CreateDevice is on device chain it's dispatchable object isn't
3647 * a VkDevice or child of VkDevice so return NULL.
3648 */
3649 if (!strcmp(pName, "CreateDevice"))
3650 return NULL;
3651
Jon Ashburne18431b2015-04-13 18:10:06 -06003652 /* return the dispatch table entrypoint for the fastest case */
Jon Ashburn1245cec2015-05-18 13:20:15 -06003653 const VkLayerDispatchTable *disp_table = * (VkLayerDispatchTable **) device;
Jon Ashburnd43f9b62014-10-14 19:15:22 -06003654 if (disp_table == NULL)
3655 return NULL;
3656
Jon Ashburnfce93d92015-05-12 17:26:48 -06003657 addr = loader_lookup_device_dispatch_table(disp_table, pName);
Chia-I Wu38e5a2c2015-01-04 11:12:47 +08003658 if (addr)
3659 return addr;
Jon Ashburn99456002015-11-06 11:02:40 -07003660
3661 if (disp_table->GetDeviceProcAddr == NULL)
3662 return NULL;
3663 return disp_table->GetDeviceProcAddr(device, pName);
Jon Ashburnd43f9b62014-10-14 19:15:22 -06003664}
3665
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +08003666LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003667 const char* pLayerName,
Chia-I Wu763a7492015-10-26 20:48:51 +08003668 uint32_t* pPropertyCount,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003669 VkExtensionProperties* pProperties)
3670{
Jon Ashburnb8605fe2015-09-18 12:53:16 -06003671 struct loader_extension_list *global_ext_list=NULL;
Jon Ashburn182b8302015-08-11 14:49:54 -06003672 struct loader_layer_list instance_layers;
Jon Ashburnc1d1eb72015-08-14 11:57:54 -06003673 struct loader_extension_list icd_extensions;
Jon Ashburn754f1992015-08-18 18:04:47 -06003674 struct loader_icd_libs icd_libs;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003675 uint32_t copy_size;
3676
Jon Ashburn413d6582015-08-28 15:19:27 -06003677 tls_instance = NULL;
Jon Ashburnc1d1eb72015-08-14 11:57:54 -06003678 memset(&icd_extensions, 0, sizeof(icd_extensions));
Mike Stroyana73e50c2015-10-01 15:23:48 -06003679 memset(&instance_layers, 0, sizeof(instance_layers));
Jon Ashburn754f1992015-08-18 18:04:47 -06003680 loader_platform_thread_once(&once_init, loader_initialize);
Jon Ashburnc1d1eb72015-08-14 11:57:54 -06003681
Jon Ashburn182b8302015-08-11 14:49:54 -06003682 /* get layer libraries if needed */
3683 if (pLayerName && strlen(pLayerName) != 0) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06003684 loader_layer_scan(NULL, &instance_layers, NULL);
Jon Ashburn182b8302015-08-11 14:49:54 -06003685 for (uint32_t i = 0; i < instance_layers.count; i++) {
3686 struct loader_layer_properties *props = &instance_layers.list[i];
3687 if (strcmp(props->info.layerName, pLayerName) == 0) {
3688 global_ext_list = &props->instance_extension_list;
3689 }
3690 }
3691 }
3692 else {
Jon Ashburn754f1992015-08-18 18:04:47 -06003693 /* Scan/discover all ICD libraries */
3694 memset(&icd_libs, 0 , sizeof(struct loader_icd_libs));
Jon Ashburne58f1a32015-08-28 13:38:21 -06003695 loader_icd_scan(NULL, &icd_libs);
Jon Ashburnc1d1eb72015-08-14 11:57:54 -06003696 /* get extensions from all ICD's, merge so no duplicates */
Jon Ashburne58f1a32015-08-28 13:38:21 -06003697 loader_get_icd_loader_instance_extensions(NULL, &icd_libs, &icd_extensions);
3698 loader_scanned_icd_clear(NULL, &icd_libs);
Jon Ashburnc1d1eb72015-08-14 11:57:54 -06003699 global_ext_list = &icd_extensions;
Jon Ashburn182b8302015-08-11 14:49:54 -06003700 }
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003701
Jon Ashburn182b8302015-08-11 14:49:54 -06003702 if (global_ext_list == NULL) {
Mike Stroyana73e50c2015-10-01 15:23:48 -06003703 loader_destroy_layer_list(NULL, &instance_layers);
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -06003704 return VK_ERROR_LAYER_NOT_PRESENT;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003705 }
3706
3707 if (pProperties == NULL) {
Chia-I Wu763a7492015-10-26 20:48:51 +08003708 *pPropertyCount = global_ext_list->count;
Mike Stroyana73e50c2015-10-01 15:23:48 -06003709 loader_destroy_layer_list(NULL, &instance_layers);
Jon Ashburn8f6be302015-12-10 08:51:10 -07003710 loader_destroy_generic_list(NULL, (struct loader_generic_list *)
3711 &icd_extensions);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003712 return VK_SUCCESS;
3713 }
3714
Chia-I Wu763a7492015-10-26 20:48:51 +08003715 copy_size = *pPropertyCount < global_ext_list->count ? *pPropertyCount : global_ext_list->count;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003716 for (uint32_t i = 0; i < copy_size; i++) {
3717 memcpy(&pProperties[i],
Jon Ashburn182b8302015-08-11 14:49:54 -06003718 &global_ext_list->list[i],
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003719 sizeof(VkExtensionProperties));
3720 }
Chia-I Wu763a7492015-10-26 20:48:51 +08003721 *pPropertyCount = copy_size;
Jon Ashburn8f6be302015-12-10 08:51:10 -07003722 loader_destroy_generic_list(NULL, (struct loader_generic_list *)
3723 &icd_extensions);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003724
Jon Ashburn182b8302015-08-11 14:49:54 -06003725 if (copy_size < global_ext_list->count) {
Mike Stroyana73e50c2015-10-01 15:23:48 -06003726 loader_destroy_layer_list(NULL, &instance_layers);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003727 return VK_INCOMPLETE;
3728 }
3729
Mike Stroyana73e50c2015-10-01 15:23:48 -06003730 loader_destroy_layer_list(NULL, &instance_layers);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003731 return VK_SUCCESS;
3732}
3733
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +08003734LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(
Chia-I Wu763a7492015-10-26 20:48:51 +08003735 uint32_t* pPropertyCount,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003736 VkLayerProperties* pProperties)
Tony Barbour426b9052015-06-24 16:06:58 -06003737{
Jon Ashburnb40f2562015-05-29 13:15:39 -06003738
Jon Ashburn182b8302015-08-11 14:49:54 -06003739 struct loader_layer_list instance_layer_list;
Jon Ashburn413d6582015-08-28 15:19:27 -06003740 tls_instance = NULL;
Jon Ashburn182b8302015-08-11 14:49:54 -06003741
Jon Ashburn754f1992015-08-18 18:04:47 -06003742 loader_platform_thread_once(&once_init, loader_initialize);
Courtney Goeltzenleuchter0199e952015-02-27 15:19:33 -07003743
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003744 uint32_t copy_size;
Jon Ashburneb2728b2015-04-10 14:33:07 -06003745
Jon Ashburn182b8302015-08-11 14:49:54 -06003746 /* get layer libraries */
3747 memset(&instance_layer_list, 0, sizeof(instance_layer_list));
Jon Ashburne58f1a32015-08-28 13:38:21 -06003748 loader_layer_scan(NULL, &instance_layer_list, NULL);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003749
3750 if (pProperties == NULL) {
Chia-I Wu763a7492015-10-26 20:48:51 +08003751 *pPropertyCount = instance_layer_list.count;
Jon Ashburne58f1a32015-08-28 13:38:21 -06003752 loader_destroy_layer_list(NULL, &instance_layer_list);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003753 return VK_SUCCESS;
3754 }
3755
Chia-I Wu763a7492015-10-26 20:48:51 +08003756 copy_size = (*pPropertyCount < instance_layer_list.count) ? *pPropertyCount : instance_layer_list.count;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003757 for (uint32_t i = 0; i < copy_size; i++) {
Jon Ashburn182b8302015-08-11 14:49:54 -06003758 memcpy(&pProperties[i], &instance_layer_list.list[i].info, sizeof(VkLayerProperties));
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003759 }
Chia-I Wu763a7492015-10-26 20:48:51 +08003760 *pPropertyCount = copy_size;
Jon Ashburne58f1a32015-08-28 13:38:21 -06003761 loader_destroy_layer_list(NULL, &instance_layer_list);
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003762
Jon Ashburn182b8302015-08-11 14:49:54 -06003763 if (copy_size < instance_layer_list.count) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003764 return VK_INCOMPLETE;
3765 }
Tony Barbour426b9052015-06-24 16:06:58 -06003766
3767 return VK_SUCCESS;
3768}
3769
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +08003770VKAPI_ATTR VkResult VKAPI_CALL loader_EnumerateDeviceExtensionProperties(
Jon Ashburn251258f2015-11-01 14:04:06 -07003771 VkPhysicalDevice physicalDevice,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003772 const char* pLayerName,
Chia-I Wu763a7492015-10-26 20:48:51 +08003773 uint32_t* pPropertyCount,
Tony Barbour426b9052015-06-24 16:06:58 -06003774 VkExtensionProperties* pProperties)
3775{
Jon Ashburned158d12015-12-14 08:52:14 -07003776 struct loader_physical_device *phys_dev;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003777 uint32_t copy_size;
Courtney Goeltzenleuchter0199e952015-02-27 15:19:33 -07003778
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003779 uint32_t count;
Jon Ashburn738136f2015-12-10 18:17:34 -07003780 struct loader_device_extension_list *dev_ext_list=NULL;
Jon Ashburned158d12015-12-14 08:52:14 -07003781 //TODO fix this aliases physical devices
3782 phys_dev = loader_get_physical_device(physicalDevice);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003783
Jon Ashburn182b8302015-08-11 14:49:54 -06003784 /* get layer libraries if needed */
3785 if (pLayerName && strlen(pLayerName) != 0) {
Jon Ashburn251258f2015-11-01 14:04:06 -07003786 for (uint32_t i = 0; i < phys_dev->this_instance->device_layer_list.count; i++) {
3787 struct loader_layer_properties *props = &phys_dev->this_instance->device_layer_list.list[i];
Jon Ashburn182b8302015-08-11 14:49:54 -06003788 if (strcmp(props->info.layerName, pLayerName) == 0) {
3789 dev_ext_list = &props->device_extension_list;
3790 }
3791 }
3792 }
3793 else {
Jon Ashburndb5a5bc2015-11-02 17:40:01 -07003794 /* this case is during the call down the instance chain */
3795 struct loader_icd *icd = phys_dev->this_icd;
3796 VkResult res;
3797 res = icd->EnumerateDeviceExtensionProperties(phys_dev->phys_dev, NULL, pPropertyCount, pProperties);
3798 if (pProperties != NULL && res == VK_SUCCESS) {
3799 /* initialize dev_extension list within the physicalDevice object */
Courtney Goeltzenleuchter03c80a62015-12-02 14:00:19 -07003800 res = loader_init_device_extensions(phys_dev->this_instance,
Jon Ashburndb5a5bc2015-11-02 17:40:01 -07003801 phys_dev, *pPropertyCount, pProperties,
3802 &phys_dev->device_extension_cache);
3803 }
3804 return res;
Jon Ashburn182b8302015-08-11 14:49:54 -06003805 }
3806
Jon Ashburnb8605fe2015-09-18 12:53:16 -06003807 count = (dev_ext_list == NULL) ? 0: dev_ext_list->count;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003808 if (pProperties == NULL) {
Chia-I Wu763a7492015-10-26 20:48:51 +08003809 *pPropertyCount = count;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003810 return VK_SUCCESS;
3811 }
3812
Chia-I Wu763a7492015-10-26 20:48:51 +08003813 copy_size = *pPropertyCount < count ? *pPropertyCount : count;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003814 for (uint32_t i = 0; i < copy_size; i++) {
3815 memcpy(&pProperties[i],
Jon Ashburn738136f2015-12-10 18:17:34 -07003816 &dev_ext_list->list[i].props,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003817 sizeof(VkExtensionProperties));
3818 }
Chia-I Wu763a7492015-10-26 20:48:51 +08003819 *pPropertyCount = copy_size;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003820
3821 if (copy_size < count) {
3822 return VK_INCOMPLETE;
3823 }
3824
3825 return VK_SUCCESS;
3826}
3827
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +08003828VKAPI_ATTR VkResult VKAPI_CALL loader_EnumerateDeviceLayerProperties(
Jon Ashburn251258f2015-11-01 14:04:06 -07003829 VkPhysicalDevice physicalDevice,
Chia-I Wu763a7492015-10-26 20:48:51 +08003830 uint32_t* pPropertyCount,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003831 VkLayerProperties* pProperties)
3832{
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003833 uint32_t copy_size;
Jon Ashburned158d12015-12-14 08:52:14 -07003834 struct loader_physical_device *phys_dev;
3835 //TODO fix this, aliases physical devices
3836 phys_dev = loader_get_physical_device(physicalDevice);
Jon Ashburn251258f2015-11-01 14:04:06 -07003837 uint32_t count = phys_dev->this_instance->device_layer_list.count;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003838
3839 if (pProperties == NULL) {
Chia-I Wu763a7492015-10-26 20:48:51 +08003840 *pPropertyCount = count;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003841 return VK_SUCCESS;
3842 }
3843
Chia-I Wu763a7492015-10-26 20:48:51 +08003844 copy_size = (*pPropertyCount < count) ? *pPropertyCount : count;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003845 for (uint32_t i = 0; i < copy_size; i++) {
Jon Ashburn251258f2015-11-01 14:04:06 -07003846 memcpy(&pProperties[i], &(phys_dev->this_instance->device_layer_list.list[i].info), sizeof(VkLayerProperties));
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003847 }
Chia-I Wu763a7492015-10-26 20:48:51 +08003848 *pPropertyCount = copy_size;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003849
3850 if (copy_size < count) {
3851 return VK_INCOMPLETE;
3852 }
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003853
3854 return VK_SUCCESS;
Jon Ashburn2666e2f2015-05-15 15:09:35 -06003855}