blob: bc020ee9c6a94b2a2811e0ff2a88e834f1bda86b [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,
Mark Lobodzinskifaa90812015-11-25 13:26:15 -0700117 .DbgCreateMsgCallback = loader_DbgCreateMsgCallback,
118 .DbgDestroyMsgCallback = loader_DbgDestroyMsgCallback,
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
Jon Ashburn27cd5842015-05-12 17:26:48 -0600139};
140
Jon Ashburn8810c5f2015-08-18 18:04:47 -0600141LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_init);
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700142
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600143void* loader_heap_alloc(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600144 const struct loader_instance *instance,
145 size_t size,
Jon Ashburn39fbd4e2015-12-10 18:17:34 -0700146 VkSystemAllocationScope alloc_scope)
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600147{
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800148 if (instance && instance->alloc_callbacks.pfnAllocation) {
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600149 /* TODO: What should default alignment be? 1, 4, 8, other? */
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800150 return instance->alloc_callbacks.pfnAllocation(instance->alloc_callbacks.pUserData, size, 4, alloc_scope);
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600151 }
152 return malloc(size);
153}
154
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600155void loader_heap_free(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600156 const struct loader_instance *instance,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800157 void *pMemory)
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600158{
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800159 if (pMemory == NULL) return;
Jon Ashburneacfa3a2015-08-14 12:51:47 -0600160 if (instance && instance->alloc_callbacks.pfnFree) {
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800161 instance->alloc_callbacks.pfnFree(instance->alloc_callbacks.pUserData, pMemory);
Jon Ashburnd2c171b2015-08-13 08:28:48 -0600162 return;
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600163 }
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800164 free(pMemory);
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600165}
166
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600167void* loader_heap_realloc(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600168 const struct loader_instance *instance,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800169 void *pMemory,
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600170 size_t orig_size,
171 size_t size,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800172 VkSystemAllocationScope alloc_scope)
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600173{
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800174 if (pMemory == NULL || orig_size == 0)
Chia-I Wuf7458c52015-10-26 21:10:41 +0800175 return loader_heap_alloc(instance, size, alloc_scope);
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600176 if (size == 0) {
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800177 loader_heap_free(instance, pMemory);
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600178 return NULL;
179 }
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800180 if (instance && instance->alloc_callbacks.pfnAllocation) {
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600181 if (size <= orig_size) {
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800182 memset(((uint8_t *)pMemory) + size, 0, orig_size - size);
183 return pMemory;
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600184 }
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800185 void *new_ptr = instance->alloc_callbacks.pfnAllocation(instance->alloc_callbacks.pUserData, size, 4, alloc_scope);
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600186 if (!new_ptr)
187 return NULL;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800188 memcpy(new_ptr, pMemory, orig_size);
189 instance->alloc_callbacks.pfnFree(instance->alloc_callbacks.pUserData, pMemory);
Jon Ashburne3753b32015-10-21 16:09:27 -0600190 return new_ptr;
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600191 }
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800192 return realloc(pMemory, size);
Jon Ashburnc82eb1c2015-08-27 15:23:52 -0600193}
194
Jon Ashburn87d6aa92015-08-28 15:19:27 -0600195void *loader_tls_heap_alloc(size_t size)
196{
Chia-I Wucf804e82015-10-31 00:31:16 +0800197 return loader_heap_alloc(tls_instance, size, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
Jon Ashburn87d6aa92015-08-28 15:19:27 -0600198}
199
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800200void loader_tls_heap_free(void *pMemory)
Jon Ashburn87d6aa92015-08-28 15:19:27 -0600201{
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800202 loader_heap_free(tls_instance, pMemory);
Jon Ashburn87d6aa92015-08-28 15:19:27 -0600203}
204
Jon Ashburnffad94d2015-06-30 14:46:22 -0700205static void loader_log(VkFlags msg_type, int32_t msg_code,
206 const char *format, ...)
207{
Jon Ashburn86723b02015-07-31 15:47:59 -0600208 char msg[512];
Jon Ashburnffad94d2015-06-30 14:46:22 -0700209 va_list ap;
210 int ret;
211
212 if (!(msg_type & g_loader_log_msgs)) {
213 return;
214 }
215
216 va_start(ap, format);
217 ret = vsnprintf(msg, sizeof(msg), format, ap);
218 if ((ret >= (int) sizeof(msg)) || ret < 0) {
219 msg[sizeof(msg)-1] = '\0';
220 }
221 va_end(ap);
222
Ian Elliott4470a302015-02-17 10:33:47 -0700223#if defined(WIN32)
Jon Ashburnffad94d2015-06-30 14:46:22 -0700224 OutputDebugString(msg);
mschottb9cdb782015-07-22 14:11:29 +0200225 OutputDebugString("\n");
Jon Ashburnffad94d2015-06-30 14:46:22 -0700226#endif
227 fputs(msg, stderr);
228 fputc('\n', stderr);
229}
230
231#if defined(WIN32)
Tony Barbourea968902015-07-29 14:26:21 -0600232static char *loader_get_next_path(char *path);
Jon Ashburnffad94d2015-06-30 14:46:22 -0700233/**
234* Find the list of registry files (names within a key) in key "location".
235*
236* This function looks in the registry (hive = DEFAULT_VK_REGISTRY_HIVE) key as given in "location"
237* for a list or name/values which are added to a returned list (function return value).
238* The DWORD values within the key must be 0 or they are skipped.
Jon Ashburne39a4f82015-08-28 13:38:21 -0600239* Function return is a string with a ';' separated list of filenames.
Jon Ashburnffad94d2015-06-30 14:46:22 -0700240* Function return is NULL if no valid name/value pairs are found in the key,
241* or the key is not found.
242*
243* \returns
244* A string list of filenames as pointer.
245* When done using the returned string list, pointer should be freed.
246*/
Jon Ashburne39a4f82015-08-28 13:38:21 -0600247static char *loader_get_registry_files(const struct loader_instance *inst, char *location)
Jon Ashburnffad94d2015-06-30 14:46:22 -0700248{
249 LONG rtn_value;
250 HKEY hive, key;
Piers Daniell524ec732015-11-05 16:58:26 -0700251 DWORD access_flags;
Jon Ashburnffad94d2015-06-30 14:46:22 -0700252 char name[2048];
253 char *out = NULL;
Tony Barbourea968902015-07-29 14:26:21 -0600254 char *loc = location;
255 char *next;
Jon Ashburnffad94d2015-06-30 14:46:22 -0700256 DWORD idx = 0;
257 DWORD name_size = sizeof(name);
258 DWORD value;
259 DWORD total_size = 4096;
260 DWORD value_size = sizeof(value);
Tony Barbourea968902015-07-29 14:26:21 -0600261
262 while(*loc)
263 {
264 next = loader_get_next_path(loc);
265 hive = DEFAULT_VK_REGISTRY_HIVE;
Piers Daniell524ec732015-11-05 16:58:26 -0700266 access_flags = KEY_QUERY_VALUE;
Tony Barbourea968902015-07-29 14:26:21 -0600267 rtn_value = RegOpenKeyEx(hive, loc, 0, access_flags, &key);
268 if (rtn_value != ERROR_SUCCESS) {
269 // We didn't find the key. Try the 32-bit hive (where we've seen the
270 // key end up on some people's systems):
271 access_flags |= KEY_WOW64_32KEY;
272 rtn_value = RegOpenKeyEx(hive, loc, 0, access_flags, &key);
273 if (rtn_value != ERROR_SUCCESS) {
274 // We still couldn't find the key, so give up:
275 loc = next;
276 continue;
Jon Ashburnffad94d2015-06-30 14:46:22 -0700277 }
Jon Ashburnffad94d2015-06-30 14:46:22 -0700278 }
Tony Barbourea968902015-07-29 14:26:21 -0600279
Jon Ashburne39a4f82015-08-28 13:38:21 -0600280 while ((rtn_value = RegEnumValue(key, idx++, name, &name_size, NULL, NULL, (LPBYTE) &value, &value_size)) == ERROR_SUCCESS) {
Tony Barbourea968902015-07-29 14:26:21 -0600281 if (value_size == sizeof(value) && value == 0) {
282 if (out == NULL) {
Courtney Goeltzenleuchter2961e1c2015-11-02 17:43:04 -0700283 out = loader_heap_alloc(inst, total_size, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Tony Barbourea968902015-07-29 14:26:21 -0600284 out[0] = '\0';
285 }
286 else if (strlen(out) + name_size + 1 > total_size) {
Courtney Goeltzenleuchter2961e1c2015-11-02 17:43:04 -0700287 out = loader_heap_realloc(inst, out, total_size, total_size * 2, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Tony Barbourea968902015-07-29 14:26:21 -0600288 total_size *= 2;
289 }
290 if (out == NULL) {
291 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory, failed loader_get_registry_files");
292 return NULL;
293 }
294 if (strlen(out) == 0)
295 snprintf(out, name_size + 1, "%s", name);
296 else
297 snprintf(out + strlen(out), name_size + 2, "%c%s", PATH_SEPERATOR, name);
298 }
299 name_size = 2048;
300 }
301 loc = next;
Jon Ashburnffad94d2015-06-30 14:46:22 -0700302 }
Tony Barbourea968902015-07-29 14:26:21 -0600303
Jon Ashburnffad94d2015-06-30 14:46:22 -0700304 return out;
305}
306
Ian Elliott4470a302015-02-17 10:33:47 -0700307#endif // WIN32
308
Jon Ashburnc7237a72015-08-03 09:08:46 -0600309/**
Daniel Dadap00b4aba2015-09-30 11:50:51 -0500310 * Combine path elements, separating each element with the platform-specific
311 * directory separator, and save the combined string to a destination buffer,
312 * not exceeding the given length. Path elements are given as variadic args,
313 * with a NULL element terminating the list.
314 *
315 * \returns the total length of the combined string, not including an ASCII
316 * NUL termination character. This length may exceed the available storage:
317 * in this case, the written string will be truncated to avoid a buffer
318 * overrun, and the return value will greater than or equal to the storage
319 * size. A NULL argument may be provided as the destination buffer in order
320 * to determine the required string length without actually writing a string.
321 */
322
323static int loader_platform_combine_path(char *dest, int len, ...)
324{
325 int required_len = 0;
326 va_list ap;
327 const char *component;
328
329 va_start(ap, len);
330
331 while((component = va_arg(ap, const char *))) {
332 if (required_len > 0) {
333 // This path element is not the first non-empty element; prepend
334 // a directory separator if space allows
335 if (dest && required_len + 1 < len) {
336 snprintf(dest + required_len, len - required_len, "%c",
337 DIRECTORY_SYMBOL);
338 }
339 required_len++;
340 }
341
342 if (dest && required_len < len) {
343 strncpy(dest + required_len, component, len - required_len);
344 }
345 required_len += strlen(component);
346 }
347
348 va_end(ap);
349
350 // strncpy(3) won't add a NUL terminating byte in the event of truncation.
351 if (dest && required_len >= len) {
352 dest[len - 1] = '\0';
353 }
354
355 return required_len;
356}
357
358
359/**
Jon Ashburnc7237a72015-08-03 09:08:46 -0600360 * Given string of three part form "maj.min.pat" convert to a vulkan version
361 * number.
362 */
363static uint32_t loader_make_version(const char *vers_str)
364{
Jon Ashburn432d2762015-09-18 12:53:16 -0600365 uint32_t vers = 0, major=0, minor=0, patch=0;
Jon Ashburnc7237a72015-08-03 09:08:46 -0600366 char *minor_str= NULL;
367 char *patch_str = NULL;
368 char *cstr;
369 char *str;
370
371 if (!vers_str)
372 return vers;
373 cstr = loader_stack_alloc(strlen(vers_str) + 1);
374 strcpy(cstr, vers_str);
375 while ((str = strchr(cstr, '.')) != NULL) {
376 if (minor_str == NULL) {
377 minor_str = str + 1;
378 *str = '\0';
379 major = atoi(cstr);
380 }
381 else if (patch_str == NULL) {
382 patch_str = str + 1;
383 *str = '\0';
384 minor = atoi(minor_str);
385 }
386 else {
387 return vers;
388 }
389 cstr = str + 1;
390 }
391 patch = atoi(patch_str);
392
393 return VK_MAKE_VERSION(major, minor, patch);
394
395}
396
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600397bool compare_vk_extension_properties(const VkExtensionProperties *op1, const VkExtensionProperties *op2)
398{
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800399 return strcmp(op1->extensionName, op2->extensionName) == 0 ? true : false;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600400}
401
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -0600402/**
Jon Ashburnbd6c4882015-07-02 12:59:25 -0600403 * Search the given ext_array for an extension
404 * matching the given vk_ext_prop
405 */
406bool has_vk_extension_property_array(
407 const VkExtensionProperties *vk_ext_prop,
408 const uint32_t count,
409 const VkExtensionProperties *ext_array)
410{
411 for (uint32_t i = 0; i < count; i++) {
412 if (compare_vk_extension_properties(vk_ext_prop, &ext_array[i]))
413 return true;
414 }
415 return false;
416}
417
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -0600418/**
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600419 * Search the given ext_list for an extension
420 * matching the given vk_ext_prop
421 */
422bool has_vk_extension_property(
423 const VkExtensionProperties *vk_ext_prop,
424 const struct loader_extension_list *ext_list)
425{
426 for (uint32_t i = 0; i < ext_list->count; i++) {
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600427 if (compare_vk_extension_properties(&ext_list->list[i], vk_ext_prop))
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600428 return true;
429 }
430 return false;
431}
432
Jon Ashburnb2ef1372015-07-16 17:19:31 -0600433static inline bool loader_is_layer_type_device(const enum layer_type type) {
434 if ((type & VK_LAYER_TYPE_DEVICE_EXPLICIT) ||
435 (type & VK_LAYER_TYPE_DEVICE_IMPLICIT))
436 return true;
437 return false;
438}
439
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600440/*
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -0600441 * Search the given layer list for a layer matching the given layer name
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600442 */
Jon Ashburne13ecc92015-08-03 17:19:30 -0600443static struct loader_layer_properties *loader_get_layer_property(
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600444 const char *name,
445 const struct loader_layer_list *layer_list)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600446{
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600447 for (uint32_t i = 0; i < layer_list->count; i++) {
448 const VkLayerProperties *item = &layer_list->list[i].info;
449 if (strcmp(name, item->layerName) == 0)
450 return &layer_list->list[i];
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600451 }
452 return NULL;
453}
454
Jon Ashburne13ecc92015-08-03 17:19:30 -0600455/**
456 * Get the next unused layer property in the list. Init the property to zero.
457 */
458static struct loader_layer_properties *loader_get_next_layer_property(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600459 const struct loader_instance *inst,
Jon Ashburne13ecc92015-08-03 17:19:30 -0600460 struct loader_layer_list *layer_list)
461{
462 if (layer_list->capacity == 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600463 layer_list->list = loader_heap_alloc(inst,
464 sizeof(struct loader_layer_properties) * 64,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800465 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburne13ecc92015-08-03 17:19:30 -0600466 if (layer_list->list == NULL) {
467 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't add any layer properties to list");
468 return NULL;
469 }
470 memset(layer_list->list, 0, sizeof(struct loader_layer_properties) * 64);
471 layer_list->capacity = sizeof(struct loader_layer_properties) * 64;
472 }
473
474 // ensure enough room to add an entry
475 if ((layer_list->count + 1) * sizeof (struct loader_layer_properties)
476 > layer_list->capacity) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600477 layer_list->list = loader_heap_realloc(inst, layer_list->list,
478 layer_list->capacity,
479 layer_list->capacity * 2,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800480 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburne13ecc92015-08-03 17:19:30 -0600481 if (layer_list->list == NULL) {
482 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
483 "realloc failed for layer list");
484 }
485 layer_list->capacity *= 2;
486 }
487
488 layer_list->count++;
489 return &(layer_list->list[layer_list->count - 1]);
490}
491
492/**
493 * Remove all layer properties entrys from the list
494 */
Jon Ashburne39a4f82015-08-28 13:38:21 -0600495void loader_delete_layer_properties(
496 const struct loader_instance *inst,
497 struct loader_layer_list *layer_list)
Jon Ashburne13ecc92015-08-03 17:19:30 -0600498{
Jon Ashburn39fbd4e2015-12-10 18:17:34 -0700499 uint32_t i, j;
500 struct loader_device_extension_list *dev_ext_list;
Jon Ashburnb82c1852015-08-11 14:49:54 -0600501 if (!layer_list)
502 return;
503
Jon Ashburne13ecc92015-08-03 17:19:30 -0600504 for (i = 0; i < layer_list->count; i++) {
Jon Ashburn6e6a2162015-12-10 08:51:10 -0700505 loader_destroy_generic_list(inst, (struct loader_generic_list *)
506 &layer_list->list[i].instance_extension_list);
Jon Ashburn39fbd4e2015-12-10 18:17:34 -0700507 dev_ext_list = &layer_list->list[i].device_extension_list;
508 if (dev_ext_list->capacity > 0 && dev_ext_list->list->entrypoint_count > 0) {
509 for (j= 0; j < dev_ext_list->list->entrypoint_count; j++) {
510 loader_heap_free(inst, dev_ext_list->list->entrypoints[j]);
511 }
512 loader_heap_free(inst, dev_ext_list->list->entrypoints);
513 }
Jon Ashburn6e6a2162015-12-10 08:51:10 -0700514 loader_destroy_generic_list(inst, (struct loader_generic_list *)
Jon Ashburn39fbd4e2015-12-10 18:17:34 -0700515 dev_ext_list);
Jon Ashburne13ecc92015-08-03 17:19:30 -0600516 }
517 layer_list->count = 0;
518
Jon Ashburnb82c1852015-08-11 14:49:54 -0600519 if (layer_list->capacity > 0) {
520 layer_list->capacity = 0;
Jon Ashburne39a4f82015-08-28 13:38:21 -0600521 loader_heap_free(inst, layer_list->list);
Jon Ashburnb82c1852015-08-11 14:49:54 -0600522 }
Jon Ashburne13ecc92015-08-03 17:19:30 -0600523
524}
525
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600526static void loader_add_global_extensions(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600527 const struct loader_instance *inst,
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -0600528 const PFN_vkEnumerateInstanceExtensionProperties fp_get_props,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600529 const char *lib_name,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600530 struct loader_extension_list *ext_list)
531{
532 uint32_t i, count;
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600533 VkExtensionProperties *ext_props;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600534 VkResult res;
535
Courtney Goeltzenleuchter5c6cf472015-07-06 22:28:18 -0600536 if (!fp_get_props) {
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -0600537 /* No EnumerateInstanceExtensionProperties defined */
Courtney Goeltzenleuchter5c6cf472015-07-06 22:28:18 -0600538 return;
539 }
540
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600541 res = fp_get_props(NULL, &count, NULL);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600542 if (res != VK_SUCCESS) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600543 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Error getting global extension count from %s", lib_name);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600544 return;
545 }
Jon Ashburn953bb3c2015-06-10 16:11:42 -0600546
Courtney Goeltzenleuchter5c6cf472015-07-06 22:28:18 -0600547 if (count == 0) {
548 /* No ExtensionProperties to report */
549 return;
550 }
551
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600552 ext_props = loader_stack_alloc(count * sizeof(VkExtensionProperties));
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600553
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600554 res = fp_get_props(NULL, &count, ext_props);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600555 if (res != VK_SUCCESS) {
556 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Error getting global extensions from %s", lib_name);
557 return;
558 }
Tony Barbour59a47322015-06-24 16:06:58 -0600559
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600560 for (i = 0; i < count; i++) {
Courtney Goeltzenleuchter53043732015-07-12 13:20:05 -0600561 char spec_version[64];
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600562
563 snprintf(spec_version, sizeof(spec_version), "%d.%d.%d",
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600564 VK_MAJOR(ext_props[i].specVersion),
565 VK_MINOR(ext_props[i].specVersion),
566 VK_PATCH(ext_props[i].specVersion));
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600567 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Courtney Goeltzenleuchter53043732015-07-12 13:20:05 -0600568 "Global Extension: %s (%s) version %s",
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800569 ext_props[i].extensionName, lib_name, spec_version);
Jon Ashburne39a4f82015-08-28 13:38:21 -0600570 loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600571 }
572
573 return;
574}
575
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700576/*
577 * Initialize ext_list with the physical device extensions.
578 * The extension properties are passed as inputs in count and ext_props.
579 */
580static VkResult loader_init_physical_device_extensions(
581 const struct loader_instance *inst,
582 struct loader_physical_device *phys_dev,
583 uint32_t count,
584 VkExtensionProperties *ext_props,
585 struct loader_extension_list *ext_list)
586{
587 VkResult res;
588 uint32_t i;
589
Jon Ashburn6e6a2162015-12-10 08:51:10 -0700590 if (!loader_init_generic_list(inst, (struct loader_generic_list *) ext_list,
591 sizeof(VkExtensionProperties))) {
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700592 return VK_ERROR_OUT_OF_HOST_MEMORY;
593 }
594
595 for (i = 0; i < count; i++) {
596 char spec_version[64];
597
598 snprintf(spec_version, sizeof (spec_version), "%d.%d.%d",
599 VK_MAJOR(ext_props[i].specVersion),
600 VK_MINOR(ext_props[i].specVersion),
601 VK_PATCH(ext_props[i].specVersion));
602 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
603 "PhysicalDevice Extension: %s (%s) version %s",
604 ext_props[i].extensionName, phys_dev->this_icd->this_icd_lib->lib_name, spec_version);
605 res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
606 if (res != VK_SUCCESS)
607 return res;
608 }
609
610 return VK_SUCCESS;
611}
612
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700613static VkResult loader_add_physical_device_extensions(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600614 const struct loader_instance *inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600615 VkPhysicalDevice physical_device,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600616 const char *lib_name,
617 struct loader_extension_list *ext_list)
618{
619 uint32_t i, count;
620 VkResult res;
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600621 VkExtensionProperties *ext_props;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600622
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700623 res = loader_EnumerateDeviceExtensionProperties(physical_device, NULL, &count, NULL);
624 if (res == VK_SUCCESS && count > 0) {
625 ext_props = loader_stack_alloc(count * sizeof (VkExtensionProperties));
626 if (!ext_props)
627 return VK_ERROR_OUT_OF_HOST_MEMORY;
628 res = loader_EnumerateDeviceExtensionProperties(physical_device, NULL, &count, ext_props);
629 if (res != VK_SUCCESS)
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700630 return res;
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700631 for (i = 0; i < count; i++) {
632 char spec_version[64];
633
634 snprintf(spec_version, sizeof (spec_version), "%d.%d.%d",
635 VK_MAJOR(ext_props[i].specVersion),
636 VK_MINOR(ext_props[i].specVersion),
637 VK_PATCH(ext_props[i].specVersion));
638 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
639 "PhysicalDevice Extension: %s (%s) version %s",
640 ext_props[i].extensionName, lib_name, spec_version);
641 res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]);
642 if (res != VK_SUCCESS)
643 return res;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600644 }
Jon Ashburn00eb6c02015-11-02 17:40:01 -0700645 } else {
646 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Error getting physical device extension info count from library %s", lib_name);
647 return res;
648 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600649
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700650 return VK_SUCCESS;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600651}
652
Jon Ashburn6e6a2162015-12-10 08:51:10 -0700653static bool loader_init_generic_list(const struct loader_instance *inst,
654 struct loader_generic_list *list_info,
655 size_t element_size)
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600656{
Jon Ashburn6e6a2162015-12-10 08:51:10 -0700657 list_info->capacity = 32 * element_size;
658 list_info->list = loader_heap_alloc(inst, list_info->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
659 if (list_info->list == NULL) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600660 return false;
661 }
Jon Ashburn6e6a2162015-12-10 08:51:10 -0700662 memset(list_info->list, 0, list_info->capacity);
663 list_info->count = 0;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600664 return true;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600665}
666
Jon Ashburn6e6a2162015-12-10 08:51:10 -0700667void loader_destroy_generic_list(const struct loader_instance *inst,
668 struct loader_generic_list *list)
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600669{
Jon Ashburn6e6a2162015-12-10 08:51:10 -0700670 loader_heap_free(inst, list->list);
671 list->count = 0;
672 list->capacity = 0;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600673}
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600674
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600675/*
676 * Append non-duplicate extension properties defined in props
677 * to the given ext_list.
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700678 * Return
679 * Vk_SUCCESS on success
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600680 */
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700681VkResult loader_add_to_ext_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600682 const struct loader_instance *inst,
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600683 struct loader_extension_list *ext_list,
684 uint32_t prop_list_count,
685 const VkExtensionProperties *props)
686{
687 uint32_t i;
688 const VkExtensionProperties *cur_ext;
689
690 if (ext_list->list == NULL || ext_list->capacity == 0) {
Jon Ashburn6e6a2162015-12-10 08:51:10 -0700691 loader_init_generic_list(inst, (struct loader_generic_list *) ext_list,
692 sizeof(VkExtensionProperties));
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600693 }
694
695 if (ext_list->list == NULL)
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700696 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600697
698 for (i = 0; i < prop_list_count; i++) {
699 cur_ext = &props[i];
700
701 // look for duplicates
702 if (has_vk_extension_property(cur_ext, ext_list)) {
703 continue;
704 }
705
706 // add to list at end
707 // check for enough capacity
708 if (ext_list->count * sizeof(VkExtensionProperties)
709 >= ext_list->capacity) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600710
711 ext_list->list = loader_heap_realloc(inst,
712 ext_list->list,
713 ext_list->capacity,
714 ext_list->capacity * 2,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800715 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700716
717 if (ext_list->list == NULL)
718 return VK_ERROR_OUT_OF_HOST_MEMORY;
719
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600720 // double capacity
721 ext_list->capacity *= 2;
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600722 }
723
724 memcpy(&ext_list->list[ext_list->count], cur_ext, sizeof(VkExtensionProperties));
725 ext_list->count++;
726 }
Jon Ashburn24cd4be2015-11-01 14:04:06 -0700727 return VK_SUCCESS;
Jon Ashburn5c042ea2015-08-04 11:14:18 -0600728}
729
Jon Ashburn39fbd4e2015-12-10 18:17:34 -0700730/*
731 * Append one extension property defined in props with entrypoints
732 * defined in entrys to the given ext_list.
733 * Return
734 * Vk_SUCCESS on success
735 */
736VkResult loader_add_to_dev_ext_list(
737 const struct loader_instance *inst,
738 struct loader_device_extension_list *ext_list,
739 const VkExtensionProperties *props,
740 uint32_t entry_count,
741 char **entrys)
742{
743 uint32_t idx;
744 if (ext_list->list == NULL || ext_list->capacity == 0) {
745 loader_init_generic_list(inst, (struct loader_generic_list *) ext_list,
746 sizeof(struct loader_dev_ext_props));
747 }
748
749 if (ext_list->list == NULL)
750 return VK_ERROR_OUT_OF_HOST_MEMORY;
751
752 idx =ext_list->count;
753 // add to list at end
754 // check for enough capacity
755 if (idx * sizeof (struct loader_dev_ext_props)
756 >= ext_list->capacity) {
757
758 ext_list->list = loader_heap_realloc(inst,
759 ext_list->list,
760 ext_list->capacity,
761 ext_list->capacity * 2,
762 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
763
764 if (ext_list->list == NULL)
765 return VK_ERROR_OUT_OF_HOST_MEMORY;
766
767 // double capacity
768 ext_list->capacity *= 2;
769 }
770
771 memcpy(&ext_list->list[idx].props, props, sizeof(struct loader_dev_ext_props));
772 ext_list->list[idx].entrypoint_count = entry_count;
773 ext_list->list[idx].entrypoints = loader_heap_alloc(inst,
774 sizeof(char *) * entry_count,
775 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
776 if (ext_list->list[idx].entrypoints == NULL)
777 return VK_ERROR_OUT_OF_HOST_MEMORY;
778 for (uint32_t i = 0; i < entry_count; i++) {
779 ext_list->list[idx].entrypoints[i] = loader_heap_alloc(inst,
780 strlen(entrys[i]) + 1,
781 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
782 if (ext_list->list[idx].entrypoints[i] == NULL)
783 return VK_ERROR_OUT_OF_HOST_MEMORY;
784 strcpy(ext_list->list[idx].entrypoints[i], entrys[i]);
785 }
786 ext_list->count++;
787
788 return VK_SUCCESS;
789}
790
Jon Ashburnbd6c4882015-07-02 12:59:25 -0600791/**
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600792 * Search the given search_list for any layers in the props list.
793 * Add these to the output layer_list. Don't add duplicates to the output layer_list.
Jon Ashburnbd6c4882015-07-02 12:59:25 -0600794 */
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -0600795static VkResult loader_add_layer_names_to_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600796 const struct loader_instance *inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600797 struct loader_layer_list *output_list,
798 uint32_t name_count,
799 const char * const *names,
800 const struct loader_layer_list *search_list)
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600801{
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600802 struct loader_layer_properties *layer_prop;
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -0600803 VkResult err = VK_SUCCESS;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600804
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600805 for (uint32_t i = 0; i < name_count; i++) {
806 const char *search_target = names[i];
Jon Ashburne13ecc92015-08-03 17:19:30 -0600807 layer_prop = loader_get_layer_property(search_target, search_list);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600808 if (!layer_prop) {
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -0600809 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Unable to find layer %s", search_target);
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -0600810 err = VK_ERROR_LAYER_NOT_PRESENT;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600811 continue;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600812 }
813
Jon Ashburne39a4f82015-08-28 13:38:21 -0600814 loader_add_to_layer_list(inst, output_list, 1, layer_prop);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600815 }
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -0600816
817 return err;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600818}
819
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600820
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600821/*
822 * Manage lists of VkLayerProperties
823 */
Jon Ashburne39a4f82015-08-28 13:38:21 -0600824static bool loader_init_layer_list(const struct loader_instance *inst,
825 struct loader_layer_list *list)
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600826{
827 list->capacity = 32 * sizeof(struct loader_layer_properties);
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800828 list->list = loader_heap_alloc(inst, list->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600829 if (list->list == NULL) {
830 return false;
831 }
832 memset(list->list, 0, list->capacity);
833 list->count = 0;
834 return true;
835}
836
Jon Ashburne39a4f82015-08-28 13:38:21 -0600837void loader_destroy_layer_list(const struct loader_instance *inst,
838 struct loader_layer_list *layer_list)
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600839{
Jon Ashburne39a4f82015-08-28 13:38:21 -0600840 loader_heap_free(inst, layer_list->list);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600841 layer_list->count = 0;
842 layer_list->capacity = 0;
843}
844
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600845/*
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600846 * Manage list of layer libraries (loader_lib_info)
847 */
Jon Ashburne39a4f82015-08-28 13:38:21 -0600848static bool loader_init_layer_library_list(const struct loader_instance *inst,
849 struct loader_layer_library_list *list)
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600850{
851 list->capacity = 32 * sizeof(struct loader_lib_info);
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800852 list->list = loader_heap_alloc(inst, list->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600853 if (list->list == NULL) {
854 return false;
855 }
856 memset(list->list, 0, list->capacity);
857 list->count = 0;
858 return true;
859}
860
Jon Ashburne39a4f82015-08-28 13:38:21 -0600861void loader_destroy_layer_library_list(const struct loader_instance *inst,
862 struct loader_layer_library_list *list)
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600863{
864 for (uint32_t i = 0; i < list->count; i++) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600865 loader_heap_free(inst, list->list[i].lib_name);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600866 }
Jon Ashburne39a4f82015-08-28 13:38:21 -0600867 loader_heap_free(inst, list->list);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600868 list->count = 0;
869 list->capacity = 0;
870}
871
872void loader_add_to_layer_library_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600873 const struct loader_instance *inst,
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600874 struct loader_layer_library_list *list,
875 uint32_t item_count,
876 const struct loader_lib_info *new_items)
877{
878 uint32_t i;
879 struct loader_lib_info *item;
880
881 if (list->list == NULL || list->capacity == 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600882 loader_init_layer_library_list(inst, list);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600883 }
884
885 if (list->list == NULL)
886 return;
887
888 for (i = 0; i < item_count; i++) {
889 item = (struct loader_lib_info *) &new_items[i];
890
891 // look for duplicates
892 for (uint32_t j = 0; j < list->count; j++) {
893 if (strcmp(list->list[i].lib_name, new_items->lib_name) == 0) {
894 continue;
895 }
896 }
897
898 // add to list at end
899 // check for enough capacity
900 if (list->count * sizeof(struct loader_lib_info)
901 >= list->capacity) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600902
903 list->list = loader_heap_realloc(inst,
904 list->list,
905 list->capacity,
906 list->capacity * 2,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800907 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600908 // double capacity
909 list->capacity *= 2;
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600910 }
911
912 memcpy(&list->list[list->count], item, sizeof(struct loader_lib_info));
913 list->count++;
914 }
915}
916
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600917
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600918/*
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600919 * Search the given layer list for a list
920 * matching the given VkLayerProperties
921 */
922bool has_vk_layer_property(
923 const VkLayerProperties *vk_layer_prop,
924 const struct loader_layer_list *list)
925{
926 for (uint32_t i = 0; i < list->count; i++) {
927 if (strcmp(vk_layer_prop->layerName, list->list[i].info.layerName) == 0)
928 return true;
929 }
930 return false;
931}
932
933/*
934 * Search the given layer list for a layer
935 * matching the given name
936 */
937bool has_layer_name(
938 const char *name,
939 const struct loader_layer_list *list)
940{
941 for (uint32_t i = 0; i < list->count; i++) {
942 if (strcmp(name, list->list[i].info.layerName) == 0)
943 return true;
944 }
945 return false;
946}
947
948/*
949 * Append non-duplicate layer properties defined in prop_list
950 * to the given layer_info list
951 */
952void loader_add_to_layer_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -0600953 const struct loader_instance *inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600954 struct loader_layer_list *list,
955 uint32_t prop_list_count,
956 const struct loader_layer_properties *props)
957{
958 uint32_t i;
959 struct loader_layer_properties *layer;
960
961 if (list->list == NULL || list->capacity == 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600962 loader_init_layer_list(inst, list);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600963 }
964
965 if (list->list == NULL)
966 return;
967
968 for (i = 0; i < prop_list_count; i++) {
969 layer = (struct loader_layer_properties *) &props[i];
970
971 // look for duplicates
972 if (has_vk_layer_property(&layer->info, list)) {
973 continue;
974 }
975
976 // add to list at end
977 // check for enough capacity
978 if (list->count * sizeof(struct loader_layer_properties)
979 >= list->capacity) {
Jon Ashburne39a4f82015-08-28 13:38:21 -0600980
981 list->list = loader_heap_realloc(inst,
982 list->list,
983 list->capacity,
984 list->capacity * 2,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800985 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600986 // double capacity
987 list->capacity *= 2;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600988 }
989
990 memcpy(&list->list[list->count], layer, sizeof(struct loader_layer_properties));
991 list->count++;
992 }
993}
994
Jon Ashburnbd332cc2015-07-07 10:27:45 -0600995/**
996 * Search the search_list for any layer with a name
997 * that matches the given name and a type that matches the given type
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600998 * Add all matching layers to the found_list
Jon Ashburnbd332cc2015-07-07 10:27:45 -0600999 * Do not add if found loader_layer_properties is already
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06001000 * on the found_list.
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001001 */
Jon Ashburnbd6c4882015-07-02 12:59:25 -06001002static void loader_find_layer_name_add_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -06001003 const struct loader_instance *inst,
Jon Ashburnbd6c4882015-07-02 12:59:25 -06001004 const char *name,
Jon Ashburnbd332cc2015-07-07 10:27:45 -06001005 const enum layer_type type,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06001006 const struct loader_layer_list *search_list,
1007 struct loader_layer_list *found_list)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001008{
Jon Ashburn56151d62015-10-05 09:03:21 -06001009 bool found = false;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001010 for (uint32_t i = 0; i < search_list->count; i++) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06001011 struct loader_layer_properties *layer_prop = &search_list->list[i];
Jon Ashburnbd332cc2015-07-07 10:27:45 -06001012 if (0 == strcmp(layer_prop->info.layerName, name) &&
1013 (layer_prop->type & type)) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06001014 /* Found a layer with the same name, add to found_list */
Jon Ashburne39a4f82015-08-28 13:38:21 -06001015 loader_add_to_layer_list(inst, found_list, 1, layer_prop);
Jon Ashburn56151d62015-10-05 09:03:21 -06001016 found = true;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001017 }
1018 }
Jon Ashburn56151d62015-10-05 09:03:21 -06001019 if (!found) {
1020 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Warning, couldn't find layer name %s to activate", name);
1021 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001022}
1023
Jon Ashburn5c042ea2015-08-04 11:14:18 -06001024static VkExtensionProperties *get_extension_property(
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06001025 const char *name,
1026 const struct loader_extension_list *list)
Jon Ashburnfc2e38c2015-04-14 09:15:32 -06001027{
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06001028 for (uint32_t i = 0; i < list->count; i++) {
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001029 if (strcmp(name, list->list[i].extensionName) == 0)
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06001030 return &list->list[i];
Jon Ashburnfc2e38c2015-04-14 09:15:32 -06001031 }
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06001032 return NULL;
Jon Ashburnfc2e38c2015-04-14 09:15:32 -06001033}
1034
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001035static VkExtensionProperties *get_dev_extension_property(
1036 const char *name,
1037 const struct loader_device_extension_list *list)
1038{
1039 for (uint32_t i = 0; i < list->count; i++) {
1040 if (strcmp(name, list->list[i].props.extensionName) == 0)
1041 return &list->list[i].props;
1042 }
1043 return NULL;
1044}
1045
Jon Ashburnbd6c4882015-07-02 12:59:25 -06001046/*
Jon Ashburn232e3af2015-11-30 17:21:25 -07001047 * For global extensions implemented within the loader (i.e. DEBUG_REPORT
Jon Ashburnbd6c4882015-07-02 12:59:25 -06001048 * the extension must provide two entry points for the loader to use:
1049 * - "trampoline" entry point - this is the address returned by GetProcAddr
1050 * and will always do what's necessary to support a global call.
1051 * - "terminator" function - this function will be put at the end of the
Jon Ashburn232e3af2015-11-30 17:21:25 -07001052 * instance chain and will contain the necessary logic to call / process
Jon Ashburnbd6c4882015-07-02 12:59:25 -06001053 * the extension for the appropriate ICDs that are available.
1054 * There is no generic mechanism for including these functions, the references
1055 * must be placed into the appropriate loader entry points.
1056 * GetInstanceProcAddr: call extension GetInstanceProcAddr to check for GetProcAddr requests
1057 * loader_coalesce_extensions(void) - add extension records to the list of global
1058 * extension available to the app.
1059 * instance_disp - add function pointer for terminator function to this array.
1060 * The extension itself should be in a separate file that will be
1061 * linked directly with the loader.
1062 */
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06001063
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001064void loader_get_icd_loader_instance_extensions(
Jon Ashburne39a4f82015-08-28 13:38:21 -06001065 const struct loader_instance *inst,
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001066 struct loader_icd_libs *icd_libs,
1067 struct loader_extension_list *inst_exts)
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001068{
Jon Ashburn5c6a46f2015-08-14 14:49:22 -06001069 struct loader_extension_list icd_exts;
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06001070 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, "Build ICD instance extension list");
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001071 // traverse scanned icd list adding non-duplicate extensions to the list
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001072 for (uint32_t i = 0; i < icd_libs->count; i++) {
Jon Ashburn6e6a2162015-12-10 08:51:10 -07001073 loader_init_generic_list(inst, (struct loader_generic_list *) &icd_exts,
1074 sizeof(VkExtensionProperties));
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06001075 loader_add_global_extensions(inst, icd_libs->list[i].EnumerateInstanceExtensionProperties,
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001076 icd_libs->list[i].lib_name,
Jon Ashburn5c6a46f2015-08-14 14:49:22 -06001077 &icd_exts);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001078 loader_add_to_ext_list(inst, inst_exts,
Jon Ashburn5c6a46f2015-08-14 14:49:22 -06001079 icd_exts.count,
1080 icd_exts.list);
Jon Ashburn6e6a2162015-12-10 08:51:10 -07001081 loader_destroy_generic_list(inst, (struct loader_generic_list *) &icd_exts);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001082 };
1083
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001084 // Traverse loader's extensions, adding non-duplicate extensions to the list
Ian Elliott954fa342015-10-30 15:28:23 -06001085 wsi_add_instance_extensions(inst, inst_exts);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001086 debug_report_add_instance_extensions(inst, inst_exts);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001087}
1088
Jon Ashburn46674bf2015-12-11 09:41:34 -07001089struct loader_physical_device *loader_get_physical_device(const VkPhysicalDevice physdev)
1090{
1091 uint32_t i;
1092 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
1093 for (i = 0; i < inst->total_gpu_count; i++) {
1094 //TODO this aliases physDevices within instances, need for this
1095 // function to go away
1096 if (inst->phys_devs[i].disp == loader_get_instance_dispatch(physdev)) {
1097 return &inst->phys_devs[i];
1098 }
1099 }
1100 }
1101 return NULL;
1102}
1103
Jon Ashburne39a4f82015-08-28 13:38:21 -06001104struct loader_icd *loader_get_icd_and_device(const VkDevice device,
1105 struct loader_device **found_dev)
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001106{
1107 *found_dev = NULL;
1108 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
1109 for (struct loader_icd *icd = inst->icds; icd; icd = icd->next) {
1110 for (struct loader_device *dev = icd->logical_device_list; dev; dev = dev->next)
Jon Ashburne0e64572015-09-30 12:56:42 -06001111 /* Value comparison of device prevents object wrapping by layers */
1112 if (loader_get_dispatch(dev->device) == loader_get_dispatch(device)) {
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001113 *found_dev = dev;
1114 return icd;
1115 }
1116 }
1117 }
1118 return NULL;
1119}
1120
Jon Ashburne39a4f82015-08-28 13:38:21 -06001121static void loader_destroy_logical_device(const struct loader_instance *inst,
1122 struct loader_device *dev)
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001123{
Jon Ashburne39a4f82015-08-28 13:38:21 -06001124 loader_heap_free(inst, dev->app_extension_props);
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001125 if (dev->activated_layer_list.count)
Jon Ashburne39a4f82015-08-28 13:38:21 -06001126 loader_destroy_layer_list(inst, &dev->activated_layer_list);
1127 loader_heap_free(inst, dev);
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001128}
1129
Jon Ashburne39a4f82015-08-28 13:38:21 -06001130static struct loader_device *loader_add_logical_device(
1131 const struct loader_instance *inst,
1132 const VkDevice dev,
1133 struct loader_device **device_list)
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001134{
1135 struct loader_device *new_dev;
1136
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001137 new_dev = loader_heap_alloc(inst, sizeof(struct loader_device), VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001138 if (!new_dev) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06001139 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc struct laoder-device");
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001140 return NULL;
1141 }
1142
1143 memset(new_dev, 0, sizeof(struct loader_device));
1144
1145 new_dev->next = *device_list;
1146 new_dev->device = dev;
1147 *device_list = new_dev;
1148 return new_dev;
1149}
1150
Jon Ashburne39a4f82015-08-28 13:38:21 -06001151void loader_remove_logical_device(
1152 const struct loader_instance *inst,
Jon Ashburn781a7ae2015-11-19 15:43:26 -07001153 struct loader_icd *icd,
1154 struct loader_device *found_dev)
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001155{
Jon Ashburn781a7ae2015-11-19 15:43:26 -07001156 struct loader_device *dev, *prev_dev;
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001157
1158 if (!icd || !found_dev)
1159 return;
1160
1161 prev_dev = NULL;
1162 dev = icd->logical_device_list;
1163 while (dev && dev != found_dev) {
1164 prev_dev = dev;
1165 dev = dev->next;
1166 }
1167
1168 if (prev_dev)
1169 prev_dev->next = found_dev->next;
1170 else
1171 icd->logical_device_list = found_dev->next;
Jon Ashburne39a4f82015-08-28 13:38:21 -06001172 loader_destroy_logical_device(inst, found_dev);
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001173}
1174
1175
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001176static void loader_icd_destroy(
1177 struct loader_instance *ptr_inst,
1178 struct loader_icd *icd)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001179{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001180 ptr_inst->total_icd_count--;
Courtney Goeltzenleuchter1f157ac2015-06-14 19:57:15 -06001181 for (struct loader_device *dev = icd->logical_device_list; dev; ) {
1182 struct loader_device *next_dev = dev->next;
Jon Ashburne39a4f82015-08-28 13:38:21 -06001183 loader_destroy_logical_device(ptr_inst, dev);
Courtney Goeltzenleuchter1f157ac2015-06-14 19:57:15 -06001184 dev = next_dev;
1185 }
Jon Ashburndc6fcad2015-06-10 10:06:06 -06001186
Jon Ashburne39a4f82015-08-28 13:38:21 -06001187 loader_heap_free(ptr_inst, icd);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001188}
1189
Jon Ashburne39a4f82015-08-28 13:38:21 -06001190static struct loader_icd * loader_icd_create(const struct loader_instance *inst)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001191{
1192 struct loader_icd *icd;
1193
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001194 icd = loader_heap_alloc(inst, sizeof(*icd), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001195 if (!icd)
1196 return NULL;
1197
Courtney Goeltzenleuchter55001bb2014-10-28 10:29:27 -06001198 memset(icd, 0, sizeof(*icd));
1199
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001200 return icd;
1201}
1202
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001203static struct loader_icd *loader_icd_add(
1204 struct loader_instance *ptr_inst,
Jon Ashburn3d002332015-08-20 16:35:30 -06001205 const struct loader_scanned_icds *icd_lib)
Chia-I Wu13a61a52014-08-04 11:18:20 +08001206{
1207 struct loader_icd *icd;
1208
Jon Ashburne39a4f82015-08-28 13:38:21 -06001209 icd = loader_icd_create(ptr_inst);
Chia-I Wu13a61a52014-08-04 11:18:20 +08001210 if (!icd)
1211 return NULL;
1212
Jon Ashburn3d002332015-08-20 16:35:30 -06001213 icd->this_icd_lib = icd_lib;
1214 icd->this_instance = ptr_inst;
1215
Chia-I Wu13a61a52014-08-04 11:18:20 +08001216 /* prepend to the list */
Jon Ashburn46888392015-01-29 15:45:51 -07001217 icd->next = ptr_inst->icds;
1218 ptr_inst->icds = icd;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001219 ptr_inst->total_icd_count++;
Chia-I Wu13a61a52014-08-04 11:18:20 +08001220
1221 return icd;
1222}
1223
Jon Ashburne39a4f82015-08-28 13:38:21 -06001224void loader_scanned_icd_clear(
1225 const struct loader_instance *inst,
1226 struct loader_icd_libs *icd_libs)
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001227{
1228 if (icd_libs->capacity == 0)
1229 return;
1230 for (uint32_t i = 0; i < icd_libs->count; i++) {
1231 loader_platform_close_library(icd_libs->list[i].handle);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001232 loader_heap_free(inst, icd_libs->list[i].lib_name);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001233 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06001234 loader_heap_free(inst, icd_libs->list);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001235 icd_libs->capacity = 0;
1236 icd_libs->count = 0;
1237 icd_libs->list = NULL;
1238}
1239
Jon Ashburne39a4f82015-08-28 13:38:21 -06001240static void loader_scanned_icd_init(const struct loader_instance *inst,
1241 struct loader_icd_libs *icd_libs)
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001242{
Jon Ashburne39a4f82015-08-28 13:38:21 -06001243 loader_scanned_icd_clear(inst, icd_libs);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001244 icd_libs->capacity = 8 * sizeof(struct loader_scanned_icds);
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001245 icd_libs->list = loader_heap_alloc(inst, icd_libs->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001246
1247}
1248
1249static void loader_scanned_icd_add(
Jon Ashburne39a4f82015-08-28 13:38:21 -06001250 const struct loader_instance *inst,
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001251 struct loader_icd_libs *icd_libs,
Jon Ashburn005617f2015-11-17 17:35:40 -07001252 const char *filename,
1253 uint32_t api_version)
Jon Ashburn46d1f582015-01-28 11:01:35 -07001254{
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001255 loader_platform_dl_handle handle;
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06001256 PFN_vkCreateInstance fp_create_inst;
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06001257 PFN_vkEnumerateInstanceExtensionProperties fp_get_global_ext_props;
Jon Ashburnc624c882015-07-16 10:17:29 -06001258 PFN_vkGetInstanceProcAddr fp_get_proc_addr;
Jon Ashburn46d1f582015-01-28 11:01:35 -07001259 struct loader_scanned_icds *new_node;
1260
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001261 /* TODO implement ref counting of libraries, for now this function leaves
1262 libraries open and the scanned_icd_clear closes them */
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001263 // Used to call: dlopen(filename, RTLD_LAZY);
1264 handle = loader_platform_open_library(filename);
Jon Ashburn46d1f582015-01-28 11:01:35 -07001265 if (!handle) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001266 loader_log(VK_DBG_REPORT_WARN_BIT, 0, loader_platform_open_library_error(filename));
Jon Ashburn46d1f582015-01-28 11:01:35 -07001267 return;
1268 }
1269
Jon Ashburnc624c882015-07-16 10:17:29 -06001270#define LOOKUP_LD(func_ptr, func) do { \
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -06001271 func_ptr = (PFN_vk ##func) loader_platform_get_proc_address(handle, "vk" #func); \
Jon Ashburn46d1f582015-01-28 11:01:35 -07001272 if (!func_ptr) { \
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001273 loader_log(VK_DBG_REPORT_WARN_BIT, 0, loader_platform_get_proc_address_error("vk" #func)); \
Jon Ashburn46d1f582015-01-28 11:01:35 -07001274 return; \
1275 } \
1276} while (0)
1277
Jon Ashburnc624c882015-07-16 10:17:29 -06001278 LOOKUP_LD(fp_get_proc_addr, GetInstanceProcAddr);
1279 LOOKUP_LD(fp_create_inst, CreateInstance);
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06001280 LOOKUP_LD(fp_get_global_ext_props, EnumerateInstanceExtensionProperties);
Jon Ashburnc624c882015-07-16 10:17:29 -06001281
1282#undef LOOKUP_LD
Jon Ashburn46d1f582015-01-28 11:01:35 -07001283
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001284 // check for enough capacity
1285 if ((icd_libs->count * sizeof(struct loader_scanned_icds)) >= icd_libs->capacity) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06001286
1287 icd_libs->list = loader_heap_realloc(inst,
1288 icd_libs->list,
1289 icd_libs->capacity,
1290 icd_libs->capacity * 2,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001291 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001292 // double capacity
1293 icd_libs->capacity *= 2;
Jon Ashburn46d1f582015-01-28 11:01:35 -07001294 }
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001295 new_node = &(icd_libs->list[icd_libs->count]);
Jon Ashburn46d1f582015-01-28 11:01:35 -07001296
1297 new_node->handle = handle;
Jon Ashburn005617f2015-11-17 17:35:40 -07001298 new_node->api_version = api_version;
Jon Ashburnc624c882015-07-16 10:17:29 -06001299 new_node->GetInstanceProcAddr = fp_get_proc_addr;
Jon Ashburn46888392015-01-29 15:45:51 -07001300 new_node->CreateInstance = fp_create_inst;
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06001301 new_node->EnumerateInstanceExtensionProperties = fp_get_global_ext_props;
Jon Ashburn46d1f582015-01-28 11:01:35 -07001302
Jon Ashburne39a4f82015-08-28 13:38:21 -06001303 new_node->lib_name = (char *) loader_heap_alloc(inst,
1304 strlen(filename) + 1,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001305 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001306 if (!new_node->lib_name) {
1307 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Out of memory can't add icd");
1308 return;
1309 }
1310 strcpy(new_node->lib_name, filename);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001311 icd_libs->count++;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001312}
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001313
Jon Ashburnc624c882015-07-16 10:17:29 -06001314static bool loader_icd_init_entrys(struct loader_icd *icd,
1315 VkInstance inst,
1316 const PFN_vkGetInstanceProcAddr fp_gipa)
Jon Ashburn3da71f22015-05-14 12:43:38 -06001317{
1318 /* initialize entrypoint function pointers */
1319
Jon Ashburnc624c882015-07-16 10:17:29 -06001320 #define LOOKUP_GIPA(func, required) do { \
1321 icd->func = (PFN_vk ##func) fp_gipa(inst, "vk" #func); \
1322 if (!icd->func && required) { \
1323 loader_log(VK_DBG_REPORT_WARN_BIT, 0, \
1324 loader_platform_get_proc_address_error("vk" #func)); \
1325 return false; \
1326 } \
Jon Ashburn3da71f22015-05-14 12:43:38 -06001327 } while (0)
1328
Jon Ashburnc624c882015-07-16 10:17:29 -06001329 LOOKUP_GIPA(GetDeviceProcAddr, true);
1330 LOOKUP_GIPA(DestroyInstance, true);
1331 LOOKUP_GIPA(EnumeratePhysicalDevices, true);
1332 LOOKUP_GIPA(GetPhysicalDeviceFeatures, true);
1333 LOOKUP_GIPA(GetPhysicalDeviceFormatProperties, true);
Jon Ashburn754864f2015-07-23 18:49:07 -06001334 LOOKUP_GIPA(GetPhysicalDeviceImageFormatProperties, true);
Jon Ashburnc624c882015-07-16 10:17:29 -06001335 LOOKUP_GIPA(CreateDevice, true);
1336 LOOKUP_GIPA(GetPhysicalDeviceProperties, true);
1337 LOOKUP_GIPA(GetPhysicalDeviceMemoryProperties, true);
Cody Northropd0802882015-08-03 17:04:53 -06001338 LOOKUP_GIPA(GetPhysicalDeviceQueueFamilyProperties, true);
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06001339 LOOKUP_GIPA(EnumerateDeviceExtensionProperties, true);
Jon Ashburnc624c882015-07-16 10:17:29 -06001340 LOOKUP_GIPA(GetPhysicalDeviceSparseImageFormatProperties, true);
1341 LOOKUP_GIPA(DbgCreateMsgCallback, false);
1342 LOOKUP_GIPA(DbgDestroyMsgCallback, false);
Ian Elliott7e40db92015-08-21 15:09:33 -06001343 LOOKUP_GIPA(GetPhysicalDeviceSurfaceSupportKHR, false);
Ian Elliott486c5502015-11-19 16:05:09 -07001344 LOOKUP_GIPA(GetPhysicalDeviceSurfaceCapabilitiesKHR, false);
1345 LOOKUP_GIPA(GetPhysicalDeviceSurfaceFormatsKHR, false);
1346 LOOKUP_GIPA(GetPhysicalDeviceSurfacePresentModesKHR, false);
Ian Elliott919fa302015-11-24 15:39:10 -07001347#ifdef VK_USE_PLATFORM_WIN32_KHR
1348 LOOKUP_GIPA(GetPhysicalDeviceWin32PresentationSupportKHR, false);
1349#endif
1350#ifdef VK_USE_PLATFORM_XCB_KHR
1351 LOOKUP_GIPA(GetPhysicalDeviceXcbPresentationSupportKHR, false);
1352#endif
Jon Ashburn3da71f22015-05-14 12:43:38 -06001353
Jon Ashburnc624c882015-07-16 10:17:29 -06001354#undef LOOKUP_GIPA
Ian Elliottd3ef02f2015-07-06 14:36:13 -06001355
Jon Ashburnc624c882015-07-16 10:17:29 -06001356 return true;
Jon Ashburn3da71f22015-05-14 12:43:38 -06001357}
1358
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001359static void loader_debug_init(void)
1360{
1361 const char *env;
1362
1363 if (g_loader_debug > 0)
1364 return;
1365
1366 g_loader_debug = 0;
1367
1368 /* parse comma-separated debug options */
Courtney Goeltzenleuchterfce60db2015-07-29 09:08:22 -06001369 env = getenv("VK_LOADER_DEBUG");
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001370 while (env) {
1371 const char *p = strchr(env, ',');
1372 size_t len;
1373
1374 if (p)
1375 len = p - env;
1376 else
1377 len = strlen(env);
1378
1379 if (len > 0) {
Michael Worcester25c73e72015-12-10 18:06:24 +00001380 if (strncmp(env, "all", len) == 0) {
1381 g_loader_debug = ~0u;
1382 g_loader_log_msgs = ~0u;
1383 } else if (strncmp(env, "warn", len) == 0) {
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001384 g_loader_debug |= LOADER_WARN_BIT;
1385 g_loader_log_msgs |= VK_DBG_REPORT_WARN_BIT;
1386 } else if (strncmp(env, "info", len) == 0) {
1387 g_loader_debug |= LOADER_INFO_BIT;
1388 g_loader_log_msgs |= VK_DBG_REPORT_INFO_BIT;
1389 } else if (strncmp(env, "perf", len) == 0) {
1390 g_loader_debug |= LOADER_PERF_BIT;
1391 g_loader_log_msgs |= VK_DBG_REPORT_PERF_WARN_BIT;
1392 } else if (strncmp(env, "error", len) == 0) {
1393 g_loader_debug |= LOADER_ERROR_BIT;
1394 g_loader_log_msgs |= VK_DBG_REPORT_ERROR_BIT;
1395 } else if (strncmp(env, "debug", len) == 0) {
1396 g_loader_debug |= LOADER_DEBUG_BIT;
1397 g_loader_log_msgs |= VK_DBG_REPORT_DEBUG_BIT;
1398 }
1399 }
1400
1401 if (!p)
1402 break;
1403
1404 env = p + 1;
1405 }
1406}
1407
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001408void loader_initialize(void)
1409{
Jon Ashburn6461ef22015-09-22 13:11:00 -06001410 // initialize mutexs
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001411 loader_platform_thread_create_mutex(&loader_lock);
Jon Ashburn6461ef22015-09-22 13:11:00 -06001412 loader_platform_thread_create_mutex(&loader_json_lock);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001413
1414 // initialize logging
1415 loader_debug_init();
Jon Ashburn87d6aa92015-08-28 15:19:27 -06001416
1417 // initial cJSON to use alloc callbacks
1418 cJSON_Hooks alloc_fns = {
1419 .malloc_fn = loader_tls_heap_alloc,
1420 .free_fn = loader_tls_heap_free,
1421 };
1422 cJSON_InitHooks(&alloc_fns);
Jon Ashburn8810c5f2015-08-18 18:04:47 -06001423}
1424
Jon Ashburn2077e382015-06-29 11:25:34 -06001425struct loader_manifest_files {
1426 uint32_t count;
1427 char **filename_list;
1428};
1429
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06001430/**
Jon Ashburn2077e382015-06-29 11:25:34 -06001431 * Get next file or dirname given a string list or registry key path
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06001432 *
1433 * \returns
Jon Ashburn2077e382015-06-29 11:25:34 -06001434 * A pointer to first char in the next path.
1435 * The next path (or NULL) in the list is returned in next_path.
1436 * Note: input string is modified in some cases. PASS IN A COPY!
1437 */
Jon Ashburn2077e382015-06-29 11:25:34 -06001438static char *loader_get_next_path(char *path)
1439{
1440 uint32_t len;
1441 char *next;
1442
1443 if (path == NULL)
1444 return NULL;
1445 next = strchr(path, PATH_SEPERATOR);
1446 if (next == NULL) {
1447 len = (uint32_t) strlen(path);
1448 next = path + len;
1449 }
1450 else {
1451 *next = '\0';
1452 next++;
1453 }
1454
1455 return next;
1456}
1457
1458/**
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001459 * Given a path which is absolute or relative, expand the path if relative or
1460 * leave the path unmodified if absolute. The base path to prepend to relative
1461 * paths is given in rel_base.
Jon Ashburn15315172015-07-07 15:06:25 -06001462 *
1463 * \returns
1464 * A string in out_fullpath of the full absolute path
Jon Ashburn15315172015-07-07 15:06:25 -06001465 */
1466static void loader_expand_path(const char *path,
1467 const char *rel_base,
1468 size_t out_size,
1469 char *out_fullpath)
1470{
1471 if (loader_platform_is_path_absolute(path)) {
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001472 // do not prepend a base to an absolute path
1473 rel_base = "";
Jon Ashburn15315172015-07-07 15:06:25 -06001474 }
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001475
1476 loader_platform_combine_path(out_fullpath, out_size, rel_base, path, NULL);
Jon Ashburn15315172015-07-07 15:06:25 -06001477}
1478
1479/**
Jon Ashburn2077e382015-06-29 11:25:34 -06001480 * Given a filename (file) and a list of paths (dir), try to find an existing
1481 * file in the paths. If filename already is a path then no
1482 * searching in the given paths.
1483 *
1484 * \returns
1485 * A string in out_fullpath of either the full path or file.
Jon Ashburn2077e382015-06-29 11:25:34 -06001486 */
1487static void loader_get_fullpath(const char *file,
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001488 const char *dirs,
Jon Ashburn2077e382015-06-29 11:25:34 -06001489 size_t out_size,
1490 char *out_fullpath)
1491{
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001492 if (!loader_platform_is_path(file) && *dirs) {
1493 char *dirs_copy, *dir, *next_dir;
1494
1495 dirs_copy = loader_stack_alloc(strlen(dirs) + 1);
1496 strcpy(dirs_copy, dirs);
1497
1498 //find if file exists after prepending paths in given list
1499 for (dir = dirs_copy;
1500 *dir && (next_dir = loader_get_next_path(dir));
1501 dir = next_dir) {
1502 loader_platform_combine_path(out_fullpath, out_size, dir, file, NULL);
Jon Ashburn2077e382015-06-29 11:25:34 -06001503 if (loader_platform_file_exists(out_fullpath)) {
1504 return;
1505 }
Jon Ashburn2077e382015-06-29 11:25:34 -06001506 }
1507 }
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001508
Jon Ashburn2077e382015-06-29 11:25:34 -06001509 snprintf(out_fullpath, out_size, "%s", file);
1510}
1511
1512/**
1513 * Read a JSON file into a buffer.
1514 *
1515 * \returns
1516 * A pointer to a cJSON object representing the JSON parse tree.
1517 * This returned buffer should be freed by caller.
1518 */
1519static cJSON *loader_get_json(const char *filename)
1520{
1521 FILE *file;
1522 char *json_buf;
1523 cJSON *json;
1524 uint64_t len;
1525 file = fopen(filename,"rb");
Jon Ashburnaa4ea472015-08-27 08:30:50 -06001526 if (!file) {
1527 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Couldn't open JSON file %s", filename);
1528 return NULL;
1529 }
Jon Ashburn2077e382015-06-29 11:25:34 -06001530 fseek(file, 0, SEEK_END);
1531 len = ftell(file);
1532 fseek(file, 0, SEEK_SET);
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -06001533 json_buf = (char*) loader_stack_alloc(len+1);
Jon Ashburn2077e382015-06-29 11:25:34 -06001534 if (json_buf == NULL) {
1535 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get JSON file");
1536 fclose(file);
1537 return NULL;
1538 }
1539 if (fread(json_buf, sizeof(char), len, file) != len) {
1540 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "fread failed can't get JSON file");
1541 fclose(file);
1542 return NULL;
1543 }
1544 fclose(file);
1545 json_buf[len] = '\0';
1546
1547 //parse text from file
1548 json = cJSON_Parse(json_buf);
1549 if (json == NULL)
1550 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Can't parse JSON file %s", filename);
1551 return json;
1552}
1553
1554/**
Jon Ashburn3d002332015-08-20 16:35:30 -06001555 * Do a deep copy of the loader_layer_properties structure.
1556 */
1557static void loader_copy_layer_properties(
Jon Ashburne39a4f82015-08-28 13:38:21 -06001558 const struct loader_instance *inst,
Jon Ashburn3d002332015-08-20 16:35:30 -06001559 struct loader_layer_properties *dst,
1560 struct loader_layer_properties *src)
1561{
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001562 uint32_t cnt, i;
Jon Ashburn3d002332015-08-20 16:35:30 -06001563 memcpy(dst, src, sizeof (*src));
Jon Ashburne39a4f82015-08-28 13:38:21 -06001564 dst->instance_extension_list.list = loader_heap_alloc(
1565 inst,
1566 sizeof(VkExtensionProperties) *
1567 src->instance_extension_list.count,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001568 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001569 dst->instance_extension_list.capacity = sizeof(VkExtensionProperties) *
1570 src->instance_extension_list.count;
1571 memcpy(dst->instance_extension_list.list, src->instance_extension_list.list,
1572 dst->instance_extension_list.capacity);
1573 dst->device_extension_list.list = loader_heap_alloc(
1574 inst,
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001575 sizeof(struct loader_dev_ext_props) *
Jon Ashburne39a4f82015-08-28 13:38:21 -06001576 src->device_extension_list.count,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001577 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001578
1579 dst->device_extension_list.capacity = sizeof(struct loader_dev_ext_props) *
Jon Ashburne39a4f82015-08-28 13:38:21 -06001580 src->device_extension_list.count;
1581 memcpy(dst->device_extension_list.list, src->device_extension_list.list,
1582 dst->device_extension_list.capacity);
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001583 if (src->device_extension_list.count > 0 &&
1584 src->device_extension_list.list->entrypoint_count > 0) {
1585 cnt = src->device_extension_list.list->entrypoint_count;
1586 dst->device_extension_list.list->entrypoints = loader_heap_alloc(
1587 inst,
1588 sizeof(char *) * cnt,
1589 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
1590 for (i = 0; i < cnt; i++) {
1591 dst->device_extension_list.list->entrypoints[i] = loader_heap_alloc(
1592 inst,
1593 strlen(src->device_extension_list.list->entrypoints[i]) + 1,
1594 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
1595 strcpy(dst->device_extension_list.list->entrypoints[i],
1596 src->device_extension_list.list->entrypoints[i]);
1597 }
1598 }
Jon Ashburn3d002332015-08-20 16:35:30 -06001599}
1600
1601/**
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001602 * Given a cJSON struct (json) of the top level JSON object from layer manifest
1603 * file, add entry to the layer_list.
Jon Ashburne13ecc92015-08-03 17:19:30 -06001604 * Fill out the layer_properties in this list entry from the input cJSON object.
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001605 *
1606 * \returns
1607 * void
1608 * layer_list has a new entry and initialized accordingly.
1609 * If the json input object does not have all the required fields no entry
1610 * is added to the list.
1611 */
Jon Ashburne39a4f82015-08-28 13:38:21 -06001612static void loader_add_layer_properties(const struct loader_instance *inst,
1613 struct loader_layer_list *layer_instance_list,
Jon Ashburnb2ef1372015-07-16 17:19:31 -06001614 struct loader_layer_list *layer_device_list,
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001615 cJSON *json,
1616 bool is_implicit,
1617 char *filename)
1618{
1619 /* Fields in layer manifest file that are required:
1620 * (required) “file_format_version”
1621 * following are required in the "layer" object:
1622 * (required) "name"
1623 * (required) "type"
1624 * (required) “library_path”
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001625 * (required) “api_version”
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001626 * (required) “implementation_version”
1627 * (required) “description”
1628 * (required for implicit layers) “disable_environment”
1629 *
1630 * First get all required items and if any missing abort
1631 */
1632
1633 cJSON *item, *layer_node, *ext_item;
1634 char *temp;
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001635 char *name, *type, *library_path, *api_version;
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001636 char *implementation_version, *description;
1637 cJSON *disable_environment;
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001638 int i, j;
Jon Ashburn5c042ea2015-08-04 11:14:18 -06001639 VkExtensionProperties ext_prop;
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001640 item = cJSON_GetObjectItem(json, "file_format_version");
1641 if (item == NULL) {
1642 return;
1643 }
1644 char *file_vers = cJSON_PrintUnformatted(item);
1645 loader_log(VK_DBG_REPORT_INFO_BIT, 0, "Found manifest file %s, version %s",
1646 filename, file_vers);
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001647 if (strcmp(file_vers, "\"1.0.0\"") != 0)
1648 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Unexpected manifest file version (expected 1.0.0), may cause errors");
Jon Ashburn87d6aa92015-08-28 15:19:27 -06001649 loader_tls_heap_free(file_vers);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001650
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001651 layer_node = cJSON_GetObjectItem(json, "layer");
1652 if (layer_node == NULL) {
1653 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"layer\" object in manifest JSON file, skipping");
1654 return;
1655 }
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001656
1657 // loop through all "layer" objects in the file
1658 do {
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001659#define GET_JSON_OBJECT(node, var) { \
1660 var = cJSON_GetObjectItem(node, #var); \
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001661 if (var == NULL) { \
1662 layer_node = layer_node->next; \
1663 continue; \
1664 } \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001665 }
1666#define GET_JSON_ITEM(node, var) { \
1667 item = cJSON_GetObjectItem(node, #var); \
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001668 if (item == NULL) { \
1669 layer_node = layer_node->next; \
1670 continue; \
1671 } \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001672 temp = cJSON_Print(item); \
1673 temp[strlen(temp) - 1] = '\0'; \
Jon Ashburnf73e9212015-08-04 10:22:33 -06001674 var = loader_stack_alloc(strlen(temp) + 1); \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001675 strcpy(var, &temp[1]); \
Jon Ashburn87d6aa92015-08-28 15:19:27 -06001676 loader_tls_heap_free(temp); \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001677 }
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001678 GET_JSON_ITEM(layer_node, name)
1679 GET_JSON_ITEM(layer_node, type)
1680 GET_JSON_ITEM(layer_node, library_path)
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001681 GET_JSON_ITEM(layer_node, api_version)
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001682 GET_JSON_ITEM(layer_node, implementation_version)
1683 GET_JSON_ITEM(layer_node, description)
1684 if (is_implicit) {
1685 GET_JSON_OBJECT(layer_node, disable_environment)
1686 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001687#undef GET_JSON_ITEM
1688#undef GET_JSON_OBJECT
1689
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001690 // add list entry
Jon Ashburn432d2762015-09-18 12:53:16 -06001691 struct loader_layer_properties *props=NULL;
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001692 if (!strcmp(type, "DEVICE")) {
1693 if (layer_device_list == NULL) {
1694 layer_node = layer_node->next;
1695 continue;
1696 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06001697 props = loader_get_next_layer_property(inst, layer_device_list);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001698 props->type = (is_implicit) ? VK_LAYER_TYPE_DEVICE_IMPLICIT : VK_LAYER_TYPE_DEVICE_EXPLICIT;
1699 }
1700 if (!strcmp(type, "INSTANCE")) {
1701 if (layer_instance_list == NULL) {
1702 layer_node = layer_node->next;
1703 continue;
1704 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06001705 props = loader_get_next_layer_property(inst, layer_instance_list);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001706 props->type = (is_implicit) ? VK_LAYER_TYPE_INSTANCE_IMPLICIT : VK_LAYER_TYPE_INSTANCE_EXPLICIT;
1707 }
1708 if (!strcmp(type, "GLOBAL")) {
1709 if (layer_instance_list != NULL)
Jon Ashburne39a4f82015-08-28 13:38:21 -06001710 props = loader_get_next_layer_property(inst, layer_instance_list);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001711 else if (layer_device_list != NULL)
Jon Ashburne39a4f82015-08-28 13:38:21 -06001712 props = loader_get_next_layer_property(inst, layer_device_list);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001713 else {
1714 layer_node = layer_node->next;
1715 continue;
1716 }
1717 props->type = (is_implicit) ? VK_LAYER_TYPE_GLOBAL_IMPLICIT : VK_LAYER_TYPE_GLOBAL_EXPLICIT;
1718 }
Jon Ashburnb2ef1372015-07-16 17:19:31 -06001719
Jon Ashburn432d2762015-09-18 12:53:16 -06001720 if (props == NULL) {
1721 layer_node = layer_node->next;
1722 continue;
1723 }
1724
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001725 strncpy(props->info.layerName, name, sizeof (props->info.layerName));
1726 props->info.layerName[sizeof (props->info.layerName) - 1] = '\0';
Jon Ashburn15315172015-07-07 15:06:25 -06001727
Jon Ashburn3d002332015-08-20 16:35:30 -06001728 char *fullpath = props->lib_name;
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001729 char *rel_base;
Jon Ashburn6e08ebd2015-12-01 17:11:02 -07001730 if (loader_platform_is_path(library_path)) {
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001731 // a relative or absolute path
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001732 char *name_copy = loader_stack_alloc(strlen(filename) + 1);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001733 strcpy(name_copy, filename);
1734 rel_base = loader_platform_dirname(name_copy);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001735 loader_expand_path(library_path, rel_base, MAX_STRING_SIZE, fullpath);
Daniel Dadap00b4aba2015-09-30 11:50:51 -05001736 } else {
1737 // a filename which is assumed in a system directory
1738 loader_get_fullpath(library_path, DEFAULT_VK_LAYERS_PATH, MAX_STRING_SIZE, fullpath);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001739 }
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001740 props->info.specVersion = loader_make_version(api_version);
1741 props->info.implementationVersion = atoi(implementation_version);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001742 strncpy((char *) props->info.description, description, sizeof (props->info.description));
1743 props->info.description[sizeof (props->info.description) - 1] = '\0';
1744 if (is_implicit) {
1745 strncpy(props->disable_env_var.name, disable_environment->child->string, sizeof (props->disable_env_var.name));
1746 props->disable_env_var.name[sizeof (props->disable_env_var.name) - 1] = '\0';
1747 strncpy(props->disable_env_var.value, disable_environment->child->valuestring, sizeof (props->disable_env_var.value));
1748 props->disable_env_var.value[sizeof (props->disable_env_var.value) - 1] = '\0';
1749 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001750
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001751 /**
1752 * Now get all optional items and objects and put in list:
1753 * functions
1754 * instance_extensions
1755 * device_extensions
1756 * enable_environment (implicit layers only)
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001757 * disable_environment (implicit_layers_only)
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001758 */
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001759#define GET_JSON_OBJECT(node, var) { \
1760 var = cJSON_GetObjectItem(node, #var); \
1761 }
1762#define GET_JSON_ITEM(node, var) { \
1763 item = cJSON_GetObjectItem(node, #var); \
Jon Ashburn21c21ee2015-09-09 11:29:24 -06001764 if (item != NULL) { \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001765 temp = cJSON_Print(item); \
Jon Ashburn21c21ee2015-09-09 11:29:24 -06001766 temp[strlen(temp) - 1] = '\0'; \
1767 var = loader_stack_alloc(strlen(temp) + 1);\
1768 strcpy(var, &temp[1]); \
1769 loader_tls_heap_free(temp); \
1770 } \
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001771 }
1772
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001773 cJSON *instance_extensions, *device_extensions, *functions, *enable_environment;
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001774 cJSON *entrypoints;
1775 char *vkGetInstanceProcAddr, *vkGetDeviceProcAddr, *spec_version;
1776 char **entry_array;
1777 vkGetInstanceProcAddr = NULL;
1778 vkGetDeviceProcAddr = NULL;
1779 spec_version = NULL;
1780 entrypoints = NULL;
1781 entry_array = NULL;
1782 /**
1783 * functions
1784 * vkGetInstanceProcAddr
1785 * vkGetDeviceProcAddr
1786 */
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001787 GET_JSON_OBJECT(layer_node, functions)
1788 if (functions != NULL) {
1789 GET_JSON_ITEM(functions, vkGetInstanceProcAddr)
1790 GET_JSON_ITEM(functions, vkGetDeviceProcAddr)
Jon Ashburn21c21ee2015-09-09 11:29:24 -06001791 if (vkGetInstanceProcAddr != NULL)
1792 strncpy(props->functions.str_gipa, vkGetInstanceProcAddr, sizeof (props->functions.str_gipa));
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001793 props->functions.str_gipa[sizeof (props->functions.str_gipa) - 1] = '\0';
Jon Ashburn21c21ee2015-09-09 11:29:24 -06001794 if (vkGetDeviceProcAddr != NULL)
1795 strncpy(props->functions.str_gdpa, vkGetDeviceProcAddr, sizeof (props->functions.str_gdpa));
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001796 props->functions.str_gdpa[sizeof (props->functions.str_gdpa) - 1] = '\0';
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001797 }
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001798 /**
1799 * instance_extensions
1800 * array of
1801 * name
1802 * spec_version
1803 */
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001804 GET_JSON_OBJECT(layer_node, instance_extensions)
1805 if (instance_extensions != NULL) {
1806 int count = cJSON_GetArraySize(instance_extensions);
1807 for (i = 0; i < count; i++) {
1808 ext_item = cJSON_GetArrayItem(instance_extensions, i);
1809 GET_JSON_ITEM(ext_item, name)
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001810 GET_JSON_ITEM(ext_item, spec_version)
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001811 if (name != NULL) {
Jon Ashburn6e6a2162015-12-10 08:51:10 -07001812 strncpy(ext_prop.extensionName, name, sizeof (ext_prop.extensionName));
1813 ext_prop.extensionName[sizeof (ext_prop.extensionName) - 1] = '\0';
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001814 }
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001815 ext_prop.specVersion = atoi(spec_version);
Jon Ashburne39a4f82015-08-28 13:38:21 -06001816 loader_add_to_ext_list(inst, &props->instance_extension_list, 1, &ext_prop);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001817 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001818 }
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001819 /**
1820 * device_extensions
1821 * array of
1822 * name
1823 * spec_version
1824 * entrypoints
1825 */
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001826 GET_JSON_OBJECT(layer_node, device_extensions)
1827 if (device_extensions != NULL) {
1828 int count = cJSON_GetArraySize(device_extensions);
1829 for (i = 0; i < count; i++) {
1830 ext_item = cJSON_GetArrayItem(device_extensions, i);
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001831 GET_JSON_ITEM(ext_item, name)
1832 GET_JSON_ITEM(ext_item, spec_version)
1833 if (name != NULL) {
Jon Ashburn6e6a2162015-12-10 08:51:10 -07001834 strncpy(ext_prop.extensionName, name, sizeof (ext_prop.extensionName));
1835 ext_prop.extensionName[sizeof (ext_prop.extensionName) - 1] = '\0';
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001836 }
Jon Ashburnf2a944f2015-11-18 16:46:48 -07001837 ext_prop.specVersion = atoi(spec_version);
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001838 //entrypoints = cJSON_GetObjectItem(ext_item, "entrypoints");
1839 GET_JSON_OBJECT(ext_item, entrypoints)
1840 int entry_count;
1841 if (entrypoints == NULL)
1842 continue;
1843 entry_count = cJSON_GetArraySize(entrypoints);
1844 if (entry_count)
1845 entry_array = (char **) loader_stack_alloc(sizeof(char *) * entry_count);
1846 for (j = 0; j < entry_count; j++) {
1847 ext_item = cJSON_GetArrayItem(entrypoints, j);
1848 if (ext_item != NULL) {
1849 temp = cJSON_Print(ext_item);
1850 temp[strlen(temp) - 1] = '\0';
1851 entry_array[j] = loader_stack_alloc(strlen(temp) + 1);
1852 strcpy(entry_array[j], &temp[1]);
1853 loader_tls_heap_free(temp);
Jon Ashburn6e6a2162015-12-10 08:51:10 -07001854 }
1855 }
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001856 loader_add_to_dev_ext_list(inst, &props->device_extension_list,
1857 &ext_prop, entry_count, entry_array);
1858 }
1859 }
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001860 if (is_implicit) {
1861 GET_JSON_OBJECT(layer_node, enable_environment)
1862 strncpy(props->enable_env_var.name, enable_environment->child->string, sizeof (props->enable_env_var.name));
1863 props->enable_env_var.name[sizeof (props->enable_env_var.name) - 1] = '\0';
1864 strncpy(props->enable_env_var.value, enable_environment->child->valuestring, sizeof (props->enable_env_var.value));
1865 props->enable_env_var.value[sizeof (props->enable_env_var.value) - 1] = '\0';
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07001866 //TODO add disable_environment for implicit layers
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001867 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001868#undef GET_JSON_ITEM
1869#undef GET_JSON_OBJECT
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001870 // for global layers need to add them to both device and instance list
1871 if (!strcmp(type, "GLOBAL")) {
1872 struct loader_layer_properties *dev_props;
1873 if (layer_instance_list == NULL || layer_device_list == NULL) {
1874 layer_node = layer_node->next;
1875 continue;
1876 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06001877 dev_props = loader_get_next_layer_property(inst, layer_device_list);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001878 //copy into device layer list
Jon Ashburne39a4f82015-08-28 13:38:21 -06001879 loader_copy_layer_properties(inst, dev_props, props);
Jon Ashburnfb8ac012015-08-12 16:39:32 -06001880 }
1881 layer_node = layer_node->next;
1882 } while (layer_node != NULL);
1883 return;
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001884}
1885
1886/**
Jon Ashburn2077e382015-06-29 11:25:34 -06001887 * Find the Vulkan library manifest files.
1888 *
1889 * This function scans the location or env_override directories/files
1890 * for a list of JSON manifest files. If env_override is non-NULL
1891 * and has a valid value. Then the location is ignored. Otherwise
1892 * location is used to look for manifest files. The location
1893 * is interpreted as Registry path on Windows and a directory path(s)
1894 * on Linux.
1895 *
1896 * \returns
1897 * A string list of manifest files to be opened in out_files param.
1898 * List has a pointer to string for each manifest filename.
1899 * When done using the list in out_files, pointers should be freed.
Jon Ashburnffad94d2015-06-30 14:46:22 -07001900 * Location or override string lists can be either files or directories as follows:
1901 * | location | override
1902 * --------------------------------
1903 * Win ICD | files | files
1904 * Win Layer | files | dirs
1905 * Linux ICD | dirs | files
1906 * Linux Layer| dirs | dirs
Jon Ashburn2077e382015-06-29 11:25:34 -06001907 */
Jon Ashburne39a4f82015-08-28 13:38:21 -06001908static void loader_get_manifest_files(const struct loader_instance *inst,
1909 const char *env_override,
Jon Ashburnffad94d2015-06-30 14:46:22 -07001910 bool is_layer,
1911 const char *location,
1912 struct loader_manifest_files *out_files)
Jon Ashburn2077e382015-06-29 11:25:34 -06001913{
1914 char *override = NULL;
1915 char *loc;
1916 char *file, *next_file, *name;
1917 size_t alloced_count = 64;
1918 char full_path[2048];
1919 DIR *sysdir = NULL;
Jon Ashburnffad94d2015-06-30 14:46:22 -07001920 bool list_is_dirs = false;
Jon Ashburn2077e382015-06-29 11:25:34 -06001921 struct dirent *dent;
1922
1923 out_files->count = 0;
1924 out_files->filename_list = NULL;
1925
Jon Ashburn2077e382015-06-29 11:25:34 -06001926 if (env_override != NULL && (override = getenv(env_override))) {
Johannes van Waveren9bd805012015-10-28 11:45:00 -05001927#if !defined(_WIN32)
Jon Ashburn2077e382015-06-29 11:25:34 -06001928 if (geteuid() != getuid()) {
Jon Ashburnffad94d2015-06-30 14:46:22 -07001929 /* Don't allow setuid apps to use the env var: */
Jon Ashburn2077e382015-06-29 11:25:34 -06001930 override = NULL;
1931 }
1932#endif
1933 }
1934
1935 if (location == NULL) {
1936 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
Jon Ashburnffad94d2015-06-30 14:46:22 -07001937 "Can't get manifest files with NULL location, env_override=%s",
1938 env_override);
Jon Ashburn2077e382015-06-29 11:25:34 -06001939 return;
1940 }
1941
Johannes van Waveren9bd805012015-10-28 11:45:00 -05001942#if defined(_WIN32)
Jon Ashburnffad94d2015-06-30 14:46:22 -07001943 list_is_dirs = (is_layer && override != NULL) ? true : false;
Johannes van Waveren9bd805012015-10-28 11:45:00 -05001944#else
1945 list_is_dirs = (override == NULL || is_layer) ? true : false;
Jon Ashburnffad94d2015-06-30 14:46:22 -07001946#endif
Jon Ashburn2077e382015-06-29 11:25:34 -06001947 // Make a copy of the input we are using so it is not modified
Jon Ashburnffad94d2015-06-30 14:46:22 -07001948 // Also handle getting the location(s) from registry on Windows
1949 if (override == NULL) {
Jon Ashburn3b78e462015-07-31 10:11:24 -06001950 loc = loader_stack_alloc(strlen(location) + 1);
Jon Ashburnffad94d2015-06-30 14:46:22 -07001951 if (loc == NULL) {
1952 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files");
1953 return;
1954 }
1955 strcpy(loc, location);
Johannes van Waveren9bd805012015-10-28 11:45:00 -05001956#if defined(_WIN32)
Jon Ashburn480a50a2015-08-28 14:58:46 -07001957 loc = loader_get_registry_files(inst, loc);
Jon Ashburn24265ac2015-07-31 09:33:21 -06001958 if (loc == NULL) {
1959 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Registry lookup failed can't get manifest files");
1960 return;
1961 }
Jon Ashburnffad94d2015-06-30 14:46:22 -07001962#endif
Jon Ashburn2077e382015-06-29 11:25:34 -06001963 }
Jon Ashburnffad94d2015-06-30 14:46:22 -07001964 else {
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -06001965 loc = loader_stack_alloc(strlen(override) + 1);
Jon Ashburnffad94d2015-06-30 14:46:22 -07001966 if (loc == NULL) {
1967 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files");
1968 return;
1969 }
1970 strcpy(loc, override);
1971 }
Jon Ashburn2077e382015-06-29 11:25:34 -06001972
Liam Middlebrook9b14e892015-07-23 18:32:20 -07001973 // Print out the paths being searched if debugging is enabled
Jon Ashburn46e20d82015-07-31 09:41:31 -06001974 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, "Searching the following paths for manifest files: %s\n", loc);
Liam Middlebrook9b14e892015-07-23 18:32:20 -07001975
Jon Ashburn2077e382015-06-29 11:25:34 -06001976 file = loc;
1977 while (*file) {
1978 next_file = loader_get_next_path(file);
Jon Ashburnffad94d2015-06-30 14:46:22 -07001979 if (list_is_dirs) {
Jon Ashburn2077e382015-06-29 11:25:34 -06001980 sysdir = opendir(file);
1981 name = NULL;
1982 if (sysdir) {
1983 dent = readdir(sysdir);
1984 if (dent == NULL)
1985 break;
1986 name = &(dent->d_name[0]);
1987 loader_get_fullpath(name, file, sizeof(full_path), full_path);
1988 name = full_path;
1989 }
1990 }
1991 else {
Johannes van Waveren9bd805012015-10-28 11:45:00 -05001992#if defined(_WIN32)
1993 name = file;
1994#else
Jon Ashburnffad94d2015-06-30 14:46:22 -07001995 // only Linux has relative paths
Jon Ashburn2077e382015-06-29 11:25:34 -06001996 char *dir;
1997 // make a copy of location so it isn't modified
Jason Ekstrandcc7550e2015-10-10 08:33:37 -07001998 dir = loader_stack_alloc(strlen(loc) + 1);
Jon Ashburn2077e382015-06-29 11:25:34 -06001999 if (dir == NULL) {
2000 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files");
2001 return;
2002 }
Jason Ekstrandcc7550e2015-10-10 08:33:37 -07002003 strcpy(dir, loc);
Jon Ashburn2077e382015-06-29 11:25:34 -06002004
2005 loader_get_fullpath(file, dir, sizeof(full_path), full_path);
2006
2007 name = full_path;
Jon Ashburnffad94d2015-06-30 14:46:22 -07002008#endif
Jon Ashburn2077e382015-06-29 11:25:34 -06002009 }
2010 while (name) {
2011 /* Look for files ending with ".json" suffix */
2012 uint32_t nlen = (uint32_t) strlen(name);
2013 const char *suf = name + nlen - 5;
2014 if ((nlen > 5) && !strncmp(suf, ".json", 5)) {
2015 if (out_files->count == 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06002016 out_files->filename_list = loader_heap_alloc(inst,
2017 alloced_count * sizeof(char *),
Chia-I Wucf804e82015-10-31 00:31:16 +08002018 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
Jon Ashburn2077e382015-06-29 11:25:34 -06002019 }
2020 else if (out_files->count == alloced_count) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06002021 out_files->filename_list = loader_heap_realloc(inst,
2022 out_files->filename_list,
2023 alloced_count * sizeof(char *),
2024 alloced_count * sizeof(char *) * 2,
Chia-I Wucf804e82015-10-31 00:31:16 +08002025 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
Jon Ashburn2077e382015-06-29 11:25:34 -06002026 alloced_count *= 2;
2027 }
2028 if (out_files->filename_list == NULL) {
2029 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't alloc manifest file list");
2030 return;
2031 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06002032 out_files->filename_list[out_files->count] = loader_heap_alloc(
2033 inst,
2034 strlen(name) + 1,
Chia-I Wucf804e82015-10-31 00:31:16 +08002035 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
Jon Ashburn2077e382015-06-29 11:25:34 -06002036 if (out_files->filename_list[out_files->count] == NULL) {
2037 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files");
2038 return;
2039 }
2040 strcpy(out_files->filename_list[out_files->count], name);
2041 out_files->count++;
Jon Ashburnf70f3612015-07-02 10:08:47 -06002042 } else if (!list_is_dirs) {
2043 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Skipping manifest file %s, file name must end in .json", name);
Jon Ashburn2077e382015-06-29 11:25:34 -06002044 }
Jon Ashburnffad94d2015-06-30 14:46:22 -07002045 if (list_is_dirs) {
Jon Ashburn2077e382015-06-29 11:25:34 -06002046 dent = readdir(sysdir);
2047 if (dent == NULL)
2048 break;
2049 name = &(dent->d_name[0]);
2050 loader_get_fullpath(name, file, sizeof(full_path), full_path);
2051 name = full_path;
2052 }
2053 else {
2054 break;
2055 }
2056 }
2057 if (sysdir)
2058 closedir(sysdir);
2059 file = next_file;
2060 }
2061 return;
2062}
2063
Jon Ashburn8810c5f2015-08-18 18:04:47 -06002064void loader_init_icd_lib_list()
2065{
2066
2067}
2068
2069void loader_destroy_icd_lib_list()
2070{
2071
2072}
Jon Ashburn2077e382015-06-29 11:25:34 -06002073/**
2074 * Try to find the Vulkan ICD driver(s).
2075 *
2076 * This function scans the default system loader path(s) or path
2077 * specified by the \c VK_ICD_FILENAMES environment variable in
2078 * order to find loadable VK ICDs manifest files. From these
2079 * manifest files it finds the ICD libraries.
2080 *
2081 * \returns
Jon Ashburn8810c5f2015-08-18 18:04:47 -06002082 * a list of icds that were discovered
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06002083 */
Jon Ashburne39a4f82015-08-28 13:38:21 -06002084void loader_icd_scan(
2085 const struct loader_instance *inst,
2086 struct loader_icd_libs *icds)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08002087{
Jon Ashburn2077e382015-06-29 11:25:34 -06002088 char *file_str;
2089 struct loader_manifest_files manifest_files;
2090
Jon Ashburne39a4f82015-08-28 13:38:21 -06002091 loader_scanned_icd_init(inst, icds);
Jon Ashburn2077e382015-06-29 11:25:34 -06002092 // Get a list of manifest files for ICDs
Jon Ashburne39a4f82015-08-28 13:38:21 -06002093 loader_get_manifest_files(inst, "VK_ICD_FILENAMES", false,
2094 DEFAULT_VK_DRIVERS_INFO, &manifest_files);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002095 if (manifest_files.count == 0)
2096 return;
Jon Ashburn6461ef22015-09-22 13:11:00 -06002097 loader_platform_thread_lock_mutex(&loader_json_lock);
Jon Ashburn2077e382015-06-29 11:25:34 -06002098 for (uint32_t i = 0; i < manifest_files.count; i++) {
2099 file_str = manifest_files.filename_list[i];
2100 if (file_str == NULL)
2101 continue;
2102
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002103 cJSON *json;
Jon Ashburn2077e382015-06-29 11:25:34 -06002104 json = loader_get_json(file_str);
Jon Ashburnaa4ea472015-08-27 08:30:50 -06002105 if (!json)
2106 continue;
Jon Ashburn005617f2015-11-17 17:35:40 -07002107 cJSON *item, *itemICD;
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002108 item = cJSON_GetObjectItem(json, "file_format_version");
Jon Ashburn6461ef22015-09-22 13:11:00 -06002109 if (item == NULL) {
2110 loader_platform_thread_unlock_mutex(&loader_json_lock);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002111 return;
Jon Ashburn6461ef22015-09-22 13:11:00 -06002112 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002113 char *file_vers = cJSON_Print(item);
2114 loader_log(VK_DBG_REPORT_INFO_BIT, 0, "Found manifest file %s, version %s",
2115 file_str, file_vers);
2116 if (strcmp(file_vers, "\"1.0.0\"") != 0)
2117 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Unexpected manifest file version (expected 1.0.0), may cause errors");
Jon Ashburn87d6aa92015-08-28 15:19:27 -06002118 loader_tls_heap_free(file_vers);
Jon Ashburn005617f2015-11-17 17:35:40 -07002119 itemICD = cJSON_GetObjectItem(json, "ICD");
2120 if (itemICD != NULL) {
2121 item = cJSON_GetObjectItem(itemICD, "library_path");
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002122 if (item != NULL) {
Jon Ashburn86251302015-08-25 16:48:24 -06002123 char *temp= cJSON_Print(item);
2124 if (!temp || strlen(temp) == 0) {
2125 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"library_path\" in ICD JSON file %s, skipping", file_str);
Jon Ashburn87d6aa92015-08-28 15:19:27 -06002126 loader_tls_heap_free(temp);
Jon Ashburne39a4f82015-08-28 13:38:21 -06002127 loader_heap_free(inst, file_str);
Jon Ashburn86251302015-08-25 16:48:24 -06002128 cJSON_Delete(json);
2129 continue;
Jon Ashburn2077e382015-06-29 11:25:34 -06002130 }
Jon Ashburn86251302015-08-25 16:48:24 -06002131 //strip out extra quotes
2132 temp[strlen(temp) - 1] = '\0';
2133 char *library_path = loader_stack_alloc(strlen(temp) + 1);
2134 strcpy(library_path, &temp[1]);
Jon Ashburn87d6aa92015-08-28 15:19:27 -06002135 loader_tls_heap_free(temp);
Jon Ashburn86251302015-08-25 16:48:24 -06002136 if (!library_path || strlen(library_path) == 0) {
2137 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"library_path\" in ICD JSON file %s, skipping", file_str);
Jon Ashburne39a4f82015-08-28 13:38:21 -06002138 loader_heap_free(inst, file_str);
Jon Ashburn86251302015-08-25 16:48:24 -06002139 cJSON_Delete(json);
2140 continue;
2141 }
Daniel Dadap00b4aba2015-09-30 11:50:51 -05002142 char fullpath[MAX_STRING_SIZE];
Jon Ashburn86251302015-08-25 16:48:24 -06002143 // Print out the paths being searched if debugging is enabled
2144 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, "Searching for ICD drivers named %s default dir %s\n", library_path, DEFAULT_VK_DRIVERS_PATH);
Daniel Dadap00b4aba2015-09-30 11:50:51 -05002145 if (loader_platform_is_path(library_path)) {
Jon Ashburn86251302015-08-25 16:48:24 -06002146 // a relative or absolute path
Daniel Dadap00b4aba2015-09-30 11:50:51 -05002147 char *name_copy = loader_stack_alloc(strlen(file_str) + 1);
2148 char *rel_base;
Jon Ashburn86251302015-08-25 16:48:24 -06002149 strcpy(name_copy, file_str);
2150 rel_base = loader_platform_dirname(name_copy);
Daniel Dadap00b4aba2015-09-30 11:50:51 -05002151 loader_expand_path(library_path, rel_base, sizeof(fullpath), fullpath);
2152 } else {
2153 // a filename which is assumed in a system directory
2154 loader_get_fullpath(library_path, DEFAULT_VK_DRIVERS_PATH, sizeof(fullpath), fullpath);
Jon Ashburn86251302015-08-25 16:48:24 -06002155 }
Jon Ashburn005617f2015-11-17 17:35:40 -07002156
2157 uint32_t vers = 0;
2158 item = cJSON_GetObjectItem(itemICD, "api_version");
2159 if (item != NULL) {
2160 temp= cJSON_Print(item);
2161 vers = loader_make_version(temp);
2162 loader_tls_heap_free(temp);
2163 }
2164 loader_scanned_icd_add(inst, icds, fullpath, vers);
Jon Ashburn2077e382015-06-29 11:25:34 -06002165 }
Jon Ashburn005617f2015-11-17 17:35:40 -07002166 else
2167 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"library_path\" object in ICD JSON file %s, skipping", file_str);
Jon Ashburn2077e382015-06-29 11:25:34 -06002168 }
2169 else
2170 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"ICD\" object in ICD JSON file %s, skipping", file_str);
2171
Jon Ashburne39a4f82015-08-28 13:38:21 -06002172 loader_heap_free(inst, file_str);
Jon Ashburn2077e382015-06-29 11:25:34 -06002173 cJSON_Delete(json);
2174 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06002175 loader_heap_free(inst, manifest_files.filename_list);
Jon Ashburn6461ef22015-09-22 13:11:00 -06002176 loader_platform_thread_unlock_mutex(&loader_json_lock);
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08002177}
2178
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002179
Jon Ashburne39a4f82015-08-28 13:38:21 -06002180void loader_layer_scan(
2181 const struct loader_instance *inst,
2182 struct loader_layer_list *instance_layers,
2183 struct loader_layer_list *device_layers)
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002184{
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002185 char *file_str;
2186 struct loader_manifest_files manifest_files;
2187 cJSON *json;
2188 uint32_t i;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002189
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002190 // Get a list of manifest files for layers
Jon Ashburne39a4f82015-08-28 13:38:21 -06002191 loader_get_manifest_files(inst, LAYERS_PATH_ENV, true, DEFAULT_VK_LAYERS_INFO,
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002192 &manifest_files);
2193 if (manifest_files.count == 0)
Courtney Goeltzenleuchter57985ce2014-12-01 09:29:42 -07002194 return;
Jon Ashburn90c6a0e2015-06-04 15:30:58 -06002195
Jon Ashburne13ecc92015-08-03 17:19:30 -06002196#if 0 //TODO
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002197 /**
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -06002198 * We need a list of the layer libraries, not just a list of
2199 * the layer properties (a layer library could expose more than
2200 * one layer property). This list of scanned layers would be
2201 * used to check for global and physicaldevice layer properties.
2202 */
2203 if (!loader_init_layer_library_list(&loader.scanned_layer_libraries)) {
2204 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
Jon Ashburne39a4f82015-08-28 13:38:21 -06002205 "Alloc for layer list failed: %s line: %d", __FILE__, __LINE__);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -06002206 return;
Jon Ashburn5ef20602015-07-02 09:40:15 -06002207 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002208#endif
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002209
Jon Ashburne13ecc92015-08-03 17:19:30 -06002210 /* cleanup any previously scanned libraries */
Jon Ashburne39a4f82015-08-28 13:38:21 -06002211 loader_delete_layer_properties(inst, instance_layers);
2212 loader_delete_layer_properties(inst, device_layers);
Jon Ashburnb2ef1372015-07-16 17:19:31 -06002213
Jon Ashburn6461ef22015-09-22 13:11:00 -06002214 loader_platform_thread_lock_mutex(&loader_json_lock);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002215 for (i = 0; i < manifest_files.count; i++) {
2216 file_str = manifest_files.filename_list[i];
2217 if (file_str == NULL)
2218 continue;
Courtney Goeltzenleuchtera9e4af42015-06-01 14:49:17 -06002219
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002220 // parse file into JSON struct
2221 json = loader_get_json(file_str);
2222 if (!json) {
2223 continue;
2224 }
Jon Ashburne13ecc92015-08-03 17:19:30 -06002225
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002226 //TODO pass in implicit versus explicit bool
Jon Ashburnb2ef1372015-07-16 17:19:31 -06002227 //TODO error if device layers expose instance_extensions
2228 //TODO error if instance layers expose device extensions
Jon Ashburne39a4f82015-08-28 13:38:21 -06002229 loader_add_layer_properties(inst,
2230 instance_layers,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002231 device_layers,
Jon Ashburnb2ef1372015-07-16 17:19:31 -06002232 json,
2233 false,
2234 file_str);
2235
Jon Ashburne39a4f82015-08-28 13:38:21 -06002236 loader_heap_free(inst, file_str);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002237 cJSON_Delete(json);
2238 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06002239 loader_heap_free(inst, manifest_files.filename_list);
Jon Ashburn6461ef22015-09-22 13:11:00 -06002240 loader_platform_thread_unlock_mutex(&loader_json_lock);
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002241}
2242
Chia-I Wu9ab61502015-11-06 06:42:02 +08002243static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL loader_gpa_instance_internal(VkInstance inst, const char * pName)
Jon Ashburn27cd5842015-05-12 17:26:48 -06002244{
2245 // inst is not wrapped
2246 if (inst == VK_NULL_HANDLE) {
2247 return NULL;
2248 }
2249 VkLayerInstanceDispatchTable* disp_table = * (VkLayerInstanceDispatchTable **) inst;
2250 void *addr;
2251
Jon Ashburn8fd08252015-05-28 16:25:02 -06002252 if (!strcmp(pName, "vkGetInstanceProcAddr"))
2253 return (void *) loader_gpa_instance_internal;
2254
Jon Ashburn27cd5842015-05-12 17:26:48 -06002255 if (disp_table == NULL)
2256 return NULL;
2257
2258 addr = loader_lookup_instance_dispatch_table(disp_table, pName);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002259 if (addr) {
Jon Ashburn27cd5842015-05-12 17:26:48 -06002260 return addr;
Jon Ashburn3d526cb2015-04-13 18:10:06 -06002261 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002262
2263 if (disp_table->GetInstanceProcAddr == NULL) {
2264 return NULL;
2265 }
2266 return disp_table->GetInstanceProcAddr(inst, pName);
Jon Ashburn3d526cb2015-04-13 18:10:06 -06002267}
2268
Jon Ashburnfc1031e2015-11-17 15:31:02 -07002269/**
2270 * Initialize device_ext dispatch table entry as follows:
2271 * If dev == NULL find all logical devices created within this instance and
2272 * init the entry (given by idx) in the ext dispatch table.
2273 * If dev != NULL only initialize the entry in the given dev's dispatch table.
2274 * The initialization value is gotten by calling down the device chain with GDPA.
2275 * If GDPA returns NULL then don't initialize the dispatch table entry.
2276 */
2277static void loader_init_dispatch_dev_ext_entry(struct loader_instance *inst,
2278 struct loader_device *dev,
2279 uint32_t idx,
2280 const char *funcName)
2281
2282 {
2283 void *gdpa_value;
2284 if (dev != NULL) {
2285 gdpa_value = dev->loader_dispatch.core_dispatch.GetDeviceProcAddr(
2286 dev->device, funcName);
2287 if (gdpa_value != NULL)
2288 dev->loader_dispatch.ext_dispatch.DevExt[idx] = (PFN_vkDevExt) gdpa_value;
2289 } else {
2290 for (uint32_t i = 0; i < inst->total_icd_count; i++) {
2291 struct loader_icd *icd = &inst->icds[i];
2292 struct loader_device *dev = icd->logical_device_list;
2293 while (dev) {
2294 gdpa_value = dev->loader_dispatch.core_dispatch.GetDeviceProcAddr(
2295 dev->device, funcName);
2296 if (gdpa_value != NULL)
2297 dev->loader_dispatch.ext_dispatch.DevExt[idx] =
2298 (PFN_vkDevExt) gdpa_value;
2299 dev = dev->next;
2300 }
2301 }
2302 }
2303
2304}
2305
2306/**
2307 * Find all dev extension in the hash table and initialize the dispatch table
2308 * for dev for each of those extension entrypoints found in hash table.
2309
2310 */
2311static void loader_init_dispatch_dev_ext(struct loader_instance *inst,
2312 struct loader_device *dev)
2313{
2314 for (uint32_t i = 0; i < MAX_NUM_DEV_EXTS; i++) {
2315 if (inst->disp_hash[i].func_name != NULL)
2316 loader_init_dispatch_dev_ext_entry(inst, dev, i,
2317 inst->disp_hash[i].func_name);
2318 }
2319}
2320
2321static bool loader_check_icds_for_address(struct loader_instance *inst,
2322 const char *funcName)
2323{
2324 struct loader_icd *icd;
2325 icd = inst->icds;
2326 while (icd) {
2327 if (icd->this_icd_lib->GetInstanceProcAddr(icd->instance, funcName))
2328 // this icd supports funcName
2329 return true;
2330 icd = icd->next;
2331 }
2332
2333 return false;
2334}
2335
2336static void loader_free_dev_ext_table(struct loader_instance *inst)
2337{
2338 for (uint32_t i = 0; i < MAX_NUM_DEV_EXTS; i++) {
2339 loader_heap_free(inst, inst->disp_hash[i].func_name);
2340 loader_heap_free(inst, inst->disp_hash[i].list.index);
2341
2342 }
2343 memset(inst->disp_hash, 0, sizeof(inst->disp_hash));
2344}
2345
2346static bool loader_add_dev_ext_table(struct loader_instance *inst,
2347 uint32_t *ptr_idx,
2348 const char *funcName)
2349{
2350 uint32_t i;
2351 uint32_t idx = *ptr_idx;
2352 struct loader_dispatch_hash_list *list = &inst->disp_hash[idx].list;
2353
2354 if (!inst->disp_hash[idx].func_name) {
2355 // no entry here at this idx, so use it
2356 assert(list->capacity == 0);
2357 inst->disp_hash[idx].func_name = (char *) loader_heap_alloc(inst,
2358 strlen(funcName) + 1,
2359 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
2360 if (inst->disp_hash[idx].func_name == NULL) {
2361 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
2362 "loader_add_dev_ext_table() can't allocate memory for func_name");
2363 return false;
2364 }
2365 strncpy(inst->disp_hash[idx].func_name, funcName, strlen(funcName) + 1);
2366 return true;
2367 }
2368
2369 // check for enough capacity
2370 if (list->capacity == 0) {
2371 list->index = loader_heap_alloc(inst, 8 * sizeof(*(list->index)),
2372 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
2373 if (list->index == NULL) {
2374 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
2375 "loader_add_dev_ext_table() can't allocate list memory");
2376 return false;
2377 }
2378 list->capacity = 8 * sizeof(*(list->index));
2379 } else if (list->capacity < (list->count + 1) * sizeof(*(list->index))) {
2380 list->index = loader_heap_realloc(inst, list->index, list->capacity,
2381 list->capacity * 2,
2382 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
2383 if (list->index == NULL) {
2384 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
2385 "loader_add_dev_ext_table() can't reallocate list memory");
2386 return false;
2387 }
2388 list->capacity *= 2;
2389 }
2390
2391 //find an unused index in the hash table and use it
2392 i = (idx + 1) % MAX_NUM_DEV_EXTS;
2393 do {
2394 if (!inst->disp_hash[i].func_name) {
2395 assert(inst->disp_hash[i].list.capacity == 0);
2396 inst->disp_hash[i].func_name = (char *) loader_heap_alloc(inst,
2397 strlen(funcName) + 1,
2398 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
2399 if (inst->disp_hash[i].func_name == NULL) {
2400 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
2401 "loader_add_dev_ext_table() can't rallocate func_name memory");
2402 return false;
2403 }
2404 strncpy(inst->disp_hash[i].func_name, funcName, strlen(funcName) + 1);
2405 list->index[list->count] = i;
2406 list->count++;
2407 *ptr_idx = i;
2408 return true;
2409 }
2410 i = (i + 1) % MAX_NUM_DEV_EXTS;
2411 } while (i != idx);
2412
2413 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
2414 "loader_add_dev_ext_table() couldn't insert into hash table; is it full?");
2415 return false;
2416}
2417
2418static bool loader_name_in_dev_ext_table(struct loader_instance *inst,
2419 uint32_t *idx,
2420 const char *funcName)
2421{
2422 uint32_t alt_idx;
2423 if (inst->disp_hash[*idx].func_name && !strcmp(
2424 inst->disp_hash[*idx].func_name,
2425 funcName))
2426 return true;
2427
2428 // funcName wasn't at the primary spot in the hash table
2429 // search the list of secondary locations (shallow search, not deep search)
2430 for (uint32_t i = 0; i < inst->disp_hash[*idx].list.count; i++) {
2431 alt_idx = inst->disp_hash[*idx].list.index[i];
2432 if (!strcmp(inst->disp_hash[*idx].func_name, funcName)) {
2433 *idx = alt_idx;
2434 return true;
2435 }
2436 }
2437
2438 return false;
2439}
2440
2441/**
2442 * This function returns generic trampoline code address for unknown entry points.
2443 * Presumably, these unknown entry points (as given by funcName) are device
2444 * extension entrypoints. A hash table is used to keep a list of unknown entry
2445 * points and their mapping to the device extension dispatch table
2446 * (struct loader_dev_ext_dispatch_table).
2447 * \returns
2448 * For a given entry point string (funcName), if an existing mapping is found the
2449 * trampoline address for that mapping is returned. Otherwise, this unknown entry point
2450 * has not been seen yet. Next check if a layer or ICD supports it. If so then a
2451 * new entry in the hash table is initialized and that trampoline address for
2452 * the new entry is returned. Null is returned if the hash table is full or
2453 * if no discovered layer or ICD returns a non-NULL GetProcAddr for it.
2454 */
2455void *loader_dev_ext_gpa(struct loader_instance *inst,
2456 const char *funcName)
2457{
2458 uint32_t idx;
2459 uint32_t seed = 0;
2460
2461 idx = murmurhash(funcName, strlen(funcName), seed) % MAX_NUM_DEV_EXTS;
2462
2463 if (loader_name_in_dev_ext_table(inst, &idx, funcName))
2464 // found funcName already in hash
2465 return loader_get_dev_ext_trampoline(idx);
2466
2467 // Check if funcName is supported in either ICDs or a layer library
2468 if (!loader_check_icds_for_address(inst, funcName)) {
2469 // TODO Add check in layer libraries for support of address
2470 // if support found in layers continue on
2471 return NULL;
2472 }
2473
2474 if (loader_add_dev_ext_table(inst, &idx, funcName)) {
2475 // successfully added new table entry
2476 // init any dev dispatch table entrys as needed
2477 loader_init_dispatch_dev_ext_entry(inst, NULL, idx, funcName);
2478 return loader_get_dev_ext_trampoline(idx);
2479 }
2480
2481 return NULL;
2482}
2483
Jon Ashburne0e64572015-09-30 12:56:42 -06002484struct loader_instance *loader_get_instance(const VkInstance instance)
2485{
2486 /* look up the loader_instance in our list by comparing dispatch tables, as
2487 * there is no guarantee the instance is still a loader_instance* after any
2488 * layers which wrap the instance object.
2489 */
2490 const VkLayerInstanceDispatchTable *disp;
2491 struct loader_instance *ptr_instance = NULL;
2492 disp = loader_get_instance_dispatch(instance);
2493 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
2494 if (inst->disp == disp) {
2495 ptr_instance = inst;
2496 break;
2497 }
2498 }
2499 return ptr_instance;
2500}
2501
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002502static loader_platform_dl_handle loader_add_layer_lib(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002503 const struct loader_instance *inst,
Jon Ashburn4f67d742015-05-27 13:19:22 -06002504 const char *chain_type,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002505 struct loader_layer_properties *layer_prop)
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002506{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002507 struct loader_lib_info *new_layer_lib_list, *my_lib;
Jon Ashburne39a4f82015-08-28 13:38:21 -06002508 size_t new_alloc_size;
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -06002509 /*
2510 * TODO: We can now track this information in the
2511 * scanned_layer_libraries list.
2512 */
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002513 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) {
Jon Ashburn3d002332015-08-20 16:35:30 -06002514 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, layer_prop->lib_name) == 0) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002515 /* Have already loaded this library, just increment ref count */
2516 loader.loaded_layer_lib_list[i].ref_count++;
Courtney Goeltzenleuchterca8c81a2015-06-14 11:59:07 -06002517 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002518 "%s Chain: Increment layer reference count for layer library %s",
Jon Ashburn3d002332015-08-20 16:35:30 -06002519 chain_type, layer_prop->lib_name);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002520 return loader.loaded_layer_lib_list[i].lib_handle;
2521 }
2522 }
2523
2524 /* Haven't seen this library so load it */
Jon Ashburne39a4f82015-08-28 13:38:21 -06002525 new_alloc_size = 0;
2526 if (loader.loaded_layer_lib_capacity == 0)
2527 new_alloc_size = 8 * sizeof(struct loader_lib_info);
2528 else if (loader.loaded_layer_lib_capacity <= loader.loaded_layer_lib_count *
2529 sizeof(struct loader_lib_info))
2530 new_alloc_size = loader.loaded_layer_lib_capacity * 2;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002531
Jon Ashburne39a4f82015-08-28 13:38:21 -06002532 if (new_alloc_size) {
2533 new_layer_lib_list = loader_heap_realloc(
2534 inst, loader.loaded_layer_lib_list,
2535 loader.loaded_layer_lib_capacity,
2536 new_alloc_size,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002537 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburne39a4f82015-08-28 13:38:21 -06002538 if (!new_layer_lib_list) {
2539 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "loader: realloc failed in loader_add_layer_lib");
2540 return NULL;
2541 }
2542 loader.loaded_layer_lib_capacity = new_alloc_size;
2543 } else
2544 new_layer_lib_list = loader.loaded_layer_lib_list;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002545 my_lib = &new_layer_lib_list[loader.loaded_layer_lib_count];
2546
Jon Ashburn3d002332015-08-20 16:35:30 -06002547 strncpy(my_lib->lib_name, layer_prop->lib_name, sizeof(my_lib->lib_name));
2548 my_lib->lib_name[sizeof(my_lib->lib_name) - 1] = '\0';
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002549 my_lib->ref_count = 0;
2550 my_lib->lib_handle = NULL;
2551
2552 if ((my_lib->lib_handle = loader_platform_open_library(my_lib->lib_name)) == NULL) {
2553 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
2554 loader_platform_open_library_error(my_lib->lib_name));
2555 return NULL;
2556 } else {
Courtney Goeltzenleuchterca8c81a2015-06-14 11:59:07 -06002557 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002558 "Chain: %s: Loading layer library %s",
Jon Ashburn3d002332015-08-20 16:35:30 -06002559 chain_type, layer_prop->lib_name);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002560 }
2561 loader.loaded_layer_lib_count++;
2562 loader.loaded_layer_lib_list = new_layer_lib_list;
2563 my_lib->ref_count++;
2564
2565 return my_lib->lib_handle;
2566}
2567
2568static void loader_remove_layer_lib(
2569 struct loader_instance *inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002570 struct loader_layer_properties *layer_prop)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002571{
2572 uint32_t idx;
Tony Barbourb5d2c942015-07-14 13:34:05 -06002573 struct loader_lib_info *new_layer_lib_list, *my_lib = NULL;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002574
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002575 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) {
Jon Ashburn3d002332015-08-20 16:35:30 -06002576 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, layer_prop->lib_name) == 0) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002577 /* found matching library */
2578 idx = i;
2579 my_lib = &loader.loaded_layer_lib_list[i];
2580 break;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002581 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002582 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002583
Tony Barbourb5d2c942015-07-14 13:34:05 -06002584 if (my_lib) {
2585 my_lib->ref_count--;
2586 if (my_lib->ref_count > 0) {
2587 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Jon Ashburn3d002332015-08-20 16:35:30 -06002588 "Decrement reference count for layer library %s", layer_prop->lib_name);
Tony Barbourb5d2c942015-07-14 13:34:05 -06002589 return;
2590 }
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07002591 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002592 loader_platform_close_library(my_lib->lib_handle);
Courtney Goeltzenleuchterca8c81a2015-06-14 11:59:07 -06002593 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Jon Ashburn3d002332015-08-20 16:35:30 -06002594 "Unloading layer library %s", layer_prop->lib_name);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002595
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002596 /* Need to remove unused library from list */
Jon Ashburne39a4f82015-08-28 13:38:21 -06002597 new_layer_lib_list = loader_heap_alloc(inst,
2598 loader.loaded_layer_lib_capacity,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002599 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002600 if (!new_layer_lib_list) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06002601 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "loader: heap alloc failed loader_remove_layer_library");
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002602 return;
2603 }
2604
2605 if (idx > 0) {
2606 /* Copy records before idx */
2607 memcpy(new_layer_lib_list, &loader.loaded_layer_lib_list[0],
2608 sizeof(struct loader_lib_info) * idx);
2609 }
2610 if (idx < (loader.loaded_layer_lib_count - 1)) {
2611 /* Copy records after idx */
2612 memcpy(&new_layer_lib_list[idx], &loader.loaded_layer_lib_list[idx+1],
2613 sizeof(struct loader_lib_info) * (loader.loaded_layer_lib_count - idx - 1));
2614 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002615
Jon Ashburne39a4f82015-08-28 13:38:21 -06002616 loader_heap_free(inst, loader.loaded_layer_lib_list);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002617 loader.loaded_layer_lib_count--;
2618 loader.loaded_layer_lib_list = new_layer_lib_list;
Jon Ashburnb8358052014-11-18 09:06:04 -07002619}
2620
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002621
2622/**
2623 * Go through the search_list and find any layers which match type. If layer
2624 * type match is found in then add it to ext_list.
2625 */
2626//TODO need to handle implict layer enable env var and disable env var
Jon Ashburn0c26e712015-07-02 16:10:32 -06002627static void loader_add_layer_implicit(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002628 const struct loader_instance *inst,
Jon Ashburn0c26e712015-07-02 16:10:32 -06002629 const enum layer_type type,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002630 struct loader_layer_list *list,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002631 const struct loader_layer_list *search_list)
Jon Ashburn0c26e712015-07-02 16:10:32 -06002632{
2633 uint32_t i;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002634 for (i = 0; i < search_list->count; i++) {
2635 const struct loader_layer_properties *prop = &search_list->list[i];
Jon Ashburn0c26e712015-07-02 16:10:32 -06002636 if (prop->type & type) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002637 /* Found an layer with the same type, add to layer_list */
Jon Ashburne39a4f82015-08-28 13:38:21 -06002638 loader_add_to_layer_list(inst, list, 1, prop);
Jon Ashburn0c26e712015-07-02 16:10:32 -06002639 }
2640 }
2641
2642}
2643
2644/**
2645 * Get the layer name(s) from the env_name environment variable. If layer
Jon Ashburnbd332cc2015-07-07 10:27:45 -06002646 * is found in search_list then add it to layer_list. But only add it to
2647 * layer_list if type matches.
Jon Ashburn0c26e712015-07-02 16:10:32 -06002648 */
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002649static void loader_add_layer_env(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002650 const struct loader_instance *inst,
Jon Ashburnbd332cc2015-07-07 10:27:45 -06002651 const enum layer_type type,
Jon Ashburneb6d5682015-07-02 14:10:53 -06002652 const char *env_name,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002653 struct loader_layer_list *layer_list,
2654 const struct loader_layer_list *search_list)
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002655{
Ian Elliott4470a302015-02-17 10:33:47 -07002656 char *layerEnv;
Jon Ashburneb6d5682015-07-02 14:10:53 -06002657 char *next, *name;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002658
Jon Ashburneb6d5682015-07-02 14:10:53 -06002659 layerEnv = getenv(env_name);
Ian Elliott4470a302015-02-17 10:33:47 -07002660 if (layerEnv == NULL) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002661 return;
Ian Elliott4470a302015-02-17 10:33:47 -07002662 }
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -06002663 name = loader_stack_alloc(strlen(layerEnv) + 1);
Jon Ashburneb6d5682015-07-02 14:10:53 -06002664 if (name == NULL) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002665 return;
Ian Elliott4470a302015-02-17 10:33:47 -07002666 }
Jon Ashburneb6d5682015-07-02 14:10:53 -06002667 strcpy(name, layerEnv);
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002668
Jon Ashburneb6d5682015-07-02 14:10:53 -06002669 while (name && *name ) {
2670 next = loader_get_next_path(name);
Jon Ashburne39a4f82015-08-28 13:38:21 -06002671 loader_find_layer_name_add_list(inst, name, type, search_list, layer_list);
Jon Ashburneb6d5682015-07-02 14:10:53 -06002672 name = next;
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07002673 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002674
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002675 return;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002676}
2677
Courtney Goeltzenleuchter7d0023c2015-06-08 15:09:22 -06002678void loader_deactivate_instance_layers(struct loader_instance *instance)
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002679{
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002680 if (!instance->activated_layer_list.count) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002681 return;
2682 }
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002683
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002684 /* Create instance chain of enabled layers */
Courtney Goeltzenleuchter7d0023c2015-06-08 15:09:22 -06002685 for (uint32_t i = 0; i < instance->activated_layer_list.count; i++) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002686 struct loader_layer_properties *layer_prop = &instance->activated_layer_list.list[i];
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002687
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002688 loader_remove_layer_lib(instance, layer_prop);
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002689 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06002690 loader_destroy_layer_list(instance, &instance->activated_layer_list);
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002691}
2692
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002693VkResult loader_enable_instance_layers(
Jon Ashburnb82c1852015-08-11 14:49:54 -06002694 struct loader_instance *inst,
2695 const VkInstanceCreateInfo *pCreateInfo,
2696 const struct loader_layer_list *instance_layers)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002697{
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002698 VkResult err;
2699
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06002700 assert(inst && "Cannot have null instance");
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002701
Jon Ashburne39a4f82015-08-28 13:38:21 -06002702 if (!loader_init_layer_list(inst, &inst->activated_layer_list)) {
2703 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc Instance activated layer list");
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002704 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002705 }
2706
Jon Ashburn0c26e712015-07-02 16:10:32 -06002707 /* Add any implicit layers first */
2708 loader_add_layer_implicit(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002709 inst,
Jon Ashburn0c26e712015-07-02 16:10:32 -06002710 VK_LAYER_TYPE_INSTANCE_IMPLICIT,
2711 &inst->activated_layer_list,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002712 instance_layers);
Jon Ashburn0c26e712015-07-02 16:10:32 -06002713
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002714 /* Add any layers specified via environment variable next */
Jon Ashburneb6d5682015-07-02 14:10:53 -06002715 loader_add_layer_env(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002716 inst,
Jon Ashburnbd332cc2015-07-07 10:27:45 -06002717 VK_LAYER_TYPE_INSTANCE_EXPLICIT,
Jon Ashburneb6d5682015-07-02 14:10:53 -06002718 "VK_INSTANCE_LAYERS",
2719 &inst->activated_layer_list,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002720 instance_layers);
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002721
2722 /* Add layers specified by the application */
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002723 err = loader_add_layer_names_to_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002724 inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002725 &inst->activated_layer_list,
Chia-I Wud50a7d72015-10-26 20:48:51 +08002726 pCreateInfo->enabledLayerNameCount,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002727 pCreateInfo->ppEnabledLayerNames,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002728 instance_layers);
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002729
2730 return err;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002731}
2732
Jon Ashburn27cd5842015-05-12 17:26:48 -06002733uint32_t loader_activate_instance_layers(struct loader_instance *inst)
2734{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002735 uint32_t layer_idx;
Jon Ashburn128f9422015-05-28 19:16:58 -06002736 VkBaseLayerObject *wrappedInstance;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002737
David Pinedoa0a8a242015-06-24 15:29:18 -06002738 if (inst == NULL) {
Jon Ashburn27cd5842015-05-12 17:26:48 -06002739 return 0;
David Pinedoa0a8a242015-06-24 15:29:18 -06002740 }
Jon Ashburn27cd5842015-05-12 17:26:48 -06002741
2742 // NOTE inst is unwrapped at this point in time
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002743 void* baseObj = (void*) inst;
2744 void* nextObj = (void*) inst;
Jon Ashburn27cd5842015-05-12 17:26:48 -06002745 VkBaseLayerObject *nextInstObj;
2746 PFN_vkGetInstanceProcAddr nextGPA = loader_gpa_instance_internal;
2747
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002748 if (!inst->activated_layer_list.count) {
Courtney Goeltzenleuchtered1a8dd2015-08-07 09:53:18 -06002749 loader_init_instance_core_dispatch_table(inst->disp, nextGPA, (VkInstance) nextObj, (VkInstance) baseObj);
Jon Ashburn27cd5842015-05-12 17:26:48 -06002750 return 0;
2751 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002752
Courtney Goeltzenleuchter6f460c52015-07-06 09:04:55 -06002753 wrappedInstance = loader_stack_alloc(sizeof(VkBaseLayerObject)
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002754 * inst->activated_layer_list.count);
Jon Ashburn128f9422015-05-28 19:16:58 -06002755 if (!wrappedInstance) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06002756 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc Instance objects for layer");
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002757 return 0;
2758 }
2759
2760 /* Create instance chain of enabled layers */
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002761 layer_idx = inst->activated_layer_list.count - 1;
Courtney Goeltzenleuchter0f1d8eb2015-06-07 17:28:17 -06002762 for (int32_t i = inst->activated_layer_list.count - 1; i >= 0; i--) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002763 struct loader_layer_properties *layer_prop = &inst->activated_layer_list.list[i];
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002764 loader_platform_dl_handle lib_handle;
2765
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002766 /*
Courtney Goeltzenleuchteree3b16a2015-06-01 14:12:42 -06002767 * Note: An extension's Get*ProcAddr should not return a function pointer for
2768 * any extension entry points until the extension has been enabled.
2769 * To do this requires a different behavior from Get*ProcAddr functions implemented
2770 * in layers.
2771 * The very first call to a layer will be it's Get*ProcAddr function requesting
Tobin Ehlis1cb7f572015-10-06 09:09:24 -06002772 * the layer's vkGet*ProcAddr. The layer should initialize its internal dispatch table
Courtney Goeltzenleuchteree3b16a2015-06-01 14:12:42 -06002773 * with the wrapped object given (either Instance or Device) and return the layer's
2774 * Get*ProcAddr function. The layer should also use this opportunity to record the
2775 * baseObject so that it can find the correct local dispatch table on future calls.
2776 * Subsequent calls to Get*ProcAddr, CreateInstance, CreateDevice
2777 * will not use a wrapped object and must look up their local dispatch table from
2778 * the given baseObject.
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002779 */
Jon Ashburn128f9422015-05-28 19:16:58 -06002780 nextInstObj = (wrappedInstance + layer_idx);
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002781 nextInstObj->pGPA = (PFN_vkGPA) nextGPA;
Jon Ashburn27cd5842015-05-12 17:26:48 -06002782 nextInstObj->baseObject = baseObj;
2783 nextInstObj->nextObject = nextObj;
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002784 nextObj = (void*) nextInstObj;
Jon Ashburn27cd5842015-05-12 17:26:48 -06002785
Jon Ashburne39a4f82015-08-28 13:38:21 -06002786 lib_handle = loader_add_layer_lib(inst, "instance", layer_prop);
Jon Ashburnf72a04b2015-11-25 17:55:49 -07002787 if (!lib_handle)
2788 continue; // TODO what should we do in this case
Jon Ashburn21c21ee2015-09-09 11:29:24 -06002789 if ((nextGPA = layer_prop->functions.get_instance_proc_addr) == NULL) {
2790 if (layer_prop->functions.str_gipa == NULL || strlen(layer_prop->functions.str_gipa) == 0) {
2791 nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetInstanceProcAddr");
2792 layer_prop->functions.get_instance_proc_addr = nextGPA;
2793 } else
2794 nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gipa);
2795 if (!nextGPA) {
2796 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to find vkGetInstanceProcAddr in layer %s", layer_prop->lib_name);
Courtney Goeltzenleuchtera9e4af42015-06-01 14:49:17 -06002797
Jon Ashburn21c21ee2015-09-09 11:29:24 -06002798 /* TODO: Should we return nextObj, nextGPA to previous? or decrement layer_list count*/
2799 continue;
2800 }
Jon Ashburn27cd5842015-05-12 17:26:48 -06002801 }
2802
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002803 loader_log(VK_DBG_REPORT_INFO_BIT, 0,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002804 "Insert instance layer %s (%s)",
2805 layer_prop->info.layerName,
Jon Ashburn3d002332015-08-20 16:35:30 -06002806 layer_prop->lib_name);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002807
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002808 layer_idx--;
Jon Ashburn27cd5842015-05-12 17:26:48 -06002809 }
2810
Jon Ashburn8fd08252015-05-28 16:25:02 -06002811 loader_init_instance_core_dispatch_table(inst->disp, nextGPA, (VkInstance) nextObj, (VkInstance) baseObj);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002812
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002813 return inst->activated_layer_list.count;
Jon Ashburn27cd5842015-05-12 17:26:48 -06002814}
2815
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002816void loader_activate_instance_layer_extensions(struct loader_instance *inst)
2817{
2818
2819 loader_init_instance_extension_dispatch_table(inst->disp,
2820 inst->disp->GetInstanceProcAddr,
Jon Ashburn128f9422015-05-28 19:16:58 -06002821 (VkInstance) inst);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002822}
2823
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002824static VkResult loader_enable_device_layers(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002825 const struct loader_instance *inst,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002826 struct loader_icd *icd,
2827 struct loader_device *dev,
2828 const VkDeviceCreateInfo *pCreateInfo,
2829 const struct loader_layer_list *device_layers)
2830
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002831{
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002832 VkResult err;
2833
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06002834 assert(dev && "Cannot have null device");
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002835
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002836 if (dev->activated_layer_list.list == NULL || dev->activated_layer_list.capacity == 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06002837 loader_init_layer_list(inst, &dev->activated_layer_list);
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002838 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002839
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002840 if (dev->activated_layer_list.list == NULL) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06002841 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc device activated layer list");
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002842 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002843 }
2844
Jon Ashburn0c26e712015-07-02 16:10:32 -06002845 /* Add any implicit layers first */
2846 loader_add_layer_implicit(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002847 inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002848 VK_LAYER_TYPE_DEVICE_IMPLICIT,
2849 &dev->activated_layer_list,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002850 device_layers);
Jon Ashburn0c26e712015-07-02 16:10:32 -06002851
2852 /* Add any layers specified via environment variable next */
Jon Ashburneb6d5682015-07-02 14:10:53 -06002853 loader_add_layer_env(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002854 inst,
Jon Ashburnbd332cc2015-07-07 10:27:45 -06002855 VK_LAYER_TYPE_DEVICE_EXPLICIT,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002856 "VK_DEVICE_LAYERS",
2857 &dev->activated_layer_list,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002858 device_layers);
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002859
2860 /* Add layers specified by the application */
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002861 err = loader_add_layer_names_to_list(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002862 inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002863 &dev->activated_layer_list,
Chia-I Wud50a7d72015-10-26 20:48:51 +08002864 pCreateInfo->enabledLayerNameCount,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002865 pCreateInfo->ppEnabledLayerNames,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002866 device_layers);
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002867
2868 return err;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002869}
2870
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002871/*
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06002872 * This function terminates the device chain for CreateDevice.
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002873 * CreateDevice is a special case and so the loader call's
2874 * the ICD's CreateDevice before creating the chain. Since
2875 * we can't call CreateDevice twice we must terminate the
2876 * device chain with something else.
2877 */
Chia-I Wu9ab61502015-11-06 06:42:02 +08002878static VKAPI_ATTR VkResult VKAPI_CALL scratch_vkCreateDevice(
Jon Ashburn24cd4be2015-11-01 14:04:06 -07002879 VkPhysicalDevice physicalDevice,
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002880 const VkDeviceCreateInfo *pCreateInfo,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002881 const VkAllocationCallbacks* pAllocator,
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002882 VkDevice *pDevice)
2883{
2884 return VK_SUCCESS;
2885}
2886
Chia-I Wu9ab61502015-11-06 06:42:02 +08002887static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL loader_GetDeviceChainProcAddr(VkDevice device, const char * name)
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002888{
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002889 if (!strcmp(name, "vkGetDeviceProcAddr"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06002890 return (PFN_vkVoidFunction) loader_GetDeviceChainProcAddr;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002891 if (!strcmp(name, "vkCreateDevice"))
Courtney Goeltzenleuchter2d3ba632015-07-12 14:35:22 -06002892 return (PFN_vkVoidFunction) scratch_vkCreateDevice;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002893
Courtney Goeltzenleuchter3e029d12015-06-29 16:09:23 -06002894 struct loader_device *found_dev;
2895 struct loader_icd *icd = loader_get_icd_and_device(device, &found_dev);
2896 return icd->GetDeviceProcAddr(device, name);
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002897}
2898
Jon Ashburndc6fcad2015-06-10 10:06:06 -06002899static uint32_t loader_activate_device_layers(
Jon Ashburne39a4f82015-08-28 13:38:21 -06002900 const struct loader_instance *inst,
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002901 struct loader_device *dev,
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -06002902 VkDevice device)
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002903{
David Pinedoa0a8a242015-06-24 15:29:18 -06002904 if (!dev) {
Jon Ashburndc6fcad2015-06-10 10:06:06 -06002905 return 0;
David Pinedoa0a8a242015-06-24 15:29:18 -06002906 }
Jon Ashburn94e70492015-06-10 10:13:10 -06002907
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002908 /* activate any layer libraries */
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002909 void* nextObj = (void*) device;
2910 void* baseObj = nextObj;
Jon Ashburn94e70492015-06-10 10:13:10 -06002911 VkBaseLayerObject *nextGpuObj;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002912 PFN_vkGetDeviceProcAddr nextGPA = loader_GetDeviceChainProcAddr;
Jon Ashburn94e70492015-06-10 10:13:10 -06002913 VkBaseLayerObject *wrappedGpus;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002914
Courtney Goeltzenleuchtered1a8dd2015-08-07 09:53:18 -06002915 if (!dev->activated_layer_list.count) {
2916 loader_init_device_dispatch_table(&dev->loader_dispatch, nextGPA,
2917 (VkDevice) nextObj, (VkDevice) baseObj);
Jon Ashburn94e70492015-06-10 10:13:10 -06002918 return 0;
Courtney Goeltzenleuchtered1a8dd2015-08-07 09:53:18 -06002919 }
Jon Ashburn94e70492015-06-10 10:13:10 -06002920
Jon Ashburne39a4f82015-08-28 13:38:21 -06002921 wrappedGpus = loader_heap_alloc(inst,
2922 sizeof (VkBaseLayerObject) * dev->activated_layer_list.count,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08002923 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jon Ashburn94e70492015-06-10 10:13:10 -06002924 if (!wrappedGpus) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06002925 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc Gpu objects for layer");
Jon Ashburn94e70492015-06-10 10:13:10 -06002926 return 0;
2927 }
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002928
Jon Ashburn94e70492015-06-10 10:13:10 -06002929 for (int32_t i = dev->activated_layer_list.count - 1; i >= 0; i--) {
2930
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002931 struct loader_layer_properties *layer_prop = &dev->activated_layer_list.list[i];
Jon Ashburn94e70492015-06-10 10:13:10 -06002932 loader_platform_dl_handle lib_handle;
2933
Jon Ashburn94e70492015-06-10 10:13:10 -06002934 nextGpuObj = (wrappedGpus + i);
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002935 nextGpuObj->pGPA = (PFN_vkGPA)nextGPA;
Jon Ashburn94e70492015-06-10 10:13:10 -06002936 nextGpuObj->baseObject = baseObj;
2937 nextGpuObj->nextObject = nextObj;
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002938 nextObj = (void*) nextGpuObj;
Jon Ashburn94e70492015-06-10 10:13:10 -06002939
Jon Ashburne39a4f82015-08-28 13:38:21 -06002940 lib_handle = loader_add_layer_lib(inst, "device", layer_prop);
Jon Ashburn21c21ee2015-09-09 11:29:24 -06002941 if ((nextGPA = layer_prop->functions.get_device_proc_addr) == NULL) {
2942 if (layer_prop->functions.str_gdpa == NULL || strlen(layer_prop->functions.str_gdpa) == 0) {
2943 nextGPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetDeviceProcAddr");
2944 layer_prop->functions.get_device_proc_addr = nextGPA;
2945 } else
2946 nextGPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gdpa);
2947 if (!nextGPA) {
2948 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to find vkGetDeviceProcAddr in layer %s", layer_prop->lib_name);
2949 continue;
2950 }
Jon Ashburn94e70492015-06-10 10:13:10 -06002951 }
2952
2953 loader_log(VK_DBG_REPORT_INFO_BIT, 0,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002954 "Insert device layer library %s (%s)",
2955 layer_prop->info.layerName,
Jon Ashburn3d002332015-08-20 16:35:30 -06002956 layer_prop->lib_name);
Jon Ashburn94e70492015-06-10 10:13:10 -06002957
2958 }
2959
2960 loader_init_device_dispatch_table(&dev->loader_dispatch, nextGPA,
Tony Barbour1d2cd3f2015-07-03 10:33:54 -06002961 (VkDevice) nextObj, (VkDevice) baseObj);
Jon Ashburne39a4f82015-08-28 13:38:21 -06002962 loader_heap_free(inst, wrappedGpus);
Jon Ashburn94e70492015-06-10 10:13:10 -06002963
Jon Ashburndc6fcad2015-06-10 10:06:06 -06002964 return dev->activated_layer_list.count;
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002965}
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002966
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002967VkResult loader_validate_layers(
2968 const uint32_t layer_count,
2969 const char * const *ppEnabledLayerNames,
Jon Ashburn3d002332015-08-20 16:35:30 -06002970 const struct loader_layer_list *list)
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06002971{
2972 struct loader_layer_properties *prop;
2973
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002974 for (uint32_t i = 0; i < layer_count; i++) {
Jon Ashburne13ecc92015-08-03 17:19:30 -06002975 prop = loader_get_layer_property(ppEnabledLayerNames[i],
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002976 list);
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06002977 if (!prop) {
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06002978 return VK_ERROR_LAYER_NOT_PRESENT;
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06002979 }
2980 }
2981
2982 return VK_SUCCESS;
2983}
2984
2985VkResult loader_validate_instance_extensions(
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06002986 const struct loader_extension_list *icd_exts,
Jon Ashburnb82c1852015-08-11 14:49:54 -06002987 const struct loader_layer_list *instance_layer,
2988 const VkInstanceCreateInfo *pCreateInfo)
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06002989{
Jon Ashburn5c042ea2015-08-04 11:14:18 -06002990 VkExtensionProperties *extension_prop;
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002991 struct loader_layer_properties *layer_prop;
2992
Chia-I Wud50a7d72015-10-26 20:48:51 +08002993 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) {
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002994 extension_prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06002995 icd_exts);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002996
2997 if (extension_prop) {
2998 continue;
2999 }
3000
3001 extension_prop = NULL;
3002
3003 /* Not in global list, search layer extension lists */
Chia-I Wud50a7d72015-10-26 20:48:51 +08003004 for (uint32_t j = 0; j < pCreateInfo->enabledLayerNameCount; j++) {
Jon Ashburne13ecc92015-08-03 17:19:30 -06003005 layer_prop = loader_get_layer_property(pCreateInfo->ppEnabledLayerNames[i],
Jon Ashburnb82c1852015-08-11 14:49:54 -06003006 instance_layer);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003007 if (!layer_prop) {
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003008 /* Should NOT get here, loader_validate_layers
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003009 * should have already filtered this case out.
3010 */
3011 continue;
3012 }
3013
3014 extension_prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
3015 &layer_prop->instance_extension_list);
3016 if (extension_prop) {
3017 /* Found the extension in one of the layers enabled by the app. */
3018 break;
3019 }
3020 }
3021
3022 if (!extension_prop) {
3023 /* Didn't find extension name in any of the global layers, error out */
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06003024 return VK_ERROR_EXTENSION_NOT_PRESENT;
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003025 }
3026 }
3027 return VK_SUCCESS;
3028}
3029
3030VkResult loader_validate_device_extensions(
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003031 struct loader_physical_device *phys_dev,
Jon Ashburnb82c1852015-08-11 14:49:54 -06003032 const struct loader_layer_list *device_layer,
3033 const VkDeviceCreateInfo *pCreateInfo)
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003034{
Jon Ashburn5c042ea2015-08-04 11:14:18 -06003035 VkExtensionProperties *extension_prop;
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003036 struct loader_layer_properties *layer_prop;
3037
Chia-I Wud50a7d72015-10-26 20:48:51 +08003038 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) {
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003039 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i];
3040 extension_prop = get_extension_property(extension_name,
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003041 &phys_dev->device_extension_cache);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003042
3043 if (extension_prop) {
3044 continue;
3045 }
3046
3047 /* Not in global list, search layer extension lists */
Chia-I Wud50a7d72015-10-26 20:48:51 +08003048 for (uint32_t j = 0; j < pCreateInfo->enabledLayerNameCount; j++) {
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003049 const char *layer_name = pCreateInfo->ppEnabledLayerNames[j];
Jon Ashburne13ecc92015-08-03 17:19:30 -06003050 layer_prop = loader_get_layer_property(layer_name,
Jon Ashburnb82c1852015-08-11 14:49:54 -06003051 device_layer);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003052
3053 if (!layer_prop) {
3054 /* Should NOT get here, loader_validate_instance_layers
3055 * should have already filtered this case out.
3056 */
3057 continue;
3058 }
3059
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07003060 extension_prop = get_dev_extension_property(extension_name,
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003061 &layer_prop->device_extension_list);
3062 if (extension_prop) {
3063 /* Found the extension in one of the layers enabled by the app. */
3064 break;
3065 }
3066 }
3067
3068 if (!extension_prop) {
3069 /* Didn't find extension name in any of the device layers, error out */
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06003070 return VK_ERROR_EXTENSION_NOT_PRESENT;
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003071 }
3072 }
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06003073 return VK_SUCCESS;
3074}
3075
Chia-I Wu9ab61502015-11-06 06:42:02 +08003076VKAPI_ATTR VkResult VKAPI_CALL loader_CreateInstance(
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003077 const VkInstanceCreateInfo* pCreateInfo,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003078 const VkAllocationCallbacks* pAllocator,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003079 VkInstance* pInstance)
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003080{
Jon Ashburneed0c002015-05-21 17:42:17 -06003081 struct loader_instance *ptr_instance = *(struct loader_instance **) pInstance;
Jon Ashburn46888392015-01-29 15:45:51 -07003082 struct loader_icd *icd;
Jon Ashburn5c042ea2015-08-04 11:14:18 -06003083 VkExtensionProperties *prop;
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003084 char **filtered_extension_names = NULL;
3085 VkInstanceCreateInfo icd_create_info;
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06003086 VkResult res = VK_SUCCESS;
Jon Ashburn7e18de02015-11-19 09:29:51 -07003087 bool success = false;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003088
Tony Barbour3c78ff42015-12-04 13:24:39 -07003089 memcpy(&icd_create_info, pCreateInfo, sizeof(icd_create_info));
3090
Chia-I Wud50a7d72015-10-26 20:48:51 +08003091 icd_create_info.enabledLayerNameCount = 0;
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003092 icd_create_info.ppEnabledLayerNames = NULL;
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003093
3094 /*
3095 * NOTE: Need to filter the extensions to only those
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003096 * supported by the ICD.
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003097 * No ICD will advertise support for layers. An ICD
3098 * library could support a layer, but it would be
3099 * independent of the actual ICD, just in the same library.
3100 */
Chia-I Wud50a7d72015-10-26 20:48:51 +08003101 filtered_extension_names = loader_stack_alloc(pCreateInfo->enabledExtensionNameCount * sizeof(char *));
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003102 if (!filtered_extension_names) {
3103 return VK_ERROR_OUT_OF_HOST_MEMORY;
3104 }
3105 icd_create_info.ppEnabledExtensionNames = (const char * const *) filtered_extension_names;
3106
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003107 for (uint32_t i = 0; i < ptr_instance->icd_libs.count; i++) {
3108 icd = loader_icd_add(ptr_instance, &ptr_instance->icd_libs.list[i]);
Jon Ashburn46888392015-01-29 15:45:51 -07003109 if (icd) {
Chia-I Wud50a7d72015-10-26 20:48:51 +08003110 icd_create_info.enabledExtensionNameCount = 0;
3111 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) {
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003112 prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
Jon Ashburn5c6a46f2015-08-14 14:49:22 -06003113 &ptr_instance->ext_list);
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003114 if (prop) {
Chia-I Wud50a7d72015-10-26 20:48:51 +08003115 filtered_extension_names[icd_create_info.enabledExtensionNameCount] = (char *) pCreateInfo->ppEnabledExtensionNames[i];
3116 icd_create_info.enabledExtensionNameCount++;
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06003117 }
3118 }
3119
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003120 res = ptr_instance->icd_libs.list[i].CreateInstance(&icd_create_info,
Chia-I Wuf7458c52015-10-26 21:10:41 +08003121 pAllocator,
Jon Ashburn3da71f22015-05-14 12:43:38 -06003122 &(icd->instance));
Jon Ashburn7e18de02015-11-19 09:29:51 -07003123 if (res == VK_SUCCESS)
3124 success = loader_icd_init_entrys(
Jon Ashburnc624c882015-07-16 10:17:29 -06003125 icd,
3126 icd->instance,
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003127 ptr_instance->icd_libs.list[i].GetInstanceProcAddr);
Jon Ashburnc624c882015-07-16 10:17:29 -06003128
3129 if (res != VK_SUCCESS || !success)
Jon Ashburn46888392015-01-29 15:45:51 -07003130 {
3131 ptr_instance->icds = ptr_instance->icds->next;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003132 loader_icd_destroy(ptr_instance, icd);
Jon Ashburn3da71f22015-05-14 12:43:38 -06003133 icd->instance = VK_NULL_HANDLE;
Jon Ashburnc624c882015-07-16 10:17:29 -06003134 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
3135 "ICD ignored: failed to CreateInstance and find entrypoints with ICD");
Jon Ashburn46888392015-01-29 15:45:51 -07003136 }
3137 }
Jon Ashburn46888392015-01-29 15:45:51 -07003138 }
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003139
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06003140 /*
3141 * If no ICDs were added to instance list and res is unchanged
3142 * from it's initial value, the loader was unable to find
3143 * a suitable ICD.
3144 */
Ian Elliotteb450762015-02-05 15:19:15 -07003145 if (ptr_instance->icds == NULL) {
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06003146 if (res == VK_SUCCESS) {
3147 return VK_ERROR_INCOMPATIBLE_DRIVER;
3148 } else {
3149 return res;
3150 }
Ian Elliotteb450762015-02-05 15:19:15 -07003151 }
Jon Ashburn46888392015-01-29 15:45:51 -07003152
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06003153 return VK_SUCCESS;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003154}
3155
Chia-I Wu9ab61502015-11-06 06:42:02 +08003156VKAPI_ATTR void VKAPI_CALL loader_DestroyInstance(
Chia-I Wuf7458c52015-10-26 21:10:41 +08003157 VkInstance instance,
Chia-I Wu3432a0c2015-10-27 18:04:07 +08003158 const VkAllocationCallbacks* pAllocator)
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003159{
Courtney Goeltzenleuchterdeceded2015-06-08 15:04:02 -06003160 struct loader_instance *ptr_instance = loader_instance(instance);
Jon Ashburn3da71f22015-05-14 12:43:38 -06003161 struct loader_icd *icds = ptr_instance->icds;
Jon Ashburna6fd2612015-06-16 14:43:19 -06003162 struct loader_icd *next_icd;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003163
3164 // Remove this instance from the list of instances:
3165 struct loader_instance *prev = NULL;
3166 struct loader_instance *next = loader.instances;
3167 while (next != NULL) {
3168 if (next == ptr_instance) {
3169 // Remove this instance from the list:
3170 if (prev)
3171 prev->next = next->next;
Jon Ashburnc5c49602015-02-03 09:26:59 -07003172 else
3173 loader.instances = next->next;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003174 break;
3175 }
3176 prev = next;
3177 next = next->next;
3178 }
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003179
Jon Ashburn3da71f22015-05-14 12:43:38 -06003180 while (icds) {
3181 if (icds->instance) {
Chia-I Wuf7458c52015-10-26 21:10:41 +08003182 icds->DestroyInstance(icds->instance, pAllocator);
Tony Barbourf20f87b2015-04-22 09:02:32 -06003183 }
Jon Ashburna6fd2612015-06-16 14:43:19 -06003184 next_icd = icds->next;
Jon Ashburn3da71f22015-05-14 12:43:38 -06003185 icds->instance = VK_NULL_HANDLE;
Jon Ashburna6fd2612015-06-16 14:43:19 -06003186 loader_icd_destroy(ptr_instance, icds);
3187
3188 icds = next_icd;
Jon Ashburn46888392015-01-29 15:45:51 -07003189 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06003190 loader_delete_layer_properties(ptr_instance, &ptr_instance->device_layer_list);
3191 loader_delete_layer_properties(ptr_instance, &ptr_instance->instance_layer_list);
3192 loader_scanned_icd_clear(ptr_instance, &ptr_instance->icd_libs);
Jon Ashburn6e6a2162015-12-10 08:51:10 -07003193 loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *)
3194 &ptr_instance->ext_list);
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003195 for (uint32_t i = 0; i < ptr_instance->total_gpu_count; i++)
Jon Ashburn6e6a2162015-12-10 08:51:10 -07003196 loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *)
3197 &ptr_instance->phys_devs[i].device_extension_cache);
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003198 loader_heap_free(ptr_instance, ptr_instance->phys_devs);
Jon Ashburnfc1031e2015-11-17 15:31:02 -07003199 loader_free_dev_ext_table(ptr_instance);
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003200}
3201
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003202VkResult loader_init_physical_device_info(struct loader_instance *ptr_instance)
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003203{
3204 struct loader_icd *icd;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003205 uint32_t i, j, idx, count = 0;
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06003206 VkResult res;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003207 struct loader_phys_dev_per_icd *phys_devs;
3208
3209 ptr_instance->total_gpu_count = 0;
3210 phys_devs = (struct loader_phys_dev_per_icd *) loader_stack_alloc(
3211 sizeof(struct loader_phys_dev_per_icd) *
3212 ptr_instance->total_icd_count);
3213 if (!phys_devs)
3214 return VK_ERROR_OUT_OF_HOST_MEMORY;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003215
3216 icd = ptr_instance->icds;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003217 for (i = 0; i < ptr_instance->total_icd_count; i++) {
3218 assert(icd);
3219 res = icd->EnumeratePhysicalDevices(icd->instance, &phys_devs[i].count, NULL);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003220 if (res != VK_SUCCESS)
3221 return res;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003222 count += phys_devs[i].count;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003223 icd = icd->next;
3224 }
3225
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003226 ptr_instance->phys_devs = (struct loader_physical_device *) loader_heap_alloc(
3227 ptr_instance,
3228 count * sizeof(struct loader_physical_device),
3229 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
3230 if (!ptr_instance->phys_devs)
3231 return VK_ERROR_OUT_OF_HOST_MEMORY;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003232
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003233 icd = ptr_instance->icds;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003234
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003235 struct loader_physical_device *inst_phys_devs = ptr_instance->phys_devs;
3236 idx = 0;
3237 for (i = 0; i < ptr_instance->total_icd_count; i++) {
3238 assert(icd);
3239
3240 phys_devs[i].phys_devs = (VkPhysicalDevice *) loader_stack_alloc(
3241 phys_devs[i].count * sizeof(VkPhysicalDevice));
3242 if (!phys_devs[i].phys_devs) {
Jon Ashburn093ce202015-11-02 17:59:02 -07003243 loader_heap_free(ptr_instance, ptr_instance->phys_devs);
3244 ptr_instance->phys_devs = NULL;
Jon Ashburn128f9422015-05-28 19:16:58 -06003245 return VK_ERROR_OUT_OF_HOST_MEMORY;
3246 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003247 res = icd->EnumeratePhysicalDevices(
3248 icd->instance,
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003249 &(phys_devs[i].count),
3250 phys_devs[i].phys_devs);
3251 if ((res == VK_SUCCESS)) {
3252 ptr_instance->total_gpu_count += phys_devs[i].count;
3253 for (j = 0; j < phys_devs[i].count; j++) {
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003254
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003255 // initialize the loader's physicalDevice object
3256 loader_set_dispatch((void *) &inst_phys_devs[idx], ptr_instance->disp);
3257 inst_phys_devs[idx].this_instance = ptr_instance;
3258 inst_phys_devs[idx].this_icd = icd;
3259 inst_phys_devs[idx].phys_dev = phys_devs[i].phys_devs[j];
Jon Ashburn00eb6c02015-11-02 17:40:01 -07003260 memset(&inst_phys_devs[idx].device_extension_cache, 0, sizeof(struct loader_extension_list));
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003261
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003262 idx++;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003263 }
Jon Ashburn093ce202015-11-02 17:59:02 -07003264 } else {
3265 loader_heap_free(ptr_instance, ptr_instance->phys_devs);
3266 ptr_instance->phys_devs = NULL;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003267 return res;
Jon Ashburn093ce202015-11-02 17:59:02 -07003268 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003269
3270 icd = icd->next;
3271 }
3272
3273 return VK_SUCCESS;
3274}
3275
Chia-I Wu9ab61502015-11-06 06:42:02 +08003276VKAPI_ATTR VkResult VKAPI_CALL loader_EnumeratePhysicalDevices(
Courtney Goeltzenleuchter5e41f1d2015-04-20 12:48:54 -06003277 VkInstance instance,
3278 uint32_t* pPhysicalDeviceCount,
3279 VkPhysicalDevice* pPhysicalDevices)
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003280{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003281 uint32_t i;
Jon Ashburn4c392fb2015-01-28 19:57:09 -07003282 struct loader_instance *ptr_instance = (struct loader_instance *) instance;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003283 VkResult res = VK_SUCCESS;
Jon Ashburn4c392fb2015-01-28 19:57:09 -07003284
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003285 if (ptr_instance->total_gpu_count == 0) {
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003286 res = loader_init_physical_device_info(ptr_instance);
Jon Ashburn4c392fb2015-01-28 19:57:09 -07003287 }
3288
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003289 *pPhysicalDeviceCount = ptr_instance->total_gpu_count;
3290 if (!pPhysicalDevices) {
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003291 return res;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003292 }
Jon Ashburn4c392fb2015-01-28 19:57:09 -07003293
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003294 for (i = 0; i < ptr_instance->total_gpu_count; i++) {
3295 pPhysicalDevices[i] = (VkPhysicalDevice) &ptr_instance->phys_devs[i];
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003296 }
3297
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003298 return res;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07003299}
3300
Chia-I Wu9ab61502015-11-06 06:42:02 +08003301VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceProperties(
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003302 VkPhysicalDevice physicalDevice,
Tony Barbour59a47322015-06-24 16:06:58 -06003303 VkPhysicalDeviceProperties* pProperties)
Jon Ashburn3da71f22015-05-14 12:43:38 -06003304{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003305 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3306 struct loader_icd *icd = phys_dev->this_icd;
Jon Ashburn3da71f22015-05-14 12:43:38 -06003307
Tony Barbour59a47322015-06-24 16:06:58 -06003308 if (icd->GetPhysicalDeviceProperties)
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003309 icd->GetPhysicalDeviceProperties(phys_dev->phys_dev, pProperties);
Tony Barbour59a47322015-06-24 16:06:58 -06003310}
3311
Chia-I Wu9ab61502015-11-06 06:42:02 +08003312VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceQueueFamilyProperties (
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003313 VkPhysicalDevice physicalDevice,
Chia-I Wud50a7d72015-10-26 20:48:51 +08003314 uint32_t* pQueueFamilyPropertyCount,
Cody Northropd0802882015-08-03 17:04:53 -06003315 VkQueueFamilyProperties* pProperties)
Tony Barbour59a47322015-06-24 16:06:58 -06003316{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003317 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3318 struct loader_icd *icd = phys_dev->this_icd;
Tony Barbour59a47322015-06-24 16:06:58 -06003319
Cody Northropd0802882015-08-03 17:04:53 -06003320 if (icd->GetPhysicalDeviceQueueFamilyProperties)
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003321 icd->GetPhysicalDeviceQueueFamilyProperties(phys_dev->phys_dev, pQueueFamilyPropertyCount, pProperties);
Tony Barbour59a47322015-06-24 16:06:58 -06003322}
3323
Chia-I Wu9ab61502015-11-06 06:42:02 +08003324VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceMemoryProperties (
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003325 VkPhysicalDevice physicalDevice,
Tony Barbour59a47322015-06-24 16:06:58 -06003326 VkPhysicalDeviceMemoryProperties* pProperties)
3327{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003328 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3329 struct loader_icd *icd = phys_dev->this_icd;
Tony Barbour59a47322015-06-24 16:06:58 -06003330
3331 if (icd->GetPhysicalDeviceMemoryProperties)
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003332 icd->GetPhysicalDeviceMemoryProperties(phys_dev->phys_dev, pProperties);
Jon Ashburn3da71f22015-05-14 12:43:38 -06003333}
3334
Chia-I Wu9ab61502015-11-06 06:42:02 +08003335VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceFeatures(
Chris Forbesbc0bb772015-06-21 22:55:02 +12003336 VkPhysicalDevice physicalDevice,
3337 VkPhysicalDeviceFeatures* pFeatures)
3338{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003339 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3340 struct loader_icd *icd = phys_dev->this_icd;
Chris Forbesbc0bb772015-06-21 22:55:02 +12003341
3342 if (icd->GetPhysicalDeviceFeatures)
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003343 icd->GetPhysicalDeviceFeatures(phys_dev->phys_dev, pFeatures);
Chris Forbesbc0bb772015-06-21 22:55:02 +12003344}
3345
Chia-I Wu9ab61502015-11-06 06:42:02 +08003346VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceFormatProperties(
Chris Forbesbc0bb772015-06-21 22:55:02 +12003347 VkPhysicalDevice physicalDevice,
3348 VkFormat format,
3349 VkFormatProperties* pFormatInfo)
3350{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003351 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3352 struct loader_icd *icd = phys_dev->this_icd;
Chris Forbesbc0bb772015-06-21 22:55:02 +12003353
Courtney Goeltzenleuchter2caec862015-07-12 12:52:09 -06003354 if (icd->GetPhysicalDeviceFormatProperties)
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003355 icd->GetPhysicalDeviceFormatProperties(phys_dev->phys_dev, format, pFormatInfo);
Chris Forbesbc0bb772015-06-21 22:55:02 +12003356}
3357
Chia-I Wu9ab61502015-11-06 06:42:02 +08003358VKAPI_ATTR VkResult VKAPI_CALL loader_GetPhysicalDeviceImageFormatProperties(
Jon Ashburn754864f2015-07-23 18:49:07 -06003359 VkPhysicalDevice physicalDevice,
3360 VkFormat format,
3361 VkImageType type,
3362 VkImageTiling tiling,
3363 VkImageUsageFlags usage,
Courtney Goeltzenleuchtera22097a2015-09-10 13:44:12 -06003364 VkImageCreateFlags flags,
Jon Ashburn754864f2015-07-23 18:49:07 -06003365 VkImageFormatProperties* pImageFormatProperties)
3366{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003367 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3368 struct loader_icd *icd = phys_dev->this_icd;
Jon Ashburn754864f2015-07-23 18:49:07 -06003369
Chia-I Wu17241042015-10-31 00:31:16 +08003370 if (!icd->GetPhysicalDeviceImageFormatProperties)
3371 return VK_ERROR_INITIALIZATION_FAILED;
3372
3373 return icd->GetPhysicalDeviceImageFormatProperties(phys_dev->phys_dev, format,
3374 type, tiling, usage, flags, pImageFormatProperties);
Jon Ashburn754864f2015-07-23 18:49:07 -06003375}
3376
Chia-I Wu9ab61502015-11-06 06:42:02 +08003377VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceSparseImageFormatProperties(
Mark Lobodzinski16e8bef2015-07-03 15:58:09 -06003378 VkPhysicalDevice physicalDevice,
3379 VkFormat format,
3380 VkImageType type,
Chia-I Wu5c17c962015-10-31 00:31:16 +08003381 VkSampleCountFlagBits samples,
Mark Lobodzinski16e8bef2015-07-03 15:58:09 -06003382 VkImageUsageFlags usage,
3383 VkImageTiling tiling,
3384 uint32_t* pNumProperties,
3385 VkSparseImageFormatProperties* pProperties)
3386{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003387 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
3388 struct loader_icd *icd = phys_dev->this_icd;
Mark Lobodzinski16e8bef2015-07-03 15:58:09 -06003389
3390 if (icd->GetPhysicalDeviceSparseImageFormatProperties)
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003391 icd->GetPhysicalDeviceSparseImageFormatProperties(phys_dev->phys_dev, format, type, samples, usage, tiling, pNumProperties, pProperties);
Mark Lobodzinski16e8bef2015-07-03 15:58:09 -06003392}
3393
Chia-I Wu9ab61502015-11-06 06:42:02 +08003394VKAPI_ATTR VkResult VKAPI_CALL loader_CreateDevice(
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003395 VkPhysicalDevice physicalDevice,
Jon Ashburn95a77ba2015-05-15 15:09:35 -06003396 const VkDeviceCreateInfo* pCreateInfo,
Jon Ashburn46674bf2015-12-11 09:41:34 -07003397 const VkAllocationCallbacks* pAllocator,
Jon Ashburn95a77ba2015-05-15 15:09:35 -06003398 VkDevice* pDevice)
3399{
Jon Ashburn46674bf2015-12-11 09:41:34 -07003400 struct loader_physical_device *phys_dev;
3401 struct loader_icd *icd;
Jon Ashburndc6fcad2015-06-10 10:06:06 -06003402 struct loader_device *dev;
Jon Ashburnfc1031e2015-11-17 15:31:02 -07003403 struct loader_instance *inst;
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003404 VkDeviceCreateInfo device_create_info;
3405 char **filtered_extension_names = NULL;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003406 VkResult res;
Jon Ashburn95a77ba2015-05-15 15:09:35 -06003407
Chia-I Wu02124482015-11-06 06:42:02 +08003408 assert(pCreateInfo->queueCreateInfoCount >= 1);
Mark Lobodzinski0c29b922015-09-17 15:17:34 -06003409
Jon Ashburn46674bf2015-12-11 09:41:34 -07003410 //TODO this only works for one physical device per instance
3411 // once CreateDevice layer bootstrapping is done via DeviceCreateInfo
3412 // hopefully don't need this anymore in trampoline code
3413 phys_dev = loader_get_physical_device(physicalDevice);
3414 icd = phys_dev->this_icd;
Jon Ashburna4cf12b2015-10-26 16:54:51 -06003415 if (!icd)
3416 return VK_ERROR_INITIALIZATION_FAILED;
3417
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003418 inst = phys_dev->this_instance;
Jon Ashburna4cf12b2015-10-26 16:54:51 -06003419
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003420 if (!icd->CreateDevice) {
3421 return VK_ERROR_INITIALIZATION_FAILED;
Jon Ashburn95a77ba2015-05-15 15:09:35 -06003422 }
3423
Jon Ashburnb82c1852015-08-11 14:49:54 -06003424 /* validate any app enabled layers are available */
Chia-I Wud50a7d72015-10-26 20:48:51 +08003425 if (pCreateInfo->enabledLayerNameCount > 0) {
3426 res = loader_validate_layers(pCreateInfo->enabledLayerNameCount,
Jon Ashburnb82c1852015-08-11 14:49:54 -06003427 pCreateInfo->ppEnabledLayerNames,
Jon Ashburne39a4f82015-08-28 13:38:21 -06003428 &inst->device_layer_list);
Jon Ashburnb82c1852015-08-11 14:49:54 -06003429 if (res != VK_SUCCESS) {
3430 return res;
3431 }
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003432 }
3433
Jon Ashburn00eb6c02015-11-02 17:40:01 -07003434 /* Get the physical device extensions if they haven't been retrieved yet */
3435 if (phys_dev->device_extension_cache.capacity == 0) {
Jon Ashburn6e6a2162015-12-10 08:51:10 -07003436 if (!loader_init_generic_list(inst, (struct loader_generic_list *)
3437 &phys_dev->device_extension_cache,
3438 sizeof(VkExtensionProperties))) {
Jon Ashburn00eb6c02015-11-02 17:40:01 -07003439 return VK_ERROR_OUT_OF_HOST_MEMORY;
3440 }
3441 res = loader_add_physical_device_extensions(
3442 inst, physicalDevice,
3443 phys_dev->this_icd->this_icd_lib->lib_name,
3444 &phys_dev->device_extension_cache);
3445 if (res != VK_SUCCESS) {
3446 return res;
3447 }
3448 }
3449 /* make sure requested extensions to be enabled are supported */
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003450 res = loader_validate_device_extensions(phys_dev, &inst->device_layer_list, pCreateInfo);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06003451 if (res != VK_SUCCESS) {
3452 return res;
3453 }
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003454
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003455 /*
3456 * NOTE: Need to filter the extensions to only those
3457 * supported by the ICD.
3458 * No ICD will advertise support for layers. An ICD
3459 * library could support a layer, but it would be
3460 * independent of the actual ICD, just in the same library.
3461 */
Chia-I Wud50a7d72015-10-26 20:48:51 +08003462 filtered_extension_names = loader_stack_alloc(pCreateInfo->enabledExtensionNameCount * sizeof(char *));
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003463 if (!filtered_extension_names) {
3464 return VK_ERROR_OUT_OF_HOST_MEMORY;
3465 }
3466
3467 /* Copy user's data */
3468 memcpy(&device_create_info, pCreateInfo, sizeof(VkDeviceCreateInfo));
3469
3470 /* ICD's do not use layers */
Chia-I Wud50a7d72015-10-26 20:48:51 +08003471 device_create_info.enabledLayerNameCount = 0;
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003472 device_create_info.ppEnabledLayerNames = NULL;
3473
Chia-I Wud50a7d72015-10-26 20:48:51 +08003474 device_create_info.enabledExtensionNameCount = 0;
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003475 device_create_info.ppEnabledExtensionNames = (const char * const *) filtered_extension_names;
3476
Chia-I Wud50a7d72015-10-26 20:48:51 +08003477 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) {
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003478 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i];
Jon Ashburn5c042ea2015-08-04 11:14:18 -06003479 VkExtensionProperties *prop = get_extension_property(extension_name,
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003480 &phys_dev->device_extension_cache);
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003481 if (prop) {
Chia-I Wud50a7d72015-10-26 20:48:51 +08003482 filtered_extension_names[device_create_info.enabledExtensionNameCount] = (char *) extension_name;
3483 device_create_info.enabledExtensionNameCount++;
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06003484 }
3485 }
3486
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003487 // since physicalDevice object maybe wrapped by a layer need to get unwrapped version
Jon Ashburne0e64572015-09-30 12:56:42 -06003488 // we haven't yet called down the chain for the layer to unwrap the object
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003489 res = icd->CreateDevice(phys_dev->phys_dev, pCreateInfo, pAllocator, pDevice);
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003490 if (res != VK_SUCCESS) {
3491 return res;
3492 }
3493
Jon Ashburne39a4f82015-08-28 13:38:21 -06003494 dev = loader_add_logical_device(inst, *pDevice, &icd->logical_device_list);
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003495 if (dev == NULL) {
3496 return VK_ERROR_OUT_OF_HOST_MEMORY;
3497 }
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003498
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003499 loader_init_dispatch(*pDevice, &dev->loader_dispatch);
3500
Jon Ashburnb82c1852015-08-11 14:49:54 -06003501 /* activate any layers on device chain which terminates with device*/
Jon Ashburne39a4f82015-08-28 13:38:21 -06003502 res = loader_enable_device_layers(inst, icd, dev, pCreateInfo, &inst->device_layer_list);
Jon Ashburnb82c1852015-08-11 14:49:54 -06003503 if (res != VK_SUCCESS) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06003504 loader_destroy_logical_device(inst, dev);
Jon Ashburnb82c1852015-08-11 14:49:54 -06003505 return res;
3506 }
Jon Ashburne39a4f82015-08-28 13:38:21 -06003507 loader_activate_device_layers(inst, dev, *pDevice);
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003508
Jon Ashburnfc1031e2015-11-17 15:31:02 -07003509 /* finally can call down the chain */
3510 res = dev->loader_dispatch.core_dispatch.CreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
3511
Jon Ashburn54978592015-12-11 10:45:00 -07003512 /* initialize any device extension dispatch entry's from the instance list*/
3513 loader_init_dispatch_dev_ext(inst, dev);
3514
Jon Ashburn232e3af2015-11-30 17:21:25 -07003515 /* initialize WSI device extensions as part of core dispatch since loader has
3516 * dedicated trampoline code for these*/
3517 loader_init_device_extension_dispatch_table(&dev->loader_dispatch,
3518 dev->loader_dispatch.core_dispatch.GetDeviceProcAddr,
3519 *pDevice);
Jon Ashburnfc1031e2015-11-17 15:31:02 -07003520 dev->loader_dispatch.core_dispatch.CreateDevice = icd->CreateDevice;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06003521
Jon Ashburn95a77ba2015-05-15 15:09:35 -06003522 return res;
3523}
3524
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003525/**
3526 * Get an instance level or global level entry point address.
3527 * @param instance
3528 * @param pName
3529 * @return
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003530 * If instance == NULL returns a global level functions only
3531 * If instance is valid returns a trampoline entry point for all dispatchable Vulkan
3532 * functions both core and extensions.
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003533 */
Chia-I Wu9ab61502015-11-06 06:42:02 +08003534LOADER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char * pName)
Jon Ashburnb0fbe912015-05-06 10:15:07 -06003535{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003536
Jon Ashburn07daee72015-05-21 18:13:33 -06003537 void *addr;
Jon Ashburnb0fbe912015-05-06 10:15:07 -06003538
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003539 addr = globalGetProcAddr(pName);
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003540 if (instance == VK_NULL_HANDLE) {
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003541 // get entrypoint addresses that are global (no dispatchable object)
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003542
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003543 return addr;
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003544 } else {
3545 // if a global entrypoint return NULL
3546 if (addr)
3547 return NULL;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06003548 }
3549
Jon Ashburne0e64572015-09-30 12:56:42 -06003550 struct loader_instance *ptr_instance = loader_get_instance(instance);
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003551 if (ptr_instance == NULL)
Jon Ashburn07daee72015-05-21 18:13:33 -06003552 return NULL;
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003553 // Return trampoline code for non-global entrypoints including any extensions.
3554 // Device extensions are returned if a layer or ICD supports the extension.
3555 // Instance extensions are returned if the extension is enabled and the loader
3556 // or someone else supports the extension
3557 return trampolineGetProcAddr(ptr_instance, pName);
Jon Ashburn07daee72015-05-21 18:13:33 -06003558
Jon Ashburnb0fbe912015-05-06 10:15:07 -06003559}
3560
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003561/**
3562 * Get a device level or global level entry point address.
3563 * @param device
3564 * @param pName
3565 * @return
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003566 * If device is valid, returns a device relative entry point for device level
3567 * entry points both core and extensions.
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003568 * Device relative means call down the device chain.
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003569 */
Chia-I Wu9ab61502015-11-06 06:42:02 +08003570LOADER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char * pName)
Courtney Goeltzenleuchter9ec39ac2015-06-22 17:45:21 -06003571{
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003572 void *addr;
Courtney Goeltzenleuchter9ec39ac2015-06-22 17:45:21 -06003573
Jon Ashburn3d526cb2015-04-13 18:10:06 -06003574 /* for entrypoints that loader must handle (ie non-dispatchable or create object)
3575 make sure the loader entrypoint is returned */
Jon Ashburn69e9ea22015-09-28 16:15:00 -06003576 addr = loader_non_passthrough_gdpa(pName);
Ian Elliotte19c9152015-04-15 12:53:19 -06003577 if (addr) {
Jon Ashburn3d526cb2015-04-13 18:10:06 -06003578 return addr;
Ian Elliotte19c9152015-04-15 12:53:19 -06003579 }
Jon Ashburn3d526cb2015-04-13 18:10:06 -06003580
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003581 /* Although CreateDevice is on device chain it's dispatchable object isn't
3582 * a VkDevice or child of VkDevice so return NULL.
3583 */
3584 if (!strcmp(pName, "CreateDevice"))
3585 return NULL;
3586
Jon Ashburn3d526cb2015-04-13 18:10:06 -06003587 /* return the dispatch table entrypoint for the fastest case */
Jon Ashburn8d1b0b52015-05-18 13:20:15 -06003588 const VkLayerDispatchTable *disp_table = * (VkLayerDispatchTable **) device;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06003589 if (disp_table == NULL)
3590 return NULL;
3591
Jon Ashburn27cd5842015-05-12 17:26:48 -06003592 addr = loader_lookup_device_dispatch_table(disp_table, pName);
Chia-I Wuf46b81a2015-01-04 11:12:47 +08003593 if (addr)
3594 return addr;
Jon Ashburn8a39efc2015-11-06 11:02:40 -07003595
3596 if (disp_table->GetDeviceProcAddr == NULL)
3597 return NULL;
3598 return disp_table->GetDeviceProcAddr(device, pName);
Jon Ashburnd38bfb12014-10-14 19:15:22 -06003599}
3600
Chia-I Wu9ab61502015-11-06 06:42:02 +08003601LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003602 const char* pLayerName,
Chia-I Wud50a7d72015-10-26 20:48:51 +08003603 uint32_t* pPropertyCount,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003604 VkExtensionProperties* pProperties)
3605{
Jon Ashburn432d2762015-09-18 12:53:16 -06003606 struct loader_extension_list *global_ext_list=NULL;
Jon Ashburnb82c1852015-08-11 14:49:54 -06003607 struct loader_layer_list instance_layers;
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003608 struct loader_extension_list icd_extensions;
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003609 struct loader_icd_libs icd_libs;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003610 uint32_t copy_size;
3611
Jon Ashburn87d6aa92015-08-28 15:19:27 -06003612 tls_instance = NULL;
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003613 memset(&icd_extensions, 0, sizeof(icd_extensions));
Mike Stroyan09c06c72015-10-01 15:23:48 -06003614 memset(&instance_layers, 0, sizeof(instance_layers));
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003615 loader_platform_thread_once(&once_init, loader_initialize);
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003616
Jon Ashburnb82c1852015-08-11 14:49:54 -06003617 /* get layer libraries if needed */
3618 if (pLayerName && strlen(pLayerName) != 0) {
Jon Ashburne39a4f82015-08-28 13:38:21 -06003619 loader_layer_scan(NULL, &instance_layers, NULL);
Jon Ashburnb82c1852015-08-11 14:49:54 -06003620 for (uint32_t i = 0; i < instance_layers.count; i++) {
3621 struct loader_layer_properties *props = &instance_layers.list[i];
3622 if (strcmp(props->info.layerName, pLayerName) == 0) {
3623 global_ext_list = &props->instance_extension_list;
3624 }
3625 }
3626 }
3627 else {
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003628 /* Scan/discover all ICD libraries */
3629 memset(&icd_libs, 0 , sizeof(struct loader_icd_libs));
Jon Ashburne39a4f82015-08-28 13:38:21 -06003630 loader_icd_scan(NULL, &icd_libs);
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003631 /* get extensions from all ICD's, merge so no duplicates */
Jon Ashburne39a4f82015-08-28 13:38:21 -06003632 loader_get_icd_loader_instance_extensions(NULL, &icd_libs, &icd_extensions);
3633 loader_scanned_icd_clear(NULL, &icd_libs);
Jon Ashburn9a4c6aa2015-08-14 11:57:54 -06003634 global_ext_list = &icd_extensions;
Jon Ashburnb82c1852015-08-11 14:49:54 -06003635 }
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003636
Jon Ashburnb82c1852015-08-11 14:49:54 -06003637 if (global_ext_list == NULL) {
Mike Stroyan09c06c72015-10-01 15:23:48 -06003638 loader_destroy_layer_list(NULL, &instance_layers);
Courtney Goeltzenleuchter55659b72015-09-14 18:01:17 -06003639 return VK_ERROR_LAYER_NOT_PRESENT;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003640 }
3641
3642 if (pProperties == NULL) {
Chia-I Wud50a7d72015-10-26 20:48:51 +08003643 *pPropertyCount = global_ext_list->count;
Mike Stroyan09c06c72015-10-01 15:23:48 -06003644 loader_destroy_layer_list(NULL, &instance_layers);
Jon Ashburn6e6a2162015-12-10 08:51:10 -07003645 loader_destroy_generic_list(NULL, (struct loader_generic_list *)
3646 &icd_extensions);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003647 return VK_SUCCESS;
3648 }
3649
Chia-I Wud50a7d72015-10-26 20:48:51 +08003650 copy_size = *pPropertyCount < global_ext_list->count ? *pPropertyCount : global_ext_list->count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003651 for (uint32_t i = 0; i < copy_size; i++) {
3652 memcpy(&pProperties[i],
Jon Ashburnb82c1852015-08-11 14:49:54 -06003653 &global_ext_list->list[i],
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003654 sizeof(VkExtensionProperties));
3655 }
Chia-I Wud50a7d72015-10-26 20:48:51 +08003656 *pPropertyCount = copy_size;
Jon Ashburn6e6a2162015-12-10 08:51:10 -07003657 loader_destroy_generic_list(NULL, (struct loader_generic_list *)
3658 &icd_extensions);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003659
Jon Ashburnb82c1852015-08-11 14:49:54 -06003660 if (copy_size < global_ext_list->count) {
Mike Stroyan09c06c72015-10-01 15:23:48 -06003661 loader_destroy_layer_list(NULL, &instance_layers);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003662 return VK_INCOMPLETE;
3663 }
3664
Mike Stroyan09c06c72015-10-01 15:23:48 -06003665 loader_destroy_layer_list(NULL, &instance_layers);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003666 return VK_SUCCESS;
3667}
3668
Chia-I Wu9ab61502015-11-06 06:42:02 +08003669LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(
Chia-I Wud50a7d72015-10-26 20:48:51 +08003670 uint32_t* pPropertyCount,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003671 VkLayerProperties* pProperties)
Tony Barbour59a47322015-06-24 16:06:58 -06003672{
Jon Ashburn6301a0f2015-05-29 13:15:39 -06003673
Jon Ashburnb82c1852015-08-11 14:49:54 -06003674 struct loader_layer_list instance_layer_list;
Jon Ashburn87d6aa92015-08-28 15:19:27 -06003675 tls_instance = NULL;
Jon Ashburnb82c1852015-08-11 14:49:54 -06003676
Jon Ashburn8810c5f2015-08-18 18:04:47 -06003677 loader_platform_thread_once(&once_init, loader_initialize);
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07003678
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003679 uint32_t copy_size;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06003680
Jon Ashburnb82c1852015-08-11 14:49:54 -06003681 /* get layer libraries */
3682 memset(&instance_layer_list, 0, sizeof(instance_layer_list));
Jon Ashburne39a4f82015-08-28 13:38:21 -06003683 loader_layer_scan(NULL, &instance_layer_list, NULL);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003684
3685 if (pProperties == NULL) {
Chia-I Wud50a7d72015-10-26 20:48:51 +08003686 *pPropertyCount = instance_layer_list.count;
Jon Ashburne39a4f82015-08-28 13:38:21 -06003687 loader_destroy_layer_list(NULL, &instance_layer_list);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003688 return VK_SUCCESS;
3689 }
3690
Chia-I Wud50a7d72015-10-26 20:48:51 +08003691 copy_size = (*pPropertyCount < instance_layer_list.count) ? *pPropertyCount : instance_layer_list.count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003692 for (uint32_t i = 0; i < copy_size; i++) {
Jon Ashburnb82c1852015-08-11 14:49:54 -06003693 memcpy(&pProperties[i], &instance_layer_list.list[i].info, sizeof(VkLayerProperties));
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003694 }
Chia-I Wud50a7d72015-10-26 20:48:51 +08003695 *pPropertyCount = copy_size;
Jon Ashburne39a4f82015-08-28 13:38:21 -06003696 loader_destroy_layer_list(NULL, &instance_layer_list);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003697
Jon Ashburnb82c1852015-08-11 14:49:54 -06003698 if (copy_size < instance_layer_list.count) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003699 return VK_INCOMPLETE;
3700 }
Tony Barbour59a47322015-06-24 16:06:58 -06003701
3702 return VK_SUCCESS;
3703}
3704
Chia-I Wu9ab61502015-11-06 06:42:02 +08003705VKAPI_ATTR VkResult VKAPI_CALL loader_EnumerateDeviceExtensionProperties(
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003706 VkPhysicalDevice physicalDevice,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003707 const char* pLayerName,
Chia-I Wud50a7d72015-10-26 20:48:51 +08003708 uint32_t* pPropertyCount,
Tony Barbour59a47322015-06-24 16:06:58 -06003709 VkExtensionProperties* pProperties)
3710{
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003711 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003712 uint32_t copy_size;
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07003713
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003714 uint32_t count;
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07003715 struct loader_device_extension_list *dev_ext_list=NULL;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003716
Jon Ashburnb82c1852015-08-11 14:49:54 -06003717 /* get layer libraries if needed */
3718 if (pLayerName && strlen(pLayerName) != 0) {
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003719 for (uint32_t i = 0; i < phys_dev->this_instance->device_layer_list.count; i++) {
3720 struct loader_layer_properties *props = &phys_dev->this_instance->device_layer_list.list[i];
Jon Ashburnb82c1852015-08-11 14:49:54 -06003721 if (strcmp(props->info.layerName, pLayerName) == 0) {
3722 dev_ext_list = &props->device_extension_list;
3723 }
3724 }
3725 }
3726 else {
Jon Ashburn00eb6c02015-11-02 17:40:01 -07003727 /* this case is during the call down the instance chain */
3728 struct loader_icd *icd = phys_dev->this_icd;
3729 VkResult res;
3730 res = icd->EnumerateDeviceExtensionProperties(phys_dev->phys_dev, NULL, pPropertyCount, pProperties);
3731 if (pProperties != NULL && res == VK_SUCCESS) {
3732 /* initialize dev_extension list within the physicalDevice object */
3733 res = loader_init_physical_device_extensions(phys_dev->this_instance,
3734 phys_dev, *pPropertyCount, pProperties,
3735 &phys_dev->device_extension_cache);
3736 }
3737 return res;
Jon Ashburnb82c1852015-08-11 14:49:54 -06003738 }
3739
Jon Ashburn432d2762015-09-18 12:53:16 -06003740 count = (dev_ext_list == NULL) ? 0: dev_ext_list->count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003741 if (pProperties == NULL) {
Chia-I Wud50a7d72015-10-26 20:48:51 +08003742 *pPropertyCount = count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003743 return VK_SUCCESS;
3744 }
3745
Chia-I Wud50a7d72015-10-26 20:48:51 +08003746 copy_size = *pPropertyCount < count ? *pPropertyCount : count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003747 for (uint32_t i = 0; i < copy_size; i++) {
3748 memcpy(&pProperties[i],
Jon Ashburn39fbd4e2015-12-10 18:17:34 -07003749 &dev_ext_list->list[i].props,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003750 sizeof(VkExtensionProperties));
3751 }
Chia-I Wud50a7d72015-10-26 20:48:51 +08003752 *pPropertyCount = copy_size;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003753
3754 if (copy_size < count) {
3755 return VK_INCOMPLETE;
3756 }
3757
3758 return VK_SUCCESS;
3759}
3760
Chia-I Wu9ab61502015-11-06 06:42:02 +08003761VKAPI_ATTR VkResult VKAPI_CALL loader_EnumerateDeviceLayerProperties(
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003762 VkPhysicalDevice physicalDevice,
Chia-I Wud50a7d72015-10-26 20:48:51 +08003763 uint32_t* pPropertyCount,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003764 VkLayerProperties* pProperties)
3765{
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003766 uint32_t copy_size;
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003767 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003768
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003769 uint32_t count = phys_dev->this_instance->device_layer_list.count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003770
3771 if (pProperties == NULL) {
Chia-I Wud50a7d72015-10-26 20:48:51 +08003772 *pPropertyCount = count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003773 return VK_SUCCESS;
3774 }
3775
Chia-I Wud50a7d72015-10-26 20:48:51 +08003776 copy_size = (*pPropertyCount < count) ? *pPropertyCount : count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003777 for (uint32_t i = 0; i < copy_size; i++) {
Jon Ashburn24cd4be2015-11-01 14:04:06 -07003778 memcpy(&pProperties[i], &(phys_dev->this_instance->device_layer_list.list[i].info), sizeof(VkLayerProperties));
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003779 }
Chia-I Wud50a7d72015-10-26 20:48:51 +08003780 *pPropertyCount = copy_size;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003781
3782 if (copy_size < count) {
3783 return VK_INCOMPLETE;
3784 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003785
3786 return VK_SUCCESS;
Jon Ashburn95a77ba2015-05-15 15:09:35 -06003787}