blob: 9c72502450db22d8ba7422b628af4718519f6fd2 [file] [log] [blame]
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001/*
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06002 * Vulkan
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08003 *
4 * Copyright (C) 2014 LunarG, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
Chia-I Wu701f3f62014-09-02 08:32:09 +080023 *
24 * Authors:
25 * Chia-I Wu <olv@lunarg.com>
Jon Ashburn01e2d662014-11-14 09:52:42 -070026 * Jon Ashburn <jon@lunarg.com>
Chia-I Wu701f3f62014-09-02 08:32:09 +080027 * Courtney Goeltzenleuchter <courtney@lunarg.com>
Ian Elliott5aa4ea22015-03-31 15:32:41 -060028 * Ian Elliott <ian@lunarg.com>
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080029 */
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>
Ian Elliott2d4ab1e2015-01-13 17:52:38 -070038#if defined(WIN32)
39#include "dirent_on_windows.h"
40#else // WIN32
Chia-I Wu13a61a52014-08-04 11:18:20 +080041#include <dirent.h>
Ian Elliott2d4ab1e2015-01-13 17:52:38 -070042#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 Ashburn07daee72015-05-21 18:13:33 -060045#include "wsi_lunarg.h"
Jon Ashburn27cd5842015-05-12 17:26:48 -060046#include "gpa_helper.h"
47#include "table_ops.h"
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -060048#include "debug_report.h"
Tobin Ehlis0c6f9ee2015-07-03 09:42:57 -060049#include "vk_icd.h"
Jon Ashburn2077e382015-06-29 11:25:34 -060050#include "cJSON.h"
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080051
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -060052void loader_add_to_ext_list(
53 struct loader_extension_list *ext_list,
54 uint32_t prop_list_count,
55 const struct loader_extension_property *prop_list);
56
Courtney Goeltzenleuchtered488302015-06-01 14:09:34 -060057static loader_platform_dl_handle loader_add_layer_lib(
58 const char *chain_type,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -060059 struct loader_layer_properties *layer_prop);
Courtney Goeltzenleuchtered488302015-06-01 14:09:34 -060060
61static void loader_remove_layer_lib(
62 struct loader_instance *inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -060063 struct loader_layer_properties *layer_prop);
Courtney Goeltzenleuchtered488302015-06-01 14:09:34 -060064
Jon Ashburn27cd5842015-05-12 17:26:48 -060065struct loader_struct loader = {0};
Chia-I Wu5f72d0f2014-08-01 11:21:23 +080066
Courtney Goeltzenleuchter9ec39ac2015-06-22 17:45:21 -060067static void * VKAPI loader_GetInstanceProcAddr(VkInstance instance, const char * pName);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -060068static bool loader_init_ext_list(struct loader_extension_list *ext_info);
Courtney Goeltzenleuchter9ec39ac2015-06-22 17:45:21 -060069
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -060070enum loader_debug {
71 LOADER_INFO_BIT = VK_BIT(0),
72 LOADER_WARN_BIT = VK_BIT(1),
73 LOADER_PERF_BIT = VK_BIT(2),
74 LOADER_ERROR_BIT = VK_BIT(3),
75 LOADER_DEBUG_BIT = VK_BIT(4),
76};
77
78uint32_t g_loader_debug = 0;
79uint32_t g_loader_log_msgs = 0;
80
Jon Ashburn6301a0f2015-05-29 13:15:39 -060081//thread safety lock for accessing global data structures such as "loader"
82// all entrypoints on the instance chain need to be locked except GPA
Jon Ashburn2077e382015-06-29 11:25:34 -060083// additionally CreateDevice and DestroyDevice needs to be locked
Jon Ashburn6301a0f2015-05-29 13:15:39 -060084loader_platform_thread_mutex loader_lock;
85
86const VkLayerInstanceDispatchTable instance_disp = {
Courtney Goeltzenleuchter9ec39ac2015-06-22 17:45:21 -060087 .GetInstanceProcAddr = loader_GetInstanceProcAddr,
Jon Ashburn27cd5842015-05-12 17:26:48 -060088 .CreateInstance = loader_CreateInstance,
89 .DestroyInstance = loader_DestroyInstance,
90 .EnumeratePhysicalDevices = loader_EnumeratePhysicalDevices,
Chris Forbesbc0bb772015-06-21 22:55:02 +120091 .GetPhysicalDeviceFeatures = loader_GetPhysicalDeviceFeatures,
92 .GetPhysicalDeviceFormatInfo = loader_GetPhysicalDeviceFormatInfo,
93 .GetPhysicalDeviceLimits = loader_GetPhysicalDeviceLimits,
Tony Barbour59a47322015-06-24 16:06:58 -060094 .GetPhysicalDeviceProperties = loader_GetPhysicalDeviceProperties,
95 .GetPhysicalDevicePerformance = loader_GetPhysicalDevicePerformance,
96 .GetPhysicalDeviceQueueCount = loader_GetPhysicalDeviceQueueCount,
97 .GetPhysicalDeviceQueueProperties = loader_GetPhysicalDeviceQueueProperties,
98 .GetPhysicalDeviceMemoryProperties = loader_GetPhysicalDeviceMemoryProperties,
Tony Barbour59a47322015-06-24 16:06:58 -060099 .GetPhysicalDeviceExtensionProperties = loader_GetPhysicalDeviceExtensionProperties,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600100 .GetPhysicalDeviceLayerProperties = loader_GetPhysicalDeviceLayerProperties,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600101 .DbgCreateMsgCallback = loader_DbgCreateMsgCallback,
102 .DbgDestroyMsgCallback = loader_DbgDestroyMsgCallback,
Jon Ashburn27cd5842015-05-12 17:26:48 -0600103};
104
105LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_icd);
106LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_layer);
107LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_exts);
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700108
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600109void* loader_heap_alloc(
110 struct loader_instance *instance,
111 size_t size,
112 VkSystemAllocType alloc_type)
113{
114 if (instance && instance->alloc_callbacks.pfnAlloc) {
115 /* TODO: What should default alignment be? 1, 4, 8, other? */
116 return instance->alloc_callbacks.pfnAlloc(instance->alloc_callbacks.pUserData, size, 4, alloc_type);
117 }
118 return malloc(size);
119}
120
121void* loader_aligned_heap_alloc(
122 struct loader_instance *instance,
123 size_t size,
124 size_t alignment,
125 VkSystemAllocType alloc_type)
126{
127 if (!instance && instance->alloc_callbacks.pfnAlloc) {
128 return instance->alloc_callbacks.pfnAlloc(instance->alloc_callbacks.pUserData, size, alignment, alloc_type);
129 }
Cody Northrop33fa0412015-07-08 16:48:37 -0600130#if defined(_WIN32)
131 return _aligned_malloc(alignment, size);
132#else
133 return aligned_alloc(alignment, size);
134#endif
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600135}
136
137void loader_heap_free(
138 struct loader_instance *instance,
139 void *pMem)
140{
141 if (!instance && instance->alloc_callbacks.pfnFree) {
142 return instance->alloc_callbacks.pfnFree(instance->alloc_callbacks.pUserData, pMem);
143 }
144 return free(pMem);
145}
146
Jon Ashburnffad94d2015-06-30 14:46:22 -0700147static void loader_log(VkFlags msg_type, int32_t msg_code,
148 const char *format, ...)
149{
150 char msg[256];
151 va_list ap;
152 int ret;
153
154 if (!(msg_type & g_loader_log_msgs)) {
155 return;
156 }
157
158 va_start(ap, format);
159 ret = vsnprintf(msg, sizeof(msg), format, ap);
160 if ((ret >= (int) sizeof(msg)) || ret < 0) {
161 msg[sizeof(msg)-1] = '\0';
162 }
163 va_end(ap);
164
Ian Elliott4470a302015-02-17 10:33:47 -0700165#if defined(WIN32)
Jon Ashburnffad94d2015-06-30 14:46:22 -0700166 OutputDebugString(msg);
167#endif
168 fputs(msg, stderr);
169 fputc('\n', stderr);
170}
171
172#if defined(WIN32)
173/**
174* Find the list of registry files (names within a key) in key "location".
175*
176* This function looks in the registry (hive = DEFAULT_VK_REGISTRY_HIVE) key as given in "location"
177* for a list or name/values which are added to a returned list (function return value).
178* The DWORD values within the key must be 0 or they are skipped.
179* Function return is a string with a ';' seperated list of filenames.
180* Function return is NULL if no valid name/value pairs are found in the key,
181* or the key is not found.
182*
183* \returns
184* A string list of filenames as pointer.
185* When done using the returned string list, pointer should be freed.
186*/
187static char *loader_get_registry_files(const char *location)
188{
189 LONG rtn_value;
190 HKEY hive, key;
191 DWORD access_flags = KEY_QUERY_VALUE;
192 char name[2048];
193 char *out = NULL;
194
195 hive = DEFAULT_VK_REGISTRY_HIVE;
196 rtn_value = RegOpenKeyEx(hive, location, 0, access_flags, &key);
197 if (rtn_value != ERROR_SUCCESS) {
198 // We didn't find the key. Try the 32-bit hive (where we've seen the
199 // key end up on some people's systems):
200 access_flags |= KEY_WOW64_32KEY;
201 rtn_value = RegOpenKeyEx(hive, location, 0, access_flags, &key);
202 if (rtn_value != ERROR_SUCCESS) {
203 // We still couldn't find the key, so give up:
204 return NULL;
205 }
206 }
207
208 DWORD idx = 0;
209 DWORD name_size = sizeof(name);
210 DWORD value;
211 DWORD total_size = 4096;
212 DWORD value_size = sizeof(value);
213 while((rtn_value = RegEnumValue(key, idx++, name, &name_size, NULL, NULL, (LPBYTE) &value, &value_size)) == ERROR_SUCCESS) {
214 if (value_size == sizeof(value) && value == 0) {
215 if (out == NULL) {
216 out = malloc(total_size);
217 out[0] = '\0';
218 }
219 else if (strlen(out) + name_size + 1 > total_size) {
220 out = realloc(out, total_size * 2);
221 total_size *= 2;
222 }
223 if (out == NULL) {
224 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory, failed loader_get_registry_files");
225 return NULL;
226 }
227 if (strlen(out) == 0)
228 snprintf(out, name_size + 1, "%s", name);
229 else
230 snprintf(out + strlen(out), name_size + 1, "%c%s", PATH_SEPERATOR, name);
231 }
232 }
233 return out;
234}
235
Ian Elliott4470a302015-02-17 10:33:47 -0700236#endif // WIN32
237
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600238bool compare_vk_extension_properties(const VkExtensionProperties *op1, const VkExtensionProperties *op2)
239{
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600240 return strcmp(op1->extName, op2->extName) == 0 ? true : false;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600241}
242
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -0600243/**
Jon Ashburnbd6c4882015-07-02 12:59:25 -0600244 * Search the given ext_array for an extension
245 * matching the given vk_ext_prop
246 */
247bool has_vk_extension_property_array(
248 const VkExtensionProperties *vk_ext_prop,
249 const uint32_t count,
250 const VkExtensionProperties *ext_array)
251{
252 for (uint32_t i = 0; i < count; i++) {
253 if (compare_vk_extension_properties(vk_ext_prop, &ext_array[i]))
254 return true;
255 }
256 return false;
257}
258
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -0600259/**
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600260 * Search the given ext_list for an extension
261 * matching the given vk_ext_prop
262 */
263bool has_vk_extension_property(
264 const VkExtensionProperties *vk_ext_prop,
265 const struct loader_extension_list *ext_list)
266{
267 for (uint32_t i = 0; i < ext_list->count; i++) {
268 if (compare_vk_extension_properties(&ext_list->list[i].info, vk_ext_prop))
269 return true;
270 }
271 return false;
272}
273
274/*
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -0600275 * Search the given layer list for a layer matching the given layer name
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600276 */
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600277static struct loader_layer_properties *get_layer_property(
278 const char *name,
279 const struct loader_layer_list *layer_list)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600280{
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600281 for (uint32_t i = 0; i < layer_list->count; i++) {
282 const VkLayerProperties *item = &layer_list->list[i].info;
283 if (strcmp(name, item->layerName) == 0)
284 return &layer_list->list[i];
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600285 }
286 return NULL;
287}
288
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600289static void loader_add_global_extensions(
Tony Barbour59a47322015-06-24 16:06:58 -0600290 const PFN_vkGetGlobalExtensionProperties fp_get_props,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600291 const char *lib_name,
Jon Ashburn953bb3c2015-06-10 16:11:42 -0600292 const loader_platform_dl_handle lib_handle,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600293 const enum extension_origin origin,
294 struct loader_extension_list *ext_list)
295{
296 uint32_t i, count;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600297 struct loader_extension_property ext_props;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600298 VkExtensionProperties *extension_properties;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600299 VkResult res;
300
Courtney Goeltzenleuchter5c6cf472015-07-06 22:28:18 -0600301 if (!fp_get_props) {
302 /* No GetGlobalExtensionProperties defined */
303 return;
304 }
305
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600306 res = fp_get_props(NULL, &count, NULL);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600307 if (res != VK_SUCCESS) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600308 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Error getting global extension count from %s", lib_name);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600309 return;
310 }
Jon Ashburn953bb3c2015-06-10 16:11:42 -0600311
Courtney Goeltzenleuchter5c6cf472015-07-06 22:28:18 -0600312 if (count == 0) {
313 /* No ExtensionProperties to report */
314 return;
315 }
316
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600317 extension_properties = loader_stack_alloc(count * sizeof(VkExtensionProperties));
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600318
319 res = fp_get_props(NULL, &count, extension_properties);
320 if (res != VK_SUCCESS) {
321 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Error getting global extensions from %s", lib_name);
322 return;
323 }
Tony Barbour59a47322015-06-24 16:06:58 -0600324
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600325 for (i = 0; i < count; i++) {
Courtney Goeltzenleuchter0f1d8eb2015-06-07 17:28:17 -0600326 memset(&ext_props, 0, sizeof(ext_props));
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600327 memcpy(&ext_props.info, &extension_properties[i], sizeof(VkExtensionProperties));
328 //TODO eventually get this from the layer config file
329 ext_props.origin = origin;
330 ext_props.lib_name = lib_name;
Jon Ashburn953bb3c2015-06-10 16:11:42 -0600331
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600332 char spec_version[64], version[64];
333
334 snprintf(spec_version, sizeof(spec_version), "%d.%d.%d",
335 VK_MAJOR(ext_props.info.specVersion),
336 VK_MINOR(ext_props.info.specVersion),
337 VK_PATCH(ext_props.info.specVersion));
338 snprintf(version, sizeof(version), "%d.%d.%d",
339 VK_MAJOR(ext_props.info.version),
340 VK_MINOR(ext_props.info.version),
341 VK_PATCH(ext_props.info.version));
342
343 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
344 "Global Extension: %s (%s) version %s, Vulkan version %s",
345 ext_props.info.extName, lib_name, version, spec_version);
346 loader_add_to_ext_list(ext_list, 1, &ext_props);
347 }
348
349 return;
350}
351
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600352static void loader_add_physical_device_extensions(
353 PFN_vkGetPhysicalDeviceExtensionProperties get_phys_dev_ext_props,
354 VkPhysicalDevice physical_device,
355 const enum extension_origin origin,
356 const char *lib_name,
357 struct loader_extension_list *ext_list)
358{
359 uint32_t i, count;
360 VkResult res;
361 struct loader_extension_property ext_props;
362 VkExtensionProperties *extension_properties;
363
364 memset(&ext_props, 0, sizeof(ext_props));
365 ext_props.origin = origin;
366 ext_props.lib_name = lib_name;
367
368 if (get_phys_dev_ext_props) {
369 res = get_phys_dev_ext_props(physical_device, NULL, &count, NULL);
370 if (res == VK_SUCCESS && count > 0) {
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600371
372 extension_properties = loader_stack_alloc(count * sizeof(VkExtensionProperties));
373
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600374 res = get_phys_dev_ext_props(physical_device, NULL, &count, extension_properties);
375 for (i = 0; i < count; i++) {
376 char spec_version[64], version[64];
377
378 memcpy(&ext_props.info, &extension_properties[i], sizeof(VkExtensionProperties));
379
380 snprintf(spec_version, sizeof(spec_version), "%d.%d.%d",
381 VK_MAJOR(ext_props.info.specVersion),
382 VK_MINOR(ext_props.info.specVersion),
383 VK_PATCH(ext_props.info.specVersion));
384 snprintf(version, sizeof(version), "%d.%d.%d",
385 VK_MAJOR(ext_props.info.version),
386 VK_MINOR(ext_props.info.version),
387 VK_PATCH(ext_props.info.version));
388
389 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
390 "PhysicalDevice Extension: %s (%s) version %s, Vulkan version %s",
391 ext_props.info.extName, lib_name, version, spec_version);
392 loader_add_to_ext_list(ext_list, 1, &ext_props);
Jon Ashburn953bb3c2015-06-10 16:11:42 -0600393 }
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600394 } else {
395 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Error getting physical device extension info count from Layer %s", ext_props.lib_name);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600396 }
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600397 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600398
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600399 return;
400}
401
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600402static void loader_add_physical_device_layer_properties(
403 struct loader_icd *icd,
404 char *lib_name,
405 const loader_platform_dl_handle lib_handle)
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600406{
407 uint32_t i, count;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600408 VkLayerProperties *layer_properties;
409 PFN_vkGetPhysicalDeviceExtensionProperties fp_get_ext_props;
410 PFN_vkGetPhysicalDeviceLayerProperties fp_get_layer_props;
411 VkPhysicalDevice gpu = icd->gpus[0];
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600412 VkResult res;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600413
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600414 fp_get_ext_props = loader_platform_get_proc_address(lib_handle, "vkGetPhysicalDeviceExtensionProperties");
415 if (!fp_get_ext_props) {
416 loader_log(VK_DBG_REPORT_INFO_BIT, 0,
417 "Couldn't dlsym vkGetPhysicalDeviceExtensionProperties from library %s",
418 lib_name);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600419 }
420
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600421 fp_get_layer_props = loader_platform_get_proc_address(lib_handle, "vkGetPhysicalDeviceLayerProperties");
422 if (!fp_get_layer_props) {
423 loader_log(VK_DBG_REPORT_INFO_BIT, 0,
424 "Couldn't dlsym vkGetPhysicalDeviceLayerProperties from library %s",
425 lib_name);
426 return;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600427 }
428
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600429 /*
430 * NOTE: We assume that all GPUs of an ICD support the same PhysicalDevice
431 * layers and extensions. Thus only ask for info about the first gpu.
432 */
433 res = fp_get_layer_props(gpu, &count, NULL);
434 if (res != VK_SUCCESS) {
435 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Error getting PhysicalDevice layer count from %s", lib_name);
436 return;
437 }
438
439 if (count == 0) {
440 return;
441 }
442
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600443 layer_properties = loader_stack_alloc(count * sizeof(VkLayerProperties));
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600444
445 res = fp_get_layer_props(gpu, &count, layer_properties);
446 if (res != VK_SUCCESS) {
447 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Error getting %d PhysicalDevice layer properties from %s",
448 count, lib_name);
449 return;
450 }
451
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -0600452 //TODO get layer properties from manifest file
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600453 for (i = 0; i < count; i++) {
454 struct loader_layer_properties layer;
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600455
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600456 memset(&layer, 0, sizeof(struct loader_layer_properties));
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600457
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600458 layer.lib_info.lib_name = lib_name;
459 memcpy(&layer.info, &layer_properties[i], sizeof(VkLayerProperties));
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600460
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600461 loader_init_ext_list(&layer.instance_extension_list);
462 loader_init_ext_list(&layer.device_extension_list);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600463
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600464 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, "Collecting PhysicalDevice extensions for layer %s (%s)",
465 layer.info.layerName, layer.info.description);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600466
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600467 loader_add_physical_device_extensions(
468 fp_get_ext_props,
469 icd->gpus[i],
470 VK_EXTENSION_ORIGIN_LAYER,
471 lib_name,
472 &layer.device_extension_list);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600473
474 loader_add_to_layer_list(&icd->layer_properties_cache, 1, &layer);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600475 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600476 return;
477}
478
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600479static bool loader_init_ext_list(struct loader_extension_list *ext_info)
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600480{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600481 ext_info->capacity = 32 * sizeof(struct loader_extension_property);
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600482 /* TODO: Need to use loader_stack_alloc or loader_heap_alloc */
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600483 ext_info->list = malloc(ext_info->capacity);
484 if (ext_info->list == NULL) {
485 return false;
486 }
487 memset(ext_info->list, 0, ext_info->capacity);
488 ext_info->count = 0;
489 return true;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600490}
491
Courtney Goeltzenleuchter7d0023c2015-06-08 15:09:22 -0600492void loader_destroy_ext_list(struct loader_extension_list *ext_info)
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600493{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600494 free(ext_info->list);
495 ext_info->count = 0;
496 ext_info->capacity = 0;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600497}
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600498
Jon Ashburnbd6c4882015-07-02 12:59:25 -0600499/**
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600500 * Search the given search_list for any layers in the props list.
501 * Add these to the output layer_list. Don't add duplicates to the output layer_list.
Jon Ashburnbd6c4882015-07-02 12:59:25 -0600502 */
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -0600503static VkResult loader_add_layer_names_to_list(
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600504 struct loader_layer_list *output_list,
505 uint32_t name_count,
506 const char * const *names,
507 const struct loader_layer_list *search_list)
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600508{
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600509 struct loader_layer_properties *layer_prop;
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -0600510 VkResult err = VK_SUCCESS;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600511
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600512 for (uint32_t i = 0; i < name_count; i++) {
513 const char *search_target = names[i];
514 layer_prop = get_layer_property(search_target, search_list);
515 if (!layer_prop) {
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -0600516 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Unable to find layer %s", search_target);
517 err = VK_ERROR_INVALID_LAYER;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600518 continue;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600519 }
520
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600521 loader_add_to_layer_list(output_list, 1, layer_prop);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600522 }
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -0600523
524 return err;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600525}
526
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600527/*
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -0600528 * Append non-duplicate extension properties defined in props
529 * to the given ext_list.
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600530 */
531void loader_add_to_ext_list(
532 struct loader_extension_list *ext_list,
533 uint32_t prop_list_count,
534 const struct loader_extension_property *props)
535{
536 uint32_t i;
537 struct loader_extension_property *cur_ext;
538
539 if (ext_list->list == NULL || ext_list->capacity == 0) {
540 loader_init_ext_list(ext_list);
541 }
542
543 if (ext_list->list == NULL)
544 return;
545
546 for (i = 0; i < prop_list_count; i++) {
547 cur_ext = (struct loader_extension_property *) &props[i];
548
549 // look for duplicates
550 if (has_vk_extension_property(&cur_ext->info, ext_list)) {
551 continue;
552 }
553
554 // add to list at end
555 // check for enough capacity
556 if (ext_list->count * sizeof(struct loader_extension_property)
557 >= ext_list->capacity) {
558 // double capacity
559 ext_list->capacity *= 2;
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600560 /* TODO: Need to use loader_stack_alloc or loader_heap_alloc */
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600561 ext_list->list = realloc(ext_list->list, ext_list->capacity);
562 }
Courtney Goeltzenleuchter0f1d8eb2015-06-07 17:28:17 -0600563
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600564 memcpy(&ext_list->list[ext_list->count], cur_ext, sizeof(struct loader_extension_property));
565 ext_list->count++;
566 }
567}
568
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600569/*
570 * Manage lists of VkLayerProperties
571 */
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600572static bool loader_init_layer_list(struct loader_layer_list *list)
573{
574 list->capacity = 32 * sizeof(struct loader_layer_properties);
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600575 /* TODO: Need to use loader_stack_alloc or loader_heap_alloc */
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600576 list->list = malloc(list->capacity);
577 if (list->list == NULL) {
578 return false;
579 }
580 memset(list->list, 0, list->capacity);
581 list->count = 0;
582 return true;
583}
584
585void loader_destroy_layer_list(struct loader_layer_list *layer_list)
586{
587 free(layer_list->list);
588 layer_list->count = 0;
589 layer_list->capacity = 0;
590}
591
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600592/*
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600593 * Manage list of layer libraries (loader_lib_info)
594 */
595static bool loader_init_layer_library_list(struct loader_layer_library_list *list)
596{
597 list->capacity = 32 * sizeof(struct loader_lib_info);
598 /* TODO: Need to use loader_stack_alloc or loader_heap_alloc */
599 list->list = malloc(list->capacity);
600 if (list->list == NULL) {
601 return false;
602 }
603 memset(list->list, 0, list->capacity);
604 list->count = 0;
605 return true;
606}
607
608void loader_destroy_layer_library_list(struct loader_layer_library_list *list)
609{
610 for (uint32_t i = 0; i < list->count; i++) {
611 free(list->list[i].lib_name);
612 }
613 free(list->list);
614 list->count = 0;
615 list->capacity = 0;
616}
617
618void loader_add_to_layer_library_list(
619 struct loader_layer_library_list *list,
620 uint32_t item_count,
621 const struct loader_lib_info *new_items)
622{
623 uint32_t i;
624 struct loader_lib_info *item;
625
626 if (list->list == NULL || list->capacity == 0) {
627 loader_init_layer_library_list(list);
628 }
629
630 if (list->list == NULL)
631 return;
632
633 for (i = 0; i < item_count; i++) {
634 item = (struct loader_lib_info *) &new_items[i];
635
636 // look for duplicates
637 for (uint32_t j = 0; j < list->count; j++) {
638 if (strcmp(list->list[i].lib_name, new_items->lib_name) == 0) {
639 continue;
640 }
641 }
642
643 // add to list at end
644 // check for enough capacity
645 if (list->count * sizeof(struct loader_lib_info)
646 >= list->capacity) {
647 // double capacity
648 list->capacity *= 2;
649 /* TODO: Need to use loader_stack_alloc or loader_heap_alloc */
650 list->list = realloc(list->list, list->capacity);
651 }
652
653 memcpy(&list->list[list->count], item, sizeof(struct loader_lib_info));
654 list->count++;
655 }
656}
657
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -0600658#if 0
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600659/*
660 * Add's library indicated by lib_name to list if it
661 * implements vkGetGlobalLayerProperties or
662 * vkGetPhysicalDeviceLayerProperties.
663 */
664static void loader_add_layer_library(
665 struct loader_instance *instance,
666 const char *lib_name,
667 const loader_platform_dl_handle lib_handle,
668 struct loader_layer_library_list *list)
669{
670 struct loader_lib_info *library_info;
671 PFN_vkGetPhysicalDeviceLayerProperties fp_get_phydev_props;
672 PFN_vkGetGlobalLayerProperties fp_get_layer_props;
673
674 fp_get_layer_props = loader_platform_get_proc_address(lib_handle, "vkGetGlobalLayerProperties");
675 fp_get_phydev_props = loader_platform_get_proc_address(lib_handle, "vkGetPhysicalDeviceLayerProperties");
676
677 if (!fp_get_layer_props && !fp_get_phydev_props)
678 return;
679
680 /*
681 * Allocate enough space for the library name to
682 * immediately follow the loader_lib_info structure
683 */
684 library_info = loader_heap_alloc(instance, sizeof(struct loader_lib_info) + strlen(lib_name) + 1, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
685 if (!library_info) {
686 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
687 "Malloc for layer library list failed: %s line: %d", __FILE__, __LINE__);
688 return;
689 }
690 memset(library_info, 0, sizeof(struct loader_lib_info));
691 library_info->lib_name = (char *) &library_info[1];
692 strcpy(library_info->lib_name, lib_name);
693
694 loader_add_to_layer_library_list(list, 1, library_info);
695}
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -0600696#endif
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -0600697/*
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600698 * Search the given layer list for a list
699 * matching the given VkLayerProperties
700 */
701bool has_vk_layer_property(
702 const VkLayerProperties *vk_layer_prop,
703 const struct loader_layer_list *list)
704{
705 for (uint32_t i = 0; i < list->count; i++) {
706 if (strcmp(vk_layer_prop->layerName, list->list[i].info.layerName) == 0)
707 return true;
708 }
709 return false;
710}
711
712/*
713 * Search the given layer list for a layer
714 * matching the given name
715 */
716bool has_layer_name(
717 const char *name,
718 const struct loader_layer_list *list)
719{
720 for (uint32_t i = 0; i < list->count; i++) {
721 if (strcmp(name, list->list[i].info.layerName) == 0)
722 return true;
723 }
724 return false;
725}
726
727/*
728 * Append non-duplicate layer properties defined in prop_list
729 * to the given layer_info list
730 */
731void loader_add_to_layer_list(
732 struct loader_layer_list *list,
733 uint32_t prop_list_count,
734 const struct loader_layer_properties *props)
735{
736 uint32_t i;
737 struct loader_layer_properties *layer;
738
739 if (list->list == NULL || list->capacity == 0) {
740 loader_init_layer_list(list);
741 }
742
743 if (list->list == NULL)
744 return;
745
746 for (i = 0; i < prop_list_count; i++) {
747 layer = (struct loader_layer_properties *) &props[i];
748
749 // look for duplicates
750 if (has_vk_layer_property(&layer->info, list)) {
751 continue;
752 }
753
754 // add to list at end
755 // check for enough capacity
756 if (list->count * sizeof(struct loader_layer_properties)
757 >= list->capacity) {
758 // double capacity
759 list->capacity *= 2;
760 list->list = realloc(list->list, list->capacity);
761 }
762
763 memcpy(&list->list[list->count], layer, sizeof(struct loader_layer_properties));
764 list->count++;
765 }
766}
767
Jon Ashburnbd332cc2015-07-07 10:27:45 -0600768/**
769 * Search the search_list for any layer with a name
770 * that matches the given name and a type that matches the given type
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600771 * Add all matching layers to the found_list
Jon Ashburnbd332cc2015-07-07 10:27:45 -0600772 * Do not add if found loader_layer_properties is already
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600773 * on the found_list.
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600774 */
Jon Ashburnbd6c4882015-07-02 12:59:25 -0600775static void loader_find_layer_name_add_list(
776 const char *name,
Jon Ashburnbd332cc2015-07-07 10:27:45 -0600777 const enum layer_type type,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600778 const struct loader_layer_list *search_list,
779 struct loader_layer_list *found_list)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600780{
781 for (uint32_t i = 0; i < search_list->count; i++) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600782 struct loader_layer_properties *layer_prop = &search_list->list[i];
Jon Ashburnbd332cc2015-07-07 10:27:45 -0600783 if (0 == strcmp(layer_prop->info.layerName, name) &&
784 (layer_prop->type & type)) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600785 /* Found a layer with the same name, add to found_list */
786 loader_add_to_layer_list(found_list, 1, layer_prop);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600787 }
788 }
789}
790
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -0600791static struct loader_extension_property *get_extension_property(
792 const char *name,
793 const struct loader_extension_list *list)
Jon Ashburnfc2e38c2015-04-14 09:15:32 -0600794{
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -0600795 for (uint32_t i = 0; i < list->count; i++) {
796 const VkExtensionProperties *item = &list->list[i].info;
797 if (strcmp(name, item->extName) == 0)
798 return &list->list[i];
Jon Ashburnfc2e38c2015-04-14 09:15:32 -0600799 }
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -0600800 return NULL;
Jon Ashburnfc2e38c2015-04-14 09:15:32 -0600801}
802
Jon Ashburnbd6c4882015-07-02 12:59:25 -0600803/*
804 * For global exenstions implemented within the loader (i.e. DEBUG_REPORT
805 * the extension must provide two entry points for the loader to use:
806 * - "trampoline" entry point - this is the address returned by GetProcAddr
807 * and will always do what's necessary to support a global call.
808 * - "terminator" function - this function will be put at the end of the
809 * instance chain and will contain the necessary logica to call / process
810 * the extension for the appropriate ICDs that are available.
811 * There is no generic mechanism for including these functions, the references
812 * must be placed into the appropriate loader entry points.
813 * GetInstanceProcAddr: call extension GetInstanceProcAddr to check for GetProcAddr requests
814 * loader_coalesce_extensions(void) - add extension records to the list of global
815 * extension available to the app.
816 * instance_disp - add function pointer for terminator function to this array.
817 * The extension itself should be in a separate file that will be
818 * linked directly with the loader.
819 */
Jon Ashburn27cd5842015-05-12 17:26:48 -0600820void loader_coalesce_extensions(void)
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600821{
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600822 struct loader_scanned_icds *icd_list = loader.scanned_icd_list;
823
824 // traverse scanned icd list adding non-duplicate extensions to the list
825 while (icd_list != NULL) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600826 loader_add_to_ext_list(&loader.global_extensions,
827 icd_list->global_extension_list.count,
828 icd_list->global_extension_list.list);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600829 icd_list = icd_list->next;
830 };
831
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600832 // Traverse loader's extensions, adding non-duplicate extensions to the list
833 debug_report_add_instance_extensions(&loader.global_extensions);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600834}
835
Jon Ashburndc6fcad2015-06-10 10:06:06 -0600836static struct loader_icd *loader_get_icd_and_device(const VkDevice device,
837 struct loader_device **found_dev)
838{
839 *found_dev = NULL;
840 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
841 for (struct loader_icd *icd = inst->icds; icd; icd = icd->next) {
842 for (struct loader_device *dev = icd->logical_device_list; dev; dev = dev->next)
843 if (dev->device == device) {
844 *found_dev = dev;
845 return icd;
846 }
847 }
848 }
849 return NULL;
850}
851
852static void loader_destroy_logical_device(struct loader_device *dev)
853{
854 free(dev->app_extension_props);
Jon Ashburndc6fcad2015-06-10 10:06:06 -0600855 if (dev->activated_layer_list.count)
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -0600856 loader_destroy_layer_list(&dev->activated_layer_list);
Jon Ashburndc6fcad2015-06-10 10:06:06 -0600857 free(dev);
858}
859
860static struct loader_device *loader_add_logical_device(const VkDevice dev, struct loader_device **device_list)
861{
862 struct loader_device *new_dev;
863
864 new_dev = malloc(sizeof(struct loader_device));
865 if (!new_dev) {
866 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to malloc struct laoder-device");
867 return NULL;
868 }
869
870 memset(new_dev, 0, sizeof(struct loader_device));
871
872 new_dev->next = *device_list;
873 new_dev->device = dev;
874 *device_list = new_dev;
875 return new_dev;
876}
877
878void loader_remove_logical_device(VkDevice device)
879{
880 struct loader_device *found_dev, *dev, *prev_dev;
881 struct loader_icd *icd;
882 icd = loader_get_icd_and_device(device, &found_dev);
883
884 if (!icd || !found_dev)
885 return;
886
887 prev_dev = NULL;
888 dev = icd->logical_device_list;
889 while (dev && dev != found_dev) {
890 prev_dev = dev;
891 dev = dev->next;
892 }
893
894 if (prev_dev)
895 prev_dev->next = found_dev->next;
896 else
897 icd->logical_device_list = found_dev->next;
898 loader_destroy_logical_device(found_dev);
899}
900
901
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600902static void loader_icd_destroy(
903 struct loader_instance *ptr_inst,
904 struct loader_icd *icd)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800905{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600906 ptr_inst->total_icd_count--;
Jon Ashburn128f9422015-05-28 19:16:58 -0600907 free(icd->gpus);
Courtney Goeltzenleuchter1f157ac2015-06-14 19:57:15 -0600908 for (struct loader_device *dev = icd->logical_device_list; dev; ) {
909 struct loader_device *next_dev = dev->next;
Jon Ashburndc6fcad2015-06-10 10:06:06 -0600910 loader_destroy_logical_device(dev);
Courtney Goeltzenleuchter1f157ac2015-06-14 19:57:15 -0600911 dev = next_dev;
912 }
Jon Ashburndc6fcad2015-06-10 10:06:06 -0600913
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800914 free(icd);
915}
916
Jon Ashburn9fd4cc42015-04-10 14:33:07 -0600917static struct loader_icd * loader_icd_create(const struct loader_scanned_icds *scanned)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800918{
919 struct loader_icd *icd;
920
921 icd = malloc(sizeof(*icd));
922 if (!icd)
923 return NULL;
924
Courtney Goeltzenleuchter55001bb2014-10-28 10:29:27 -0600925 memset(icd, 0, sizeof(*icd));
926
Jon Ashburn46d1f582015-01-28 11:01:35 -0700927 icd->scanned_icds = scanned;
Chia-I Wu5f72d0f2014-08-01 11:21:23 +0800928
929 return icd;
930}
931
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600932static struct loader_icd *loader_icd_add(
933 struct loader_instance *ptr_inst,
934 const struct loader_scanned_icds *scanned)
Chia-I Wu13a61a52014-08-04 11:18:20 +0800935{
936 struct loader_icd *icd;
937
Jon Ashburn46d1f582015-01-28 11:01:35 -0700938 icd = loader_icd_create(scanned);
Chia-I Wu13a61a52014-08-04 11:18:20 +0800939 if (!icd)
940 return NULL;
941
Chia-I Wu13a61a52014-08-04 11:18:20 +0800942 /* prepend to the list */
Jon Ashburn46888392015-01-29 15:45:51 -0700943 icd->next = ptr_inst->icds;
944 ptr_inst->icds = icd;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600945 ptr_inst->total_icd_count++;
Chia-I Wu13a61a52014-08-04 11:18:20 +0800946
947 return icd;
948}
949
Jon Ashburn46d1f582015-01-28 11:01:35 -0700950static void loader_scanned_icd_add(const char *filename)
951{
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700952 loader_platform_dl_handle handle;
Jon Ashburn3da71f22015-05-14 12:43:38 -0600953 void *fp_create_inst;
Tony Barbour59a47322015-06-24 16:06:58 -0600954 void *fp_get_global_ext_props;
Tony Barbour59a47322015-06-24 16:06:58 -0600955 void *fp_get_device_ext_props;
Jon Ashburn953bb3c2015-06-10 16:11:42 -0600956 PFN_vkGPA fp_get_proc_addr;
Jon Ashburn46d1f582015-01-28 11:01:35 -0700957 struct loader_scanned_icds *new_node;
958
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700959 // Used to call: dlopen(filename, RTLD_LAZY);
960 handle = loader_platform_open_library(filename);
Jon Ashburn46d1f582015-01-28 11:01:35 -0700961 if (!handle) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600962 loader_log(VK_DBG_REPORT_WARN_BIT, 0, loader_platform_open_library_error(filename));
Jon Ashburn46d1f582015-01-28 11:01:35 -0700963 return;
964 }
965
966#define LOOKUP(func_ptr, func) do { \
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -0600967 func_ptr = (PFN_vk ##func) loader_platform_get_proc_address(handle, "vk" #func); \
Jon Ashburn46d1f582015-01-28 11:01:35 -0700968 if (!func_ptr) { \
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600969 loader_log(VK_DBG_REPORT_WARN_BIT, 0, loader_platform_get_proc_address_error("vk" #func)); \
Jon Ashburn46d1f582015-01-28 11:01:35 -0700970 return; \
971 } \
972} while (0)
973
Jon Ashburn46888392015-01-29 15:45:51 -0700974 LOOKUP(fp_create_inst, CreateInstance);
Tony Barbour59a47322015-06-24 16:06:58 -0600975 LOOKUP(fp_get_global_ext_props, GetGlobalExtensionProperties);
Tony Barbour59a47322015-06-24 16:06:58 -0600976 LOOKUP(fp_get_device_ext_props, GetPhysicalDeviceExtensionProperties);
Jon Ashburn953bb3c2015-06-10 16:11:42 -0600977 LOOKUP(fp_get_proc_addr, GetDeviceProcAddr);
Jon Ashburn46d1f582015-01-28 11:01:35 -0700978#undef LOOKUP
979
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600980 new_node = (struct loader_scanned_icds *) malloc(sizeof(struct loader_scanned_icds)
981 + strlen(filename) + 1);
Jon Ashburn46d1f582015-01-28 11:01:35 -0700982 if (!new_node) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600983 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Out of memory can't add icd");
Jon Ashburn46d1f582015-01-28 11:01:35 -0700984 return;
985 }
986
987 new_node->handle = handle;
Jon Ashburn46888392015-01-29 15:45:51 -0700988 new_node->CreateInstance = fp_create_inst;
Tony Barbour59a47322015-06-24 16:06:58 -0600989 new_node->GetGlobalExtensionProperties = fp_get_global_ext_props;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600990 loader_init_ext_list(&new_node->global_extension_list);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -0600991 loader_init_ext_list(&new_node->device_extension_list);
Jon Ashburn46d1f582015-01-28 11:01:35 -0700992 new_node->next = loader.scanned_icd_list;
Jon Ashburn46d1f582015-01-28 11:01:35 -0700993
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -0600994 new_node->lib_name = (char *) (new_node + 1);
995 if (!new_node->lib_name) {
996 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Out of memory can't add icd");
997 return;
998 }
999 strcpy(new_node->lib_name, filename);
1000
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001001 loader.scanned_icd_list = new_node;
1002
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06001003 loader_add_global_extensions(
Tony Barbour59a47322015-06-24 16:06:58 -06001004 (PFN_vkGetGlobalExtensionProperties) fp_get_global_ext_props,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001005 new_node->lib_name,
Jon Ashburn953bb3c2015-06-10 16:11:42 -06001006 handle,
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001007 VK_EXTENSION_ORIGIN_ICD,
1008 &new_node->global_extension_list);
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001009}
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001010
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06001011static struct loader_extension_list *loader_global_extensions(const char *pLayerName)
1012{
1013 if (pLayerName == NULL || (strlen(pLayerName) == 0)) {
1014 return &loader.global_extensions;
1015 }
1016
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -06001017 /* Find and return global extension list for given layer */
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001018 for (uint32_t i = 0; i < loader.scanned_layers.count; i++) {
1019 struct loader_layer_properties *work_layer = &loader.scanned_layers.list[i];
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06001020 if (strcmp(work_layer->info.layerName, pLayerName) == 0) {
1021 return &work_layer->instance_extension_list;
1022 }
1023 }
1024
1025 return NULL;
1026}
1027
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001028static struct loader_layer_list *loader_scanned_layers()
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06001029{
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001030 return &loader.scanned_layers;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06001031}
1032
1033static void loader_physical_device_layers(
1034 struct loader_icd *icd,
1035 uint32_t *count,
1036 struct loader_layer_list **list)
1037{
1038 *count = icd->layer_properties_cache.count;
1039 *list = &icd->layer_properties_cache;
1040}
1041
1042static void loader_physical_device_extensions(
1043 struct loader_icd *icd,
1044 uint32_t gpu_idx,
1045 const char *layer_name,
1046 uint32_t *count,
1047 struct loader_extension_list **list)
1048{
1049 if (layer_name == NULL || (strlen(layer_name) == 0)) {
1050 *count = icd->device_extension_cache[gpu_idx].count;
1051 *list = &icd->device_extension_cache[gpu_idx];
1052 return;
1053 }
1054 for (uint32_t i = 0; i < icd->layer_properties_cache.count; i++) {
1055 if (strcmp(layer_name, icd->layer_properties_cache.list[i].info.layerName) == 0) {
1056 *count = icd->layer_properties_cache.list[i].device_extension_list.count;
1057 *list = &icd->layer_properties_cache.list[i].device_extension_list;
1058 }
1059 }
1060}
1061
Jon Ashburn3da71f22015-05-14 12:43:38 -06001062static void loader_icd_init_entrys(struct loader_icd *icd,
1063 struct loader_scanned_icds *scanned_icds)
1064{
1065 /* initialize entrypoint function pointers */
1066
1067 #define LOOKUP(func) do { \
1068 icd->func = (PFN_vk ##func) loader_platform_get_proc_address(scanned_icds->handle, "vk" #func); \
1069 if (!icd->func) { \
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001070 loader_log(VK_DBG_REPORT_WARN_BIT, 0, loader_platform_get_proc_address_error("vk" #func)); \
Jon Ashburn3da71f22015-05-14 12:43:38 -06001071 return; \
1072 } \
1073 } while (0)
1074
Jon Ashburn8d1b0b52015-05-18 13:20:15 -06001075 /* could change this to use GetInstanceProcAddr in driver instead of dlsym */
1076 LOOKUP(GetDeviceProcAddr);
Jon Ashburn3da71f22015-05-14 12:43:38 -06001077 LOOKUP(DestroyInstance);
1078 LOOKUP(EnumeratePhysicalDevices);
Chris Forbesbc0bb772015-06-21 22:55:02 +12001079 LOOKUP(GetPhysicalDeviceFeatures);
1080 LOOKUP(GetPhysicalDeviceFormatInfo);
1081 LOOKUP(GetPhysicalDeviceLimits);
Jon Ashburn3da71f22015-05-14 12:43:38 -06001082 LOOKUP(CreateDevice);
Tony Barbour59a47322015-06-24 16:06:58 -06001083 LOOKUP(GetPhysicalDeviceProperties);
1084 LOOKUP(GetPhysicalDeviceMemoryProperties);
1085 LOOKUP(GetPhysicalDevicePerformance);
1086 LOOKUP(GetPhysicalDeviceQueueCount);
1087 LOOKUP(GetPhysicalDeviceQueueProperties);
1088 LOOKUP(GetPhysicalDeviceExtensionProperties);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001089 LOOKUP(DbgCreateMsgCallback);
1090 LOOKUP(DbgDestroyMsgCallback);
Jon Ashburn3da71f22015-05-14 12:43:38 -06001091#undef LOOKUP
1092
1093 return;
1094}
1095
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001096static void loader_debug_init(void)
1097{
1098 const char *env;
1099
1100 if (g_loader_debug > 0)
1101 return;
1102
1103 g_loader_debug = 0;
1104
1105 /* parse comma-separated debug options */
1106 env = getenv("LOADER_DEBUG");
1107 while (env) {
1108 const char *p = strchr(env, ',');
1109 size_t len;
1110
1111 if (p)
1112 len = p - env;
1113 else
1114 len = strlen(env);
1115
1116 if (len > 0) {
1117 if (strncmp(env, "warn", len) == 0) {
1118 g_loader_debug |= LOADER_WARN_BIT;
1119 g_loader_log_msgs |= VK_DBG_REPORT_WARN_BIT;
1120 } else if (strncmp(env, "info", len) == 0) {
1121 g_loader_debug |= LOADER_INFO_BIT;
1122 g_loader_log_msgs |= VK_DBG_REPORT_INFO_BIT;
1123 } else if (strncmp(env, "perf", len) == 0) {
1124 g_loader_debug |= LOADER_PERF_BIT;
1125 g_loader_log_msgs |= VK_DBG_REPORT_PERF_WARN_BIT;
1126 } else if (strncmp(env, "error", len) == 0) {
1127 g_loader_debug |= LOADER_ERROR_BIT;
1128 g_loader_log_msgs |= VK_DBG_REPORT_ERROR_BIT;
1129 } else if (strncmp(env, "debug", len) == 0) {
1130 g_loader_debug |= LOADER_DEBUG_BIT;
1131 g_loader_log_msgs |= VK_DBG_REPORT_DEBUG_BIT;
1132 }
1133 }
1134
1135 if (!p)
1136 break;
1137
1138 env = p + 1;
1139 }
1140}
1141
Jon Ashburn2077e382015-06-29 11:25:34 -06001142struct loader_manifest_files {
1143 uint32_t count;
1144 char **filename_list;
1145};
1146
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06001147/**
Jon Ashburn2077e382015-06-29 11:25:34 -06001148 * Get next file or dirname given a string list or registry key path
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06001149 *
1150 * \returns
Jon Ashburn2077e382015-06-29 11:25:34 -06001151 * A pointer to first char in the next path.
1152 * The next path (or NULL) in the list is returned in next_path.
1153 * Note: input string is modified in some cases. PASS IN A COPY!
1154 */
Jon Ashburn2077e382015-06-29 11:25:34 -06001155static char *loader_get_next_path(char *path)
1156{
1157 uint32_t len;
1158 char *next;
1159
1160 if (path == NULL)
1161 return NULL;
1162 next = strchr(path, PATH_SEPERATOR);
1163 if (next == NULL) {
1164 len = (uint32_t) strlen(path);
1165 next = path + len;
1166 }
1167 else {
1168 *next = '\0';
1169 next++;
1170 }
1171
1172 return next;
1173}
1174
1175/**
Jon Ashburn15315172015-07-07 15:06:25 -06001176 * Given a path which is absolute or relative. Expand the path if relative otherwise
1177 * leave the path unmodified if absolute. The path which is relative from is
1178 * given in rel_base and should include trailing directory seperator '/'
1179 *
1180 * \returns
1181 * A string in out_fullpath of the full absolute path
1182 * Side effect is that dir string maybe modified.
1183 */
1184static void loader_expand_path(const char *path,
1185 const char *rel_base,
1186 size_t out_size,
1187 char *out_fullpath)
1188{
1189 if (loader_platform_is_path_absolute(path)) {
1190 strncpy(out_fullpath, path, out_size);
1191 out_fullpath[out_size - 1] = '\0';
1192 }
1193 else {
1194 // convert relative to absolute path based on rel_base
1195 size_t len = strlen(path);
1196 strncpy(out_fullpath, rel_base, out_size);
1197 out_fullpath[out_size - 1] = '\0';
1198 assert(out_size >= strlen(out_fullpath) + len + 1);
1199 strncat(out_fullpath, path, len);
1200 }
1201}
1202
1203/**
Jon Ashburn2077e382015-06-29 11:25:34 -06001204 * Given a filename (file) and a list of paths (dir), try to find an existing
1205 * file in the paths. If filename already is a path then no
1206 * searching in the given paths.
1207 *
1208 * \returns
1209 * A string in out_fullpath of either the full path or file.
1210 * Side effect is that dir string maybe modified.
1211 */
1212static void loader_get_fullpath(const char *file,
1213 char *dir,
1214 size_t out_size,
1215 char *out_fullpath)
1216{
1217 char *next_dir;
1218 if (strchr(file,DIRECTORY_SYMBOL) == NULL) {
1219 //find file exists with prepending given path
1220 while (*dir) {
1221 next_dir = loader_get_next_path(dir);
1222 snprintf(out_fullpath, out_size, "%s%c%s",
1223 dir, DIRECTORY_SYMBOL, file);
1224 if (loader_platform_file_exists(out_fullpath)) {
1225 return;
1226 }
1227 dir = next_dir;
1228 }
1229 }
1230 snprintf(out_fullpath, out_size, "%s", file);
1231}
1232
1233/**
1234 * Read a JSON file into a buffer.
1235 *
1236 * \returns
1237 * A pointer to a cJSON object representing the JSON parse tree.
1238 * This returned buffer should be freed by caller.
1239 */
1240static cJSON *loader_get_json(const char *filename)
1241{
1242 FILE *file;
1243 char *json_buf;
1244 cJSON *json;
1245 uint64_t len;
1246 file = fopen(filename,"rb");
1247 fseek(file, 0, SEEK_END);
1248 len = ftell(file);
1249 fseek(file, 0, SEEK_SET);
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -06001250 json_buf = (char*) loader_stack_alloc(len+1);
Jon Ashburn2077e382015-06-29 11:25:34 -06001251 if (json_buf == NULL) {
1252 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get JSON file");
1253 fclose(file);
1254 return NULL;
1255 }
1256 if (fread(json_buf, sizeof(char), len, file) != len) {
1257 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "fread failed can't get JSON file");
1258 fclose(file);
1259 return NULL;
1260 }
1261 fclose(file);
1262 json_buf[len] = '\0';
1263
1264 //parse text from file
1265 json = cJSON_Parse(json_buf);
1266 if (json == NULL)
1267 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Can't parse JSON file %s", filename);
1268 return json;
1269}
1270
1271/**
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001272 * Given a cJSON struct (json) of the top level JSON object from layer manifest
1273 * file, add entry to the layer_list.
1274 * Fill out the layer_properties in this list entry from the input cHJSON object.
1275 *
1276 * \returns
1277 * void
1278 * layer_list has a new entry and initialized accordingly.
1279 * If the json input object does not have all the required fields no entry
1280 * is added to the list.
1281 */
1282static void loader_add_layer_properties(struct loader_layer_list *layer_list,
1283 cJSON *json,
1284 bool is_implicit,
1285 char *filename)
1286{
1287 /* Fields in layer manifest file that are required:
1288 * (required) “file_format_version”
1289 * following are required in the "layer" object:
1290 * (required) "name"
1291 * (required) "type"
1292 * (required) “library_path”
1293 * (required) “abi_versions”
1294 * (required) “implementation_version”
1295 * (required) “description”
1296 * (required for implicit layers) “disable_environment”
1297 *
1298 * First get all required items and if any missing abort
1299 */
1300
1301 cJSON *item, *layer_node, *ext_item;
1302 char *temp;
1303 char *name, *type, *library_path, *abi_versions;
1304 char *implementation_version, *description;
1305 cJSON *disable_environment;
1306 int i;
1307 struct loader_extension_property ext_prop;
1308 item = cJSON_GetObjectItem(json, "file_format_version");
1309 if (item == NULL) {
1310 return;
1311 }
1312 char *file_vers = cJSON_PrintUnformatted(item);
1313 loader_log(VK_DBG_REPORT_INFO_BIT, 0, "Found manifest file %s, version %s",
1314 filename, file_vers);
1315 if (strcmp(file_vers, "\"0.9.0\"") != 0)
1316 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Unexpected manifest file version (expected 1.0.0), may cause errors");
1317 free(file_vers);
1318
1319 //TODO handle multiple layer nodes in the file
1320 //TODO handle scanned libraries not one per layer property
1321 layer_node = cJSON_GetObjectItem(json, "layer");
1322 if (layer_node == NULL) {
1323 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"layer\" object in manifest JSON file, skipping");
1324 return;
1325 }
1326#define GET_JSON_OBJECT(node, var) { \
1327 var = cJSON_GetObjectItem(node, #var); \
1328 if (var == NULL) \
1329 return; \
1330 }
1331#define GET_JSON_ITEM(node, var) { \
1332 item = cJSON_GetObjectItem(node, #var); \
1333 if (item == NULL) \
1334 return; \
1335 temp = cJSON_Print(item); \
1336 temp[strlen(temp) - 1] = '\0'; \
1337 var = malloc(strlen(temp) + 1); \
1338 strcpy(var, &temp[1]); \
1339 free(temp); \
1340 }
1341 GET_JSON_ITEM(layer_node, name)
1342 GET_JSON_ITEM(layer_node, type)
1343 GET_JSON_ITEM(layer_node, library_path)
1344 GET_JSON_ITEM(layer_node, abi_versions)
1345 GET_JSON_ITEM(layer_node, implementation_version)
1346 GET_JSON_ITEM(layer_node, description)
1347 if (is_implicit) {
1348 GET_JSON_OBJECT(layer_node, disable_environment)
1349 }
1350#undef GET_JSON_ITEM
1351#undef GET_JSON_OBJECT
1352
1353 // add list entry
1354 assert((layer_list->count + 1) * sizeof(struct loader_layer_properties) <= layer_list->capacity);
1355 struct loader_layer_properties *props = &(layer_list->list[layer_list->count]);
Jon Ashburn15315172015-07-07 15:06:25 -06001356 strncpy(props->info.layerName, name, sizeof(props->info.layerName));
1357 props->info.layerName[sizeof(props->info.layerName) - 1] = '\0';
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001358 free(name);
Jon Ashburn15315172015-07-07 15:06:25 -06001359
Jon Ashburnbd332cc2015-07-07 10:27:45 -06001360 if (!strcmp(type, "DEVICE"))
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001361 props->type = (is_implicit) ? VK_LAYER_TYPE_DEVICE_IMPLICIT : VK_LAYER_TYPE_DEVICE_EXPLICIT;
Jon Ashburnbd332cc2015-07-07 10:27:45 -06001362 if (!strcmp(type, "INSTANCE"))
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001363 props->type = (is_implicit) ? VK_LAYER_TYPE_INSTANCE_IMPLICIT : VK_LAYER_TYPE_INSTANCE_EXPLICIT;
Jon Ashburnbd332cc2015-07-07 10:27:45 -06001364 if (!strcmp(type, "GLOBAL"))
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001365 props->type = (is_implicit) ? VK_LAYER_TYPE_GLOBAL_IMPLICIT : VK_LAYER_TYPE_GLOBAL_EXPLICIT;
1366 free(type);
Jon Ashburn15315172015-07-07 15:06:25 -06001367
1368 char *fullpath = malloc(2048);
1369 char *rel_base;
1370 if (strchr(library_path, DIRECTORY_SYMBOL) == NULL) {
1371 // a filename which is assumed in the system directory
1372 loader_get_fullpath(library_path, DEFAULT_VK_LAYERS_PATH, 2048, fullpath);
1373 }
1374 else {
1375 // a relative or absolute path
1376 char *name_copy = loader_stack_alloc(strlen(filename) + 2);
1377 size_t len;
1378 strcpy(name_copy, filename);
1379 rel_base = loader_platform_dirname(name_copy);
1380 len = strlen(rel_base);
1381 rel_base[len] = DIRECTORY_SYMBOL;
1382 rel_base[len + 1] = '\0';
1383 loader_expand_path(library_path, rel_base, 2048, fullpath);
1384 }
1385 props->lib_info.lib_name = fullpath;
1386 free(library_path);
1387 //TODO merge the info with the versions and convert string to int
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001388 props->abi_version = abi_versions;
1389 props->impl_version = implementation_version;
Jon Ashburn15315172015-07-07 15:06:25 -06001390 strncpy(props->info.description, description, sizeof(props->info.description));
1391 props->info.description[sizeof(props->info.description) - 1] = '\0';
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001392 free(description);
1393 if (is_implicit) {
1394 props->disable_env_var.name = disable_environment->child->string;
1395 props->disable_env_var.value = disable_environment->child->valuestring;
1396 }
1397 layer_list->count++;
1398
1399 /**
1400 * Now get all optional items and objects and put in list:
1401 * functions
1402 * instance_extensions
1403 * device_extensions
1404 * enable_environment (implicit layers only)
1405 */
1406#define GET_JSON_OBJECT(node, var) { \
1407 var = cJSON_GetObjectItem(node, #var); \
1408 }
1409#define GET_JSON_ITEM(node, var) { \
1410 item = cJSON_GetObjectItem(node, #var); \
1411 if (item != NULL) \
1412 temp = cJSON_Print(item); \
1413 temp[strlen(temp) - 1] = '\0'; \
1414 var = malloc(strlen(temp) + 1); \
1415 strcpy(var, &temp[1]); \
1416 free(temp); \
1417 }
1418
1419 cJSON *instance_extensions, *device_extensions, *functions, *enable_environment;
1420 char *vkGetInstanceProcAddr, *vkGetDeviceProcAddr, *version;
1421 GET_JSON_OBJECT(layer_node, functions)
1422 if (functions != NULL) {
1423 GET_JSON_ITEM(functions, vkGetInstanceProcAddr)
1424 GET_JSON_ITEM(functions, vkGetDeviceProcAddr)
1425 props->functions.str_gipa = vkGetInstanceProcAddr;
1426 props->functions.str_gdpa = vkGetDeviceProcAddr;
1427 }
1428 GET_JSON_OBJECT(layer_node, instance_extensions)
1429 if (instance_extensions != NULL) {
1430 int count = cJSON_GetArraySize(instance_extensions);
1431 for (i = 0; i < count; i++) {
1432 ext_item = cJSON_GetArrayItem(instance_extensions, i);
1433 GET_JSON_ITEM(ext_item, name)
1434 GET_JSON_ITEM(ext_item, version)
1435 ext_prop.origin = VK_EXTENSION_ORIGIN_LAYER;
1436 ext_prop.lib_name = library_path;
1437 strcpy(ext_prop.info.extName, name);
1438 //TODO convert from string to int ext_prop.info.version = version;
1439 loader_add_to_ext_list(&props->instance_extension_list, 1, &ext_prop);
1440 }
1441 }
1442 GET_JSON_OBJECT(layer_node, device_extensions)
1443 if (device_extensions != NULL) {
1444 int count = cJSON_GetArraySize(device_extensions);
1445 for (i = 0; i < count; i++) {
1446 ext_item = cJSON_GetArrayItem(device_extensions, i);
1447 GET_JSON_ITEM(ext_item, name);
1448 GET_JSON_ITEM(ext_item, version);
1449 ext_prop.origin = VK_EXTENSION_ORIGIN_LAYER;
1450 ext_prop.lib_name = library_path;
1451 strcpy(ext_prop.info.extName, name);
1452 //TODO convert from string to int ext_prop.info.version = version;
1453 loader_add_to_ext_list(&props->device_extension_list, 1, &ext_prop);
1454 }
1455 }
1456 if (is_implicit) {
1457 GET_JSON_OBJECT(layer_node, enable_environment)
1458 props->enable_env_var.name = enable_environment->child->string;
1459 props->enable_env_var.value = enable_environment->child->valuestring;
1460 }
1461#undef GET_JSON_ITEM
1462#undef GET_JSON_OBJECT
1463
1464}
1465
1466/**
Jon Ashburn2077e382015-06-29 11:25:34 -06001467 * Find the Vulkan library manifest files.
1468 *
1469 * This function scans the location or env_override directories/files
1470 * for a list of JSON manifest files. If env_override is non-NULL
1471 * and has a valid value. Then the location is ignored. Otherwise
1472 * location is used to look for manifest files. The location
1473 * is interpreted as Registry path on Windows and a directory path(s)
1474 * on Linux.
1475 *
1476 * \returns
1477 * A string list of manifest files to be opened in out_files param.
1478 * List has a pointer to string for each manifest filename.
1479 * When done using the list in out_files, pointers should be freed.
Jon Ashburnffad94d2015-06-30 14:46:22 -07001480 * Location or override string lists can be either files or directories as follows:
1481 * | location | override
1482 * --------------------------------
1483 * Win ICD | files | files
1484 * Win Layer | files | dirs
1485 * Linux ICD | dirs | files
1486 * Linux Layer| dirs | dirs
Jon Ashburn2077e382015-06-29 11:25:34 -06001487 */
1488static void loader_get_manifest_files(const char *env_override,
Jon Ashburnffad94d2015-06-30 14:46:22 -07001489 bool is_layer,
1490 const char *location,
1491 struct loader_manifest_files *out_files)
Jon Ashburn2077e382015-06-29 11:25:34 -06001492{
1493 char *override = NULL;
1494 char *loc;
1495 char *file, *next_file, *name;
1496 size_t alloced_count = 64;
1497 char full_path[2048];
1498 DIR *sysdir = NULL;
Jon Ashburnffad94d2015-06-30 14:46:22 -07001499 bool list_is_dirs = false;
Jon Ashburn2077e382015-06-29 11:25:34 -06001500 struct dirent *dent;
1501
1502 out_files->count = 0;
1503 out_files->filename_list = NULL;
1504
Jon Ashburn2077e382015-06-29 11:25:34 -06001505 if (env_override != NULL && (override = getenv(env_override))) {
1506#if defined(__linux__)
1507 if (geteuid() != getuid()) {
Jon Ashburnffad94d2015-06-30 14:46:22 -07001508 /* Don't allow setuid apps to use the env var: */
Jon Ashburn2077e382015-06-29 11:25:34 -06001509 override = NULL;
1510 }
1511#endif
1512 }
1513
1514 if (location == NULL) {
1515 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
Jon Ashburnffad94d2015-06-30 14:46:22 -07001516 "Can't get manifest files with NULL location, env_override=%s",
1517 env_override);
Jon Ashburn2077e382015-06-29 11:25:34 -06001518 return;
1519 }
1520
Jon Ashburnffad94d2015-06-30 14:46:22 -07001521#if defined(__linux__)
1522 list_is_dirs = (override == NULL || is_layer) ? true : false;
1523#else //WIN32
1524 list_is_dirs = (is_layer && override != NULL) ? true : false;
1525#endif
Jon Ashburn2077e382015-06-29 11:25:34 -06001526 // Make a copy of the input we are using so it is not modified
Jon Ashburnffad94d2015-06-30 14:46:22 -07001527 // Also handle getting the location(s) from registry on Windows
1528 if (override == NULL) {
1529#if defined (_WIN32)
1530 loc = loader_get_registry_files(location);
1531 if (loc == NULL) {
1532 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Registry lookup failed can't get manifest files");
1533 return;
1534 }
1535#else
Jon Ashburn2077e382015-06-29 11:25:34 -06001536 loc = alloca(strlen(location) + 1);
Jon Ashburnffad94d2015-06-30 14:46:22 -07001537 if (loc == NULL) {
1538 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files");
1539 return;
1540 }
1541 strcpy(loc, location);
1542#endif
Jon Ashburn2077e382015-06-29 11:25:34 -06001543 }
Jon Ashburnffad94d2015-06-30 14:46:22 -07001544 else {
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -06001545 loc = loader_stack_alloc(strlen(override) + 1);
Jon Ashburnffad94d2015-06-30 14:46:22 -07001546 if (loc == NULL) {
1547 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files");
1548 return;
1549 }
1550 strcpy(loc, override);
1551 }
Jon Ashburn2077e382015-06-29 11:25:34 -06001552
1553 file = loc;
1554 while (*file) {
1555 next_file = loader_get_next_path(file);
Jon Ashburnffad94d2015-06-30 14:46:22 -07001556 if (list_is_dirs) {
Jon Ashburn2077e382015-06-29 11:25:34 -06001557 sysdir = opendir(file);
1558 name = NULL;
1559 if (sysdir) {
1560 dent = readdir(sysdir);
1561 if (dent == NULL)
1562 break;
1563 name = &(dent->d_name[0]);
1564 loader_get_fullpath(name, file, sizeof(full_path), full_path);
1565 name = full_path;
1566 }
1567 }
1568 else {
Jon Ashburnffad94d2015-06-30 14:46:22 -07001569#if defined(__linux__)
1570 // only Linux has relative paths
Jon Ashburn2077e382015-06-29 11:25:34 -06001571 char *dir;
1572 // make a copy of location so it isn't modified
1573 dir = alloca(strlen(location) + 1);
1574 if (dir == NULL) {
1575 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files");
1576 return;
1577 }
1578 strcpy(dir, location);
1579
1580 loader_get_fullpath(file, dir, sizeof(full_path), full_path);
1581
1582 name = full_path;
Jon Ashburnffad94d2015-06-30 14:46:22 -07001583#else // WIN32
1584 name = file;
1585#endif
Jon Ashburn2077e382015-06-29 11:25:34 -06001586 }
1587 while (name) {
1588 /* Look for files ending with ".json" suffix */
1589 uint32_t nlen = (uint32_t) strlen(name);
1590 const char *suf = name + nlen - 5;
1591 if ((nlen > 5) && !strncmp(suf, ".json", 5)) {
1592 if (out_files->count == 0) {
1593 out_files->filename_list = malloc(alloced_count * sizeof(char *));
1594 }
1595 else if (out_files->count == alloced_count) {
1596 out_files->filename_list = realloc(out_files->filename_list,
1597 alloced_count * sizeof(char *) * 2);
1598 alloced_count *= 2;
1599 }
1600 if (out_files->filename_list == NULL) {
1601 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't alloc manifest file list");
1602 return;
1603 }
1604 out_files->filename_list[out_files->count] = malloc(strlen(name) + 1);
1605 if (out_files->filename_list[out_files->count] == NULL) {
1606 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files");
1607 return;
1608 }
1609 strcpy(out_files->filename_list[out_files->count], name);
1610 out_files->count++;
Jon Ashburnf70f3612015-07-02 10:08:47 -06001611 } else if (!list_is_dirs) {
1612 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 -06001613 }
Jon Ashburnffad94d2015-06-30 14:46:22 -07001614 if (list_is_dirs) {
Jon Ashburn2077e382015-06-29 11:25:34 -06001615 dent = readdir(sysdir);
1616 if (dent == NULL)
1617 break;
1618 name = &(dent->d_name[0]);
1619 loader_get_fullpath(name, file, sizeof(full_path), full_path);
1620 name = full_path;
1621 }
1622 else {
1623 break;
1624 }
1625 }
1626 if (sysdir)
1627 closedir(sysdir);
1628 file = next_file;
1629 }
1630 return;
1631}
1632
1633/**
1634 * Try to find the Vulkan ICD driver(s).
1635 *
1636 * This function scans the default system loader path(s) or path
1637 * specified by the \c VK_ICD_FILENAMES environment variable in
1638 * order to find loadable VK ICDs manifest files. From these
1639 * manifest files it finds the ICD libraries.
1640 *
1641 * \returns
Jon Ashburn3a37aee2015-06-30 16:44:28 -06001642 * void
Courtney Goeltzenleuchter4af9bd12014-08-01 14:18:11 -06001643 */
Jon Ashburn27cd5842015-05-12 17:26:48 -06001644void loader_icd_scan(void)
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001645{
Jon Ashburn2077e382015-06-29 11:25:34 -06001646 char *file_str;
1647 struct loader_manifest_files manifest_files;
1648
Jon Ashburn6301a0f2015-05-29 13:15:39 -06001649
1650 // convenient place to initialize a mutex
1651 loader_platform_thread_create_mutex(&loader_lock);
1652
Jon Ashburn2077e382015-06-29 11:25:34 -06001653 // convenient place to initialize logging
Courtney Goeltzenleuchter880a2a72015-06-08 15:11:18 -06001654 loader_debug_init();
1655
Jon Ashburn2077e382015-06-29 11:25:34 -06001656 // Get a list of manifest files for ICDs
1657 loader_get_manifest_files("VK_ICD_FILENAMES", false, DEFAULT_VK_DRIVERS_INFO,
1658 &manifest_files);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001659 if (manifest_files.count == 0)
1660 return;
Jon Ashburn2077e382015-06-29 11:25:34 -06001661 for (uint32_t i = 0; i < manifest_files.count; i++) {
1662 file_str = manifest_files.filename_list[i];
1663 if (file_str == NULL)
1664 continue;
1665
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001666 cJSON *json;
Jon Ashburn2077e382015-06-29 11:25:34 -06001667 json = loader_get_json(file_str);
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001668 cJSON *item;
1669 item = cJSON_GetObjectItem(json, "file_format_version");
1670 if (item == NULL)
1671 return;
1672 char *file_vers = cJSON_Print(item);
1673 loader_log(VK_DBG_REPORT_INFO_BIT, 0, "Found manifest file %s, version %s",
1674 file_str, file_vers);
1675 if (strcmp(file_vers, "\"1.0.0\"") != 0)
1676 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Unexpected manifest file version (expected 1.0.0), may cause errors");
1677 free(file_vers);
1678 item = cJSON_GetObjectItem(json, "ICD");
1679 if (item != NULL) {
1680 item = cJSON_GetObjectItem(item, "library_path");
1681 if (item != NULL) {
1682 char *icd_filename = cJSON_PrintUnformatted(item);
Jon Ashburn2077e382015-06-29 11:25:34 -06001683 char *icd_file = icd_filename;
1684 if (icd_filename != NULL) {
Jon Ashburn2077e382015-06-29 11:25:34 -06001685 char def_dir[] = DEFAULT_VK_DRIVERS_PATH;
1686 char *dir = def_dir;
1687 // strip off extra quotes
1688 if (icd_filename[strlen(icd_filename) - 1] == '"')
1689 icd_filename[strlen(icd_filename) - 1] = '\0';
1690 if (icd_filename[0] == '"')
1691 icd_filename++;
Jon Ashburnffad94d2015-06-30 14:46:22 -07001692#if defined(__linux__)
1693 char full_path[2048];
Jon Ashburn2077e382015-06-29 11:25:34 -06001694 loader_get_fullpath(icd_filename, dir, sizeof(full_path), full_path);
1695 loader_scanned_icd_add(full_path);
Jon Ashburnffad94d2015-06-30 14:46:22 -07001696#else // WIN32
1697 loader_scanned_icd_add(icd_filename);
1698#endif
Jon Ashburn2077e382015-06-29 11:25:34 -06001699 free(icd_file);
1700 }
1701 }
1702 else
1703 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"library_path\" in ICD JSON file %s, skipping", file_str);
1704 }
1705 else
1706 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"ICD\" object in ICD JSON file %s, skipping", file_str);
1707
1708 free(file_str);
1709 cJSON_Delete(json);
1710 }
1711 free(manifest_files.filename_list);
1712
Chia-I Wu5f72d0f2014-08-01 11:21:23 +08001713}
1714
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001715
Jon Ashburn5ef20602015-07-02 09:40:15 -06001716void loader_layer_scan(void)
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001717{
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001718 char *file_str;
1719 struct loader_manifest_files manifest_files;
1720 cJSON *json;
1721 uint32_t i;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001722
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001723 // Get a list of manifest files for layers
1724 loader_get_manifest_files(LAYERS_PATH_ENV, true, DEFAULT_VK_LAYERS_INFO,
1725 &manifest_files);
1726 if (manifest_files.count == 0)
Courtney Goeltzenleuchter57985ce2014-12-01 09:29:42 -07001727 return;
Jon Ashburn90c6a0e2015-06-04 15:30:58 -06001728
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001729#if 0
1730 /**
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -06001731 * We need a list of the layer libraries, not just a list of
1732 * the layer properties (a layer library could expose more than
1733 * one layer property). This list of scanned layers would be
1734 * used to check for global and physicaldevice layer properties.
1735 */
1736 if (!loader_init_layer_library_list(&loader.scanned_layer_libraries)) {
1737 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
1738 "Malloc for layer list failed: %s line: %d", __FILE__, __LINE__);
1739 return;
Jon Ashburn5ef20602015-07-02 09:40:15 -06001740 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001741#endif
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001742
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001743 // TODO use global_layer add and delete functions instead
1744 if (loader.scanned_layers.capacity == 0) {
1745 loader.scanned_layers.list = malloc(sizeof(struct loader_layer_properties) * 64);
1746 if (loader.scanned_layers.list == NULL) {
1747 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can'add any layer properties to list");
1748 return;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001749 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001750 memset(loader.scanned_layers.list, 0, sizeof(struct loader_layer_properties) * 64);
1751 loader.scanned_layers.capacity = sizeof(struct loader_layer_properties) * 64;
1752 }
1753 else {
1754 /* cleanup any previously scanned libraries */
1755 //TODO make sure everything is cleaned up properly
1756 for (i = 0; i < loader.scanned_layers.count; i++) {
1757 if (loader.scanned_layers.list[i].lib_info.lib_name != NULL)
1758 free(loader.scanned_layers.list[i].lib_info.lib_name);
1759 loader_destroy_ext_list(&loader.scanned_layers.list[i].instance_extension_list);
1760 loader_destroy_ext_list(&loader.scanned_layers.list[i].device_extension_list);
1761 loader.scanned_layers.list[i].lib_info.lib_name = NULL;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06001762 }
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001763 loader.scanned_layers.count = 0;
1764 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001765
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001766 for (i = 0; i < manifest_files.count; i++) {
1767 file_str = manifest_files.filename_list[i];
1768 if (file_str == NULL)
1769 continue;
Courtney Goeltzenleuchtera9e4af42015-06-01 14:49:17 -06001770
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001771 // parse file into JSON struct
1772 json = loader_get_json(file_str);
1773 if (!json) {
1774 continue;
1775 }
1776 // ensure enough room to add an entry
1777 if ((loader.scanned_layers.count + 1) * sizeof (struct loader_layer_properties)
1778 > loader.scanned_layers.capacity) {
1779 loader.scanned_layers.list = realloc(loader.scanned_layers.list,
1780 loader.scanned_layers.capacity * 2);
1781 if (loader.scanned_layers.list == NULL) {
1782 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
1783 "realloc failed for scanned layers");
1784 break;
1785 }
1786 loader.scanned_layers.capacity *= 2;
1787 }
1788 //TODO pass in implicit versus explicit bool
1789 loader_add_layer_properties(&loader.scanned_layers, json, false, file_str);
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -06001790
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001791 free(file_str);
1792 cJSON_Delete(json);
1793 }
1794 free(manifest_files.filename_list);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001795
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001796}
1797
Jon Ashburn27cd5842015-05-12 17:26:48 -06001798static void* VKAPI loader_gpa_instance_internal(VkInstance inst, const char * pName)
1799{
1800 // inst is not wrapped
1801 if (inst == VK_NULL_HANDLE) {
1802 return NULL;
1803 }
1804 VkLayerInstanceDispatchTable* disp_table = * (VkLayerInstanceDispatchTable **) inst;
1805 void *addr;
1806
Jon Ashburn8fd08252015-05-28 16:25:02 -06001807 if (!strcmp(pName, "vkGetInstanceProcAddr"))
1808 return (void *) loader_gpa_instance_internal;
1809
Jon Ashburn27cd5842015-05-12 17:26:48 -06001810 if (disp_table == NULL)
1811 return NULL;
1812
1813 addr = loader_lookup_instance_dispatch_table(disp_table, pName);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001814 if (addr) {
Jon Ashburn27cd5842015-05-12 17:26:48 -06001815 return addr;
Jon Ashburn3d526cb2015-04-13 18:10:06 -06001816 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001817
1818 if (disp_table->GetInstanceProcAddr == NULL) {
1819 return NULL;
1820 }
1821 return disp_table->GetInstanceProcAddr(inst, pName);
Jon Ashburn3d526cb2015-04-13 18:10:06 -06001822}
1823
Jon Ashburn128f9422015-05-28 19:16:58 -06001824struct loader_icd * loader_get_icd(const VkPhysicalDevice gpu, uint32_t *gpu_index)
Jon Ashburn876b1ac2014-10-17 15:09:07 -06001825{
Jon Ashburn128f9422015-05-28 19:16:58 -06001826
Jon Ashburn98bd4542015-01-29 16:44:24 -07001827 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) {
1828 for (struct loader_icd *icd = inst->icds; icd; icd = icd->next) {
1829 for (uint32_t i = 0; i < icd->gpu_count; i++)
Jon Ashburn128f9422015-05-28 19:16:58 -06001830 if (icd->gpus[i] == gpu) {
Jon Ashburn98bd4542015-01-29 16:44:24 -07001831 *gpu_index = i;
1832 return icd;
1833 }
1834 }
Jon Ashburn876b1ac2014-10-17 15:09:07 -06001835 }
1836 return NULL;
1837}
1838
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001839static loader_platform_dl_handle loader_add_layer_lib(
Jon Ashburn4f67d742015-05-27 13:19:22 -06001840 const char *chain_type,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06001841 struct loader_layer_properties *layer_prop)
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001842{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001843 struct loader_lib_info *new_layer_lib_list, *my_lib;
1844
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -06001845 /*
1846 * TODO: We can now track this information in the
1847 * scanned_layer_libraries list.
1848 */
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001849 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06001850 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, layer_prop->lib_info.lib_name) == 0) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001851 /* Have already loaded this library, just increment ref count */
1852 loader.loaded_layer_lib_list[i].ref_count++;
Courtney Goeltzenleuchterca8c81a2015-06-14 11:59:07 -06001853 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001854 "%s Chain: Increment layer reference count for layer library %s",
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06001855 chain_type, layer_prop->lib_info.lib_name);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001856 return loader.loaded_layer_lib_list[i].lib_handle;
1857 }
1858 }
1859
1860 /* Haven't seen this library so load it */
1861 new_layer_lib_list = realloc(loader.loaded_layer_lib_list,
1862 (loader.loaded_layer_lib_count + 1) * sizeof(struct loader_lib_info));
1863 if (!new_layer_lib_list) {
1864 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "loader: malloc failed");
1865 return NULL;
1866 }
1867
1868 my_lib = &new_layer_lib_list[loader.loaded_layer_lib_count];
1869
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06001870 /* NOTE: We require that the layer property be immutable */
1871 my_lib->lib_name = (char *) layer_prop->lib_info.lib_name;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001872 my_lib->ref_count = 0;
1873 my_lib->lib_handle = NULL;
1874
1875 if ((my_lib->lib_handle = loader_platform_open_library(my_lib->lib_name)) == NULL) {
1876 loader_log(VK_DBG_REPORT_ERROR_BIT, 0,
1877 loader_platform_open_library_error(my_lib->lib_name));
1878 return NULL;
1879 } else {
Courtney Goeltzenleuchterca8c81a2015-06-14 11:59:07 -06001880 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001881 "Chain: %s: Loading layer library %s",
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06001882 chain_type, layer_prop->lib_info.lib_name);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001883 }
1884 loader.loaded_layer_lib_count++;
1885 loader.loaded_layer_lib_list = new_layer_lib_list;
1886 my_lib->ref_count++;
1887
1888 return my_lib->lib_handle;
1889}
1890
1891static void loader_remove_layer_lib(
1892 struct loader_instance *inst,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06001893 struct loader_layer_properties *layer_prop)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001894{
1895 uint32_t idx;
1896 struct loader_lib_info *new_layer_lib_list, *my_lib;
1897
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001898 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06001899 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, layer_prop->lib_info.lib_name) == 0) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001900 /* found matching library */
1901 idx = i;
1902 my_lib = &loader.loaded_layer_lib_list[i];
1903 break;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001904 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001905 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001906
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001907 my_lib->ref_count--;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001908 if (my_lib->ref_count > 0) {
Courtney Goeltzenleuchterca8c81a2015-06-14 11:59:07 -06001909 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06001910 "Decrement reference count for layer library %s", layer_prop->lib_info.lib_name);
Jon Ashburn27cd5842015-05-12 17:26:48 -06001911 return;
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07001912 }
Jon Ashburn19c25022015-04-14 14:14:48 -06001913
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001914 loader_platform_close_library(my_lib->lib_handle);
Courtney Goeltzenleuchterca8c81a2015-06-14 11:59:07 -06001915 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06001916 "Unloading layer library %s", layer_prop->lib_info.lib_name);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001917
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001918 /* Need to remove unused library from list */
1919 new_layer_lib_list = malloc((loader.loaded_layer_lib_count - 1) * sizeof(struct loader_lib_info));
1920 if (!new_layer_lib_list) {
1921 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "loader: malloc failed");
1922 return;
1923 }
1924
1925 if (idx > 0) {
1926 /* Copy records before idx */
1927 memcpy(new_layer_lib_list, &loader.loaded_layer_lib_list[0],
1928 sizeof(struct loader_lib_info) * idx);
1929 }
1930 if (idx < (loader.loaded_layer_lib_count - 1)) {
1931 /* Copy records after idx */
1932 memcpy(&new_layer_lib_list[idx], &loader.loaded_layer_lib_list[idx+1],
1933 sizeof(struct loader_lib_info) * (loader.loaded_layer_lib_count - idx - 1));
1934 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06001935
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001936 free(loader.loaded_layer_lib_list);
1937 loader.loaded_layer_lib_count--;
1938 loader.loaded_layer_lib_list = new_layer_lib_list;
Jon Ashburnb8358052014-11-18 09:06:04 -07001939}
1940
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06001941
1942/**
1943 * Go through the search_list and find any layers which match type. If layer
1944 * type match is found in then add it to ext_list.
1945 */
1946//TODO need to handle implict layer enable env var and disable env var
Jon Ashburn0c26e712015-07-02 16:10:32 -06001947static void loader_add_layer_implicit(
1948 const enum layer_type type,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06001949 struct loader_layer_list *list,
1950 struct loader_layer_list *search_list)
Jon Ashburn0c26e712015-07-02 16:10:32 -06001951{
1952 uint32_t i;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06001953 for (i = 0; i < search_list->count; i++) {
1954 const struct loader_layer_properties *prop = &search_list->list[i];
Jon Ashburn0c26e712015-07-02 16:10:32 -06001955 if (prop->type & type) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06001956 /* Found an layer with the same type, add to layer_list */
1957 loader_add_to_layer_list(list, 1, prop);
Jon Ashburn0c26e712015-07-02 16:10:32 -06001958 }
1959 }
1960
1961}
1962
1963/**
1964 * Get the layer name(s) from the env_name environment variable. If layer
Jon Ashburnbd332cc2015-07-07 10:27:45 -06001965 * is found in search_list then add it to layer_list. But only add it to
1966 * layer_list if type matches.
Jon Ashburn0c26e712015-07-02 16:10:32 -06001967 */
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001968static void loader_add_layer_env(
Jon Ashburnbd332cc2015-07-07 10:27:45 -06001969 const enum layer_type type,
Jon Ashburneb6d5682015-07-02 14:10:53 -06001970 const char *env_name,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06001971 struct loader_layer_list *layer_list,
1972 const struct loader_layer_list *search_list)
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001973{
Ian Elliott4470a302015-02-17 10:33:47 -07001974 char *layerEnv;
Jon Ashburneb6d5682015-07-02 14:10:53 -06001975 char *next, *name;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001976
Jon Ashburneb6d5682015-07-02 14:10:53 -06001977 layerEnv = getenv(env_name);
Ian Elliott4470a302015-02-17 10:33:47 -07001978 if (layerEnv == NULL) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001979 return;
Ian Elliott4470a302015-02-17 10:33:47 -07001980 }
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -06001981 name = loader_stack_alloc(strlen(layerEnv) + 1);
Jon Ashburneb6d5682015-07-02 14:10:53 -06001982 if (name == NULL) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001983 return;
Ian Elliott4470a302015-02-17 10:33:47 -07001984 }
Jon Ashburneb6d5682015-07-02 14:10:53 -06001985 strcpy(name, layerEnv);
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001986
Jon Ashburneb6d5682015-07-02 14:10:53 -06001987 while (name && *name ) {
1988 next = loader_get_next_path(name);
Jon Ashburnbd332cc2015-07-07 10:27:45 -06001989 loader_find_layer_name_add_list(name, type, search_list, layer_list);
Jon Ashburneb6d5682015-07-02 14:10:53 -06001990 name = next;
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07001991 }
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001992
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001993 return;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06001994}
1995
Courtney Goeltzenleuchter7d0023c2015-06-08 15:09:22 -06001996void loader_deactivate_instance_layers(struct loader_instance *instance)
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06001997{
Jon Ashburnbd6c4882015-07-02 12:59:25 -06001998 if (!instance->activated_layer_list.count) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06001999 return;
2000 }
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002001
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002002 /* Create instance chain of enabled layers */
Courtney Goeltzenleuchter7d0023c2015-06-08 15:09:22 -06002003 for (uint32_t i = 0; i < instance->activated_layer_list.count; i++) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002004 struct loader_layer_properties *layer_prop = &instance->activated_layer_list.list[i];
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002005
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002006 loader_remove_layer_lib(instance, layer_prop);
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002007 }
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002008 loader_destroy_layer_list(&instance->activated_layer_list);
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002009}
2010
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002011VkResult loader_enable_instance_layers(
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002012 struct loader_instance *inst,
2013 const VkInstanceCreateInfo *pCreateInfo)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002014{
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002015 VkResult err;
2016
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002017 if (inst == NULL)
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002018 return VK_ERROR_UNKNOWN;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002019
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002020 if (!loader_init_layer_list(&inst->activated_layer_list)) {
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002021 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to malloc Instance activated layer list");
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002022 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002023 }
2024
Jon Ashburn0c26e712015-07-02 16:10:32 -06002025 /* Add any implicit layers first */
2026 loader_add_layer_implicit(
2027 VK_LAYER_TYPE_INSTANCE_IMPLICIT,
2028 &inst->activated_layer_list,
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002029 &loader.scanned_layers);
Jon Ashburn0c26e712015-07-02 16:10:32 -06002030
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002031 /* Add any layers specified via environment variable next */
Jon Ashburneb6d5682015-07-02 14:10:53 -06002032 loader_add_layer_env(
Jon Ashburnbd332cc2015-07-07 10:27:45 -06002033 VK_LAYER_TYPE_INSTANCE_EXPLICIT,
Jon Ashburneb6d5682015-07-02 14:10:53 -06002034 "VK_INSTANCE_LAYERS",
2035 &inst->activated_layer_list,
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002036 &loader.scanned_layers);
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002037
2038 /* Add layers specified by the application */
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002039 err = loader_add_layer_names_to_list(
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002040 &inst->activated_layer_list,
2041 pCreateInfo->layerCount,
2042 pCreateInfo->ppEnabledLayerNames,
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002043 &loader.scanned_layers);
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002044
2045 return err;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002046}
2047
Jon Ashburn27cd5842015-05-12 17:26:48 -06002048uint32_t loader_activate_instance_layers(struct loader_instance *inst)
2049{
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002050 uint32_t layer_idx;
Jon Ashburn128f9422015-05-28 19:16:58 -06002051 VkBaseLayerObject *wrappedInstance;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002052
David Pinedoa0a8a242015-06-24 15:29:18 -06002053 if (inst == NULL) {
Jon Ashburn27cd5842015-05-12 17:26:48 -06002054 return 0;
David Pinedoa0a8a242015-06-24 15:29:18 -06002055 }
Jon Ashburn27cd5842015-05-12 17:26:48 -06002056
2057 // NOTE inst is unwrapped at this point in time
2058 VkObject baseObj = (VkObject) inst;
2059 VkObject nextObj = (VkObject) inst;
2060 VkBaseLayerObject *nextInstObj;
2061 PFN_vkGetInstanceProcAddr nextGPA = loader_gpa_instance_internal;
2062
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002063 if (!inst->activated_layer_list.count) {
Jon Ashburn27cd5842015-05-12 17:26:48 -06002064 return 0;
2065 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002066
Courtney Goeltzenleuchter6f460c52015-07-06 09:04:55 -06002067 wrappedInstance = loader_stack_alloc(sizeof(VkBaseLayerObject)
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002068 * inst->activated_layer_list.count);
Jon Ashburn128f9422015-05-28 19:16:58 -06002069 if (!wrappedInstance) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002070 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to malloc Instance objects for layer");
2071 return 0;
2072 }
2073
2074 /* Create instance chain of enabled layers */
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002075 layer_idx = inst->activated_layer_list.count - 1;
Courtney Goeltzenleuchter0f1d8eb2015-06-07 17:28:17 -06002076 for (int32_t i = inst->activated_layer_list.count - 1; i >= 0; i--) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002077 struct loader_layer_properties *layer_prop = &inst->activated_layer_list.list[i];
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002078 loader_platform_dl_handle lib_handle;
2079
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002080 /*
Courtney Goeltzenleuchteree3b16a2015-06-01 14:12:42 -06002081 * Note: An extension's Get*ProcAddr should not return a function pointer for
2082 * any extension entry points until the extension has been enabled.
2083 * To do this requires a different behavior from Get*ProcAddr functions implemented
2084 * in layers.
2085 * The very first call to a layer will be it's Get*ProcAddr function requesting
2086 * the layer's vkGet*ProcAddr. The layer should intialize it's internal dispatch table
2087 * with the wrapped object given (either Instance or Device) and return the layer's
2088 * Get*ProcAddr function. The layer should also use this opportunity to record the
2089 * baseObject so that it can find the correct local dispatch table on future calls.
2090 * Subsequent calls to Get*ProcAddr, CreateInstance, CreateDevice
2091 * will not use a wrapped object and must look up their local dispatch table from
2092 * the given baseObject.
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002093 */
Jon Ashburn128f9422015-05-28 19:16:58 -06002094 nextInstObj = (wrappedInstance + layer_idx);
Jon Ashburn27cd5842015-05-12 17:26:48 -06002095 nextInstObj->pGPA = nextGPA;
2096 nextInstObj->baseObject = baseObj;
2097 nextInstObj->nextObject = nextObj;
2098 nextObj = (VkObject) nextInstObj;
2099
2100 char funcStr[256];
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002101 snprintf(funcStr, 256, "%sGetInstanceProcAddr", layer_prop->info.layerName);
2102 lib_handle = loader_add_layer_lib("instance", layer_prop);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002103 if ((nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, funcStr)) == NULL)
2104 nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetInstanceProcAddr");
Jon Ashburn27cd5842015-05-12 17:26:48 -06002105 if (!nextGPA) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002106 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to find vkGetInstanceProcAddr in layer %s", layer_prop->lib_info.lib_name);
Courtney Goeltzenleuchtera9e4af42015-06-01 14:49:17 -06002107
2108 /* TODO: Should we return nextObj, nextGPA to previous? */
Jon Ashburn27cd5842015-05-12 17:26:48 -06002109 continue;
2110 }
2111
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002112 loader_log(VK_DBG_REPORT_INFO_BIT, 0,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002113 "Insert instance layer %s (%s)",
2114 layer_prop->info.layerName,
2115 layer_prop->lib_info.lib_name);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002116
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002117 layer_idx--;
Jon Ashburn27cd5842015-05-12 17:26:48 -06002118 }
2119
Jon Ashburn8fd08252015-05-28 16:25:02 -06002120 loader_init_instance_core_dispatch_table(inst->disp, nextGPA, (VkInstance) nextObj, (VkInstance) baseObj);
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002121
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002122 return inst->activated_layer_list.count;
Jon Ashburn27cd5842015-05-12 17:26:48 -06002123}
2124
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002125void loader_activate_instance_layer_extensions(struct loader_instance *inst)
2126{
2127
2128 loader_init_instance_extension_dispatch_table(inst->disp,
2129 inst->disp->GetInstanceProcAddr,
Jon Ashburn128f9422015-05-28 19:16:58 -06002130 (VkInstance) inst);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002131}
2132
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002133static VkResult loader_enable_device_layers(
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -06002134 struct loader_icd *icd,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002135 struct loader_device *dev,
2136 const VkDeviceCreateInfo *pCreateInfo)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002137{
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002138 VkResult err;
2139
Jon Ashburndc6fcad2015-06-10 10:06:06 -06002140 if (dev == NULL)
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002141 return VK_ERROR_UNKNOWN;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002142
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002143 if (dev->activated_layer_list.list == NULL || dev->activated_layer_list.capacity == 0) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002144 loader_init_layer_list(&dev->activated_layer_list);
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002145 }
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002146
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002147 if (dev->activated_layer_list.list == NULL) {
2148 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to malloc device activated layer list");
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002149 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002150 }
2151
Jon Ashburn0c26e712015-07-02 16:10:32 -06002152 /* Add any implicit layers first */
2153 loader_add_layer_implicit(
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002154 VK_LAYER_TYPE_DEVICE_IMPLICIT,
2155 &dev->activated_layer_list,
Jon Ashburnbd332cc2015-07-07 10:27:45 -06002156 &loader.scanned_layers);
Jon Ashburn0c26e712015-07-02 16:10:32 -06002157
2158 /* Add any layers specified via environment variable next */
Jon Ashburneb6d5682015-07-02 14:10:53 -06002159 loader_add_layer_env(
Jon Ashburnbd332cc2015-07-07 10:27:45 -06002160 VK_LAYER_TYPE_DEVICE_EXPLICIT,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002161 "VK_DEVICE_LAYERS",
2162 &dev->activated_layer_list,
Jon Ashburnbd332cc2015-07-07 10:27:45 -06002163 &loader.scanned_layers);
Jon Ashburnbd6c4882015-07-02 12:59:25 -06002164
2165 /* Add layers specified by the application */
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002166 err = loader_add_layer_names_to_list(
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002167 &dev->activated_layer_list,
2168 pCreateInfo->layerCount,
2169 pCreateInfo->ppEnabledLayerNames,
Jon Ashburnbd332cc2015-07-07 10:27:45 -06002170 &loader.scanned_layers);
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002171
2172 return err;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002173}
2174
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002175/*
2176 * This function terminates the device chain fro CreateDevice.
2177 * CreateDevice is a special case and so the loader call's
2178 * the ICD's CreateDevice before creating the chain. Since
2179 * we can't call CreateDevice twice we must terminate the
2180 * device chain with something else.
2181 */
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002182static VkResult scratch_vkCreateDevice(
2183 VkPhysicalDevice gpu,
2184 const VkDeviceCreateInfo *pCreateInfo,
2185 VkDevice *pDevice)
2186{
2187 return VK_SUCCESS;
2188}
2189
2190static void * VKAPI loader_GetDeviceChainProcAddr(VkDevice device, const char * name)
2191{
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002192 if (!strcmp(name, "vkGetDeviceProcAddr"))
2193 return (void *) loader_GetDeviceChainProcAddr;
2194 if (!strcmp(name, "vkCreateDevice"))
2195 return (void *) scratch_vkCreateDevice;
2196
Courtney Goeltzenleuchter3e029d12015-06-29 16:09:23 -06002197 struct loader_device *found_dev;
2198 struct loader_icd *icd = loader_get_icd_and_device(device, &found_dev);
2199 return icd->GetDeviceProcAddr(device, name);
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002200}
2201
Jon Ashburndc6fcad2015-06-10 10:06:06 -06002202static uint32_t loader_activate_device_layers(
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -06002203 struct loader_icd *icd,
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002204 struct loader_device *dev,
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -06002205 VkDevice device)
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002206{
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002207 if (!icd)
2208 return 0;
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002209
David Pinedoa0a8a242015-06-24 15:29:18 -06002210 if (!dev) {
Jon Ashburndc6fcad2015-06-10 10:06:06 -06002211 return 0;
David Pinedoa0a8a242015-06-24 15:29:18 -06002212 }
Jon Ashburn94e70492015-06-10 10:13:10 -06002213
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002214 /* activate any layer libraries */
Jon Ashburn94e70492015-06-10 10:13:10 -06002215 VkObject nextObj = (VkObject) device;
2216 VkObject baseObj = nextObj;
2217 VkBaseLayerObject *nextGpuObj;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002218 PFN_vkGetDeviceProcAddr nextGPA = loader_GetDeviceChainProcAddr;
Jon Ashburn94e70492015-06-10 10:13:10 -06002219 VkBaseLayerObject *wrappedGpus;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002220
Jon Ashburn94e70492015-06-10 10:13:10 -06002221 if (!dev->activated_layer_list.count)
2222 return 0;
2223
2224 wrappedGpus = malloc(sizeof (VkBaseLayerObject) * dev->activated_layer_list.count);
2225 if (!wrappedGpus) {
2226 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to malloc Gpu objects for layer");
2227 return 0;
2228 }
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002229
Jon Ashburn94e70492015-06-10 10:13:10 -06002230 for (int32_t i = dev->activated_layer_list.count - 1; i >= 0; i--) {
2231
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002232 struct loader_layer_properties *layer_prop = &dev->activated_layer_list.list[i];
Jon Ashburn94e70492015-06-10 10:13:10 -06002233 loader_platform_dl_handle lib_handle;
2234
Jon Ashburn94e70492015-06-10 10:13:10 -06002235 nextGpuObj = (wrappedGpus + i);
2236 nextGpuObj->pGPA = nextGPA;
2237 nextGpuObj->baseObject = baseObj;
2238 nextGpuObj->nextObject = nextObj;
2239 nextObj = (VkObject) nextGpuObj;
2240
2241 char funcStr[256];
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002242 snprintf(funcStr, 256, "%sGetDeviceProcAddr", layer_prop->info.layerName);
2243 lib_handle = loader_add_layer_lib("device", layer_prop);
Jon Ashburn94e70492015-06-10 10:13:10 -06002244 if ((nextGPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, funcStr)) == NULL)
2245 nextGPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetDeviceProcAddr");
2246 if (!nextGPA) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002247 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to find vkGetDeviceProcAddr in layer %s", layer_prop->info.layerName);
Jon Ashburn94e70492015-06-10 10:13:10 -06002248 continue;
2249 }
2250
2251 loader_log(VK_DBG_REPORT_INFO_BIT, 0,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002252 "Insert device layer library %s (%s)",
2253 layer_prop->info.layerName,
2254 layer_prop->lib_info.lib_name);
Jon Ashburn94e70492015-06-10 10:13:10 -06002255
2256 }
2257
2258 loader_init_device_dispatch_table(&dev->loader_dispatch, nextGPA,
2259 (VkPhysicalDevice) nextObj, (VkPhysicalDevice) baseObj);
2260 free(wrappedGpus);
2261
Jon Ashburndc6fcad2015-06-10 10:06:06 -06002262 return dev->activated_layer_list.count;
Jon Ashburn6b4d70c2014-10-22 18:13:16 -06002263}
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002264
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002265VkResult loader_validate_layers(
2266 const uint32_t layer_count,
2267 const char * const *ppEnabledLayerNames,
2268 struct loader_layer_list *list)
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06002269{
2270 struct loader_layer_properties *prop;
2271
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002272 for (uint32_t i = 0; i < layer_count; i++) {
2273 prop = get_layer_property(ppEnabledLayerNames[i],
2274 list);
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06002275 if (!prop) {
2276 return VK_ERROR_INVALID_LAYER;
2277 }
2278 }
2279
2280 return VK_SUCCESS;
2281}
2282
2283VkResult loader_validate_instance_extensions(
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002284 const VkInstanceCreateInfo *pCreateInfo)
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06002285{
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002286 struct loader_extension_property *extension_prop;
2287 struct loader_layer_properties *layer_prop;
2288
2289 for (uint32_t i = 0; i < pCreateInfo->extensionCount; i++) {
2290 extension_prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
2291 &loader.global_extensions);
2292
2293 if (extension_prop) {
2294 continue;
2295 }
2296
2297 extension_prop = NULL;
2298
2299 /* Not in global list, search layer extension lists */
2300 for (uint32_t j = 0; j < pCreateInfo->layerCount; j++) {
2301 layer_prop = get_layer_property(pCreateInfo->ppEnabledLayerNames[i],
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002302 &loader.scanned_layers);
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002303
2304 if (!layer_prop) {
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06002305 /* Should NOT get here, loader_validate_layers
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002306 * should have already filtered this case out.
2307 */
2308 continue;
2309 }
2310
2311 extension_prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
2312 &layer_prop->instance_extension_list);
2313 if (extension_prop) {
2314 /* Found the extension in one of the layers enabled by the app. */
2315 break;
2316 }
2317 }
2318
2319 if (!extension_prop) {
2320 /* Didn't find extension name in any of the global layers, error out */
2321 return VK_ERROR_INVALID_EXTENSION;
2322 }
2323 }
2324 return VK_SUCCESS;
2325}
2326
2327VkResult loader_validate_device_extensions(
2328 struct loader_icd *icd,
2329 const VkDeviceCreateInfo *pCreateInfo)
2330{
2331 struct loader_extension_property *extension_prop;
2332 struct loader_layer_properties *layer_prop;
2333
2334 for (uint32_t i = 0; i < pCreateInfo->extensionCount; i++) {
2335 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i];
2336 extension_prop = get_extension_property(extension_name,
2337 &loader.global_extensions);
2338
2339 if (extension_prop) {
2340 continue;
2341 }
2342
2343 /* Not in global list, search layer extension lists */
2344 for (uint32_t j = 0; j < pCreateInfo->layerCount; j++) {
2345 const char *layer_name = pCreateInfo->ppEnabledLayerNames[j];
2346 layer_prop = get_layer_property(layer_name,
2347 &icd->layer_properties_cache);
2348
2349 if (!layer_prop) {
2350 /* Should NOT get here, loader_validate_instance_layers
2351 * should have already filtered this case out.
2352 */
2353 continue;
2354 }
2355
2356 extension_prop = get_extension_property(extension_name,
2357 &layer_prop->device_extension_list);
2358 if (extension_prop) {
2359 /* Found the extension in one of the layers enabled by the app. */
2360 break;
2361 }
2362 }
2363
2364 if (!extension_prop) {
2365 /* Didn't find extension name in any of the device layers, error out */
2366 return VK_ERROR_INVALID_EXTENSION;
2367 }
2368 }
Courtney Goeltzenleuchter3b8c5ff2015-07-06 17:45:08 -06002369 return VK_SUCCESS;
2370}
2371
Jon Ashburn27cd5842015-05-12 17:26:48 -06002372VkResult loader_CreateInstance(
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002373 const VkInstanceCreateInfo* pCreateInfo,
2374 VkInstance* pInstance)
Jon Ashburn1beab2d2015-01-26 14:51:40 -07002375{
Jon Ashburneed0c002015-05-21 17:42:17 -06002376 struct loader_instance *ptr_instance = *(struct loader_instance **) pInstance;
Jon Ashburn46888392015-01-29 15:45:51 -07002377 struct loader_scanned_icds *scanned_icds;
2378 struct loader_icd *icd;
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06002379 struct loader_extension_property *prop;
2380 char **filtered_extension_names = NULL;
2381 VkInstanceCreateInfo icd_create_info;
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002382 VkResult res = VK_SUCCESS;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07002383
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06002384 icd_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
2385 icd_create_info.layerCount = 0;
2386 icd_create_info.ppEnabledLayerNames = NULL;
2387 icd_create_info.pAllocCb = pCreateInfo->pAllocCb;
2388 icd_create_info.pAppInfo = pCreateInfo->pAppInfo;
2389 icd_create_info.pNext = pCreateInfo->pNext;
2390
2391 /*
2392 * NOTE: Need to filter the extensions to only those
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002393 * supported by the ICD.
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06002394 * No ICD will advertise support for layers. An ICD
2395 * library could support a layer, but it would be
2396 * independent of the actual ICD, just in the same library.
2397 */
2398 filtered_extension_names = loader_stack_alloc(pCreateInfo->extensionCount * sizeof(char *));
2399 if (!filtered_extension_names) {
2400 return VK_ERROR_OUT_OF_HOST_MEMORY;
2401 }
2402 icd_create_info.ppEnabledExtensionNames = (const char * const *) filtered_extension_names;
2403
Jon Ashburn46888392015-01-29 15:45:51 -07002404 scanned_icds = loader.scanned_icd_list;
2405 while (scanned_icds) {
2406 icd = loader_icd_add(ptr_instance, scanned_icds);
2407 if (icd) {
Courtney Goeltzenleuchter746db732015-07-06 17:42:01 -06002408
2409 icd_create_info.extensionCount = 0;
2410 for (uint32_t i = 0; i < pCreateInfo->extensionCount; i++) {
2411 prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i],
2412 &scanned_icds->global_extension_list);
2413 if (prop) {
2414 filtered_extension_names[icd_create_info.extensionCount] = (char *) pCreateInfo->ppEnabledExtensionNames[i];
2415 icd_create_info.extensionCount++;
2416 }
2417 }
2418
2419 res = scanned_icds->CreateInstance(&icd_create_info,
Jon Ashburn3da71f22015-05-14 12:43:38 -06002420 &(icd->instance));
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06002421 if (res != VK_SUCCESS)
Jon Ashburn46888392015-01-29 15:45:51 -07002422 {
2423 ptr_instance->icds = ptr_instance->icds->next;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002424 loader_icd_destroy(ptr_instance, icd);
Jon Ashburn3da71f22015-05-14 12:43:38 -06002425 icd->instance = VK_NULL_HANDLE;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002426 loader_log(VK_DBG_REPORT_WARN_BIT, 0,
Jon Ashburn46888392015-01-29 15:45:51 -07002427 "ICD ignored: failed to CreateInstance on device");
Jon Ashburn3da71f22015-05-14 12:43:38 -06002428 } else
2429 {
2430 loader_icd_init_entrys(icd, scanned_icds);
Jon Ashburn46888392015-01-29 15:45:51 -07002431 }
2432 }
2433 scanned_icds = scanned_icds->next;
2434 }
Jon Ashburn1beab2d2015-01-26 14:51:40 -07002435
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002436 /*
2437 * If no ICDs were added to instance list and res is unchanged
2438 * from it's initial value, the loader was unable to find
2439 * a suitable ICD.
2440 */
Ian Elliotteb450762015-02-05 15:19:15 -07002441 if (ptr_instance->icds == NULL) {
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002442 if (res == VK_SUCCESS) {
2443 return VK_ERROR_INCOMPATIBLE_DRIVER;
2444 } else {
2445 return res;
2446 }
Ian Elliotteb450762015-02-05 15:19:15 -07002447 }
Jon Ashburn46888392015-01-29 15:45:51 -07002448
Courtney Goeltzenleuchter40caf0b2015-07-06 09:06:34 -06002449 return VK_SUCCESS;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07002450}
2451
Jon Ashburn27cd5842015-05-12 17:26:48 -06002452VkResult loader_DestroyInstance(
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -06002453 VkInstance instance)
Jon Ashburn1beab2d2015-01-26 14:51:40 -07002454{
Courtney Goeltzenleuchterdeceded2015-06-08 15:04:02 -06002455 struct loader_instance *ptr_instance = loader_instance(instance);
Jon Ashburn3da71f22015-05-14 12:43:38 -06002456 struct loader_icd *icds = ptr_instance->icds;
Jon Ashburna6fd2612015-06-16 14:43:19 -06002457 struct loader_icd *next_icd;
Courtney Goeltzenleuchterfb4efc62015-04-10 08:34:15 -06002458 VkResult res;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07002459
2460 // Remove this instance from the list of instances:
2461 struct loader_instance *prev = NULL;
2462 struct loader_instance *next = loader.instances;
2463 while (next != NULL) {
2464 if (next == ptr_instance) {
2465 // Remove this instance from the list:
2466 if (prev)
2467 prev->next = next->next;
Jon Ashburnc5c49602015-02-03 09:26:59 -07002468 else
2469 loader.instances = next->next;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07002470 break;
2471 }
2472 prev = next;
2473 next = next->next;
2474 }
2475 if (next == NULL) {
2476 // This must be an invalid instance handle or empty list
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06002477 return VK_ERROR_INVALID_HANDLE;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07002478 }
2479
Jon Ashburn3da71f22015-05-14 12:43:38 -06002480 while (icds) {
2481 if (icds->instance) {
2482 res = icds->DestroyInstance(icds->instance);
Tony Barbourf20f87b2015-04-22 09:02:32 -06002483 if (res != VK_SUCCESS)
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002484 loader_log(VK_DBG_REPORT_WARN_BIT, 0,
Tony Barbourf20f87b2015-04-22 09:02:32 -06002485 "ICD ignored: failed to DestroyInstance on device");
2486 }
Jon Ashburna6fd2612015-06-16 14:43:19 -06002487 next_icd = icds->next;
Jon Ashburn3da71f22015-05-14 12:43:38 -06002488 icds->instance = VK_NULL_HANDLE;
Jon Ashburna6fd2612015-06-16 14:43:19 -06002489 loader_icd_destroy(ptr_instance, icds);
2490
2491 icds = next_icd;
Jon Ashburn46888392015-01-29 15:45:51 -07002492 }
2493
Jon Ashburn1beab2d2015-01-26 14:51:40 -07002494
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -06002495 return VK_SUCCESS;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07002496}
2497
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002498VkResult loader_init_physical_device_info(
2499 struct loader_instance *ptr_instance)
2500{
2501 struct loader_icd *icd;
2502 uint32_t n, count = 0;
2503 VkResult res = VK_ERROR_UNKNOWN;
2504
2505 icd = ptr_instance->icds;
2506 while (icd) {
2507 res = icd->EnumeratePhysicalDevices(icd->instance, &n, NULL);
2508 if (res != VK_SUCCESS)
2509 return res;
2510 icd->gpu_count = n;
2511 count += n;
2512 icd = icd->next;
2513 }
2514
2515 ptr_instance->total_gpu_count = count;
2516
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002517 icd = ptr_instance->icds;
2518 while (icd) {
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002519
2520 n = icd->gpu_count;
Jon Ashburn128f9422015-05-28 19:16:58 -06002521 icd->gpus = (VkPhysicalDevice *) malloc(n * sizeof(VkPhysicalDevice));
2522 if (!icd->gpus) {
2523 /* TODO: Add cleanup code here */
2524 return VK_ERROR_OUT_OF_HOST_MEMORY;
2525 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002526 res = icd->EnumeratePhysicalDevices(
2527 icd->instance,
2528 &n,
Jon Ashburn128f9422015-05-28 19:16:58 -06002529 icd->gpus);
2530 if ((res == VK_SUCCESS) && (n == icd->gpu_count)) {
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002531
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002532 for (unsigned int i = 0; i < n; i++) {
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002533
Jon Ashburn128f9422015-05-28 19:16:58 -06002534 loader_init_dispatch(icd->gpus[i], ptr_instance->disp);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002535
2536 if (!loader_init_ext_list(&icd->device_extension_cache[i])) {
2537 /* TODO: Add cleanup code here */
2538 res = VK_ERROR_OUT_OF_HOST_MEMORY;
2539 }
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002540 if (res == VK_SUCCESS) {
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002541
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002542 loader_add_physical_device_extensions(
2543 icd->GetPhysicalDeviceExtensionProperties,
2544 icd->gpus[0],
2545 VK_EXTENSION_ORIGIN_ICD,
2546 icd->scanned_icds->lib_name,
2547 &icd->device_extension_cache[i]);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002548
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002549 for (uint32_t l = 0; l < loader.scanned_layers.count; l++) {
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002550 loader_platform_dl_handle lib_handle;
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002551 char *lib_name = loader.scanned_layers.list[l].lib_info.lib_name;
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002552
2553 lib_handle = loader_platform_open_library(lib_name);
2554 if (lib_handle == NULL) {
2555 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, "open library failed: %s", lib_name);
2556 continue;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002557 }
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002558 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0,
2559 "library: %s", lib_name);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002560
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002561 loader_add_physical_device_layer_properties(
2562 icd, lib_name, lib_handle);
2563
2564 loader_platform_close_library(lib_handle);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002565 }
2566 }
2567
2568 if (res != VK_SUCCESS) {
2569 /* clean up any extension lists previously created before this request failed */
2570 for (uint32_t j = 0; j < i; j++) {
2571 loader_destroy_ext_list(&icd->device_extension_cache[i]);
2572 }
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002573
2574 loader_destroy_layer_list(&icd->layer_properties_cache);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002575 return res;
2576 }
2577 }
2578
2579 count += n;
2580 }
2581
2582 icd = icd->next;
2583 }
2584
2585 return VK_SUCCESS;
2586}
2587
Jon Ashburn27cd5842015-05-12 17:26:48 -06002588VkResult loader_EnumeratePhysicalDevices(
Courtney Goeltzenleuchter5e41f1d2015-04-20 12:48:54 -06002589 VkInstance instance,
2590 uint32_t* pPhysicalDeviceCount,
2591 VkPhysicalDevice* pPhysicalDevices)
Jon Ashburn1beab2d2015-01-26 14:51:40 -07002592{
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002593 uint32_t index = 0;
Jon Ashburn4c392fb2015-01-28 19:57:09 -07002594 struct loader_instance *ptr_instance = (struct loader_instance *) instance;
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002595 struct loader_icd *icd = ptr_instance->icds;
Jon Ashburn4c392fb2015-01-28 19:57:09 -07002596
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002597 if (ptr_instance->total_gpu_count == 0) {
2598 loader_init_physical_device_info(ptr_instance);
Jon Ashburn4c392fb2015-01-28 19:57:09 -07002599 }
2600
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002601 *pPhysicalDeviceCount = ptr_instance->total_gpu_count;
2602 if (!pPhysicalDevices) {
2603 return VK_SUCCESS;
2604 }
Jon Ashburn4c392fb2015-01-28 19:57:09 -07002605
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002606 while (icd) {
2607 assert((index + icd->gpu_count) <= *pPhysicalDeviceCount);
Jon Ashburn128f9422015-05-28 19:16:58 -06002608 memcpy(&pPhysicalDevices[index], icd->gpus, icd->gpu_count * sizeof(VkPhysicalDevice));
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06002609 index += icd->gpu_count;
2610 icd = icd->next;
2611 }
2612
2613 return VK_SUCCESS;
Jon Ashburn1beab2d2015-01-26 14:51:40 -07002614}
2615
Tony Barbour59a47322015-06-24 16:06:58 -06002616VkResult loader_GetPhysicalDeviceProperties(
Jon Ashburn3da71f22015-05-14 12:43:38 -06002617 VkPhysicalDevice gpu,
Tony Barbour59a47322015-06-24 16:06:58 -06002618 VkPhysicalDeviceProperties* pProperties)
Jon Ashburn3da71f22015-05-14 12:43:38 -06002619{
2620 uint32_t gpu_index;
Jon Ashburn128f9422015-05-28 19:16:58 -06002621 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
Jon Ashburn3da71f22015-05-14 12:43:38 -06002622 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2623
Tony Barbour59a47322015-06-24 16:06:58 -06002624 if (icd->GetPhysicalDeviceProperties)
2625 res = icd->GetPhysicalDeviceProperties(gpu, pProperties);
2626
2627 return res;
2628}
2629
2630VkResult loader_GetPhysicalDevicePerformance(
2631 VkPhysicalDevice gpu,
2632 VkPhysicalDevicePerformance* pPerformance)
2633{
2634 uint32_t gpu_index;
2635 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
2636 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2637
2638 if (icd->GetPhysicalDevicePerformance)
2639 res = icd->GetPhysicalDevicePerformance(gpu, pPerformance);
2640
2641 return res;
2642}
2643
2644VkResult loader_GetPhysicalDeviceQueueCount(
2645 VkPhysicalDevice gpu,
2646 uint32_t* pCount)
2647{
2648 uint32_t gpu_index;
2649 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
2650 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2651
2652 if (icd->GetPhysicalDeviceQueueCount)
2653 res = icd->GetPhysicalDeviceQueueCount(gpu, pCount);
2654
2655 return res;
2656}
2657
2658VkResult loader_GetPhysicalDeviceQueueProperties (
2659 VkPhysicalDevice gpu,
2660 uint32_t count,
2661 VkPhysicalDeviceQueueProperties * pProperties)
2662{
2663 uint32_t gpu_index;
2664 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
2665 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2666
2667 if (icd->GetPhysicalDeviceQueueProperties)
2668 res = icd->GetPhysicalDeviceQueueProperties(gpu, count, pProperties);
2669
2670 return res;
2671}
2672
2673VkResult loader_GetPhysicalDeviceMemoryProperties (
2674 VkPhysicalDevice gpu,
2675 VkPhysicalDeviceMemoryProperties* pProperties)
2676{
2677 uint32_t gpu_index;
2678 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
2679 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2680
2681 if (icd->GetPhysicalDeviceMemoryProperties)
2682 res = icd->GetPhysicalDeviceMemoryProperties(gpu, pProperties);
Jon Ashburn3da71f22015-05-14 12:43:38 -06002683
2684 return res;
2685}
2686
Chris Forbesbc0bb772015-06-21 22:55:02 +12002687VkResult loader_GetPhysicalDeviceFeatures(
2688 VkPhysicalDevice physicalDevice,
2689 VkPhysicalDeviceFeatures* pFeatures)
2690{
2691 uint32_t gpu_index;
2692 struct loader_icd *icd = loader_get_icd(physicalDevice, &gpu_index);
2693 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2694
2695 if (icd->GetPhysicalDeviceFeatures)
2696 res = icd->GetPhysicalDeviceFeatures(physicalDevice, pFeatures);
2697
2698 return res;
2699}
2700
2701VkResult loader_GetPhysicalDeviceFormatInfo(
2702 VkPhysicalDevice physicalDevice,
2703 VkFormat format,
2704 VkFormatProperties* pFormatInfo)
2705{
2706 uint32_t gpu_index;
2707 struct loader_icd *icd = loader_get_icd(physicalDevice, &gpu_index);
2708 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2709
2710 if (icd->GetPhysicalDeviceFormatInfo)
2711 res = icd->GetPhysicalDeviceFormatInfo(physicalDevice, format, pFormatInfo);
2712
2713 return res;
2714}
2715
2716VkResult loader_GetPhysicalDeviceLimits(
2717 VkPhysicalDevice physicalDevice,
2718 VkPhysicalDeviceLimits* pLimits)
2719{
2720 uint32_t gpu_index;
2721 struct loader_icd *icd = loader_get_icd(physicalDevice, &gpu_index);
2722 VkResult res = VK_ERROR_INITIALIZATION_FAILED;
2723
2724 if (icd->GetPhysicalDeviceLimits)
2725 res = icd->GetPhysicalDeviceLimits(physicalDevice, pLimits);
2726
2727 return res;
2728}
2729
Jon Ashburn95a77ba2015-05-15 15:09:35 -06002730VkResult loader_CreateDevice(
2731 VkPhysicalDevice gpu,
2732 const VkDeviceCreateInfo* pCreateInfo,
2733 VkDevice* pDevice)
2734{
2735 uint32_t gpu_index;
Jon Ashburn128f9422015-05-28 19:16:58 -06002736 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
Jon Ashburndc6fcad2015-06-10 10:06:06 -06002737 struct loader_device *dev;
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06002738 VkDeviceCreateInfo device_create_info;
2739 char **filtered_extension_names = NULL;
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002740 VkResult res;
Jon Ashburn95a77ba2015-05-15 15:09:35 -06002741
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002742 if (!icd->CreateDevice) {
2743 return VK_ERROR_INITIALIZATION_FAILED;
Jon Ashburn95a77ba2015-05-15 15:09:35 -06002744 }
2745
Courtney Goeltzenleuchter366b27a2015-07-06 20:14:18 -06002746 res = loader_validate_layers(pCreateInfo->layerCount,
2747 pCreateInfo->ppEnabledLayerNames,
2748 &icd->layer_properties_cache);
2749 if (res != VK_SUCCESS) {
2750 return res;
2751 }
2752
2753 res = loader_validate_device_extensions(icd, pCreateInfo);
2754 if (res != VK_SUCCESS) {
2755 return res;
2756 }
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002757
Courtney Goeltzenleuchter6f5b00c2015-07-06 20:46:50 -06002758 /*
2759 * NOTE: Need to filter the extensions to only those
2760 * supported by the ICD.
2761 * No ICD will advertise support for layers. An ICD
2762 * library could support a layer, but it would be
2763 * independent of the actual ICD, just in the same library.
2764 */
2765 filtered_extension_names = loader_stack_alloc(pCreateInfo->extensionCount * sizeof(char *));
2766 if (!filtered_extension_names) {
2767 return VK_ERROR_OUT_OF_HOST_MEMORY;
2768 }
2769
2770 /* Copy user's data */
2771 memcpy(&device_create_info, pCreateInfo, sizeof(VkDeviceCreateInfo));
2772
2773 /* ICD's do not use layers */
2774 device_create_info.layerCount = 0;
2775 device_create_info.ppEnabledLayerNames = NULL;
2776
2777 device_create_info.extensionCount = 0;
2778 device_create_info.ppEnabledExtensionNames = (const char * const *) filtered_extension_names;
2779
2780 for (uint32_t i = 0; i < pCreateInfo->extensionCount; i++) {
2781 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i];
2782 struct loader_extension_property *prop = get_extension_property(extension_name,
2783 &icd->device_extension_cache[gpu_index]);
2784 if (prop) {
2785 filtered_extension_names[device_create_info.extensionCount] = (char *) extension_name;
2786 device_create_info.extensionCount++;
2787 }
2788 }
2789
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002790 res = icd->CreateDevice(gpu, pCreateInfo, pDevice);
2791 if (res != VK_SUCCESS) {
2792 return res;
2793 }
2794
2795 dev = loader_add_logical_device(*pDevice, &icd->logical_device_list);
2796 if (dev == NULL) {
2797 return VK_ERROR_OUT_OF_HOST_MEMORY;
2798 }
2799 PFN_vkGetDeviceProcAddr get_proc_addr = icd->GetDeviceProcAddr;
2800 loader_init_device_dispatch_table(&dev->loader_dispatch, get_proc_addr,
2801 icd->gpus[gpu_index], icd->gpus[gpu_index]);
2802
2803 dev->loader_dispatch.CreateDevice = scratch_vkCreateDevice;
2804 loader_init_dispatch(*pDevice, &dev->loader_dispatch);
2805
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002806 /*
2807 * Put together the complete list of extensions to enable
2808 * This includes extensions requested via environment variables.
2809 */
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -06002810 loader_enable_device_layers(icd, dev, pCreateInfo);
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002811
2812 /*
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002813 * Load the libraries and build the device chain
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002814 * terminating with the selected device.
2815 */
Courtney Goeltzenleuchter371de702015-07-05 12:53:31 -06002816 loader_activate_device_layers(icd, dev, *pDevice);
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -06002817
2818 res = dev->loader_dispatch.CreateDevice(gpu, pCreateInfo, pDevice);
2819
2820 dev->loader_dispatch.CreateDevice = icd->CreateDevice;
2821
Jon Ashburn95a77ba2015-05-15 15:09:35 -06002822 return res;
2823}
2824
Courtney Goeltzenleuchter9ec39ac2015-06-22 17:45:21 -06002825static void * VKAPI loader_GetInstanceProcAddr(VkInstance instance, const char * pName)
Jon Ashburnb0fbe912015-05-06 10:15:07 -06002826{
Jon Ashburn07daee72015-05-21 18:13:33 -06002827 if (instance == VK_NULL_HANDLE)
2828 return NULL;
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002829
Jon Ashburn07daee72015-05-21 18:13:33 -06002830 void *addr;
2831 /* get entrypoint addresses that are global (in the loader)*/
2832 addr = globalGetProcAddr(pName);
2833 if (addr)
2834 return addr;
Jon Ashburnb0fbe912015-05-06 10:15:07 -06002835
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002836 struct loader_instance *ptr_instance = (struct loader_instance *) instance;
2837
Jon Ashburn922c8f62015-06-18 09:05:37 -06002838 /* return any extension global entrypoints */
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002839 addr = debug_report_instance_gpa(ptr_instance, pName);
2840 if (addr) {
2841 return addr;
2842 }
2843
Jon Ashburn922c8f62015-06-18 09:05:37 -06002844 /* TODO Remove this once WSI has no loader special code */
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002845 addr = wsi_lunarg_GetInstanceProcAddr(instance, pName);
David Pinedoa0a8a242015-06-24 15:29:18 -06002846 if (addr) {
Jon Ashburn922c8f62015-06-18 09:05:37 -06002847 return addr;
David Pinedoa0a8a242015-06-24 15:29:18 -06002848 }
Jon Ashburn07daee72015-05-21 18:13:33 -06002849
2850 /* return the instance dispatch table entrypoint for extensions */
2851 const VkLayerInstanceDispatchTable *disp_table = * (VkLayerInstanceDispatchTable **) instance;
2852 if (disp_table == NULL)
2853 return NULL;
2854
2855 addr = loader_lookup_instance_dispatch_table(disp_table, pName);
2856 if (addr)
2857 return addr;
Jon Ashburnb0fbe912015-05-06 10:15:07 -06002858
2859 return NULL;
2860}
2861
Courtney Goeltzenleuchter9ec39ac2015-06-22 17:45:21 -06002862LOADER_EXPORT void * VKAPI vkGetInstanceProcAddr(VkInstance instance, const char * pName)
2863{
2864 return loader_GetInstanceProcAddr(instance, pName);
2865}
2866
2867static void * VKAPI loader_GetDeviceProcAddr(VkDevice device, const char * pName)
Jon Ashburn1beab2d2015-01-26 14:51:40 -07002868{
Jon Ashburn8d1b0b52015-05-18 13:20:15 -06002869 if (device == VK_NULL_HANDLE) {
2870 return NULL;
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07002871 }
Jon Ashburn3d526cb2015-04-13 18:10:06 -06002872
Chia-I Wuf46b81a2015-01-04 11:12:47 +08002873 void *addr;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002874
Jon Ashburn3d526cb2015-04-13 18:10:06 -06002875 /* for entrypoints that loader must handle (ie non-dispatchable or create object)
2876 make sure the loader entrypoint is returned */
2877 addr = loader_non_passthrough_gpa(pName);
Ian Elliotte19c9152015-04-15 12:53:19 -06002878 if (addr) {
Jon Ashburn3d526cb2015-04-13 18:10:06 -06002879 return addr;
Ian Elliotte19c9152015-04-15 12:53:19 -06002880 }
Jon Ashburn3d526cb2015-04-13 18:10:06 -06002881
Jon Ashburn07daee72015-05-21 18:13:33 -06002882 /* return any extension device entrypoints the loader knows about */
Jon Ashburn922c8f62015-06-18 09:05:37 -06002883 /* TODO once WSI has no loader special code remove this */
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002884 addr = wsi_lunarg_GetDeviceProcAddr(device, pName);
David Pinedoa0a8a242015-06-24 15:29:18 -06002885 if (addr) {
Courtney Goeltzenleuchterf579fa62015-06-10 17:39:03 -06002886 return addr;
David Pinedoa0a8a242015-06-24 15:29:18 -06002887 }
Jon Ashburn07daee72015-05-21 18:13:33 -06002888
Jon Ashburn3d526cb2015-04-13 18:10:06 -06002889 /* return the dispatch table entrypoint for the fastest case */
Jon Ashburn8d1b0b52015-05-18 13:20:15 -06002890 const VkLayerDispatchTable *disp_table = * (VkLayerDispatchTable **) device;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002891 if (disp_table == NULL)
2892 return NULL;
2893
Jon Ashburn27cd5842015-05-12 17:26:48 -06002894 addr = loader_lookup_device_dispatch_table(disp_table, pName);
Chia-I Wuf46b81a2015-01-04 11:12:47 +08002895 if (addr)
2896 return addr;
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002897 else {
Jon Ashburn8d1b0b52015-05-18 13:20:15 -06002898 if (disp_table->GetDeviceProcAddr == NULL)
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002899 return NULL;
Jon Ashburn8d1b0b52015-05-18 13:20:15 -06002900 return disp_table->GetDeviceProcAddr(device, pName);
Jon Ashburnd38bfb12014-10-14 19:15:22 -06002901 }
2902}
2903
Courtney Goeltzenleuchter9ec39ac2015-06-22 17:45:21 -06002904LOADER_EXPORT void * VKAPI vkGetDeviceProcAddr(VkDevice device, const char * pName)
2905{
2906 return loader_GetDeviceProcAddr(device, pName);
2907}
2908
Tony Barbour59a47322015-06-24 16:06:58 -06002909LOADER_EXPORT VkResult VKAPI vkGetGlobalExtensionProperties(
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002910 const char* pLayerName,
2911 uint32_t* pCount,
2912 VkExtensionProperties* pProperties)
2913{
2914 struct loader_extension_list *global_extension_list;
2915
2916 /* Scan/discover all ICD libraries in a single-threaded manner */
2917 loader_platform_thread_once(&once_icd, loader_icd_scan);
2918
2919 /* get layer libraries in a single-threaded manner */
2920 loader_platform_thread_once(&once_layer, loader_layer_scan);
2921
2922 /* merge any duplicate extensions */
2923 loader_platform_thread_once(&once_exts, loader_coalesce_extensions);
2924
2925 uint32_t copy_size;
2926
2927 if (pCount == NULL) {
2928 return VK_ERROR_INVALID_POINTER;
2929 }
2930
2931 loader_platform_thread_lock_mutex(&loader_lock);
2932
2933 global_extension_list = loader_global_extensions(pLayerName);
2934 if (global_extension_list == NULL) {
2935 loader_platform_thread_unlock_mutex(&loader_lock);
2936 return VK_ERROR_INVALID_LAYER;
2937 }
2938
2939 if (pProperties == NULL) {
2940 *pCount = global_extension_list->count;
2941 loader_platform_thread_unlock_mutex(&loader_lock);
2942 return VK_SUCCESS;
2943 }
2944
2945 copy_size = *pCount < global_extension_list->count ? *pCount : global_extension_list->count;
2946 for (uint32_t i = 0; i < copy_size; i++) {
2947 memcpy(&pProperties[i],
2948 &global_extension_list->list[i].info,
2949 sizeof(VkExtensionProperties));
2950 }
2951 *pCount = copy_size;
2952
2953 loader_platform_thread_unlock_mutex(&loader_lock);
2954
2955 if (copy_size < global_extension_list->count) {
2956 return VK_INCOMPLETE;
2957 }
2958
2959 return VK_SUCCESS;
2960}
2961
2962LOADER_EXPORT VkResult VKAPI vkGetGlobalLayerProperties(
2963 uint32_t* pCount,
2964 VkLayerProperties* pProperties)
Tony Barbour59a47322015-06-24 16:06:58 -06002965{
Jon Ashburn6301a0f2015-05-29 13:15:39 -06002966
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06002967 /* Scan/discover all ICD libraries in a single-threaded manner */
2968 loader_platform_thread_once(&once_icd, loader_icd_scan);
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07002969
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06002970 /* get layer libraries in a single-threaded manner */
Jon Ashburn5ef20602015-07-02 09:40:15 -06002971 loader_platform_thread_once(&once_layer, loader_layer_scan);
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07002972
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06002973 /* merge any duplicate extensions */
2974 loader_platform_thread_once(&once_exts, loader_coalesce_extensions);
2975
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002976 uint32_t copy_size;
Jon Ashburn9fd4cc42015-04-10 14:33:07 -06002977
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002978 if (pCount == NULL) {
2979 return VK_ERROR_INVALID_POINTER;
2980 }
2981
2982 /* TODO: do we still need to lock */
Jon Ashburn6301a0f2015-05-29 13:15:39 -06002983 loader_platform_thread_lock_mutex(&loader_lock);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002984
2985 struct loader_layer_list *layer_list;
Jon Ashburn2d0c4bb2015-07-06 15:40:35 -06002986 layer_list = loader_scanned_layers();
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06002987
2988 if (pProperties == NULL) {
2989 *pCount = layer_list->count;
2990 loader_platform_thread_unlock_mutex(&loader_lock);
2991 return VK_SUCCESS;
2992 }
2993
2994 copy_size = *pCount < layer_list->count ? *pCount : layer_list->count;
2995 for (uint32_t i = 0; i < copy_size; i++) {
2996 memcpy(&pProperties[i], &layer_list->list[i].info, sizeof(VkLayerProperties));
2997 }
2998 *pCount = copy_size;
Tony Barbour59a47322015-06-24 16:06:58 -06002999
Jon Ashburn6301a0f2015-05-29 13:15:39 -06003000 loader_platform_thread_unlock_mutex(&loader_lock);
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003001
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003002 if (copy_size < layer_list->count) {
3003 return VK_INCOMPLETE;
3004 }
Tony Barbour59a47322015-06-24 16:06:58 -06003005
3006 return VK_SUCCESS;
3007}
3008
3009VkResult loader_GetPhysicalDeviceExtensionProperties(
3010 VkPhysicalDevice gpu,
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003011 const char* pLayerName,
3012 uint32_t* pCount,
Tony Barbour59a47322015-06-24 16:06:58 -06003013 VkExtensionProperties* pProperties)
3014{
3015 uint32_t gpu_index;
Jon Ashburn128f9422015-05-28 19:16:58 -06003016 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003017 uint32_t copy_size;
Courtney Goeltzenleuchter499b3ba2015-02-27 15:19:33 -07003018
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003019 if (pCount == NULL) {
3020 return VK_ERROR_INVALID_POINTER;
3021 }
Jon Ashburn95a77ba2015-05-15 15:09:35 -06003022
Courtney Goeltzenleuchter110fdf92015-06-29 15:39:26 -06003023 uint32_t count;
3024 struct loader_extension_list *list;
3025 loader_physical_device_extensions(icd, gpu_index, pLayerName, &count, &list);
3026
3027 if (pProperties == NULL) {
3028 *pCount = count;
3029 return VK_SUCCESS;
3030 }
3031
3032 copy_size = *pCount < count ? *pCount : count;
3033 for (uint32_t i = 0; i < copy_size; i++) {
3034 memcpy(&pProperties[i],
3035 &list->list[i].info,
3036 sizeof(VkExtensionProperties));
3037 }
3038 *pCount = copy_size;
3039
3040 if (copy_size < count) {
3041 return VK_INCOMPLETE;
3042 }
3043
3044 return VK_SUCCESS;
3045}
3046
3047VkResult loader_GetPhysicalDeviceLayerProperties(
3048 VkPhysicalDevice gpu,
3049 uint32_t* pCount,
3050 VkLayerProperties* pProperties)
3051{
3052 uint32_t gpu_index;
3053 struct loader_icd *icd = loader_get_icd(gpu, &gpu_index);
3054 uint32_t copy_size;
3055
3056 if (pCount == NULL) {
3057 return VK_ERROR_INVALID_POINTER;
3058 }
3059
3060 uint32_t count;
3061 struct loader_layer_list *layer_list;
3062 loader_physical_device_layers(icd, &count, &layer_list);
3063
3064 if (pProperties == NULL) {
3065 *pCount = count;
3066 return VK_SUCCESS;
3067 }
3068
3069 copy_size = *pCount < count ? *pCount : count;
3070 for (uint32_t i = 0; i < copy_size; i++) {
3071 memcpy(&pProperties[i],
3072 &layer_list->list[i].info,
3073 sizeof(VkLayerProperties));
3074 }
3075 *pCount = copy_size;
3076
3077 if (copy_size < count) {
3078 return VK_INCOMPLETE;
3079 }
Courtney Goeltzenleuchterd971b612015-06-17 20:51:59 -06003080
3081 return VK_SUCCESS;
Jon Ashburn95a77ba2015-05-15 15:09:35 -06003082}