blob: f308105e820cc143093a60235d5af00d282d9a3c [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? */
Jon Ashburn9a3c2b42016-01-07 15:21:14 -0700155 return instance->alloc_callbacks.pfnAllocation(instance->alloc_callbacks.pUserData, size, sizeof(int), 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 }
Jon Ashburn9a3c2b42016-01-07 15:21:14 -0700185 //TODO use the callback realloc function
Chia-I Wu1f851912015-10-27 18:04:07 +0800186 if (instance && instance->alloc_callbacks.pfnAllocation) {
Jon Ashburne5e60df2015-08-27 15:23:52 -0600187 if (size <= orig_size) {
Chia-I Wu1f851912015-10-27 18:04:07 +0800188 memset(((uint8_t *)pMemory) + size, 0, orig_size - size);
189 return pMemory;
Jon Ashburne5e60df2015-08-27 15:23:52 -0600190 }
Jon Ashburn9a3c2b42016-01-07 15:21:14 -0700191 /* TODO: What should default alignment be? 1, 4, 8, other? */
192 void *new_ptr = instance->alloc_callbacks.pfnAllocation(instance->alloc_callbacks.pUserData, size, sizeof(int), alloc_scope);
Jon Ashburne5e60df2015-08-27 15:23:52 -0600193 if (!new_ptr)
194 return NULL;
Chia-I Wu1f851912015-10-27 18:04:07 +0800195 memcpy(new_ptr, pMemory, orig_size);
196 instance->alloc_callbacks.pfnFree(instance->alloc_callbacks.pUserData, pMemory);
Jon Ashburn37984152015-10-21 16:09:27 -0600197 return new_ptr;
Jon Ashburne5e60df2015-08-27 15:23:52 -0600198 }
Chia-I Wu1f851912015-10-27 18:04:07 +0800199 return realloc(pMemory, size);
Jon Ashburne5e60df2015-08-27 15:23:52 -0600200}
201
Jon Ashburn413d6582015-08-28 15:19:27 -0600202void *loader_tls_heap_alloc(size_t size)
203{
Chia-I Wu5eca31f2015-10-31 00:31:16 +0800204 return loader_heap_alloc(tls_instance, size, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
Jon Ashburn413d6582015-08-28 15:19:27 -0600205}
206
Chia-I Wu1f851912015-10-27 18:04:07 +0800207void loader_tls_heap_free(void *pMemory)
Jon Ashburn413d6582015-08-28 15:19:27 -0600208{
Chia-I Wu1f851912015-10-27 18:04:07 +0800209 loader_heap_free(tls_instance, pMemory);
Jon Ashburn413d6582015-08-28 15:19:27 -0600210}
211
Courtney Goeltzenleuchter05525da2015-12-03 13:48:01 -0700212static void loader_log(const struct loader_instance *inst, VkFlags msg_type, int32_t msg_code,
Jon Ashburnee33ae72015-06-30 14:46:22 -0700213 const char *format, ...)
214{
Jon Ashburn2b779162015-07-31 15:47:59 -0600215 char msg[512];
Jon Ashburnee33ae72015-06-30 14:46:22 -0700216 va_list ap;
217 int ret;
218
Jon Ashburnee33ae72015-06-30 14:46:22 -0700219 va_start(ap, format);
220 ret = vsnprintf(msg, sizeof(msg), format, ap);
221 if ((ret >= (int) sizeof(msg)) || ret < 0) {
222 msg[sizeof(msg)-1] = '\0';
223 }
224 va_end(ap);
225
Courtney Goeltzenleuchter05525da2015-12-03 13:48:01 -0700226 if (inst) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -0700227 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 -0700228 }
229
230 if (!(msg_type & g_loader_log_msgs)) {
231 return;
232 }
233
Ian Elliott225188f2015-02-17 10:33:47 -0700234#if defined(WIN32)
Jon Ashburnee33ae72015-06-30 14:46:22 -0700235 OutputDebugString(msg);
mschott632564c2015-07-22 14:11:29 +0200236 OutputDebugString("\n");
Jon Ashburnee33ae72015-06-30 14:46:22 -0700237#endif
238 fputs(msg, stderr);
239 fputc('\n', stderr);
240}
241
242#if defined(WIN32)
Tony Barbour76096e62015-07-29 14:26:21 -0600243static char *loader_get_next_path(char *path);
Jon Ashburnee33ae72015-06-30 14:46:22 -0700244/**
245* Find the list of registry files (names within a key) in key "location".
246*
247* This function looks in the registry (hive = DEFAULT_VK_REGISTRY_HIVE) key as given in "location"
248* for a list or name/values which are added to a returned list (function return value).
249* The DWORD values within the key must be 0 or they are skipped.
Jon Ashburne58f1a32015-08-28 13:38:21 -0600250* Function return is a string with a ';' separated list of filenames.
Jon Ashburnee33ae72015-06-30 14:46:22 -0700251* Function return is NULL if no valid name/value pairs are found in the key,
252* or the key is not found.
253*
254* \returns
255* A string list of filenames as pointer.
256* When done using the returned string list, pointer should be freed.
257*/
Jon Ashburne58f1a32015-08-28 13:38:21 -0600258static char *loader_get_registry_files(const struct loader_instance *inst, char *location)
Jon Ashburnee33ae72015-06-30 14:46:22 -0700259{
260 LONG rtn_value;
261 HKEY hive, key;
Piers Daniellb1f6f6d2015-11-05 16:58:26 -0700262 DWORD access_flags;
Jon Ashburnee33ae72015-06-30 14:46:22 -0700263 char name[2048];
264 char *out = NULL;
Tony Barbour76096e62015-07-29 14:26:21 -0600265 char *loc = location;
266 char *next;
Jon Ashburnee33ae72015-06-30 14:46:22 -0700267 DWORD idx = 0;
268 DWORD name_size = sizeof(name);
269 DWORD value;
270 DWORD total_size = 4096;
271 DWORD value_size = sizeof(value);
Tony Barbour76096e62015-07-29 14:26:21 -0600272
273 while(*loc)
274 {
275 next = loader_get_next_path(loc);
276 hive = DEFAULT_VK_REGISTRY_HIVE;
Piers Daniellb1f6f6d2015-11-05 16:58:26 -0700277 access_flags = KEY_QUERY_VALUE;
Tony Barbour76096e62015-07-29 14:26:21 -0600278 rtn_value = RegOpenKeyEx(hive, loc, 0, access_flags, &key);
279 if (rtn_value != ERROR_SUCCESS) {
280 // We didn't find the key. Try the 32-bit hive (where we've seen the
281 // key end up on some people's systems):
282 access_flags |= KEY_WOW64_32KEY;
283 rtn_value = RegOpenKeyEx(hive, loc, 0, access_flags, &key);
284 if (rtn_value != ERROR_SUCCESS) {
285 // We still couldn't find the key, so give up:
286 loc = next;
287 continue;
Jon Ashburnee33ae72015-06-30 14:46:22 -0700288 }
Jon Ashburnee33ae72015-06-30 14:46:22 -0700289 }
Tony Barbour76096e62015-07-29 14:26:21 -0600290
Jon Ashburne58f1a32015-08-28 13:38:21 -0600291 while ((rtn_value = RegEnumValue(key, idx++, name, &name_size, NULL, NULL, (LPBYTE) &value, &value_size)) == ERROR_SUCCESS) {
Tony Barbour76096e62015-07-29 14:26:21 -0600292 if (value_size == sizeof(value) && value == 0) {
293 if (out == NULL) {
Courtney Goeltzenleuchterbed84552015-11-02 17:43:04 -0700294 out = loader_heap_alloc(inst, total_size, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Tony Barbour76096e62015-07-29 14:26:21 -0600295 out[0] = '\0';
296 }
297 else if (strlen(out) + name_size + 1 > total_size) {
Courtney Goeltzenleuchterbed84552015-11-02 17:43:04 -0700298 out = loader_heap_realloc(inst, out, total_size, total_size * 2, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Tony Barbour76096e62015-07-29 14:26:21 -0600299 total_size *= 2;
300 }
301 if (out == NULL) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -0700302 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 -0600303 return NULL;
304 }
305 if (strlen(out) == 0)
306 snprintf(out, name_size + 1, "%s", name);
307 else
308 snprintf(out + strlen(out), name_size + 2, "%c%s", PATH_SEPERATOR, name);
309 }
310 name_size = 2048;
311 }
312 loc = next;
Jon Ashburnee33ae72015-06-30 14:46:22 -0700313 }
Tony Barbour76096e62015-07-29 14:26:21 -0600314
Jon Ashburnee33ae72015-06-30 14:46:22 -0700315 return out;
316}
317
Ian Elliott225188f2015-02-17 10:33:47 -0700318#endif // WIN32
319
Jon Ashburn4b7f35f2015-08-03 09:08:46 -0600320/**
Daniel Dadap2e13fca2015-09-30 11:50:51 -0500321 * Combine path elements, separating each element with the platform-specific
322 * directory separator, and save the combined string to a destination buffer,
323 * not exceeding the given length. Path elements are given as variadic args,
324 * with a NULL element terminating the list.
325 *
326 * \returns the total length of the combined string, not including an ASCII
327 * NUL termination character. This length may exceed the available storage:
328 * in this case, the written string will be truncated to avoid a buffer
329 * overrun, and the return value will greater than or equal to the storage
330 * size. A NULL argument may be provided as the destination buffer in order
331 * to determine the required string length without actually writing a string.
332 */
333
Courtney Goeltzenleuchtere728d122015-12-16 16:19:46 -0700334static size_t loader_platform_combine_path(char *dest, size_t len, ...)
Daniel Dadap2e13fca2015-09-30 11:50:51 -0500335{
Courtney Goeltzenleuchtere728d122015-12-16 16:19:46 -0700336 size_t required_len = 0;
Daniel Dadap2e13fca2015-09-30 11:50:51 -0500337 va_list ap;
338 const char *component;
339
340 va_start(ap, len);
341
342 while((component = va_arg(ap, const char *))) {
343 if (required_len > 0) {
344 // This path element is not the first non-empty element; prepend
345 // a directory separator if space allows
346 if (dest && required_len + 1 < len) {
347 snprintf(dest + required_len, len - required_len, "%c",
348 DIRECTORY_SYMBOL);
349 }
350 required_len++;
351 }
352
353 if (dest && required_len < len) {
354 strncpy(dest + required_len, component, len - required_len);
355 }
356 required_len += strlen(component);
357 }
358
359 va_end(ap);
360
361 // strncpy(3) won't add a NUL terminating byte in the event of truncation.
362 if (dest && required_len >= len) {
363 dest[len - 1] = '\0';
364 }
365
366 return required_len;
367}
368
369
370/**
Jon Ashburn4b7f35f2015-08-03 09:08:46 -0600371 * Given string of three part form "maj.min.pat" convert to a vulkan version
372 * number.
373 */
374static uint32_t loader_make_version(const char *vers_str)
375{
Jon Ashburnb8605fe2015-09-18 12:53:16 -0600376 uint32_t vers = 0, major=0, minor=0, patch=0;
Jon Ashburn4b7f35f2015-08-03 09:08:46 -0600377 char *minor_str= NULL;
378 char *patch_str = NULL;
379 char *cstr;
380 char *str;
381
382 if (!vers_str)
383 return vers;
384 cstr = loader_stack_alloc(strlen(vers_str) + 1);
385 strcpy(cstr, vers_str);
386 while ((str = strchr(cstr, '.')) != NULL) {
387 if (minor_str == NULL) {
388 minor_str = str + 1;
389 *str = '\0';
390 major = atoi(cstr);
391 }
392 else if (patch_str == NULL) {
393 patch_str = str + 1;
394 *str = '\0';
395 minor = atoi(minor_str);
396 }
397 else {
398 return vers;
399 }
400 cstr = str + 1;
401 }
402 patch = atoi(patch_str);
403
404 return VK_MAKE_VERSION(major, minor, patch);
405
406}
407
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600408bool compare_vk_extension_properties(const VkExtensionProperties *op1, const VkExtensionProperties *op2)
409{
Chia-I Wu1f851912015-10-27 18:04:07 +0800410 return strcmp(op1->extensionName, op2->extensionName) == 0 ? true : false;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600411}
412
Jon Ashburn1b111de2015-07-06 15:40:35 -0600413/**
Jon Ashburn60378412015-07-02 12:59:25 -0600414 * Search the given ext_array for an extension
415 * matching the given vk_ext_prop
416 */
417bool has_vk_extension_property_array(
418 const VkExtensionProperties *vk_ext_prop,
419 const uint32_t count,
420 const VkExtensionProperties *ext_array)
421{
422 for (uint32_t i = 0; i < count; i++) {
423 if (compare_vk_extension_properties(vk_ext_prop, &ext_array[i]))
424 return true;
425 }
426 return false;
427}
428
Jon Ashburn1b111de2015-07-06 15:40:35 -0600429/**
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600430 * Search the given ext_list for an extension
431 * matching the given vk_ext_prop
432 */
433bool has_vk_extension_property(
434 const VkExtensionProperties *vk_ext_prop,
435 const struct loader_extension_list *ext_list)
436{
437 for (uint32_t i = 0; i < ext_list->count; i++) {
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600438 if (compare_vk_extension_properties(&ext_list->list[i], vk_ext_prop))
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600439 return true;
440 }
441 return false;
442}
443
Jon Ashburn0bf6a182015-07-16 17:19:31 -0600444static inline bool loader_is_layer_type_device(const enum layer_type type) {
445 if ((type & VK_LAYER_TYPE_DEVICE_EXPLICIT) ||
446 (type & VK_LAYER_TYPE_DEVICE_IMPLICIT))
447 return true;
448 return false;
449}
450
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600451/*
Jon Ashburn1b111de2015-07-06 15:40:35 -0600452 * Search the given layer list for a layer matching the given layer name
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600453 */
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600454static struct loader_layer_properties *loader_get_layer_property(
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600455 const char *name,
456 const struct loader_layer_list *layer_list)
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600457{
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600458 for (uint32_t i = 0; i < layer_list->count; i++) {
459 const VkLayerProperties *item = &layer_list->list[i].info;
460 if (strcmp(name, item->layerName) == 0)
461 return &layer_list->list[i];
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600462 }
463 return NULL;
464}
465
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600466/**
467 * Get the next unused layer property in the list. Init the property to zero.
468 */
469static struct loader_layer_properties *loader_get_next_layer_property(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600470 const struct loader_instance *inst,
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600471 struct loader_layer_list *layer_list)
472{
473 if (layer_list->capacity == 0) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600474 layer_list->list = loader_heap_alloc(inst,
475 sizeof(struct loader_layer_properties) * 64,
Chia-I Wu1f851912015-10-27 18:04:07 +0800476 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600477 if (layer_list->list == NULL) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -0700478 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 -0600479 return NULL;
480 }
481 memset(layer_list->list, 0, sizeof(struct loader_layer_properties) * 64);
482 layer_list->capacity = sizeof(struct loader_layer_properties) * 64;
483 }
484
485 // ensure enough room to add an entry
486 if ((layer_list->count + 1) * sizeof (struct loader_layer_properties)
487 > layer_list->capacity) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600488 layer_list->list = loader_heap_realloc(inst, layer_list->list,
489 layer_list->capacity,
490 layer_list->capacity * 2,
Chia-I Wu1f851912015-10-27 18:04:07 +0800491 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600492 if (layer_list->list == NULL) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -0700493 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600494 "realloc failed for layer list");
495 }
496 layer_list->capacity *= 2;
497 }
498
499 layer_list->count++;
500 return &(layer_list->list[layer_list->count - 1]);
501}
502
503/**
504 * Remove all layer properties entrys from the list
505 */
Jon Ashburne58f1a32015-08-28 13:38:21 -0600506void loader_delete_layer_properties(
507 const struct loader_instance *inst,
508 struct loader_layer_list *layer_list)
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600509{
Jon Ashburn738136f2015-12-10 18:17:34 -0700510 uint32_t i, j;
511 struct loader_device_extension_list *dev_ext_list;
Jon Ashburn182b8302015-08-11 14:49:54 -0600512 if (!layer_list)
513 return;
514
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600515 for (i = 0; i < layer_list->count; i++) {
Jon Ashburn8f6be302015-12-10 08:51:10 -0700516 loader_destroy_generic_list(inst, (struct loader_generic_list *)
517 &layer_list->list[i].instance_extension_list);
Jon Ashburn738136f2015-12-10 18:17:34 -0700518 dev_ext_list = &layer_list->list[i].device_extension_list;
519 if (dev_ext_list->capacity > 0 && dev_ext_list->list->entrypoint_count > 0) {
520 for (j= 0; j < dev_ext_list->list->entrypoint_count; j++) {
521 loader_heap_free(inst, dev_ext_list->list->entrypoints[j]);
522 }
523 loader_heap_free(inst, dev_ext_list->list->entrypoints);
524 }
Jon Ashburn8f6be302015-12-10 08:51:10 -0700525 loader_destroy_generic_list(inst, (struct loader_generic_list *)
Jon Ashburn738136f2015-12-10 18:17:34 -0700526 dev_ext_list);
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600527 }
528 layer_list->count = 0;
529
Jon Ashburn182b8302015-08-11 14:49:54 -0600530 if (layer_list->capacity > 0) {
531 layer_list->capacity = 0;
Jon Ashburne58f1a32015-08-28 13:38:21 -0600532 loader_heap_free(inst, layer_list->list);
Jon Ashburn182b8302015-08-11 14:49:54 -0600533 }
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600534
535}
536
Courtney Goeltzenleuchter03c80a62015-12-02 14:00:19 -0700537static void loader_add_instance_extensions(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600538 const struct loader_instance *inst,
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -0600539 const PFN_vkEnumerateInstanceExtensionProperties fp_get_props,
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600540 const char *lib_name,
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600541 struct loader_extension_list *ext_list)
542{
Courtney Goeltzenleuchterf843d2d2015-12-21 16:41:47 -0700543 uint32_t i, count = 0;
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600544 VkExtensionProperties *ext_props;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600545 VkResult res;
546
Courtney Goeltzenleuchteraa9faab2015-07-06 22:28:18 -0600547 if (!fp_get_props) {
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -0600548 /* No EnumerateInstanceExtensionProperties defined */
Courtney Goeltzenleuchteraa9faab2015-07-06 22:28:18 -0600549 return;
550 }
551
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600552 res = fp_get_props(NULL, &count, NULL);
Jon Ashburneb2728b2015-04-10 14:33:07 -0600553 if (res != VK_SUCCESS) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -0700554 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 -0600555 return;
556 }
Jon Ashburn60699262015-06-10 16:11:42 -0600557
Courtney Goeltzenleuchteraa9faab2015-07-06 22:28:18 -0600558 if (count == 0) {
559 /* No ExtensionProperties to report */
560 return;
561 }
562
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600563 ext_props = loader_stack_alloc(count * sizeof(VkExtensionProperties));
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600564
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600565 res = fp_get_props(NULL, &count, ext_props);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600566 if (res != VK_SUCCESS) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -0700567 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 -0600568 return;
569 }
Tony Barbour426b9052015-06-24 16:06:58 -0600570
Jon Ashburneb2728b2015-04-10 14:33:07 -0600571 for (i = 0; i < count; i++) {
Courtney Goeltzenleuchter73a21d32015-07-12 13:20:05 -0600572 char spec_version[64];
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600573
574 snprintf(spec_version, sizeof(spec_version), "%d.%d.%d",
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600575 VK_MAJOR(ext_props[i].specVersion),
576 VK_MINOR(ext_props[i].specVersion),
577 VK_PATCH(ext_props[i].specVersion));
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -0700578 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
Courtney Goeltzenleuchter03c80a62015-12-02 14:00:19 -0700579 "Instance Extension: %s (%s) version %s",
Chia-I Wu1f851912015-10-27 18:04:07 +0800580 ext_props[i].extensionName, lib_name, spec_version);
Jon Ashburne58f1a32015-08-28 13:38:21 -0600581 loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600582 }
583
584 return;
585}
586
Jon Ashburndb5a5bc2015-11-02 17:40:01 -0700587/*
588 * Initialize ext_list with the physical device extensions.
589 * The extension properties are passed as inputs in count and ext_props.
590 */
Courtney Goeltzenleuchter03c80a62015-12-02 14:00:19 -0700591static VkResult loader_init_device_extensions(
Jon Ashburndb5a5bc2015-11-02 17:40:01 -0700592 const struct loader_instance *inst,
593 struct loader_physical_device *phys_dev,
594 uint32_t count,
595 VkExtensionProperties *ext_props,
596 struct loader_extension_list *ext_list)
597{
598 VkResult res;
599 uint32_t i;
600
Jon Ashburn8f6be302015-12-10 08:51:10 -0700601 if (!loader_init_generic_list(inst, (struct loader_generic_list *) ext_list,
602 sizeof(VkExtensionProperties))) {
Jon Ashburndb5a5bc2015-11-02 17:40:01 -0700603 return VK_ERROR_OUT_OF_HOST_MEMORY;
604 }
605
606 for (i = 0; i < count; i++) {
607 char spec_version[64];
608
609 snprintf(spec_version, sizeof (spec_version), "%d.%d.%d",
610 VK_MAJOR(ext_props[i].specVersion),
611 VK_MINOR(ext_props[i].specVersion),
612 VK_PATCH(ext_props[i].specVersion));
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -0700613 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
Courtney Goeltzenleuchter03c80a62015-12-02 14:00:19 -0700614 "Device Extension: %s (%s) version %s",
Jon Ashburndb5a5bc2015-11-02 17:40:01 -0700615 ext_props[i].extensionName, phys_dev->this_icd->this_icd_lib->lib_name, spec_version);
616 res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
617 if (res != VK_SUCCESS)
618 return res;
619 }
620
621 return VK_SUCCESS;
622}
623
Courtney Goeltzenleuchter03c80a62015-12-02 14:00:19 -0700624static VkResult loader_add_device_extensions(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600625 const struct loader_instance *inst,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600626 VkPhysicalDevice physical_device,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600627 const char *lib_name,
628 struct loader_extension_list *ext_list)
629{
630 uint32_t i, count;
631 VkResult res;
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600632 VkExtensionProperties *ext_props;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600633
Jon Ashburndb5a5bc2015-11-02 17:40:01 -0700634 res = loader_EnumerateDeviceExtensionProperties(physical_device, NULL, &count, NULL);
635 if (res == VK_SUCCESS && count > 0) {
636 ext_props = loader_stack_alloc(count * sizeof (VkExtensionProperties));
637 if (!ext_props)
638 return VK_ERROR_OUT_OF_HOST_MEMORY;
639 res = loader_EnumerateDeviceExtensionProperties(physical_device, NULL, &count, ext_props);
640 if (res != VK_SUCCESS)
Jon Ashburn251258f2015-11-01 14:04:06 -0700641 return res;
Jon Ashburndb5a5bc2015-11-02 17:40:01 -0700642 for (i = 0; i < count; i++) {
643 char spec_version[64];
644
645 snprintf(spec_version, sizeof (spec_version), "%d.%d.%d",
646 VK_MAJOR(ext_props[i].specVersion),
647 VK_MINOR(ext_props[i].specVersion),
648 VK_PATCH(ext_props[i].specVersion));
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -0700649 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
Courtney Goeltzenleuchter03c80a62015-12-02 14:00:19 -0700650 "Device Extension: %s (%s) version %s",
Jon Ashburndb5a5bc2015-11-02 17:40:01 -0700651 ext_props[i].extensionName, lib_name, spec_version);
652 res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
653 if (res != VK_SUCCESS)
654 return res;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600655 }
Jon Ashburndb5a5bc2015-11-02 17:40:01 -0700656 } else {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -0700657 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 -0700658 return res;
659 }
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600660
Jon Ashburn251258f2015-11-01 14:04:06 -0700661 return VK_SUCCESS;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600662}
663
Jon Ashburn8f6be302015-12-10 08:51:10 -0700664static bool loader_init_generic_list(const struct loader_instance *inst,
665 struct loader_generic_list *list_info,
666 size_t element_size)
Jon Ashburneb2728b2015-04-10 14:33:07 -0600667{
Jon Ashburn8f6be302015-12-10 08:51:10 -0700668 list_info->capacity = 32 * element_size;
669 list_info->list = loader_heap_alloc(inst, list_info->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
670 if (list_info->list == NULL) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600671 return false;
672 }
Jon Ashburn8f6be302015-12-10 08:51:10 -0700673 memset(list_info->list, 0, list_info->capacity);
674 list_info->count = 0;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600675 return true;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600676}
677
Jon Ashburn8f6be302015-12-10 08:51:10 -0700678void loader_destroy_generic_list(const struct loader_instance *inst,
679 struct loader_generic_list *list)
Jon Ashburneb2728b2015-04-10 14:33:07 -0600680{
Jon Ashburn8f6be302015-12-10 08:51:10 -0700681 loader_heap_free(inst, list->list);
682 list->count = 0;
683 list->capacity = 0;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600684}
Jon Ashburneb2728b2015-04-10 14:33:07 -0600685
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600686/*
687 * Append non-duplicate extension properties defined in props
688 * to the given ext_list.
Jon Ashburn251258f2015-11-01 14:04:06 -0700689 * Return
690 * Vk_SUCCESS on success
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600691 */
Jon Ashburn251258f2015-11-01 14:04:06 -0700692VkResult loader_add_to_ext_list(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600693 const struct loader_instance *inst,
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600694 struct loader_extension_list *ext_list,
695 uint32_t prop_list_count,
696 const VkExtensionProperties *props)
697{
698 uint32_t i;
699 const VkExtensionProperties *cur_ext;
700
701 if (ext_list->list == NULL || ext_list->capacity == 0) {
Jon Ashburn8f6be302015-12-10 08:51:10 -0700702 loader_init_generic_list(inst, (struct loader_generic_list *) ext_list,
703 sizeof(VkExtensionProperties));
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600704 }
705
706 if (ext_list->list == NULL)
Jon Ashburn251258f2015-11-01 14:04:06 -0700707 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600708
709 for (i = 0; i < prop_list_count; i++) {
710 cur_ext = &props[i];
711
712 // look for duplicates
713 if (has_vk_extension_property(cur_ext, ext_list)) {
714 continue;
715 }
716
717 // add to list at end
718 // check for enough capacity
719 if (ext_list->count * sizeof(VkExtensionProperties)
720 >= ext_list->capacity) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600721
722 ext_list->list = loader_heap_realloc(inst,
723 ext_list->list,
724 ext_list->capacity,
725 ext_list->capacity * 2,
Chia-I Wu1f851912015-10-27 18:04:07 +0800726 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn251258f2015-11-01 14:04:06 -0700727
728 if (ext_list->list == NULL)
729 return VK_ERROR_OUT_OF_HOST_MEMORY;
730
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600731 // double capacity
732 ext_list->capacity *= 2;
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600733 }
734
735 memcpy(&ext_list->list[ext_list->count], cur_ext, sizeof(VkExtensionProperties));
736 ext_list->count++;
737 }
Jon Ashburn251258f2015-11-01 14:04:06 -0700738 return VK_SUCCESS;
Jon Ashburnc4748dc2015-08-04 11:14:18 -0600739}
740
Jon Ashburn738136f2015-12-10 18:17:34 -0700741/*
742 * Append one extension property defined in props with entrypoints
743 * defined in entrys to the given ext_list.
744 * Return
745 * Vk_SUCCESS on success
746 */
747VkResult loader_add_to_dev_ext_list(
748 const struct loader_instance *inst,
749 struct loader_device_extension_list *ext_list,
750 const VkExtensionProperties *props,
751 uint32_t entry_count,
752 char **entrys)
753{
754 uint32_t idx;
755 if (ext_list->list == NULL || ext_list->capacity == 0) {
756 loader_init_generic_list(inst, (struct loader_generic_list *) ext_list,
757 sizeof(struct loader_dev_ext_props));
758 }
759
760 if (ext_list->list == NULL)
761 return VK_ERROR_OUT_OF_HOST_MEMORY;
762
763 idx =ext_list->count;
764 // add to list at end
765 // check for enough capacity
766 if (idx * sizeof (struct loader_dev_ext_props)
767 >= ext_list->capacity) {
768
769 ext_list->list = loader_heap_realloc(inst,
770 ext_list->list,
771 ext_list->capacity,
772 ext_list->capacity * 2,
773 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
774
775 if (ext_list->list == NULL)
776 return VK_ERROR_OUT_OF_HOST_MEMORY;
777
778 // double capacity
779 ext_list->capacity *= 2;
780 }
781
782 memcpy(&ext_list->list[idx].props, props, sizeof(struct loader_dev_ext_props));
783 ext_list->list[idx].entrypoint_count = entry_count;
784 ext_list->list[idx].entrypoints = loader_heap_alloc(inst,
785 sizeof(char *) * entry_count,
786 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
787 if (ext_list->list[idx].entrypoints == NULL)
788 return VK_ERROR_OUT_OF_HOST_MEMORY;
789 for (uint32_t i = 0; i < entry_count; i++) {
790 ext_list->list[idx].entrypoints[i] = loader_heap_alloc(inst,
791 strlen(entrys[i]) + 1,
792 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
793 if (ext_list->list[idx].entrypoints[i] == NULL)
794 return VK_ERROR_OUT_OF_HOST_MEMORY;
795 strcpy(ext_list->list[idx].entrypoints[i], entrys[i]);
796 }
797 ext_list->count++;
798
799 return VK_SUCCESS;
800}
801
Jon Ashburn60378412015-07-02 12:59:25 -0600802/**
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600803 * Search the given search_list for any layers in the props list.
804 * Add these to the output layer_list. Don't add duplicates to the output layer_list.
Jon Ashburn60378412015-07-02 12:59:25 -0600805 */
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -0600806static VkResult loader_add_layer_names_to_list(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600807 const struct loader_instance *inst,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600808 struct loader_layer_list *output_list,
809 uint32_t name_count,
810 const char * const *names,
811 const struct loader_layer_list *search_list)
Jon Ashburneb2728b2015-04-10 14:33:07 -0600812{
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600813 struct loader_layer_properties *layer_prop;
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -0600814 VkResult err = VK_SUCCESS;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600815
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600816 for (uint32_t i = 0; i < name_count; i++) {
817 const char *search_target = names[i];
Jon Ashburn8e4fab42015-08-03 17:19:30 -0600818 layer_prop = loader_get_layer_property(search_target, search_list);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600819 if (!layer_prop) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -0700820 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Unable to find layer %s", search_target);
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -0600821 err = VK_ERROR_LAYER_NOT_PRESENT;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600822 continue;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600823 }
824
Jon Ashburne58f1a32015-08-28 13:38:21 -0600825 loader_add_to_layer_list(inst, output_list, 1, layer_prop);
Jon Ashburneb2728b2015-04-10 14:33:07 -0600826 }
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -0600827
828 return err;
Jon Ashburneb2728b2015-04-10 14:33:07 -0600829}
830
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600831
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600832/*
833 * Manage lists of VkLayerProperties
834 */
Jon Ashburne58f1a32015-08-28 13:38:21 -0600835static bool loader_init_layer_list(const struct loader_instance *inst,
836 struct loader_layer_list *list)
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600837{
838 list->capacity = 32 * sizeof(struct loader_layer_properties);
Chia-I Wu1f851912015-10-27 18:04:07 +0800839 list->list = loader_heap_alloc(inst, list->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600840 if (list->list == NULL) {
841 return false;
842 }
843 memset(list->list, 0, list->capacity);
844 list->count = 0;
845 return true;
846}
847
Jon Ashburne58f1a32015-08-28 13:38:21 -0600848void loader_destroy_layer_list(const struct loader_instance *inst,
849 struct loader_layer_list *layer_list)
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600850{
Jon Ashburne58f1a32015-08-28 13:38:21 -0600851 loader_heap_free(inst, layer_list->list);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600852 layer_list->count = 0;
853 layer_list->capacity = 0;
854}
855
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -0600856/*
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600857 * Manage list of layer libraries (loader_lib_info)
858 */
Jon Ashburne58f1a32015-08-28 13:38:21 -0600859static bool loader_init_layer_library_list(const struct loader_instance *inst,
860 struct loader_layer_library_list *list)
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600861{
862 list->capacity = 32 * sizeof(struct loader_lib_info);
Chia-I Wu1f851912015-10-27 18:04:07 +0800863 list->list = loader_heap_alloc(inst, list->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600864 if (list->list == NULL) {
865 return false;
866 }
867 memset(list->list, 0, list->capacity);
868 list->count = 0;
869 return true;
870}
871
Jon Ashburne58f1a32015-08-28 13:38:21 -0600872void loader_destroy_layer_library_list(const struct loader_instance *inst,
873 struct loader_layer_library_list *list)
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600874{
875 for (uint32_t i = 0; i < list->count; i++) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600876 loader_heap_free(inst, list->list[i].lib_name);
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600877 }
Jon Ashburne58f1a32015-08-28 13:38:21 -0600878 loader_heap_free(inst, list->list);
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600879 list->count = 0;
880 list->capacity = 0;
881}
882
883void loader_add_to_layer_library_list(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600884 const struct loader_instance *inst,
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600885 struct loader_layer_library_list *list,
886 uint32_t item_count,
887 const struct loader_lib_info *new_items)
888{
889 uint32_t i;
890 struct loader_lib_info *item;
891
892 if (list->list == NULL || list->capacity == 0) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600893 loader_init_layer_library_list(inst, list);
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600894 }
895
896 if (list->list == NULL)
897 return;
898
899 for (i = 0; i < item_count; i++) {
900 item = (struct loader_lib_info *) &new_items[i];
901
902 // look for duplicates
903 for (uint32_t j = 0; j < list->count; j++) {
904 if (strcmp(list->list[i].lib_name, new_items->lib_name) == 0) {
905 continue;
906 }
907 }
908
909 // add to list at end
910 // check for enough capacity
911 if (list->count * sizeof(struct loader_lib_info)
912 >= list->capacity) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600913
914 list->list = loader_heap_realloc(inst,
915 list->list,
916 list->capacity,
917 list->capacity * 2,
Chia-I Wu1f851912015-10-27 18:04:07 +0800918 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600919 // double capacity
920 list->capacity *= 2;
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600921 }
922
923 memcpy(&list->list[list->count], item, sizeof(struct loader_lib_info));
924 list->count++;
925 }
926}
927
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600928
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -0600929/*
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600930 * Search the given layer list for a list
931 * matching the given VkLayerProperties
932 */
933bool has_vk_layer_property(
934 const VkLayerProperties *vk_layer_prop,
935 const struct loader_layer_list *list)
936{
937 for (uint32_t i = 0; i < list->count; i++) {
938 if (strcmp(vk_layer_prop->layerName, list->list[i].info.layerName) == 0)
939 return true;
940 }
941 return false;
942}
943
944/*
945 * Search the given layer list for a layer
946 * matching the given name
947 */
948bool has_layer_name(
949 const char *name,
950 const struct loader_layer_list *list)
951{
952 for (uint32_t i = 0; i < list->count; i++) {
953 if (strcmp(name, list->list[i].info.layerName) == 0)
954 return true;
955 }
956 return false;
957}
958
959/*
960 * Append non-duplicate layer properties defined in prop_list
961 * to the given layer_info list
962 */
963void loader_add_to_layer_list(
Jon Ashburne58f1a32015-08-28 13:38:21 -0600964 const struct loader_instance *inst,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600965 struct loader_layer_list *list,
966 uint32_t prop_list_count,
967 const struct loader_layer_properties *props)
968{
969 uint32_t i;
970 struct loader_layer_properties *layer;
971
972 if (list->list == NULL || list->capacity == 0) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600973 loader_init_layer_list(inst, list);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600974 }
975
976 if (list->list == NULL)
977 return;
978
979 for (i = 0; i < prop_list_count; i++) {
980 layer = (struct loader_layer_properties *) &props[i];
981
982 // look for duplicates
983 if (has_vk_layer_property(&layer->info, list)) {
984 continue;
985 }
986
987 // add to list at end
988 // check for enough capacity
989 if (list->count * sizeof(struct loader_layer_properties)
990 >= list->capacity) {
Jon Ashburne58f1a32015-08-28 13:38:21 -0600991
992 list->list = loader_heap_realloc(inst,
993 list->list,
994 list->capacity,
995 list->capacity * 2,
Chia-I Wu1f851912015-10-27 18:04:07 +0800996 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600997 // double capacity
998 list->capacity *= 2;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -0600999 }
1000
1001 memcpy(&list->list[list->count], layer, sizeof(struct loader_layer_properties));
1002 list->count++;
1003 }
1004}
1005
Jon Ashburnf2ddb732015-07-07 10:27:45 -06001006/**
1007 * Search the search_list for any layer with a name
1008 * that matches the given name and a type that matches the given type
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06001009 * Add all matching layers to the found_list
Jon Ashburnf2ddb732015-07-07 10:27:45 -06001010 * Do not add if found loader_layer_properties is already
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06001011 * on the found_list.
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001012 */
Jon Ashburn60378412015-07-02 12:59:25 -06001013static void loader_find_layer_name_add_list(
Jon Ashburne58f1a32015-08-28 13:38:21 -06001014 const struct loader_instance *inst,
Jon Ashburn60378412015-07-02 12:59:25 -06001015 const char *name,
Jon Ashburnf2ddb732015-07-07 10:27:45 -06001016 const enum layer_type type,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06001017 const struct loader_layer_list *search_list,
1018 struct loader_layer_list *found_list)
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001019{
Jon Ashburn87c8fe92015-10-05 09:03:21 -06001020 bool found = false;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001021 for (uint32_t i = 0; i < search_list->count; i++) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06001022 struct loader_layer_properties *layer_prop = &search_list->list[i];
Jon Ashburnf2ddb732015-07-07 10:27:45 -06001023 if (0 == strcmp(layer_prop->info.layerName, name) &&
1024 (layer_prop->type & type)) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06001025 /* Found a layer with the same name, add to found_list */
Jon Ashburne58f1a32015-08-28 13:38:21 -06001026 loader_add_to_layer_list(inst, found_list, 1, layer_prop);
Jon Ashburn87c8fe92015-10-05 09:03:21 -06001027 found = true;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001028 }
1029 }
Jon Ashburn87c8fe92015-10-05 09:03:21 -06001030 if (!found) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001031 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 -06001032 }
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001033}
1034
Jon Ashburnc4748dc2015-08-04 11:14:18 -06001035static VkExtensionProperties *get_extension_property(
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06001036 const char *name,
1037 const struct loader_extension_list *list)
Jon Ashburn42e41032015-04-14 09:15:32 -06001038{
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06001039 for (uint32_t i = 0; i < list->count; i++) {
Chia-I Wu1f851912015-10-27 18:04:07 +08001040 if (strcmp(name, list->list[i].extensionName) == 0)
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06001041 return &list->list[i];
Jon Ashburn42e41032015-04-14 09:15:32 -06001042 }
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06001043 return NULL;
Jon Ashburn42e41032015-04-14 09:15:32 -06001044}
1045
Jon Ashburn738136f2015-12-10 18:17:34 -07001046static VkExtensionProperties *get_dev_extension_property(
1047 const char *name,
1048 const struct loader_device_extension_list *list)
1049{
1050 for (uint32_t i = 0; i < list->count; i++) {
1051 if (strcmp(name, list->list[i].props.extensionName) == 0)
1052 return &list->list[i].props;
1053 }
1054 return NULL;
1055}
1056
Jon Ashburn60378412015-07-02 12:59:25 -06001057/*
Courtney Goeltzenleuchter03c80a62015-12-02 14:00:19 -07001058 * For Instance extensions implemented within the loader (i.e. DEBUG_REPORT
Jon Ashburn60378412015-07-02 12:59:25 -06001059 * the extension must provide two entry points for the loader to use:
1060 * - "trampoline" entry point - this is the address returned by GetProcAddr
1061 * and will always do what's necessary to support a global call.
1062 * - "terminator" function - this function will be put at the end of the
Jon Ashburn2818eb72015-11-30 17:21:25 -07001063 * instance chain and will contain the necessary logic to call / process
Jon Ashburn60378412015-07-02 12:59:25 -06001064 * the extension for the appropriate ICDs that are available.
1065 * There is no generic mechanism for including these functions, the references
1066 * must be placed into the appropriate loader entry points.
1067 * GetInstanceProcAddr: call extension GetInstanceProcAddr to check for GetProcAddr requests
1068 * loader_coalesce_extensions(void) - add extension records to the list of global
1069 * extension available to the app.
1070 * instance_disp - add function pointer for terminator function to this array.
1071 * The extension itself should be in a separate file that will be
1072 * linked directly with the loader.
1073 */
Jon Ashburnc1d1eb72015-08-14 11:57:54 -06001074
Jon Ashburn754f1992015-08-18 18:04:47 -06001075void loader_get_icd_loader_instance_extensions(
Jon Ashburne58f1a32015-08-28 13:38:21 -06001076 const struct loader_instance *inst,
Jon Ashburn754f1992015-08-18 18:04:47 -06001077 struct loader_icd_libs *icd_libs,
1078 struct loader_extension_list *inst_exts)
Jon Ashburneb2728b2015-04-10 14:33:07 -06001079{
Jon Ashburn85f98072015-08-14 14:49:22 -06001080 struct loader_extension_list icd_exts;
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001081 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Build ICD instance extension list");
Jon Ashburneb2728b2015-04-10 14:33:07 -06001082 // traverse scanned icd list adding non-duplicate extensions to the list
Jon Ashburn754f1992015-08-18 18:04:47 -06001083 for (uint32_t i = 0; i < icd_libs->count; i++) {
Jon Ashburn8f6be302015-12-10 08:51:10 -07001084 loader_init_generic_list(inst, (struct loader_generic_list *) &icd_exts,
1085 sizeof(VkExtensionProperties));
Courtney Goeltzenleuchter03c80a62015-12-02 14:00:19 -07001086 loader_add_instance_extensions(inst, icd_libs->list[i].EnumerateInstanceExtensionProperties,
Jon Ashburn754f1992015-08-18 18:04:47 -06001087 icd_libs->list[i].lib_name,
Jon Ashburn85f98072015-08-14 14:49:22 -06001088 &icd_exts);
Jon Ashburne58f1a32015-08-28 13:38:21 -06001089 loader_add_to_ext_list(inst, inst_exts,
Jon Ashburn85f98072015-08-14 14:49:22 -06001090 icd_exts.count,
1091 icd_exts.list);
Jon Ashburn8f6be302015-12-10 08:51:10 -07001092 loader_destroy_generic_list(inst, (struct loader_generic_list *) &icd_exts);
Jon Ashburneb2728b2015-04-10 14:33:07 -06001093 };
1094
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001095 // Traverse loader's extensions, adding non-duplicate extensions to the list
Ian Elliotta81e8ac2015-10-30 15:28:23 -06001096 wsi_add_instance_extensions(inst, inst_exts);
Jon Ashburne58f1a32015-08-28 13:38:21 -06001097 debug_report_add_instance_extensions(inst, inst_exts);
Jon Ashburneb2728b2015-04-10 14:33:07 -06001098}
1099
Jon Ashburnba1f24e2015-12-11 09:41:34 -07001100struct loader_physical_device *loader_get_physical_device(const VkPhysicalDevice physdev)
1101{
1102 uint32_t i;
1103 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
1104 for (i = 0; i < inst->total_gpu_count; i++) {
1105 //TODO this aliases physDevices within instances, need for this
1106 // function to go away
1107 if (inst->phys_devs[i].disp == loader_get_instance_dispatch(physdev)) {
1108 return &inst->phys_devs[i];
1109 }
1110 }
1111 }
1112 return NULL;
1113}
1114
Jon Ashburne58f1a32015-08-28 13:38:21 -06001115struct loader_icd *loader_get_icd_and_device(const VkDevice device,
1116 struct loader_device **found_dev)
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06001117{
1118 *found_dev = NULL;
1119 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
1120 for (struct loader_icd *icd = inst->icds; icd; icd = icd->next) {
1121 for (struct loader_device *dev = icd->logical_device_list; dev; dev = dev->next)
Jon Ashburn0c5eea22015-09-30 12:56:42 -06001122 /* Value comparison of device prevents object wrapping by layers */
1123 if (loader_get_dispatch(dev->device) == loader_get_dispatch(device)) {
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06001124 *found_dev = dev;
1125 return icd;
1126 }
1127 }
1128 }
1129 return NULL;
1130}
1131
Jon Ashburne58f1a32015-08-28 13:38:21 -06001132static void loader_destroy_logical_device(const struct loader_instance *inst,
1133 struct loader_device *dev)
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06001134{
Jon Ashburne58f1a32015-08-28 13:38:21 -06001135 loader_heap_free(inst, dev->app_extension_props);
BogDan Vatrababfa702016-01-04 14:05:49 +02001136 loader_destroy_layer_list(inst, &dev->activated_layer_list);
Jon Ashburne58f1a32015-08-28 13:38:21 -06001137 loader_heap_free(inst, dev);
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06001138}
1139
Jon Ashburne58f1a32015-08-28 13:38:21 -06001140static struct loader_device *loader_add_logical_device(
1141 const struct loader_instance *inst,
1142 const VkDevice dev,
1143 struct loader_device **device_list)
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06001144{
1145 struct loader_device *new_dev;
1146
Chia-I Wu1f851912015-10-27 18:04:07 +08001147 new_dev = loader_heap_alloc(inst, sizeof(struct loader_device), VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06001148 if (!new_dev) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001149 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Failed to alloc struct laoder-device");
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06001150 return NULL;
1151 }
1152
1153 memset(new_dev, 0, sizeof(struct loader_device));
1154
1155 new_dev->next = *device_list;
1156 new_dev->device = dev;
1157 *device_list = new_dev;
1158 return new_dev;
1159}
1160
Jon Ashburne58f1a32015-08-28 13:38:21 -06001161void loader_remove_logical_device(
1162 const struct loader_instance *inst,
Jon Ashburndbf8cee2015-11-19 15:43:26 -07001163 struct loader_icd *icd,
1164 struct loader_device *found_dev)
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06001165{
Jon Ashburndbf8cee2015-11-19 15:43:26 -07001166 struct loader_device *dev, *prev_dev;
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06001167
1168 if (!icd || !found_dev)
1169 return;
1170
1171 prev_dev = NULL;
1172 dev = icd->logical_device_list;
1173 while (dev && dev != found_dev) {
1174 prev_dev = dev;
1175 dev = dev->next;
1176 }
1177
1178 if (prev_dev)
1179 prev_dev->next = found_dev->next;
1180 else
1181 icd->logical_device_list = found_dev->next;
Jon Ashburne58f1a32015-08-28 13:38:21 -06001182 loader_destroy_logical_device(inst, found_dev);
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06001183}
1184
1185
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001186static void loader_icd_destroy(
1187 struct loader_instance *ptr_inst,
1188 struct loader_icd *icd)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001189{
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001190 ptr_inst->total_icd_count--;
Courtney Goeltzenleuchter6b70e362015-06-14 19:57:15 -06001191 for (struct loader_device *dev = icd->logical_device_list; dev; ) {
1192 struct loader_device *next_dev = dev->next;
Jon Ashburne58f1a32015-08-28 13:38:21 -06001193 loader_destroy_logical_device(ptr_inst, dev);
Courtney Goeltzenleuchter6b70e362015-06-14 19:57:15 -06001194 dev = next_dev;
1195 }
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06001196
Jon Ashburne58f1a32015-08-28 13:38:21 -06001197 loader_heap_free(ptr_inst, icd);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001198}
1199
Jon Ashburne58f1a32015-08-28 13:38:21 -06001200static struct loader_icd * loader_icd_create(const struct loader_instance *inst)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001201{
1202 struct loader_icd *icd;
1203
Chia-I Wu1f851912015-10-27 18:04:07 +08001204 icd = loader_heap_alloc(inst, sizeof(*icd), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001205 if (!icd)
1206 return NULL;
1207
Courtney Goeltzenleuchter6f928162014-10-28 10:29:27 -06001208 memset(icd, 0, sizeof(*icd));
1209
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001210 return icd;
1211}
1212
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001213static struct loader_icd *loader_icd_add(
1214 struct loader_instance *ptr_inst,
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06001215 const struct loader_scanned_icds *icd_lib)
Chia-I Wu894a1172014-08-04 11:18:20 +08001216{
1217 struct loader_icd *icd;
1218
Jon Ashburne58f1a32015-08-28 13:38:21 -06001219 icd = loader_icd_create(ptr_inst);
Chia-I Wu894a1172014-08-04 11:18:20 +08001220 if (!icd)
1221 return NULL;
1222
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06001223 icd->this_icd_lib = icd_lib;
1224 icd->this_instance = ptr_inst;
1225
Chia-I Wu894a1172014-08-04 11:18:20 +08001226 /* prepend to the list */
Jon Ashburn3336df82015-01-29 15:45:51 -07001227 icd->next = ptr_inst->icds;
1228 ptr_inst->icds = icd;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001229 ptr_inst->total_icd_count++;
Chia-I Wu894a1172014-08-04 11:18:20 +08001230
1231 return icd;
1232}
1233
Jon Ashburne58f1a32015-08-28 13:38:21 -06001234void loader_scanned_icd_clear(
1235 const struct loader_instance *inst,
1236 struct loader_icd_libs *icd_libs)
Jon Ashburn754f1992015-08-18 18:04:47 -06001237{
1238 if (icd_libs->capacity == 0)
1239 return;
1240 for (uint32_t i = 0; i < icd_libs->count; i++) {
1241 loader_platform_close_library(icd_libs->list[i].handle);
Jon Ashburne58f1a32015-08-28 13:38:21 -06001242 loader_heap_free(inst, icd_libs->list[i].lib_name);
Jon Ashburn754f1992015-08-18 18:04:47 -06001243 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06001244 loader_heap_free(inst, icd_libs->list);
Jon Ashburn754f1992015-08-18 18:04:47 -06001245 icd_libs->capacity = 0;
1246 icd_libs->count = 0;
1247 icd_libs->list = NULL;
1248}
1249
Jon Ashburne58f1a32015-08-28 13:38:21 -06001250static void loader_scanned_icd_init(const struct loader_instance *inst,
1251 struct loader_icd_libs *icd_libs)
Jon Ashburn754f1992015-08-18 18:04:47 -06001252{
Jon Ashburne58f1a32015-08-28 13:38:21 -06001253 loader_scanned_icd_clear(inst, icd_libs);
Jon Ashburn754f1992015-08-18 18:04:47 -06001254 icd_libs->capacity = 8 * sizeof(struct loader_scanned_icds);
Chia-I Wu1f851912015-10-27 18:04:07 +08001255 icd_libs->list = loader_heap_alloc(inst, icd_libs->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn754f1992015-08-18 18:04:47 -06001256
1257}
1258
1259static void loader_scanned_icd_add(
Jon Ashburne58f1a32015-08-28 13:38:21 -06001260 const struct loader_instance *inst,
Jon Ashburn754f1992015-08-18 18:04:47 -06001261 struct loader_icd_libs *icd_libs,
Jon Ashburn0083b222015-11-17 17:35:40 -07001262 const char *filename,
1263 uint32_t api_version)
Jon Ashburn14275da2015-01-28 11:01:35 -07001264{
Ian Elliott81ac44c2015-01-13 17:52:38 -07001265 loader_platform_dl_handle handle;
Tony Barbourde4124d2015-07-03 10:33:54 -06001266 PFN_vkCreateInstance fp_create_inst;
Jon Ashburn6b689942016-01-07 09:44:27 -07001267 PFN_vkEnumerateInstanceExtensionProperties fp_get_inst_ext_props;
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001268 PFN_vkGetInstanceProcAddr fp_get_proc_addr;
Jon Ashburn14275da2015-01-28 11:01:35 -07001269 struct loader_scanned_icds *new_node;
1270
Jon Ashburn754f1992015-08-18 18:04:47 -06001271 /* TODO implement ref counting of libraries, for now this function leaves
1272 libraries open and the scanned_icd_clear closes them */
Ian Elliott81ac44c2015-01-13 17:52:38 -07001273 // Used to call: dlopen(filename, RTLD_LAZY);
1274 handle = loader_platform_open_library(filename);
Jon Ashburn14275da2015-01-28 11:01:35 -07001275 if (!handle) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001276 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0, loader_platform_open_library_error(filename));
Jon Ashburn14275da2015-01-28 11:01:35 -07001277 return;
1278 }
1279
Jon Ashburn6b689942016-01-07 09:44:27 -07001280 fp_get_proc_addr = loader_platform_get_proc_address(handle, "vk_icdGetInstanceProcAddr");
1281 if (!fp_get_proc_addr) {
Jon Ashburn3f19e052016-01-11 14:41:35 -07001282 // Use deprecated interface
Jon Ashburn6b689942016-01-07 09:44:27 -07001283 fp_get_proc_addr = loader_platform_get_proc_address(handle, "vkGetInstanceProcAddr");
1284 if (!fp_get_proc_addr) {
1285 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, loader_platform_get_proc_address_error("vk_icdGetInstanceProcAddr"));
1286 return;
1287 } else {
1288 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0, "Using deprecated ICD interface of vkGetInstanceProcAddr instead of vk_icdGetInstanceProcAddr");
1289 }
Jon Ashburn3f19e052016-01-11 14:41:35 -07001290 fp_create_inst = loader_platform_get_proc_address(handle, "vkCreateInstance");
1291 if (!fp_create_inst) {
1292 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Couldn't get vkCreateInstance via dlsym/loadlibrary from ICD");
1293 return;
1294 }
1295 fp_get_inst_ext_props = loader_platform_get_proc_address(handle, "vkEnumerateInstanceExtensionProperties");
1296 if (!fp_get_inst_ext_props) {
1297 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Couldn't get vkEnumerateInstanceExtensionProperties via dlsym/loadlibrary from ICD");
1298 return;
1299 }
Jon Ashburn6b689942016-01-07 09:44:27 -07001300 }
Jon Ashburn3f19e052016-01-11 14:41:35 -07001301 else {
1302 // Use newer interface
1303 fp_create_inst = (PFN_vkCreateInstance) fp_get_proc_addr(NULL, "vkCreateInstance");
1304 if (!fp_create_inst) {
1305 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Couldn't get vkCreateInstance via vk_icdGetInstanceProcAddr from ICD");
1306 return;
1307 }
1308 fp_get_inst_ext_props = (PFN_vkEnumerateInstanceExtensionProperties)fp_get_proc_addr(NULL, "vkEnumerateInstanceExtensionProperties");
1309 if (!fp_get_inst_ext_props) {
1310 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Couldn't get vkEnumerateInstanceExtensionProperties via vk_icdGetInstanceProcAddr from ICD");
1311 return;
1312 }
Jon Ashburn6b689942016-01-07 09:44:27 -07001313 }
Jon Ashburn14275da2015-01-28 11:01:35 -07001314
Jon Ashburn754f1992015-08-18 18:04:47 -06001315 // check for enough capacity
1316 if ((icd_libs->count * sizeof(struct loader_scanned_icds)) >= icd_libs->capacity) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06001317
1318 icd_libs->list = loader_heap_realloc(inst,
1319 icd_libs->list,
1320 icd_libs->capacity,
1321 icd_libs->capacity * 2,
Chia-I Wu1f851912015-10-27 18:04:07 +08001322 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn754f1992015-08-18 18:04:47 -06001323 // double capacity
1324 icd_libs->capacity *= 2;
Jon Ashburn14275da2015-01-28 11:01:35 -07001325 }
Jon Ashburn754f1992015-08-18 18:04:47 -06001326 new_node = &(icd_libs->list[icd_libs->count]);
Jon Ashburn14275da2015-01-28 11:01:35 -07001327
1328 new_node->handle = handle;
Jon Ashburn0083b222015-11-17 17:35:40 -07001329 new_node->api_version = api_version;
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001330 new_node->GetInstanceProcAddr = fp_get_proc_addr;
Jon Ashburn6b689942016-01-07 09:44:27 -07001331 new_node->EnumerateInstanceExtensionProperties = fp_get_inst_ext_props;
Jon Ashburn3336df82015-01-29 15:45:51 -07001332 new_node->CreateInstance = fp_create_inst;
Jon Ashburn14275da2015-01-28 11:01:35 -07001333
Jon Ashburne58f1a32015-08-28 13:38:21 -06001334 new_node->lib_name = (char *) loader_heap_alloc(inst,
1335 strlen(filename) + 1,
Chia-I Wu1f851912015-10-27 18:04:07 +08001336 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001337 if (!new_node->lib_name) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001338 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0, "Out of memory can't add icd");
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06001339 return;
1340 }
1341 strcpy(new_node->lib_name, filename);
Jon Ashburn754f1992015-08-18 18:04:47 -06001342 icd_libs->count++;
Jon Ashburneb2728b2015-04-10 14:33:07 -06001343}
Ian Elliott81ac44c2015-01-13 17:52:38 -07001344
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001345static bool loader_icd_init_entrys(struct loader_icd *icd,
1346 VkInstance inst,
1347 const PFN_vkGetInstanceProcAddr fp_gipa)
Jon Ashburn0dd356d2015-05-14 12:43:38 -06001348{
1349 /* initialize entrypoint function pointers */
1350
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001351 #define LOOKUP_GIPA(func, required) do { \
1352 icd->func = (PFN_vk ##func) fp_gipa(inst, "vk" #func); \
1353 if (!icd->func && required) { \
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001354 loader_log((struct loader_instance *) inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0, \
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001355 loader_platform_get_proc_address_error("vk" #func)); \
1356 return false; \
1357 } \
Jon Ashburn0dd356d2015-05-14 12:43:38 -06001358 } while (0)
1359
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001360 LOOKUP_GIPA(GetDeviceProcAddr, true);
1361 LOOKUP_GIPA(DestroyInstance, true);
1362 LOOKUP_GIPA(EnumeratePhysicalDevices, true);
1363 LOOKUP_GIPA(GetPhysicalDeviceFeatures, true);
1364 LOOKUP_GIPA(GetPhysicalDeviceFormatProperties, true);
Jon Ashburn4e189562015-07-23 18:49:07 -06001365 LOOKUP_GIPA(GetPhysicalDeviceImageFormatProperties, true);
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001366 LOOKUP_GIPA(CreateDevice, true);
1367 LOOKUP_GIPA(GetPhysicalDeviceProperties, true);
1368 LOOKUP_GIPA(GetPhysicalDeviceMemoryProperties, true);
Cody Northropef72e2a2015-08-03 17:04:53 -06001369 LOOKUP_GIPA(GetPhysicalDeviceQueueFamilyProperties, true);
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -06001370 LOOKUP_GIPA(EnumerateDeviceExtensionProperties, true);
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001371 LOOKUP_GIPA(GetPhysicalDeviceSparseImageFormatProperties, true);
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001372 LOOKUP_GIPA(CreateDebugReportCallbackEXT, false);
1373 LOOKUP_GIPA(DestroyDebugReportCallbackEXT, false);
Ian Elliott338dedb2015-08-21 15:09:33 -06001374 LOOKUP_GIPA(GetPhysicalDeviceSurfaceSupportKHR, false);
Ian Elliott8cda1802015-11-19 16:05:09 -07001375 LOOKUP_GIPA(GetPhysicalDeviceSurfaceCapabilitiesKHR, false);
1376 LOOKUP_GIPA(GetPhysicalDeviceSurfaceFormatsKHR, false);
1377 LOOKUP_GIPA(GetPhysicalDeviceSurfacePresentModesKHR, false);
Ian Elliott4e309e92015-11-24 15:39:10 -07001378#ifdef VK_USE_PLATFORM_WIN32_KHR
1379 LOOKUP_GIPA(GetPhysicalDeviceWin32PresentationSupportKHR, false);
1380#endif
1381#ifdef VK_USE_PLATFORM_XCB_KHR
1382 LOOKUP_GIPA(GetPhysicalDeviceXcbPresentationSupportKHR, false);
1383#endif
Jon Ashburn0dd356d2015-05-14 12:43:38 -06001384
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001385#undef LOOKUP_GIPA
Ian Elliott1d73e662015-07-06 14:36:13 -06001386
Jon Ashburnce7e3d92015-07-16 10:17:29 -06001387 return true;
Jon Ashburn0dd356d2015-05-14 12:43:38 -06001388}
1389
Courtney Goeltzenleuchter8b253f92015-06-08 15:11:18 -06001390static void loader_debug_init(void)
1391{
Jon Ashburn5b25d9f2016-01-04 14:01:38 -07001392 const char *env, *orig;
Courtney Goeltzenleuchter8b253f92015-06-08 15:11:18 -06001393
1394 if (g_loader_debug > 0)
1395 return;
1396
1397 g_loader_debug = 0;
1398
1399 /* parse comma-separated debug options */
Jon Ashburn5b25d9f2016-01-04 14:01:38 -07001400 orig = env = loader_getenv("VK_LOADER_DEBUG");
Courtney Goeltzenleuchter8b253f92015-06-08 15:11:18 -06001401 while (env) {
1402 const char *p = strchr(env, ',');
1403 size_t len;
1404
1405 if (p)
1406 len = p - env;
1407 else
1408 len = strlen(env);
1409
1410 if (len > 0) {
Michael Worcesterc21f5ad2015-12-10 18:06:24 +00001411 if (strncmp(env, "all", len) == 0) {
1412 g_loader_debug = ~0u;
1413 g_loader_log_msgs = ~0u;
1414 } else if (strncmp(env, "warn", len) == 0) {
Courtney Goeltzenleuchter8b253f92015-06-08 15:11:18 -06001415 g_loader_debug |= LOADER_WARN_BIT;
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001416 g_loader_log_msgs |= VK_DEBUG_REPORT_WARN_BIT_EXT;
Courtney Goeltzenleuchter8b253f92015-06-08 15:11:18 -06001417 } else if (strncmp(env, "info", len) == 0) {
1418 g_loader_debug |= LOADER_INFO_BIT;
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001419 g_loader_log_msgs |= VK_DEBUG_REPORT_INFO_BIT_EXT;
Courtney Goeltzenleuchter8b253f92015-06-08 15:11:18 -06001420 } else if (strncmp(env, "perf", len) == 0) {
1421 g_loader_debug |= LOADER_PERF_BIT;
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001422 g_loader_log_msgs |= VK_DEBUG_REPORT_PERF_WARN_BIT_EXT;
Courtney Goeltzenleuchter8b253f92015-06-08 15:11:18 -06001423 } else if (strncmp(env, "error", len) == 0) {
1424 g_loader_debug |= LOADER_ERROR_BIT;
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001425 g_loader_log_msgs |= VK_DEBUG_REPORT_ERROR_BIT_EXT;
Courtney Goeltzenleuchter8b253f92015-06-08 15:11:18 -06001426 } else if (strncmp(env, "debug", len) == 0) {
1427 g_loader_debug |= LOADER_DEBUG_BIT;
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001428 g_loader_log_msgs |= VK_DEBUG_REPORT_DEBUG_BIT_EXT;
Courtney Goeltzenleuchter8b253f92015-06-08 15:11:18 -06001429 }
1430 }
1431
1432 if (!p)
1433 break;
1434
1435 env = p + 1;
1436 }
Jon Ashburn5b25d9f2016-01-04 14:01:38 -07001437
1438 loader_free_getenv(orig);
Courtney Goeltzenleuchter8b253f92015-06-08 15:11:18 -06001439}
1440
Jon Ashburn754f1992015-08-18 18:04:47 -06001441void loader_initialize(void)
1442{
Jon Ashburnd02fc2c2015-09-22 13:11:00 -06001443 // initialize mutexs
Jon Ashburn754f1992015-08-18 18:04:47 -06001444 loader_platform_thread_create_mutex(&loader_lock);
Jon Ashburnd02fc2c2015-09-22 13:11:00 -06001445 loader_platform_thread_create_mutex(&loader_json_lock);
Jon Ashburn754f1992015-08-18 18:04:47 -06001446
1447 // initialize logging
1448 loader_debug_init();
Jon Ashburn413d6582015-08-28 15:19:27 -06001449
1450 // initial cJSON to use alloc callbacks
1451 cJSON_Hooks alloc_fns = {
1452 .malloc_fn = loader_tls_heap_alloc,
1453 .free_fn = loader_tls_heap_free,
1454 };
1455 cJSON_InitHooks(&alloc_fns);
Jon Ashburn754f1992015-08-18 18:04:47 -06001456}
1457
Jon Ashburnffd5d672015-06-29 11:25:34 -06001458struct loader_manifest_files {
1459 uint32_t count;
1460 char **filename_list;
1461};
1462
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06001463/**
Jon Ashburnffd5d672015-06-29 11:25:34 -06001464 * Get next file or dirname given a string list or registry key path
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06001465 *
1466 * \returns
Jon Ashburnffd5d672015-06-29 11:25:34 -06001467 * A pointer to first char in the next path.
1468 * The next path (or NULL) in the list is returned in next_path.
1469 * Note: input string is modified in some cases. PASS IN A COPY!
1470 */
Jon Ashburnffd5d672015-06-29 11:25:34 -06001471static char *loader_get_next_path(char *path)
1472{
1473 uint32_t len;
1474 char *next;
1475
1476 if (path == NULL)
1477 return NULL;
1478 next = strchr(path, PATH_SEPERATOR);
1479 if (next == NULL) {
1480 len = (uint32_t) strlen(path);
1481 next = path + len;
1482 }
1483 else {
1484 *next = '\0';
1485 next++;
1486 }
1487
1488 return next;
1489}
1490
1491/**
Daniel Dadap2e13fca2015-09-30 11:50:51 -05001492 * Given a path which is absolute or relative, expand the path if relative or
1493 * leave the path unmodified if absolute. The base path to prepend to relative
1494 * paths is given in rel_base.
Jon Ashburn38144502015-07-07 15:06:25 -06001495 *
1496 * \returns
1497 * A string in out_fullpath of the full absolute path
Jon Ashburn38144502015-07-07 15:06:25 -06001498 */
1499static void loader_expand_path(const char *path,
1500 const char *rel_base,
1501 size_t out_size,
1502 char *out_fullpath)
1503{
1504 if (loader_platform_is_path_absolute(path)) {
Daniel Dadap2e13fca2015-09-30 11:50:51 -05001505 // do not prepend a base to an absolute path
1506 rel_base = "";
Jon Ashburn38144502015-07-07 15:06:25 -06001507 }
Daniel Dadap2e13fca2015-09-30 11:50:51 -05001508
1509 loader_platform_combine_path(out_fullpath, out_size, rel_base, path, NULL);
Jon Ashburn38144502015-07-07 15:06:25 -06001510}
1511
1512/**
Jon Ashburnffd5d672015-06-29 11:25:34 -06001513 * Given a filename (file) and a list of paths (dir), try to find an existing
1514 * file in the paths. If filename already is a path then no
1515 * searching in the given paths.
1516 *
1517 * \returns
1518 * A string in out_fullpath of either the full path or file.
Jon Ashburnffd5d672015-06-29 11:25:34 -06001519 */
1520static void loader_get_fullpath(const char *file,
Daniel Dadap2e13fca2015-09-30 11:50:51 -05001521 const char *dirs,
Jon Ashburnffd5d672015-06-29 11:25:34 -06001522 size_t out_size,
1523 char *out_fullpath)
1524{
Daniel Dadap2e13fca2015-09-30 11:50:51 -05001525 if (!loader_platform_is_path(file) && *dirs) {
1526 char *dirs_copy, *dir, *next_dir;
1527
1528 dirs_copy = loader_stack_alloc(strlen(dirs) + 1);
1529 strcpy(dirs_copy, dirs);
1530
1531 //find if file exists after prepending paths in given list
1532 for (dir = dirs_copy;
1533 *dir && (next_dir = loader_get_next_path(dir));
1534 dir = next_dir) {
1535 loader_platform_combine_path(out_fullpath, out_size, dir, file, NULL);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001536 if (loader_platform_file_exists(out_fullpath)) {
1537 return;
1538 }
Jon Ashburnffd5d672015-06-29 11:25:34 -06001539 }
1540 }
Daniel Dadap2e13fca2015-09-30 11:50:51 -05001541
Jon Ashburnffd5d672015-06-29 11:25:34 -06001542 snprintf(out_fullpath, out_size, "%s", file);
1543}
1544
1545/**
1546 * Read a JSON file into a buffer.
1547 *
1548 * \returns
1549 * A pointer to a cJSON object representing the JSON parse tree.
1550 * This returned buffer should be freed by caller.
1551 */
Courtney Goeltzenleuchter05525da2015-12-03 13:48:01 -07001552static cJSON *loader_get_json(const struct loader_instance *inst, const char *filename)
Jon Ashburnffd5d672015-06-29 11:25:34 -06001553{
1554 FILE *file;
1555 char *json_buf;
1556 cJSON *json;
1557 uint64_t len;
1558 file = fopen(filename,"rb");
Jon Ashburna01fb3e2015-08-27 08:30:50 -06001559 if (!file) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001560 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Couldn't open JSON file %s", filename);
Jon Ashburna01fb3e2015-08-27 08:30:50 -06001561 return NULL;
1562 }
Jon Ashburnffd5d672015-06-29 11:25:34 -06001563 fseek(file, 0, SEEK_END);
1564 len = ftell(file);
1565 fseek(file, 0, SEEK_SET);
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -06001566 json_buf = (char*) loader_stack_alloc(len+1);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001567 if (json_buf == NULL) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001568 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 -06001569 fclose(file);
1570 return NULL;
1571 }
1572 if (fread(json_buf, sizeof(char), len, file) != len) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001573 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "fread failed can't get JSON file");
Jon Ashburnffd5d672015-06-29 11:25:34 -06001574 fclose(file);
1575 return NULL;
1576 }
1577 fclose(file);
1578 json_buf[len] = '\0';
1579
1580 //parse text from file
1581 json = cJSON_Parse(json_buf);
1582 if (json == NULL)
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001583 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Can't parse JSON file %s", filename);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001584 return json;
1585}
1586
1587/**
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06001588 * Do a deep copy of the loader_layer_properties structure.
1589 */
1590static void loader_copy_layer_properties(
Jon Ashburne58f1a32015-08-28 13:38:21 -06001591 const struct loader_instance *inst,
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06001592 struct loader_layer_properties *dst,
1593 struct loader_layer_properties *src)
1594{
Jon Ashburn738136f2015-12-10 18:17:34 -07001595 uint32_t cnt, i;
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06001596 memcpy(dst, src, sizeof (*src));
Jon Ashburne58f1a32015-08-28 13:38:21 -06001597 dst->instance_extension_list.list = loader_heap_alloc(
1598 inst,
1599 sizeof(VkExtensionProperties) *
1600 src->instance_extension_list.count,
Chia-I Wu1f851912015-10-27 18:04:07 +08001601 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburne58f1a32015-08-28 13:38:21 -06001602 dst->instance_extension_list.capacity = sizeof(VkExtensionProperties) *
1603 src->instance_extension_list.count;
1604 memcpy(dst->instance_extension_list.list, src->instance_extension_list.list,
1605 dst->instance_extension_list.capacity);
1606 dst->device_extension_list.list = loader_heap_alloc(
1607 inst,
Jon Ashburn738136f2015-12-10 18:17:34 -07001608 sizeof(struct loader_dev_ext_props) *
Jon Ashburne58f1a32015-08-28 13:38:21 -06001609 src->device_extension_list.count,
Chia-I Wu1f851912015-10-27 18:04:07 +08001610 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn738136f2015-12-10 18:17:34 -07001611
1612 dst->device_extension_list.capacity = sizeof(struct loader_dev_ext_props) *
Jon Ashburne58f1a32015-08-28 13:38:21 -06001613 src->device_extension_list.count;
1614 memcpy(dst->device_extension_list.list, src->device_extension_list.list,
1615 dst->device_extension_list.capacity);
Jon Ashburn738136f2015-12-10 18:17:34 -07001616 if (src->device_extension_list.count > 0 &&
1617 src->device_extension_list.list->entrypoint_count > 0) {
1618 cnt = src->device_extension_list.list->entrypoint_count;
1619 dst->device_extension_list.list->entrypoints = loader_heap_alloc(
1620 inst,
1621 sizeof(char *) * cnt,
1622 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
1623 for (i = 0; i < cnt; i++) {
1624 dst->device_extension_list.list->entrypoints[i] = loader_heap_alloc(
1625 inst,
1626 strlen(src->device_extension_list.list->entrypoints[i]) + 1,
1627 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
1628 strcpy(dst->device_extension_list.list->entrypoints[i],
1629 src->device_extension_list.list->entrypoints[i]);
1630 }
1631 }
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06001632}
1633
1634/**
Jon Ashburn1b111de2015-07-06 15:40:35 -06001635 * Given a cJSON struct (json) of the top level JSON object from layer manifest
1636 * file, add entry to the layer_list.
Jon Ashburn8e4fab42015-08-03 17:19:30 -06001637 * Fill out the layer_properties in this list entry from the input cJSON object.
Jon Ashburn1b111de2015-07-06 15:40:35 -06001638 *
1639 * \returns
1640 * void
1641 * layer_list has a new entry and initialized accordingly.
1642 * If the json input object does not have all the required fields no entry
1643 * is added to the list.
1644 */
Jon Ashburne58f1a32015-08-28 13:38:21 -06001645static void loader_add_layer_properties(const struct loader_instance *inst,
1646 struct loader_layer_list *layer_instance_list,
Jon Ashburn0bf6a182015-07-16 17:19:31 -06001647 struct loader_layer_list *layer_device_list,
Jon Ashburn1b111de2015-07-06 15:40:35 -06001648 cJSON *json,
1649 bool is_implicit,
1650 char *filename)
1651{
1652 /* Fields in layer manifest file that are required:
1653 * (required) “file_format_version”
1654 * following are required in the "layer" object:
1655 * (required) "name"
1656 * (required) "type"
1657 * (required) “library_path”
Jon Ashburn44fe0062015-11-18 16:46:48 -07001658 * (required) “api_version”
Jon Ashburn1b111de2015-07-06 15:40:35 -06001659 * (required) “implementation_version”
1660 * (required) “description”
1661 * (required for implicit layers) “disable_environment”
1662 *
1663 * First get all required items and if any missing abort
1664 */
1665
1666 cJSON *item, *layer_node, *ext_item;
1667 char *temp;
Jon Ashburn44fe0062015-11-18 16:46:48 -07001668 char *name, *type, *library_path, *api_version;
Jon Ashburn1b111de2015-07-06 15:40:35 -06001669 char *implementation_version, *description;
1670 cJSON *disable_environment;
Jon Ashburn738136f2015-12-10 18:17:34 -07001671 int i, j;
Jon Ashburnc4748dc2015-08-04 11:14:18 -06001672 VkExtensionProperties ext_prop;
Jon Ashburn1b111de2015-07-06 15:40:35 -06001673 item = cJSON_GetObjectItem(json, "file_format_version");
1674 if (item == NULL) {
1675 return;
1676 }
1677 char *file_vers = cJSON_PrintUnformatted(item);
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001678 loader_log(inst, VK_DEBUG_REPORT_INFO_BIT_EXT, 0, "Found manifest file %s, version %s",
Jon Ashburn1b111de2015-07-06 15:40:35 -06001679 filename, file_vers);
Jon Ashburn44fe0062015-11-18 16:46:48 -07001680 if (strcmp(file_vers, "\"1.0.0\"") != 0)
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001681 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 -06001682 loader_tls_heap_free(file_vers);
Jon Ashburn1b111de2015-07-06 15:40:35 -06001683
Jon Ashburn1b111de2015-07-06 15:40:35 -06001684 layer_node = cJSON_GetObjectItem(json, "layer");
1685 if (layer_node == NULL) {
Jon Ashburnd2c905c2015-12-17 17:38:24 -07001686 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 -06001687 return;
1688 }
Jon Ashburn082569b2015-08-12 16:39:32 -06001689
1690 // loop through all "layer" objects in the file
1691 do {
Jon Ashburn1b111de2015-07-06 15:40:35 -06001692#define GET_JSON_OBJECT(node, var) { \
1693 var = cJSON_GetObjectItem(node, #var); \
Jon Ashburn082569b2015-08-12 16:39:32 -06001694 if (var == NULL) { \
1695 layer_node = layer_node->next; \
Jon Ashburnd2c905c2015-12-17 17:38:24 -07001696 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0,\
1697 "Didn't find required layer object %s in manifest JSON file, skipping this layer",\
1698 #var); \
Jon Ashburn082569b2015-08-12 16:39:32 -06001699 continue; \
1700 } \
Jon Ashburn1b111de2015-07-06 15:40:35 -06001701 }
1702#define GET_JSON_ITEM(node, var) { \
1703 item = cJSON_GetObjectItem(node, #var); \
Jon Ashburn082569b2015-08-12 16:39:32 -06001704 if (item == NULL) { \
1705 layer_node = layer_node->next; \
Jon Ashburnd2c905c2015-12-17 17:38:24 -07001706 loader_log(inst, VK_DEBUG_REPORT_WARN_BIT_EXT, 0,\
1707 "Didn't find required layer value %s in manifest JSON file, skipping this layer",\
1708 #var); \
Jon Ashburn082569b2015-08-12 16:39:32 -06001709 continue; \
1710 } \
Jon Ashburn1b111de2015-07-06 15:40:35 -06001711 temp = cJSON_Print(item); \
1712 temp[strlen(temp) - 1] = '\0'; \
Jon Ashburn0b728052015-08-04 10:22:33 -06001713 var = loader_stack_alloc(strlen(temp) + 1); \
Jon Ashburn1b111de2015-07-06 15:40:35 -06001714 strcpy(var, &temp[1]); \
Jon Ashburn413d6582015-08-28 15:19:27 -06001715 loader_tls_heap_free(temp); \
Jon Ashburn1b111de2015-07-06 15:40:35 -06001716 }
Jon Ashburn082569b2015-08-12 16:39:32 -06001717 GET_JSON_ITEM(layer_node, name)
1718 GET_JSON_ITEM(layer_node, type)
1719 GET_JSON_ITEM(layer_node, library_path)
Jon Ashburn44fe0062015-11-18 16:46:48 -07001720 GET_JSON_ITEM(layer_node, api_version)
Jon Ashburn082569b2015-08-12 16:39:32 -06001721 GET_JSON_ITEM(layer_node, implementation_version)
1722 GET_JSON_ITEM(layer_node, description)
1723 if (is_implicit) {
1724 GET_JSON_OBJECT(layer_node, disable_environment)
1725 }
Jon Ashburn1b111de2015-07-06 15:40:35 -06001726#undef GET_JSON_ITEM
1727#undef GET_JSON_OBJECT
1728
Jon Ashburn082569b2015-08-12 16:39:32 -06001729 // add list entry
Jon Ashburnb8605fe2015-09-18 12:53:16 -06001730 struct loader_layer_properties *props=NULL;
Jon Ashburn082569b2015-08-12 16:39:32 -06001731 if (!strcmp(type, "DEVICE")) {
1732 if (layer_device_list == NULL) {
1733 layer_node = layer_node->next;
1734 continue;
1735 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06001736 props = loader_get_next_layer_property(inst, layer_device_list);
Jon Ashburn082569b2015-08-12 16:39:32 -06001737 props->type = (is_implicit) ? VK_LAYER_TYPE_DEVICE_IMPLICIT : VK_LAYER_TYPE_DEVICE_EXPLICIT;
1738 }
1739 if (!strcmp(type, "INSTANCE")) {
1740 if (layer_instance_list == NULL) {
1741 layer_node = layer_node->next;
1742 continue;
1743 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06001744 props = loader_get_next_layer_property(inst, layer_instance_list);
Jon Ashburn082569b2015-08-12 16:39:32 -06001745 props->type = (is_implicit) ? VK_LAYER_TYPE_INSTANCE_IMPLICIT : VK_LAYER_TYPE_INSTANCE_EXPLICIT;
1746 }
1747 if (!strcmp(type, "GLOBAL")) {
1748 if (layer_instance_list != NULL)
Jon Ashburne58f1a32015-08-28 13:38:21 -06001749 props = loader_get_next_layer_property(inst, layer_instance_list);
Jon Ashburn082569b2015-08-12 16:39:32 -06001750 else if (layer_device_list != NULL)
Jon Ashburne58f1a32015-08-28 13:38:21 -06001751 props = loader_get_next_layer_property(inst, layer_device_list);
Jon Ashburn082569b2015-08-12 16:39:32 -06001752 else {
1753 layer_node = layer_node->next;
1754 continue;
1755 }
1756 props->type = (is_implicit) ? VK_LAYER_TYPE_GLOBAL_IMPLICIT : VK_LAYER_TYPE_GLOBAL_EXPLICIT;
1757 }
Jon Ashburn0bf6a182015-07-16 17:19:31 -06001758
Jon Ashburnb8605fe2015-09-18 12:53:16 -06001759 if (props == NULL) {
1760 layer_node = layer_node->next;
1761 continue;
1762 }
1763
Jon Ashburn082569b2015-08-12 16:39:32 -06001764 strncpy(props->info.layerName, name, sizeof (props->info.layerName));
1765 props->info.layerName[sizeof (props->info.layerName) - 1] = '\0';
Jon Ashburn38144502015-07-07 15:06:25 -06001766
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06001767 char *fullpath = props->lib_name;
Jon Ashburn082569b2015-08-12 16:39:32 -06001768 char *rel_base;
Jon Ashburnfc8f38d2015-12-01 17:11:02 -07001769 if (loader_platform_is_path(library_path)) {
Jon Ashburn082569b2015-08-12 16:39:32 -06001770 // a relative or absolute path
Daniel Dadap2e13fca2015-09-30 11:50:51 -05001771 char *name_copy = loader_stack_alloc(strlen(filename) + 1);
Jon Ashburn082569b2015-08-12 16:39:32 -06001772 strcpy(name_copy, filename);
1773 rel_base = loader_platform_dirname(name_copy);
Jon Ashburn082569b2015-08-12 16:39:32 -06001774 loader_expand_path(library_path, rel_base, MAX_STRING_SIZE, fullpath);
Daniel Dadap2e13fca2015-09-30 11:50:51 -05001775 } else {
1776 // a filename which is assumed in a system directory
1777 loader_get_fullpath(library_path, DEFAULT_VK_LAYERS_PATH, MAX_STRING_SIZE, fullpath);
Jon Ashburn082569b2015-08-12 16:39:32 -06001778 }
Jon Ashburn44fe0062015-11-18 16:46:48 -07001779 props->info.specVersion = loader_make_version(api_version);
1780 props->info.implementationVersion = atoi(implementation_version);
Jon Ashburn082569b2015-08-12 16:39:32 -06001781 strncpy((char *) props->info.description, description, sizeof (props->info.description));
1782 props->info.description[sizeof (props->info.description) - 1] = '\0';
1783 if (is_implicit) {
1784 strncpy(props->disable_env_var.name, disable_environment->child->string, sizeof (props->disable_env_var.name));
1785 props->disable_env_var.name[sizeof (props->disable_env_var.name) - 1] = '\0';
1786 strncpy(props->disable_env_var.value, disable_environment->child->valuestring, sizeof (props->disable_env_var.value));
1787 props->disable_env_var.value[sizeof (props->disable_env_var.value) - 1] = '\0';
1788 }
Jon Ashburn1b111de2015-07-06 15:40:35 -06001789
Jon Ashburn082569b2015-08-12 16:39:32 -06001790 /**
1791 * Now get all optional items and objects and put in list:
1792 * functions
1793 * instance_extensions
1794 * device_extensions
1795 * enable_environment (implicit layers only)
1796 */
Jon Ashburn1b111de2015-07-06 15:40:35 -06001797#define GET_JSON_OBJECT(node, var) { \
1798 var = cJSON_GetObjectItem(node, #var); \
1799 }
1800#define GET_JSON_ITEM(node, var) { \
1801 item = cJSON_GetObjectItem(node, #var); \
Jon Ashburn2db08042015-09-09 11:29:24 -06001802 if (item != NULL) { \
Jon Ashburn1b111de2015-07-06 15:40:35 -06001803 temp = cJSON_Print(item); \
Jon Ashburn2db08042015-09-09 11:29:24 -06001804 temp[strlen(temp) - 1] = '\0'; \
1805 var = loader_stack_alloc(strlen(temp) + 1);\
1806 strcpy(var, &temp[1]); \
1807 loader_tls_heap_free(temp); \
1808 } \
Jon Ashburn1b111de2015-07-06 15:40:35 -06001809 }
1810
Jon Ashburn082569b2015-08-12 16:39:32 -06001811 cJSON *instance_extensions, *device_extensions, *functions, *enable_environment;
Jon Ashburn738136f2015-12-10 18:17:34 -07001812 cJSON *entrypoints;
1813 char *vkGetInstanceProcAddr, *vkGetDeviceProcAddr, *spec_version;
1814 char **entry_array;
1815 vkGetInstanceProcAddr = NULL;
1816 vkGetDeviceProcAddr = NULL;
1817 spec_version = NULL;
1818 entrypoints = NULL;
1819 entry_array = NULL;
1820 /**
1821 * functions
1822 * vkGetInstanceProcAddr
1823 * vkGetDeviceProcAddr
1824 */
Jon Ashburn082569b2015-08-12 16:39:32 -06001825 GET_JSON_OBJECT(layer_node, functions)
1826 if (functions != NULL) {
1827 GET_JSON_ITEM(functions, vkGetInstanceProcAddr)
1828 GET_JSON_ITEM(functions, vkGetDeviceProcAddr)
Jon Ashburn2db08042015-09-09 11:29:24 -06001829 if (vkGetInstanceProcAddr != NULL)
1830 strncpy(props->functions.str_gipa, vkGetInstanceProcAddr, sizeof (props->functions.str_gipa));
Jon Ashburn082569b2015-08-12 16:39:32 -06001831 props->functions.str_gipa[sizeof (props->functions.str_gipa) - 1] = '\0';
Jon Ashburn2db08042015-09-09 11:29:24 -06001832 if (vkGetDeviceProcAddr != NULL)
1833 strncpy(props->functions.str_gdpa, vkGetDeviceProcAddr, sizeof (props->functions.str_gdpa));
Jon Ashburn082569b2015-08-12 16:39:32 -06001834 props->functions.str_gdpa[sizeof (props->functions.str_gdpa) - 1] = '\0';
Jon Ashburn1b111de2015-07-06 15:40:35 -06001835 }
Jon Ashburn738136f2015-12-10 18:17:34 -07001836 /**
1837 * instance_extensions
1838 * array of
1839 * name
1840 * spec_version
1841 */
Jon Ashburn082569b2015-08-12 16:39:32 -06001842 GET_JSON_OBJECT(layer_node, instance_extensions)
1843 if (instance_extensions != NULL) {
1844 int count = cJSON_GetArraySize(instance_extensions);
1845 for (i = 0; i < count; i++) {
1846 ext_item = cJSON_GetArrayItem(instance_extensions, i);
1847 GET_JSON_ITEM(ext_item, name)
Jon Ashburn44fe0062015-11-18 16:46:48 -07001848 GET_JSON_ITEM(ext_item, spec_version)
Jon Ashburn738136f2015-12-10 18:17:34 -07001849 if (name != NULL) {
Jon Ashburn8f6be302015-12-10 08:51:10 -07001850 strncpy(ext_prop.extensionName, name, sizeof (ext_prop.extensionName));
1851 ext_prop.extensionName[sizeof (ext_prop.extensionName) - 1] = '\0';
Jon Ashburn738136f2015-12-10 18:17:34 -07001852 }
Jon Ashburn44fe0062015-11-18 16:46:48 -07001853 ext_prop.specVersion = atoi(spec_version);
Jon Ashburne58f1a32015-08-28 13:38:21 -06001854 loader_add_to_ext_list(inst, &props->instance_extension_list, 1, &ext_prop);
Jon Ashburn082569b2015-08-12 16:39:32 -06001855 }
Jon Ashburn1b111de2015-07-06 15:40:35 -06001856 }
Jon Ashburn738136f2015-12-10 18:17:34 -07001857 /**
1858 * device_extensions
1859 * array of
1860 * name
1861 * spec_version
1862 * entrypoints
1863 */
Jon Ashburn082569b2015-08-12 16:39:32 -06001864 GET_JSON_OBJECT(layer_node, device_extensions)
1865 if (device_extensions != NULL) {
1866 int count = cJSON_GetArraySize(device_extensions);
1867 for (i = 0; i < count; i++) {
1868 ext_item = cJSON_GetArrayItem(device_extensions, i);
Jon Ashburn738136f2015-12-10 18:17:34 -07001869 GET_JSON_ITEM(ext_item, name)
1870 GET_JSON_ITEM(ext_item, spec_version)
1871 if (name != NULL) {
Jon Ashburn8f6be302015-12-10 08:51:10 -07001872 strncpy(ext_prop.extensionName, name, sizeof (ext_prop.extensionName));
1873 ext_prop.extensionName[sizeof (ext_prop.extensionName) - 1] = '\0';
Jon Ashburn738136f2015-12-10 18:17:34 -07001874 }
Jon Ashburn44fe0062015-11-18 16:46:48 -07001875 ext_prop.specVersion = atoi(spec_version);
Jon Ashburn738136f2015-12-10 18:17:34 -07001876 //entrypoints = cJSON_GetObjectItem(ext_item, "entrypoints");
1877 GET_JSON_OBJECT(ext_item, entrypoints)
1878 int entry_count;
1879 if (entrypoints == NULL)
1880 continue;
1881 entry_count = cJSON_GetArraySize(entrypoints);
1882 if (entry_count)
1883 entry_array = (char **) loader_stack_alloc(sizeof(char *) * entry_count);
1884 for (j = 0; j < entry_count; j++) {
1885 ext_item = cJSON_GetArrayItem(entrypoints, j);
1886 if (ext_item != NULL) {
1887 temp = cJSON_Print(ext_item);
1888 temp[strlen(temp) - 1] = '\0';
1889 entry_array[j] = loader_stack_alloc(strlen(temp) + 1);
1890 strcpy(entry_array[j], &temp[1]);
1891 loader_tls_heap_free(temp);
Jon Ashburn8f6be302015-12-10 08:51:10 -07001892 }
1893 }
Jon Ashburn738136f2015-12-10 18:17:34 -07001894 loader_add_to_dev_ext_list(inst, &props->device_extension_list,
1895 &ext_prop, entry_count, entry_array);
1896 }
1897 }
Jon Ashburn082569b2015-08-12 16:39:32 -06001898 if (is_implicit) {
1899 GET_JSON_OBJECT(layer_node, enable_environment)
Jon Ashburnd2c905c2015-12-17 17:38:24 -07001900
1901 // enable_environment is optional
1902 if (enable_environment) {
1903 strncpy(props->enable_env_var.name, enable_environment->child->string, sizeof (props->enable_env_var.name));
1904 props->enable_env_var.name[sizeof (props->enable_env_var.name) - 1] = '\0';
1905 strncpy(props->enable_env_var.value, enable_environment->child->valuestring, sizeof (props->enable_env_var.value));
1906 props->enable_env_var.value[sizeof (props->enable_env_var.value) - 1] = '\0';
1907 }
Jon Ashburn082569b2015-08-12 16:39:32 -06001908 }
Jon Ashburn1b111de2015-07-06 15:40:35 -06001909#undef GET_JSON_ITEM
1910#undef GET_JSON_OBJECT
Jon Ashburn082569b2015-08-12 16:39:32 -06001911 // for global layers need to add them to both device and instance list
1912 if (!strcmp(type, "GLOBAL")) {
1913 struct loader_layer_properties *dev_props;
1914 if (layer_instance_list == NULL || layer_device_list == NULL) {
1915 layer_node = layer_node->next;
1916 continue;
1917 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06001918 dev_props = loader_get_next_layer_property(inst, layer_device_list);
Jon Ashburn082569b2015-08-12 16:39:32 -06001919 //copy into device layer list
Jon Ashburne58f1a32015-08-28 13:38:21 -06001920 loader_copy_layer_properties(inst, dev_props, props);
Jon Ashburn082569b2015-08-12 16:39:32 -06001921 }
1922 layer_node = layer_node->next;
1923 } while (layer_node != NULL);
1924 return;
Jon Ashburn1b111de2015-07-06 15:40:35 -06001925}
1926
1927/**
Jon Ashburnffd5d672015-06-29 11:25:34 -06001928 * Find the Vulkan library manifest files.
1929 *
1930 * This function scans the location or env_override directories/files
1931 * for a list of JSON manifest files. If env_override is non-NULL
1932 * and has a valid value. Then the location is ignored. Otherwise
1933 * location is used to look for manifest files. The location
1934 * is interpreted as Registry path on Windows and a directory path(s)
1935 * on Linux.
1936 *
1937 * \returns
1938 * A string list of manifest files to be opened in out_files param.
1939 * List has a pointer to string for each manifest filename.
1940 * When done using the list in out_files, pointers should be freed.
Jon Ashburnee33ae72015-06-30 14:46:22 -07001941 * Location or override string lists can be either files or directories as follows:
1942 * | location | override
1943 * --------------------------------
1944 * Win ICD | files | files
1945 * Win Layer | files | dirs
1946 * Linux ICD | dirs | files
1947 * Linux Layer| dirs | dirs
Jon Ashburnffd5d672015-06-29 11:25:34 -06001948 */
Jon Ashburne58f1a32015-08-28 13:38:21 -06001949static void loader_get_manifest_files(const struct loader_instance *inst,
1950 const char *env_override,
Jon Ashburnee33ae72015-06-30 14:46:22 -07001951 bool is_layer,
1952 const char *location,
1953 struct loader_manifest_files *out_files)
Jon Ashburnffd5d672015-06-29 11:25:34 -06001954{
1955 char *override = NULL;
1956 char *loc;
1957 char *file, *next_file, *name;
1958 size_t alloced_count = 64;
1959 char full_path[2048];
1960 DIR *sysdir = NULL;
Jon Ashburnee33ae72015-06-30 14:46:22 -07001961 bool list_is_dirs = false;
Jon Ashburnffd5d672015-06-29 11:25:34 -06001962 struct dirent *dent;
1963
1964 out_files->count = 0;
1965 out_files->filename_list = NULL;
1966
Jon Ashburn5b25d9f2016-01-04 14:01:38 -07001967 if (env_override != NULL && (override = loader_getenv(env_override))) {
Johannes van Waverena6ce7b72015-10-28 11:45:00 -05001968#if !defined(_WIN32)
Jon Ashburnffd5d672015-06-29 11:25:34 -06001969 if (geteuid() != getuid()) {
Jon Ashburnee33ae72015-06-30 14:46:22 -07001970 /* Don't allow setuid apps to use the env var: */
Jon Ashburn5b25d9f2016-01-04 14:01:38 -07001971 loader_free_getenv(override);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001972 override = NULL;
1973 }
1974#endif
1975 }
1976
1977 if (location == NULL) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001978 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburnee33ae72015-06-30 14:46:22 -07001979 "Can't get manifest files with NULL location, env_override=%s",
1980 env_override);
Jon Ashburnffd5d672015-06-29 11:25:34 -06001981 return;
1982 }
1983
Johannes van Waverena6ce7b72015-10-28 11:45:00 -05001984#if defined(_WIN32)
Jon Ashburnee33ae72015-06-30 14:46:22 -07001985 list_is_dirs = (is_layer && override != NULL) ? true : false;
Johannes van Waverena6ce7b72015-10-28 11:45:00 -05001986#else
1987 list_is_dirs = (override == NULL || is_layer) ? true : false;
Jon Ashburnee33ae72015-06-30 14:46:22 -07001988#endif
Jon Ashburnffd5d672015-06-29 11:25:34 -06001989 // Make a copy of the input we are using so it is not modified
Jon Ashburnee33ae72015-06-30 14:46:22 -07001990 // Also handle getting the location(s) from registry on Windows
1991 if (override == NULL) {
Jon Ashburncdc9f0a2015-07-31 10:11:24 -06001992 loc = loader_stack_alloc(strlen(location) + 1);
Jon Ashburnee33ae72015-06-30 14:46:22 -07001993 if (loc == NULL) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07001994 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 -07001995 return;
1996 }
1997 strcpy(loc, location);
Johannes van Waverena6ce7b72015-10-28 11:45:00 -05001998#if defined(_WIN32)
Jon Ashburn6fb9a532015-08-28 14:58:46 -07001999 loc = loader_get_registry_files(inst, loc);
Jon Ashburnc1381ed2015-07-31 09:33:21 -06002000 if (loc == NULL) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002001 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 -06002002 return;
2003 }
Jon Ashburnee33ae72015-06-30 14:46:22 -07002004#endif
Jon Ashburnffd5d672015-06-29 11:25:34 -06002005 }
Jon Ashburnee33ae72015-06-30 14:46:22 -07002006 else {
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -06002007 loc = loader_stack_alloc(strlen(override) + 1);
Jon Ashburnee33ae72015-06-30 14:46:22 -07002008 if (loc == NULL) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002009 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 -07002010 return;
2011 }
2012 strcpy(loc, override);
Jon Ashburn5b25d9f2016-01-04 14:01:38 -07002013 loader_free_getenv(override);
Jon Ashburnee33ae72015-06-30 14:46:22 -07002014 }
Jon Ashburnffd5d672015-06-29 11:25:34 -06002015
Liam Middlebrookf2a6ec42015-07-23 18:32:20 -07002016 // Print out the paths being searched if debugging is enabled
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002017 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 -07002018
Jon Ashburnffd5d672015-06-29 11:25:34 -06002019 file = loc;
2020 while (*file) {
2021 next_file = loader_get_next_path(file);
Jon Ashburnee33ae72015-06-30 14:46:22 -07002022 if (list_is_dirs) {
Jon Ashburnffd5d672015-06-29 11:25:34 -06002023 sysdir = opendir(file);
2024 name = NULL;
2025 if (sysdir) {
2026 dent = readdir(sysdir);
2027 if (dent == NULL)
2028 break;
2029 name = &(dent->d_name[0]);
2030 loader_get_fullpath(name, file, sizeof(full_path), full_path);
2031 name = full_path;
2032 }
2033 }
2034 else {
Johannes van Waverena6ce7b72015-10-28 11:45:00 -05002035#if defined(_WIN32)
2036 name = file;
2037#else
Jon Ashburnee33ae72015-06-30 14:46:22 -07002038 // only Linux has relative paths
Jon Ashburnffd5d672015-06-29 11:25:34 -06002039 char *dir;
2040 // make a copy of location so it isn't modified
Jason Ekstrand35fa1a12015-10-10 08:33:37 -07002041 dir = loader_stack_alloc(strlen(loc) + 1);
Jon Ashburnffd5d672015-06-29 11:25:34 -06002042 if (dir == NULL) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002043 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 -06002044 return;
2045 }
Jason Ekstrand35fa1a12015-10-10 08:33:37 -07002046 strcpy(dir, loc);
Jon Ashburnffd5d672015-06-29 11:25:34 -06002047
2048 loader_get_fullpath(file, dir, sizeof(full_path), full_path);
2049
2050 name = full_path;
Jon Ashburnee33ae72015-06-30 14:46:22 -07002051#endif
Jon Ashburnffd5d672015-06-29 11:25:34 -06002052 }
2053 while (name) {
2054 /* Look for files ending with ".json" suffix */
2055 uint32_t nlen = (uint32_t) strlen(name);
2056 const char *suf = name + nlen - 5;
2057 if ((nlen > 5) && !strncmp(suf, ".json", 5)) {
2058 if (out_files->count == 0) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06002059 out_files->filename_list = loader_heap_alloc(inst,
2060 alloced_count * sizeof(char *),
Chia-I Wu5eca31f2015-10-31 00:31:16 +08002061 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
Jon Ashburnffd5d672015-06-29 11:25:34 -06002062 }
2063 else if (out_files->count == alloced_count) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06002064 out_files->filename_list = loader_heap_realloc(inst,
2065 out_files->filename_list,
2066 alloced_count * sizeof(char *),
2067 alloced_count * sizeof(char *) * 2,
Chia-I Wu5eca31f2015-10-31 00:31:16 +08002068 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
Jon Ashburnffd5d672015-06-29 11:25:34 -06002069 alloced_count *= 2;
2070 }
2071 if (out_files->filename_list == NULL) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002072 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 -06002073 return;
2074 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06002075 out_files->filename_list[out_files->count] = loader_heap_alloc(
2076 inst,
2077 strlen(name) + 1,
Chia-I Wu5eca31f2015-10-31 00:31:16 +08002078 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
Jon Ashburnffd5d672015-06-29 11:25:34 -06002079 if (out_files->filename_list[out_files->count] == NULL) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002080 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 -06002081 return;
2082 }
2083 strcpy(out_files->filename_list[out_files->count], name);
2084 out_files->count++;
Jon Ashburnc5662f62015-07-02 10:08:47 -06002085 } else if (!list_is_dirs) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002086 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 -06002087 }
Jon Ashburnee33ae72015-06-30 14:46:22 -07002088 if (list_is_dirs) {
Jon Ashburnffd5d672015-06-29 11:25:34 -06002089 dent = readdir(sysdir);
2090 if (dent == NULL)
2091 break;
2092 name = &(dent->d_name[0]);
2093 loader_get_fullpath(name, file, sizeof(full_path), full_path);
2094 name = full_path;
2095 }
2096 else {
2097 break;
2098 }
2099 }
2100 if (sysdir)
2101 closedir(sysdir);
2102 file = next_file;
2103 }
2104 return;
2105}
2106
Jon Ashburn754f1992015-08-18 18:04:47 -06002107void loader_init_icd_lib_list()
2108{
2109
2110}
2111
2112void loader_destroy_icd_lib_list()
2113{
2114
2115}
Jon Ashburnffd5d672015-06-29 11:25:34 -06002116/**
2117 * Try to find the Vulkan ICD driver(s).
2118 *
2119 * This function scans the default system loader path(s) or path
2120 * specified by the \c VK_ICD_FILENAMES environment variable in
2121 * order to find loadable VK ICDs manifest files. From these
2122 * manifest files it finds the ICD libraries.
2123 *
2124 * \returns
Jon Ashburn754f1992015-08-18 18:04:47 -06002125 * a list of icds that were discovered
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06002126 */
Jon Ashburne58f1a32015-08-28 13:38:21 -06002127void loader_icd_scan(
2128 const struct loader_instance *inst,
2129 struct loader_icd_libs *icds)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08002130{
Jon Ashburnffd5d672015-06-29 11:25:34 -06002131 char *file_str;
2132 struct loader_manifest_files manifest_files;
2133
Jon Ashburne58f1a32015-08-28 13:38:21 -06002134 loader_scanned_icd_init(inst, icds);
Jon Ashburnffd5d672015-06-29 11:25:34 -06002135 // Get a list of manifest files for ICDs
Jon Ashburne58f1a32015-08-28 13:38:21 -06002136 loader_get_manifest_files(inst, "VK_ICD_FILENAMES", false,
2137 DEFAULT_VK_DRIVERS_INFO, &manifest_files);
Jon Ashburn1b111de2015-07-06 15:40:35 -06002138 if (manifest_files.count == 0)
2139 return;
Jon Ashburnd02fc2c2015-09-22 13:11:00 -06002140 loader_platform_thread_lock_mutex(&loader_json_lock);
Jon Ashburnffd5d672015-06-29 11:25:34 -06002141 for (uint32_t i = 0; i < manifest_files.count; i++) {
2142 file_str = manifest_files.filename_list[i];
2143 if (file_str == NULL)
2144 continue;
2145
Jon Ashburn1b111de2015-07-06 15:40:35 -06002146 cJSON *json;
Courtney Goeltzenleuchter05525da2015-12-03 13:48:01 -07002147 json = loader_get_json(inst, file_str);
Jon Ashburna01fb3e2015-08-27 08:30:50 -06002148 if (!json)
2149 continue;
Jon Ashburn0083b222015-11-17 17:35:40 -07002150 cJSON *item, *itemICD;
Jon Ashburn1b111de2015-07-06 15:40:35 -06002151 item = cJSON_GetObjectItem(json, "file_format_version");
Jon Ashburnd02fc2c2015-09-22 13:11:00 -06002152 if (item == NULL) {
2153 loader_platform_thread_unlock_mutex(&loader_json_lock);
Jon Ashburn1b111de2015-07-06 15:40:35 -06002154 return;
Jon Ashburnd02fc2c2015-09-22 13:11:00 -06002155 }
Jon Ashburn1b111de2015-07-06 15:40:35 -06002156 char *file_vers = cJSON_Print(item);
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002157 loader_log(inst, VK_DEBUG_REPORT_INFO_BIT_EXT, 0, "Found manifest file %s, version %s",
Jon Ashburn1b111de2015-07-06 15:40:35 -06002158 file_str, file_vers);
2159 if (strcmp(file_vers, "\"1.0.0\"") != 0)
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002160 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 -06002161 loader_tls_heap_free(file_vers);
Jon Ashburn0083b222015-11-17 17:35:40 -07002162 itemICD = cJSON_GetObjectItem(json, "ICD");
2163 if (itemICD != NULL) {
2164 item = cJSON_GetObjectItem(itemICD, "library_path");
Jon Ashburn1b111de2015-07-06 15:40:35 -06002165 if (item != NULL) {
Jon Ashburn10442c12015-08-25 16:48:24 -06002166 char *temp= cJSON_Print(item);
2167 if (!temp || strlen(temp) == 0) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002168 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 -06002169 loader_tls_heap_free(temp);
Jon Ashburne58f1a32015-08-28 13:38:21 -06002170 loader_heap_free(inst, file_str);
Jon Ashburn10442c12015-08-25 16:48:24 -06002171 cJSON_Delete(json);
2172 continue;
Jon Ashburnffd5d672015-06-29 11:25:34 -06002173 }
Jon Ashburn10442c12015-08-25 16:48:24 -06002174 //strip out extra quotes
2175 temp[strlen(temp) - 1] = '\0';
2176 char *library_path = loader_stack_alloc(strlen(temp) + 1);
2177 strcpy(library_path, &temp[1]);
Jon Ashburn413d6582015-08-28 15:19:27 -06002178 loader_tls_heap_free(temp);
Jon Ashburn10442c12015-08-25 16:48:24 -06002179 if (!library_path || strlen(library_path) == 0) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002180 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 -06002181 loader_heap_free(inst, file_str);
Jon Ashburn10442c12015-08-25 16:48:24 -06002182 cJSON_Delete(json);
2183 continue;
2184 }
Daniel Dadap2e13fca2015-09-30 11:50:51 -05002185 char fullpath[MAX_STRING_SIZE];
Jon Ashburn10442c12015-08-25 16:48:24 -06002186 // Print out the paths being searched if debugging is enabled
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002187 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 -05002188 if (loader_platform_is_path(library_path)) {
Jon Ashburn10442c12015-08-25 16:48:24 -06002189 // a relative or absolute path
Daniel Dadap2e13fca2015-09-30 11:50:51 -05002190 char *name_copy = loader_stack_alloc(strlen(file_str) + 1);
2191 char *rel_base;
Jon Ashburn10442c12015-08-25 16:48:24 -06002192 strcpy(name_copy, file_str);
2193 rel_base = loader_platform_dirname(name_copy);
Daniel Dadap2e13fca2015-09-30 11:50:51 -05002194 loader_expand_path(library_path, rel_base, sizeof(fullpath), fullpath);
2195 } else {
2196 // a filename which is assumed in a system directory
2197 loader_get_fullpath(library_path, DEFAULT_VK_DRIVERS_PATH, sizeof(fullpath), fullpath);
Jon Ashburn10442c12015-08-25 16:48:24 -06002198 }
Jon Ashburn0083b222015-11-17 17:35:40 -07002199
2200 uint32_t vers = 0;
2201 item = cJSON_GetObjectItem(itemICD, "api_version");
2202 if (item != NULL) {
2203 temp= cJSON_Print(item);
2204 vers = loader_make_version(temp);
2205 loader_tls_heap_free(temp);
2206 }
2207 loader_scanned_icd_add(inst, icds, fullpath, vers);
Jon Ashburnffd5d672015-06-29 11:25:34 -06002208 }
Jon Ashburn0083b222015-11-17 17:35:40 -07002209 else
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002210 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 -06002211 }
2212 else
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002213 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 -06002214
Jon Ashburne58f1a32015-08-28 13:38:21 -06002215 loader_heap_free(inst, file_str);
Jon Ashburnffd5d672015-06-29 11:25:34 -06002216 cJSON_Delete(json);
2217 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06002218 loader_heap_free(inst, manifest_files.filename_list);
Jon Ashburnd02fc2c2015-09-22 13:11:00 -06002219 loader_platform_thread_unlock_mutex(&loader_json_lock);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08002220}
2221
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002222
Jon Ashburne58f1a32015-08-28 13:38:21 -06002223void loader_layer_scan(
2224 const struct loader_instance *inst,
2225 struct loader_layer_list *instance_layers,
2226 struct loader_layer_list *device_layers)
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002227{
Jon Ashburn1b111de2015-07-06 15:40:35 -06002228 char *file_str;
Jon Ashburnd2c905c2015-12-17 17:38:24 -07002229 struct loader_manifest_files manifest_files[2]; // [0] = explicit, [1] = implicit
Jon Ashburn1b111de2015-07-06 15:40:35 -06002230 cJSON *json;
2231 uint32_t i;
Jon Ashburnd2c905c2015-12-17 17:38:24 -07002232 uint32_t implicit;
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002233
Jon Ashburn1b111de2015-07-06 15:40:35 -06002234 // Get a list of manifest files for layers
Jon Ashburnd2c905c2015-12-17 17:38:24 -07002235 loader_get_manifest_files(inst, LAYERS_PATH_ENV, true, DEFAULT_VK_ELAYERS_INFO,
2236 &manifest_files[0]);
Jon Ashburnec71e112015-12-24 13:58:35 -07002237 // Pass NULL for environment variable override - implicit layers are not overridden by LAYERS_PATH_ENV
2238 loader_get_manifest_files(inst, NULL, true, DEFAULT_VK_ILAYERS_INFO,
Jon Ashburnd2c905c2015-12-17 17:38:24 -07002239 &manifest_files[1]);
2240 if (manifest_files[0].count == 0 && manifest_files[1].count == 0)
Courtney Goeltzenleuchterbce445a2014-12-01 09:29:42 -07002241 return;
Jon Ashburn0dcd6192015-06-04 15:30:58 -06002242
Jon Ashburn8e4fab42015-08-03 17:19:30 -06002243#if 0 //TODO
Jon Ashburn1b111de2015-07-06 15:40:35 -06002244 /**
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -06002245 * We need a list of the layer libraries, not just a list of
2246 * the layer properties (a layer library could expose more than
2247 * one layer property). This list of scanned layers would be
2248 * used to check for global and physicaldevice layer properties.
2249 */
2250 if (!loader_init_layer_library_list(&loader.scanned_layer_libraries)) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002251 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburne58f1a32015-08-28 13:38:21 -06002252 "Alloc for layer list failed: %s line: %d", __FILE__, __LINE__);
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -06002253 return;
Jon Ashburn68a63922015-07-02 09:40:15 -06002254 }
Jon Ashburn1b111de2015-07-06 15:40:35 -06002255#endif
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002256
Jon Ashburn8e4fab42015-08-03 17:19:30 -06002257 /* cleanup any previously scanned libraries */
Jon Ashburne58f1a32015-08-28 13:38:21 -06002258 loader_delete_layer_properties(inst, instance_layers);
2259 loader_delete_layer_properties(inst, device_layers);
Jon Ashburn0bf6a182015-07-16 17:19:31 -06002260
Jon Ashburnd02fc2c2015-09-22 13:11:00 -06002261 loader_platform_thread_lock_mutex(&loader_json_lock);
Jon Ashburnd2c905c2015-12-17 17:38:24 -07002262 for (implicit = 0; implicit < 2; implicit++) {
2263 for (i = 0; i < manifest_files[implicit].count; i++) {
2264 file_str = manifest_files[implicit].filename_list[i];
2265 if (file_str == NULL)
2266 continue;
Courtney Goeltzenleuchteraa685052015-06-01 14:49:17 -06002267
Jon Ashburnd2c905c2015-12-17 17:38:24 -07002268 // parse file into JSON struct
2269 json = loader_get_json(inst, file_str);
2270 if (!json) {
2271 continue;
2272 }
2273
2274 //TODO error if device layers expose instance_extensions
2275 //TODO error if instance layers expose device extensions
2276 loader_add_layer_properties(inst,
2277 instance_layers,
2278 device_layers,
2279 json,
2280 (implicit == 1),
2281 file_str);
2282
2283 loader_heap_free(inst, file_str);
2284 cJSON_Delete(json);
Jon Ashburn1b111de2015-07-06 15:40:35 -06002285 }
Jon Ashburn1b111de2015-07-06 15:40:35 -06002286 }
Jon Ashburnd2c905c2015-12-17 17:38:24 -07002287 if (manifest_files[0].count != 0)
2288 loader_heap_free(inst, manifest_files[0].filename_list);
2289
2290 if (manifest_files[1].count != 0)
2291 loader_heap_free(inst, manifest_files[1].filename_list);
Jon Ashburnd02fc2c2015-09-22 13:11:00 -06002292 loader_platform_thread_unlock_mutex(&loader_json_lock);
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002293}
2294
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +08002295static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL loader_gpa_instance_internal(VkInstance inst, const char * pName)
Jon Ashburnfce93d92015-05-12 17:26:48 -06002296{
2297 // inst is not wrapped
2298 if (inst == VK_NULL_HANDLE) {
2299 return NULL;
2300 }
2301 VkLayerInstanceDispatchTable* disp_table = * (VkLayerInstanceDispatchTable **) inst;
2302 void *addr;
2303
Jon Ashburn4f2575f2015-05-28 16:25:02 -06002304 if (!strcmp(pName, "vkGetInstanceProcAddr"))
2305 return (void *) loader_gpa_instance_internal;
2306
Jon Ashburnfce93d92015-05-12 17:26:48 -06002307 if (disp_table == NULL)
2308 return NULL;
2309
2310 addr = loader_lookup_instance_dispatch_table(disp_table, pName);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002311 if (addr) {
Jon Ashburnfce93d92015-05-12 17:26:48 -06002312 return addr;
Jon Ashburne18431b2015-04-13 18:10:06 -06002313 }
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002314
2315 if (disp_table->GetInstanceProcAddr == NULL) {
2316 return NULL;
2317 }
2318 return disp_table->GetInstanceProcAddr(inst, pName);
Jon Ashburne18431b2015-04-13 18:10:06 -06002319}
2320
Jon Ashburn429e19f2015-11-17 15:31:02 -07002321/**
2322 * Initialize device_ext dispatch table entry as follows:
2323 * If dev == NULL find all logical devices created within this instance and
2324 * init the entry (given by idx) in the ext dispatch table.
2325 * If dev != NULL only initialize the entry in the given dev's dispatch table.
2326 * The initialization value is gotten by calling down the device chain with GDPA.
2327 * If GDPA returns NULL then don't initialize the dispatch table entry.
2328 */
2329static void loader_init_dispatch_dev_ext_entry(struct loader_instance *inst,
2330 struct loader_device *dev,
2331 uint32_t idx,
2332 const char *funcName)
2333
2334 {
2335 void *gdpa_value;
2336 if (dev != NULL) {
2337 gdpa_value = dev->loader_dispatch.core_dispatch.GetDeviceProcAddr(
2338 dev->device, funcName);
2339 if (gdpa_value != NULL)
2340 dev->loader_dispatch.ext_dispatch.DevExt[idx] = (PFN_vkDevExt) gdpa_value;
2341 } else {
2342 for (uint32_t i = 0; i < inst->total_icd_count; i++) {
2343 struct loader_icd *icd = &inst->icds[i];
2344 struct loader_device *dev = icd->logical_device_list;
2345 while (dev) {
2346 gdpa_value = dev->loader_dispatch.core_dispatch.GetDeviceProcAddr(
2347 dev->device, funcName);
2348 if (gdpa_value != NULL)
2349 dev->loader_dispatch.ext_dispatch.DevExt[idx] =
2350 (PFN_vkDevExt) gdpa_value;
2351 dev = dev->next;
2352 }
2353 }
2354 }
2355
2356}
2357
2358/**
2359 * Find all dev extension in the hash table and initialize the dispatch table
2360 * for dev for each of those extension entrypoints found in hash table.
2361
2362 */
2363static void loader_init_dispatch_dev_ext(struct loader_instance *inst,
2364 struct loader_device *dev)
2365{
2366 for (uint32_t i = 0; i < MAX_NUM_DEV_EXTS; i++) {
2367 if (inst->disp_hash[i].func_name != NULL)
2368 loader_init_dispatch_dev_ext_entry(inst, dev, i,
2369 inst->disp_hash[i].func_name);
2370 }
2371}
2372
2373static bool loader_check_icds_for_address(struct loader_instance *inst,
2374 const char *funcName)
2375{
2376 struct loader_icd *icd;
2377 icd = inst->icds;
2378 while (icd) {
2379 if (icd->this_icd_lib->GetInstanceProcAddr(icd->instance, funcName))
2380 // this icd supports funcName
2381 return true;
2382 icd = icd->next;
2383 }
2384
2385 return false;
2386}
2387
2388static void loader_free_dev_ext_table(struct loader_instance *inst)
2389{
2390 for (uint32_t i = 0; i < MAX_NUM_DEV_EXTS; i++) {
2391 loader_heap_free(inst, inst->disp_hash[i].func_name);
2392 loader_heap_free(inst, inst->disp_hash[i].list.index);
2393
2394 }
2395 memset(inst->disp_hash, 0, sizeof(inst->disp_hash));
2396}
2397
2398static bool loader_add_dev_ext_table(struct loader_instance *inst,
2399 uint32_t *ptr_idx,
2400 const char *funcName)
2401{
2402 uint32_t i;
2403 uint32_t idx = *ptr_idx;
2404 struct loader_dispatch_hash_list *list = &inst->disp_hash[idx].list;
2405
2406 if (!inst->disp_hash[idx].func_name) {
2407 // no entry here at this idx, so use it
2408 assert(list->capacity == 0);
2409 inst->disp_hash[idx].func_name = (char *) loader_heap_alloc(inst,
2410 strlen(funcName) + 1,
2411 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
2412 if (inst->disp_hash[idx].func_name == NULL) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002413 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburn429e19f2015-11-17 15:31:02 -07002414 "loader_add_dev_ext_table() can't allocate memory for func_name");
2415 return false;
2416 }
2417 strncpy(inst->disp_hash[idx].func_name, funcName, strlen(funcName) + 1);
2418 return true;
2419 }
2420
2421 // check for enough capacity
2422 if (list->capacity == 0) {
2423 list->index = loader_heap_alloc(inst, 8 * sizeof(*(list->index)),
2424 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
2425 if (list->index == NULL) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002426 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburn429e19f2015-11-17 15:31:02 -07002427 "loader_add_dev_ext_table() can't allocate list memory");
2428 return false;
2429 }
2430 list->capacity = 8 * sizeof(*(list->index));
2431 } else if (list->capacity < (list->count + 1) * sizeof(*(list->index))) {
2432 list->index = loader_heap_realloc(inst, list->index, list->capacity,
2433 list->capacity * 2,
2434 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
2435 if (list->index == NULL) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002436 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburn429e19f2015-11-17 15:31:02 -07002437 "loader_add_dev_ext_table() can't reallocate list memory");
2438 return false;
2439 }
2440 list->capacity *= 2;
2441 }
2442
2443 //find an unused index in the hash table and use it
2444 i = (idx + 1) % MAX_NUM_DEV_EXTS;
2445 do {
2446 if (!inst->disp_hash[i].func_name) {
2447 assert(inst->disp_hash[i].list.capacity == 0);
2448 inst->disp_hash[i].func_name = (char *) loader_heap_alloc(inst,
2449 strlen(funcName) + 1,
2450 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
2451 if (inst->disp_hash[i].func_name == NULL) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002452 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburn429e19f2015-11-17 15:31:02 -07002453 "loader_add_dev_ext_table() can't rallocate func_name memory");
2454 return false;
2455 }
2456 strncpy(inst->disp_hash[i].func_name, funcName, strlen(funcName) + 1);
2457 list->index[list->count] = i;
2458 list->count++;
2459 *ptr_idx = i;
2460 return true;
2461 }
2462 i = (i + 1) % MAX_NUM_DEV_EXTS;
2463 } while (i != idx);
2464
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002465 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburn429e19f2015-11-17 15:31:02 -07002466 "loader_add_dev_ext_table() couldn't insert into hash table; is it full?");
2467 return false;
2468}
2469
2470static bool loader_name_in_dev_ext_table(struct loader_instance *inst,
2471 uint32_t *idx,
2472 const char *funcName)
2473{
2474 uint32_t alt_idx;
2475 if (inst->disp_hash[*idx].func_name && !strcmp(
2476 inst->disp_hash[*idx].func_name,
2477 funcName))
2478 return true;
2479
2480 // funcName wasn't at the primary spot in the hash table
2481 // search the list of secondary locations (shallow search, not deep search)
2482 for (uint32_t i = 0; i < inst->disp_hash[*idx].list.count; i++) {
2483 alt_idx = inst->disp_hash[*idx].list.index[i];
2484 if (!strcmp(inst->disp_hash[*idx].func_name, funcName)) {
2485 *idx = alt_idx;
2486 return true;
2487 }
2488 }
2489
2490 return false;
2491}
2492
2493/**
2494 * This function returns generic trampoline code address for unknown entry points.
2495 * Presumably, these unknown entry points (as given by funcName) are device
2496 * extension entrypoints. A hash table is used to keep a list of unknown entry
2497 * points and their mapping to the device extension dispatch table
2498 * (struct loader_dev_ext_dispatch_table).
2499 * \returns
2500 * For a given entry point string (funcName), if an existing mapping is found the
2501 * trampoline address for that mapping is returned. Otherwise, this unknown entry point
2502 * has not been seen yet. Next check if a layer or ICD supports it. If so then a
2503 * new entry in the hash table is initialized and that trampoline address for
2504 * the new entry is returned. Null is returned if the hash table is full or
2505 * if no discovered layer or ICD returns a non-NULL GetProcAddr for it.
2506 */
2507void *loader_dev_ext_gpa(struct loader_instance *inst,
2508 const char *funcName)
2509{
2510 uint32_t idx;
2511 uint32_t seed = 0;
2512
2513 idx = murmurhash(funcName, strlen(funcName), seed) % MAX_NUM_DEV_EXTS;
2514
2515 if (loader_name_in_dev_ext_table(inst, &idx, funcName))
2516 // found funcName already in hash
2517 return loader_get_dev_ext_trampoline(idx);
2518
2519 // Check if funcName is supported in either ICDs or a layer library
2520 if (!loader_check_icds_for_address(inst, funcName)) {
2521 // TODO Add check in layer libraries for support of address
2522 // if support found in layers continue on
2523 return NULL;
2524 }
2525
2526 if (loader_add_dev_ext_table(inst, &idx, funcName)) {
2527 // successfully added new table entry
2528 // init any dev dispatch table entrys as needed
2529 loader_init_dispatch_dev_ext_entry(inst, NULL, idx, funcName);
2530 return loader_get_dev_ext_trampoline(idx);
2531 }
2532
2533 return NULL;
2534}
2535
Jon Ashburn0c5eea22015-09-30 12:56:42 -06002536struct loader_instance *loader_get_instance(const VkInstance instance)
2537{
2538 /* look up the loader_instance in our list by comparing dispatch tables, as
2539 * there is no guarantee the instance is still a loader_instance* after any
2540 * layers which wrap the instance object.
2541 */
2542 const VkLayerInstanceDispatchTable *disp;
2543 struct loader_instance *ptr_instance = NULL;
2544 disp = loader_get_instance_dispatch(instance);
2545 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
2546 if (inst->disp == disp) {
2547 ptr_instance = inst;
2548 break;
2549 }
2550 }
2551 return ptr_instance;
2552}
2553
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002554static loader_platform_dl_handle loader_add_layer_lib(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002555 const struct loader_instance *inst,
Jon Ashburn9a9de1f2015-05-27 13:19:22 -06002556 const char *chain_type,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002557 struct loader_layer_properties *layer_prop)
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002558{
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002559 struct loader_lib_info *new_layer_lib_list, *my_lib;
Jon Ashburne58f1a32015-08-28 13:38:21 -06002560 size_t new_alloc_size;
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -06002561 /*
2562 * TODO: We can now track this information in the
2563 * scanned_layer_libraries list.
2564 */
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002565 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) {
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002566 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, layer_prop->lib_name) == 0) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002567 /* Have already loaded this library, just increment ref count */
2568 loader.loaded_layer_lib_list[i].ref_count++;
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002569 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002570 "%s Chain: Increment layer reference count for layer library %s",
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002571 chain_type, layer_prop->lib_name);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002572 return loader.loaded_layer_lib_list[i].lib_handle;
2573 }
2574 }
2575
2576 /* Haven't seen this library so load it */
Jon Ashburne58f1a32015-08-28 13:38:21 -06002577 new_alloc_size = 0;
2578 if (loader.loaded_layer_lib_capacity == 0)
2579 new_alloc_size = 8 * sizeof(struct loader_lib_info);
2580 else if (loader.loaded_layer_lib_capacity <= loader.loaded_layer_lib_count *
2581 sizeof(struct loader_lib_info))
2582 new_alloc_size = loader.loaded_layer_lib_capacity * 2;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002583
Jon Ashburne58f1a32015-08-28 13:38:21 -06002584 if (new_alloc_size) {
2585 new_layer_lib_list = loader_heap_realloc(
2586 inst, loader.loaded_layer_lib_list,
2587 loader.loaded_layer_lib_capacity,
2588 new_alloc_size,
Chia-I Wu1f851912015-10-27 18:04:07 +08002589 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburne58f1a32015-08-28 13:38:21 -06002590 if (!new_layer_lib_list) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002591 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 -06002592 return NULL;
2593 }
2594 loader.loaded_layer_lib_capacity = new_alloc_size;
Courtney Goeltzenleuchter65e31cc2015-12-09 12:26:34 -07002595 loader.loaded_layer_lib_list = new_layer_lib_list;
Jon Ashburne58f1a32015-08-28 13:38:21 -06002596 } else
2597 new_layer_lib_list = loader.loaded_layer_lib_list;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002598 my_lib = &new_layer_lib_list[loader.loaded_layer_lib_count];
2599
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002600 strncpy(my_lib->lib_name, layer_prop->lib_name, sizeof(my_lib->lib_name));
2601 my_lib->lib_name[sizeof(my_lib->lib_name) - 1] = '\0';
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002602 my_lib->ref_count = 0;
2603 my_lib->lib_handle = NULL;
2604
2605 if ((my_lib->lib_handle = loader_platform_open_library(my_lib->lib_name)) == NULL) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002606 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002607 loader_platform_open_library_error(my_lib->lib_name));
2608 return NULL;
2609 } else {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002610 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002611 "Chain: %s: Loading layer library %s",
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002612 chain_type, layer_prop->lib_name);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002613 }
2614 loader.loaded_layer_lib_count++;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002615 my_lib->ref_count++;
2616
2617 return my_lib->lib_handle;
2618}
2619
2620static void loader_remove_layer_lib(
2621 struct loader_instance *inst,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002622 struct loader_layer_properties *layer_prop)
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002623{
Courtney Goeltzenleuchter46724972015-12-17 09:51:22 -07002624 uint32_t idx = loader.loaded_layer_lib_count;
Tony Barbour9687cb12015-07-14 13:34:05 -06002625 struct loader_lib_info *new_layer_lib_list, *my_lib = NULL;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002626
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002627 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) {
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002628 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, layer_prop->lib_name) == 0) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002629 /* found matching library */
2630 idx = i;
2631 my_lib = &loader.loaded_layer_lib_list[i];
2632 break;
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002633 }
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002634 }
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002635
Courtney Goeltzenleuchter46724972015-12-17 09:51:22 -07002636 if (idx == loader.loaded_layer_lib_count) {
Jon Ashburndb68e4b2015-12-17 14:30:21 -07002637 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Courtney Goeltzenleuchter46724972015-12-17 09:51:22 -07002638 "Unable to unref library %s", layer_prop->lib_name);
2639 return;
2640 }
2641
Tony Barbour9687cb12015-07-14 13:34:05 -06002642 if (my_lib) {
2643 my_lib->ref_count--;
2644 if (my_lib->ref_count > 0) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002645 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002646 "Decrement reference count for layer library %s", layer_prop->lib_name);
Tony Barbour9687cb12015-07-14 13:34:05 -06002647 return;
2648 }
Courtney Goeltzenleuchter0199e952015-02-27 15:19:33 -07002649 }
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002650 loader_platform_close_library(my_lib->lib_handle);
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002651 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0,
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002652 "Unloading layer library %s", layer_prop->lib_name);
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002653
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002654 /* Need to remove unused library from list */
Jon Ashburne58f1a32015-08-28 13:38:21 -06002655 new_layer_lib_list = loader_heap_alloc(inst,
2656 loader.loaded_layer_lib_capacity,
Chia-I Wu1f851912015-10-27 18:04:07 +08002657 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002658 if (!new_layer_lib_list) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002659 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 -06002660 return;
2661 }
2662
2663 if (idx > 0) {
2664 /* Copy records before idx */
2665 memcpy(new_layer_lib_list, &loader.loaded_layer_lib_list[0],
2666 sizeof(struct loader_lib_info) * idx);
2667 }
2668 if (idx < (loader.loaded_layer_lib_count - 1)) {
2669 /* Copy records after idx */
2670 memcpy(&new_layer_lib_list[idx], &loader.loaded_layer_lib_list[idx+1],
2671 sizeof(struct loader_lib_info) * (loader.loaded_layer_lib_count - idx - 1));
2672 }
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002673
Jon Ashburne58f1a32015-08-28 13:38:21 -06002674 loader_heap_free(inst, loader.loaded_layer_lib_list);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002675 loader.loaded_layer_lib_count--;
2676 loader.loaded_layer_lib_list = new_layer_lib_list;
Jon Ashburnead95c52014-11-18 09:06:04 -07002677}
2678
Jon Ashburn1b111de2015-07-06 15:40:35 -06002679
2680/**
2681 * Go through the search_list and find any layers which match type. If layer
2682 * type match is found in then add it to ext_list.
2683 */
Jon Ashburn535bd002015-07-02 16:10:32 -06002684static void loader_add_layer_implicit(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002685 const struct loader_instance *inst,
Jon Ashburn535bd002015-07-02 16:10:32 -06002686 const enum layer_type type,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002687 struct loader_layer_list *list,
Jon Ashburn182b8302015-08-11 14:49:54 -06002688 const struct loader_layer_list *search_list)
Jon Ashburn535bd002015-07-02 16:10:32 -06002689{
Jon Ashburnd2c905c2015-12-17 17:38:24 -07002690 bool enable;
2691 char *env_value;
Jon Ashburn535bd002015-07-02 16:10:32 -06002692 uint32_t i;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002693 for (i = 0; i < search_list->count; i++) {
2694 const struct loader_layer_properties *prop = &search_list->list[i];
Jon Ashburn535bd002015-07-02 16:10:32 -06002695 if (prop->type & type) {
Jon Ashburnd2c905c2015-12-17 17:38:24 -07002696 /* Found an implicit layer, see if it should be enabled */
2697 enable = false;
2698
2699 // if no enable_environment variable is specified, this implicit layer
2700 // should always be enabled. Otherwise check if the variable is set
2701 if (prop->enable_env_var.name[0] == 0) {
2702 enable = true;
2703 } else {
Jon Ashburn5b25d9f2016-01-04 14:01:38 -07002704 env_value = loader_getenv(prop->enable_env_var.name);
Jon Ashburnd2c905c2015-12-17 17:38:24 -07002705 if (env_value && !strcmp(prop->enable_env_var.value, env_value))
2706 enable = true;
Jon Ashburn5b25d9f2016-01-04 14:01:38 -07002707 loader_free_getenv(env_value);
Jon Ashburnd2c905c2015-12-17 17:38:24 -07002708 }
2709
2710 // disable_environment has priority, i.e. if both enable and disable
2711 // environment variables are set, the layer is disabled. Implicit layers
2712 // are required to have a disable_environment variables
Jon Ashburn5b25d9f2016-01-04 14:01:38 -07002713 env_value = loader_getenv(prop->disable_env_var.name);
Jon Ashburnd2c905c2015-12-17 17:38:24 -07002714 if (env_value)
2715 enable = false;
Jon Ashburn5b25d9f2016-01-04 14:01:38 -07002716 loader_free_getenv(env_value);
Jon Ashburnd2c905c2015-12-17 17:38:24 -07002717
2718 if (enable)
2719 loader_add_to_layer_list(inst, list, 1, prop);
Jon Ashburn535bd002015-07-02 16:10:32 -06002720 }
2721 }
2722
2723}
2724
2725/**
2726 * Get the layer name(s) from the env_name environment variable. If layer
Jon Ashburnf2ddb732015-07-07 10:27:45 -06002727 * is found in search_list then add it to layer_list. But only add it to
2728 * layer_list if type matches.
Jon Ashburn535bd002015-07-02 16:10:32 -06002729 */
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002730static void loader_add_layer_env(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002731 const struct loader_instance *inst,
Jon Ashburnf2ddb732015-07-07 10:27:45 -06002732 const enum layer_type type,
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002733 const char *env_name,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002734 struct loader_layer_list *layer_list,
2735 const struct loader_layer_list *search_list)
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002736{
Ian Elliott225188f2015-02-17 10:33:47 -07002737 char *layerEnv;
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002738 char *next, *name;
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002739
Jon Ashburn5b25d9f2016-01-04 14:01:38 -07002740 layerEnv = loader_getenv(env_name);
Ian Elliott225188f2015-02-17 10:33:47 -07002741 if (layerEnv == NULL) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002742 return;
Ian Elliott225188f2015-02-17 10:33:47 -07002743 }
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -06002744 name = loader_stack_alloc(strlen(layerEnv) + 1);
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002745 if (name == NULL) {
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002746 return;
Ian Elliott225188f2015-02-17 10:33:47 -07002747 }
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002748 strcpy(name, layerEnv);
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002749
Jon Ashburn5b25d9f2016-01-04 14:01:38 -07002750 loader_free_getenv(layerEnv);
2751
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002752 while (name && *name ) {
2753 next = loader_get_next_path(name);
Jon Ashburne58f1a32015-08-28 13:38:21 -06002754 loader_find_layer_name_add_list(inst, name, type, search_list, layer_list);
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002755 name = next;
Courtney Goeltzenleuchter0199e952015-02-27 15:19:33 -07002756 }
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002757
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002758 return;
Jon Ashburnd43f9b62014-10-14 19:15:22 -06002759}
2760
Courtney Goeltzenleuchter3d8dc1f2015-06-08 15:09:22 -06002761void loader_deactivate_instance_layers(struct loader_instance *instance)
Jon Ashburn183dfd02014-10-22 18:13:16 -06002762{
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002763 /* Create instance chain of enabled layers */
Courtney Goeltzenleuchter3d8dc1f2015-06-08 15:09:22 -06002764 for (uint32_t i = 0; i < instance->activated_layer_list.count; i++) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002765 struct loader_layer_properties *layer_prop = &instance->activated_layer_list.list[i];
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002766
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002767 loader_remove_layer_lib(instance, layer_prop);
Jon Ashburn183dfd02014-10-22 18:13:16 -06002768 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06002769 loader_destroy_layer_list(instance, &instance->activated_layer_list);
Jon Ashburn183dfd02014-10-22 18:13:16 -06002770}
2771
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002772VkResult loader_enable_instance_layers(
Jon Ashburn182b8302015-08-11 14:49:54 -06002773 struct loader_instance *inst,
2774 const VkInstanceCreateInfo *pCreateInfo,
2775 const struct loader_layer_list *instance_layers)
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002776{
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002777 VkResult err;
2778
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -06002779 assert(inst && "Cannot have null instance");
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002780
Jon Ashburne58f1a32015-08-28 13:38:21 -06002781 if (!loader_init_layer_list(inst, &inst->activated_layer_list)) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002782 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Failed to alloc Instance activated layer list");
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002783 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburn60378412015-07-02 12:59:25 -06002784 }
2785
Jon Ashburn535bd002015-07-02 16:10:32 -06002786 /* Add any implicit layers first */
2787 loader_add_layer_implicit(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002788 inst,
Jon Ashburn535bd002015-07-02 16:10:32 -06002789 VK_LAYER_TYPE_INSTANCE_IMPLICIT,
2790 &inst->activated_layer_list,
Jon Ashburn182b8302015-08-11 14:49:54 -06002791 instance_layers);
Jon Ashburn535bd002015-07-02 16:10:32 -06002792
Jon Ashburn1b111de2015-07-06 15:40:35 -06002793 /* Add any layers specified via environment variable next */
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002794 loader_add_layer_env(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002795 inst,
Jon Ashburnf2ddb732015-07-07 10:27:45 -06002796 VK_LAYER_TYPE_INSTANCE_EXPLICIT,
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002797 "VK_INSTANCE_LAYERS",
2798 &inst->activated_layer_list,
Jon Ashburn182b8302015-08-11 14:49:54 -06002799 instance_layers);
Jon Ashburn60378412015-07-02 12:59:25 -06002800
2801 /* Add layers specified by the application */
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002802 err = loader_add_layer_names_to_list(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002803 inst,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002804 &inst->activated_layer_list,
Jon Ashburna4ae48b2016-01-11 13:12:43 -07002805 pCreateInfo->enabledLayerCount,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002806 pCreateInfo->ppEnabledLayerNames,
Jon Ashburn182b8302015-08-11 14:49:54 -06002807 instance_layers);
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002808
2809 return err;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002810}
2811
Jon Ashburnfce93d92015-05-12 17:26:48 -06002812uint32_t loader_activate_instance_layers(struct loader_instance *inst)
2813{
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002814 uint32_t layer_idx;
Jon Ashburnd5df54d2015-05-28 19:16:58 -06002815 VkBaseLayerObject *wrappedInstance;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002816
David Pinedo0fab78b2015-06-24 15:29:18 -06002817 if (inst == NULL) {
Jon Ashburnfce93d92015-05-12 17:26:48 -06002818 return 0;
David Pinedo0fab78b2015-06-24 15:29:18 -06002819 }
Jon Ashburnfce93d92015-05-12 17:26:48 -06002820
2821 // NOTE inst is unwrapped at this point in time
Tony Barbourde4124d2015-07-03 10:33:54 -06002822 void* baseObj = (void*) inst;
2823 void* nextObj = (void*) inst;
Jon Ashburnfce93d92015-05-12 17:26:48 -06002824 VkBaseLayerObject *nextInstObj;
2825 PFN_vkGetInstanceProcAddr nextGPA = loader_gpa_instance_internal;
2826
Jon Ashburn60378412015-07-02 12:59:25 -06002827 if (!inst->activated_layer_list.count) {
Courtney Goeltzenleuchter33243142015-08-07 09:53:18 -06002828 loader_init_instance_core_dispatch_table(inst->disp, nextGPA, (VkInstance) nextObj, (VkInstance) baseObj);
Jon Ashburnfce93d92015-05-12 17:26:48 -06002829 return 0;
2830 }
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002831
Courtney Goeltzenleuchter0248b992015-07-06 09:04:55 -06002832 wrappedInstance = loader_stack_alloc(sizeof(VkBaseLayerObject)
Jon Ashburn60378412015-07-02 12:59:25 -06002833 * inst->activated_layer_list.count);
Jon Ashburnd5df54d2015-05-28 19:16:58 -06002834 if (!wrappedInstance) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002835 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Failed to alloc Instance objects for layer");
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002836 return 0;
2837 }
2838
2839 /* Create instance chain of enabled layers */
Jon Ashburn60378412015-07-02 12:59:25 -06002840 layer_idx = inst->activated_layer_list.count - 1;
Courtney Goeltzenleuchterf4b430e2015-06-07 17:28:17 -06002841 for (int32_t i = inst->activated_layer_list.count - 1; i >= 0; i--) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002842 struct loader_layer_properties *layer_prop = &inst->activated_layer_list.list[i];
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002843 loader_platform_dl_handle lib_handle;
2844
Jon Ashburn60378412015-07-02 12:59:25 -06002845 /*
Courtney Goeltzenleuchterc27292a2015-06-01 14:12:42 -06002846 * Note: An extension's Get*ProcAddr should not return a function pointer for
2847 * any extension entry points until the extension has been enabled.
2848 * To do this requires a different behavior from Get*ProcAddr functions implemented
2849 * in layers.
2850 * The very first call to a layer will be it's Get*ProcAddr function requesting
Tobin Ehlis84492ee2015-10-06 09:09:24 -06002851 * the layer's vkGet*ProcAddr. The layer should initialize its internal dispatch table
Courtney Goeltzenleuchterc27292a2015-06-01 14:12:42 -06002852 * with the wrapped object given (either Instance or Device) and return the layer's
2853 * Get*ProcAddr function. The layer should also use this opportunity to record the
2854 * baseObject so that it can find the correct local dispatch table on future calls.
2855 * Subsequent calls to Get*ProcAddr, CreateInstance, CreateDevice
2856 * will not use a wrapped object and must look up their local dispatch table from
2857 * the given baseObject.
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002858 */
Jon Ashburnd5df54d2015-05-28 19:16:58 -06002859 nextInstObj = (wrappedInstance + layer_idx);
Tony Barbourde4124d2015-07-03 10:33:54 -06002860 nextInstObj->pGPA = (PFN_vkGPA) nextGPA;
Jon Ashburnfce93d92015-05-12 17:26:48 -06002861 nextInstObj->baseObject = baseObj;
2862 nextInstObj->nextObject = nextObj;
Tony Barbourde4124d2015-07-03 10:33:54 -06002863 nextObj = (void*) nextInstObj;
Jon Ashburnfce93d92015-05-12 17:26:48 -06002864
Jon Ashburne58f1a32015-08-28 13:38:21 -06002865 lib_handle = loader_add_layer_lib(inst, "instance", layer_prop);
Jon Ashburn25a158f2015-11-25 17:55:49 -07002866 if (!lib_handle)
2867 continue; // TODO what should we do in this case
Jon Ashburn2db08042015-09-09 11:29:24 -06002868 if ((nextGPA = layer_prop->functions.get_instance_proc_addr) == NULL) {
2869 if (layer_prop->functions.str_gipa == NULL || strlen(layer_prop->functions.str_gipa) == 0) {
2870 nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetInstanceProcAddr");
2871 layer_prop->functions.get_instance_proc_addr = nextGPA;
2872 } else
2873 nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gipa);
2874 if (!nextGPA) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002875 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 -06002876
Jon Ashburn2db08042015-09-09 11:29:24 -06002877 /* TODO: Should we return nextObj, nextGPA to previous? or decrement layer_list count*/
2878 continue;
2879 }
Jon Ashburnfce93d92015-05-12 17:26:48 -06002880 }
2881
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002882 loader_log(inst, VK_DEBUG_REPORT_INFO_BIT_EXT, 0,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002883 "Insert instance layer %s (%s)",
2884 layer_prop->info.layerName,
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06002885 layer_prop->lib_name);
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002886
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002887 layer_idx--;
Jon Ashburnfce93d92015-05-12 17:26:48 -06002888 }
2889
Jon Ashburn4f2575f2015-05-28 16:25:02 -06002890 loader_init_instance_core_dispatch_table(inst->disp, nextGPA, (VkInstance) nextObj, (VkInstance) baseObj);
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002891
Jon Ashburn60378412015-07-02 12:59:25 -06002892 return inst->activated_layer_list.count;
Jon Ashburnfce93d92015-05-12 17:26:48 -06002893}
2894
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002895void loader_activate_instance_layer_extensions(struct loader_instance *inst)
2896{
2897
2898 loader_init_instance_extension_dispatch_table(inst->disp,
2899 inst->disp->GetInstanceProcAddr,
Jon Ashburnd5df54d2015-05-28 19:16:58 -06002900 (VkInstance) inst);
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06002901}
2902
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002903static VkResult loader_enable_device_layers(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002904 const struct loader_instance *inst,
Jon Ashburn182b8302015-08-11 14:49:54 -06002905 struct loader_icd *icd,
2906 struct loader_device *dev,
2907 const VkDeviceCreateInfo *pCreateInfo,
2908 const struct loader_layer_list *device_layers)
2909
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002910{
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002911 VkResult err;
2912
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -06002913 assert(dev && "Cannot have null device");
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002914
Jon Ashburn60378412015-07-02 12:59:25 -06002915 if (dev->activated_layer_list.list == NULL || dev->activated_layer_list.capacity == 0) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06002916 loader_init_layer_list(inst, &dev->activated_layer_list);
Jon Ashburn60378412015-07-02 12:59:25 -06002917 }
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002918
Jon Ashburn60378412015-07-02 12:59:25 -06002919 if (dev->activated_layer_list.list == NULL) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07002920 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Failed to alloc device activated layer list");
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002921 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburn60378412015-07-02 12:59:25 -06002922 }
2923
Jon Ashburn535bd002015-07-02 16:10:32 -06002924 /* Add any implicit layers first */
2925 loader_add_layer_implicit(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002926 inst,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002927 VK_LAYER_TYPE_DEVICE_IMPLICIT,
2928 &dev->activated_layer_list,
Jon Ashburn182b8302015-08-11 14:49:54 -06002929 device_layers);
Jon Ashburn535bd002015-07-02 16:10:32 -06002930
2931 /* Add any layers specified via environment variable next */
Jon Ashburna2e6efe2015-07-02 14:10:53 -06002932 loader_add_layer_env(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002933 inst,
Jon Ashburnf2ddb732015-07-07 10:27:45 -06002934 VK_LAYER_TYPE_DEVICE_EXPLICIT,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002935 "VK_DEVICE_LAYERS",
2936 &dev->activated_layer_list,
Jon Ashburn182b8302015-08-11 14:49:54 -06002937 device_layers);
Jon Ashburn60378412015-07-02 12:59:25 -06002938
2939 /* Add layers specified by the application */
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002940 err = loader_add_layer_names_to_list(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002941 inst,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002942 &dev->activated_layer_list,
Jon Ashburna4ae48b2016-01-11 13:12:43 -07002943 pCreateInfo->enabledLayerCount,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002944 pCreateInfo->ppEnabledLayerNames,
Jon Ashburn182b8302015-08-11 14:49:54 -06002945 device_layers);
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06002946
2947 return err;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06002948}
2949
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002950/*
Jon Ashburnc1d1eb72015-08-14 11:57:54 -06002951 * This function terminates the device chain for CreateDevice.
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06002952 * CreateDevice is a special case and so the loader call's
2953 * the ICD's CreateDevice before creating the chain. Since
2954 * we can't call CreateDevice twice we must terminate the
2955 * device chain with something else.
2956 */
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +08002957static VKAPI_ATTR VkResult VKAPI_CALL scratch_vkCreateDevice(
Jon Ashburn251258f2015-11-01 14:04:06 -07002958 VkPhysicalDevice physicalDevice,
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002959 const VkDeviceCreateInfo *pCreateInfo,
Chia-I Wu1f851912015-10-27 18:04:07 +08002960 const VkAllocationCallbacks* pAllocator,
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002961 VkDevice *pDevice)
2962{
2963 return VK_SUCCESS;
2964}
2965
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +08002966static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL loader_GetDeviceChainProcAddr(VkDevice device, const char * name)
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002967{
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002968 if (!strcmp(name, "vkGetDeviceProcAddr"))
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -06002969 return (PFN_vkVoidFunction) loader_GetDeviceChainProcAddr;
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002970 if (!strcmp(name, "vkCreateDevice"))
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -06002971 return (PFN_vkVoidFunction) scratch_vkCreateDevice;
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002972
Courtney Goeltzenleuchtere76db422015-06-29 16:09:23 -06002973 struct loader_device *found_dev;
2974 struct loader_icd *icd = loader_get_icd_and_device(device, &found_dev);
2975 return icd->GetDeviceProcAddr(device, name);
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002976}
2977
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06002978static uint32_t loader_activate_device_layers(
Jon Ashburne58f1a32015-08-28 13:38:21 -06002979 const struct loader_instance *inst,
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002980 struct loader_device *dev,
Courtney Goeltzenleuchterc5cf7d72015-07-05 12:53:31 -06002981 VkDevice device)
Jon Ashburn183dfd02014-10-22 18:13:16 -06002982{
David Pinedo0fab78b2015-06-24 15:29:18 -06002983 if (!dev) {
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06002984 return 0;
David Pinedo0fab78b2015-06-24 15:29:18 -06002985 }
Jon Ashburn612539f2015-06-10 10:13:10 -06002986
Jon Ashburn183dfd02014-10-22 18:13:16 -06002987 /* activate any layer libraries */
Tony Barbourde4124d2015-07-03 10:33:54 -06002988 void* nextObj = (void*) device;
2989 void* baseObj = nextObj;
Jon Ashburn612539f2015-06-10 10:13:10 -06002990 VkBaseLayerObject *nextGpuObj;
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002991 PFN_vkGetDeviceProcAddr nextGPA = loader_GetDeviceChainProcAddr;
Jon Ashburn612539f2015-06-10 10:13:10 -06002992 VkBaseLayerObject *wrappedGpus;
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06002993
Courtney Goeltzenleuchter33243142015-08-07 09:53:18 -06002994 if (!dev->activated_layer_list.count) {
2995 loader_init_device_dispatch_table(&dev->loader_dispatch, nextGPA,
2996 (VkDevice) nextObj, (VkDevice) baseObj);
Jon Ashburn612539f2015-06-10 10:13:10 -06002997 return 0;
Courtney Goeltzenleuchter33243142015-08-07 09:53:18 -06002998 }
Jon Ashburn612539f2015-06-10 10:13:10 -06002999
Jon Ashburne58f1a32015-08-28 13:38:21 -06003000 wrappedGpus = loader_heap_alloc(inst,
3001 sizeof (VkBaseLayerObject) * dev->activated_layer_list.count,
Chia-I Wu1f851912015-10-27 18:04:07 +08003002 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn612539f2015-06-10 10:13:10 -06003003 if (!wrappedGpus) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07003004 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "Failed to alloc Gpu objects for layer");
Jon Ashburn612539f2015-06-10 10:13:10 -06003005 return 0;
3006 }
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06003007
Jon Ashburn612539f2015-06-10 10:13:10 -06003008 for (int32_t i = dev->activated_layer_list.count - 1; i >= 0; i--) {
3009
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003010 struct loader_layer_properties *layer_prop = &dev->activated_layer_list.list[i];
Jon Ashburn612539f2015-06-10 10:13:10 -06003011 loader_platform_dl_handle lib_handle;
3012
Jon Ashburn612539f2015-06-10 10:13:10 -06003013 nextGpuObj = (wrappedGpus + i);
Tony Barbourde4124d2015-07-03 10:33:54 -06003014 nextGpuObj->pGPA = (PFN_vkGPA)nextGPA;
Jon Ashburn612539f2015-06-10 10:13:10 -06003015 nextGpuObj->baseObject = baseObj;
3016 nextGpuObj->nextObject = nextObj;
Tony Barbourde4124d2015-07-03 10:33:54 -06003017 nextObj = (void*) nextGpuObj;
Jon Ashburn612539f2015-06-10 10:13:10 -06003018
Jon Ashburne58f1a32015-08-28 13:38:21 -06003019 lib_handle = loader_add_layer_lib(inst, "device", layer_prop);
Jon Ashburn2db08042015-09-09 11:29:24 -06003020 if ((nextGPA = layer_prop->functions.get_device_proc_addr) == NULL) {
3021 if (layer_prop->functions.str_gdpa == NULL || strlen(layer_prop->functions.str_gdpa) == 0) {
3022 nextGPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetDeviceProcAddr");
3023 layer_prop->functions.get_device_proc_addr = nextGPA;
3024 } else
3025 nextGPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gdpa);
3026 if (!nextGPA) {
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07003027 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 -06003028 continue;
3029 }
Jon Ashburn612539f2015-06-10 10:13:10 -06003030 }
3031
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07003032 loader_log(inst, VK_DEBUG_REPORT_INFO_BIT_EXT, 0,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003033 "Insert device layer library %s (%s)",
3034 layer_prop->info.layerName,
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06003035 layer_prop->lib_name);
Jon Ashburn612539f2015-06-10 10:13:10 -06003036
3037 }
3038
3039 loader_init_device_dispatch_table(&dev->loader_dispatch, nextGPA,
Tony Barbourde4124d2015-07-03 10:33:54 -06003040 (VkDevice) nextObj, (VkDevice) baseObj);
Jon Ashburne58f1a32015-08-28 13:38:21 -06003041 loader_heap_free(inst, wrappedGpus);
Jon Ashburn612539f2015-06-10 10:13:10 -06003042
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06003043 return dev->activated_layer_list.count;
Jon Ashburn183dfd02014-10-22 18:13:16 -06003044}
Jon Ashburnd43f9b62014-10-14 19:15:22 -06003045
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06003046VkResult loader_validate_layers(
3047 const uint32_t layer_count,
3048 const char * const *ppEnabledLayerNames,
Jon Ashburne9ca8fa2015-08-20 16:35:30 -06003049 const struct loader_layer_list *list)
Courtney Goeltzenleuchter5d9f29b2015-07-06 17:45:08 -06003050{
3051 struct loader_layer_properties *prop;
3052
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06003053 for (uint32_t i = 0; i < layer_count; i++) {
Jon Ashburn8e4fab42015-08-03 17:19:30 -06003054 prop = loader_get_layer_property(ppEnabledLayerNames[i],
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06003055 list);
Courtney Goeltzenleuchter5d9f29b2015-07-06 17:45:08 -06003056 if (!prop) {
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -06003057 return VK_ERROR_LAYER_NOT_PRESENT;
Courtney Goeltzenleuchter5d9f29b2015-07-06 17:45:08 -06003058 }
3059 }
3060
3061 return VK_SUCCESS;
3062}
3063
3064VkResult loader_validate_instance_extensions(
Jon Ashburnc1d1eb72015-08-14 11:57:54 -06003065 const struct loader_extension_list *icd_exts,
Jon Ashburn182b8302015-08-11 14:49:54 -06003066 const struct loader_layer_list *instance_layer,
3067 const VkInstanceCreateInfo *pCreateInfo)
Courtney Goeltzenleuchter5d9f29b2015-07-06 17:45:08 -06003068{
Jon Ashburnc4748dc2015-08-04 11:14:18 -06003069 VkExtensionProperties *extension_prop;
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06003070 struct loader_layer_properties *layer_prop;
3071
Jon Ashburna4ae48b2016-01-11 13:12:43 -07003072 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06003073 extension_prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
Jon Ashburnc1d1eb72015-08-14 11:57:54 -06003074 icd_exts);
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06003075
3076 if (extension_prop) {
3077 continue;
3078 }
3079
3080 extension_prop = NULL;
3081
3082 /* Not in global list, search layer extension lists */
Jon Ashburna4ae48b2016-01-11 13:12:43 -07003083 for (uint32_t j = 0; j < pCreateInfo->enabledLayerCount; j++) {
Jon Ashburn8e4fab42015-08-03 17:19:30 -06003084 layer_prop = loader_get_layer_property(pCreateInfo->ppEnabledLayerNames[i],
Jon Ashburn182b8302015-08-11 14:49:54 -06003085 instance_layer);
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06003086 if (!layer_prop) {
Courtney Goeltzenleuchter91371ff2015-07-06 20:46:50 -06003087 /* Should NOT get here, loader_validate_layers
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06003088 * should have already filtered this case out.
3089 */
3090 continue;
3091 }
3092
3093 extension_prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
3094 &layer_prop->instance_extension_list);
3095 if (extension_prop) {
3096 /* Found the extension in one of the layers enabled by the app. */
3097 break;
3098 }
3099 }
3100
3101 if (!extension_prop) {
3102 /* Didn't find extension name in any of the global layers, error out */
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -06003103 return VK_ERROR_EXTENSION_NOT_PRESENT;
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06003104 }
3105 }
3106 return VK_SUCCESS;
3107}
3108
3109VkResult loader_validate_device_extensions(
Jon Ashburn251258f2015-11-01 14:04:06 -07003110 struct loader_physical_device *phys_dev,
Jon Ashburn182b8302015-08-11 14:49:54 -06003111 const struct loader_layer_list *device_layer,
3112 const VkDeviceCreateInfo *pCreateInfo)
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06003113{
Jon Ashburnc4748dc2015-08-04 11:14:18 -06003114 VkExtensionProperties *extension_prop;
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06003115 struct loader_layer_properties *layer_prop;
3116
Jon Ashburna4ae48b2016-01-11 13:12:43 -07003117 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06003118 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i];
3119 extension_prop = get_extension_property(extension_name,
Jon Ashburn251258f2015-11-01 14:04:06 -07003120 &phys_dev->device_extension_cache);
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06003121
3122 if (extension_prop) {
3123 continue;
3124 }
3125
3126 /* Not in global list, search layer extension lists */
Jon Ashburna4ae48b2016-01-11 13:12:43 -07003127 for (uint32_t j = 0; j < pCreateInfo->enabledLayerCount; j++) {
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06003128 const char *layer_name = pCreateInfo->ppEnabledLayerNames[j];
Jon Ashburn8e4fab42015-08-03 17:19:30 -06003129 layer_prop = loader_get_layer_property(layer_name,
Jon Ashburn182b8302015-08-11 14:49:54 -06003130 device_layer);
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06003131
3132 if (!layer_prop) {
3133 /* Should NOT get here, loader_validate_instance_layers
3134 * should have already filtered this case out.
3135 */
3136 continue;
3137 }
3138
Jon Ashburn738136f2015-12-10 18:17:34 -07003139 extension_prop = get_dev_extension_property(extension_name,
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06003140 &layer_prop->device_extension_list);
3141 if (extension_prop) {
3142 /* Found the extension in one of the layers enabled by the app. */
3143 break;
3144 }
3145 }
3146
3147 if (!extension_prop) {
3148 /* Didn't find extension name in any of the device layers, error out */
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -06003149 return VK_ERROR_EXTENSION_NOT_PRESENT;
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06003150 }
3151 }
Courtney Goeltzenleuchter5d9f29b2015-07-06 17:45:08 -06003152 return VK_SUCCESS;
3153}
3154
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +08003155VKAPI_ATTR VkResult VKAPI_CALL loader_CreateInstance(
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06003156 const VkInstanceCreateInfo* pCreateInfo,
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07003157 const VkAllocationCallbacks* pAllocator,
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06003158 VkInstance* pInstance)
Jon Ashburn349508d2015-01-26 14:51:40 -07003159{
Jon Ashburna179dcf2015-05-21 17:42:17 -06003160 struct loader_instance *ptr_instance = *(struct loader_instance **) pInstance;
Jon Ashburn3336df82015-01-29 15:45:51 -07003161 struct loader_icd *icd;
Jon Ashburnc4748dc2015-08-04 11:14:18 -06003162 VkExtensionProperties *prop;
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06003163 char **filtered_extension_names = NULL;
3164 VkInstanceCreateInfo icd_create_info;
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06003165 VkResult res = VK_SUCCESS;
Jon Ashburn2869bc72015-11-19 09:29:51 -07003166 bool success = false;
Jon Ashburn349508d2015-01-26 14:51:40 -07003167
Tony Barbour809d5d32015-12-04 13:24:39 -07003168 memcpy(&icd_create_info, pCreateInfo, sizeof(icd_create_info));
3169
Jon Ashburna4ae48b2016-01-11 13:12:43 -07003170 icd_create_info.enabledLayerCount = 0;
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06003171 icd_create_info.ppEnabledLayerNames = NULL;
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06003172
3173 /*
3174 * NOTE: Need to filter the extensions to only those
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06003175 * supported by the ICD.
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06003176 * No ICD will advertise support for layers. An ICD
3177 * library could support a layer, but it would be
3178 * independent of the actual ICD, just in the same library.
3179 */
Jon Ashburna4ae48b2016-01-11 13:12:43 -07003180 filtered_extension_names = loader_stack_alloc(pCreateInfo->enabledExtensionCount * sizeof(char *));
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06003181 if (!filtered_extension_names) {
3182 return VK_ERROR_OUT_OF_HOST_MEMORY;
3183 }
3184 icd_create_info.ppEnabledExtensionNames = (const char * const *) filtered_extension_names;
3185
Jon Ashburn754f1992015-08-18 18:04:47 -06003186 for (uint32_t i = 0; i < ptr_instance->icd_libs.count; i++) {
3187 icd = loader_icd_add(ptr_instance, &ptr_instance->icd_libs.list[i]);
Jon Ashburn3336df82015-01-29 15:45:51 -07003188 if (icd) {
Jon Ashburna4ae48b2016-01-11 13:12:43 -07003189 icd_create_info.enabledExtensionCount = 0;
Courtney Goeltzenleuchterf843d2d2015-12-21 16:41:47 -07003190 struct loader_extension_list icd_exts;
3191
3192 loader_log(ptr_instance, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Build ICD instance extension list");
3193 // traverse scanned icd list adding non-duplicate extensions to the list
3194 loader_init_generic_list(ptr_instance, (struct loader_generic_list *) &icd_exts,
3195 sizeof(VkExtensionProperties));
3196 loader_add_instance_extensions(ptr_instance,
3197 icd->this_icd_lib->EnumerateInstanceExtensionProperties,
3198 icd->this_icd_lib->lib_name,
3199 &icd_exts);
3200
Jon Ashburna4ae48b2016-01-11 13:12:43 -07003201 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06003202 prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
Courtney Goeltzenleuchterf843d2d2015-12-21 16:41:47 -07003203 &icd_exts);
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06003204 if (prop) {
Jon Ashburna4ae48b2016-01-11 13:12:43 -07003205 filtered_extension_names[icd_create_info.enabledExtensionCount] = (char *) pCreateInfo->ppEnabledExtensionNames[i];
3206 icd_create_info.enabledExtensionCount++;
Courtney Goeltzenleuchterab27f462015-07-06 17:42:01 -06003207 }
3208 }
3209
Courtney Goeltzenleuchterf843d2d2015-12-21 16:41:47 -07003210 loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *) &icd_exts);
3211
Jon Ashburn754f1992015-08-18 18:04:47 -06003212 res = ptr_instance->icd_libs.list[i].CreateInstance(&icd_create_info,
Chia-I Wu69f40122015-10-26 21:10:41 +08003213 pAllocator,
Jon Ashburn0dd356d2015-05-14 12:43:38 -06003214 &(icd->instance));
Jon Ashburn2869bc72015-11-19 09:29:51 -07003215 if (res == VK_SUCCESS)
3216 success = loader_icd_init_entrys(
Jon Ashburnce7e3d92015-07-16 10:17:29 -06003217 icd,
3218 icd->instance,
Jon Ashburn754f1992015-08-18 18:04:47 -06003219 ptr_instance->icd_libs.list[i].GetInstanceProcAddr);
Jon Ashburnce7e3d92015-07-16 10:17:29 -06003220
3221 if (res != VK_SUCCESS || !success)
Jon Ashburn3336df82015-01-29 15:45:51 -07003222 {
3223 ptr_instance->icds = ptr_instance->icds->next;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06003224 loader_icd_destroy(ptr_instance, icd);
Jon Ashburn0dd356d2015-05-14 12:43:38 -06003225 icd->instance = VK_NULL_HANDLE;
Courtney Goeltzenleuchteracb13592015-12-09 15:48:16 -07003226 loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
Jon Ashburnce7e3d92015-07-16 10:17:29 -06003227 "ICD ignored: failed to CreateInstance and find entrypoints with ICD");
Jon Ashburn3336df82015-01-29 15:45:51 -07003228 }
3229 }
Jon Ashburn3336df82015-01-29 15:45:51 -07003230 }
Jon Ashburn349508d2015-01-26 14:51:40 -07003231
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06003232 /*
3233 * If no ICDs were added to instance list and res is unchanged
3234 * from it's initial value, the loader was unable to find
3235 * a suitable ICD.
3236 */
Ian Elliott617fdec2015-02-05 15:19:15 -07003237 if (ptr_instance->icds == NULL) {
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06003238 if (res == VK_SUCCESS) {
3239 return VK_ERROR_INCOMPATIBLE_DRIVER;
3240 } else {
3241 return res;
3242 }
Ian Elliott617fdec2015-02-05 15:19:15 -07003243 }
Jon Ashburn3336df82015-01-29 15:45:51 -07003244
Courtney Goeltzenleuchter1fcceeb2015-07-06 09:06:34 -06003245 return VK_SUCCESS;
Jon Ashburn349508d2015-01-26 14:51:40 -07003246}
3247
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +08003248VKAPI_ATTR void VKAPI_CALL loader_DestroyInstance(
Chia-I Wu69f40122015-10-26 21:10:41 +08003249 VkInstance instance,
Chia-I Wu1f851912015-10-27 18:04:07 +08003250 const VkAllocationCallbacks* pAllocator)
Jon Ashburn349508d2015-01-26 14:51:40 -07003251{
Courtney Goeltzenleuchter8afefb52015-06-08 15:04:02 -06003252 struct loader_instance *ptr_instance = loader_instance(instance);
Jon Ashburn0dd356d2015-05-14 12:43:38 -06003253 struct loader_icd *icds = ptr_instance->icds;
Jon Ashburn16a16d62015-06-16 14:43:19 -06003254 struct loader_icd *next_icd;
Jon Ashburn349508d2015-01-26 14:51:40 -07003255
3256 // Remove this instance from the list of instances:
3257 struct loader_instance *prev = NULL;
3258 struct loader_instance *next = loader.instances;
3259 while (next != NULL) {
3260 if (next == ptr_instance) {
3261 // Remove this instance from the list:
3262 if (prev)
3263 prev->next = next->next;
Jon Ashburn2cabd252015-02-03 09:26:59 -07003264 else
3265 loader.instances = next->next;
Jon Ashburn349508d2015-01-26 14:51:40 -07003266 break;
3267 }
3268 prev = next;
3269 next = next->next;
3270 }
Jon Ashburn349508d2015-01-26 14:51:40 -07003271
Jon Ashburn0dd356d2015-05-14 12:43:38 -06003272 while (icds) {
3273 if (icds->instance) {
Chia-I Wu69f40122015-10-26 21:10:41 +08003274 icds->DestroyInstance(icds->instance, pAllocator);
Tony Barbour22a30862015-04-22 09:02:32 -06003275 }
Jon Ashburn16a16d62015-06-16 14:43:19 -06003276 next_icd = icds->next;
Jon Ashburn0dd356d2015-05-14 12:43:38 -06003277 icds->instance = VK_NULL_HANDLE;
Jon Ashburn16a16d62015-06-16 14:43:19 -06003278 loader_icd_destroy(ptr_instance, icds);
3279
3280 icds = next_icd;
Jon Ashburn3336df82015-01-29 15:45:51 -07003281 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06003282 loader_delete_layer_properties(ptr_instance, &ptr_instance->device_layer_list);
3283 loader_delete_layer_properties(ptr_instance, &ptr_instance->instance_layer_list);
3284 loader_scanned_icd_clear(ptr_instance, &ptr_instance->icd_libs);
Jon Ashburn8f6be302015-12-10 08:51:10 -07003285 loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *)
3286 &ptr_instance->ext_list);
Jon Ashburn251258f2015-11-01 14:04:06 -07003287 for (uint32_t i = 0; i < ptr_instance->total_gpu_count; i++)
Jon Ashburn8f6be302015-12-10 08:51:10 -07003288 loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *)
3289 &ptr_instance->phys_devs[i].device_extension_cache);
Jon Ashburn251258f2015-11-01 14:04:06 -07003290 loader_heap_free(ptr_instance, ptr_instance->phys_devs);
Jon Ashburn429e19f2015-11-17 15:31:02 -07003291 loader_free_dev_ext_table(ptr_instance);
Jon Ashburn349508d2015-01-26 14:51:40 -07003292}
3293
Jon Ashburn251258f2015-11-01 14:04:06 -07003294VkResult loader_init_physical_device_info(struct loader_instance *ptr_instance)
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003295{
3296 struct loader_icd *icd;
Jon Ashburn251258f2015-11-01 14:04:06 -07003297 uint32_t i, j, idx, count = 0;
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -06003298 VkResult res;
Jon Ashburn251258f2015-11-01 14:04:06 -07003299 struct loader_phys_dev_per_icd *phys_devs;
3300
3301 ptr_instance->total_gpu_count = 0;
3302 phys_devs = (struct loader_phys_dev_per_icd *) loader_stack_alloc(
3303 sizeof(struct loader_phys_dev_per_icd) *
3304 ptr_instance->total_icd_count);
3305 if (!phys_devs)
3306 return VK_ERROR_OUT_OF_HOST_MEMORY;
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003307
3308 icd = ptr_instance->icds;
Jon Ashburn251258f2015-11-01 14:04:06 -07003309 for (i = 0; i < ptr_instance->total_icd_count; i++) {
3310 assert(icd);
3311 res = icd->EnumeratePhysicalDevices(icd->instance, &phys_devs[i].count, NULL);
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003312 if (res != VK_SUCCESS)
3313 return res;
Jon Ashburn251258f2015-11-01 14:04:06 -07003314 count += phys_devs[i].count;
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003315 icd = icd->next;
3316 }
3317
Jon Ashburn251258f2015-11-01 14:04:06 -07003318 ptr_instance->phys_devs = (struct loader_physical_device *) loader_heap_alloc(
3319 ptr_instance,
3320 count * sizeof(struct loader_physical_device),
3321 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
3322 if (!ptr_instance->phys_devs)
3323 return VK_ERROR_OUT_OF_HOST_MEMORY;
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003324
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003325 icd = ptr_instance->icds;
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003326
Jon Ashburn251258f2015-11-01 14:04:06 -07003327 struct loader_physical_device *inst_phys_devs = ptr_instance->phys_devs;
3328 idx = 0;
3329 for (i = 0; i < ptr_instance->total_icd_count; i++) {
3330 assert(icd);
3331
3332 phys_devs[i].phys_devs = (VkPhysicalDevice *) loader_stack_alloc(
3333 phys_devs[i].count * sizeof(VkPhysicalDevice));
3334 if (!phys_devs[i].phys_devs) {
Jon Ashburna8ca5c42015-11-02 17:59:02 -07003335 loader_heap_free(ptr_instance, ptr_instance->phys_devs);
3336 ptr_instance->phys_devs = NULL;
Jon Ashburnd5df54d2015-05-28 19:16:58 -06003337 return VK_ERROR_OUT_OF_HOST_MEMORY;
3338 }
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003339 res = icd->EnumeratePhysicalDevices(
3340 icd->instance,
Jon Ashburn251258f2015-11-01 14:04:06 -07003341 &(phys_devs[i].count),
3342 phys_devs[i].phys_devs);
3343 if ((res == VK_SUCCESS)) {
3344 ptr_instance->total_gpu_count += phys_devs[i].count;
3345 for (j = 0; j < phys_devs[i].count; j++) {
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003346
Jon Ashburn251258f2015-11-01 14:04:06 -07003347 // initialize the loader's physicalDevice object
3348 loader_set_dispatch((void *) &inst_phys_devs[idx], ptr_instance->disp);
3349 inst_phys_devs[idx].this_instance = ptr_instance;
3350 inst_phys_devs[idx].this_icd = icd;
3351 inst_phys_devs[idx].phys_dev = phys_devs[i].phys_devs[j];
Jon Ashburndb5a5bc2015-11-02 17:40:01 -07003352 memset(&inst_phys_devs[idx].device_extension_cache, 0, sizeof(struct loader_extension_list));
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003353
Jon Ashburn251258f2015-11-01 14:04:06 -07003354 idx++;
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003355 }
Jon Ashburna8ca5c42015-11-02 17:59:02 -07003356 } else {
3357 loader_heap_free(ptr_instance, ptr_instance->phys_devs);
3358 ptr_instance->phys_devs = NULL;
Jon Ashburn251258f2015-11-01 14:04:06 -07003359 return res;
Jon Ashburna8ca5c42015-11-02 17:59:02 -07003360 }
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003361
3362 icd = icd->next;
3363 }
3364
3365 return VK_SUCCESS;
3366}
3367
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +08003368VKAPI_ATTR VkResult VKAPI_CALL loader_EnumeratePhysicalDevices(
Courtney Goeltzenleuchter9f530cb2015-04-20 12:48:54 -06003369 VkInstance instance,
3370 uint32_t* pPhysicalDeviceCount,
3371 VkPhysicalDevice* pPhysicalDevices)
Jon Ashburn349508d2015-01-26 14:51:40 -07003372{
Jon Ashburn251258f2015-11-01 14:04:06 -07003373 uint32_t i;
Jon Ashburnb048a9b2015-01-28 19:57:09 -07003374 struct loader_instance *ptr_instance = (struct loader_instance *) instance;
Jon Ashburn251258f2015-11-01 14:04:06 -07003375 VkResult res = VK_SUCCESS;
Jon Ashburnb048a9b2015-01-28 19:57:09 -07003376
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003377 if (ptr_instance->total_gpu_count == 0) {
Jon Ashburn251258f2015-11-01 14:04:06 -07003378 res = loader_init_physical_device_info(ptr_instance);
Jon Ashburnb048a9b2015-01-28 19:57:09 -07003379 }
3380
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003381 *pPhysicalDeviceCount = ptr_instance->total_gpu_count;
3382 if (!pPhysicalDevices) {
Jon Ashburn251258f2015-11-01 14:04:06 -07003383 return res;
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003384 }
Jon Ashburnb048a9b2015-01-28 19:57:09 -07003385
Jon Ashburn251258f2015-11-01 14:04:06 -07003386 for (i = 0; i < ptr_instance->total_gpu_count; i++) {
3387 pPhysicalDevices[i] = (VkPhysicalDevice) &ptr_instance->phys_devs[i];
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003388 }
3389
Jon Ashburn251258f2015-11-01 14:04:06 -07003390 return res;
Jon Ashburn349508d2015-01-26 14:51:40 -07003391}
3392
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +08003393VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceProperties(
Jon Ashburn251258f2015-11-01 14:04:06 -07003394 VkPhysicalDevice physicalDevice,
Tony Barbour426b9052015-06-24 16:06:58 -06003395 VkPhysicalDeviceProperties* pProperties)
Jon Ashburn0dd356d2015-05-14 12:43:38 -06003396{
Jon Ashburn251258f2015-11-01 14:04:06 -07003397 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3398 struct loader_icd *icd = phys_dev->this_icd;
Jon Ashburn0dd356d2015-05-14 12:43:38 -06003399
Tony Barbour426b9052015-06-24 16:06:58 -06003400 if (icd->GetPhysicalDeviceProperties)
Jon Ashburn251258f2015-11-01 14:04:06 -07003401 icd->GetPhysicalDeviceProperties(phys_dev->phys_dev, pProperties);
Tony Barbour426b9052015-06-24 16:06:58 -06003402}
3403
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +08003404VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceQueueFamilyProperties (
Jon Ashburn251258f2015-11-01 14:04:06 -07003405 VkPhysicalDevice physicalDevice,
Chia-I Wu763a7492015-10-26 20:48:51 +08003406 uint32_t* pQueueFamilyPropertyCount,
Cody Northropef72e2a2015-08-03 17:04:53 -06003407 VkQueueFamilyProperties* pProperties)
Tony Barbour426b9052015-06-24 16:06:58 -06003408{
Jon Ashburn251258f2015-11-01 14:04:06 -07003409 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3410 struct loader_icd *icd = phys_dev->this_icd;
Tony Barbour426b9052015-06-24 16:06:58 -06003411
Cody Northropef72e2a2015-08-03 17:04:53 -06003412 if (icd->GetPhysicalDeviceQueueFamilyProperties)
Jon Ashburn251258f2015-11-01 14:04:06 -07003413 icd->GetPhysicalDeviceQueueFamilyProperties(phys_dev->phys_dev, pQueueFamilyPropertyCount, pProperties);
Tony Barbour426b9052015-06-24 16:06:58 -06003414}
3415
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +08003416VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceMemoryProperties (
Jon Ashburn251258f2015-11-01 14:04:06 -07003417 VkPhysicalDevice physicalDevice,
Tony Barbour426b9052015-06-24 16:06:58 -06003418 VkPhysicalDeviceMemoryProperties* pProperties)
3419{
Jon Ashburn251258f2015-11-01 14:04:06 -07003420 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3421 struct loader_icd *icd = phys_dev->this_icd;
Tony Barbour426b9052015-06-24 16:06:58 -06003422
3423 if (icd->GetPhysicalDeviceMemoryProperties)
Jon Ashburn251258f2015-11-01 14:04:06 -07003424 icd->GetPhysicalDeviceMemoryProperties(phys_dev->phys_dev, pProperties);
Jon Ashburn0dd356d2015-05-14 12:43:38 -06003425}
3426
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +08003427VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceFeatures(
Chris Forbesd7576302015-06-21 22:55:02 +12003428 VkPhysicalDevice physicalDevice,
3429 VkPhysicalDeviceFeatures* pFeatures)
3430{
Jon Ashburn251258f2015-11-01 14:04:06 -07003431 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3432 struct loader_icd *icd = phys_dev->this_icd;
Chris Forbesd7576302015-06-21 22:55:02 +12003433
3434 if (icd->GetPhysicalDeviceFeatures)
Jon Ashburn251258f2015-11-01 14:04:06 -07003435 icd->GetPhysicalDeviceFeatures(phys_dev->phys_dev, pFeatures);
Chris Forbesd7576302015-06-21 22:55:02 +12003436}
3437
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +08003438VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceFormatProperties(
Chris Forbesd7576302015-06-21 22:55:02 +12003439 VkPhysicalDevice physicalDevice,
3440 VkFormat format,
3441 VkFormatProperties* pFormatInfo)
3442{
Jon Ashburn251258f2015-11-01 14:04:06 -07003443 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3444 struct loader_icd *icd = phys_dev->this_icd;
Chris Forbesd7576302015-06-21 22:55:02 +12003445
Courtney Goeltzenleuchter4da96aa2015-07-12 12:52:09 -06003446 if (icd->GetPhysicalDeviceFormatProperties)
Jon Ashburn251258f2015-11-01 14:04:06 -07003447 icd->GetPhysicalDeviceFormatProperties(phys_dev->phys_dev, format, pFormatInfo);
Chris Forbesd7576302015-06-21 22:55:02 +12003448}
3449
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +08003450VKAPI_ATTR VkResult VKAPI_CALL loader_GetPhysicalDeviceImageFormatProperties(
Jon Ashburn4e189562015-07-23 18:49:07 -06003451 VkPhysicalDevice physicalDevice,
3452 VkFormat format,
3453 VkImageType type,
3454 VkImageTiling tiling,
3455 VkImageUsageFlags usage,
Courtney Goeltzenleuchter83c95f82015-09-10 13:44:12 -06003456 VkImageCreateFlags flags,
Jon Ashburn4e189562015-07-23 18:49:07 -06003457 VkImageFormatProperties* pImageFormatProperties)
3458{
Jon Ashburn251258f2015-11-01 14:04:06 -07003459 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3460 struct loader_icd *icd = phys_dev->this_icd;
Jon Ashburn4e189562015-07-23 18:49:07 -06003461
Chia-I Wu5202c542015-10-31 00:31:16 +08003462 if (!icd->GetPhysicalDeviceImageFormatProperties)
3463 return VK_ERROR_INITIALIZATION_FAILED;
3464
3465 return icd->GetPhysicalDeviceImageFormatProperties(phys_dev->phys_dev, format,
3466 type, tiling, usage, flags, pImageFormatProperties);
Jon Ashburn4e189562015-07-23 18:49:07 -06003467}
3468
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +08003469VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceSparseImageFormatProperties(
Mark Lobodzinski83d4e6a2015-07-03 15:58:09 -06003470 VkPhysicalDevice physicalDevice,
3471 VkFormat format,
3472 VkImageType type,
Chia-I Wu3138d6a2015-10-31 00:31:16 +08003473 VkSampleCountFlagBits samples,
Mark Lobodzinski83d4e6a2015-07-03 15:58:09 -06003474 VkImageUsageFlags usage,
3475 VkImageTiling tiling,
3476 uint32_t* pNumProperties,
3477 VkSparseImageFormatProperties* pProperties)
3478{
Jon Ashburn251258f2015-11-01 14:04:06 -07003479 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3480 struct loader_icd *icd = phys_dev->this_icd;
Mark Lobodzinski83d4e6a2015-07-03 15:58:09 -06003481
3482 if (icd->GetPhysicalDeviceSparseImageFormatProperties)
Jon Ashburn251258f2015-11-01 14:04:06 -07003483 icd->GetPhysicalDeviceSparseImageFormatProperties(phys_dev->phys_dev, format, type, samples, usage, tiling, pNumProperties, pProperties);
Mark Lobodzinski83d4e6a2015-07-03 15:58:09 -06003484}
3485
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +08003486VKAPI_ATTR VkResult VKAPI_CALL loader_CreateDevice(
Jon Ashburn251258f2015-11-01 14:04:06 -07003487 VkPhysicalDevice physicalDevice,
Jon Ashburn2666e2f2015-05-15 15:09:35 -06003488 const VkDeviceCreateInfo* pCreateInfo,
Jon Ashburnba1f24e2015-12-11 09:41:34 -07003489 const VkAllocationCallbacks* pAllocator,
Jon Ashburn2666e2f2015-05-15 15:09:35 -06003490 VkDevice* pDevice)
3491{
Jon Ashburnba1f24e2015-12-11 09:41:34 -07003492 struct loader_physical_device *phys_dev;
3493 struct loader_icd *icd;
Jon Ashburncb5a5ac2015-06-10 10:06:06 -06003494 struct loader_device *dev;
Jon Ashburn429e19f2015-11-17 15:31:02 -07003495 struct loader_instance *inst;
Courtney Goeltzenleuchter91371ff2015-07-06 20:46:50 -06003496 VkDeviceCreateInfo device_create_info;
3497 char **filtered_extension_names = NULL;
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06003498 VkResult res;
Jon Ashburn2666e2f2015-05-15 15:09:35 -06003499
Chia-I Wu045654f2015-11-06 06:42:02 +08003500 assert(pCreateInfo->queueCreateInfoCount >= 1);
Mark Lobodzinski5ea338c2015-09-17 15:17:34 -06003501
Jon Ashburnba1f24e2015-12-11 09:41:34 -07003502 //TODO this only works for one physical device per instance
3503 // once CreateDevice layer bootstrapping is done via DeviceCreateInfo
3504 // hopefully don't need this anymore in trampoline code
3505 phys_dev = loader_get_physical_device(physicalDevice);
3506 icd = phys_dev->this_icd;
Jon Ashburn6853e7e2015-10-26 16:54:51 -06003507 if (!icd)
3508 return VK_ERROR_INITIALIZATION_FAILED;
3509
Jon Ashburn251258f2015-11-01 14:04:06 -07003510 inst = phys_dev->this_instance;
Jon Ashburn6853e7e2015-10-26 16:54:51 -06003511
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06003512 if (!icd->CreateDevice) {
3513 return VK_ERROR_INITIALIZATION_FAILED;
Jon Ashburn2666e2f2015-05-15 15:09:35 -06003514 }
3515
Jon Ashburn182b8302015-08-11 14:49:54 -06003516 /* validate any app enabled layers are available */
Jon Ashburna4ae48b2016-01-11 13:12:43 -07003517 if (pCreateInfo->enabledLayerCount > 0) {
3518 res = loader_validate_layers(pCreateInfo->enabledLayerCount,
Jon Ashburn182b8302015-08-11 14:49:54 -06003519 pCreateInfo->ppEnabledLayerNames,
Jon Ashburne58f1a32015-08-28 13:38:21 -06003520 &inst->device_layer_list);
Jon Ashburn182b8302015-08-11 14:49:54 -06003521 if (res != VK_SUCCESS) {
3522 return res;
3523 }
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06003524 }
3525
Jon Ashburndb5a5bc2015-11-02 17:40:01 -07003526 /* Get the physical device extensions if they haven't been retrieved yet */
3527 if (phys_dev->device_extension_cache.capacity == 0) {
Jon Ashburn8f6be302015-12-10 08:51:10 -07003528 if (!loader_init_generic_list(inst, (struct loader_generic_list *)
3529 &phys_dev->device_extension_cache,
3530 sizeof(VkExtensionProperties))) {
Jon Ashburndb5a5bc2015-11-02 17:40:01 -07003531 return VK_ERROR_OUT_OF_HOST_MEMORY;
3532 }
Courtney Goeltzenleuchter03c80a62015-12-02 14:00:19 -07003533 res = loader_add_device_extensions(
Jon Ashburndb5a5bc2015-11-02 17:40:01 -07003534 inst, physicalDevice,
3535 phys_dev->this_icd->this_icd_lib->lib_name,
3536 &phys_dev->device_extension_cache);
3537 if (res != VK_SUCCESS) {
3538 return res;
3539 }
3540 }
3541 /* make sure requested extensions to be enabled are supported */
Jon Ashburn251258f2015-11-01 14:04:06 -07003542 res = loader_validate_device_extensions(phys_dev, &inst->device_layer_list, pCreateInfo);
Courtney Goeltzenleuchtera17697f2015-07-06 20:14:18 -06003543 if (res != VK_SUCCESS) {
3544 return res;
3545 }
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003546
Courtney Goeltzenleuchter91371ff2015-07-06 20:46:50 -06003547 /*
3548 * NOTE: Need to filter the extensions to only those
3549 * supported by the ICD.
3550 * No ICD will advertise support for layers. An ICD
3551 * library could support a layer, but it would be
3552 * independent of the actual ICD, just in the same library.
3553 */
Jon Ashburna4ae48b2016-01-11 13:12:43 -07003554 filtered_extension_names = loader_stack_alloc(pCreateInfo->enabledExtensionCount * sizeof(char *));
Courtney Goeltzenleuchter91371ff2015-07-06 20:46:50 -06003555 if (!filtered_extension_names) {
3556 return VK_ERROR_OUT_OF_HOST_MEMORY;
3557 }
3558
3559 /* Copy user's data */
3560 memcpy(&device_create_info, pCreateInfo, sizeof(VkDeviceCreateInfo));
3561
3562 /* ICD's do not use layers */
Jon Ashburna4ae48b2016-01-11 13:12:43 -07003563 device_create_info.enabledLayerCount = 0;
Courtney Goeltzenleuchter91371ff2015-07-06 20:46:50 -06003564 device_create_info.ppEnabledLayerNames = NULL;
3565
Jon Ashburna4ae48b2016-01-11 13:12:43 -07003566 device_create_info.enabledExtensionCount = 0;
Courtney Goeltzenleuchter91371ff2015-07-06 20:46:50 -06003567 device_create_info.ppEnabledExtensionNames = (const char * const *) filtered_extension_names;
3568
Jon Ashburna4ae48b2016-01-11 13:12:43 -07003569 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
Courtney Goeltzenleuchter91371ff2015-07-06 20:46:50 -06003570 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i];
Jon Ashburnc4748dc2015-08-04 11:14:18 -06003571 VkExtensionProperties *prop = get_extension_property(extension_name,
Jon Ashburn251258f2015-11-01 14:04:06 -07003572 &phys_dev->device_extension_cache);
Courtney Goeltzenleuchter91371ff2015-07-06 20:46:50 -06003573 if (prop) {
Jon Ashburna4ae48b2016-01-11 13:12:43 -07003574 filtered_extension_names[device_create_info.enabledExtensionCount] = (char *) extension_name;
3575 device_create_info.enabledExtensionCount++;
Courtney Goeltzenleuchter91371ff2015-07-06 20:46:50 -06003576 }
3577 }
3578
Jon Ashburn251258f2015-11-01 14:04:06 -07003579 // since physicalDevice object maybe wrapped by a layer need to get unwrapped version
Jon Ashburn0c5eea22015-09-30 12:56:42 -06003580 // we haven't yet called down the chain for the layer to unwrap the object
Jon Ashburn59d7b682015-12-24 10:50:08 -07003581 res = icd->CreateDevice(phys_dev->phys_dev, &device_create_info, pAllocator, pDevice);
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06003582 if (res != VK_SUCCESS) {
3583 return res;
3584 }
3585
Jon Ashburne58f1a32015-08-28 13:38:21 -06003586 dev = loader_add_logical_device(inst, *pDevice, &icd->logical_device_list);
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06003587 if (dev == NULL) {
3588 return VK_ERROR_OUT_OF_HOST_MEMORY;
3589 }
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06003590
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06003591 loader_init_dispatch(*pDevice, &dev->loader_dispatch);
3592
Jon Ashburn182b8302015-08-11 14:49:54 -06003593 /* activate any layers on device chain which terminates with device*/
Jon Ashburne58f1a32015-08-28 13:38:21 -06003594 res = loader_enable_device_layers(inst, icd, dev, pCreateInfo, &inst->device_layer_list);
Jon Ashburn182b8302015-08-11 14:49:54 -06003595 if (res != VK_SUCCESS) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06003596 loader_destroy_logical_device(inst, dev);
Jon Ashburn182b8302015-08-11 14:49:54 -06003597 return res;
3598 }
Jon Ashburne58f1a32015-08-28 13:38:21 -06003599 loader_activate_device_layers(inst, dev, *pDevice);
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06003600
Jon Ashburn429e19f2015-11-17 15:31:02 -07003601 /* finally can call down the chain */
3602 res = dev->loader_dispatch.core_dispatch.CreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
3603
Jon Ashburnbbad5a62015-12-11 10:45:00 -07003604 /* initialize any device extension dispatch entry's from the instance list*/
3605 loader_init_dispatch_dev_ext(inst, dev);
3606
Jon Ashburn2818eb72015-11-30 17:21:25 -07003607 /* initialize WSI device extensions as part of core dispatch since loader has
3608 * dedicated trampoline code for these*/
3609 loader_init_device_extension_dispatch_table(&dev->loader_dispatch,
3610 dev->loader_dispatch.core_dispatch.GetDeviceProcAddr,
3611 *pDevice);
Jon Ashburn429e19f2015-11-17 15:31:02 -07003612 dev->loader_dispatch.core_dispatch.CreateDevice = icd->CreateDevice;
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -06003613
Jon Ashburn2666e2f2015-05-15 15:09:35 -06003614 return res;
3615}
3616
Jon Ashburn8aa75cb2015-09-28 16:15:00 -06003617/**
3618 * Get an instance level or global level entry point address.
3619 * @param instance
3620 * @param pName
3621 * @return
Jon Ashburn99456002015-11-06 11:02:40 -07003622 * If instance == NULL returns a global level functions only
3623 * If instance is valid returns a trampoline entry point for all dispatchable Vulkan
3624 * functions both core and extensions.
Jon Ashburn8aa75cb2015-09-28 16:15:00 -06003625 */
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +08003626LOADER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char * pName)
Jon Ashburn53c16772015-05-06 10:15:07 -06003627{
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06003628
Jon Ashburncedc15f2015-05-21 18:13:33 -06003629 void *addr;
Jon Ashburn53c16772015-05-06 10:15:07 -06003630
Jon Ashburn99456002015-11-06 11:02:40 -07003631 addr = globalGetProcAddr(pName);
Jon Ashburn8aa75cb2015-09-28 16:15:00 -06003632 if (instance == VK_NULL_HANDLE) {
Jon Ashburn99456002015-11-06 11:02:40 -07003633 // get entrypoint addresses that are global (no dispatchable object)
Jon Ashburn8aa75cb2015-09-28 16:15:00 -06003634
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06003635 return addr;
Jon Ashburn99456002015-11-06 11:02:40 -07003636 } else {
3637 // if a global entrypoint return NULL
3638 if (addr)
3639 return NULL;
Courtney Goeltzenleuchter1c7c65d2015-06-10 17:39:03 -06003640 }
3641
Jon Ashburn0c5eea22015-09-30 12:56:42 -06003642 struct loader_instance *ptr_instance = loader_get_instance(instance);
Jon Ashburn99456002015-11-06 11:02:40 -07003643 if (ptr_instance == NULL)
Jon Ashburncedc15f2015-05-21 18:13:33 -06003644 return NULL;
Jon Ashburn99456002015-11-06 11:02:40 -07003645 // Return trampoline code for non-global entrypoints including any extensions.
3646 // Device extensions are returned if a layer or ICD supports the extension.
3647 // Instance extensions are returned if the extension is enabled and the loader
3648 // or someone else supports the extension
3649 return trampolineGetProcAddr(ptr_instance, pName);
Jon Ashburncedc15f2015-05-21 18:13:33 -06003650
Jon Ashburn53c16772015-05-06 10:15:07 -06003651}
3652
Jon Ashburn8aa75cb2015-09-28 16:15:00 -06003653/**
3654 * Get a device level or global level entry point address.
3655 * @param device
3656 * @param pName
3657 * @return
Jon Ashburn8aa75cb2015-09-28 16:15:00 -06003658 * If device is valid, returns a device relative entry point for device level
3659 * entry points both core and extensions.
Jon Ashburn99456002015-11-06 11:02:40 -07003660 * Device relative means call down the device chain.
Jon Ashburn8aa75cb2015-09-28 16:15:00 -06003661 */
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +08003662LOADER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char * pName)
Courtney Goeltzenleuchter9a4f38c2015-06-22 17:45:21 -06003663{
Jon Ashburn8aa75cb2015-09-28 16:15:00 -06003664 void *addr;
Courtney Goeltzenleuchter9a4f38c2015-06-22 17:45:21 -06003665
Jon Ashburne18431b2015-04-13 18:10:06 -06003666 /* for entrypoints that loader must handle (ie non-dispatchable or create object)
3667 make sure the loader entrypoint is returned */
Jon Ashburn8aa75cb2015-09-28 16:15:00 -06003668 addr = loader_non_passthrough_gdpa(pName);
Ian Elliottfdf00b62015-04-15 12:53:19 -06003669 if (addr) {
Jon Ashburne18431b2015-04-13 18:10:06 -06003670 return addr;
Ian Elliottfdf00b62015-04-15 12:53:19 -06003671 }
Jon Ashburne18431b2015-04-13 18:10:06 -06003672
Jon Ashburn99456002015-11-06 11:02:40 -07003673 /* Although CreateDevice is on device chain it's dispatchable object isn't
3674 * a VkDevice or child of VkDevice so return NULL.
3675 */
3676 if (!strcmp(pName, "CreateDevice"))
3677 return NULL;
3678
Jon Ashburne18431b2015-04-13 18:10:06 -06003679 /* return the dispatch table entrypoint for the fastest case */
Jon Ashburn1245cec2015-05-18 13:20:15 -06003680 const VkLayerDispatchTable *disp_table = * (VkLayerDispatchTable **) device;
Jon Ashburnd43f9b62014-10-14 19:15:22 -06003681 if (disp_table == NULL)
3682 return NULL;
3683
Jon Ashburnfce93d92015-05-12 17:26:48 -06003684 addr = loader_lookup_device_dispatch_table(disp_table, pName);
Chia-I Wu38e5a2c2015-01-04 11:12:47 +08003685 if (addr)
3686 return addr;
Jon Ashburn99456002015-11-06 11:02:40 -07003687
3688 if (disp_table->GetDeviceProcAddr == NULL)
3689 return NULL;
3690 return disp_table->GetDeviceProcAddr(device, pName);
Jon Ashburnd43f9b62014-10-14 19:15:22 -06003691}
3692
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +08003693LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003694 const char* pLayerName,
Chia-I Wu763a7492015-10-26 20:48:51 +08003695 uint32_t* pPropertyCount,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003696 VkExtensionProperties* pProperties)
3697{
Jon Ashburnb8605fe2015-09-18 12:53:16 -06003698 struct loader_extension_list *global_ext_list=NULL;
Jon Ashburn182b8302015-08-11 14:49:54 -06003699 struct loader_layer_list instance_layers;
Jon Ashburnc1d1eb72015-08-14 11:57:54 -06003700 struct loader_extension_list icd_extensions;
Jon Ashburn754f1992015-08-18 18:04:47 -06003701 struct loader_icd_libs icd_libs;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003702 uint32_t copy_size;
3703
Jon Ashburn413d6582015-08-28 15:19:27 -06003704 tls_instance = NULL;
Jon Ashburnc1d1eb72015-08-14 11:57:54 -06003705 memset(&icd_extensions, 0, sizeof(icd_extensions));
Mike Stroyana73e50c2015-10-01 15:23:48 -06003706 memset(&instance_layers, 0, sizeof(instance_layers));
Jon Ashburn754f1992015-08-18 18:04:47 -06003707 loader_platform_thread_once(&once_init, loader_initialize);
Jon Ashburnc1d1eb72015-08-14 11:57:54 -06003708
Jon Ashburn182b8302015-08-11 14:49:54 -06003709 /* get layer libraries if needed */
3710 if (pLayerName && strlen(pLayerName) != 0) {
Jon Ashburne58f1a32015-08-28 13:38:21 -06003711 loader_layer_scan(NULL, &instance_layers, NULL);
Jon Ashburn182b8302015-08-11 14:49:54 -06003712 for (uint32_t i = 0; i < instance_layers.count; i++) {
3713 struct loader_layer_properties *props = &instance_layers.list[i];
3714 if (strcmp(props->info.layerName, pLayerName) == 0) {
3715 global_ext_list = &props->instance_extension_list;
3716 }
3717 }
3718 }
3719 else {
Jon Ashburn754f1992015-08-18 18:04:47 -06003720 /* Scan/discover all ICD libraries */
3721 memset(&icd_libs, 0 , sizeof(struct loader_icd_libs));
Jon Ashburne58f1a32015-08-28 13:38:21 -06003722 loader_icd_scan(NULL, &icd_libs);
Jon Ashburnc1d1eb72015-08-14 11:57:54 -06003723 /* get extensions from all ICD's, merge so no duplicates */
Jon Ashburne58f1a32015-08-28 13:38:21 -06003724 loader_get_icd_loader_instance_extensions(NULL, &icd_libs, &icd_extensions);
3725 loader_scanned_icd_clear(NULL, &icd_libs);
Jon Ashburnc1d1eb72015-08-14 11:57:54 -06003726 global_ext_list = &icd_extensions;
Jon Ashburn182b8302015-08-11 14:49:54 -06003727 }
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003728
Jon Ashburn182b8302015-08-11 14:49:54 -06003729 if (global_ext_list == NULL) {
Mike Stroyana73e50c2015-10-01 15:23:48 -06003730 loader_destroy_layer_list(NULL, &instance_layers);
Courtney Goeltzenleuchterac544f32015-09-14 18:01:17 -06003731 return VK_ERROR_LAYER_NOT_PRESENT;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003732 }
3733
3734 if (pProperties == NULL) {
Chia-I Wu763a7492015-10-26 20:48:51 +08003735 *pPropertyCount = global_ext_list->count;
Mike Stroyana73e50c2015-10-01 15:23:48 -06003736 loader_destroy_layer_list(NULL, &instance_layers);
Jon Ashburn8f6be302015-12-10 08:51:10 -07003737 loader_destroy_generic_list(NULL, (struct loader_generic_list *)
3738 &icd_extensions);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003739 return VK_SUCCESS;
3740 }
3741
Chia-I Wu763a7492015-10-26 20:48:51 +08003742 copy_size = *pPropertyCount < global_ext_list->count ? *pPropertyCount : global_ext_list->count;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003743 for (uint32_t i = 0; i < copy_size; i++) {
3744 memcpy(&pProperties[i],
Jon Ashburn182b8302015-08-11 14:49:54 -06003745 &global_ext_list->list[i],
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003746 sizeof(VkExtensionProperties));
3747 }
Chia-I Wu763a7492015-10-26 20:48:51 +08003748 *pPropertyCount = copy_size;
Jon Ashburn8f6be302015-12-10 08:51:10 -07003749 loader_destroy_generic_list(NULL, (struct loader_generic_list *)
3750 &icd_extensions);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003751
Jon Ashburn182b8302015-08-11 14:49:54 -06003752 if (copy_size < global_ext_list->count) {
Mike Stroyana73e50c2015-10-01 15:23:48 -06003753 loader_destroy_layer_list(NULL, &instance_layers);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003754 return VK_INCOMPLETE;
3755 }
3756
Mike Stroyana73e50c2015-10-01 15:23:48 -06003757 loader_destroy_layer_list(NULL, &instance_layers);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003758 return VK_SUCCESS;
3759}
3760
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +08003761LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(
Chia-I Wu763a7492015-10-26 20:48:51 +08003762 uint32_t* pPropertyCount,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003763 VkLayerProperties* pProperties)
Tony Barbour426b9052015-06-24 16:06:58 -06003764{
Jon Ashburnb40f2562015-05-29 13:15:39 -06003765
Jon Ashburn182b8302015-08-11 14:49:54 -06003766 struct loader_layer_list instance_layer_list;
Jon Ashburn413d6582015-08-28 15:19:27 -06003767 tls_instance = NULL;
Jon Ashburn182b8302015-08-11 14:49:54 -06003768
Jon Ashburn754f1992015-08-18 18:04:47 -06003769 loader_platform_thread_once(&once_init, loader_initialize);
Courtney Goeltzenleuchter0199e952015-02-27 15:19:33 -07003770
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003771 uint32_t copy_size;
Jon Ashburneb2728b2015-04-10 14:33:07 -06003772
Jon Ashburn182b8302015-08-11 14:49:54 -06003773 /* get layer libraries */
3774 memset(&instance_layer_list, 0, sizeof(instance_layer_list));
Jon Ashburne58f1a32015-08-28 13:38:21 -06003775 loader_layer_scan(NULL, &instance_layer_list, NULL);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003776
3777 if (pProperties == NULL) {
Chia-I Wu763a7492015-10-26 20:48:51 +08003778 *pPropertyCount = instance_layer_list.count;
Jon Ashburne58f1a32015-08-28 13:38:21 -06003779 loader_destroy_layer_list(NULL, &instance_layer_list);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003780 return VK_SUCCESS;
3781 }
3782
Chia-I Wu763a7492015-10-26 20:48:51 +08003783 copy_size = (*pPropertyCount < instance_layer_list.count) ? *pPropertyCount : instance_layer_list.count;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003784 for (uint32_t i = 0; i < copy_size; i++) {
Jon Ashburn182b8302015-08-11 14:49:54 -06003785 memcpy(&pProperties[i], &instance_layer_list.list[i].info, sizeof(VkLayerProperties));
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003786 }
Chia-I Wu763a7492015-10-26 20:48:51 +08003787 *pPropertyCount = copy_size;
Jon Ashburne58f1a32015-08-28 13:38:21 -06003788 loader_destroy_layer_list(NULL, &instance_layer_list);
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003789
Jon Ashburn182b8302015-08-11 14:49:54 -06003790 if (copy_size < instance_layer_list.count) {
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003791 return VK_INCOMPLETE;
3792 }
Tony Barbour426b9052015-06-24 16:06:58 -06003793
3794 return VK_SUCCESS;
3795}
3796
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +08003797VKAPI_ATTR VkResult VKAPI_CALL loader_EnumerateDeviceExtensionProperties(
Jon Ashburn251258f2015-11-01 14:04:06 -07003798 VkPhysicalDevice physicalDevice,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003799 const char* pLayerName,
Chia-I Wu763a7492015-10-26 20:48:51 +08003800 uint32_t* pPropertyCount,
Tony Barbour426b9052015-06-24 16:06:58 -06003801 VkExtensionProperties* pProperties)
3802{
Jon Ashburned158d12015-12-14 08:52:14 -07003803 struct loader_physical_device *phys_dev;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003804 uint32_t copy_size;
Courtney Goeltzenleuchter0199e952015-02-27 15:19:33 -07003805
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003806 uint32_t count;
Jon Ashburn738136f2015-12-10 18:17:34 -07003807 struct loader_device_extension_list *dev_ext_list=NULL;
Jon Ashburned158d12015-12-14 08:52:14 -07003808 //TODO fix this aliases physical devices
3809 phys_dev = loader_get_physical_device(physicalDevice);
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003810
Jon Ashburn182b8302015-08-11 14:49:54 -06003811 /* get layer libraries if needed */
3812 if (pLayerName && strlen(pLayerName) != 0) {
Jon Ashburn251258f2015-11-01 14:04:06 -07003813 for (uint32_t i = 0; i < phys_dev->this_instance->device_layer_list.count; i++) {
3814 struct loader_layer_properties *props = &phys_dev->this_instance->device_layer_list.list[i];
Jon Ashburn182b8302015-08-11 14:49:54 -06003815 if (strcmp(props->info.layerName, pLayerName) == 0) {
3816 dev_ext_list = &props->device_extension_list;
3817 }
3818 }
3819 }
3820 else {
Jon Ashburndb5a5bc2015-11-02 17:40:01 -07003821 /* this case is during the call down the instance chain */
3822 struct loader_icd *icd = phys_dev->this_icd;
3823 VkResult res;
3824 res = icd->EnumerateDeviceExtensionProperties(phys_dev->phys_dev, NULL, pPropertyCount, pProperties);
3825 if (pProperties != NULL && res == VK_SUCCESS) {
3826 /* initialize dev_extension list within the physicalDevice object */
Courtney Goeltzenleuchter03c80a62015-12-02 14:00:19 -07003827 res = loader_init_device_extensions(phys_dev->this_instance,
Jon Ashburndb5a5bc2015-11-02 17:40:01 -07003828 phys_dev, *pPropertyCount, pProperties,
3829 &phys_dev->device_extension_cache);
3830 }
3831 return res;
Jon Ashburn182b8302015-08-11 14:49:54 -06003832 }
3833
Jon Ashburnb8605fe2015-09-18 12:53:16 -06003834 count = (dev_ext_list == NULL) ? 0: dev_ext_list->count;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003835 if (pProperties == NULL) {
Chia-I Wu763a7492015-10-26 20:48:51 +08003836 *pPropertyCount = count;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003837 return VK_SUCCESS;
3838 }
3839
Chia-I Wu763a7492015-10-26 20:48:51 +08003840 copy_size = *pPropertyCount < count ? *pPropertyCount : count;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003841 for (uint32_t i = 0; i < copy_size; i++) {
3842 memcpy(&pProperties[i],
Jon Ashburn738136f2015-12-10 18:17:34 -07003843 &dev_ext_list->list[i].props,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003844 sizeof(VkExtensionProperties));
3845 }
Chia-I Wu763a7492015-10-26 20:48:51 +08003846 *pPropertyCount = copy_size;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003847
3848 if (copy_size < count) {
3849 return VK_INCOMPLETE;
3850 }
3851
3852 return VK_SUCCESS;
3853}
3854
Chia-I Wuaf9e4fd2015-11-06 06:42:02 +08003855VKAPI_ATTR VkResult VKAPI_CALL loader_EnumerateDeviceLayerProperties(
Jon Ashburn251258f2015-11-01 14:04:06 -07003856 VkPhysicalDevice physicalDevice,
Chia-I Wu763a7492015-10-26 20:48:51 +08003857 uint32_t* pPropertyCount,
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003858 VkLayerProperties* pProperties)
3859{
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003860 uint32_t copy_size;
Jon Ashburned158d12015-12-14 08:52:14 -07003861 struct loader_physical_device *phys_dev;
3862 //TODO fix this, aliases physical devices
3863 phys_dev = loader_get_physical_device(physicalDevice);
Jon Ashburn251258f2015-11-01 14:04:06 -07003864 uint32_t count = phys_dev->this_instance->device_layer_list.count;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003865
3866 if (pProperties == NULL) {
Chia-I Wu763a7492015-10-26 20:48:51 +08003867 *pPropertyCount = count;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003868 return VK_SUCCESS;
3869 }
3870
Chia-I Wu763a7492015-10-26 20:48:51 +08003871 copy_size = (*pPropertyCount < count) ? *pPropertyCount : count;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003872 for (uint32_t i = 0; i < copy_size; i++) {
Jon Ashburn251258f2015-11-01 14:04:06 -07003873 memcpy(&pProperties[i], &(phys_dev->this_instance->device_layer_list.list[i].info), sizeof(VkLayerProperties));
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003874 }
Chia-I Wu763a7492015-10-26 20:48:51 +08003875 *pPropertyCount = copy_size;
Courtney Goeltzenleuchter18061cd2015-06-29 15:39:26 -06003876
3877 if (copy_size < count) {
3878 return VK_INCOMPLETE;
3879 }
Courtney Goeltzenleuchter23b5f8d2015-06-17 20:51:59 -06003880
3881 return VK_SUCCESS;
Jon Ashburn2666e2f2015-05-15 15:09:35 -06003882}