blob: 6e37f061d2d152078b66dac46f29b7d2dfca2c48 [file] [log] [blame]
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001/*
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08002 *
Courtney Goeltzenleuchterfcbe16f2015-10-29 13:50:34 -06003 * Copyright (C) 2015 Valve Corporation
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08004 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
Chia-I Wu701f3f62014-09-02 08:32:09 +080022 *
Courtney Goeltzenleuchter05559522015-10-30 11:14:30 -060023 * Author: Chia-I Wu <olvaffe@gmail.com>
24 * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
25 * Author: Ian Elliott <ian@LunarG.com>
26 * Author: Jon Ashburn <jon@lunarg.com>
27 *
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080028 */
Mark Lobodzinskifaa90812015-11-25 13:26:15 -070029
Jon Ashburn6b4d70c2014-10-22 18:13:16 -060030#define _GNU_SOURCE
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080031#include <stdio.h>
32#include <stdlib.h>
33#include <stdarg.h>
34#include <stdbool.h>
35#include <string.h>
36
Chia-I Wu13a61a52014-08-04 11:18:20 +080037#include <sys/types.h>
Johannes van Waveren9bd805012015-10-28 11:45:00 -050038#if defined(_WIN32)
Ian Elliott2d4ab1e2015-01-13 17:52:38 -070039#include "dirent_on_windows.h"
Johannes van Waveren9bd805012015-10-28 11:45:00 -050040#else // _WIN32
Chia-I Wu13a61a52014-08-04 11:18:20 +080041#include <dirent.h>
Johannes van Waveren9bd805012015-10-28 11:45:00 -050042#endif // _WIN32
Tobin Ehlisb835d1b2015-07-03 10:34:49 -060043#include "vk_loader_platform.h"
Chia-I Wu19300602014-08-04 08:03:57 +080044#include "loader.h"
Jon Ashburn27cd5842015-05-12 17:26:48 -060045#include "gpa_helper.h"
46#include "table_ops.h"
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -060047#include "debug_report.h"
Ian Elliott954fa342015-10-30 15:28:23 -060048#include "wsi.h"
David Pinedo9316d3b2015-11-06 12:54:48 -070049#include "vulkan/vk_icd.h"
Jon Ashburn2077e382015-06-29 11:25:34 -060050#include "cJSON.h"
Jon Ashburnfc1031e2015-11-17 15:31:02 -070051#include "murmurhash.h"
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080052
Courtney Goeltzenleuchtered488302015-06-01 14:09:34 -060053static loader_platform_dl_handle loader_add_layer_lib(
Jon Ashburne39a4f82015-08-28 13:38:21 -060054 const struct loader_instance *inst,
Courtney Goeltzenleuchtered488302015-06-01 14:09:34 -060055 const char *chain_type,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -060056 struct loader_layer_properties *layer_prop);
Courtney Goeltzenleuchtered488302015-06-01 14:09:34 -060057
58static void loader_remove_layer_lib(
59 struct loader_instance *inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -060060 struct loader_layer_properties *layer_prop);
Courtney Goeltzenleuchtered488302015-06-01 14:09:34 -060061
Jon Ashburn27cd5842015-05-12 17:26:48 -060062struct loader_struct loader = {0};
Jon Ashburn87d6aa92015-08-28 15:19:27 -060063// TLS for instance for alloc/free callbacks
64THREAD_LOCAL_DECL struct loader_instance *tls_instance;
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080065
Jon Ashburn6e6a2162015-12-10 08:51:10 -070066static bool loader_init_generic_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -060067 const struct loader_instance *inst,
Jon Ashburn6e6a2162015-12-10 08:51:10 -070068 struct loader_generic_list *list_info,
69 size_t element_size);
Courtney Goeltzenleuchter9ec39ac2015-06-22 17:45:21 -060070
Daniel Dadap00b4aba2015-09-30 11:50:51 -050071static int loader_platform_combine_path(char *dest, int len, ...);
72
Jon Ashburn24cd4be2015-11-01 14:04:06 -070073struct loader_phys_dev_per_icd {
74 uint32_t count;
75 VkPhysicalDevice *phys_devs;
76};
77
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -060078enum loader_debug {
Courtney Goeltzenleuchterf3387652015-07-08 18:41:08 -060079 LOADER_INFO_BIT = 0x01,
80 LOADER_WARN_BIT = 0x02,
81 LOADER_PERF_BIT = 0x04,
82 LOADER_ERROR_BIT = 0x08,
83 LOADER_DEBUG_BIT = 0x10,
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -060084};
85
86uint32_t g_loader_debug = 0;
87uint32_t g_loader_log_msgs = 0;
88
Jon Ashburn6301a0f2015-05-29 13:15:39 -060089//thread safety lock for accessing global data structures such as "loader"
90// all entrypoints on the instance chain need to be locked except GPA
Jon Ashburn2077e382015-06-29 11:25:34 -060091// additionally CreateDevice and DestroyDevice needs to be locked
Jon Ashburn6301a0f2015-05-29 13:15:39 -060092loader_platform_thread_mutex loader_lock;
Jon Ashburn6461ef22015-09-22 13:11:00 -060093loader_platform_thread_mutex loader_json_lock;
Jon Ashburn6301a0f2015-05-29 13:15:39 -060094
Ian Elliottd3ef02f2015-07-06 14:36:13 -060095// This table contains the loader's instance dispatch table, which contains
96// default functions if no instance layers are activated. This contains
97// pointers to "terminator functions".
Jon Ashburn6301a0f2015-05-29 13:15:39 -060098const VkLayerInstanceDispatchTable instance_disp = {
Jon Ashburn69e9ea22015-09-28 16:15:00 -060099 .GetInstanceProcAddr = vkGetInstanceProcAddr,
Jon Ashburn27cd5842015-05-12 17:26:48 -0600100 .CreateInstance = loader_CreateInstance,
101 .DestroyInstance = loader_DestroyInstance,
102 .EnumeratePhysicalDevices = loader_EnumeratePhysicalDevices,
Chris Forbesbc0bb772015-06-21 22:55:02 +1200103 .GetPhysicalDeviceFeatures = loader_GetPhysicalDeviceFeatures,
Courtney Goeltzenleuchter2caec862015-07-12 12:52:09 -0600104 .GetPhysicalDeviceFormatProperties = loader_GetPhysicalDeviceFormatProperties,
Jon Ashburn754864f2015-07-23 18:49:07 -0600105 .GetPhysicalDeviceImageFormatProperties = loader_GetPhysicalDeviceImageFormatProperties,
Tony Barbour59a47322015-06-24 16:06:58 -0600106 .GetPhysicalDeviceProperties = loader_GetPhysicalDeviceProperties,
Cody Northropd0802882015-08-03 17:04:53 -0600107 .GetPhysicalDeviceQueueFamilyProperties = loader_GetPhysicalDeviceQueueFamilyProperties,
Tony Barbour59a47322015-06-24 16:06:58 -0600108 .GetPhysicalDeviceMemoryProperties = loader_GetPhysicalDeviceMemoryProperties,
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -0600109 .EnumerateDeviceExtensionProperties = loader_EnumerateDeviceExtensionProperties,
110 .EnumerateDeviceLayerProperties = loader_EnumerateDeviceLayerProperties,
Mark Lobodzinski16e8bef2015-07-03 15:58:09 -0600111 .GetPhysicalDeviceSparseImageFormatProperties = loader_GetPhysicalDeviceSparseImageFormatProperties,
Ian Elliottfb42cd72015-11-25 14:43:02 -0700112 .DestroySurfaceKHR = loader_DestroySurfaceKHR,
Ian Elliott7e40db92015-08-21 15:09:33 -0600113 .GetPhysicalDeviceSurfaceSupportKHR = loader_GetPhysicalDeviceSurfaceSupportKHR,
Ian Elliott486c5502015-11-19 16:05:09 -0700114 .GetPhysicalDeviceSurfaceCapabilitiesKHR = loader_GetPhysicalDeviceSurfaceCapabilitiesKHR,
115 .GetPhysicalDeviceSurfaceFormatsKHR = loader_GetPhysicalDeviceSurfaceFormatsKHR,
116 .GetPhysicalDeviceSurfacePresentModesKHR = loader_GetPhysicalDeviceSurfacePresentModesKHR,
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700117 .CreateDebugReportCallbackLUNARG = loader_CreateDebugReportCallback,
118 .DestroyDebugReportCallbackLUNARG = loader_DestroyDebugReportCallback,
Ian Elliottdb4300a2015-11-23 10:17:23 -0700119#ifdef VK_USE_PLATFORM_MIR_KHR
Jon Ashburnf72a04b2015-11-25 17:55:49 -0700120 .CreateMirSurfaceKHR = loader_CreateMirSurfaceKHR,
Ian Elliott919fa302015-11-24 15:39:10 -0700121 .GetPhysicalDeviceMirPresentationSupportKHR = loader_GetPhysicalDeviceMirPresentationSupportKHR,
Ian Elliottdb4300a2015-11-23 10:17:23 -0700122#endif
123#ifdef VK_USE_PLATFORM_WAYLAND_KHR
Jon Ashburnf72a04b2015-11-25 17:55:49 -0700124 .CreateWaylandSurfaceKHR = loader_CreateWaylandSurfaceKHR,
Ian Elliott919fa302015-11-24 15:39:10 -0700125 .GetPhysicalDeviceWaylandPresentationSupportKHR = loader_GetPhysicalDeviceWaylandPresentationSupportKHR,
Ian Elliottdb4300a2015-11-23 10:17:23 -0700126#endif
127#ifdef VK_USE_PLATFORM_WIN32_KHR
Jon Ashburnf72a04b2015-11-25 17:55:49 -0700128 .CreateWin32SurfaceKHR = loader_CreateWin32SurfaceKHR,
Ian Elliott919fa302015-11-24 15:39:10 -0700129 .GetPhysicalDeviceWin32PresentationSupportKHR = loader_GetPhysicalDeviceWin32PresentationSupportKHR,
Ian Elliottdb4300a2015-11-23 10:17:23 -0700130#endif
131#ifdef VK_USE_PLATFORM_XCB_KHR
Jon Ashburnf72a04b2015-11-25 17:55:49 -0700132 .CreateXcbSurfaceKHR = loader_CreateXcbSurfaceKHR,
Ian Elliott919fa302015-11-24 15:39:10 -0700133 .GetPhysicalDeviceXcbPresentationSupportKHR = loader_GetPhysicalDeviceXcbPresentationSupportKHR,
Ian Elliottdb4300a2015-11-23 10:17:23 -0700134#endif
135#ifdef VK_USE_PLATFORM_XLIB_KHR
Jon Ashburnf72a04b2015-11-25 17:55:49 -0700136 .CreateXlibSurfaceKHR = loader_CreateXlibSurfaceKHR,
Ian Elliott919fa302015-11-24 15:39:10 -0700137 .GetPhysicalDeviceXlibPresentationSupportKHR = loader_GetPhysicalDeviceXlibPresentationSupportKHR,
Ian Elliottdb4300a2015-11-23 10:17:23 -0700138#endif
Mark Lobodzinskia8a5f852015-12-10 16:25:21 -0700139#ifdef VK_USE_PLATFORM_ANDROID_KHR
140 .CreateAndroidSurfaceKHR = loader_CreateAndroidSurfaceKHR,
141#endif
Jon Ashburn27cd5842015-05-12 17:26:48 -0600142};
143
Jon Ashburn8810c5f2015-08-18 18:04:47 -0600144LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_init);
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700145
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600146void* loader_heap_alloc(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600147 const struct loader_instance *instance,
148 size_t size,
Jon Ashburn39fbd4e2015-12-10 18:17:34 -0700149 VkSystemAllocationScope alloc_scope)
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600150{
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800151 if (instance && instance->alloc_callbacks.pfnAllocation) {
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600152 /* TODO: What should default alignment be? 1, 4, 8, other? */
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800153 return instance->alloc_callbacks.pfnAllocation(instance->alloc_callbacks.pUserData, size, 4, alloc_scope);
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600154 }
155 return malloc(size);
156}
157
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600158void loader_heap_free(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600159 const struct loader_instance *instance,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800160 void *pMemory)
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600161{
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800162 if (pMemory == NULL) return;
Jon Ashburneacfa3a2015-08-14 12:51:47 -0600163 if (instance && instance->alloc_callbacks.pfnFree) {
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800164 instance->alloc_callbacks.pfnFree(instance->alloc_callbacks.pUserData, pMemory);
Jon Ashburnd2c171b2015-08-13 08:28:48 -0600165 return;
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600166 }
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800167 free(pMemory);
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600168}
169
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600170void* loader_heap_realloc(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600171 const struct loader_instance *instance,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800172 void *pMemory,
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600173 size_t orig_size,
174 size_t size,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800175 VkSystemAllocationScope alloc_scope)
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600176{
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800177 if (pMemory == NULL || orig_size == 0)
Chia-I Wuf7458c52015-10-26 21:10:41 +0800178 return loader_heap_alloc(instance, size, alloc_scope);
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600179 if (size == 0) {
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800180 loader_heap_free(instance, pMemory);
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600181 return NULL;
182 }
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800183 if (instance && instance->alloc_callbacks.pfnAllocation) {
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600184 if (size <= orig_size) {
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800185 memset(((uint8_t *)pMemory) + size, 0, orig_size - size);
186 return pMemory;
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600187 }
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800188 void *new_ptr = instance->alloc_callbacks.pfnAllocation(instance->alloc_callbacks.pUserData, size, 4, alloc_scope);
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600189 if (!new_ptr)
190 return NULL;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800191 memcpy(new_ptr, pMemory, orig_size);
192 instance->alloc_callbacks.pfnFree(instance->alloc_callbacks.pUserData, pMemory);
Jon Ashburne3753b32015-10-21 16:09:27 -0600193 return new_ptr;
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600194 }
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800195 return realloc(pMemory, size);
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600196}
197
Jon Ashburn87d6aa92015-08-28 15:19:27 -0600198void *loader_tls_heap_alloc(size_t size)
199{
Chia-I Wucf804e82015-10-31 00:31:16 +0800200 return loader_heap_alloc(tls_instance, size, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
Jon Ashburn87d6aa92015-08-28 15:19:27 -0600201}
202
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800203void loader_tls_heap_free(void *pMemory)
Jon Ashburn87d6aa92015-08-28 15:19:27 -0600204{
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800205 loader_heap_free(tls_instance, pMemory);
Jon Ashburn87d6aa92015-08-28 15:19:27 -0600206}
207
Jon Ashburnffad94d2015-06-30 14:46:22 -0700208static void loader_log(VkFlags msg_type, int32_t msg_code,
209 const char *format, ...)
210{
Jon Ashburn86723b02015-07-31 15:47:59 -0600211 char msg[512];
Jon Ashburnffad94d2015-06-30 14:46:22 -0700212 va_list ap;
213 int ret;
214
215 if (!(msg_type & g_loader_log_msgs)) {
216 return;
217 }
218
219 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
Ian Elliott4470a302015-02-17 10:33:47 -0700226#if defined(WIN32)
Jon Ashburnffad94d2015-06-30 14:46:22 -0700227 OutputDebugString(msg);
mschottb9cdb782015-07-22 14:11:29 +0200228 OutputDebugString("\n");
Jon Ashburnffad94d2015-06-30 14:46:22 -0700229#endif
230 fputs(msg, stderr);
231 fputc('\n', stderr);
232}
233
234#if defined(WIN32)
Tony Barbourea968902015-07-29 14:26:21 -0600235static char *loader_get_next_path(char *path);
Jon Ashburnffad94d2015-06-30 14:46:22 -0700236/**
237* Find the list of registry files (names within a key) in key "location".
238*
239* This function looks in the registry (hive = DEFAULT_VK_REGISTRY_HIVE) key as given in "location"
240* for a list or name/values which are added to a returned list (function return value).
241* The DWORD values within the key must be 0 or they are skipped.
Jon Ashburne39a4f82015-08-28 13:38:21 -0600242* Function return is a string with a ';' separated list of filenames.
Jon Ashburnffad94d2015-06-30 14:46:22 -0700243* Function return is NULL if no valid name/value pairs are found in the key,
244* or the key is not found.
245*
246* \returns
247* A string list of filenames as pointer.
248* When done using the returned string list, pointer should be freed.
249*/
Jon Ashburne39a4f82015-08-28 13:38:21 -0600250static char *loader_get_registry_files(const struct loader_instance *inst, char *location)
Jon Ashburnffad94d2015-06-30 14:46:22 -0700251{
252 LONG rtn_value;
253 HKEY hive, key;
Piers Daniell524ec732015-11-05 16:58:26 -0700254 DWORD access_flags;
Jon Ashburnffad94d2015-06-30 14:46:22 -0700255 char name[2048];
256 char *out = NULL;
Tony Barbourea968902015-07-29 14:26:21 -0600257 char *loc = location;
258 char *next;
Jon Ashburnffad94d2015-06-30 14:46:22 -0700259 DWORD idx = 0;
260 DWORD name_size = sizeof(name);
261 DWORD value;
262 DWORD total_size = 4096;
263 DWORD value_size = sizeof(value);
Tony Barbourea968902015-07-29 14:26:21 -0600264
265 while(*loc)
266 {
267 next = loader_get_next_path(loc);
268 hive = DEFAULT_VK_REGISTRY_HIVE;
Piers Daniell524ec732015-11-05 16:58:26 -0700269 access_flags = KEY_QUERY_VALUE;
Tony Barbourea968902015-07-29 14:26:21 -0600270 rtn_value = RegOpenKeyEx(hive, loc, 0, access_flags, &key);
271 if (rtn_value != ERROR_SUCCESS) {
272 // We didn't find the key. Try the 32-bit hive (where we've seen the
273 // key end up on some people's systems):
274 access_flags |= KEY_WOW64_32KEY;
275 rtn_value = RegOpenKeyEx(hive, loc, 0, access_flags, &key);
276 if (rtn_value != ERROR_SUCCESS) {
277 // We still couldn't find the key, so give up:
278 loc = next;
279 continue;
Jon Ashburnffad94d2015-06-30 14:46:22 -0700280 }
Jon Ashburnffad94d2015-06-30 14:46:22 -0700281 }
Tony Barbourea968902015-07-29 14:26:21 -0600282
Jon Ashburne39a4f82015-08-28 13:38:21 -0600283 while ((rtn_value = RegEnumValue(key, idx++, name, &name_size, NULL, NULL, (LPBYTE) &value, &value_size)) == ERROR_SUCCESS) {
Tony Barbourea968902015-07-29 14:26:21 -0600284 if (value_size == sizeof(value) && value == 0) {
285 if (out == NULL) {
Courtney Goeltzenleuchter2961e1c2015-11-02 17:43:04 -0700286 out = loader_heap_alloc(inst, total_size, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Tony Barbourea968902015-07-29 14:26:21 -0600287 out[0] = '\0';
288 }
289 else if (strlen(out) + name_size + 1 > total_size) {
Courtney Goeltzenleuchter2961e1c2015-11-02 17:43:04 -0700290 out = loader_heap_realloc(inst, out, total_size, total_size * 2, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Tony Barbourea968902015-07-29 14:26:21 -0600291 total_size *= 2;
292 }
293 if (out == NULL) {
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -0700294 loader_log(VK_DEBUG_REPORT_ERROR_BIT, 0, "Out of memory, failed loader_get_registry_files");
Tony Barbourea968902015-07-29 14:26:21 -0600295 return NULL;
296 }
297 if (strlen(out) == 0)
298 snprintf(out, name_size + 1, "%s", name);
299 else
300 snprintf(out + strlen(out), name_size + 2, "%c%s", PATH_SEPERATOR, name);
301 }
302 name_size = 2048;
303 }
304 loc = next;
Jon Ashburnffad94d2015-06-30 14:46:22 -0700305 }
Tony Barbourea968902015-07-29 14:26:21 -0600306
Jon Ashburnffad94d2015-06-30 14:46:22 -0700307 return out;
308}
309
Ian Elliott4470a302015-02-17 10:33:47 -0700310#endif // WIN32
311
Jon Ashburnc7237a72015-08-03 09:08:46 -0600312/**
Daniel Dadap00b4aba2015-09-30 11:50:51 -0500313 * Combine path elements, separating each element with the platform-specific
314 * directory separator, and save the combined string to a destination buffer,
315 * not exceeding the given length. Path elements are given as variadic args,
316 * with a NULL element terminating the list.
317 *
318 * \returns the total length of the combined string, not including an ASCII
319 * NUL termination character. This length may exceed the available storage:
320 * in this case, the written string will be truncated to avoid a buffer
321 * overrun, and the return value will greater than or equal to the storage
322 * size. A NULL argument may be provided as the destination buffer in order
323 * to determine the required string length without actually writing a string.
324 */
325
326static int loader_platform_combine_path(char *dest, int len, ...)
327{
328 int required_len = 0;
329 va_list ap;
330 const char *component;
331
332 va_start(ap, len);
333
334 while((component = va_arg(ap, const char *))) {
335 if (required_len > 0) {
336 // This path element is not the first non-empty element; prepend
337 // a directory separator if space allows
338 if (dest && required_len + 1 < len) {
339 snprintf(dest + required_len, len - required_len, "%c",
340 DIRECTORY_SYMBOL);
341 }
342 required_len++;
343 }
344
345 if (dest && required_len < len) {
346 strncpy(dest + required_len, component, len - required_len);
347 }
348 required_len += strlen(component);
349 }
350
351 va_end(ap);
352
353 // strncpy(3) won't add a NUL terminating byte in the event of truncation.
354 if (dest && required_len >= len) {
355 dest[len - 1] = '\0';
356 }
357
358 return required_len;
359}
360
361
362/**
Jon Ashburnc7237a72015-08-03 09:08:46 -0600363 * Given string of three part form "maj.min.pat" convert to a vulkan version
364 * number.
365 */
366static uint32_t loader_make_version(const char *vers_str)
367{
Jon Ashburn432d2762015-09-18 12:53:16 -0600368 uint32_t vers = 0, major=0, minor=0, patch=0;
Jon Ashburnc7237a72015-08-03 09:08:46 -0600369 char *minor_str= NULL;
370 char *patch_str = NULL;
371 char *cstr;
372 char *str;
373
374 if (!vers_str)
375 return vers;
376 cstr = loader_stack_alloc(strlen(vers_str) + 1);
377 strcpy(cstr, vers_str);
378 while ((str = strchr(cstr, '.')) != NULL) {
379 if (minor_str == NULL) {
380 minor_str = str + 1;
381 *str = '\0';
382 major = atoi(cstr);
383 }
384 else if (patch_str == NULL) {
385 patch_str = str + 1;
386 *str = '\0';
387 minor = atoi(minor_str);
388 }
389 else {
390 return vers;
391 }
392 cstr = str + 1;
393 }
394 patch = atoi(patch_str);
395
396 return VK_MAKE_VERSION(major, minor, patch);
397
398}
399
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600400bool compare_vk_extension_properties(const VkExtensionProperties *op1, const VkExtensionProperties *op2)
401{
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800402 return strcmp(op1->extensionName, op2->extensionName) == 0 ? true : false;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600403}
404
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -0600405/**
Jon Ashburnbd6c4882015-07-02 12:59:25 -0600406 * Search the given ext_array for an extension
407 * matching the given vk_ext_prop
408 */
409bool has_vk_extension_property_array(
410 const VkExtensionProperties *vk_ext_prop,
411 const uint32_t count,
412 const VkExtensionProperties *ext_array)
413{
414 for (uint32_t i = 0; i < count; i++) {
415 if (compare_vk_extension_properties(vk_ext_prop, &ext_array[i]))
416 return true;
417 }
418 return false;
419}
420
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -0600421/**
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600422 * Search the given ext_list for an extension
423 * matching the given vk_ext_prop
424 */
425bool has_vk_extension_property(
426 const VkExtensionProperties *vk_ext_prop,
427 const struct loader_extension_list *ext_list)
428{
429 for (uint32_t i = 0; i < ext_list->count; i++) {
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600430 if (compare_vk_extension_properties(&ext_list->list[i], vk_ext_prop))
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600431 return true;
432 }
433 return false;
434}
435
Jon Ashburnb2ef1372015-07-16 17:19:31 -0600436static inline bool loader_is_layer_type_device(const enum layer_type type) {
437 if ((type & VK_LAYER_TYPE_DEVICE_EXPLICIT) ||
438 (type & VK_LAYER_TYPE_DEVICE_IMPLICIT))
439 return true;
440 return false;
441}
442
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600443/*
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -0600444 * Search the given layer list for a layer matching the given layer name
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600445 */
Jon Ashburne13ecc92015-08-03 17:19:30 -0600446static struct loader_layer_properties *loader_get_layer_property(
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600447 const char *name,
448 const struct loader_layer_list *layer_list)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600449{
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600450 for (uint32_t i = 0; i < layer_list->count; i++) {
451 const VkLayerProperties *item = &layer_list->list[i].info;
452 if (strcmp(name, item->layerName) == 0)
453 return &layer_list->list[i];
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600454 }
455 return NULL;
456}
457
Jon Ashburne13ecc92015-08-03 17:19:30 -0600458/**
459 * Get the next unused layer property in the list. Init the property to zero.
460 */
461static struct loader_layer_properties *loader_get_next_layer_property(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600462 const struct loader_instance *inst,
Jon Ashburne13ecc92015-08-03 17:19:30 -0600463 struct loader_layer_list *layer_list)
464{
465 if (layer_list->capacity == 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600466 layer_list->list = loader_heap_alloc(inst,
467 sizeof(struct loader_layer_properties) * 64,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800468 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburne13ecc92015-08-03 17:19:30 -0600469 if (layer_list->list == NULL) {
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -0700470 loader_log(VK_DEBUG_REPORT_ERROR_BIT, 0, "Out of memory can't add any layer properties to list");
Jon Ashburne13ecc92015-08-03 17:19:30 -0600471 return NULL;
472 }
473 memset(layer_list->list, 0, sizeof(struct loader_layer_properties) * 64);
474 layer_list->capacity = sizeof(struct loader_layer_properties) * 64;
475 }
476
477 // ensure enough room to add an entry
478 if ((layer_list->count + 1) * sizeof (struct loader_layer_properties)
479 > layer_list->capacity) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600480 layer_list->list = loader_heap_realloc(inst, layer_list->list,
481 layer_list->capacity,
482 layer_list->capacity * 2,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800483 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburne13ecc92015-08-03 17:19:30 -0600484 if (layer_list->list == NULL) {
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -0700485 loader_log(VK_DEBUG_REPORT_ERROR_BIT, 0,
Jon Ashburne13ecc92015-08-03 17:19:30 -0600486 "realloc failed for layer list");
487 }
488 layer_list->capacity *= 2;
489 }
490
491 layer_list->count++;
492 return &(layer_list->list[layer_list->count - 1]);
493}
494
495/**
496 * Remove all layer properties entrys from the list
497 */
Jon Ashburne39a4f82015-08-28 13:38:21 -0600498void loader_delete_layer_properties(
499 const struct loader_instance *inst,
500 struct loader_layer_list *layer_list)
Jon Ashburne13ecc92015-08-03 17:19:30 -0600501{
Jon Ashburn39fbd4e2015-12-10 18:17:34 -0700502 uint32_t i, j;
503 struct loader_device_extension_list *dev_ext_list;
Jon Ashburnb82c1852015-08-11 14:49:54 -0600504 if (!layer_list)
505 return;
506
Jon Ashburne13ecc92015-08-03 17:19:30 -0600507 for (i = 0; i < layer_list->count; i++) {
Jon Ashburn6e6a2162015-12-10 08:51:10 -0700508 loader_destroy_generic_list(inst, (struct loader_generic_list *)
509 &layer_list->list[i].instance_extension_list);
Jon Ashburn39fbd4e2015-12-10 18:17:34 -0700510 dev_ext_list = &layer_list->list[i].device_extension_list;
511 if (dev_ext_list->capacity > 0 && dev_ext_list->list->entrypoint_count > 0) {
512 for (j= 0; j < dev_ext_list->list->entrypoint_count; j++) {
513 loader_heap_free(inst, dev_ext_list->list->entrypoints[j]);
514 }
515 loader_heap_free(inst, dev_ext_list->list->entrypoints);
516 }
Jon Ashburn6e6a2162015-12-10 08:51:10 -0700517 loader_destroy_generic_list(inst, (struct loader_generic_list *)
Jon Ashburn39fbd4e2015-12-10 18:17:34 -0700518 dev_ext_list);
Jon Ashburne13ecc92015-08-03 17:19:30 -0600519 }
520 layer_list->count = 0;
521
Jon Ashburnb82c1852015-08-11 14:49:54 -0600522 if (layer_list->capacity > 0) {
523 layer_list->capacity = 0;
Jon Ashburne39a4f82015-08-28 13:38:21 -0600524 loader_heap_free(inst, layer_list->list);
Jon Ashburnb82c1852015-08-11 14:49:54 -0600525 }
Jon Ashburne13ecc92015-08-03 17:19:30 -0600526
527}
528
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600529static void loader_add_global_extensions(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600530 const struct loader_instance *inst,
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -0600531 const PFN_vkEnumerateInstanceExtensionProperties fp_get_props,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600532 const char *lib_name,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600533 struct loader_extension_list *ext_list)
534{
535 uint32_t i, count;
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600536 VkExtensionProperties *ext_props;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600537 VkResult res;
538
Courtney Goeltzenleuchter5c6cf472015-07-06 22:28:18 -0600539 if (!fp_get_props) {
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -0600540 /* No EnumerateInstanceExtensionProperties defined */
Courtney Goeltzenleuchter5c6cf472015-07-06 22:28:18 -0600541 return;
542 }
543
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600544 res = fp_get_props(NULL, &count, NULL);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600545 if (res != VK_SUCCESS) {
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -0700546 loader_log(VK_DEBUG_REPORT_WARN_BIT, 0, "Error getting global extension count from %s", lib_name);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600547 return;
548 }
Jon Ashburn953bb3c2015-06-10 16:11:42 -0600549
Courtney Goeltzenleuchter5c6cf472015-07-06 22:28:18 -0600550 if (count == 0) {
551 /* No ExtensionProperties to report */
552 return;
553 }
554
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600555 ext_props = loader_stack_alloc(count * sizeof(VkExtensionProperties));
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600556
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600557 res = fp_get_props(NULL, &count, ext_props);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600558 if (res != VK_SUCCESS) {
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -0700559 loader_log(VK_DEBUG_REPORT_WARN_BIT, 0, "Error getting global extensions from %s", lib_name);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600560 return;
561 }
Tony Barbour59a47322015-06-24 16:06:58 -0600562
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600563 for (i = 0; i < count; i++) {
Courtney Goeltzenleuchter53043732015-07-12 13:20:05 -0600564 char spec_version[64];
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600565
566 snprintf(spec_version, sizeof(spec_version), "%d.%d.%d",
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600567 VK_MAJOR(ext_props[i].specVersion),
568 VK_MINOR(ext_props[i].specVersion),
569 VK_PATCH(ext_props[i].specVersion));
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -0700570 loader_log(VK_DEBUG_REPORT_DEBUG_BIT, 0,
Courtney Goeltzenleuchter53043732015-07-12 13:20:05 -0600571 "Global Extension: %s (%s) version %s",
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800572 ext_props[i].extensionName, lib_name, spec_version);
Jon Ashburne39a4f82015-08-28 13:38:21 -0600573 loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600574 }
575
576 return;
577}
578
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700579/*
580 * Initialize ext_list with the physical device extensions.
581 * The extension properties are passed as inputs in count and ext_props.
582 */
583static VkResult loader_init_physical_device_extensions(
584 const struct loader_instance *inst,
585 struct loader_physical_device *phys_dev,
586 uint32_t count,
587 VkExtensionProperties *ext_props,
588 struct loader_extension_list *ext_list)
589{
590 VkResult res;
591 uint32_t i;
592
Jon Ashburn6e6a2162015-12-10 08:51:10 -0700593 if (!loader_init_generic_list(inst, (struct loader_generic_list *) ext_list,
594 sizeof(VkExtensionProperties))) {
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700595 return VK_ERROR_OUT_OF_HOST_MEMORY;
596 }
597
598 for (i = 0; i < count; i++) {
599 char spec_version[64];
600
601 snprintf(spec_version, sizeof (spec_version), "%d.%d.%d",
602 VK_MAJOR(ext_props[i].specVersion),
603 VK_MINOR(ext_props[i].specVersion),
604 VK_PATCH(ext_props[i].specVersion));
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -0700605 loader_log(VK_DEBUG_REPORT_DEBUG_BIT, 0,
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700606 "PhysicalDevice Extension: %s (%s) version %s",
607 ext_props[i].extensionName, phys_dev->this_icd->this_icd_lib->lib_name, spec_version);
608 res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
609 if (res != VK_SUCCESS)
610 return res;
611 }
612
613 return VK_SUCCESS;
614}
615
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700616static VkResult loader_add_physical_device_extensions(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600617 const struct loader_instance *inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600618 VkPhysicalDevice physical_device,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600619 const char *lib_name,
620 struct loader_extension_list *ext_list)
621{
622 uint32_t i, count;
623 VkResult res;
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600624 VkExtensionProperties *ext_props;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600625
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700626 res = loader_EnumerateDeviceExtensionProperties(physical_device, NULL, &count, NULL);
627 if (res == VK_SUCCESS && count > 0) {
628 ext_props = loader_stack_alloc(count * sizeof (VkExtensionProperties));
629 if (!ext_props)
630 return VK_ERROR_OUT_OF_HOST_MEMORY;
631 res = loader_EnumerateDeviceExtensionProperties(physical_device, NULL, &count, ext_props);
632 if (res != VK_SUCCESS)
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700633 return res;
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700634 for (i = 0; i < count; i++) {
635 char spec_version[64];
636
637 snprintf(spec_version, sizeof (spec_version), "%d.%d.%d",
638 VK_MAJOR(ext_props[i].specVersion),
639 VK_MINOR(ext_props[i].specVersion),
640 VK_PATCH(ext_props[i].specVersion));
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -0700641 loader_log(VK_DEBUG_REPORT_DEBUG_BIT, 0,
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700642 "PhysicalDevice Extension: %s (%s) version %s",
643 ext_props[i].extensionName, lib_name, spec_version);
644 res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
645 if (res != VK_SUCCESS)
646 return res;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600647 }
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700648 } else {
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -0700649 loader_log(VK_DEBUG_REPORT_ERROR_BIT, 0, "Error getting physical device extension info count from library %s", lib_name);
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700650 return res;
651 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600652
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700653 return VK_SUCCESS;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600654}
655
Jon Ashburn6e6a2162015-12-10 08:51:10 -0700656static bool loader_init_generic_list(const struct loader_instance *inst,
657 struct loader_generic_list *list_info,
658 size_t element_size)
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600659{
Jon Ashburn6e6a2162015-12-10 08:51:10 -0700660 list_info->capacity = 32 * element_size;
661 list_info->list = loader_heap_alloc(inst, list_info->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
662 if (list_info->list == NULL) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600663 return false;
664 }
Jon Ashburn6e6a2162015-12-10 08:51:10 -0700665 memset(list_info->list, 0, list_info->capacity);
666 list_info->count = 0;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600667 return true;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600668}
669
Jon Ashburn6e6a2162015-12-10 08:51:10 -0700670void loader_destroy_generic_list(const struct loader_instance *inst,
671 struct loader_generic_list *list)
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600672{
Jon Ashburn6e6a2162015-12-10 08:51:10 -0700673 loader_heap_free(inst, list->list);
674 list->count = 0;
675 list->capacity = 0;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600676}
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600677
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600678/*
679 * Append non-duplicate extension properties defined in props
680 * to the given ext_list.
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700681 * Return
682 * Vk_SUCCESS on success
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600683 */
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700684VkResult loader_add_to_ext_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600685 const struct loader_instance *inst,
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600686 struct loader_extension_list *ext_list,
687 uint32_t prop_list_count,
688 const VkExtensionProperties *props)
689{
690 uint32_t i;
691 const VkExtensionProperties *cur_ext;
692
693 if (ext_list->list == NULL || ext_list->capacity == 0) {
Jon Ashburn6e6a2162015-12-10 08:51:10 -0700694 loader_init_generic_list(inst, (struct loader_generic_list *) ext_list,
695 sizeof(VkExtensionProperties));
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600696 }
697
698 if (ext_list->list == NULL)
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700699 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600700
701 for (i = 0; i < prop_list_count; i++) {
702 cur_ext = &props[i];
703
704 // look for duplicates
705 if (has_vk_extension_property(cur_ext, ext_list)) {
706 continue;
707 }
708
709 // add to list at end
710 // check for enough capacity
711 if (ext_list->count * sizeof(VkExtensionProperties)
712 >= ext_list->capacity) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600713
714 ext_list->list = loader_heap_realloc(inst,
715 ext_list->list,
716 ext_list->capacity,
717 ext_list->capacity * 2,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800718 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700719
720 if (ext_list->list == NULL)
721 return VK_ERROR_OUT_OF_HOST_MEMORY;
722
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600723 // double capacity
724 ext_list->capacity *= 2;
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600725 }
726
727 memcpy(&ext_list->list[ext_list->count], cur_ext, sizeof(VkExtensionProperties));
728 ext_list->count++;
729 }
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700730 return VK_SUCCESS;
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600731}
732
Jon Ashburn39fbd4e2015-12-10 18:17:34 -0700733/*
734 * Append one extension property defined in props with entrypoints
735 * defined in entrys to the given ext_list.
736 * Return
737 * Vk_SUCCESS on success
738 */
739VkResult loader_add_to_dev_ext_list(
740 const struct loader_instance *inst,
741 struct loader_device_extension_list *ext_list,
742 const VkExtensionProperties *props,
743 uint32_t entry_count,
744 char **entrys)
745{
746 uint32_t idx;
747 if (ext_list->list == NULL || ext_list->capacity == 0) {
748 loader_init_generic_list(inst, (struct loader_generic_list *) ext_list,
749 sizeof(struct loader_dev_ext_props));
750 }
751
752 if (ext_list->list == NULL)
753 return VK_ERROR_OUT_OF_HOST_MEMORY;
754
755 idx =ext_list->count;
756 // add to list at end
757 // check for enough capacity
758 if (idx * sizeof (struct loader_dev_ext_props)
759 >= ext_list->capacity) {
760
761 ext_list->list = loader_heap_realloc(inst,
762 ext_list->list,
763 ext_list->capacity,
764 ext_list->capacity * 2,
765 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
766
767 if (ext_list->list == NULL)
768 return VK_ERROR_OUT_OF_HOST_MEMORY;
769
770 // double capacity
771 ext_list->capacity *= 2;
772 }
773
774 memcpy(&ext_list->list[idx].props, props, sizeof(struct loader_dev_ext_props));
775 ext_list->list[idx].entrypoint_count = entry_count;
776 ext_list->list[idx].entrypoints = loader_heap_alloc(inst,
777 sizeof(char *) * entry_count,
778 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
779 if (ext_list->list[idx].entrypoints == NULL)
780 return VK_ERROR_OUT_OF_HOST_MEMORY;
781 for (uint32_t i = 0; i < entry_count; i++) {
782 ext_list->list[idx].entrypoints[i] = loader_heap_alloc(inst,
783 strlen(entrys[i]) + 1,
784 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
785 if (ext_list->list[idx].entrypoints[i] == NULL)
786 return VK_ERROR_OUT_OF_HOST_MEMORY;
787 strcpy(ext_list->list[idx].entrypoints[i], entrys[i]);
788 }
789 ext_list->count++;
790
791 return VK_SUCCESS;
792}
793
Jon Ashburnbd6c4882015-07-02 12:59:25 -0600794/**
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600795 * Search the given search_list for any layers in the props list.
796 * Add these to the output layer_list. Don't add duplicates to the output layer_list.
Jon Ashburnbd6c4882015-07-02 12:59:25 -0600797 */
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -0600798static VkResult loader_add_layer_names_to_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600799 const struct loader_instance *inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600800 struct loader_layer_list *output_list,
801 uint32_t name_count,
802 const char * const *names,
803 const struct loader_layer_list *search_list)
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600804{
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600805 struct loader_layer_properties *layer_prop;
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -0600806 VkResult err = VK_SUCCESS;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600807
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600808 for (uint32_t i = 0; i < name_count; i++) {
809 const char *search_target = names[i];
Jon Ashburne13ecc92015-08-03 17:19:30 -0600810 layer_prop = loader_get_layer_property(search_target, search_list);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600811 if (!layer_prop) {
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -0700812 loader_log(VK_DEBUG_REPORT_ERROR_BIT, 0, "Unable to find layer %s", search_target);
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -0600813 err = VK_ERROR_LAYER_NOT_PRESENT;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600814 continue;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600815 }
816
Jon Ashburne39a4f82015-08-28 13:38:21 -0600817 loader_add_to_layer_list(inst, output_list, 1, layer_prop);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600818 }
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -0600819
820 return err;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600821}
822
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600823
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600824/*
825 * Manage lists of VkLayerProperties
826 */
Jon Ashburne39a4f82015-08-28 13:38:21 -0600827static bool loader_init_layer_list(const struct loader_instance *inst,
828 struct loader_layer_list *list)
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600829{
830 list->capacity = 32 * sizeof(struct loader_layer_properties);
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800831 list->list = loader_heap_alloc(inst, list->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600832 if (list->list == NULL) {
833 return false;
834 }
835 memset(list->list, 0, list->capacity);
836 list->count = 0;
837 return true;
838}
839
Jon Ashburne39a4f82015-08-28 13:38:21 -0600840void loader_destroy_layer_list(const struct loader_instance *inst,
841 struct loader_layer_list *layer_list)
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600842{
Jon Ashburne39a4f82015-08-28 13:38:21 -0600843 loader_heap_free(inst, layer_list->list);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600844 layer_list->count = 0;
845 layer_list->capacity = 0;
846}
847
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600848/*
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600849 * Manage list of layer libraries (loader_lib_info)
850 */
Jon Ashburne39a4f82015-08-28 13:38:21 -0600851static bool loader_init_layer_library_list(const struct loader_instance *inst,
852 struct loader_layer_library_list *list)
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600853{
854 list->capacity = 32 * sizeof(struct loader_lib_info);
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800855 list->list = loader_heap_alloc(inst, list->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600856 if (list->list == NULL) {
857 return false;
858 }
859 memset(list->list, 0, list->capacity);
860 list->count = 0;
861 return true;
862}
863
Jon Ashburne39a4f82015-08-28 13:38:21 -0600864void loader_destroy_layer_library_list(const struct loader_instance *inst,
865 struct loader_layer_library_list *list)
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600866{
867 for (uint32_t i = 0; i < list->count; i++) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600868 loader_heap_free(inst, list->list[i].lib_name);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600869 }
Jon Ashburne39a4f82015-08-28 13:38:21 -0600870 loader_heap_free(inst, list->list);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600871 list->count = 0;
872 list->capacity = 0;
873}
874
875void loader_add_to_layer_library_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600876 const struct loader_instance *inst,
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600877 struct loader_layer_library_list *list,
878 uint32_t item_count,
879 const struct loader_lib_info *new_items)
880{
881 uint32_t i;
882 struct loader_lib_info *item;
883
884 if (list->list == NULL || list->capacity == 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600885 loader_init_layer_library_list(inst, list);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600886 }
887
888 if (list->list == NULL)
889 return;
890
891 for (i = 0; i < item_count; i++) {
892 item = (struct loader_lib_info *) &new_items[i];
893
894 // look for duplicates
895 for (uint32_t j = 0; j < list->count; j++) {
896 if (strcmp(list->list[i].lib_name, new_items->lib_name) == 0) {
897 continue;
898 }
899 }
900
901 // add to list at end
902 // check for enough capacity
903 if (list->count * sizeof(struct loader_lib_info)
904 >= list->capacity) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600905
906 list->list = loader_heap_realloc(inst,
907 list->list,
908 list->capacity,
909 list->capacity * 2,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800910 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600911 // double capacity
912 list->capacity *= 2;
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600913 }
914
915 memcpy(&list->list[list->count], item, sizeof(struct loader_lib_info));
916 list->count++;
917 }
918}
919
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600920
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600921/*
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600922 * Search the given layer list for a list
923 * matching the given VkLayerProperties
924 */
925bool has_vk_layer_property(
926 const VkLayerProperties *vk_layer_prop,
927 const struct loader_layer_list *list)
928{
929 for (uint32_t i = 0; i < list->count; i++) {
930 if (strcmp(vk_layer_prop->layerName, list->list[i].info.layerName) == 0)
931 return true;
932 }
933 return false;
934}
935
936/*
937 * Search the given layer list for a layer
938 * matching the given name
939 */
940bool has_layer_name(
941 const char *name,
942 const struct loader_layer_list *list)
943{
944 for (uint32_t i = 0; i < list->count; i++) {
945 if (strcmp(name, list->list[i].info.layerName) == 0)
946 return true;
947 }
948 return false;
949}
950
951/*
952 * Append non-duplicate layer properties defined in prop_list
953 * to the given layer_info list
954 */
955void loader_add_to_layer_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600956 const struct loader_instance *inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600957 struct loader_layer_list *list,
958 uint32_t prop_list_count,
959 const struct loader_layer_properties *props)
960{
961 uint32_t i;
962 struct loader_layer_properties *layer;
963
964 if (list->list == NULL || list->capacity == 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600965 loader_init_layer_list(inst, list);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600966 }
967
968 if (list->list == NULL)
969 return;
970
971 for (i = 0; i < prop_list_count; i++) {
972 layer = (struct loader_layer_properties *) &props[i];
973
974 // look for duplicates
975 if (has_vk_layer_property(&layer->info, list)) {
976 continue;
977 }
978
979 // add to list at end
980 // check for enough capacity
981 if (list->count * sizeof(struct loader_layer_properties)
982 >= list->capacity) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600983
984 list->list = loader_heap_realloc(inst,
985 list->list,
986 list->capacity,
987 list->capacity * 2,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800988 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600989 // double capacity
990 list->capacity *= 2;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600991 }
992
993 memcpy(&list->list[list->count], layer, sizeof(struct loader_layer_properties));
994 list->count++;
995 }
996}
997
Jon Ashburnbd332cc2015-07-07 10:27:45 -0600998/**
999 * Search the search_list for any layer with a name
1000 * that matches the given name and a type that matches the given type
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06001001 * Add all matching layers to the found_list
Jon Ashburnbd332cc2015-07-07 10:27:45 -06001002 * Do not add if found loader_layer_properties is already
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06001003 * on the found_list.
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001004 */
Jon Ashburnbd6c4882015-07-02 12:59:25 -06001005static void loader_find_layer_name_add_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -06001006 const struct loader_instance *inst,
Jon Ashburnbd6c4882015-07-02 12:59:25 -06001007 const char *name,
Jon Ashburnbd332cc2015-07-07 10:27:45 -06001008 const enum layer_type type,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06001009 const struct loader_layer_list *search_list,
1010 struct loader_layer_list *found_list)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001011{
Jon Ashburn56151d62015-10-05 09:03:21 -06001012 bool found = false;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001013 for (uint32_t i = 0; i < search_list->count; i++) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06001014 struct loader_layer_properties *layer_prop = &search_list->list[i];
Jon Ashburnbd332cc2015-07-07 10:27:45 -06001015 if (0 == strcmp(layer_prop->info.layerName, name) &&
1016 (layer_prop->type & type)) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06001017 /* Found a layer with the same name, add to found_list */
Jon Ashburne39a4f82015-08-28 13:38:21 -06001018 loader_add_to_layer_list(inst, found_list, 1, layer_prop);
Jon Ashburn56151d62015-10-05 09:03:21 -06001019 found = true;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001020 }
1021 }
Jon Ashburn56151d62015-10-05 09:03:21 -06001022 if (!found) {
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07001023 loader_log(VK_DEBUG_REPORT_WARN_BIT, 0, "Warning, couldn't find layer name %s to activate", name);
Jon Ashburn56151d62015-10-05 09:03:21 -06001024 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001025}
1026
Jon Ashburn5c042ea2015-08-04 11:14:18 -06001027static VkExtensionProperties *get_extension_property(
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06001028 const char *name,
1029 const struct loader_extension_list *list)
Jon Ashburnfc2e38c2015-04-14 09:15:32 -06001030{
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06001031 for (uint32_t i = 0; i < list->count; i++) {
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001032 if (strcmp(name, list->list[i].extensionName) == 0)
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06001033 return &list->list[i];
Jon Ashburnfc2e38c2015-04-14 09:15:32 -06001034 }
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06001035 return NULL;
Jon Ashburnfc2e38c2015-04-14 09:15:32 -06001036}
1037
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001038static VkExtensionProperties *get_dev_extension_property(
1039 const char *name,
1040 const struct loader_device_extension_list *list)
1041{
1042 for (uint32_t i = 0; i < list->count; i++) {
1043 if (strcmp(name, list->list[i].props.extensionName) == 0)
1044 return &list->list[i].props;
1045 }
1046 return NULL;
1047}
1048
Jon Ashburnbd6c4882015-07-02 12:59:25 -06001049/*
Jon Ashburn232e3af2015-11-30 17:21:25 -07001050 * For global extensions implemented within the loader (i.e. DEBUG_REPORT
Jon Ashburnbd6c4882015-07-02 12:59:25 -06001051 * the extension must provide two entry points for the loader to use:
1052 * - "trampoline" entry point - this is the address returned by GetProcAddr
1053 * and will always do what's necessary to support a global call.
1054 * - "terminator" function - this function will be put at the end of the
Jon Ashburn232e3af2015-11-30 17:21:25 -07001055 * instance chain and will contain the necessary logic to call / process
Jon Ashburnbd6c4882015-07-02 12:59:25 -06001056 * the extension for the appropriate ICDs that are available.
1057 * There is no generic mechanism for including these functions, the references
1058 * must be placed into the appropriate loader entry points.
1059 * GetInstanceProcAddr: call extension GetInstanceProcAddr to check for GetProcAddr requests
1060 * loader_coalesce_extensions(void) - add extension records to the list of global
1061 * extension available to the app.
1062 * instance_disp - add function pointer for terminator function to this array.
1063 * The extension itself should be in a separate file that will be
1064 * linked directly with the loader.
1065 */
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06001066
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001067void loader_get_icd_loader_instance_extensions(
Jon Ashburne39a4f82015-08-28 13:38:21 -06001068 const struct loader_instance *inst,
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001069 struct loader_icd_libs *icd_libs,
1070 struct loader_extension_list *inst_exts)
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001071{
Jon Ashburn5c6a46f2015-08-14 14:49:22 -06001072 struct loader_extension_list icd_exts;
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07001073 loader_log(VK_DEBUG_REPORT_DEBUG_BIT, 0, "Build ICD instance extension list");
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001074 // traverse scanned icd list adding non-duplicate extensions to the list
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001075 for (uint32_t i = 0; i < icd_libs->count; i++) {
Jon Ashburn6e6a2162015-12-10 08:51:10 -07001076 loader_init_generic_list(inst, (struct loader_generic_list *) &icd_exts,
1077 sizeof(VkExtensionProperties));
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06001078 loader_add_global_extensions(inst, icd_libs->list[i].EnumerateInstanceExtensionProperties,
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001079 icd_libs->list[i].lib_name,
Jon Ashburn5c6a46f2015-08-14 14:49:22 -06001080 &icd_exts);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001081 loader_add_to_ext_list(inst, inst_exts,
Jon Ashburn5c6a46f2015-08-14 14:49:22 -06001082 icd_exts.count,
1083 icd_exts.list);
Jon Ashburn6e6a2162015-12-10 08:51:10 -07001084 loader_destroy_generic_list(inst, (struct loader_generic_list *) &icd_exts);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001085 };
1086
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001087 // Traverse loader's extensions, adding non-duplicate extensions to the list
Ian Elliott954fa342015-10-30 15:28:23 -06001088 wsi_add_instance_extensions(inst, inst_exts);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001089 debug_report_add_instance_extensions(inst, inst_exts);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001090}
1091
Jon Ashburn46674bf2015-12-11 09:41:34 -07001092struct loader_physical_device *loader_get_physical_device(const VkPhysicalDevice physdev)
1093{
1094 uint32_t i;
1095 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
1096 for (i = 0; i < inst->total_gpu_count; i++) {
1097 //TODO this aliases physDevices within instances, need for this
1098 // function to go away
1099 if (inst->phys_devs[i].disp == loader_get_instance_dispatch(physdev)) {
1100 return &inst->phys_devs[i];
1101 }
1102 }
1103 }
1104 return NULL;
1105}
1106
Jon Ashburne39a4f82015-08-28 13:38:21 -06001107struct loader_icd *loader_get_icd_and_device(const VkDevice device,
1108 struct loader_device **found_dev)
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001109{
1110 *found_dev = NULL;
1111 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
1112 for (struct loader_icd *icd = inst->icds; icd; icd = icd->next) {
1113 for (struct loader_device *dev = icd->logical_device_list; dev; dev = dev->next)
Jon Ashburne0e64572015-09-30 12:56:42 -06001114 /* Value comparison of device prevents object wrapping by layers */
1115 if (loader_get_dispatch(dev->device) == loader_get_dispatch(device)) {
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001116 *found_dev = dev;
1117 return icd;
1118 }
1119 }
1120 }
1121 return NULL;
1122}
1123
Jon Ashburne39a4f82015-08-28 13:38:21 -06001124static void loader_destroy_logical_device(const struct loader_instance *inst,
1125 struct loader_device *dev)
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001126{
Jon Ashburne39a4f82015-08-28 13:38:21 -06001127 loader_heap_free(inst, dev->app_extension_props);
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001128 if (dev->activated_layer_list.count)
Jon Ashburne39a4f82015-08-28 13:38:21 -06001129 loader_destroy_layer_list(inst, &dev->activated_layer_list);
1130 loader_heap_free(inst, dev);
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001131}
1132
Jon Ashburne39a4f82015-08-28 13:38:21 -06001133static struct loader_device *loader_add_logical_device(
1134 const struct loader_instance *inst,
1135 const VkDevice dev,
1136 struct loader_device **device_list)
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001137{
1138 struct loader_device *new_dev;
1139
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001140 new_dev = loader_heap_alloc(inst, sizeof(struct loader_device), VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001141 if (!new_dev) {
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07001142 loader_log(VK_DEBUG_REPORT_ERROR_BIT, 0, "Failed to alloc struct laoder-device");
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001143 return NULL;
1144 }
1145
1146 memset(new_dev, 0, sizeof(struct loader_device));
1147
1148 new_dev->next = *device_list;
1149 new_dev->device = dev;
1150 *device_list = new_dev;
1151 return new_dev;
1152}
1153
Jon Ashburne39a4f82015-08-28 13:38:21 -06001154void loader_remove_logical_device(
1155 const struct loader_instance *inst,
Jon Ashburn781a7ae2015-11-19 15:43:26 -07001156 struct loader_icd *icd,
1157 struct loader_device *found_dev)
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001158{
Jon Ashburn781a7ae2015-11-19 15:43:26 -07001159 struct loader_device *dev, *prev_dev;
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001160
1161 if (!icd || !found_dev)
1162 return;
1163
1164 prev_dev = NULL;
1165 dev = icd->logical_device_list;
1166 while (dev && dev != found_dev) {
1167 prev_dev = dev;
1168 dev = dev->next;
1169 }
1170
1171 if (prev_dev)
1172 prev_dev->next = found_dev->next;
1173 else
1174 icd->logical_device_list = found_dev->next;
Jon Ashburne39a4f82015-08-28 13:38:21 -06001175 loader_destroy_logical_device(inst, found_dev);
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001176}
1177
1178
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001179static void loader_icd_destroy(
1180 struct loader_instance *ptr_inst,
1181 struct loader_icd *icd)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001182{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001183 ptr_inst->total_icd_count--;
Courtney Goeltzenleuchter1f157ac2015-06-14 19:57:15 -06001184 for (struct loader_device *dev = icd->logical_device_list; dev; ) {
1185 struct loader_device *next_dev = dev->next;
Jon Ashburne39a4f82015-08-28 13:38:21 -06001186 loader_destroy_logical_device(ptr_inst, dev);
Courtney Goeltzenleuchter1f157ac2015-06-14 19:57:15 -06001187 dev = next_dev;
1188 }
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001189
Jon Ashburne39a4f82015-08-28 13:38:21 -06001190 loader_heap_free(ptr_inst, icd);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001191}
1192
Jon Ashburne39a4f82015-08-28 13:38:21 -06001193static struct loader_icd * loader_icd_create(const struct loader_instance *inst)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001194{
1195 struct loader_icd *icd;
1196
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001197 icd = loader_heap_alloc(inst, sizeof(*icd), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001198 if (!icd)
1199 return NULL;
1200
Courtney Goeltzenleuchter55001bb2014-10-28 10:29:27 -06001201 memset(icd, 0, sizeof(*icd));
1202
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001203 return icd;
1204}
1205
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001206static struct loader_icd *loader_icd_add(
1207 struct loader_instance *ptr_inst,
Jon Ashburn3d002332015-08-20 16:35:30 -06001208 const struct loader_scanned_icds *icd_lib)
Chia-I Wu13a61a52014-08-04 11:18:20 +08001209{
1210 struct loader_icd *icd;
1211
Jon Ashburne39a4f82015-08-28 13:38:21 -06001212 icd = loader_icd_create(ptr_inst);
Chia-I Wu13a61a52014-08-04 11:18:20 +08001213 if (!icd)
1214 return NULL;
1215
Jon Ashburn3d002332015-08-20 16:35:30 -06001216 icd->this_icd_lib = icd_lib;
1217 icd->this_instance = ptr_inst;
1218
Chia-I Wu13a61a52014-08-04 11:18:20 +08001219 /* prepend to the list */
Jon Ashburn46888392015-01-29 15:45:51 -07001220 icd->next = ptr_inst->icds;
1221 ptr_inst->icds = icd;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001222 ptr_inst->total_icd_count++;
Chia-I Wu13a61a52014-08-04 11:18:20 +08001223
1224 return icd;
1225}
1226
Jon Ashburne39a4f82015-08-28 13:38:21 -06001227void loader_scanned_icd_clear(
1228 const struct loader_instance *inst,
1229 struct loader_icd_libs *icd_libs)
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001230{
1231 if (icd_libs->capacity == 0)
1232 return;
1233 for (uint32_t i = 0; i < icd_libs->count; i++) {
1234 loader_platform_close_library(icd_libs->list[i].handle);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001235 loader_heap_free(inst, icd_libs->list[i].lib_name);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001236 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06001237 loader_heap_free(inst, icd_libs->list);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001238 icd_libs->capacity = 0;
1239 icd_libs->count = 0;
1240 icd_libs->list = NULL;
1241}
1242
Jon Ashburne39a4f82015-08-28 13:38:21 -06001243static void loader_scanned_icd_init(const struct loader_instance *inst,
1244 struct loader_icd_libs *icd_libs)
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001245{
Jon Ashburne39a4f82015-08-28 13:38:21 -06001246 loader_scanned_icd_clear(inst, icd_libs);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001247 icd_libs->capacity = 8 * sizeof(struct loader_scanned_icds);
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001248 icd_libs->list = loader_heap_alloc(inst, icd_libs->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001249
1250}
1251
1252static void loader_scanned_icd_add(
Jon Ashburne39a4f82015-08-28 13:38:21 -06001253 const struct loader_instance *inst,
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001254 struct loader_icd_libs *icd_libs,
Jon Ashburn005617f2015-11-17 17:35:40 -07001255 const char *filename,
1256 uint32_t api_version)
Jon Ashburn46d1f582015-01-28 11:01:35 -07001257{
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001258 loader_platform_dl_handle handle;
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06001259 PFN_vkCreateInstance fp_create_inst;
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06001260 PFN_vkEnumerateInstanceExtensionProperties fp_get_global_ext_props;
Jon Ashburnc624c882015-07-16 10:17:29 -06001261 PFN_vkGetInstanceProcAddr fp_get_proc_addr;
Jon Ashburn46d1f582015-01-28 11:01:35 -07001262 struct loader_scanned_icds *new_node;
1263
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001264 /* TODO implement ref counting of libraries, for now this function leaves
1265 libraries open and the scanned_icd_clear closes them */
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001266 // Used to call: dlopen(filename, RTLD_LAZY);
1267 handle = loader_platform_open_library(filename);
Jon Ashburn46d1f582015-01-28 11:01:35 -07001268 if (!handle) {
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07001269 loader_log(VK_DEBUG_REPORT_WARN_BIT, 0, loader_platform_open_library_error(filename));
Jon Ashburn46d1f582015-01-28 11:01:35 -07001270 return;
1271 }
1272
Jon Ashburnc624c882015-07-16 10:17:29 -06001273#define LOOKUP_LD(func_ptr, func) do { \
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -06001274 func_ptr = (PFN_vk ##func) loader_platform_get_proc_address(handle, "vk" #func); \
Jon Ashburn46d1f582015-01-28 11:01:35 -07001275 if (!func_ptr) { \
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07001276 loader_log(VK_DEBUG_REPORT_WARN_BIT, 0, loader_platform_get_proc_address_error("vk" #func)); \
Jon Ashburn46d1f582015-01-28 11:01:35 -07001277 return; \
1278 } \
1279} while (0)
1280
Jon Ashburnc624c882015-07-16 10:17:29 -06001281 LOOKUP_LD(fp_get_proc_addr, GetInstanceProcAddr);
1282 LOOKUP_LD(fp_create_inst, CreateInstance);
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06001283 LOOKUP_LD(fp_get_global_ext_props, EnumerateInstanceExtensionProperties);
Jon Ashburnc624c882015-07-16 10:17:29 -06001284
1285#undef LOOKUP_LD
Jon Ashburn46d1f582015-01-28 11:01:35 -07001286
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001287 // check for enough capacity
1288 if ((icd_libs->count * sizeof(struct loader_scanned_icds)) >= icd_libs->capacity) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06001289
1290 icd_libs->list = loader_heap_realloc(inst,
1291 icd_libs->list,
1292 icd_libs->capacity,
1293 icd_libs->capacity * 2,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001294 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001295 // double capacity
1296 icd_libs->capacity *= 2;
Jon Ashburn46d1f582015-01-28 11:01:35 -07001297 }
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001298 new_node = &(icd_libs->list[icd_libs->count]);
Jon Ashburn46d1f582015-01-28 11:01:35 -07001299
1300 new_node->handle = handle;
Jon Ashburn005617f2015-11-17 17:35:40 -07001301 new_node->api_version = api_version;
Jon Ashburnc624c882015-07-16 10:17:29 -06001302 new_node->GetInstanceProcAddr = fp_get_proc_addr;
Jon Ashburn46888392015-01-29 15:45:51 -07001303 new_node->CreateInstance = fp_create_inst;
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06001304 new_node->EnumerateInstanceExtensionProperties = fp_get_global_ext_props;
Jon Ashburn46d1f582015-01-28 11:01:35 -07001305
Jon Ashburne39a4f82015-08-28 13:38:21 -06001306 new_node->lib_name = (char *) loader_heap_alloc(inst,
1307 strlen(filename) + 1,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001308 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001309 if (!new_node->lib_name) {
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07001310 loader_log(VK_DEBUG_REPORT_WARN_BIT, 0, "Out of memory can't add icd");
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001311 return;
1312 }
1313 strcpy(new_node->lib_name, filename);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001314 icd_libs->count++;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001315}
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001316
Jon Ashburnc624c882015-07-16 10:17:29 -06001317static bool loader_icd_init_entrys(struct loader_icd *icd,
1318 VkInstance inst,
1319 const PFN_vkGetInstanceProcAddr fp_gipa)
Jon Ashburn3da71f22015-05-14 12:43:38 -06001320{
1321 /* initialize entrypoint function pointers */
1322
Jon Ashburnc624c882015-07-16 10:17:29 -06001323 #define LOOKUP_GIPA(func, required) do { \
1324 icd->func = (PFN_vk ##func) fp_gipa(inst, "vk" #func); \
1325 if (!icd->func && required) { \
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07001326 loader_log(VK_DEBUG_REPORT_WARN_BIT, 0, \
Jon Ashburnc624c882015-07-16 10:17:29 -06001327 loader_platform_get_proc_address_error("vk" #func)); \
1328 return false; \
1329 } \
Jon Ashburn3da71f22015-05-14 12:43:38 -06001330 } while (0)
1331
Jon Ashburnc624c882015-07-16 10:17:29 -06001332 LOOKUP_GIPA(GetDeviceProcAddr, true);
1333 LOOKUP_GIPA(DestroyInstance, true);
1334 LOOKUP_GIPA(EnumeratePhysicalDevices, true);
1335 LOOKUP_GIPA(GetPhysicalDeviceFeatures, true);
1336 LOOKUP_GIPA(GetPhysicalDeviceFormatProperties, true);
Jon Ashburn754864f2015-07-23 18:49:07 -06001337 LOOKUP_GIPA(GetPhysicalDeviceImageFormatProperties, true);
Jon Ashburnc624c882015-07-16 10:17:29 -06001338 LOOKUP_GIPA(CreateDevice, true);
1339 LOOKUP_GIPA(GetPhysicalDeviceProperties, true);
1340 LOOKUP_GIPA(GetPhysicalDeviceMemoryProperties, true);
Cody Northropd0802882015-08-03 17:04:53 -06001341 LOOKUP_GIPA(GetPhysicalDeviceQueueFamilyProperties, true);
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06001342 LOOKUP_GIPA(EnumerateDeviceExtensionProperties, true);
Jon Ashburnc624c882015-07-16 10:17:29 -06001343 LOOKUP_GIPA(GetPhysicalDeviceSparseImageFormatProperties, true);
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -07001344 LOOKUP_GIPA(CreateDebugReportCallbackLUNARG, false);
1345 LOOKUP_GIPA(DestroyDebugReportCallbackLUNARG, false);
Ian Elliott7e40db92015-08-21 15:09:33 -06001346 LOOKUP_GIPA(GetPhysicalDeviceSurfaceSupportKHR, false);
Ian Elliott486c5502015-11-19 16:05:09 -07001347 LOOKUP_GIPA(GetPhysicalDeviceSurfaceCapabilitiesKHR, false);
1348 LOOKUP_GIPA(GetPhysicalDeviceSurfaceFormatsKHR, false);
1349 LOOKUP_GIPA(GetPhysicalDeviceSurfacePresentModesKHR, false);
Ian Elliott919fa302015-11-24 15:39:10 -07001350#ifdef VK_USE_PLATFORM_WIN32_KHR
1351 LOOKUP_GIPA(GetPhysicalDeviceWin32PresentationSupportKHR, false);
1352#endif
1353#ifdef VK_USE_PLATFORM_XCB_KHR
1354 LOOKUP_GIPA(GetPhysicalDeviceXcbPresentationSupportKHR, false);
1355#endif
Jon Ashburn3da71f22015-05-14 12:43:38 -06001356
Jon Ashburnc624c882015-07-16 10:17:29 -06001357#undef LOOKUP_GIPA
Ian Elliottd3ef02f2015-07-06 14:36:13 -06001358
Jon Ashburnc624c882015-07-16 10:17:29 -06001359 return true;
Jon Ashburn3da71f22015-05-14 12:43:38 -06001360}
1361
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001362static void loader_debug_init(void)
1363{
1364 const char *env;
1365
1366 if (g_loader_debug > 0)
1367 return;
1368
1369 g_loader_debug = 0;
1370
1371 /* parse comma-separated debug options */
Courtney Goeltzenleuchterfce60db2015-07-29 09:08:22 -06001372 env = getenv("VK_LOADER_DEBUG");
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001373 while (env) {
1374 const char *p = strchr(env, ',');
1375 size_t len;
1376
1377 if (p)
1378 len = p - env;
1379 else
1380 len = strlen(env);
1381
1382 if (len > 0) {
Michael Worcester25c73e72015-12-10 18:06:24 +00001383 if (strncmp(env, "all", len) == 0) {
1384 g_loader_debug = ~0u;
1385 g_loader_log_msgs = ~0u;
1386 } else if (strncmp(env, "warn", len) == 0) {
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001387 g_loader_debug |= LOADER_WARN_BIT;
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07001388 g_loader_log_msgs |= VK_DEBUG_REPORT_WARN_BIT;
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001389 } else if (strncmp(env, "info", len) == 0) {
1390 g_loader_debug |= LOADER_INFO_BIT;
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07001391 g_loader_log_msgs |= VK_DEBUG_REPORT_INFO_BIT;
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001392 } else if (strncmp(env, "perf", len) == 0) {
1393 g_loader_debug |= LOADER_PERF_BIT;
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07001394 g_loader_log_msgs |= VK_DEBUG_REPORT_PERF_WARN_BIT;
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001395 } else if (strncmp(env, "error", len) == 0) {
1396 g_loader_debug |= LOADER_ERROR_BIT;
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07001397 g_loader_log_msgs |= VK_DEBUG_REPORT_ERROR_BIT;
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001398 } else if (strncmp(env, "debug", len) == 0) {
1399 g_loader_debug |= LOADER_DEBUG_BIT;
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07001400 g_loader_log_msgs |= VK_DEBUG_REPORT_DEBUG_BIT;
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001401 }
1402 }
1403
1404 if (!p)
1405 break;
1406
1407 env = p + 1;
1408 }
1409}
1410
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001411void loader_initialize(void)
1412{
Jon Ashburn6461ef22015-09-22 13:11:00 -06001413 // initialize mutexs
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001414 loader_platform_thread_create_mutex(&loader_lock);
Jon Ashburn6461ef22015-09-22 13:11:00 -06001415 loader_platform_thread_create_mutex(&loader_json_lock);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001416
1417 // initialize logging
1418 loader_debug_init();
Jon Ashburn87d6aa92015-08-28 15:19:27 -06001419
1420 // initial cJSON to use alloc callbacks
1421 cJSON_Hooks alloc_fns = {
1422 .malloc_fn = loader_tls_heap_alloc,
1423 .free_fn = loader_tls_heap_free,
1424 };
1425 cJSON_InitHooks(&alloc_fns);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001426}
1427
Jon Ashburn2077e382015-06-29 11:25:34 -06001428struct loader_manifest_files {
1429 uint32_t count;
1430 char **filename_list;
1431};
1432
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06001433/**
Jon Ashburn2077e382015-06-29 11:25:34 -06001434 * Get next file or dirname given a string list or registry key path
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06001435 *
1436 * \returns
Jon Ashburn2077e382015-06-29 11:25:34 -06001437 * A pointer to first char in the next path.
1438 * The next path (or NULL) in the list is returned in next_path.
1439 * Note: input string is modified in some cases. PASS IN A COPY!
1440 */
Jon Ashburn2077e382015-06-29 11:25:34 -06001441static char *loader_get_next_path(char *path)
1442{
1443 uint32_t len;
1444 char *next;
1445
1446 if (path == NULL)
1447 return NULL;
1448 next = strchr(path, PATH_SEPERATOR);
1449 if (next == NULL) {
1450 len = (uint32_t) strlen(path);
1451 next = path + len;
1452 }
1453 else {
1454 *next = '\0';
1455 next++;
1456 }
1457
1458 return next;
1459}
1460
1461/**
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001462 * Given a path which is absolute or relative, expand the path if relative or
1463 * leave the path unmodified if absolute. The base path to prepend to relative
1464 * paths is given in rel_base.
Jon Ashburn15315172015-07-07 15:06:25 -06001465 *
1466 * \returns
1467 * A string in out_fullpath of the full absolute path
Jon Ashburn15315172015-07-07 15:06:25 -06001468 */
1469static void loader_expand_path(const char *path,
1470 const char *rel_base,
1471 size_t out_size,
1472 char *out_fullpath)
1473{
1474 if (loader_platform_is_path_absolute(path)) {
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001475 // do not prepend a base to an absolute path
1476 rel_base = "";
Jon Ashburn15315172015-07-07 15:06:25 -06001477 }
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001478
1479 loader_platform_combine_path(out_fullpath, out_size, rel_base, path, NULL);
Jon Ashburn15315172015-07-07 15:06:25 -06001480}
1481
1482/**
Jon Ashburn2077e382015-06-29 11:25:34 -06001483 * Given a filename (file) and a list of paths (dir), try to find an existing
1484 * file in the paths. If filename already is a path then no
1485 * searching in the given paths.
1486 *
1487 * \returns
1488 * A string in out_fullpath of either the full path or file.
Jon Ashburn2077e382015-06-29 11:25:34 -06001489 */
1490static void loader_get_fullpath(const char *file,
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001491 const char *dirs,
Jon Ashburn2077e382015-06-29 11:25:34 -06001492 size_t out_size,
1493 char *out_fullpath)
1494{
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001495 if (!loader_platform_is_path(file) && *dirs) {
1496 char *dirs_copy, *dir, *next_dir;
1497
1498 dirs_copy = loader_stack_alloc(strlen(dirs) + 1);
1499 strcpy(dirs_copy, dirs);
1500
1501 //find if file exists after prepending paths in given list
1502 for (dir = dirs_copy;
1503 *dir && (next_dir = loader_get_next_path(dir));
1504 dir = next_dir) {
1505 loader_platform_combine_path(out_fullpath, out_size, dir, file, NULL);
Jon Ashburn2077e382015-06-29 11:25:34 -06001506 if (loader_platform_file_exists(out_fullpath)) {
1507 return;
1508 }
Jon Ashburn2077e382015-06-29 11:25:34 -06001509 }
1510 }
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001511
Jon Ashburn2077e382015-06-29 11:25:34 -06001512 snprintf(out_fullpath, out_size, "%s", file);
1513}
1514
1515/**
1516 * Read a JSON file into a buffer.
1517 *
1518 * \returns
1519 * A pointer to a cJSON object representing the JSON parse tree.
1520 * This returned buffer should be freed by caller.
1521 */
1522static cJSON *loader_get_json(const char *filename)
1523{
1524 FILE *file;
1525 char *json_buf;
1526 cJSON *json;
1527 uint64_t len;
1528 file = fopen(filename,"rb");
Jon Ashburnaa4ea472015-08-27 08:30:50 -06001529 if (!file) {
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07001530 loader_log(VK_DEBUG_REPORT_ERROR_BIT, 0, "Couldn't open JSON file %s", filename);
Jon Ashburnaa4ea472015-08-27 08:30:50 -06001531 return NULL;
1532 }
Jon Ashburn2077e382015-06-29 11:25:34 -06001533 fseek(file, 0, SEEK_END);
1534 len = ftell(file);
1535 fseek(file, 0, SEEK_SET);
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -06001536 json_buf = (char*) loader_stack_alloc(len+1);
Jon Ashburn2077e382015-06-29 11:25:34 -06001537 if (json_buf == NULL) {
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07001538 loader_log(VK_DEBUG_REPORT_ERROR_BIT, 0, "Out of memory can't get JSON file");
Jon Ashburn2077e382015-06-29 11:25:34 -06001539 fclose(file);
1540 return NULL;
1541 }
1542 if (fread(json_buf, sizeof(char), len, file) != len) {
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07001543 loader_log(VK_DEBUG_REPORT_ERROR_BIT, 0, "fread failed can't get JSON file");
Jon Ashburn2077e382015-06-29 11:25:34 -06001544 fclose(file);
1545 return NULL;
1546 }
1547 fclose(file);
1548 json_buf[len] = '\0';
1549
1550 //parse text from file
1551 json = cJSON_Parse(json_buf);
1552 if (json == NULL)
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07001553 loader_log(VK_DEBUG_REPORT_ERROR_BIT, 0, "Can't parse JSON file %s", filename);
Jon Ashburn2077e382015-06-29 11:25:34 -06001554 return json;
1555}
1556
1557/**
Jon Ashburn3d002332015-08-20 16:35:30 -06001558 * Do a deep copy of the loader_layer_properties structure.
1559 */
1560static void loader_copy_layer_properties(
Jon Ashburne39a4f82015-08-28 13:38:21 -06001561 const struct loader_instance *inst,
Jon Ashburn3d002332015-08-20 16:35:30 -06001562 struct loader_layer_properties *dst,
1563 struct loader_layer_properties *src)
1564{
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001565 uint32_t cnt, i;
Jon Ashburn3d002332015-08-20 16:35:30 -06001566 memcpy(dst, src, sizeof (*src));
Jon Ashburne39a4f82015-08-28 13:38:21 -06001567 dst->instance_extension_list.list = loader_heap_alloc(
1568 inst,
1569 sizeof(VkExtensionProperties) *
1570 src->instance_extension_list.count,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001571 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001572 dst->instance_extension_list.capacity = sizeof(VkExtensionProperties) *
1573 src->instance_extension_list.count;
1574 memcpy(dst->instance_extension_list.list, src->instance_extension_list.list,
1575 dst->instance_extension_list.capacity);
1576 dst->device_extension_list.list = loader_heap_alloc(
1577 inst,
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001578 sizeof(struct loader_dev_ext_props) *
Jon Ashburne39a4f82015-08-28 13:38:21 -06001579 src->device_extension_list.count,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001580 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001581
1582 dst->device_extension_list.capacity = sizeof(struct loader_dev_ext_props) *
Jon Ashburne39a4f82015-08-28 13:38:21 -06001583 src->device_extension_list.count;
1584 memcpy(dst->device_extension_list.list, src->device_extension_list.list,
1585 dst->device_extension_list.capacity);
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001586 if (src->device_extension_list.count > 0 &&
1587 src->device_extension_list.list->entrypoint_count > 0) {
1588 cnt = src->device_extension_list.list->entrypoint_count;
1589 dst->device_extension_list.list->entrypoints = loader_heap_alloc(
1590 inst,
1591 sizeof(char *) * cnt,
1592 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
1593 for (i = 0; i < cnt; i++) {
1594 dst->device_extension_list.list->entrypoints[i] = loader_heap_alloc(
1595 inst,
1596 strlen(src->device_extension_list.list->entrypoints[i]) + 1,
1597 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
1598 strcpy(dst->device_extension_list.list->entrypoints[i],
1599 src->device_extension_list.list->entrypoints[i]);
1600 }
1601 }
Jon Ashburn3d002332015-08-20 16:35:30 -06001602}
1603
1604/**
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001605 * Given a cJSON struct (json) of the top level JSON object from layer manifest
1606 * file, add entry to the layer_list.
Jon Ashburne13ecc92015-08-03 17:19:30 -06001607 * Fill out the layer_properties in this list entry from the input cJSON object.
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001608 *
1609 * \returns
1610 * void
1611 * layer_list has a new entry and initialized accordingly.
1612 * If the json input object does not have all the required fields no entry
1613 * is added to the list.
1614 */
Jon Ashburne39a4f82015-08-28 13:38:21 -06001615static void loader_add_layer_properties(const struct loader_instance *inst,
1616 struct loader_layer_list *layer_instance_list,
Jon Ashburnb2ef1372015-07-16 17:19:31 -06001617 struct loader_layer_list *layer_device_list,
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001618 cJSON *json,
1619 bool is_implicit,
1620 char *filename)
1621{
1622 /* Fields in layer manifest file that are required:
1623 * (required) “file_format_version”
1624 * following are required in the "layer" object:
1625 * (required) "name"
1626 * (required) "type"
1627 * (required) “library_path”
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001628 * (required) “api_version”
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001629 * (required) “implementation_version”
1630 * (required) “description”
1631 * (required for implicit layers) “disable_environment”
1632 *
1633 * First get all required items and if any missing abort
1634 */
1635
1636 cJSON *item, *layer_node, *ext_item;
1637 char *temp;
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001638 char *name, *type, *library_path, *api_version;
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001639 char *implementation_version, *description;
1640 cJSON *disable_environment;
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001641 int i, j;
Jon Ashburn5c042ea2015-08-04 11:14:18 -06001642 VkExtensionProperties ext_prop;
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001643 item = cJSON_GetObjectItem(json, "file_format_version");
1644 if (item == NULL) {
1645 return;
1646 }
1647 char *file_vers = cJSON_PrintUnformatted(item);
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07001648 loader_log(VK_DEBUG_REPORT_INFO_BIT, 0, "Found manifest file %s, version %s",
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001649 filename, file_vers);
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001650 if (strcmp(file_vers, "\"1.0.0\"") != 0)
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07001651 loader_log(VK_DEBUG_REPORT_WARN_BIT, 0, "Unexpected manifest file version (expected 1.0.0), may cause errors");
Jon Ashburn87d6aa92015-08-28 15:19:27 -06001652 loader_tls_heap_free(file_vers);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001653
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001654 layer_node = cJSON_GetObjectItem(json, "layer");
1655 if (layer_node == NULL) {
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07001656 loader_log(VK_DEBUG_REPORT_WARN_BIT, 0, "Can't find \"layer\" object in manifest JSON file, skipping");
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001657 return;
1658 }
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001659
1660 // loop through all "layer" objects in the file
1661 do {
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001662#define GET_JSON_OBJECT(node, var) { \
1663 var = cJSON_GetObjectItem(node, #var); \
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001664 if (var == NULL) { \
1665 layer_node = layer_node->next; \
1666 continue; \
1667 } \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001668 }
1669#define GET_JSON_ITEM(node, var) { \
1670 item = cJSON_GetObjectItem(node, #var); \
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001671 if (item == NULL) { \
1672 layer_node = layer_node->next; \
1673 continue; \
1674 } \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001675 temp = cJSON_Print(item); \
1676 temp[strlen(temp) - 1] = '\0'; \
Jon Ashburnf73e9212015-08-04 10:22:33 -06001677 var = loader_stack_alloc(strlen(temp) + 1); \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001678 strcpy(var, &temp[1]); \
Jon Ashburn87d6aa92015-08-28 15:19:27 -06001679 loader_tls_heap_free(temp); \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001680 }
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001681 GET_JSON_ITEM(layer_node, name)
1682 GET_JSON_ITEM(layer_node, type)
1683 GET_JSON_ITEM(layer_node, library_path)
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001684 GET_JSON_ITEM(layer_node, api_version)
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001685 GET_JSON_ITEM(layer_node, implementation_version)
1686 GET_JSON_ITEM(layer_node, description)
1687 if (is_implicit) {
1688 GET_JSON_OBJECT(layer_node, disable_environment)
1689 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001690#undef GET_JSON_ITEM
1691#undef GET_JSON_OBJECT
1692
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001693 // add list entry
Jon Ashburn432d2762015-09-18 12:53:16 -06001694 struct loader_layer_properties *props=NULL;
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001695 if (!strcmp(type, "DEVICE")) {
1696 if (layer_device_list == NULL) {
1697 layer_node = layer_node->next;
1698 continue;
1699 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06001700 props = loader_get_next_layer_property(inst, layer_device_list);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001701 props->type = (is_implicit) ? VK_LAYER_TYPE_DEVICE_IMPLICIT : VK_LAYER_TYPE_DEVICE_EXPLICIT;
1702 }
1703 if (!strcmp(type, "INSTANCE")) {
1704 if (layer_instance_list == NULL) {
1705 layer_node = layer_node->next;
1706 continue;
1707 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06001708 props = loader_get_next_layer_property(inst, layer_instance_list);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001709 props->type = (is_implicit) ? VK_LAYER_TYPE_INSTANCE_IMPLICIT : VK_LAYER_TYPE_INSTANCE_EXPLICIT;
1710 }
1711 if (!strcmp(type, "GLOBAL")) {
1712 if (layer_instance_list != NULL)
Jon Ashburne39a4f82015-08-28 13:38:21 -06001713 props = loader_get_next_layer_property(inst, layer_instance_list);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001714 else if (layer_device_list != NULL)
Jon Ashburne39a4f82015-08-28 13:38:21 -06001715 props = loader_get_next_layer_property(inst, layer_device_list);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001716 else {
1717 layer_node = layer_node->next;
1718 continue;
1719 }
1720 props->type = (is_implicit) ? VK_LAYER_TYPE_GLOBAL_IMPLICIT : VK_LAYER_TYPE_GLOBAL_EXPLICIT;
1721 }
Jon Ashburnb2ef1372015-07-16 17:19:31 -06001722
Jon Ashburn432d2762015-09-18 12:53:16 -06001723 if (props == NULL) {
1724 layer_node = layer_node->next;
1725 continue;
1726 }
1727
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001728 strncpy(props->info.layerName, name, sizeof (props->info.layerName));
1729 props->info.layerName[sizeof (props->info.layerName) - 1] = '\0';
Jon Ashburn15315172015-07-07 15:06:25 -06001730
Jon Ashburn3d002332015-08-20 16:35:30 -06001731 char *fullpath = props->lib_name;
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001732 char *rel_base;
Jon Ashburn6e08ebd2015-12-01 17:11:02 -07001733 if (loader_platform_is_path(library_path)) {
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001734 // a relative or absolute path
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001735 char *name_copy = loader_stack_alloc(strlen(filename) + 1);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001736 strcpy(name_copy, filename);
1737 rel_base = loader_platform_dirname(name_copy);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001738 loader_expand_path(library_path, rel_base, MAX_STRING_SIZE, fullpath);
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001739 } else {
1740 // a filename which is assumed in a system directory
1741 loader_get_fullpath(library_path, DEFAULT_VK_LAYERS_PATH, MAX_STRING_SIZE, fullpath);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001742 }
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001743 props->info.specVersion = loader_make_version(api_version);
1744 props->info.implementationVersion = atoi(implementation_version);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001745 strncpy((char *) props->info.description, description, sizeof (props->info.description));
1746 props->info.description[sizeof (props->info.description) - 1] = '\0';
1747 if (is_implicit) {
1748 strncpy(props->disable_env_var.name, disable_environment->child->string, sizeof (props->disable_env_var.name));
1749 props->disable_env_var.name[sizeof (props->disable_env_var.name) - 1] = '\0';
1750 strncpy(props->disable_env_var.value, disable_environment->child->valuestring, sizeof (props->disable_env_var.value));
1751 props->disable_env_var.value[sizeof (props->disable_env_var.value) - 1] = '\0';
1752 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001753
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001754 /**
1755 * Now get all optional items and objects and put in list:
1756 * functions
1757 * instance_extensions
1758 * device_extensions
1759 * enable_environment (implicit layers only)
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001760 * disable_environment (implicit_layers_only)
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001761 */
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001762#define GET_JSON_OBJECT(node, var) { \
1763 var = cJSON_GetObjectItem(node, #var); \
1764 }
1765#define GET_JSON_ITEM(node, var) { \
1766 item = cJSON_GetObjectItem(node, #var); \
Jon Ashburn21c21ee2015-09-09 11:29:24 -06001767 if (item != NULL) { \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001768 temp = cJSON_Print(item); \
Jon Ashburn21c21ee2015-09-09 11:29:24 -06001769 temp[strlen(temp) - 1] = '\0'; \
1770 var = loader_stack_alloc(strlen(temp) + 1);\
1771 strcpy(var, &temp[1]); \
1772 loader_tls_heap_free(temp); \
1773 } \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001774 }
1775
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001776 cJSON *instance_extensions, *device_extensions, *functions, *enable_environment;
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001777 cJSON *entrypoints;
1778 char *vkGetInstanceProcAddr, *vkGetDeviceProcAddr, *spec_version;
1779 char **entry_array;
1780 vkGetInstanceProcAddr = NULL;
1781 vkGetDeviceProcAddr = NULL;
1782 spec_version = NULL;
1783 entrypoints = NULL;
1784 entry_array = NULL;
1785 /**
1786 * functions
1787 * vkGetInstanceProcAddr
1788 * vkGetDeviceProcAddr
1789 */
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001790 GET_JSON_OBJECT(layer_node, functions)
1791 if (functions != NULL) {
1792 GET_JSON_ITEM(functions, vkGetInstanceProcAddr)
1793 GET_JSON_ITEM(functions, vkGetDeviceProcAddr)
Jon Ashburn21c21ee2015-09-09 11:29:24 -06001794 if (vkGetInstanceProcAddr != NULL)
1795 strncpy(props->functions.str_gipa, vkGetInstanceProcAddr, sizeof (props->functions.str_gipa));
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001796 props->functions.str_gipa[sizeof (props->functions.str_gipa) - 1] = '\0';
Jon Ashburn21c21ee2015-09-09 11:29:24 -06001797 if (vkGetDeviceProcAddr != NULL)
1798 strncpy(props->functions.str_gdpa, vkGetDeviceProcAddr, sizeof (props->functions.str_gdpa));
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001799 props->functions.str_gdpa[sizeof (props->functions.str_gdpa) - 1] = '\0';
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001800 }
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001801 /**
1802 * instance_extensions
1803 * array of
1804 * name
1805 * spec_version
1806 */
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001807 GET_JSON_OBJECT(layer_node, instance_extensions)
1808 if (instance_extensions != NULL) {
1809 int count = cJSON_GetArraySize(instance_extensions);
1810 for (i = 0; i < count; i++) {
1811 ext_item = cJSON_GetArrayItem(instance_extensions, i);
1812 GET_JSON_ITEM(ext_item, name)
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001813 GET_JSON_ITEM(ext_item, spec_version)
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001814 if (name != NULL) {
Jon Ashburn6e6a2162015-12-10 08:51:10 -07001815 strncpy(ext_prop.extensionName, name, sizeof (ext_prop.extensionName));
1816 ext_prop.extensionName[sizeof (ext_prop.extensionName) - 1] = '\0';
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001817 }
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001818 ext_prop.specVersion = atoi(spec_version);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001819 loader_add_to_ext_list(inst, &props->instance_extension_list, 1, &ext_prop);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001820 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001821 }
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001822 /**
1823 * device_extensions
1824 * array of
1825 * name
1826 * spec_version
1827 * entrypoints
1828 */
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001829 GET_JSON_OBJECT(layer_node, device_extensions)
1830 if (device_extensions != NULL) {
1831 int count = cJSON_GetArraySize(device_extensions);
1832 for (i = 0; i < count; i++) {
1833 ext_item = cJSON_GetArrayItem(device_extensions, i);
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001834 GET_JSON_ITEM(ext_item, name)
1835 GET_JSON_ITEM(ext_item, spec_version)
1836 if (name != NULL) {
Jon Ashburn6e6a2162015-12-10 08:51:10 -07001837 strncpy(ext_prop.extensionName, name, sizeof (ext_prop.extensionName));
1838 ext_prop.extensionName[sizeof (ext_prop.extensionName) - 1] = '\0';
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001839 }
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001840 ext_prop.specVersion = atoi(spec_version);
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001841 //entrypoints = cJSON_GetObjectItem(ext_item, "entrypoints");
1842 GET_JSON_OBJECT(ext_item, entrypoints)
1843 int entry_count;
1844 if (entrypoints == NULL)
1845 continue;
1846 entry_count = cJSON_GetArraySize(entrypoints);
1847 if (entry_count)
1848 entry_array = (char **) loader_stack_alloc(sizeof(char *) * entry_count);
1849 for (j = 0; j < entry_count; j++) {
1850 ext_item = cJSON_GetArrayItem(entrypoints, j);
1851 if (ext_item != NULL) {
1852 temp = cJSON_Print(ext_item);
1853 temp[strlen(temp) - 1] = '\0';
1854 entry_array[j] = loader_stack_alloc(strlen(temp) + 1);
1855 strcpy(entry_array[j], &temp[1]);
1856 loader_tls_heap_free(temp);
Jon Ashburn6e6a2162015-12-10 08:51:10 -07001857 }
1858 }
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001859 loader_add_to_dev_ext_list(inst, &props->device_extension_list,
1860 &ext_prop, entry_count, entry_array);
1861 }
1862 }
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001863 if (is_implicit) {
1864 GET_JSON_OBJECT(layer_node, enable_environment)
1865 strncpy(props->enable_env_var.name, enable_environment->child->string, sizeof (props->enable_env_var.name));
1866 props->enable_env_var.name[sizeof (props->enable_env_var.name) - 1] = '\0';
1867 strncpy(props->enable_env_var.value, enable_environment->child->valuestring, sizeof (props->enable_env_var.value));
1868 props->enable_env_var.value[sizeof (props->enable_env_var.value) - 1] = '\0';
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001869 //TODO add disable_environment for implicit layers
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001870 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001871#undef GET_JSON_ITEM
1872#undef GET_JSON_OBJECT
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001873 // for global layers need to add them to both device and instance list
1874 if (!strcmp(type, "GLOBAL")) {
1875 struct loader_layer_properties *dev_props;
1876 if (layer_instance_list == NULL || layer_device_list == NULL) {
1877 layer_node = layer_node->next;
1878 continue;
1879 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06001880 dev_props = loader_get_next_layer_property(inst, layer_device_list);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001881 //copy into device layer list
Jon Ashburne39a4f82015-08-28 13:38:21 -06001882 loader_copy_layer_properties(inst, dev_props, props);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001883 }
1884 layer_node = layer_node->next;
1885 } while (layer_node != NULL);
1886 return;
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001887}
1888
1889/**
Jon Ashburn2077e382015-06-29 11:25:34 -06001890 * Find the Vulkan library manifest files.
1891 *
1892 * This function scans the location or env_override directories/files
1893 * for a list of JSON manifest files. If env_override is non-NULL
1894 * and has a valid value. Then the location is ignored. Otherwise
1895 * location is used to look for manifest files. The location
1896 * is interpreted as Registry path on Windows and a directory path(s)
1897 * on Linux.
1898 *
1899 * \returns
1900 * A string list of manifest files to be opened in out_files param.
1901 * List has a pointer to string for each manifest filename.
1902 * When done using the list in out_files, pointers should be freed.
Jon Ashburnffad94d2015-06-30 14:46:22 -07001903 * Location or override string lists can be either files or directories as follows:
1904 * | location | override
1905 * --------------------------------
1906 * Win ICD | files | files
1907 * Win Layer | files | dirs
1908 * Linux ICD | dirs | files
1909 * Linux Layer| dirs | dirs
Jon Ashburn2077e382015-06-29 11:25:34 -06001910 */
Jon Ashburne39a4f82015-08-28 13:38:21 -06001911static void loader_get_manifest_files(const struct loader_instance *inst,
1912 const char *env_override,
Jon Ashburnffad94d2015-06-30 14:46:22 -07001913 bool is_layer,
1914 const char *location,
1915 struct loader_manifest_files *out_files)
Jon Ashburn2077e382015-06-29 11:25:34 -06001916{
1917 char *override = NULL;
1918 char *loc;
1919 char *file, *next_file, *name;
1920 size_t alloced_count = 64;
1921 char full_path[2048];
1922 DIR *sysdir = NULL;
Jon Ashburnffad94d2015-06-30 14:46:22 -07001923 bool list_is_dirs = false;
Jon Ashburn2077e382015-06-29 11:25:34 -06001924 struct dirent *dent;
1925
1926 out_files->count = 0;
1927 out_files->filename_list = NULL;
1928
Jon Ashburn2077e382015-06-29 11:25:34 -06001929 if (env_override != NULL && (override = getenv(env_override))) {
Johannes van Waveren9bd805012015-10-28 11:45:00 -05001930#if !defined(_WIN32)
Jon Ashburn2077e382015-06-29 11:25:34 -06001931 if (geteuid() != getuid()) {
Jon Ashburnffad94d2015-06-30 14:46:22 -07001932 /* Don't allow setuid apps to use the env var: */
Jon Ashburn2077e382015-06-29 11:25:34 -06001933 override = NULL;
1934 }
1935#endif
1936 }
1937
1938 if (location == NULL) {
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07001939 loader_log(VK_DEBUG_REPORT_ERROR_BIT, 0,
Jon Ashburnffad94d2015-06-30 14:46:22 -07001940 "Can't get manifest files with NULL location, env_override=%s",
1941 env_override);
Jon Ashburn2077e382015-06-29 11:25:34 -06001942 return;
1943 }
1944
Johannes van Waveren9bd805012015-10-28 11:45:00 -05001945#if defined(_WIN32)
Jon Ashburnffad94d2015-06-30 14:46:22 -07001946 list_is_dirs = (is_layer && override != NULL) ? true : false;
Johannes van Waveren9bd805012015-10-28 11:45:00 -05001947#else
1948 list_is_dirs = (override == NULL || is_layer) ? true : false;
Jon Ashburnffad94d2015-06-30 14:46:22 -07001949#endif
Jon Ashburn2077e382015-06-29 11:25:34 -06001950 // Make a copy of the input we are using so it is not modified
Jon Ashburnffad94d2015-06-30 14:46:22 -07001951 // Also handle getting the location(s) from registry on Windows
1952 if (override == NULL) {
Jon Ashburn3b78e462015-07-31 10:11:24 -06001953 loc = loader_stack_alloc(strlen(location) + 1);
Jon Ashburnffad94d2015-06-30 14:46:22 -07001954 if (loc == NULL) {
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07001955 loader_log(VK_DEBUG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files");
Jon Ashburnffad94d2015-06-30 14:46:22 -07001956 return;
1957 }
1958 strcpy(loc, location);
Johannes van Waveren9bd805012015-10-28 11:45:00 -05001959#if defined(_WIN32)
Jon Ashburn480a50a2015-08-28 14:58:46 -07001960 loc = loader_get_registry_files(inst, loc);
Jon Ashburn24265ac2015-07-31 09:33:21 -06001961 if (loc == NULL) {
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07001962 loader_log(VK_DEBUG_REPORT_ERROR_BIT, 0, "Registry lookup failed can't get manifest files");
Jon Ashburn24265ac2015-07-31 09:33:21 -06001963 return;
1964 }
Jon Ashburnffad94d2015-06-30 14:46:22 -07001965#endif
Jon Ashburn2077e382015-06-29 11:25:34 -06001966 }
Jon Ashburnffad94d2015-06-30 14:46:22 -07001967 else {
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -06001968 loc = loader_stack_alloc(strlen(override) + 1);
Jon Ashburnffad94d2015-06-30 14:46:22 -07001969 if (loc == NULL) {
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07001970 loader_log(VK_DEBUG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files");
Jon Ashburnffad94d2015-06-30 14:46:22 -07001971 return;
1972 }
1973 strcpy(loc, override);
1974 }
Jon Ashburn2077e382015-06-29 11:25:34 -06001975
Liam Middlebrook9b14e892015-07-23 18:32:20 -07001976 // Print out the paths being searched if debugging is enabled
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07001977 loader_log(VK_DEBUG_REPORT_DEBUG_BIT, 0, "Searching the following paths for manifest files: %s\n", loc);
Liam Middlebrook9b14e892015-07-23 18:32:20 -07001978
Jon Ashburn2077e382015-06-29 11:25:34 -06001979 file = loc;
1980 while (*file) {
1981 next_file = loader_get_next_path(file);
Jon Ashburnffad94d2015-06-30 14:46:22 -07001982 if (list_is_dirs) {
Jon Ashburn2077e382015-06-29 11:25:34 -06001983 sysdir = opendir(file);
1984 name = NULL;
1985 if (sysdir) {
1986 dent = readdir(sysdir);
1987 if (dent == NULL)
1988 break;
1989 name = &(dent->d_name[0]);
1990 loader_get_fullpath(name, file, sizeof(full_path), full_path);
1991 name = full_path;
1992 }
1993 }
1994 else {
Johannes van Waveren9bd805012015-10-28 11:45:00 -05001995#if defined(_WIN32)
1996 name = file;
1997#else
Jon Ashburnffad94d2015-06-30 14:46:22 -07001998 // only Linux has relative paths
Jon Ashburn2077e382015-06-29 11:25:34 -06001999 char *dir;
2000 // make a copy of location so it isn't modified
Jason Ekstrandcc7550e2015-10-10 08:33:37 -07002001 dir = loader_stack_alloc(strlen(loc) + 1);
Jon Ashburn2077e382015-06-29 11:25:34 -06002002 if (dir == NULL) {
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07002003 loader_log(VK_DEBUG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files");
Jon Ashburn2077e382015-06-29 11:25:34 -06002004 return;
2005 }
Jason Ekstrandcc7550e2015-10-10 08:33:37 -07002006 strcpy(dir, loc);
Jon Ashburn2077e382015-06-29 11:25:34 -06002007
2008 loader_get_fullpath(file, dir, sizeof(full_path), full_path);
2009
2010 name = full_path;
Jon Ashburnffad94d2015-06-30 14:46:22 -07002011#endif
Jon Ashburn2077e382015-06-29 11:25:34 -06002012 }
2013 while (name) {
2014 /* Look for files ending with ".json" suffix */
2015 uint32_t nlen = (uint32_t) strlen(name);
2016 const char *suf = name + nlen - 5;
2017 if ((nlen > 5) && !strncmp(suf, ".json", 5)) {
2018 if (out_files->count == 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06002019 out_files->filename_list = loader_heap_alloc(inst,
2020 alloced_count * sizeof(char *),
Chia-I Wucf804e82015-10-31 00:31:16 +08002021 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
Jon Ashburn2077e382015-06-29 11:25:34 -06002022 }
2023 else if (out_files->count == alloced_count) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06002024 out_files->filename_list = loader_heap_realloc(inst,
2025 out_files->filename_list,
2026 alloced_count * sizeof(char *),
2027 alloced_count * sizeof(char *) * 2,
Chia-I Wucf804e82015-10-31 00:31:16 +08002028 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
Jon Ashburn2077e382015-06-29 11:25:34 -06002029 alloced_count *= 2;
2030 }
2031 if (out_files->filename_list == NULL) {
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07002032 loader_log(VK_DEBUG_REPORT_ERROR_BIT, 0, "Out of memory can't alloc manifest file list");
Jon Ashburn2077e382015-06-29 11:25:34 -06002033 return;
2034 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06002035 out_files->filename_list[out_files->count] = loader_heap_alloc(
2036 inst,
2037 strlen(name) + 1,
Chia-I Wucf804e82015-10-31 00:31:16 +08002038 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
Jon Ashburn2077e382015-06-29 11:25:34 -06002039 if (out_files->filename_list[out_files->count] == NULL) {
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07002040 loader_log(VK_DEBUG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files");
Jon Ashburn2077e382015-06-29 11:25:34 -06002041 return;
2042 }
2043 strcpy(out_files->filename_list[out_files->count], name);
2044 out_files->count++;
Jon Ashburnf70f3612015-07-02 10:08:47 -06002045 } else if (!list_is_dirs) {
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07002046 loader_log(VK_DEBUG_REPORT_WARN_BIT, 0, "Skipping manifest file %s, file name must end in .json", name);
Jon Ashburn2077e382015-06-29 11:25:34 -06002047 }
Jon Ashburnffad94d2015-06-30 14:46:22 -07002048 if (list_is_dirs) {
Jon Ashburn2077e382015-06-29 11:25:34 -06002049 dent = readdir(sysdir);
2050 if (dent == NULL)
2051 break;
2052 name = &(dent->d_name[0]);
2053 loader_get_fullpath(name, file, sizeof(full_path), full_path);
2054 name = full_path;
2055 }
2056 else {
2057 break;
2058 }
2059 }
2060 if (sysdir)
2061 closedir(sysdir);
2062 file = next_file;
2063 }
2064 return;
2065}
2066
Jon Ashburn8810c5f2015-08-18 18:04:47 -06002067void loader_init_icd_lib_list()
2068{
2069
2070}
2071
2072void loader_destroy_icd_lib_list()
2073{
2074
2075}
Jon Ashburn2077e382015-06-29 11:25:34 -06002076/**
2077 * Try to find the Vulkan ICD driver(s).
2078 *
2079 * This function scans the default system loader path(s) or path
2080 * specified by the \c VK_ICD_FILENAMES environment variable in
2081 * order to find loadable VK ICDs manifest files. From these
2082 * manifest files it finds the ICD libraries.
2083 *
2084 * \returns
Jon Ashburn8810c5f2015-08-18 18:04:47 -06002085 * a list of icds that were discovered
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06002086 */
Jon Ashburne39a4f82015-08-28 13:38:21 -06002087void loader_icd_scan(
2088 const struct loader_instance *inst,
2089 struct loader_icd_libs *icds)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08002090{
Jon Ashburn2077e382015-06-29 11:25:34 -06002091 char *file_str;
2092 struct loader_manifest_files manifest_files;
2093
Jon Ashburne39a4f82015-08-28 13:38:21 -06002094 loader_scanned_icd_init(inst, icds);
Jon Ashburn2077e382015-06-29 11:25:34 -06002095 // Get a list of manifest files for ICDs
Jon Ashburne39a4f82015-08-28 13:38:21 -06002096 loader_get_manifest_files(inst, "VK_ICD_FILENAMES", false,
2097 DEFAULT_VK_DRIVERS_INFO, &manifest_files);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002098 if (manifest_files.count == 0)
2099 return;
Jon Ashburn6461ef22015-09-22 13:11:00 -06002100 loader_platform_thread_lock_mutex(&loader_json_lock);
Jon Ashburn2077e382015-06-29 11:25:34 -06002101 for (uint32_t i = 0; i < manifest_files.count; i++) {
2102 file_str = manifest_files.filename_list[i];
2103 if (file_str == NULL)
2104 continue;
2105
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002106 cJSON *json;
Jon Ashburn2077e382015-06-29 11:25:34 -06002107 json = loader_get_json(file_str);
Jon Ashburnaa4ea472015-08-27 08:30:50 -06002108 if (!json)
2109 continue;
Jon Ashburn005617f2015-11-17 17:35:40 -07002110 cJSON *item, *itemICD;
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002111 item = cJSON_GetObjectItem(json, "file_format_version");
Jon Ashburn6461ef22015-09-22 13:11:00 -06002112 if (item == NULL) {
2113 loader_platform_thread_unlock_mutex(&loader_json_lock);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002114 return;
Jon Ashburn6461ef22015-09-22 13:11:00 -06002115 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002116 char *file_vers = cJSON_Print(item);
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07002117 loader_log(VK_DEBUG_REPORT_INFO_BIT, 0, "Found manifest file %s, version %s",
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002118 file_str, file_vers);
2119 if (strcmp(file_vers, "\"1.0.0\"") != 0)
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07002120 loader_log(VK_DEBUG_REPORT_WARN_BIT, 0, "Unexpected manifest file version (expected 1.0.0), may cause errors");
Jon Ashburn87d6aa92015-08-28 15:19:27 -06002121 loader_tls_heap_free(file_vers);
Jon Ashburn005617f2015-11-17 17:35:40 -07002122 itemICD = cJSON_GetObjectItem(json, "ICD");
2123 if (itemICD != NULL) {
2124 item = cJSON_GetObjectItem(itemICD, "library_path");
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002125 if (item != NULL) {
Jon Ashburn86251302015-08-25 16:48:24 -06002126 char *temp= cJSON_Print(item);
2127 if (!temp || strlen(temp) == 0) {
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07002128 loader_log(VK_DEBUG_REPORT_WARN_BIT, 0, "Can't find \"library_path\" in ICD JSON file %s, skipping", file_str);
Jon Ashburn87d6aa92015-08-28 15:19:27 -06002129 loader_tls_heap_free(temp);
Jon Ashburne39a4f82015-08-28 13:38:21 -06002130 loader_heap_free(inst, file_str);
Jon Ashburn86251302015-08-25 16:48:24 -06002131 cJSON_Delete(json);
2132 continue;
Jon Ashburn2077e382015-06-29 11:25:34 -06002133 }
Jon Ashburn86251302015-08-25 16:48:24 -06002134 //strip out extra quotes
2135 temp[strlen(temp) - 1] = '\0';
2136 char *library_path = loader_stack_alloc(strlen(temp) + 1);
2137 strcpy(library_path, &temp[1]);
Jon Ashburn87d6aa92015-08-28 15:19:27 -06002138 loader_tls_heap_free(temp);
Jon Ashburn86251302015-08-25 16:48:24 -06002139 if (!library_path || strlen(library_path) == 0) {
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07002140 loader_log(VK_DEBUG_REPORT_WARN_BIT, 0, "Can't find \"library_path\" in ICD JSON file %s, skipping", file_str);
Jon Ashburne39a4f82015-08-28 13:38:21 -06002141 loader_heap_free(inst, file_str);
Jon Ashburn86251302015-08-25 16:48:24 -06002142 cJSON_Delete(json);
2143 continue;
2144 }
Daniel Dadap00b4aba2015-09-30 11:50:51 -05002145 char fullpath[MAX_STRING_SIZE];
Jon Ashburn86251302015-08-25 16:48:24 -06002146 // Print out the paths being searched if debugging is enabled
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07002147 loader_log(VK_DEBUG_REPORT_DEBUG_BIT, 0, "Searching for ICD drivers named %s default dir %s\n", library_path, DEFAULT_VK_DRIVERS_PATH);
Daniel Dadap00b4aba2015-09-30 11:50:51 -05002148 if (loader_platform_is_path(library_path)) {
Jon Ashburn86251302015-08-25 16:48:24 -06002149 // a relative or absolute path
Daniel Dadap00b4aba2015-09-30 11:50:51 -05002150 char *name_copy = loader_stack_alloc(strlen(file_str) + 1);
2151 char *rel_base;
Jon Ashburn86251302015-08-25 16:48:24 -06002152 strcpy(name_copy, file_str);
2153 rel_base = loader_platform_dirname(name_copy);
Daniel Dadap00b4aba2015-09-30 11:50:51 -05002154 loader_expand_path(library_path, rel_base, sizeof(fullpath), fullpath);
2155 } else {
2156 // a filename which is assumed in a system directory
2157 loader_get_fullpath(library_path, DEFAULT_VK_DRIVERS_PATH, sizeof(fullpath), fullpath);
Jon Ashburn86251302015-08-25 16:48:24 -06002158 }
Jon Ashburn005617f2015-11-17 17:35:40 -07002159
2160 uint32_t vers = 0;
2161 item = cJSON_GetObjectItem(itemICD, "api_version");
2162 if (item != NULL) {
2163 temp= cJSON_Print(item);
2164 vers = loader_make_version(temp);
2165 loader_tls_heap_free(temp);
2166 }
2167 loader_scanned_icd_add(inst, icds, fullpath, vers);
Jon Ashburn2077e382015-06-29 11:25:34 -06002168 }
Jon Ashburn005617f2015-11-17 17:35:40 -07002169 else
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07002170 loader_log(VK_DEBUG_REPORT_WARN_BIT, 0, "Can't find \"library_path\" object in ICD JSON file %s, skipping", file_str);
Jon Ashburn2077e382015-06-29 11:25:34 -06002171 }
2172 else
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07002173 loader_log(VK_DEBUG_REPORT_WARN_BIT, 0, "Can't find \"ICD\" object in ICD JSON file %s, skipping", file_str);
Jon Ashburn2077e382015-06-29 11:25:34 -06002174
Jon Ashburne39a4f82015-08-28 13:38:21 -06002175 loader_heap_free(inst, file_str);
Jon Ashburn2077e382015-06-29 11:25:34 -06002176 cJSON_Delete(json);
2177 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06002178 loader_heap_free(inst, manifest_files.filename_list);
Jon Ashburn6461ef22015-09-22 13:11:00 -06002179 loader_platform_thread_unlock_mutex(&loader_json_lock);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08002180}
2181
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002182
Jon Ashburne39a4f82015-08-28 13:38:21 -06002183void loader_layer_scan(
2184 const struct loader_instance *inst,
2185 struct loader_layer_list *instance_layers,
2186 struct loader_layer_list *device_layers)
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002187{
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002188 char *file_str;
2189 struct loader_manifest_files manifest_files;
2190 cJSON *json;
2191 uint32_t i;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002192
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002193 // Get a list of manifest files for layers
Jon Ashburne39a4f82015-08-28 13:38:21 -06002194 loader_get_manifest_files(inst, LAYERS_PATH_ENV, true, DEFAULT_VK_LAYERS_INFO,
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002195 &manifest_files);
2196 if (manifest_files.count == 0)
Courtney Goeltzenleuchter57985ce2014-12-01 09:29:42 -07002197 return;
Jon Ashburn90c6a0e2015-06-04 15:30:58 -06002198
Jon Ashburne13ecc92015-08-03 17:19:30 -06002199#if 0 //TODO
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002200 /**
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -06002201 * We need a list of the layer libraries, not just a list of
2202 * the layer properties (a layer library could expose more than
2203 * one layer property). This list of scanned layers would be
2204 * used to check for global and physicaldevice layer properties.
2205 */
2206 if (!loader_init_layer_library_list(&loader.scanned_layer_libraries)) {
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07002207 loader_log(VK_DEBUG_REPORT_ERROR_BIT, 0,
Jon Ashburne39a4f82015-08-28 13:38:21 -06002208 "Alloc for layer list failed: %s line: %d", __FILE__, __LINE__);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -06002209 return;
Jon Ashburn5ef20602015-07-02 09:40:15 -06002210 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002211#endif
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002212
Jon Ashburne13ecc92015-08-03 17:19:30 -06002213 /* cleanup any previously scanned libraries */
Jon Ashburne39a4f82015-08-28 13:38:21 -06002214 loader_delete_layer_properties(inst, instance_layers);
2215 loader_delete_layer_properties(inst, device_layers);
Jon Ashburnb2ef1372015-07-16 17:19:31 -06002216
Jon Ashburn6461ef22015-09-22 13:11:00 -06002217 loader_platform_thread_lock_mutex(&loader_json_lock);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002218 for (i = 0; i < manifest_files.count; i++) {
2219 file_str = manifest_files.filename_list[i];
2220 if (file_str == NULL)
2221 continue;
Courtney Goeltzenleuchtera9e4af42015-06-01 14:49:17 -06002222
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002223 // parse file into JSON struct
2224 json = loader_get_json(file_str);
2225 if (!json) {
2226 continue;
2227 }
Jon Ashburne13ecc92015-08-03 17:19:30 -06002228
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002229 //TODO pass in implicit versus explicit bool
Jon Ashburnb2ef1372015-07-16 17:19:31 -06002230 //TODO error if device layers expose instance_extensions
2231 //TODO error if instance layers expose device extensions
Jon Ashburne39a4f82015-08-28 13:38:21 -06002232 loader_add_layer_properties(inst,
2233 instance_layers,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002234 device_layers,
Jon Ashburnb2ef1372015-07-16 17:19:31 -06002235 json,
2236 false,
2237 file_str);
2238
Jon Ashburne39a4f82015-08-28 13:38:21 -06002239 loader_heap_free(inst, file_str);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002240 cJSON_Delete(json);
2241 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06002242 loader_heap_free(inst, manifest_files.filename_list);
Jon Ashburn6461ef22015-09-22 13:11:00 -06002243 loader_platform_thread_unlock_mutex(&loader_json_lock);
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002244}
2245
Chia-I Wu9ab61502015-11-06 06:42:02 +08002246static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL loader_gpa_instance_internal(VkInstance inst, const char * pName)
Jon Ashburn27cd5842015-05-12 17:26:48 -06002247{
2248 // inst is not wrapped
2249 if (inst == VK_NULL_HANDLE) {
2250 return NULL;
2251 }
2252 VkLayerInstanceDispatchTable* disp_table = * (VkLayerInstanceDispatchTable **) inst;
2253 void *addr;
2254
Jon Ashburn8fd08252015-05-28 16:25:02 -06002255 if (!strcmp(pName, "vkGetInstanceProcAddr"))
2256 return (void *) loader_gpa_instance_internal;
2257
Jon Ashburn27cd5842015-05-12 17:26:48 -06002258 if (disp_table == NULL)
2259 return NULL;
2260
2261 addr = loader_lookup_instance_dispatch_table(disp_table, pName);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002262 if (addr) {
Jon Ashburn27cd5842015-05-12 17:26:48 -06002263 return addr;
Jon Ashburn3d526cb2015-04-13 18:10:06 -06002264 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002265
2266 if (disp_table->GetInstanceProcAddr == NULL) {
2267 return NULL;
2268 }
2269 return disp_table->GetInstanceProcAddr(inst, pName);
Jon Ashburn3d526cb2015-04-13 18:10:06 -06002270}
2271
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002272/**
2273 * Initialize device_ext dispatch table entry as follows:
2274 * If dev == NULL find all logical devices created within this instance and
2275 * init the entry (given by idx) in the ext dispatch table.
2276 * If dev != NULL only initialize the entry in the given dev's dispatch table.
2277 * The initialization value is gotten by calling down the device chain with GDPA.
2278 * If GDPA returns NULL then don't initialize the dispatch table entry.
2279 */
2280static void loader_init_dispatch_dev_ext_entry(struct loader_instance *inst,
2281 struct loader_device *dev,
2282 uint32_t idx,
2283 const char *funcName)
2284
2285 {
2286 void *gdpa_value;
2287 if (dev != NULL) {
2288 gdpa_value = dev->loader_dispatch.core_dispatch.GetDeviceProcAddr(
2289 dev->device, funcName);
2290 if (gdpa_value != NULL)
2291 dev->loader_dispatch.ext_dispatch.DevExt[idx] = (PFN_vkDevExt) gdpa_value;
2292 } else {
2293 for (uint32_t i = 0; i < inst->total_icd_count; i++) {
2294 struct loader_icd *icd = &inst->icds[i];
2295 struct loader_device *dev = icd->logical_device_list;
2296 while (dev) {
2297 gdpa_value = dev->loader_dispatch.core_dispatch.GetDeviceProcAddr(
2298 dev->device, funcName);
2299 if (gdpa_value != NULL)
2300 dev->loader_dispatch.ext_dispatch.DevExt[idx] =
2301 (PFN_vkDevExt) gdpa_value;
2302 dev = dev->next;
2303 }
2304 }
2305 }
2306
2307}
2308
2309/**
2310 * Find all dev extension in the hash table and initialize the dispatch table
2311 * for dev for each of those extension entrypoints found in hash table.
2312
2313 */
2314static void loader_init_dispatch_dev_ext(struct loader_instance *inst,
2315 struct loader_device *dev)
2316{
2317 for (uint32_t i = 0; i < MAX_NUM_DEV_EXTS; i++) {
2318 if (inst->disp_hash[i].func_name != NULL)
2319 loader_init_dispatch_dev_ext_entry(inst, dev, i,
2320 inst->disp_hash[i].func_name);
2321 }
2322}
2323
2324static bool loader_check_icds_for_address(struct loader_instance *inst,
2325 const char *funcName)
2326{
2327 struct loader_icd *icd;
2328 icd = inst->icds;
2329 while (icd) {
2330 if (icd->this_icd_lib->GetInstanceProcAddr(icd->instance, funcName))
2331 // this icd supports funcName
2332 return true;
2333 icd = icd->next;
2334 }
2335
2336 return false;
2337}
2338
2339static void loader_free_dev_ext_table(struct loader_instance *inst)
2340{
2341 for (uint32_t i = 0; i < MAX_NUM_DEV_EXTS; i++) {
2342 loader_heap_free(inst, inst->disp_hash[i].func_name);
2343 loader_heap_free(inst, inst->disp_hash[i].list.index);
2344
2345 }
2346 memset(inst->disp_hash, 0, sizeof(inst->disp_hash));
2347}
2348
2349static bool loader_add_dev_ext_table(struct loader_instance *inst,
2350 uint32_t *ptr_idx,
2351 const char *funcName)
2352{
2353 uint32_t i;
2354 uint32_t idx = *ptr_idx;
2355 struct loader_dispatch_hash_list *list = &inst->disp_hash[idx].list;
2356
2357 if (!inst->disp_hash[idx].func_name) {
2358 // no entry here at this idx, so use it
2359 assert(list->capacity == 0);
2360 inst->disp_hash[idx].func_name = (char *) loader_heap_alloc(inst,
2361 strlen(funcName) + 1,
2362 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
2363 if (inst->disp_hash[idx].func_name == NULL) {
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07002364 loader_log(VK_DEBUG_REPORT_ERROR_BIT, 0,
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002365 "loader_add_dev_ext_table() can't allocate memory for func_name");
2366 return false;
2367 }
2368 strncpy(inst->disp_hash[idx].func_name, funcName, strlen(funcName) + 1);
2369 return true;
2370 }
2371
2372 // check for enough capacity
2373 if (list->capacity == 0) {
2374 list->index = loader_heap_alloc(inst, 8 * sizeof(*(list->index)),
2375 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
2376 if (list->index == NULL) {
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07002377 loader_log(VK_DEBUG_REPORT_ERROR_BIT, 0,
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002378 "loader_add_dev_ext_table() can't allocate list memory");
2379 return false;
2380 }
2381 list->capacity = 8 * sizeof(*(list->index));
2382 } else if (list->capacity < (list->count + 1) * sizeof(*(list->index))) {
2383 list->index = loader_heap_realloc(inst, list->index, list->capacity,
2384 list->capacity * 2,
2385 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
2386 if (list->index == NULL) {
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07002387 loader_log(VK_DEBUG_REPORT_ERROR_BIT, 0,
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002388 "loader_add_dev_ext_table() can't reallocate list memory");
2389 return false;
2390 }
2391 list->capacity *= 2;
2392 }
2393
2394 //find an unused index in the hash table and use it
2395 i = (idx + 1) % MAX_NUM_DEV_EXTS;
2396 do {
2397 if (!inst->disp_hash[i].func_name) {
2398 assert(inst->disp_hash[i].list.capacity == 0);
2399 inst->disp_hash[i].func_name = (char *) loader_heap_alloc(inst,
2400 strlen(funcName) + 1,
2401 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
2402 if (inst->disp_hash[i].func_name == NULL) {
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07002403 loader_log(VK_DEBUG_REPORT_ERROR_BIT, 0,
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002404 "loader_add_dev_ext_table() can't rallocate func_name memory");
2405 return false;
2406 }
2407 strncpy(inst->disp_hash[i].func_name, funcName, strlen(funcName) + 1);
2408 list->index[list->count] = i;
2409 list->count++;
2410 *ptr_idx = i;
2411 return true;
2412 }
2413 i = (i + 1) % MAX_NUM_DEV_EXTS;
2414 } while (i != idx);
2415
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07002416 loader_log(VK_DEBUG_REPORT_ERROR_BIT, 0,
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002417 "loader_add_dev_ext_table() couldn't insert into hash table; is it full?");
2418 return false;
2419}
2420
2421static bool loader_name_in_dev_ext_table(struct loader_instance *inst,
2422 uint32_t *idx,
2423 const char *funcName)
2424{
2425 uint32_t alt_idx;
2426 if (inst->disp_hash[*idx].func_name && !strcmp(
2427 inst->disp_hash[*idx].func_name,
2428 funcName))
2429 return true;
2430
2431 // funcName wasn't at the primary spot in the hash table
2432 // search the list of secondary locations (shallow search, not deep search)
2433 for (uint32_t i = 0; i < inst->disp_hash[*idx].list.count; i++) {
2434 alt_idx = inst->disp_hash[*idx].list.index[i];
2435 if (!strcmp(inst->disp_hash[*idx].func_name, funcName)) {
2436 *idx = alt_idx;
2437 return true;
2438 }
2439 }
2440
2441 return false;
2442}
2443
2444/**
2445 * This function returns generic trampoline code address for unknown entry points.
2446 * Presumably, these unknown entry points (as given by funcName) are device
2447 * extension entrypoints. A hash table is used to keep a list of unknown entry
2448 * points and their mapping to the device extension dispatch table
2449 * (struct loader_dev_ext_dispatch_table).
2450 * \returns
2451 * For a given entry point string (funcName), if an existing mapping is found the
2452 * trampoline address for that mapping is returned. Otherwise, this unknown entry point
2453 * has not been seen yet. Next check if a layer or ICD supports it. If so then a
2454 * new entry in the hash table is initialized and that trampoline address for
2455 * the new entry is returned. Null is returned if the hash table is full or
2456 * if no discovered layer or ICD returns a non-NULL GetProcAddr for it.
2457 */
2458void *loader_dev_ext_gpa(struct loader_instance *inst,
2459 const char *funcName)
2460{
2461 uint32_t idx;
2462 uint32_t seed = 0;
2463
2464 idx = murmurhash(funcName, strlen(funcName), seed) % MAX_NUM_DEV_EXTS;
2465
2466 if (loader_name_in_dev_ext_table(inst, &idx, funcName))
2467 // found funcName already in hash
2468 return loader_get_dev_ext_trampoline(idx);
2469
2470 // Check if funcName is supported in either ICDs or a layer library
2471 if (!loader_check_icds_for_address(inst, funcName)) {
2472 // TODO Add check in layer libraries for support of address
2473 // if support found in layers continue on
2474 return NULL;
2475 }
2476
2477 if (loader_add_dev_ext_table(inst, &idx, funcName)) {
2478 // successfully added new table entry
2479 // init any dev dispatch table entrys as needed
2480 loader_init_dispatch_dev_ext_entry(inst, NULL, idx, funcName);
2481 return loader_get_dev_ext_trampoline(idx);
2482 }
2483
2484 return NULL;
2485}
2486
Jon Ashburne0e64572015-09-30 12:56:42 -06002487struct loader_instance *loader_get_instance(const VkInstance instance)
2488{
2489 /* look up the loader_instance in our list by comparing dispatch tables, as
2490 * there is no guarantee the instance is still a loader_instance* after any
2491 * layers which wrap the instance object.
2492 */
2493 const VkLayerInstanceDispatchTable *disp;
2494 struct loader_instance *ptr_instance = NULL;
2495 disp = loader_get_instance_dispatch(instance);
2496 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
2497 if (inst->disp == disp) {
2498 ptr_instance = inst;
2499 break;
2500 }
2501 }
2502 return ptr_instance;
2503}
2504
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002505static loader_platform_dl_handle loader_add_layer_lib(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002506 const struct loader_instance *inst,
Jon Ashburn4f67d742015-05-27 13:19:22 -06002507 const char *chain_type,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002508 struct loader_layer_properties *layer_prop)
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002509{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002510 struct loader_lib_info *new_layer_lib_list, *my_lib;
Jon Ashburne39a4f82015-08-28 13:38:21 -06002511 size_t new_alloc_size;
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -06002512 /*
2513 * TODO: We can now track this information in the
2514 * scanned_layer_libraries list.
2515 */
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002516 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) {
Jon Ashburn3d002332015-08-20 16:35:30 -06002517 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, layer_prop->lib_name) == 0) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002518 /* Have already loaded this library, just increment ref count */
2519 loader.loaded_layer_lib_list[i].ref_count++;
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07002520 loader_log(VK_DEBUG_REPORT_DEBUG_BIT, 0,
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002521 "%s Chain: Increment layer reference count for layer library %s",
Jon Ashburn3d002332015-08-20 16:35:30 -06002522 chain_type, layer_prop->lib_name);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002523 return loader.loaded_layer_lib_list[i].lib_handle;
2524 }
2525 }
2526
2527 /* Haven't seen this library so load it */
Jon Ashburne39a4f82015-08-28 13:38:21 -06002528 new_alloc_size = 0;
2529 if (loader.loaded_layer_lib_capacity == 0)
2530 new_alloc_size = 8 * sizeof(struct loader_lib_info);
2531 else if (loader.loaded_layer_lib_capacity <= loader.loaded_layer_lib_count *
2532 sizeof(struct loader_lib_info))
2533 new_alloc_size = loader.loaded_layer_lib_capacity * 2;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002534
Jon Ashburne39a4f82015-08-28 13:38:21 -06002535 if (new_alloc_size) {
2536 new_layer_lib_list = loader_heap_realloc(
2537 inst, loader.loaded_layer_lib_list,
2538 loader.loaded_layer_lib_capacity,
2539 new_alloc_size,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002540 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburne39a4f82015-08-28 13:38:21 -06002541 if (!new_layer_lib_list) {
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07002542 loader_log(VK_DEBUG_REPORT_ERROR_BIT, 0, "loader: realloc failed in loader_add_layer_lib");
Jon Ashburne39a4f82015-08-28 13:38:21 -06002543 return NULL;
2544 }
2545 loader.loaded_layer_lib_capacity = new_alloc_size;
2546 } else
2547 new_layer_lib_list = loader.loaded_layer_lib_list;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002548 my_lib = &new_layer_lib_list[loader.loaded_layer_lib_count];
2549
Jon Ashburn3d002332015-08-20 16:35:30 -06002550 strncpy(my_lib->lib_name, layer_prop->lib_name, sizeof(my_lib->lib_name));
2551 my_lib->lib_name[sizeof(my_lib->lib_name) - 1] = '\0';
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002552 my_lib->ref_count = 0;
2553 my_lib->lib_handle = NULL;
2554
2555 if ((my_lib->lib_handle = loader_platform_open_library(my_lib->lib_name)) == NULL) {
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07002556 loader_log(VK_DEBUG_REPORT_ERROR_BIT, 0,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002557 loader_platform_open_library_error(my_lib->lib_name));
2558 return NULL;
2559 } else {
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07002560 loader_log(VK_DEBUG_REPORT_DEBUG_BIT, 0,
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002561 "Chain: %s: Loading layer library %s",
Jon Ashburn3d002332015-08-20 16:35:30 -06002562 chain_type, layer_prop->lib_name);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002563 }
2564 loader.loaded_layer_lib_count++;
2565 loader.loaded_layer_lib_list = new_layer_lib_list;
2566 my_lib->ref_count++;
2567
2568 return my_lib->lib_handle;
2569}
2570
2571static void loader_remove_layer_lib(
2572 struct loader_instance *inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002573 struct loader_layer_properties *layer_prop)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002574{
2575 uint32_t idx;
Tony Barbourb5d2c942015-07-14 13:34:05 -06002576 struct loader_lib_info *new_layer_lib_list, *my_lib = NULL;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002577
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002578 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) {
Jon Ashburn3d002332015-08-20 16:35:30 -06002579 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, layer_prop->lib_name) == 0) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002580 /* found matching library */
2581 idx = i;
2582 my_lib = &loader.loaded_layer_lib_list[i];
2583 break;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002584 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002585 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002586
Tony Barbourb5d2c942015-07-14 13:34:05 -06002587 if (my_lib) {
2588 my_lib->ref_count--;
2589 if (my_lib->ref_count > 0) {
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07002590 loader_log(VK_DEBUG_REPORT_DEBUG_BIT, 0,
Jon Ashburn3d002332015-08-20 16:35:30 -06002591 "Decrement reference count for layer library %s", layer_prop->lib_name);
Tony Barbourb5d2c942015-07-14 13:34:05 -06002592 return;
2593 }
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07002594 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002595 loader_platform_close_library(my_lib->lib_handle);
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07002596 loader_log(VK_DEBUG_REPORT_DEBUG_BIT, 0,
Jon Ashburn3d002332015-08-20 16:35:30 -06002597 "Unloading layer library %s", layer_prop->lib_name);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002598
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002599 /* Need to remove unused library from list */
Jon Ashburne39a4f82015-08-28 13:38:21 -06002600 new_layer_lib_list = loader_heap_alloc(inst,
2601 loader.loaded_layer_lib_capacity,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002602 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002603 if (!new_layer_lib_list) {
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07002604 loader_log(VK_DEBUG_REPORT_ERROR_BIT, 0, "loader: heap alloc failed loader_remove_layer_library");
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002605 return;
2606 }
2607
2608 if (idx > 0) {
2609 /* Copy records before idx */
2610 memcpy(new_layer_lib_list, &loader.loaded_layer_lib_list[0],
2611 sizeof(struct loader_lib_info) * idx);
2612 }
2613 if (idx < (loader.loaded_layer_lib_count - 1)) {
2614 /* Copy records after idx */
2615 memcpy(&new_layer_lib_list[idx], &loader.loaded_layer_lib_list[idx+1],
2616 sizeof(struct loader_lib_info) * (loader.loaded_layer_lib_count - idx - 1));
2617 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002618
Jon Ashburne39a4f82015-08-28 13:38:21 -06002619 loader_heap_free(inst, loader.loaded_layer_lib_list);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002620 loader.loaded_layer_lib_count--;
2621 loader.loaded_layer_lib_list = new_layer_lib_list;
Jon Ashburnb8358052014-11-18 09:06:04 -07002622}
2623
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002624
2625/**
2626 * Go through the search_list and find any layers which match type. If layer
2627 * type match is found in then add it to ext_list.
2628 */
2629//TODO need to handle implict layer enable env var and disable env var
Jon Ashburn0c26e712015-07-02 16:10:32 -06002630static void loader_add_layer_implicit(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002631 const struct loader_instance *inst,
Jon Ashburn0c26e712015-07-02 16:10:32 -06002632 const enum layer_type type,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002633 struct loader_layer_list *list,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002634 const struct loader_layer_list *search_list)
Jon Ashburn0c26e712015-07-02 16:10:32 -06002635{
2636 uint32_t i;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002637 for (i = 0; i < search_list->count; i++) {
2638 const struct loader_layer_properties *prop = &search_list->list[i];
Jon Ashburn0c26e712015-07-02 16:10:32 -06002639 if (prop->type & type) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002640 /* Found an layer with the same type, add to layer_list */
Jon Ashburne39a4f82015-08-28 13:38:21 -06002641 loader_add_to_layer_list(inst, list, 1, prop);
Jon Ashburn0c26e712015-07-02 16:10:32 -06002642 }
2643 }
2644
2645}
2646
2647/**
2648 * Get the layer name(s) from the env_name environment variable. If layer
Jon Ashburnbd332cc2015-07-07 10:27:45 -06002649 * is found in search_list then add it to layer_list. But only add it to
2650 * layer_list if type matches.
Jon Ashburn0c26e712015-07-02 16:10:32 -06002651 */
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002652static void loader_add_layer_env(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002653 const struct loader_instance *inst,
Jon Ashburnbd332cc2015-07-07 10:27:45 -06002654 const enum layer_type type,
Jon Ashburneb6d5682015-07-02 14:10:53 -06002655 const char *env_name,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002656 struct loader_layer_list *layer_list,
2657 const struct loader_layer_list *search_list)
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002658{
Ian Elliott4470a302015-02-17 10:33:47 -07002659 char *layerEnv;
Jon Ashburneb6d5682015-07-02 14:10:53 -06002660 char *next, *name;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002661
Jon Ashburneb6d5682015-07-02 14:10:53 -06002662 layerEnv = getenv(env_name);
Ian Elliott4470a302015-02-17 10:33:47 -07002663 if (layerEnv == NULL) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002664 return;
Ian Elliott4470a302015-02-17 10:33:47 -07002665 }
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -06002666 name = loader_stack_alloc(strlen(layerEnv) + 1);
Jon Ashburneb6d5682015-07-02 14:10:53 -06002667 if (name == NULL) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002668 return;
Ian Elliott4470a302015-02-17 10:33:47 -07002669 }
Jon Ashburneb6d5682015-07-02 14:10:53 -06002670 strcpy(name, layerEnv);
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002671
Jon Ashburneb6d5682015-07-02 14:10:53 -06002672 while (name && *name ) {
2673 next = loader_get_next_path(name);
Jon Ashburne39a4f82015-08-28 13:38:21 -06002674 loader_find_layer_name_add_list(inst, name, type, search_list, layer_list);
Jon Ashburneb6d5682015-07-02 14:10:53 -06002675 name = next;
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07002676 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002677
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002678 return;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002679}
2680
Courtney Goeltzenleuchter7d0023c2015-06-08 15:09:22 -06002681void loader_deactivate_instance_layers(struct loader_instance *instance)
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002682{
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002683 if (!instance->activated_layer_list.count) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002684 return;
2685 }
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002686
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002687 /* Create instance chain of enabled layers */
Courtney Goeltzenleuchter7d0023c2015-06-08 15:09:22 -06002688 for (uint32_t i = 0; i < instance->activated_layer_list.count; i++) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002689 struct loader_layer_properties *layer_prop = &instance->activated_layer_list.list[i];
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002690
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002691 loader_remove_layer_lib(instance, layer_prop);
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002692 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06002693 loader_destroy_layer_list(instance, &instance->activated_layer_list);
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002694}
2695
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002696VkResult loader_enable_instance_layers(
Jon Ashburnb82c1852015-08-11 14:49:54 -06002697 struct loader_instance *inst,
2698 const VkInstanceCreateInfo *pCreateInfo,
2699 const struct loader_layer_list *instance_layers)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002700{
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002701 VkResult err;
2702
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06002703 assert(inst && "Cannot have null instance");
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002704
Jon Ashburne39a4f82015-08-28 13:38:21 -06002705 if (!loader_init_layer_list(inst, &inst->activated_layer_list)) {
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07002706 loader_log(VK_DEBUG_REPORT_ERROR_BIT, 0, "Failed to alloc Instance activated layer list");
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002707 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002708 }
2709
Jon Ashburn0c26e712015-07-02 16:10:32 -06002710 /* Add any implicit layers first */
2711 loader_add_layer_implicit(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002712 inst,
Jon Ashburn0c26e712015-07-02 16:10:32 -06002713 VK_LAYER_TYPE_INSTANCE_IMPLICIT,
2714 &inst->activated_layer_list,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002715 instance_layers);
Jon Ashburn0c26e712015-07-02 16:10:32 -06002716
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002717 /* Add any layers specified via environment variable next */
Jon Ashburneb6d5682015-07-02 14:10:53 -06002718 loader_add_layer_env(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002719 inst,
Jon Ashburnbd332cc2015-07-07 10:27:45 -06002720 VK_LAYER_TYPE_INSTANCE_EXPLICIT,
Jon Ashburneb6d5682015-07-02 14:10:53 -06002721 "VK_INSTANCE_LAYERS",
2722 &inst->activated_layer_list,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002723 instance_layers);
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002724
2725 /* Add layers specified by the application */
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002726 err = loader_add_layer_names_to_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002727 inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002728 &inst->activated_layer_list,
Chia-I Wud50a7d72015-10-26 20:48:51 +08002729 pCreateInfo->enabledLayerNameCount,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002730 pCreateInfo->ppEnabledLayerNames,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002731 instance_layers);
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002732
2733 return err;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002734}
2735
Jon Ashburn27cd5842015-05-12 17:26:48 -06002736uint32_t loader_activate_instance_layers(struct loader_instance *inst)
2737{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002738 uint32_t layer_idx;
Jon Ashburn128f9422015-05-28 19:16:58 -06002739 VkBaseLayerObject *wrappedInstance;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002740
David Pinedoa0a8a242015-06-24 15:29:18 -06002741 if (inst == NULL) {
Jon Ashburn27cd5842015-05-12 17:26:48 -06002742 return 0;
David Pinedoa0a8a242015-06-24 15:29:18 -06002743 }
Jon Ashburn27cd5842015-05-12 17:26:48 -06002744
2745 // NOTE inst is unwrapped at this point in time
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002746 void* baseObj = (void*) inst;
2747 void* nextObj = (void*) inst;
Jon Ashburn27cd5842015-05-12 17:26:48 -06002748 VkBaseLayerObject *nextInstObj;
2749 PFN_vkGetInstanceProcAddr nextGPA = loader_gpa_instance_internal;
2750
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002751 if (!inst->activated_layer_list.count) {
Courtney Goeltzenleuchtered1a8dd2015-08-07 09:53:18 -06002752 loader_init_instance_core_dispatch_table(inst->disp, nextGPA, (VkInstance) nextObj, (VkInstance) baseObj);
Jon Ashburn27cd5842015-05-12 17:26:48 -06002753 return 0;
2754 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002755
Courtney Goeltzenleuchter6f460c52015-07-06 09:04:55 -06002756 wrappedInstance = loader_stack_alloc(sizeof(VkBaseLayerObject)
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002757 * inst->activated_layer_list.count);
Jon Ashburn128f9422015-05-28 19:16:58 -06002758 if (!wrappedInstance) {
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07002759 loader_log(VK_DEBUG_REPORT_ERROR_BIT, 0, "Failed to alloc Instance objects for layer");
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002760 return 0;
2761 }
2762
2763 /* Create instance chain of enabled layers */
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002764 layer_idx = inst->activated_layer_list.count - 1;
Courtney Goeltzenleuchter0f1d8eb2015-06-07 17:28:17 -06002765 for (int32_t i = inst->activated_layer_list.count - 1; i >= 0; i--) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002766 struct loader_layer_properties *layer_prop = &inst->activated_layer_list.list[i];
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002767 loader_platform_dl_handle lib_handle;
2768
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002769 /*
Courtney Goeltzenleuchteree3b16a2015-06-01 14:12:42 -06002770 * Note: An extension's Get*ProcAddr should not return a function pointer for
2771 * any extension entry points until the extension has been enabled.
2772 * To do this requires a different behavior from Get*ProcAddr functions implemented
2773 * in layers.
2774 * The very first call to a layer will be it's Get*ProcAddr function requesting
Tobin Ehlis1cb7f572015-10-06 09:09:24 -06002775 * the layer's vkGet*ProcAddr. The layer should initialize its internal dispatch table
Courtney Goeltzenleuchteree3b16a2015-06-01 14:12:42 -06002776 * with the wrapped object given (either Instance or Device) and return the layer's
2777 * Get*ProcAddr function. The layer should also use this opportunity to record the
2778 * baseObject so that it can find the correct local dispatch table on future calls.
2779 * Subsequent calls to Get*ProcAddr, CreateInstance, CreateDevice
2780 * will not use a wrapped object and must look up their local dispatch table from
2781 * the given baseObject.
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002782 */
Jon Ashburn128f9422015-05-28 19:16:58 -06002783 nextInstObj = (wrappedInstance + layer_idx);
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002784 nextInstObj->pGPA = (PFN_vkGPA) nextGPA;
Jon Ashburn27cd5842015-05-12 17:26:48 -06002785 nextInstObj->baseObject = baseObj;
2786 nextInstObj->nextObject = nextObj;
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002787 nextObj = (void*) nextInstObj;
Jon Ashburn27cd5842015-05-12 17:26:48 -06002788
Jon Ashburne39a4f82015-08-28 13:38:21 -06002789 lib_handle = loader_add_layer_lib(inst, "instance", layer_prop);
Jon Ashburnf72a04b2015-11-25 17:55:49 -07002790 if (!lib_handle)
2791 continue; // TODO what should we do in this case
Jon Ashburn21c21ee2015-09-09 11:29:24 -06002792 if ((nextGPA = layer_prop->functions.get_instance_proc_addr) == NULL) {
2793 if (layer_prop->functions.str_gipa == NULL || strlen(layer_prop->functions.str_gipa) == 0) {
2794 nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetInstanceProcAddr");
2795 layer_prop->functions.get_instance_proc_addr = nextGPA;
2796 } else
2797 nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gipa);
2798 if (!nextGPA) {
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07002799 loader_log(VK_DEBUG_REPORT_ERROR_BIT, 0, "Failed to find vkGetInstanceProcAddr in layer %s", layer_prop->lib_name);
Courtney Goeltzenleuchtera9e4af42015-06-01 14:49:17 -06002800
Jon Ashburn21c21ee2015-09-09 11:29:24 -06002801 /* TODO: Should we return nextObj, nextGPA to previous? or decrement layer_list count*/
2802 continue;
2803 }
Jon Ashburn27cd5842015-05-12 17:26:48 -06002804 }
2805
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07002806 loader_log(VK_DEBUG_REPORT_INFO_BIT, 0,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002807 "Insert instance layer %s (%s)",
2808 layer_prop->info.layerName,
Jon Ashburn3d002332015-08-20 16:35:30 -06002809 layer_prop->lib_name);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002810
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002811 layer_idx--;
Jon Ashburn27cd5842015-05-12 17:26:48 -06002812 }
2813
Jon Ashburn8fd08252015-05-28 16:25:02 -06002814 loader_init_instance_core_dispatch_table(inst->disp, nextGPA, (VkInstance) nextObj, (VkInstance) baseObj);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002815
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002816 return inst->activated_layer_list.count;
Jon Ashburn27cd5842015-05-12 17:26:48 -06002817}
2818
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002819void loader_activate_instance_layer_extensions(struct loader_instance *inst)
2820{
2821
2822 loader_init_instance_extension_dispatch_table(inst->disp,
2823 inst->disp->GetInstanceProcAddr,
Jon Ashburn128f9422015-05-28 19:16:58 -06002824 (VkInstance) inst);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002825}
2826
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002827static VkResult loader_enable_device_layers(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002828 const struct loader_instance *inst,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002829 struct loader_icd *icd,
2830 struct loader_device *dev,
2831 const VkDeviceCreateInfo *pCreateInfo,
2832 const struct loader_layer_list *device_layers)
2833
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002834{
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002835 VkResult err;
2836
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06002837 assert(dev && "Cannot have null device");
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002838
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002839 if (dev->activated_layer_list.list == NULL || dev->activated_layer_list.capacity == 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06002840 loader_init_layer_list(inst, &dev->activated_layer_list);
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002841 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002842
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002843 if (dev->activated_layer_list.list == NULL) {
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07002844 loader_log(VK_DEBUG_REPORT_ERROR_BIT, 0, "Failed to alloc device activated layer list");
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002845 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002846 }
2847
Jon Ashburn0c26e712015-07-02 16:10:32 -06002848 /* Add any implicit layers first */
2849 loader_add_layer_implicit(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002850 inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002851 VK_LAYER_TYPE_DEVICE_IMPLICIT,
2852 &dev->activated_layer_list,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002853 device_layers);
Jon Ashburn0c26e712015-07-02 16:10:32 -06002854
2855 /* Add any layers specified via environment variable next */
Jon Ashburneb6d5682015-07-02 14:10:53 -06002856 loader_add_layer_env(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002857 inst,
Jon Ashburnbd332cc2015-07-07 10:27:45 -06002858 VK_LAYER_TYPE_DEVICE_EXPLICIT,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002859 "VK_DEVICE_LAYERS",
2860 &dev->activated_layer_list,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002861 device_layers);
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002862
2863 /* Add layers specified by the application */
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002864 err = loader_add_layer_names_to_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002865 inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002866 &dev->activated_layer_list,
Chia-I Wud50a7d72015-10-26 20:48:51 +08002867 pCreateInfo->enabledLayerNameCount,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002868 pCreateInfo->ppEnabledLayerNames,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002869 device_layers);
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002870
2871 return err;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002872}
2873
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002874/*
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06002875 * This function terminates the device chain for CreateDevice.
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002876 * CreateDevice is a special case and so the loader call's
2877 * the ICD's CreateDevice before creating the chain. Since
2878 * we can't call CreateDevice twice we must terminate the
2879 * device chain with something else.
2880 */
Chia-I Wu9ab61502015-11-06 06:42:02 +08002881static VKAPI_ATTR VkResult VKAPI_CALL scratch_vkCreateDevice(
Jon Ashburn24cd4be2015-11-01 14:04:06 -07002882 VkPhysicalDevice physicalDevice,
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002883 const VkDeviceCreateInfo *pCreateInfo,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002884 const VkAllocationCallbacks* pAllocator,
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002885 VkDevice *pDevice)
2886{
2887 return VK_SUCCESS;
2888}
2889
Chia-I Wu9ab61502015-11-06 06:42:02 +08002890static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL loader_GetDeviceChainProcAddr(VkDevice device, const char * name)
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002891{
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002892 if (!strcmp(name, "vkGetDeviceProcAddr"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06002893 return (PFN_vkVoidFunction) loader_GetDeviceChainProcAddr;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002894 if (!strcmp(name, "vkCreateDevice"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06002895 return (PFN_vkVoidFunction) scratch_vkCreateDevice;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002896
Courtney Goeltzenleuchter3e029d12015-06-29 16:09:23 -06002897 struct loader_device *found_dev;
2898 struct loader_icd *icd = loader_get_icd_and_device(device, &found_dev);
2899 return icd->GetDeviceProcAddr(device, name);
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002900}
2901
Jon Ashburndc6fcad2015-06-10 10:06:06 -06002902static uint32_t loader_activate_device_layers(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002903 const struct loader_instance *inst,
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002904 struct loader_device *dev,
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -06002905 VkDevice device)
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002906{
David Pinedoa0a8a242015-06-24 15:29:18 -06002907 if (!dev) {
Jon Ashburndc6fcad2015-06-10 10:06:06 -06002908 return 0;
David Pinedoa0a8a242015-06-24 15:29:18 -06002909 }
Jon Ashburn94e70492015-06-10 10:13:10 -06002910
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002911 /* activate any layer libraries */
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002912 void* nextObj = (void*) device;
2913 void* baseObj = nextObj;
Jon Ashburn94e70492015-06-10 10:13:10 -06002914 VkBaseLayerObject *nextGpuObj;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002915 PFN_vkGetDeviceProcAddr nextGPA = loader_GetDeviceChainProcAddr;
Jon Ashburn94e70492015-06-10 10:13:10 -06002916 VkBaseLayerObject *wrappedGpus;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002917
Courtney Goeltzenleuchtered1a8dd2015-08-07 09:53:18 -06002918 if (!dev->activated_layer_list.count) {
2919 loader_init_device_dispatch_table(&dev->loader_dispatch, nextGPA,
2920 (VkDevice) nextObj, (VkDevice) baseObj);
Jon Ashburn94e70492015-06-10 10:13:10 -06002921 return 0;
Courtney Goeltzenleuchtered1a8dd2015-08-07 09:53:18 -06002922 }
Jon Ashburn94e70492015-06-10 10:13:10 -06002923
Jon Ashburne39a4f82015-08-28 13:38:21 -06002924 wrappedGpus = loader_heap_alloc(inst,
2925 sizeof (VkBaseLayerObject) * dev->activated_layer_list.count,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002926 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn94e70492015-06-10 10:13:10 -06002927 if (!wrappedGpus) {
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07002928 loader_log(VK_DEBUG_REPORT_ERROR_BIT, 0, "Failed to alloc Gpu objects for layer");
Jon Ashburn94e70492015-06-10 10:13:10 -06002929 return 0;
2930 }
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002931
Jon Ashburn94e70492015-06-10 10:13:10 -06002932 for (int32_t i = dev->activated_layer_list.count - 1; i >= 0; i--) {
2933
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002934 struct loader_layer_properties *layer_prop = &dev->activated_layer_list.list[i];
Jon Ashburn94e70492015-06-10 10:13:10 -06002935 loader_platform_dl_handle lib_handle;
2936
Jon Ashburn94e70492015-06-10 10:13:10 -06002937 nextGpuObj = (wrappedGpus + i);
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002938 nextGpuObj->pGPA = (PFN_vkGPA)nextGPA;
Jon Ashburn94e70492015-06-10 10:13:10 -06002939 nextGpuObj->baseObject = baseObj;
2940 nextGpuObj->nextObject = nextObj;
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002941 nextObj = (void*) nextGpuObj;
Jon Ashburn94e70492015-06-10 10:13:10 -06002942
Jon Ashburne39a4f82015-08-28 13:38:21 -06002943 lib_handle = loader_add_layer_lib(inst, "device", layer_prop);
Jon Ashburn21c21ee2015-09-09 11:29:24 -06002944 if ((nextGPA = layer_prop->functions.get_device_proc_addr) == NULL) {
2945 if (layer_prop->functions.str_gdpa == NULL || strlen(layer_prop->functions.str_gdpa) == 0) {
2946 nextGPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetDeviceProcAddr");
2947 layer_prop->functions.get_device_proc_addr = nextGPA;
2948 } else
2949 nextGPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gdpa);
2950 if (!nextGPA) {
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07002951 loader_log(VK_DEBUG_REPORT_ERROR_BIT, 0, "Failed to find vkGetDeviceProcAddr in layer %s", layer_prop->lib_name);
Jon Ashburn21c21ee2015-09-09 11:29:24 -06002952 continue;
2953 }
Jon Ashburn94e70492015-06-10 10:13:10 -06002954 }
2955
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07002956 loader_log(VK_DEBUG_REPORT_INFO_BIT, 0,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002957 "Insert device layer library %s (%s)",
2958 layer_prop->info.layerName,
Jon Ashburn3d002332015-08-20 16:35:30 -06002959 layer_prop->lib_name);
Jon Ashburn94e70492015-06-10 10:13:10 -06002960
2961 }
2962
2963 loader_init_device_dispatch_table(&dev->loader_dispatch, nextGPA,
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002964 (VkDevice) nextObj, (VkDevice) baseObj);
Jon Ashburne39a4f82015-08-28 13:38:21 -06002965 loader_heap_free(inst, wrappedGpus);
Jon Ashburn94e70492015-06-10 10:13:10 -06002966
Jon Ashburndc6fcad2015-06-10 10:06:06 -06002967 return dev->activated_layer_list.count;
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002968}
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002969
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002970VkResult loader_validate_layers(
2971 const uint32_t layer_count,
2972 const char * const *ppEnabledLayerNames,
Jon Ashburn3d002332015-08-20 16:35:30 -06002973 const struct loader_layer_list *list)
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06002974{
2975 struct loader_layer_properties *prop;
2976
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002977 for (uint32_t i = 0; i < layer_count; i++) {
Jon Ashburne13ecc92015-08-03 17:19:30 -06002978 prop = loader_get_layer_property(ppEnabledLayerNames[i],
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002979 list);
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06002980 if (!prop) {
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06002981 return VK_ERROR_LAYER_NOT_PRESENT;
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06002982 }
2983 }
2984
2985 return VK_SUCCESS;
2986}
2987
2988VkResult loader_validate_instance_extensions(
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06002989 const struct loader_extension_list *icd_exts,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002990 const struct loader_layer_list *instance_layer,
2991 const VkInstanceCreateInfo *pCreateInfo)
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06002992{
Jon Ashburn5c042ea2015-08-04 11:14:18 -06002993 VkExtensionProperties *extension_prop;
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002994 struct loader_layer_properties *layer_prop;
2995
Chia-I Wud50a7d72015-10-26 20:48:51 +08002996 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) {
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002997 extension_prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06002998 icd_exts);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002999
3000 if (extension_prop) {
3001 continue;
3002 }
3003
3004 extension_prop = NULL;
3005
3006 /* Not in global list, search layer extension lists */
Chia-I Wud50a7d72015-10-26 20:48:51 +08003007 for (uint32_t j = 0; j < pCreateInfo->enabledLayerNameCount; j++) {
Jon Ashburne13ecc92015-08-03 17:19:30 -06003008 layer_prop = loader_get_layer_property(pCreateInfo->ppEnabledLayerNames[i],
Jon Ashburnb82c1852015-08-11 14:49:54 -06003009 instance_layer);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003010 if (!layer_prop) {
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003011 /* Should NOT get here, loader_validate_layers
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003012 * should have already filtered this case out.
3013 */
3014 continue;
3015 }
3016
3017 extension_prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
3018 &layer_prop->instance_extension_list);
3019 if (extension_prop) {
3020 /* Found the extension in one of the layers enabled by the app. */
3021 break;
3022 }
3023 }
3024
3025 if (!extension_prop) {
3026 /* Didn't find extension name in any of the global layers, error out */
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06003027 return VK_ERROR_EXTENSION_NOT_PRESENT;
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003028 }
3029 }
3030 return VK_SUCCESS;
3031}
3032
3033VkResult loader_validate_device_extensions(
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003034 struct loader_physical_device *phys_dev,
Jon Ashburnb82c1852015-08-11 14:49:54 -06003035 const struct loader_layer_list *device_layer,
3036 const VkDeviceCreateInfo *pCreateInfo)
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003037{
Jon Ashburn5c042ea2015-08-04 11:14:18 -06003038 VkExtensionProperties *extension_prop;
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003039 struct loader_layer_properties *layer_prop;
3040
Chia-I Wud50a7d72015-10-26 20:48:51 +08003041 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) {
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003042 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i];
3043 extension_prop = get_extension_property(extension_name,
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003044 &phys_dev->device_extension_cache);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003045
3046 if (extension_prop) {
3047 continue;
3048 }
3049
3050 /* Not in global list, search layer extension lists */
Chia-I Wud50a7d72015-10-26 20:48:51 +08003051 for (uint32_t j = 0; j < pCreateInfo->enabledLayerNameCount; j++) {
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003052 const char *layer_name = pCreateInfo->ppEnabledLayerNames[j];
Jon Ashburne13ecc92015-08-03 17:19:30 -06003053 layer_prop = loader_get_layer_property(layer_name,
Jon Ashburnb82c1852015-08-11 14:49:54 -06003054 device_layer);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003055
3056 if (!layer_prop) {
3057 /* Should NOT get here, loader_validate_instance_layers
3058 * should have already filtered this case out.
3059 */
3060 continue;
3061 }
3062
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07003063 extension_prop = get_dev_extension_property(extension_name,
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003064 &layer_prop->device_extension_list);
3065 if (extension_prop) {
3066 /* Found the extension in one of the layers enabled by the app. */
3067 break;
3068 }
3069 }
3070
3071 if (!extension_prop) {
3072 /* Didn't find extension name in any of the device layers, error out */
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06003073 return VK_ERROR_EXTENSION_NOT_PRESENT;
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003074 }
3075 }
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06003076 return VK_SUCCESS;
3077}
3078
Chia-I Wu9ab61502015-11-06 06:42:02 +08003079VKAPI_ATTR VkResult VKAPI_CALL loader_CreateInstance(
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003080 const VkInstanceCreateInfo* pCreateInfo,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003081 const VkAllocationCallbacks* pAllocator,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003082 VkInstance* pInstance)
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003083{
Jon Ashburneed0c002015-05-21 17:42:17 -06003084 struct loader_instance *ptr_instance = *(struct loader_instance **) pInstance;
Jon Ashburn46888392015-01-29 15:45:51 -07003085 struct loader_icd *icd;
Jon Ashburn5c042ea2015-08-04 11:14:18 -06003086 VkExtensionProperties *prop;
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003087 char **filtered_extension_names = NULL;
3088 VkInstanceCreateInfo icd_create_info;
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06003089 VkResult res = VK_SUCCESS;
Jon Ashburn7e18de02015-11-19 09:29:51 -07003090 bool success = false;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003091
Tony Barbour3c78ff42015-12-04 13:24:39 -07003092 memcpy(&icd_create_info, pCreateInfo, sizeof(icd_create_info));
3093
Chia-I Wud50a7d72015-10-26 20:48:51 +08003094 icd_create_info.enabledLayerNameCount = 0;
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003095 icd_create_info.ppEnabledLayerNames = NULL;
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003096
3097 /*
3098 * NOTE: Need to filter the extensions to only those
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003099 * supported by the ICD.
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003100 * No ICD will advertise support for layers. An ICD
3101 * library could support a layer, but it would be
3102 * independent of the actual ICD, just in the same library.
3103 */
Chia-I Wud50a7d72015-10-26 20:48:51 +08003104 filtered_extension_names = loader_stack_alloc(pCreateInfo->enabledExtensionNameCount * sizeof(char *));
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003105 if (!filtered_extension_names) {
3106 return VK_ERROR_OUT_OF_HOST_MEMORY;
3107 }
3108 icd_create_info.ppEnabledExtensionNames = (const char * const *) filtered_extension_names;
3109
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003110 for (uint32_t i = 0; i < ptr_instance->icd_libs.count; i++) {
3111 icd = loader_icd_add(ptr_instance, &ptr_instance->icd_libs.list[i]);
Jon Ashburn46888392015-01-29 15:45:51 -07003112 if (icd) {
Chia-I Wud50a7d72015-10-26 20:48:51 +08003113 icd_create_info.enabledExtensionNameCount = 0;
3114 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) {
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003115 prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
Jon Ashburn5c6a46f2015-08-14 14:49:22 -06003116 &ptr_instance->ext_list);
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003117 if (prop) {
Chia-I Wud50a7d72015-10-26 20:48:51 +08003118 filtered_extension_names[icd_create_info.enabledExtensionNameCount] = (char *) pCreateInfo->ppEnabledExtensionNames[i];
3119 icd_create_info.enabledExtensionNameCount++;
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003120 }
3121 }
3122
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003123 res = ptr_instance->icd_libs.list[i].CreateInstance(&icd_create_info,
Chia-I Wuf7458c52015-10-26 21:10:41 +08003124 pAllocator,
Jon Ashburn3da71f22015-05-14 12:43:38 -06003125 &(icd->instance));
Jon Ashburn7e18de02015-11-19 09:29:51 -07003126 if (res == VK_SUCCESS)
3127 success = loader_icd_init_entrys(
Jon Ashburnc624c882015-07-16 10:17:29 -06003128 icd,
3129 icd->instance,
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003130 ptr_instance->icd_libs.list[i].GetInstanceProcAddr);
Jon Ashburnc624c882015-07-16 10:17:29 -06003131
3132 if (res != VK_SUCCESS || !success)
Jon Ashburn46888392015-01-29 15:45:51 -07003133 {
3134 ptr_instance->icds = ptr_instance->icds->next;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003135 loader_icd_destroy(ptr_instance, icd);
Jon Ashburn3da71f22015-05-14 12:43:38 -06003136 icd->instance = VK_NULL_HANDLE;
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -07003137 loader_log(VK_DEBUG_REPORT_ERROR_BIT, 0,
Jon Ashburnc624c882015-07-16 10:17:29 -06003138 "ICD ignored: failed to CreateInstance and find entrypoints with ICD");
Jon Ashburn46888392015-01-29 15:45:51 -07003139 }
3140 }
Jon Ashburn46888392015-01-29 15:45:51 -07003141 }
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003142
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06003143 /*
3144 * If no ICDs were added to instance list and res is unchanged
3145 * from it's initial value, the loader was unable to find
3146 * a suitable ICD.
3147 */
Ian Elliotteb450762015-02-05 15:19:15 -07003148 if (ptr_instance->icds == NULL) {
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06003149 if (res == VK_SUCCESS) {
3150 return VK_ERROR_INCOMPATIBLE_DRIVER;
3151 } else {
3152 return res;
3153 }
Ian Elliotteb450762015-02-05 15:19:15 -07003154 }
Jon Ashburn46888392015-01-29 15:45:51 -07003155
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06003156 return VK_SUCCESS;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003157}
3158
Chia-I Wu9ab61502015-11-06 06:42:02 +08003159VKAPI_ATTR void VKAPI_CALL loader_DestroyInstance(
Chia-I Wuf7458c52015-10-26 21:10:41 +08003160 VkInstance instance,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003161 const VkAllocationCallbacks* pAllocator)
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003162{
Courtney Goeltzenleuchterdeceded2015-06-08 15:04:02 -06003163 struct loader_instance *ptr_instance = loader_instance(instance);
Jon Ashburn3da71f22015-05-14 12:43:38 -06003164 struct loader_icd *icds = ptr_instance->icds;
Jon Ashburna6fd2612015-06-16 14:43:19 -06003165 struct loader_icd *next_icd;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003166
3167 // Remove this instance from the list of instances:
3168 struct loader_instance *prev = NULL;
3169 struct loader_instance *next = loader.instances;
3170 while (next != NULL) {
3171 if (next == ptr_instance) {
3172 // Remove this instance from the list:
3173 if (prev)
3174 prev->next = next->next;
Jon Ashburnc5c49602015-02-03 09:26:59 -07003175 else
3176 loader.instances = next->next;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003177 break;
3178 }
3179 prev = next;
3180 next = next->next;
3181 }
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003182
Jon Ashburn3da71f22015-05-14 12:43:38 -06003183 while (icds) {
3184 if (icds->instance) {
Chia-I Wuf7458c52015-10-26 21:10:41 +08003185 icds->DestroyInstance(icds->instance, pAllocator);
Tony Barbourf20f87b2015-04-22 09:02:32 -06003186 }
Jon Ashburna6fd2612015-06-16 14:43:19 -06003187 next_icd = icds->next;
Jon Ashburn3da71f22015-05-14 12:43:38 -06003188 icds->instance = VK_NULL_HANDLE;
Jon Ashburna6fd2612015-06-16 14:43:19 -06003189 loader_icd_destroy(ptr_instance, icds);
3190
3191 icds = next_icd;
Jon Ashburn46888392015-01-29 15:45:51 -07003192 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06003193 loader_delete_layer_properties(ptr_instance, &ptr_instance->device_layer_list);
3194 loader_delete_layer_properties(ptr_instance, &ptr_instance->instance_layer_list);
3195 loader_scanned_icd_clear(ptr_instance, &ptr_instance->icd_libs);
Jon Ashburn6e6a2162015-12-10 08:51:10 -07003196 loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *)
3197 &ptr_instance->ext_list);
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003198 for (uint32_t i = 0; i < ptr_instance->total_gpu_count; i++)
Jon Ashburn6e6a2162015-12-10 08:51:10 -07003199 loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *)
3200 &ptr_instance->phys_devs[i].device_extension_cache);
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003201 loader_heap_free(ptr_instance, ptr_instance->phys_devs);
Jon Ashburnfc1031e2015-11-17 15:31:02 -07003202 loader_free_dev_ext_table(ptr_instance);
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003203}
3204
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003205VkResult loader_init_physical_device_info(struct loader_instance *ptr_instance)
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003206{
3207 struct loader_icd *icd;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003208 uint32_t i, j, idx, count = 0;
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06003209 VkResult res;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003210 struct loader_phys_dev_per_icd *phys_devs;
3211
3212 ptr_instance->total_gpu_count = 0;
3213 phys_devs = (struct loader_phys_dev_per_icd *) loader_stack_alloc(
3214 sizeof(struct loader_phys_dev_per_icd) *
3215 ptr_instance->total_icd_count);
3216 if (!phys_devs)
3217 return VK_ERROR_OUT_OF_HOST_MEMORY;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003218
3219 icd = ptr_instance->icds;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003220 for (i = 0; i < ptr_instance->total_icd_count; i++) {
3221 assert(icd);
3222 res = icd->EnumeratePhysicalDevices(icd->instance, &phys_devs[i].count, NULL);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003223 if (res != VK_SUCCESS)
3224 return res;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003225 count += phys_devs[i].count;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003226 icd = icd->next;
3227 }
3228
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003229 ptr_instance->phys_devs = (struct loader_physical_device *) loader_heap_alloc(
3230 ptr_instance,
3231 count * sizeof(struct loader_physical_device),
3232 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
3233 if (!ptr_instance->phys_devs)
3234 return VK_ERROR_OUT_OF_HOST_MEMORY;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003235
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003236 icd = ptr_instance->icds;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003237
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003238 struct loader_physical_device *inst_phys_devs = ptr_instance->phys_devs;
3239 idx = 0;
3240 for (i = 0; i < ptr_instance->total_icd_count; i++) {
3241 assert(icd);
3242
3243 phys_devs[i].phys_devs = (VkPhysicalDevice *) loader_stack_alloc(
3244 phys_devs[i].count * sizeof(VkPhysicalDevice));
3245 if (!phys_devs[i].phys_devs) {
Jon Ashburn093ce202015-11-02 17:59:02 -07003246 loader_heap_free(ptr_instance, ptr_instance->phys_devs);
3247 ptr_instance->phys_devs = NULL;
Jon Ashburn128f9422015-05-28 19:16:58 -06003248 return VK_ERROR_OUT_OF_HOST_MEMORY;
3249 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003250 res = icd->EnumeratePhysicalDevices(
3251 icd->instance,
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003252 &(phys_devs[i].count),
3253 phys_devs[i].phys_devs);
3254 if ((res == VK_SUCCESS)) {
3255 ptr_instance->total_gpu_count += phys_devs[i].count;
3256 for (j = 0; j < phys_devs[i].count; j++) {
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003257
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003258 // initialize the loader's physicalDevice object
3259 loader_set_dispatch((void *) &inst_phys_devs[idx], ptr_instance->disp);
3260 inst_phys_devs[idx].this_instance = ptr_instance;
3261 inst_phys_devs[idx].this_icd = icd;
3262 inst_phys_devs[idx].phys_dev = phys_devs[i].phys_devs[j];
Jon Ashburn00eb6c02015-11-02 17:40:01 -07003263 memset(&inst_phys_devs[idx].device_extension_cache, 0, sizeof(struct loader_extension_list));
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003264
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003265 idx++;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003266 }
Jon Ashburn093ce202015-11-02 17:59:02 -07003267 } else {
3268 loader_heap_free(ptr_instance, ptr_instance->phys_devs);
3269 ptr_instance->phys_devs = NULL;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003270 return res;
Jon Ashburn093ce202015-11-02 17:59:02 -07003271 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003272
3273 icd = icd->next;
3274 }
3275
3276 return VK_SUCCESS;
3277}
3278
Chia-I Wu9ab61502015-11-06 06:42:02 +08003279VKAPI_ATTR VkResult VKAPI_CALL loader_EnumeratePhysicalDevices(
Courtney Goeltzenleuchter5e41f1d2015-04-20 12:48:54 -06003280 VkInstance instance,
3281 uint32_t* pPhysicalDeviceCount,
3282 VkPhysicalDevice* pPhysicalDevices)
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003283{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003284 uint32_t i;
Jon Ashburn4c392fb2015-01-28 19:57:09 -07003285 struct loader_instance *ptr_instance = (struct loader_instance *) instance;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003286 VkResult res = VK_SUCCESS;
Jon Ashburn4c392fb2015-01-28 19:57:09 -07003287
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003288 if (ptr_instance->total_gpu_count == 0) {
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003289 res = loader_init_physical_device_info(ptr_instance);
Jon Ashburn4c392fb2015-01-28 19:57:09 -07003290 }
3291
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003292 *pPhysicalDeviceCount = ptr_instance->total_gpu_count;
3293 if (!pPhysicalDevices) {
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003294 return res;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003295 }
Jon Ashburn4c392fb2015-01-28 19:57:09 -07003296
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003297 for (i = 0; i < ptr_instance->total_gpu_count; i++) {
3298 pPhysicalDevices[i] = (VkPhysicalDevice) &ptr_instance->phys_devs[i];
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003299 }
3300
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003301 return res;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003302}
3303
Chia-I Wu9ab61502015-11-06 06:42:02 +08003304VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceProperties(
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003305 VkPhysicalDevice physicalDevice,
Tony Barbour59a47322015-06-24 16:06:58 -06003306 VkPhysicalDeviceProperties* pProperties)
Jon Ashburn3da71f22015-05-14 12:43:38 -06003307{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003308 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3309 struct loader_icd *icd = phys_dev->this_icd;
Jon Ashburn3da71f22015-05-14 12:43:38 -06003310
Tony Barbour59a47322015-06-24 16:06:58 -06003311 if (icd->GetPhysicalDeviceProperties)
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003312 icd->GetPhysicalDeviceProperties(phys_dev->phys_dev, pProperties);
Tony Barbour59a47322015-06-24 16:06:58 -06003313}
3314
Chia-I Wu9ab61502015-11-06 06:42:02 +08003315VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceQueueFamilyProperties (
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003316 VkPhysicalDevice physicalDevice,
Chia-I Wud50a7d72015-10-26 20:48:51 +08003317 uint32_t* pQueueFamilyPropertyCount,
Cody Northropd0802882015-08-03 17:04:53 -06003318 VkQueueFamilyProperties* pProperties)
Tony Barbour59a47322015-06-24 16:06:58 -06003319{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003320 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3321 struct loader_icd *icd = phys_dev->this_icd;
Tony Barbour59a47322015-06-24 16:06:58 -06003322
Cody Northropd0802882015-08-03 17:04:53 -06003323 if (icd->GetPhysicalDeviceQueueFamilyProperties)
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003324 icd->GetPhysicalDeviceQueueFamilyProperties(phys_dev->phys_dev, pQueueFamilyPropertyCount, pProperties);
Tony Barbour59a47322015-06-24 16:06:58 -06003325}
3326
Chia-I Wu9ab61502015-11-06 06:42:02 +08003327VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceMemoryProperties (
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003328 VkPhysicalDevice physicalDevice,
Tony Barbour59a47322015-06-24 16:06:58 -06003329 VkPhysicalDeviceMemoryProperties* pProperties)
3330{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003331 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3332 struct loader_icd *icd = phys_dev->this_icd;
Tony Barbour59a47322015-06-24 16:06:58 -06003333
3334 if (icd->GetPhysicalDeviceMemoryProperties)
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003335 icd->GetPhysicalDeviceMemoryProperties(phys_dev->phys_dev, pProperties);
Jon Ashburn3da71f22015-05-14 12:43:38 -06003336}
3337
Chia-I Wu9ab61502015-11-06 06:42:02 +08003338VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceFeatures(
Chris Forbesbc0bb772015-06-21 22:55:02 +12003339 VkPhysicalDevice physicalDevice,
3340 VkPhysicalDeviceFeatures* pFeatures)
3341{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003342 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3343 struct loader_icd *icd = phys_dev->this_icd;
Chris Forbesbc0bb772015-06-21 22:55:02 +12003344
3345 if (icd->GetPhysicalDeviceFeatures)
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003346 icd->GetPhysicalDeviceFeatures(phys_dev->phys_dev, pFeatures);
Chris Forbesbc0bb772015-06-21 22:55:02 +12003347}
3348
Chia-I Wu9ab61502015-11-06 06:42:02 +08003349VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceFormatProperties(
Chris Forbesbc0bb772015-06-21 22:55:02 +12003350 VkPhysicalDevice physicalDevice,
3351 VkFormat format,
3352 VkFormatProperties* pFormatInfo)
3353{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003354 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3355 struct loader_icd *icd = phys_dev->this_icd;
Chris Forbesbc0bb772015-06-21 22:55:02 +12003356
Courtney Goeltzenleuchter2caec862015-07-12 12:52:09 -06003357 if (icd->GetPhysicalDeviceFormatProperties)
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003358 icd->GetPhysicalDeviceFormatProperties(phys_dev->phys_dev, format, pFormatInfo);
Chris Forbesbc0bb772015-06-21 22:55:02 +12003359}
3360
Chia-I Wu9ab61502015-11-06 06:42:02 +08003361VKAPI_ATTR VkResult VKAPI_CALL loader_GetPhysicalDeviceImageFormatProperties(
Jon Ashburn754864f2015-07-23 18:49:07 -06003362 VkPhysicalDevice physicalDevice,
3363 VkFormat format,
3364 VkImageType type,
3365 VkImageTiling tiling,
3366 VkImageUsageFlags usage,
Courtney Goeltzenleuchtera22097a2015-09-10 13:44:12 -06003367 VkImageCreateFlags flags,
Jon Ashburn754864f2015-07-23 18:49:07 -06003368 VkImageFormatProperties* pImageFormatProperties)
3369{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003370 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3371 struct loader_icd *icd = phys_dev->this_icd;
Jon Ashburn754864f2015-07-23 18:49:07 -06003372
Chia-I Wu17241042015-10-31 00:31:16 +08003373 if (!icd->GetPhysicalDeviceImageFormatProperties)
3374 return VK_ERROR_INITIALIZATION_FAILED;
3375
3376 return icd->GetPhysicalDeviceImageFormatProperties(phys_dev->phys_dev, format,
3377 type, tiling, usage, flags, pImageFormatProperties);
Jon Ashburn754864f2015-07-23 18:49:07 -06003378}
3379
Chia-I Wu9ab61502015-11-06 06:42:02 +08003380VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceSparseImageFormatProperties(
Mark Lobodzinski16e8bef2015-07-03 15:58:09 -06003381 VkPhysicalDevice physicalDevice,
3382 VkFormat format,
3383 VkImageType type,
Chia-I Wu5c17c962015-10-31 00:31:16 +08003384 VkSampleCountFlagBits samples,
Mark Lobodzinski16e8bef2015-07-03 15:58:09 -06003385 VkImageUsageFlags usage,
3386 VkImageTiling tiling,
3387 uint32_t* pNumProperties,
3388 VkSparseImageFormatProperties* pProperties)
3389{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003390 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3391 struct loader_icd *icd = phys_dev->this_icd;
Mark Lobodzinski16e8bef2015-07-03 15:58:09 -06003392
3393 if (icd->GetPhysicalDeviceSparseImageFormatProperties)
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003394 icd->GetPhysicalDeviceSparseImageFormatProperties(phys_dev->phys_dev, format, type, samples, usage, tiling, pNumProperties, pProperties);
Mark Lobodzinski16e8bef2015-07-03 15:58:09 -06003395}
3396
Chia-I Wu9ab61502015-11-06 06:42:02 +08003397VKAPI_ATTR VkResult VKAPI_CALL loader_CreateDevice(
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003398 VkPhysicalDevice physicalDevice,
Jon Ashburn95a77ba2015-05-15 15:09:35 -06003399 const VkDeviceCreateInfo* pCreateInfo,
Jon Ashburn46674bf2015-12-11 09:41:34 -07003400 const VkAllocationCallbacks* pAllocator,
Jon Ashburn95a77ba2015-05-15 15:09:35 -06003401 VkDevice* pDevice)
3402{
Jon Ashburn46674bf2015-12-11 09:41:34 -07003403 struct loader_physical_device *phys_dev;
3404 struct loader_icd *icd;
Jon Ashburndc6fcad2015-06-10 10:06:06 -06003405 struct loader_device *dev;
Jon Ashburnfc1031e2015-11-17 15:31:02 -07003406 struct loader_instance *inst;
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003407 VkDeviceCreateInfo device_create_info;
3408 char **filtered_extension_names = NULL;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003409 VkResult res;
Jon Ashburn95a77ba2015-05-15 15:09:35 -06003410
Chia-I Wu02124482015-11-06 06:42:02 +08003411 assert(pCreateInfo->queueCreateInfoCount >= 1);
Mark Lobodzinski0c29b922015-09-17 15:17:34 -06003412
Jon Ashburn46674bf2015-12-11 09:41:34 -07003413 //TODO this only works for one physical device per instance
3414 // once CreateDevice layer bootstrapping is done via DeviceCreateInfo
3415 // hopefully don't need this anymore in trampoline code
3416 phys_dev = loader_get_physical_device(physicalDevice);
3417 icd = phys_dev->this_icd;
Jon Ashburna4cf12b2015-10-26 16:54:51 -06003418 if (!icd)
3419 return VK_ERROR_INITIALIZATION_FAILED;
3420
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003421 inst = phys_dev->this_instance;
Jon Ashburna4cf12b2015-10-26 16:54:51 -06003422
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003423 if (!icd->CreateDevice) {
3424 return VK_ERROR_INITIALIZATION_FAILED;
Jon Ashburn95a77ba2015-05-15 15:09:35 -06003425 }
3426
Jon Ashburnb82c1852015-08-11 14:49:54 -06003427 /* validate any app enabled layers are available */
Chia-I Wud50a7d72015-10-26 20:48:51 +08003428 if (pCreateInfo->enabledLayerNameCount > 0) {
3429 res = loader_validate_layers(pCreateInfo->enabledLayerNameCount,
Jon Ashburnb82c1852015-08-11 14:49:54 -06003430 pCreateInfo->ppEnabledLayerNames,
Jon Ashburne39a4f82015-08-28 13:38:21 -06003431 &inst->device_layer_list);
Jon Ashburnb82c1852015-08-11 14:49:54 -06003432 if (res != VK_SUCCESS) {
3433 return res;
3434 }
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003435 }
3436
Jon Ashburn00eb6c02015-11-02 17:40:01 -07003437 /* Get the physical device extensions if they haven't been retrieved yet */
3438 if (phys_dev->device_extension_cache.capacity == 0) {
Jon Ashburn6e6a2162015-12-10 08:51:10 -07003439 if (!loader_init_generic_list(inst, (struct loader_generic_list *)
3440 &phys_dev->device_extension_cache,
3441 sizeof(VkExtensionProperties))) {
Jon Ashburn00eb6c02015-11-02 17:40:01 -07003442 return VK_ERROR_OUT_OF_HOST_MEMORY;
3443 }
3444 res = loader_add_physical_device_extensions(
3445 inst, physicalDevice,
3446 phys_dev->this_icd->this_icd_lib->lib_name,
3447 &phys_dev->device_extension_cache);
3448 if (res != VK_SUCCESS) {
3449 return res;
3450 }
3451 }
3452 /* make sure requested extensions to be enabled are supported */
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003453 res = loader_validate_device_extensions(phys_dev, &inst->device_layer_list, pCreateInfo);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003454 if (res != VK_SUCCESS) {
3455 return res;
3456 }
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003457
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003458 /*
3459 * NOTE: Need to filter the extensions to only those
3460 * supported by the ICD.
3461 * No ICD will advertise support for layers. An ICD
3462 * library could support a layer, but it would be
3463 * independent of the actual ICD, just in the same library.
3464 */
Chia-I Wud50a7d72015-10-26 20:48:51 +08003465 filtered_extension_names = loader_stack_alloc(pCreateInfo->enabledExtensionNameCount * sizeof(char *));
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003466 if (!filtered_extension_names) {
3467 return VK_ERROR_OUT_OF_HOST_MEMORY;
3468 }
3469
3470 /* Copy user's data */
3471 memcpy(&device_create_info, pCreateInfo, sizeof(VkDeviceCreateInfo));
3472
3473 /* ICD's do not use layers */
Chia-I Wud50a7d72015-10-26 20:48:51 +08003474 device_create_info.enabledLayerNameCount = 0;
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003475 device_create_info.ppEnabledLayerNames = NULL;
3476
Chia-I Wud50a7d72015-10-26 20:48:51 +08003477 device_create_info.enabledExtensionNameCount = 0;
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003478 device_create_info.ppEnabledExtensionNames = (const char * const *) filtered_extension_names;
3479
Chia-I Wud50a7d72015-10-26 20:48:51 +08003480 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) {
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003481 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i];
Jon Ashburn5c042ea2015-08-04 11:14:18 -06003482 VkExtensionProperties *prop = get_extension_property(extension_name,
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003483 &phys_dev->device_extension_cache);
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003484 if (prop) {
Chia-I Wud50a7d72015-10-26 20:48:51 +08003485 filtered_extension_names[device_create_info.enabledExtensionNameCount] = (char *) extension_name;
3486 device_create_info.enabledExtensionNameCount++;
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003487 }
3488 }
3489
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003490 // since physicalDevice object maybe wrapped by a layer need to get unwrapped version
Jon Ashburne0e64572015-09-30 12:56:42 -06003491 // we haven't yet called down the chain for the layer to unwrap the object
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003492 res = icd->CreateDevice(phys_dev->phys_dev, pCreateInfo, pAllocator, pDevice);
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003493 if (res != VK_SUCCESS) {
3494 return res;
3495 }
3496
Jon Ashburne39a4f82015-08-28 13:38:21 -06003497 dev = loader_add_logical_device(inst, *pDevice, &icd->logical_device_list);
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003498 if (dev == NULL) {
3499 return VK_ERROR_OUT_OF_HOST_MEMORY;
3500 }
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003501
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003502 loader_init_dispatch(*pDevice, &dev->loader_dispatch);
3503
Jon Ashburnb82c1852015-08-11 14:49:54 -06003504 /* activate any layers on device chain which terminates with device*/
Jon Ashburne39a4f82015-08-28 13:38:21 -06003505 res = loader_enable_device_layers(inst, icd, dev, pCreateInfo, &inst->device_layer_list);
Jon Ashburnb82c1852015-08-11 14:49:54 -06003506 if (res != VK_SUCCESS) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06003507 loader_destroy_logical_device(inst, dev);
Jon Ashburnb82c1852015-08-11 14:49:54 -06003508 return res;
3509 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06003510 loader_activate_device_layers(inst, dev, *pDevice);
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003511
Jon Ashburnfc1031e2015-11-17 15:31:02 -07003512 /* finally can call down the chain */
3513 res = dev->loader_dispatch.core_dispatch.CreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
3514
Jon Ashburn54978592015-12-11 10:45:00 -07003515 /* initialize any device extension dispatch entry's from the instance list*/
3516 loader_init_dispatch_dev_ext(inst, dev);
3517
Jon Ashburn232e3af2015-11-30 17:21:25 -07003518 /* initialize WSI device extensions as part of core dispatch since loader has
3519 * dedicated trampoline code for these*/
3520 loader_init_device_extension_dispatch_table(&dev->loader_dispatch,
3521 dev->loader_dispatch.core_dispatch.GetDeviceProcAddr,
3522 *pDevice);
Jon Ashburnfc1031e2015-11-17 15:31:02 -07003523 dev->loader_dispatch.core_dispatch.CreateDevice = icd->CreateDevice;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003524
Jon Ashburn95a77ba2015-05-15 15:09:35 -06003525 return res;
3526}
3527
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003528/**
3529 * Get an instance level or global level entry point address.
3530 * @param instance
3531 * @param pName
3532 * @return
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003533 * If instance == NULL returns a global level functions only
3534 * If instance is valid returns a trampoline entry point for all dispatchable Vulkan
3535 * functions both core and extensions.
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003536 */
Chia-I Wu9ab61502015-11-06 06:42:02 +08003537LOADER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char * pName)
Jon Ashburnb0fbe912015-05-06 10:15:07 -06003538{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003539
Jon Ashburn07daee72015-05-21 18:13:33 -06003540 void *addr;
Jon Ashburnb0fbe912015-05-06 10:15:07 -06003541
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003542 addr = globalGetProcAddr(pName);
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003543 if (instance == VK_NULL_HANDLE) {
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003544 // get entrypoint addresses that are global (no dispatchable object)
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003545
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003546 return addr;
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003547 } else {
3548 // if a global entrypoint return NULL
3549 if (addr)
3550 return NULL;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003551 }
3552
Jon Ashburne0e64572015-09-30 12:56:42 -06003553 struct loader_instance *ptr_instance = loader_get_instance(instance);
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003554 if (ptr_instance == NULL)
Jon Ashburn07daee72015-05-21 18:13:33 -06003555 return NULL;
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003556 // Return trampoline code for non-global entrypoints including any extensions.
3557 // Device extensions are returned if a layer or ICD supports the extension.
3558 // Instance extensions are returned if the extension is enabled and the loader
3559 // or someone else supports the extension
3560 return trampolineGetProcAddr(ptr_instance, pName);
Jon Ashburn07daee72015-05-21 18:13:33 -06003561
Jon Ashburnb0fbe912015-05-06 10:15:07 -06003562}
3563
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003564/**
3565 * Get a device level or global level entry point address.
3566 * @param device
3567 * @param pName
3568 * @return
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003569 * If device is valid, returns a device relative entry point for device level
3570 * entry points both core and extensions.
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003571 * Device relative means call down the device chain.
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003572 */
Chia-I Wu9ab61502015-11-06 06:42:02 +08003573LOADER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char * pName)
Courtney Goeltzenleuchter9ec39ac2015-06-22 17:45:21 -06003574{
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003575 void *addr;
Courtney Goeltzenleuchter9ec39ac2015-06-22 17:45:21 -06003576
Jon Ashburn3d526cb2015-04-13 18:10:06 -06003577 /* for entrypoints that loader must handle (ie non-dispatchable or create object)
3578 make sure the loader entrypoint is returned */
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003579 addr = loader_non_passthrough_gdpa(pName);
Ian Elliotte19c9152015-04-15 12:53:19 -06003580 if (addr) {
Jon Ashburn3d526cb2015-04-13 18:10:06 -06003581 return addr;
Ian Elliotte19c9152015-04-15 12:53:19 -06003582 }
Jon Ashburn3d526cb2015-04-13 18:10:06 -06003583
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003584 /* Although CreateDevice is on device chain it's dispatchable object isn't
3585 * a VkDevice or child of VkDevice so return NULL.
3586 */
3587 if (!strcmp(pName, "CreateDevice"))
3588 return NULL;
3589
Jon Ashburn3d526cb2015-04-13 18:10:06 -06003590 /* return the dispatch table entrypoint for the fastest case */
Jon Ashburn8d1b0b52015-05-18 13:20:15 -06003591 const VkLayerDispatchTable *disp_table = * (VkLayerDispatchTable **) device;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06003592 if (disp_table == NULL)
3593 return NULL;
3594
Jon Ashburn27cd5842015-05-12 17:26:48 -06003595 addr = loader_lookup_device_dispatch_table(disp_table, pName);
Chia-I Wuf46b81a2015-01-04 11:12:47 +08003596 if (addr)
3597 return addr;
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003598
3599 if (disp_table->GetDeviceProcAddr == NULL)
3600 return NULL;
3601 return disp_table->GetDeviceProcAddr(device, pName);
Jon Ashburnd38bfb12014-10-14 19:15:22 -06003602}
3603
Chia-I Wu9ab61502015-11-06 06:42:02 +08003604LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003605 const char* pLayerName,
Chia-I Wud50a7d72015-10-26 20:48:51 +08003606 uint32_t* pPropertyCount,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003607 VkExtensionProperties* pProperties)
3608{
Jon Ashburn432d2762015-09-18 12:53:16 -06003609 struct loader_extension_list *global_ext_list=NULL;
Jon Ashburnb82c1852015-08-11 14:49:54 -06003610 struct loader_layer_list instance_layers;
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003611 struct loader_extension_list icd_extensions;
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003612 struct loader_icd_libs icd_libs;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003613 uint32_t copy_size;
3614
Jon Ashburn87d6aa92015-08-28 15:19:27 -06003615 tls_instance = NULL;
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003616 memset(&icd_extensions, 0, sizeof(icd_extensions));
Mike Stroyan09c06c72015-10-01 15:23:48 -06003617 memset(&instance_layers, 0, sizeof(instance_layers));
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003618 loader_platform_thread_once(&once_init, loader_initialize);
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003619
Jon Ashburnb82c1852015-08-11 14:49:54 -06003620 /* get layer libraries if needed */
3621 if (pLayerName && strlen(pLayerName) != 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06003622 loader_layer_scan(NULL, &instance_layers, NULL);
Jon Ashburnb82c1852015-08-11 14:49:54 -06003623 for (uint32_t i = 0; i < instance_layers.count; i++) {
3624 struct loader_layer_properties *props = &instance_layers.list[i];
3625 if (strcmp(props->info.layerName, pLayerName) == 0) {
3626 global_ext_list = &props->instance_extension_list;
3627 }
3628 }
3629 }
3630 else {
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003631 /* Scan/discover all ICD libraries */
3632 memset(&icd_libs, 0 , sizeof(struct loader_icd_libs));
Jon Ashburne39a4f82015-08-28 13:38:21 -06003633 loader_icd_scan(NULL, &icd_libs);
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003634 /* get extensions from all ICD's, merge so no duplicates */
Jon Ashburne39a4f82015-08-28 13:38:21 -06003635 loader_get_icd_loader_instance_extensions(NULL, &icd_libs, &icd_extensions);
3636 loader_scanned_icd_clear(NULL, &icd_libs);
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003637 global_ext_list = &icd_extensions;
Jon Ashburnb82c1852015-08-11 14:49:54 -06003638 }
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003639
Jon Ashburnb82c1852015-08-11 14:49:54 -06003640 if (global_ext_list == NULL) {
Mike Stroyan09c06c72015-10-01 15:23:48 -06003641 loader_destroy_layer_list(NULL, &instance_layers);
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06003642 return VK_ERROR_LAYER_NOT_PRESENT;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003643 }
3644
3645 if (pProperties == NULL) {
Chia-I Wud50a7d72015-10-26 20:48:51 +08003646 *pPropertyCount = global_ext_list->count;
Mike Stroyan09c06c72015-10-01 15:23:48 -06003647 loader_destroy_layer_list(NULL, &instance_layers);
Jon Ashburn6e6a2162015-12-10 08:51:10 -07003648 loader_destroy_generic_list(NULL, (struct loader_generic_list *)
3649 &icd_extensions);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003650 return VK_SUCCESS;
3651 }
3652
Chia-I Wud50a7d72015-10-26 20:48:51 +08003653 copy_size = *pPropertyCount < global_ext_list->count ? *pPropertyCount : global_ext_list->count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003654 for (uint32_t i = 0; i < copy_size; i++) {
3655 memcpy(&pProperties[i],
Jon Ashburnb82c1852015-08-11 14:49:54 -06003656 &global_ext_list->list[i],
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003657 sizeof(VkExtensionProperties));
3658 }
Chia-I Wud50a7d72015-10-26 20:48:51 +08003659 *pPropertyCount = copy_size;
Jon Ashburn6e6a2162015-12-10 08:51:10 -07003660 loader_destroy_generic_list(NULL, (struct loader_generic_list *)
3661 &icd_extensions);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003662
Jon Ashburnb82c1852015-08-11 14:49:54 -06003663 if (copy_size < global_ext_list->count) {
Mike Stroyan09c06c72015-10-01 15:23:48 -06003664 loader_destroy_layer_list(NULL, &instance_layers);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003665 return VK_INCOMPLETE;
3666 }
3667
Mike Stroyan09c06c72015-10-01 15:23:48 -06003668 loader_destroy_layer_list(NULL, &instance_layers);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003669 return VK_SUCCESS;
3670}
3671
Chia-I Wu9ab61502015-11-06 06:42:02 +08003672LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(
Chia-I Wud50a7d72015-10-26 20:48:51 +08003673 uint32_t* pPropertyCount,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003674 VkLayerProperties* pProperties)
Tony Barbour59a47322015-06-24 16:06:58 -06003675{
Jon Ashburn6301a0f2015-05-29 13:15:39 -06003676
Jon Ashburnb82c1852015-08-11 14:49:54 -06003677 struct loader_layer_list instance_layer_list;
Jon Ashburn87d6aa92015-08-28 15:19:27 -06003678 tls_instance = NULL;
Jon Ashburnb82c1852015-08-11 14:49:54 -06003679
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003680 loader_platform_thread_once(&once_init, loader_initialize);
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07003681
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003682 uint32_t copy_size;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06003683
Jon Ashburnb82c1852015-08-11 14:49:54 -06003684 /* get layer libraries */
3685 memset(&instance_layer_list, 0, sizeof(instance_layer_list));
Jon Ashburne39a4f82015-08-28 13:38:21 -06003686 loader_layer_scan(NULL, &instance_layer_list, NULL);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003687
3688 if (pProperties == NULL) {
Chia-I Wud50a7d72015-10-26 20:48:51 +08003689 *pPropertyCount = instance_layer_list.count;
Jon Ashburne39a4f82015-08-28 13:38:21 -06003690 loader_destroy_layer_list(NULL, &instance_layer_list);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003691 return VK_SUCCESS;
3692 }
3693
Chia-I Wud50a7d72015-10-26 20:48:51 +08003694 copy_size = (*pPropertyCount < instance_layer_list.count) ? *pPropertyCount : instance_layer_list.count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003695 for (uint32_t i = 0; i < copy_size; i++) {
Jon Ashburnb82c1852015-08-11 14:49:54 -06003696 memcpy(&pProperties[i], &instance_layer_list.list[i].info, sizeof(VkLayerProperties));
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003697 }
Chia-I Wud50a7d72015-10-26 20:48:51 +08003698 *pPropertyCount = copy_size;
Jon Ashburne39a4f82015-08-28 13:38:21 -06003699 loader_destroy_layer_list(NULL, &instance_layer_list);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003700
Jon Ashburnb82c1852015-08-11 14:49:54 -06003701 if (copy_size < instance_layer_list.count) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003702 return VK_INCOMPLETE;
3703 }
Tony Barbour59a47322015-06-24 16:06:58 -06003704
3705 return VK_SUCCESS;
3706}
3707
Chia-I Wu9ab61502015-11-06 06:42:02 +08003708VKAPI_ATTR VkResult VKAPI_CALL loader_EnumerateDeviceExtensionProperties(
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003709 VkPhysicalDevice physicalDevice,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003710 const char* pLayerName,
Chia-I Wud50a7d72015-10-26 20:48:51 +08003711 uint32_t* pPropertyCount,
Tony Barbour59a47322015-06-24 16:06:58 -06003712 VkExtensionProperties* pProperties)
3713{
Jon Ashburna760a512015-12-14 08:52:14 -07003714 struct loader_physical_device *phys_dev;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003715 uint32_t copy_size;
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07003716
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003717 uint32_t count;
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07003718 struct loader_device_extension_list *dev_ext_list=NULL;
Jon Ashburna760a512015-12-14 08:52:14 -07003719 //TODO fix this aliases physical devices
3720 phys_dev = loader_get_physical_device(physicalDevice);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003721
Jon Ashburnb82c1852015-08-11 14:49:54 -06003722 /* get layer libraries if needed */
3723 if (pLayerName && strlen(pLayerName) != 0) {
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003724 for (uint32_t i = 0; i < phys_dev->this_instance->device_layer_list.count; i++) {
3725 struct loader_layer_properties *props = &phys_dev->this_instance->device_layer_list.list[i];
Jon Ashburnb82c1852015-08-11 14:49:54 -06003726 if (strcmp(props->info.layerName, pLayerName) == 0) {
3727 dev_ext_list = &props->device_extension_list;
3728 }
3729 }
3730 }
3731 else {
Jon Ashburn00eb6c02015-11-02 17:40:01 -07003732 /* this case is during the call down the instance chain */
3733 struct loader_icd *icd = phys_dev->this_icd;
3734 VkResult res;
3735 res = icd->EnumerateDeviceExtensionProperties(phys_dev->phys_dev, NULL, pPropertyCount, pProperties);
3736 if (pProperties != NULL && res == VK_SUCCESS) {
3737 /* initialize dev_extension list within the physicalDevice object */
3738 res = loader_init_physical_device_extensions(phys_dev->this_instance,
3739 phys_dev, *pPropertyCount, pProperties,
3740 &phys_dev->device_extension_cache);
3741 }
3742 return res;
Jon Ashburnb82c1852015-08-11 14:49:54 -06003743 }
3744
Jon Ashburn432d2762015-09-18 12:53:16 -06003745 count = (dev_ext_list == NULL) ? 0: dev_ext_list->count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003746 if (pProperties == NULL) {
Chia-I Wud50a7d72015-10-26 20:48:51 +08003747 *pPropertyCount = count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003748 return VK_SUCCESS;
3749 }
3750
Chia-I Wud50a7d72015-10-26 20:48:51 +08003751 copy_size = *pPropertyCount < count ? *pPropertyCount : count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003752 for (uint32_t i = 0; i < copy_size; i++) {
3753 memcpy(&pProperties[i],
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07003754 &dev_ext_list->list[i].props,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003755 sizeof(VkExtensionProperties));
3756 }
Chia-I Wud50a7d72015-10-26 20:48:51 +08003757 *pPropertyCount = copy_size;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003758
3759 if (copy_size < count) {
3760 return VK_INCOMPLETE;
3761 }
3762
3763 return VK_SUCCESS;
3764}
3765
Chia-I Wu9ab61502015-11-06 06:42:02 +08003766VKAPI_ATTR VkResult VKAPI_CALL loader_EnumerateDeviceLayerProperties(
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003767 VkPhysicalDevice physicalDevice,
Chia-I Wud50a7d72015-10-26 20:48:51 +08003768 uint32_t* pPropertyCount,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003769 VkLayerProperties* pProperties)
3770{
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003771 uint32_t copy_size;
Jon Ashburna760a512015-12-14 08:52:14 -07003772 struct loader_physical_device *phys_dev;
3773 //TODO fix this, aliases physical devices
3774 phys_dev = loader_get_physical_device(physicalDevice);
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003775 uint32_t count = phys_dev->this_instance->device_layer_list.count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003776
3777 if (pProperties == NULL) {
Chia-I Wud50a7d72015-10-26 20:48:51 +08003778 *pPropertyCount = count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003779 return VK_SUCCESS;
3780 }
3781
Chia-I Wud50a7d72015-10-26 20:48:51 +08003782 copy_size = (*pPropertyCount < count) ? *pPropertyCount : count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003783 for (uint32_t i = 0; i < copy_size; i++) {
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003784 memcpy(&pProperties[i], &(phys_dev->this_instance->device_layer_list.list[i].info), sizeof(VkLayerProperties));
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003785 }
Chia-I Wud50a7d72015-10-26 20:48:51 +08003786 *pPropertyCount = copy_size;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003787
3788 if (copy_size < count) {
3789 return VK_INCOMPLETE;
3790 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003791
3792 return VK_SUCCESS;
Jon Ashburn95a77ba2015-05-15 15:09:35 -06003793}