loader.c revision b3e934dd44eaf3fb9c74c1789e8d7ac71918a8b6
1b1928704201034c785a26296a49f69355eb56a05Nick Lewycky/* 2b1928704201034c785a26296a49f69355eb56a05Nick Lewycky * 3b1928704201034c785a26296a49f69355eb56a05Nick Lewycky * Copyright (C) 2015 Valve Corporation 4b1928704201034c785a26296a49f69355eb56a05Nick Lewycky * 5b1928704201034c785a26296a49f69355eb56a05Nick Lewycky * Permission is hereby granted, free of charge, to any person obtaining a 6b1928704201034c785a26296a49f69355eb56a05Nick Lewycky * copy of this software and associated documentation files (the "Software"), 7b1928704201034c785a26296a49f69355eb56a05Nick Lewycky * to deal in the Software without restriction, including without limitation 8b1928704201034c785a26296a49f69355eb56a05Nick Lewycky * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9b1928704201034c785a26296a49f69355eb56a05Nick Lewycky * and/or sell copies of the Software, and to permit persons to whom the 10b1928704201034c785a26296a49f69355eb56a05Nick Lewycky * Software is furnished to do so, subject to the following conditions: 11b1928704201034c785a26296a49f69355eb56a05Nick Lewycky * 12b1928704201034c785a26296a49f69355eb56a05Nick Lewycky * The above copyright notice and this permission notice shall be included 13b1928704201034c785a26296a49f69355eb56a05Nick Lewycky * in all copies or substantial portions of the Software. 14b1928704201034c785a26296a49f69355eb56a05Nick Lewycky * 15b1928704201034c785a26296a49f69355eb56a05Nick Lewycky * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16b1928704201034c785a26296a49f69355eb56a05Nick Lewycky * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17b1928704201034c785a26296a49f69355eb56a05Nick Lewycky * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18b1928704201034c785a26296a49f69355eb56a05Nick Lewycky * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19b1928704201034c785a26296a49f69355eb56a05Nick Lewycky * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21b1928704201034c785a26296a49f69355eb56a05Nick Lewycky * DEALINGS IN THE SOFTWARE. 22b1928704201034c785a26296a49f69355eb56a05Nick Lewycky * 2306cb8ed00696eb14d1b831921452e50ec0568ea2Chandler Carruth * Author: Chia-I Wu <olvaffe@gmail.com> 24b1928704201034c785a26296a49f69355eb56a05Nick Lewycky * Author: Courtney Goeltzenleuchter <courtney@LunarG.com> 25b1928704201034c785a26296a49f69355eb56a05Nick Lewycky * Author: Ian Elliott <ian@LunarG.com> 26b1928704201034c785a26296a49f69355eb56a05Nick Lewycky * Author: Jon Ashburn <jon@lunarg.com> 27d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth * 280b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth */ 290b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth 300b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#define _GNU_SOURCE 31d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include <stdio.h> 32a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky#include <stdlib.h> 3306cb8ed00696eb14d1b831921452e50ec0568ea2Chandler Carruth#include <stdarg.h> 3406cb8ed00696eb14d1b831921452e50ec0568ea2Chandler Carruth#include <stdbool.h> 3539c41c3c93e0d223792acb093adce21a714b01c6Bill Wendling#include <string.h> 3606cb8ed00696eb14d1b831921452e50ec0568ea2Chandler Carruth 37a11c3e25015a62c817e60ec4f955a7f3f3bb6c67Rafael Espindola#include <sys/types.h> 3806cb8ed00696eb14d1b831921452e50ec0568ea2Chandler Carruth#if defined(_WIN32) 3906cb8ed00696eb14d1b831921452e50ec0568ea2Chandler Carruth#include "dirent_on_windows.h" 40c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky#else // _WIN32 41b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include <dirent.h> 42b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#endif // _WIN32 43b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include "vk_loader_platform.h" 44b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include "loader.h" 45a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky#include "gpa_helper.h" 46a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky#include "table_ops.h" 47a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky#include "debug_report.h" 48a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky#include "wsi.h" 49a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky#include "vulkan/vk_icd.h" 50a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky#include "cJSON.h" 51a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky#include "murmurhash.h" 52a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky 53a204ef3168c8804808c716115ba915c89d8849b9Nick Lewyckystatic loader_platform_dl_handle loader_add_layer_lib( 54a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky const struct loader_instance *inst, 55a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky const char *chain_type, 56a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky struct loader_layer_properties *layer_prop); 57a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky 58a204ef3168c8804808c716115ba915c89d8849b9Nick Lewyckystatic void loader_remove_layer_lib( 59a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky struct loader_instance *inst, 60a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky struct loader_layer_properties *layer_prop); 61a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky 62a204ef3168c8804808c716115ba915c89d8849b9Nick Lewyckystruct loader_struct loader = {0}; 63a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky// TLS for instance for alloc/free callbacks 64a204ef3168c8804808c716115ba915c89d8849b9Nick LewyckyTHREAD_LOCAL_DECL struct loader_instance *tls_instance; 65b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 66b1928704201034c785a26296a49f69355eb56a05Nick Lewyckystatic bool loader_init_generic_list( 67b1928704201034c785a26296a49f69355eb56a05Nick Lewycky const struct loader_instance *inst, 68b1928704201034c785a26296a49f69355eb56a05Nick Lewycky struct loader_generic_list *list_info, 69a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky size_t element_size); 70a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky 71a204ef3168c8804808c716115ba915c89d8849b9Nick Lewyckystatic int loader_platform_combine_path(char *dest, int len, ...); 72a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky 73a204ef3168c8804808c716115ba915c89d8849b9Nick Lewyckystruct loader_phys_dev_per_icd { 74a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky uint32_t count; 75a61e52c9b7cf874b46cef687c1c4627a35952542Nick Lewycky VkPhysicalDevice *phys_devs; 76a61e52c9b7cf874b46cef687c1c4627a35952542Nick Lewycky}; 77a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky 78a204ef3168c8804808c716115ba915c89d8849b9Nick Lewyckyenum loader_debug { 79a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky LOADER_INFO_BIT = 0x01, 80a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky LOADER_WARN_BIT = 0x02, 81a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky LOADER_PERF_BIT = 0x04, 82a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky LOADER_ERROR_BIT = 0x08, 83a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky LOADER_DEBUG_BIT = 0x10, 84a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky}; 85b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 86b1928704201034c785a26296a49f69355eb56a05Nick Lewyckyuint32_t g_loader_debug = 0; 87b1928704201034c785a26296a49f69355eb56a05Nick Lewyckyuint32_t g_loader_log_msgs = 0; 88b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 89b1928704201034c785a26296a49f69355eb56a05Nick Lewycky//thread safety lock for accessing global data structures such as "loader" 90a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky// all entrypoints on the instance chain need to be locked except GPA 91b1928704201034c785a26296a49f69355eb56a05Nick Lewycky// additionally CreateDevice and DestroyDevice needs to be locked 92269687fa350c1aa044bc063c64362a04ecabaa33Nick Lewyckyloader_platform_thread_mutex loader_lock; 93269687fa350c1aa044bc063c64362a04ecabaa33Nick Lewyckyloader_platform_thread_mutex loader_json_lock; 9464a0a33307723957bf2f15e3181a290853c6f833Nick Lewycky 9564a0a33307723957bf2f15e3181a290853c6f833Nick Lewycky// This table contains the loader's instance dispatch table, which contains 96b1928704201034c785a26296a49f69355eb56a05Nick Lewycky// default functions if no instance layers are activated. This contains 970c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewycky// pointers to "terminator functions". 980c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewyckyconst VkLayerInstanceDispatchTable instance_disp = { 99f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel .GetInstanceProcAddr = vkGetInstanceProcAddr, 1000c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewycky .CreateInstance = loader_CreateInstance, 101b1928704201034c785a26296a49f69355eb56a05Nick Lewycky .DestroyInstance = loader_DestroyInstance, 102b1928704201034c785a26296a49f69355eb56a05Nick Lewycky .EnumeratePhysicalDevices = loader_EnumeratePhysicalDevices, 10377b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling .GetPhysicalDeviceFeatures = loader_GetPhysicalDeviceFeatures, 104b1928704201034c785a26296a49f69355eb56a05Nick Lewycky .GetPhysicalDeviceFormatProperties = loader_GetPhysicalDeviceFormatProperties, 105b1928704201034c785a26296a49f69355eb56a05Nick Lewycky .GetPhysicalDeviceImageFormatProperties = loader_GetPhysicalDeviceImageFormatProperties, 10618764716861243c58a711a92190624dc2f6aafc9Bill Wendling .GetPhysicalDeviceProperties = loader_GetPhysicalDeviceProperties, 107d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling .GetPhysicalDeviceQueueFamilyProperties = loader_GetPhysicalDeviceQueueFamilyProperties, 108b1928704201034c785a26296a49f69355eb56a05Nick Lewycky .GetPhysicalDeviceMemoryProperties = loader_GetPhysicalDeviceMemoryProperties, 109b1928704201034c785a26296a49f69355eb56a05Nick Lewycky .EnumerateDeviceExtensionProperties = loader_EnumerateDeviceExtensionProperties, 1101790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky .EnumerateDeviceLayerProperties = loader_EnumerateDeviceLayerProperties, 1111790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky .GetPhysicalDeviceSparseImageFormatProperties = loader_GetPhysicalDeviceSparseImageFormatProperties, 1121790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky .DestroySurfaceKHR = loader_DestroySurfaceKHR, 1131790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky .GetPhysicalDeviceSurfaceSupportKHR = loader_GetPhysicalDeviceSurfaceSupportKHR, 1141790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky .GetPhysicalDeviceSurfaceCapabilitiesKHR = loader_GetPhysicalDeviceSurfaceCapabilitiesKHR, 1151790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky .GetPhysicalDeviceSurfaceFormatsKHR = loader_GetPhysicalDeviceSurfaceFormatsKHR, 1161790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky .GetPhysicalDeviceSurfacePresentModesKHR = loader_GetPhysicalDeviceSurfacePresentModesKHR, 1171790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky .DbgCreateMsgCallback = loader_DbgCreateMsgCallback, 11864a0a33307723957bf2f15e3181a290853c6f833Nick Lewycky .DbgDestroyMsgCallback = loader_DbgDestroyMsgCallback, 11964a0a33307723957bf2f15e3181a290853c6f833Nick Lewycky#ifdef VK_USE_PLATFORM_MIR_KHR 1201790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky .CreateMirSurfaceKHR = loader_CreateMirSurfaceKHR, 121b1928704201034c785a26296a49f69355eb56a05Nick Lewycky .GetPhysicalDeviceMirPresentationSupportKHR = loader_GetPhysicalDeviceMirPresentationSupportKHR, 122b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#endif 123d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling#ifdef VK_USE_PLATFORM_WAYLAND_KHR 124d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling .CreateWaylandSurfaceKHR = loader_CreateWaylandSurfaceKHR, 125d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling .GetPhysicalDeviceWaylandPresentationSupportKHR = loader_GetPhysicalDeviceWaylandPresentationSupportKHR, 12677b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling#endif 127b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#ifdef VK_USE_PLATFORM_WIN32_KHR 128f2a2806baf3763d551a9f361124b608b2eed66faBill Wendling .CreateWin32SurfaceKHR = loader_CreateWin32SurfaceKHR, 129269687fa350c1aa044bc063c64362a04ecabaa33Nick Lewycky .GetPhysicalDeviceWin32PresentationSupportKHR = loader_GetPhysicalDeviceWin32PresentationSupportKHR, 130a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky#endif 131a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky#ifdef VK_USE_PLATFORM_XCB_KHR 132a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky .CreateXcbSurfaceKHR = loader_CreateXcbSurfaceKHR, 133a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky .GetPhysicalDeviceXcbPresentationSupportKHR = loader_GetPhysicalDeviceXcbPresentationSupportKHR, 134a61e52c9b7cf874b46cef687c1c4627a35952542Nick Lewycky#endif 1351790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky#ifdef VK_USE_PLATFORM_XLIB_KHR 136b1928704201034c785a26296a49f69355eb56a05Nick Lewycky .CreateXlibSurfaceKHR = loader_CreateXlibSurfaceKHR, 137b1928704201034c785a26296a49f69355eb56a05Nick Lewycky .GetPhysicalDeviceXlibPresentationSupportKHR = loader_GetPhysicalDeviceXlibPresentationSupportKHR, 138b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#endif 139b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#ifdef VK_USE_PLATFORM_ANDROID_KHR 140b1928704201034c785a26296a49f69355eb56a05Nick Lewycky .CreateAndroidSurfaceKHR = loader_CreateAndroidSurfaceKHR, 141b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#endif 142b1928704201034c785a26296a49f69355eb56a05Nick Lewycky}; 143b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 144a204ef3168c8804808c716115ba915c89d8849b9Nick LewyckyLOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_init); 145a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky 146a61e52c9b7cf874b46cef687c1c4627a35952542Nick Lewyckyvoid* loader_heap_alloc( 147b1928704201034c785a26296a49f69355eb56a05Nick Lewycky const struct loader_instance *instance, 1485d22d02fac5ef25414c0fdd843b0fabba4998d6eNick Lewycky size_t size, 1495d22d02fac5ef25414c0fdd843b0fabba4998d6eNick Lewycky VkSystemAllocationScope alloc_scope) 1505d22d02fac5ef25414c0fdd843b0fabba4998d6eNick Lewycky{ 1515d22d02fac5ef25414c0fdd843b0fabba4998d6eNick Lewycky if (instance && instance->alloc_callbacks.pfnAllocation) { 1525d22d02fac5ef25414c0fdd843b0fabba4998d6eNick Lewycky /* TODO: What should default alignment be? 1, 4, 8, other? */ 1535d22d02fac5ef25414c0fdd843b0fabba4998d6eNick Lewycky return instance->alloc_callbacks.pfnAllocation(instance->alloc_callbacks.pUserData, size, 4, alloc_scope); 154b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 155b1928704201034c785a26296a49f69355eb56a05Nick Lewycky return malloc(size); 156b1928704201034c785a26296a49f69355eb56a05Nick Lewycky} 157d6d6a97c3c41395dfed46572b69fb6a5d67a5a8bCraig Topper 158d6d6a97c3c41395dfed46572b69fb6a5d67a5a8bCraig Toppervoid loader_heap_free( 159d6d6a97c3c41395dfed46572b69fb6a5d67a5a8bCraig Topper const struct loader_instance *instance, 160d6d6a97c3c41395dfed46572b69fb6a5d67a5a8bCraig Topper void *pMemory) 161b1928704201034c785a26296a49f69355eb56a05Nick Lewycky{ 162b1928704201034c785a26296a49f69355eb56a05Nick Lewycky if (pMemory == NULL) return; 163b1928704201034c785a26296a49f69355eb56a05Nick Lewycky if (instance && instance->alloc_callbacks.pfnFree) { 1641790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky instance->alloc_callbacks.pfnFree(instance->alloc_callbacks.pUserData, pMemory); 1651790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky return; 166b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 167b1928704201034c785a26296a49f69355eb56a05Nick Lewycky free(pMemory); 1681790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky} 1691790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky 170b1928704201034c785a26296a49f69355eb56a05Nick Lewyckyvoid* loader_heap_realloc( 171b1928704201034c785a26296a49f69355eb56a05Nick Lewycky const struct loader_instance *instance, 172b1928704201034c785a26296a49f69355eb56a05Nick Lewycky void *pMemory, 173b1928704201034c785a26296a49f69355eb56a05Nick Lewycky size_t orig_size, 174619850cb3161733e9284ff3bf9a68d1a3b76f0b4Craig Topper size_t size, 175b1928704201034c785a26296a49f69355eb56a05Nick Lewycky VkSystemAllocationScope alloc_scope) 17617df2c3240837b4382898ead8c3ead407a338520Nick Lewycky{ 17717df2c3240837b4382898ead8c3ead407a338520Nick Lewycky if (pMemory == NULL || orig_size == 0) 178d363ff334d796c7f3df834d928a10d88ed758454Nick Lewycky return loader_heap_alloc(instance, size, alloc_scope); 179b1928704201034c785a26296a49f69355eb56a05Nick Lewycky if (size == 0) { 180b1928704201034c785a26296a49f69355eb56a05Nick Lewycky loader_heap_free(instance, pMemory); 1811790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky return NULL; 1821790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky } 1831790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky if (instance && instance->alloc_callbacks.pfnAllocation) { 1841790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky if (size <= orig_size) { 185b1928704201034c785a26296a49f69355eb56a05Nick Lewycky memset(((uint8_t *)pMemory) + size, 0, orig_size - size); 186b1928704201034c785a26296a49f69355eb56a05Nick Lewycky return pMemory; 1877a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky } 1887a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky void *new_ptr = instance->alloc_callbacks.pfnAllocation(instance->alloc_callbacks.pUserData, size, 4, alloc_scope); 1897a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky if (!new_ptr) 190b1928704201034c785a26296a49f69355eb56a05Nick Lewycky return NULL; 191b1928704201034c785a26296a49f69355eb56a05Nick Lewycky memcpy(new_ptr, pMemory, orig_size); 192b1928704201034c785a26296a49f69355eb56a05Nick Lewycky instance->alloc_callbacks.pfnFree(instance->alloc_callbacks.pUserData, pMemory); 193b1928704201034c785a26296a49f69355eb56a05Nick Lewycky return new_ptr; 194d6d6a97c3c41395dfed46572b69fb6a5d67a5a8bCraig Topper } 195d6d6a97c3c41395dfed46572b69fb6a5d67a5a8bCraig Topper return realloc(pMemory, size); 196d6d6a97c3c41395dfed46572b69fb6a5d67a5a8bCraig Topper} 197d6d6a97c3c41395dfed46572b69fb6a5d67a5a8bCraig Topper 198b1928704201034c785a26296a49f69355eb56a05Nick Lewyckyvoid *loader_tls_heap_alloc(size_t size) 199b1928704201034c785a26296a49f69355eb56a05Nick Lewycky{ 200b1928704201034c785a26296a49f69355eb56a05Nick Lewycky return loader_heap_alloc(tls_instance, size, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 201b1928704201034c785a26296a49f69355eb56a05Nick Lewycky} 202b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 20316c19a155c65fd41865562fe4e678ef32728510bDevang Patelvoid loader_tls_heap_free(void *pMemory) 20416c19a155c65fd41865562fe4e678ef32728510bDevang Patel{ 205b1928704201034c785a26296a49f69355eb56a05Nick Lewycky loader_heap_free(tls_instance, pMemory); 206b1928704201034c785a26296a49f69355eb56a05Nick Lewycky} 2071790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky 2081790c9cbb6714e81eab1412909a2320acaecc43bNick Lewyckystatic void loader_log(VkFlags msg_type, int32_t msg_code, 209b1928704201034c785a26296a49f69355eb56a05Nick Lewycky const char *format, ...) 210b1928704201034c785a26296a49f69355eb56a05Nick Lewycky{ 211619850cb3161733e9284ff3bf9a68d1a3b76f0b4Craig Topper char msg[512]; 212bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky va_list ap; 21316c19a155c65fd41865562fe4e678ef32728510bDevang Patel int ret; 214b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 215b1928704201034c785a26296a49f69355eb56a05Nick Lewycky if (!(msg_type & g_loader_log_msgs)) { 21616c19a155c65fd41865562fe4e678ef32728510bDevang Patel return; 21716c19a155c65fd41865562fe4e678ef32728510bDevang Patel } 21816c19a155c65fd41865562fe4e678ef32728510bDevang Patel 21916c19a155c65fd41865562fe4e678ef32728510bDevang Patel va_start(ap, format); 22016c19a155c65fd41865562fe4e678ef32728510bDevang Patel ret = vsnprintf(msg, sizeof(msg), format, ap); 22116c19a155c65fd41865562fe4e678ef32728510bDevang Patel if ((ret >= (int) sizeof(msg)) || ret < 0) { 222b1928704201034c785a26296a49f69355eb56a05Nick Lewycky msg[sizeof(msg)-1] = '\0'; 22316c19a155c65fd41865562fe4e678ef32728510bDevang Patel } 22416c19a155c65fd41865562fe4e678ef32728510bDevang Patel va_end(ap); 225b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 226b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#if defined(WIN32) 227b1928704201034c785a26296a49f69355eb56a05Nick Lewycky OutputDebugString(msg); 228680018ff8965610b3f1c976b0be1dfd45116b218Devang Patel OutputDebugString("\n"); 22916c19a155c65fd41865562fe4e678ef32728510bDevang Patel#endif 2301790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky fputs(msg, stderr); 231b1928704201034c785a26296a49f69355eb56a05Nick Lewycky fputc('\n', stderr); 232b1928704201034c785a26296a49f69355eb56a05Nick Lewycky} 233c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky 234c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky#if defined(WIN32) 235c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewyckystatic char *loader_get_next_path(char *path); 236c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky/** 237c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky* Find the list of registry files (names within a key) in key "location". 238c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky* 239c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky* This function looks in the registry (hive = DEFAULT_VK_REGISTRY_HIVE) key as given in "location" 240c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky* for a list or name/values which are added to a returned list (function return value). 241c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky* The DWORD values within the key must be 0 or they are skipped. 242b1928704201034c785a26296a49f69355eb56a05Nick Lewycky* Function return is a string with a ';' separated list of filenames. 243b1928704201034c785a26296a49f69355eb56a05Nick Lewycky* Function return is NULL if no valid name/value pairs are found in the key, 244b1928704201034c785a26296a49f69355eb56a05Nick Lewycky* or the key is not found. 245b1928704201034c785a26296a49f69355eb56a05Nick Lewycky* 246b1928704201034c785a26296a49f69355eb56a05Nick Lewycky* \returns 24768155d31cd0175be89e26ee68387cb411fca537bDevang Patel* A string list of filenames as pointer. 2481790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky* When done using the returned string list, pointer should be freed. 2491790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky*/ 25016c19a155c65fd41865562fe4e678ef32728510bDevang Patelstatic char *loader_get_registry_files(const struct loader_instance *inst, char *location) 251b1928704201034c785a26296a49f69355eb56a05Nick Lewycky{ 2521790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky LONG rtn_value; 253b1928704201034c785a26296a49f69355eb56a05Nick Lewycky HKEY hive, key; 254b1928704201034c785a26296a49f69355eb56a05Nick Lewycky DWORD access_flags; 2551790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky char name[2048]; 2561790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky char *out = NULL; 257b1928704201034c785a26296a49f69355eb56a05Nick Lewycky char *loc = location; 258b1928704201034c785a26296a49f69355eb56a05Nick Lewycky char *next; 2591790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky DWORD idx = 0; 2601790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky DWORD name_size = sizeof(name); 261c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky DWORD value; 2621790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky DWORD total_size = 4096; 2631790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky DWORD value_size = sizeof(value); 26416c19a155c65fd41865562fe4e678ef32728510bDevang Patel 265c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky while(*loc) 266b1928704201034c785a26296a49f69355eb56a05Nick Lewycky { 267b1928704201034c785a26296a49f69355eb56a05Nick Lewycky next = loader_get_next_path(loc); 2681790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky hive = DEFAULT_VK_REGISTRY_HIVE; 2691790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky access_flags = KEY_QUERY_VALUE; 2701790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky rtn_value = RegOpenKeyEx(hive, loc, 0, access_flags, &key); 271c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky if (rtn_value != ERROR_SUCCESS) { 272c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky // We didn't find the key. Try the 32-bit hive (where we've seen the 273c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky // key end up on some people's systems): 2746227d5c690504c7ada5780c00a635b282c46e275Craig Topper access_flags |= KEY_WOW64_32KEY; 275c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky rtn_value = RegOpenKeyEx(hive, loc, 0, access_flags, &key); 276c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky if (rtn_value != ERROR_SUCCESS) { 277c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky // We still couldn't find the key, so give up: 2781790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky loc = next; 2791790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky continue; 280b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 281b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 282b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 2831790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky while ((rtn_value = RegEnumValue(key, idx++, name, &name_size, NULL, NULL, (LPBYTE) &value, &value_size)) == ERROR_SUCCESS) { 284b1928704201034c785a26296a49f69355eb56a05Nick Lewycky if (value_size == sizeof(value) && value == 0) { 285b1928704201034c785a26296a49f69355eb56a05Nick Lewycky if (out == NULL) { 286b1928704201034c785a26296a49f69355eb56a05Nick Lewycky out = loader_heap_alloc(inst, total_size, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 287b1928704201034c785a26296a49f69355eb56a05Nick Lewycky out[0] = '\0'; 288b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 2891790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky else if (strlen(out) + name_size + 1 > total_size) { 2901790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky out = loader_heap_realloc(inst, out, total_size, total_size * 2, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 291b1928704201034c785a26296a49f69355eb56a05Nick Lewycky total_size *= 2; 292b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 293b1928704201034c785a26296a49f69355eb56a05Nick Lewycky if (out == NULL) { 2941790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory, failed loader_get_registry_files"); 2951790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky return NULL; 2961790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky } 297b1928704201034c785a26296a49f69355eb56a05Nick Lewycky if (strlen(out) == 0) 298b1928704201034c785a26296a49f69355eb56a05Nick Lewycky snprintf(out, name_size + 1, "%s", name); 299b1928704201034c785a26296a49f69355eb56a05Nick Lewycky else 300b1928704201034c785a26296a49f69355eb56a05Nick Lewycky snprintf(out + strlen(out), name_size + 2, "%c%s", PATH_SEPERATOR, name); 301b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 302b1928704201034c785a26296a49f69355eb56a05Nick Lewycky name_size = 2048; 303b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 304d9686a98b8145010516c44a3a5b9b96bf934b9acNick Lewycky loc = next; 305a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky } 306b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 307b1928704201034c785a26296a49f69355eb56a05Nick Lewycky return out; 308b1928704201034c785a26296a49f69355eb56a05Nick Lewycky} 309bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky 310b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#endif // WIN32 311b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 3121790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky/** 313b1928704201034c785a26296a49f69355eb56a05Nick Lewycky * Combine path elements, separating each element with the platform-specific 3141790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky * directory separator, and save the combined string to a destination buffer, 3151790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky * not exceeding the given length. Path elements are given as variadic args, 3161790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky * with a NULL element terminating the list. 3175d22d02fac5ef25414c0fdd843b0fabba4998d6eNick Lewycky * 3181790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky * \returns the total length of the combined string, not including an ASCII 319a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky * NUL termination character. This length may exceed the available storage: 320bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky * in this case, the written string will be truncated to avoid a buffer 3211790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky * overrun, and the return value will greater than or equal to the storage 3221790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky * size. A NULL argument may be provided as the destination buffer in order 323bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky * to determine the required string length without actually writing a string. 324a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky */ 325bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky 3265d22d02fac5ef25414c0fdd843b0fabba4998d6eNick Lewyckystatic int loader_platform_combine_path(char *dest, int len, ...) 3271790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky{ 3281790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky int required_len = 0; 329b1928704201034c785a26296a49f69355eb56a05Nick Lewycky va_list ap; 330b1928704201034c785a26296a49f69355eb56a05Nick Lewycky const char *component; 331b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 3321790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky va_start(ap, len); 3331790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky 334b1928704201034c785a26296a49f69355eb56a05Nick Lewycky while((component = va_arg(ap, const char *))) { 335b1928704201034c785a26296a49f69355eb56a05Nick Lewycky if (required_len > 0) { 3361790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky // This path element is not the first non-empty element; prepend 3371790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky // a directory separator if space allows 338b1928704201034c785a26296a49f69355eb56a05Nick Lewycky if (dest && required_len + 1 < len) { 339b1928704201034c785a26296a49f69355eb56a05Nick Lewycky snprintf(dest + required_len, len - required_len, "%c", 3401790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky DIRECTORY_SYMBOL); 3411790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky } 342a4c4c0e1298f4dd9791eff2bae857e7be6d0ab56Nick Lewycky required_len++; 343a4c4c0e1298f4dd9791eff2bae857e7be6d0ab56Nick Lewycky } 3441790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky 345b1928704201034c785a26296a49f69355eb56a05Nick Lewycky if (dest && required_len < len) { 3461790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky strncpy(dest + required_len, component, len - required_len); 3471790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky } 3481790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky required_len += strlen(component); 3491790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky } 350b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 351bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky va_end(ap); 352b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 353b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // strncpy(3) won't add a NUL terminating byte in the event of truncation. 354c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky if (dest && required_len >= len) { 355c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky dest[len - 1] = '\0'; 356c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky } 357c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky 3581790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky return required_len; 3591790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky} 3601790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky 3611790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky 3621790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky/** 3631790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky * Given string of three part form "maj.min.pat" convert to a vulkan version 364bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky * number. 365bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky */ 3661790c9cbb6714e81eab1412909a2320acaecc43bNick Lewyckystatic uint32_t loader_make_version(const char *vers_str) 3671790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky{ 368b1928704201034c785a26296a49f69355eb56a05Nick Lewycky uint32_t vers = 0, major=0, minor=0, patch=0; 369b1928704201034c785a26296a49f69355eb56a05Nick Lewycky char *minor_str= NULL; 370b1928704201034c785a26296a49f69355eb56a05Nick Lewycky char *patch_str = NULL; 371b1928704201034c785a26296a49f69355eb56a05Nick Lewycky char *cstr; 372c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky char *str; 373c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky 374b1928704201034c785a26296a49f69355eb56a05Nick Lewycky if (!vers_str) 375b1928704201034c785a26296a49f69355eb56a05Nick Lewycky return vers; 376b1928704201034c785a26296a49f69355eb56a05Nick Lewycky cstr = loader_stack_alloc(strlen(vers_str) + 1); 377b1928704201034c785a26296a49f69355eb56a05Nick Lewycky strcpy(cstr, vers_str); 3781790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky while ((str = strchr(cstr, '.')) != NULL) { 3791790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky if (minor_str == NULL) { 380b1928704201034c785a26296a49f69355eb56a05Nick Lewycky minor_str = str + 1; 381b1928704201034c785a26296a49f69355eb56a05Nick Lewycky *str = '\0'; 382b1928704201034c785a26296a49f69355eb56a05Nick Lewycky major = atoi(cstr); 383f2a2806baf3763d551a9f361124b608b2eed66faBill Wendling } 384269687fa350c1aa044bc063c64362a04ecabaa33Nick Lewycky else if (patch_str == NULL) { 385269687fa350c1aa044bc063c64362a04ecabaa33Nick Lewycky patch_str = str + 1; 386269687fa350c1aa044bc063c64362a04ecabaa33Nick Lewycky *str = '\0'; 387269687fa350c1aa044bc063c64362a04ecabaa33Nick Lewycky minor = atoi(minor_str); 388fcf74ed5a2bc10570dec2084a2db1f6580b1210dNick Lewycky } 389269687fa350c1aa044bc063c64362a04ecabaa33Nick Lewycky else { 390fcf74ed5a2bc10570dec2084a2db1f6580b1210dNick Lewycky return vers; 391fcf74ed5a2bc10570dec2084a2db1f6580b1210dNick Lewycky } 3926e5190c193f6267893daf6943af88e95039e739cBill Wendling cstr = str + 1; 3936e5190c193f6267893daf6943af88e95039e739cBill Wendling } 3946e5190c193f6267893daf6943af88e95039e739cBill Wendling patch = atoi(patch_str); 395fcf74ed5a2bc10570dec2084a2db1f6580b1210dNick Lewycky 396269687fa350c1aa044bc063c64362a04ecabaa33Nick Lewycky return VK_MAKE_VERSION(major, minor, patch); 397269687fa350c1aa044bc063c64362a04ecabaa33Nick Lewycky 398fcf74ed5a2bc10570dec2084a2db1f6580b1210dNick Lewycky} 3996e5190c193f6267893daf6943af88e95039e739cBill Wendling 400fcf74ed5a2bc10570dec2084a2db1f6580b1210dNick Lewyckybool compare_vk_extension_properties(const VkExtensionProperties *op1, const VkExtensionProperties *op2) 40139c41c3c93e0d223792acb093adce21a714b01c6Bill Wendling{ 40239c41c3c93e0d223792acb093adce21a714b01c6Bill Wendling return strcmp(op1->extensionName, op2->extensionName) == 0 ? true : false; 40339c41c3c93e0d223792acb093adce21a714b01c6Bill Wendling} 40439c41c3c93e0d223792acb093adce21a714b01c6Bill Wendling 40539c41c3c93e0d223792acb093adce21a714b01c6Bill Wendling/** 406269687fa350c1aa044bc063c64362a04ecabaa33Nick Lewycky * Search the given ext_array for an extension 407269687fa350c1aa044bc063c64362a04ecabaa33Nick Lewycky * matching the given vk_ext_prop 4080c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewycky */ 4091790c9cbb6714e81eab1412909a2320acaecc43bNick Lewyckybool has_vk_extension_property_array( 4100c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewycky const VkExtensionProperties *vk_ext_prop, 4110c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewycky const uint32_t count, 412a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky const VkExtensionProperties *ext_array) 413a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky{ 414a61e52c9b7cf874b46cef687c1c4627a35952542Nick Lewycky for (uint32_t i = 0; i < count; i++) { 4150c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewycky if (compare_vk_extension_properties(vk_ext_prop, &ext_array[i])) 4160c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewycky return true; 41764a0a33307723957bf2f15e3181a290853c6f833Nick Lewycky } 418f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel return false; 419bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky} 420bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky 421bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky/** 422bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky * Search the given ext_list for an extension 423bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky * matching the given vk_ext_prop 424bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky */ 425bba40db07234cef7867b45c67f50632e684cbb15Nick Lewyckybool has_vk_extension_property( 426bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky const VkExtensionProperties *vk_ext_prop, 427bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky const struct loader_extension_list *ext_list) 428f2a2806baf3763d551a9f361124b608b2eed66faBill Wendling{ 429c1b49b56d4132efa2e06deb8f23508d0de4c8800Rafael Espindola for (uint32_t i = 0; i < ext_list->count; i++) { 430d9686a98b8145010516c44a3a5b9b96bf934b9acNick Lewycky if (compare_vk_extension_properties(&ext_list->list[i], vk_ext_prop)) 431a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky return true; 432d9686a98b8145010516c44a3a5b9b96bf934b9acNick Lewycky } 433bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky return false; 434bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky} 435bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky 436bba40db07234cef7867b45c67f50632e684cbb15Nick Lewyckystatic inline bool loader_is_layer_type_device(const enum layer_type type) { 437cbafae6d33031a72ba8219c28cb0e852511f79a3Manman Ren if ((type & VK_LAYER_TYPE_DEVICE_EXPLICIT) || 438cbafae6d33031a72ba8219c28cb0e852511f79a3Manman Ren (type & VK_LAYER_TYPE_DEVICE_IMPLICIT)) 439cbafae6d33031a72ba8219c28cb0e852511f79a3Manman Ren return true; 440cbafae6d33031a72ba8219c28cb0e852511f79a3Manman Ren return false; 441bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky} 442bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky 443bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky/* 444a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky * Search the given layer list for a layer matching the given layer name 445bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky */ 446bba40db07234cef7867b45c67f50632e684cbb15Nick Lewyckystatic struct loader_layer_properties *loader_get_layer_property( 447bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky const char *name, 448bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky const struct loader_layer_list *layer_list) 449bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky{ 450bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky for (uint32_t i = 0; i < layer_list->count; i++) { 451bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky const VkLayerProperties *item = &layer_list->list[i].info; 452f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel if (strcmp(name, item->layerName) == 0) 453bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky return &layer_list->list[i]; 454bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky } 455bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky return NULL; 456bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky} 457bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky 458bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky/** 459bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky * Get the next unused layer property in the list. Init the property to zero. 460bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky */ 461bba40db07234cef7867b45c67f50632e684cbb15Nick Lewyckystatic struct loader_layer_properties *loader_get_next_layer_property( 462bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky const struct loader_instance *inst, 463bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky struct loader_layer_list *layer_list) 464bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky{ 465bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky if (layer_list->capacity == 0) { 466bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky layer_list->list = loader_heap_alloc(inst, 467bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky sizeof(struct loader_layer_properties) * 64, 468b1928704201034c785a26296a49f69355eb56a05Nick Lewycky VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 469b1928704201034c785a26296a49f69355eb56a05Nick Lewycky if (layer_list->list == NULL) { 470bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't add any layer properties to list"); 471b1928704201034c785a26296a49f69355eb56a05Nick Lewycky return NULL; 472bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky } 473bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky memset(layer_list->list, 0, sizeof(struct loader_layer_properties) * 64); 474b1928704201034c785a26296a49f69355eb56a05Nick Lewycky layer_list->capacity = sizeof(struct loader_layer_properties) * 64; 475b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 476b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 477f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel // ensure enough room to add an entry 478f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel if ((layer_list->count + 1) * sizeof (struct loader_layer_properties) 479f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel > layer_list->capacity) { 480f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel layer_list->list = loader_heap_realloc(inst, layer_list->list, 481f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel layer_list->capacity, 48277b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling layer_list->capacity * 2, 483f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 484f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel if (layer_list->list == NULL) { 485f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel loader_log(VK_DBG_REPORT_ERROR_BIT, 0, 486f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel "realloc failed for layer list"); 487f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel } 488f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel layer_list->capacity *= 2; 489cbafae6d33031a72ba8219c28cb0e852511f79a3Manman Ren } 490cbafae6d33031a72ba8219c28cb0e852511f79a3Manman Ren 491cbafae6d33031a72ba8219c28cb0e852511f79a3Manman Ren layer_list->count++; 492cbafae6d33031a72ba8219c28cb0e852511f79a3Manman Ren return &(layer_list->list[layer_list->count - 1]); 493f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel} 494f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel 495f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel/** 496f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel * Remove all layer properties entrys from the list 497f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel */ 498f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patelvoid loader_delete_layer_properties( 499f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel const struct loader_instance *inst, 500f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel struct loader_layer_list *layer_list) 501f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel{ 502f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel uint32_t i, j; 503f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel struct loader_device_extension_list *dev_ext_list; 504f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel if (!layer_list) 505f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel return; 5061790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky 507f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel for (i = 0; i < layer_list->count; i++) { 5081790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky loader_destroy_generic_list(inst, (struct loader_generic_list *) 509b1928704201034c785a26296a49f69355eb56a05Nick Lewycky &layer_list->list[i].instance_extension_list); 5101790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky dev_ext_list = &layer_list->list[i].device_extension_list; 511ce718ff9f42c7da092eaa01dd0242e8d5ba84713Hans Wennborg if (dev_ext_list->capacity > 0 && dev_ext_list->list->entrypoint_count > 0) { 512f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel for (j= 0; j < dev_ext_list->list->entrypoint_count; j++) { 513f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel loader_heap_free(inst, dev_ext_list->list->entrypoints[j]); 514f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel } 515f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel loader_heap_free(inst, dev_ext_list->list->entrypoints); 516f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel } 517f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel loader_destroy_generic_list(inst, (struct loader_generic_list *) 518f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel dev_ext_list); 519f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel } 520f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel layer_list->count = 0; 521f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel 522f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel if (layer_list->capacity > 0) { 523f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel layer_list->capacity = 0; 524f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel loader_heap_free(inst, layer_list->list); 525f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel } 526f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel 527f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel} 528bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky 529f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patelstatic void loader_add_global_extensions( 530f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel const struct loader_instance *inst, 531bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky const PFN_vkEnumerateInstanceExtensionProperties fp_get_props, 532bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky const char *lib_name, 533bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky struct loader_extension_list *ext_list) 534f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel{ 535bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky uint32_t i, count; 536f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel VkExtensionProperties *ext_props; 537f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel VkResult res; 538f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel 539bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky if (!fp_get_props) { 540f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel /* No EnumerateInstanceExtensionProperties defined */ 541f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel return; 542f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel } 543f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel 544f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel res = fp_get_props(NULL, &count, NULL); 545f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel if (res != VK_SUCCESS) { 546f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Error getting global extension count from %s", lib_name); 547b1928704201034c785a26296a49f69355eb56a05Nick Lewycky return; 548b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 549f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel 550f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel if (count == 0) { 551f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel /* No ExtensionProperties to report */ 5521790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky return; 5531790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky } 554f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel 555f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel ext_props = loader_stack_alloc(count * sizeof(VkExtensionProperties)); 556f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel 557f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel res = fp_get_props(NULL, &count, ext_props); 558bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky if (res != VK_SUCCESS) { 559f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Error getting global extensions from %s", lib_name); 560f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel return; 561f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel } 56277b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling 56377b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling for (i = 0; i < count; i++) { 564f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel char spec_version[64]; 565f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel 5661790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky snprintf(spec_version, sizeof(spec_version), "%d.%d.%d", 5671790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky VK_MAJOR(ext_props[i].specVersion), 568c7a884040e4ec7795515978a94803894ad08c4caBill Wendling VK_MINOR(ext_props[i].specVersion), 569c7a884040e4ec7795515978a94803894ad08c4caBill Wendling VK_PATCH(ext_props[i].specVersion)); 57077b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, 57177b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling "Global Extension: %s (%s) version %s", 57277b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling ext_props[i].extensionName, lib_name, spec_version); 573f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]); 574b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 575b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 5764a8fefaf8303f30514bc2a40d840a1709dae65cfBill Wendling return; 577d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling} 578d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling 579d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling/* 580d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling * Initialize ext_list with the physical device extensions. 58118764716861243c58a711a92190624dc2f6aafc9Bill Wendling * The extension properties are passed as inputs in count and ext_props. 58218764716861243c58a711a92190624dc2f6aafc9Bill Wendling */ 583d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendlingstatic VkResult loader_init_physical_device_extensions( 584d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling const struct loader_instance *inst, 585d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling struct loader_physical_device *phys_dev, 586d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling uint32_t count, 587d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling VkExtensionProperties *ext_props, 588d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling struct loader_extension_list *ext_list) 589d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling{ 590d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling VkResult res; 591d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling uint32_t i; 592d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling 593d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling if (!loader_init_generic_list(inst, (struct loader_generic_list *) ext_list, 594d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling sizeof(VkExtensionProperties))) { 595d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling return VK_ERROR_OUT_OF_HOST_MEMORY; 5968640c6a5227b75666e02424e2181289692138348Bill Wendling } 5978640c6a5227b75666e02424e2181289692138348Bill Wendling 5988640c6a5227b75666e02424e2181289692138348Bill Wendling for (i = 0; i < count; i++) { 5998640c6a5227b75666e02424e2181289692138348Bill Wendling char spec_version[64]; 6008640c6a5227b75666e02424e2181289692138348Bill Wendling 6018640c6a5227b75666e02424e2181289692138348Bill Wendling snprintf(spec_version, sizeof (spec_version), "%d.%d.%d", 6028640c6a5227b75666e02424e2181289692138348Bill Wendling VK_MAJOR(ext_props[i].specVersion), 6038640c6a5227b75666e02424e2181289692138348Bill Wendling VK_MINOR(ext_props[i].specVersion), 6048640c6a5227b75666e02424e2181289692138348Bill Wendling VK_PATCH(ext_props[i].specVersion)); 6058640c6a5227b75666e02424e2181289692138348Bill Wendling loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, 606d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling "PhysicalDevice Extension: %s (%s) version %s", 607d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling ext_props[i].extensionName, phys_dev->this_icd->this_icd_lib->lib_name, spec_version); 608d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]); 609b1928704201034c785a26296a49f69355eb56a05Nick Lewycky if (res != VK_SUCCESS) 61077b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling return res; 61177b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling } 61277b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling 61377b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling return VK_SUCCESS; 614f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel} 615b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 616b1928704201034c785a26296a49f69355eb56a05Nick Lewyckystatic VkResult loader_add_physical_device_extensions( 6171790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky const struct loader_instance *inst, 6181790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky VkPhysicalDevice physical_device, 6191790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky const char *lib_name, 6201790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky struct loader_extension_list *ext_list) 6211790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky{ 6221790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky uint32_t i, count; 6231790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky VkResult res; 6241790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky VkExtensionProperties *ext_props; 6251790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky 6261790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky res = loader_EnumerateDeviceExtensionProperties(physical_device, NULL, &count, NULL); 6271790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky if (res == VK_SUCCESS && count > 0) { 6281790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky ext_props = loader_stack_alloc(count * sizeof (VkExtensionProperties)); 6299e6ee16b1814268897965b81e82a74ef39173ee1Benjamin Kramer if (!ext_props) 630db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris Lattner return VK_ERROR_OUT_OF_HOST_MEMORY; 6319e6ee16b1814268897965b81e82a74ef39173ee1Benjamin Kramer res = loader_EnumerateDeviceExtensionProperties(physical_device, NULL, &count, ext_props); 6321790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky if (res != VK_SUCCESS) 6339e6ee16b1814268897965b81e82a74ef39173ee1Benjamin Kramer return res; 6341790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky for (i = 0; i < count; i++) { 6359e6ee16b1814268897965b81e82a74ef39173ee1Benjamin Kramer char spec_version[64]; 6361790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky 6371790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky snprintf(spec_version, sizeof (spec_version), "%d.%d.%d", 6381790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky VK_MAJOR(ext_props[i].specVersion), 6391790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky VK_MINOR(ext_props[i].specVersion), 6401790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky VK_PATCH(ext_props[i].specVersion)); 6411790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, 6427a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky "PhysicalDevice Extension: %s (%s) version %s", 6431790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky ext_props[i].extensionName, lib_name, spec_version); 6441790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]); 645bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky if (res != VK_SUCCESS) 646bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky return res; 6471790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky } 6481790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky } else { 6491790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Error getting physical device extension info count from library %s", lib_name); 6501790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky return res; 6511790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky } 6521790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky 6531790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky return VK_SUCCESS; 6541790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky} 6559e6ee16b1814268897965b81e82a74ef39173ee1Benjamin Kramer 6561790c9cbb6714e81eab1412909a2320acaecc43bNick Lewyckystatic bool loader_init_generic_list(const struct loader_instance *inst, 6571790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky struct loader_generic_list *list_info, 6581790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky size_t element_size) 659267010864e139781ef5949939e081c41f954de0aJay Foad{ 6601790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky list_info->capacity = 32 * element_size; 6611790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky list_info->list = loader_heap_alloc(inst, list_info->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 6621790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky if (list_info->list == NULL) { 6631790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky return false; 6641790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky } 665b1928704201034c785a26296a49f69355eb56a05Nick Lewycky memset(list_info->list, 0, list_info->capacity); 666d9686a98b8145010516c44a3a5b9b96bf934b9acNick Lewycky list_info->count = 0; 667d9686a98b8145010516c44a3a5b9b96bf934b9acNick Lewycky return true; 668d9686a98b8145010516c44a3a5b9b96bf934b9acNick Lewycky} 669d9686a98b8145010516c44a3a5b9b96bf934b9acNick Lewycky 670d9686a98b8145010516c44a3a5b9b96bf934b9acNick Lewyckyvoid loader_destroy_generic_list(const struct loader_instance *inst, 6711790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky struct loader_generic_list *list) 6721790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky{ 6731790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky loader_heap_free(inst, list->list); 67477b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling list->count = 0; 67577b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling list->capacity = 0; 676c7a884040e4ec7795515978a94803894ad08c4caBill Wendling} 67777b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling 678b8bce928f4ffdf50eff69334f3e25b27848536b6Micah Villmow/* 679b8bce928f4ffdf50eff69334f3e25b27848536b6Micah Villmow * Append non-duplicate extension properties defined in props 68077b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling * to the given ext_list. 68177b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling * Return 68277b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling * Vk_SUCCESS on success 683b1928704201034c785a26296a49f69355eb56a05Nick Lewycky */ 684b1928704201034c785a26296a49f69355eb56a05Nick LewyckyVkResult loader_add_to_ext_list( 685b1928704201034c785a26296a49f69355eb56a05Nick Lewycky const struct loader_instance *inst, 68617d2f776011cba33f7f5afb03c8066d35dbf8afcNick Lewycky struct loader_extension_list *ext_list, 6875409a188328d9de3755febc23558d4fc1797d04eNick Lewycky uint32_t prop_list_count, 6885409a188328d9de3755febc23558d4fc1797d04eNick Lewycky const VkExtensionProperties *props) 68917d2f776011cba33f7f5afb03c8066d35dbf8afcNick Lewycky{ 6905409a188328d9de3755febc23558d4fc1797d04eNick Lewycky uint32_t i; 691c7a884040e4ec7795515978a94803894ad08c4caBill Wendling const VkExtensionProperties *cur_ext; 6921790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky 693b1928704201034c785a26296a49f69355eb56a05Nick Lewycky if (ext_list->list == NULL || ext_list->capacity == 0) { 694b1928704201034c785a26296a49f69355eb56a05Nick Lewycky loader_init_generic_list(inst, (struct loader_generic_list *) ext_list, 695b1928704201034c785a26296a49f69355eb56a05Nick Lewycky sizeof(VkExtensionProperties)); 6965fdd6c8793462549e3593890ec61573da06e3346Jay Foad } 697b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 698b1928704201034c785a26296a49f69355eb56a05Nick Lewycky if (ext_list->list == NULL) 699b1928704201034c785a26296a49f69355eb56a05Nick Lewycky return VK_ERROR_OUT_OF_HOST_MEMORY; 700d9686a98b8145010516c44a3a5b9b96bf934b9acNick Lewycky 7011790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky for (i = 0; i < prop_list_count; i++) { 702b1928704201034c785a26296a49f69355eb56a05Nick Lewycky cur_ext = &props[i]; 703b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 70418764716861243c58a711a92190624dc2f6aafc9Bill Wendling // look for duplicates 70518764716861243c58a711a92190624dc2f6aafc9Bill Wendling if (has_vk_extension_property(cur_ext, ext_list)) { 70618764716861243c58a711a92190624dc2f6aafc9Bill Wendling continue; 70718764716861243c58a711a92190624dc2f6aafc9Bill Wendling } 70818764716861243c58a711a92190624dc2f6aafc9Bill Wendling 709d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling // add to list at end 710d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling // check for enough capacity 711d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling if (ext_list->count * sizeof(VkExtensionProperties) 712d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling >= ext_list->capacity) { 713d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling 714b1928704201034c785a26296a49f69355eb56a05Nick Lewycky ext_list->list = loader_heap_realloc(inst, 715db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris Lattner ext_list->list, 7161790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky ext_list->capacity, 717b1928704201034c785a26296a49f69355eb56a05Nick Lewycky ext_list->capacity * 2, 718b1928704201034c785a26296a49f69355eb56a05Nick Lewycky VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 7191790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky 7201790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky if (ext_list->list == NULL) 7211790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky return VK_ERROR_OUT_OF_HOST_MEMORY; 7221790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky 7231790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky // double capacity 7241790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky ext_list->capacity *= 2; 7251790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky } 7261790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky 7271790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky memcpy(&ext_list->list[ext_list->count], cur_ext, sizeof(VkExtensionProperties)); 7281790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky ext_list->count++; 7291790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky } 7301790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky return VK_SUCCESS; 731b1928704201034c785a26296a49f69355eb56a05Nick Lewycky} 732d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling 73321b742ffce7bec3d71e09c7c6d901a756d55feb3Bill Wendling/* 734253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling * Append one extension property defined in props with entrypoints 735253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling * defined in entrys to the given ext_list. 736253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling * Return 737253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling * Vk_SUCCESS on success 738253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling */ 739b1928704201034c785a26296a49f69355eb56a05Nick LewyckyVkResult loader_add_to_dev_ext_list( 740034b94b17006f51722886b0f2283fb6fb19aca1fBill Wendling const struct loader_instance *inst, 741a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky struct loader_device_extension_list *ext_list, 742034b94b17006f51722886b0f2283fb6fb19aca1fBill Wendling const VkExtensionProperties *props, 743253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling uint32_t entry_count, 744253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling char **entrys) 7451790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky{ 746b1928704201034c785a26296a49f69355eb56a05Nick Lewycky uint32_t idx; 747b1928704201034c785a26296a49f69355eb56a05Nick Lewycky if (ext_list->list == NULL || ext_list->capacity == 0) { 748b1928704201034c785a26296a49f69355eb56a05Nick Lewycky loader_init_generic_list(inst, (struct loader_generic_list *) ext_list, 749b1928704201034c785a26296a49f69355eb56a05Nick Lewycky sizeof(struct loader_dev_ext_props)); 750b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 751b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 752f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel if (ext_list->list == NULL) 753f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel return VK_ERROR_OUT_OF_HOST_MEMORY; 754f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel 755032dbee2a9d401ee05beb648465f21168e279bdaBill Wendling idx =ext_list->count; 756f2a2806baf3763d551a9f361124b608b2eed66faBill Wendling // add to list at end 757d9686a98b8145010516c44a3a5b9b96bf934b9acNick Lewycky // check for enough capacity 758d9686a98b8145010516c44a3a5b9b96bf934b9acNick Lewycky if (idx * sizeof (struct loader_dev_ext_props) 759a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky >= ext_list->capacity) { 7608fa6dc431deb7a9aadc23ec0a7bdcb2d02330972Nick Lewycky 7618fa6dc431deb7a9aadc23ec0a7bdcb2d02330972Nick Lewycky ext_list->list = loader_heap_realloc(inst, 7625d22d02fac5ef25414c0fdd843b0fabba4998d6eNick Lewycky ext_list->list, 7635d22d02fac5ef25414c0fdd843b0fabba4998d6eNick Lewycky ext_list->capacity, 7645d22d02fac5ef25414c0fdd843b0fabba4998d6eNick Lewycky ext_list->capacity * 2, 7655d22d02fac5ef25414c0fdd843b0fabba4998d6eNick Lewycky VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 7665d22d02fac5ef25414c0fdd843b0fabba4998d6eNick Lewycky 7675d22d02fac5ef25414c0fdd843b0fabba4998d6eNick Lewycky if (ext_list->list == NULL) 76817d2f776011cba33f7f5afb03c8066d35dbf8afcNick Lewycky return VK_ERROR_OUT_OF_HOST_MEMORY; 7698fa6dc431deb7a9aadc23ec0a7bdcb2d02330972Nick Lewycky 770f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel // double capacity 771b1928704201034c785a26296a49f69355eb56a05Nick Lewycky ext_list->capacity *= 2; 772f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel } 773bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky 774f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel memcpy(&ext_list->list[idx].props, props, sizeof(struct loader_dev_ext_props)); 775f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel ext_list->list[idx].entrypoint_count = entry_count; 776f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel ext_list->list[idx].entrypoints = loader_heap_alloc(inst, 777b1928704201034c785a26296a49f69355eb56a05Nick Lewycky sizeof(char *) * entry_count, 778b1928704201034c785a26296a49f69355eb56a05Nick Lewycky VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 779b1928704201034c785a26296a49f69355eb56a05Nick Lewycky if (ext_list->list[idx].entrypoints == NULL) 7804a8fefaf8303f30514bc2a40d840a1709dae65cfBill Wendling return VK_ERROR_OUT_OF_HOST_MEMORY; 781d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling for (uint32_t i = 0; i < entry_count; i++) { 782b1928704201034c785a26296a49f69355eb56a05Nick Lewycky ext_list->list[idx].entrypoints[i] = loader_heap_alloc(inst, 78377b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling strlen(entrys[i]) + 1, 78477b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 78577b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling if (ext_list->list[idx].entrypoints[i] == NULL) 78677b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling return VK_ERROR_OUT_OF_HOST_MEMORY; 78777b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling strcpy(ext_list->list[idx].entrypoints[i], entrys[i]); 78877b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling } 789034b94b17006f51722886b0f2283fb6fb19aca1fBill Wendling ext_list->count++; 790a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky 791034b94b17006f51722886b0f2283fb6fb19aca1fBill Wendling return VK_SUCCESS; 79277b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling} 79377b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling 79477b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling/** 79577b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling * Search the given search_list for any layers in the props list. 79677b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling * Add these to the output layer_list. Don't add duplicates to the output layer_list. 79777b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling */ 79877b19134104c3e96424dc010f2b69c3faf580e68Bill Wendlingstatic VkResult loader_add_layer_names_to_list( 79977b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling const struct loader_instance *inst, 80077b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling struct loader_layer_list *output_list, 80177b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling uint32_t name_count, 80277b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling const char * const *names, 80377b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling const struct loader_layer_list *search_list) 80477b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling{ 80577b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling struct loader_layer_properties *layer_prop; 806bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky VkResult err = VK_SUCCESS; 80777b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling 80877b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling for (uint32_t i = 0; i < name_count; i++) { 80977b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling const char *search_target = names[i]; 81077b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling layer_prop = loader_get_layer_property(search_target, search_list); 81177b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling if (!layer_prop) { 81277b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Unable to find layer %s", search_target); 813bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky err = VK_ERROR_LAYER_NOT_PRESENT; 81477b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling continue; 81577b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling } 81677b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling 81777b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling loader_add_to_layer_list(inst, output_list, 1, layer_prop); 81858591b1647e0f1f213e5acd7bfa87c226ced0033Nick Lewycky } 81958591b1647e0f1f213e5acd7bfa87c226ced0033Nick Lewycky 82058591b1647e0f1f213e5acd7bfa87c226ced0033Nick Lewycky return err; 82177b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling} 82277b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling 82377b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling 82477b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling/* 82577b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling * Manage lists of VkLayerProperties 826bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky */ 82777b19134104c3e96424dc010f2b69c3faf580e68Bill Wendlingstatic bool loader_init_layer_list(const struct loader_instance *inst, 82877b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling struct loader_layer_list *list) 82977b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling{ 83077b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling list->capacity = 32 * sizeof(struct loader_layer_properties); 83177b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling list->list = loader_heap_alloc(inst, list->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 83277b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling if (list->list == NULL) { 83377b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling return false; 834253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling } 835d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling memset(list->list, 0, list->capacity); 836253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling list->count = 0; 837253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling return true; 838d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling} 839253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling 840253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendlingvoid loader_destroy_layer_list(const struct loader_instance *inst, 841d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling struct loader_layer_list *layer_list) 842253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling{ 843253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling loader_heap_free(inst, layer_list->list); 844253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling layer_list->count = 0; 845034b94b17006f51722886b0f2283fb6fb19aca1fBill Wendling layer_list->capacity = 0; 846a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky} 847034b94b17006f51722886b0f2283fb6fb19aca1fBill Wendling 848253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling/* 849253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling * Manage list of layer libraries (loader_lib_info) 850253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling */ 851253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendlingstatic bool loader_init_layer_library_list(const struct loader_instance *inst, 852253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling struct loader_layer_library_list *list) 853253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling{ 854253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling list->capacity = 32 * sizeof(struct loader_lib_info); 855253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling list->list = loader_heap_alloc(inst, list->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 856253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling if (list->list == NULL) { 857253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling return false; 858032dbee2a9d401ee05beb648465f21168e279bdaBill Wendling } 859032dbee2a9d401ee05beb648465f21168e279bdaBill Wendling memset(list->list, 0, list->capacity); 860032dbee2a9d401ee05beb648465f21168e279bdaBill Wendling list->count = 0; 861032dbee2a9d401ee05beb648465f21168e279bdaBill Wendling return true; 862032dbee2a9d401ee05beb648465f21168e279bdaBill Wendling} 863032dbee2a9d401ee05beb648465f21168e279bdaBill Wendling 864ec3fc2eac0e9203dd1094b9ce458e8c1b42b832fBill Wendlingvoid loader_destroy_layer_library_list(const struct loader_instance *inst, 865032dbee2a9d401ee05beb648465f21168e279bdaBill Wendling struct loader_layer_library_list *list) 866253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling{ 867253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling for (uint32_t i = 0; i < list->count; i++) { 868253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling loader_heap_free(inst, list->list[i].lib_name); 869253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling } 870253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling loader_heap_free(inst, list->list); 871d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling list->count = 0; 872253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling list->capacity = 0; 873253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling} 874d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling 875d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendlingvoid loader_add_to_layer_library_list( 876d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling const struct loader_instance *inst, 877253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling struct loader_layer_library_list *list, 878 uint32_t item_count, 879 const struct loader_lib_info *new_items) 880{ 881 uint32_t i; 882 struct loader_lib_info *item; 883 884 if (list->list == NULL || list->capacity == 0) { 885 loader_init_layer_library_list(inst, list); 886 } 887 888 if (list->list == NULL) 889 return; 890 891 for (i = 0; i < item_count; i++) { 892 item = (struct loader_lib_info *) &new_items[i]; 893 894 // look for duplicates 895 for (uint32_t j = 0; j < list->count; j++) { 896 if (strcmp(list->list[i].lib_name, new_items->lib_name) == 0) { 897 continue; 898 } 899 } 900 901 // add to list at end 902 // check for enough capacity 903 if (list->count * sizeof(struct loader_lib_info) 904 >= list->capacity) { 905 906 list->list = loader_heap_realloc(inst, 907 list->list, 908 list->capacity, 909 list->capacity * 2, 910 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 911 // double capacity 912 list->capacity *= 2; 913 } 914 915 memcpy(&list->list[list->count], item, sizeof(struct loader_lib_info)); 916 list->count++; 917 } 918} 919 920 921/* 922 * Search the given layer list for a list 923 * matching the given VkLayerProperties 924 */ 925bool has_vk_layer_property( 926 const VkLayerProperties *vk_layer_prop, 927 const struct loader_layer_list *list) 928{ 929 for (uint32_t i = 0; i < list->count; i++) { 930 if (strcmp(vk_layer_prop->layerName, list->list[i].info.layerName) == 0) 931 return true; 932 } 933 return false; 934} 935 936/* 937 * Search the given layer list for a layer 938 * matching the given name 939 */ 940bool has_layer_name( 941 const char *name, 942 const struct loader_layer_list *list) 943{ 944 for (uint32_t i = 0; i < list->count; i++) { 945 if (strcmp(name, list->list[i].info.layerName) == 0) 946 return true; 947 } 948 return false; 949} 950 951/* 952 * Append non-duplicate layer properties defined in prop_list 953 * to the given layer_info list 954 */ 955void loader_add_to_layer_list( 956 const struct loader_instance *inst, 957 struct loader_layer_list *list, 958 uint32_t prop_list_count, 959 const struct loader_layer_properties *props) 960{ 961 uint32_t i; 962 struct loader_layer_properties *layer; 963 964 if (list->list == NULL || list->capacity == 0) { 965 loader_init_layer_list(inst, list); 966 } 967 968 if (list->list == NULL) 969 return; 970 971 for (i = 0; i < prop_list_count; i++) { 972 layer = (struct loader_layer_properties *) &props[i]; 973 974 // look for duplicates 975 if (has_vk_layer_property(&layer->info, list)) { 976 continue; 977 } 978 979 // add to list at end 980 // check for enough capacity 981 if (list->count * sizeof(struct loader_layer_properties) 982 >= list->capacity) { 983 984 list->list = loader_heap_realloc(inst, 985 list->list, 986 list->capacity, 987 list->capacity * 2, 988 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 989 // double capacity 990 list->capacity *= 2; 991 } 992 993 memcpy(&list->list[list->count], layer, sizeof(struct loader_layer_properties)); 994 list->count++; 995 } 996} 997 998/** 999 * Search the search_list for any layer with a name 1000 * that matches the given name and a type that matches the given type 1001 * Add all matching layers to the found_list 1002 * Do not add if found loader_layer_properties is already 1003 * on the found_list. 1004 */ 1005static void loader_find_layer_name_add_list( 1006 const struct loader_instance *inst, 1007 const char *name, 1008 const enum layer_type type, 1009 const struct loader_layer_list *search_list, 1010 struct loader_layer_list *found_list) 1011{ 1012 bool found = false; 1013 for (uint32_t i = 0; i < search_list->count; i++) { 1014 struct loader_layer_properties *layer_prop = &search_list->list[i]; 1015 if (0 == strcmp(layer_prop->info.layerName, name) && 1016 (layer_prop->type & type)) { 1017 /* Found a layer with the same name, add to found_list */ 1018 loader_add_to_layer_list(inst, found_list, 1, layer_prop); 1019 found = true; 1020 } 1021 } 1022 if (!found) { 1023 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Warning, couldn't find layer name %s to activate", name); 1024 } 1025} 1026 1027static VkExtensionProperties *get_extension_property( 1028 const char *name, 1029 const struct loader_extension_list *list) 1030{ 1031 for (uint32_t i = 0; i < list->count; i++) { 1032 if (strcmp(name, list->list[i].extensionName) == 0) 1033 return &list->list[i]; 1034 } 1035 return NULL; 1036} 1037 1038static VkExtensionProperties *get_dev_extension_property( 1039 const char *name, 1040 const struct loader_device_extension_list *list) 1041{ 1042 for (uint32_t i = 0; i < list->count; i++) { 1043 if (strcmp(name, list->list[i].props.extensionName) == 0) 1044 return &list->list[i].props; 1045 } 1046 return NULL; 1047} 1048 1049/* 1050 * For global extensions implemented within the loader (i.e. DEBUG_REPORT 1051 * the extension must provide two entry points for the loader to use: 1052 * - "trampoline" entry point - this is the address returned by GetProcAddr 1053 * and will always do what's necessary to support a global call. 1054 * - "terminator" function - this function will be put at the end of the 1055 * instance chain and will contain the necessary logic to call / process 1056 * the extension for the appropriate ICDs that are available. 1057 * There is no generic mechanism for including these functions, the references 1058 * must be placed into the appropriate loader entry points. 1059 * GetInstanceProcAddr: call extension GetInstanceProcAddr to check for GetProcAddr requests 1060 * loader_coalesce_extensions(void) - add extension records to the list of global 1061 * extension available to the app. 1062 * instance_disp - add function pointer for terminator function to this array. 1063 * The extension itself should be in a separate file that will be 1064 * linked directly with the loader. 1065 */ 1066 1067void loader_get_icd_loader_instance_extensions( 1068 const struct loader_instance *inst, 1069 struct loader_icd_libs *icd_libs, 1070 struct loader_extension_list *inst_exts) 1071{ 1072 struct loader_extension_list icd_exts; 1073 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, "Build ICD instance extension list"); 1074 // traverse scanned icd list adding non-duplicate extensions to the list 1075 for (uint32_t i = 0; i < icd_libs->count; i++) { 1076 loader_init_generic_list(inst, (struct loader_generic_list *) &icd_exts, 1077 sizeof(VkExtensionProperties)); 1078 loader_add_global_extensions(inst, icd_libs->list[i].EnumerateInstanceExtensionProperties, 1079 icd_libs->list[i].lib_name, 1080 &icd_exts); 1081 loader_add_to_ext_list(inst, inst_exts, 1082 icd_exts.count, 1083 icd_exts.list); 1084 loader_destroy_generic_list(inst, (struct loader_generic_list *) &icd_exts); 1085 }; 1086 1087 // Traverse loader's extensions, adding non-duplicate extensions to the list 1088 wsi_add_instance_extensions(inst, inst_exts); 1089 debug_report_add_instance_extensions(inst, inst_exts); 1090} 1091 1092struct loader_physical_device *loader_get_physical_device(const VkPhysicalDevice physdev) 1093{ 1094 uint32_t i; 1095 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) { 1096 for (i = 0; i < inst->total_gpu_count; i++) { 1097 //TODO this aliases physDevices within instances, need for this 1098 // function to go away 1099 if (inst->phys_devs[i].disp == loader_get_instance_dispatch(physdev)) { 1100 return &inst->phys_devs[i]; 1101 } 1102 } 1103 } 1104 return NULL; 1105} 1106 1107struct loader_icd *loader_get_icd_and_device(const VkDevice device, 1108 struct loader_device **found_dev) 1109{ 1110 *found_dev = NULL; 1111 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) { 1112 for (struct loader_icd *icd = inst->icds; icd; icd = icd->next) { 1113 for (struct loader_device *dev = icd->logical_device_list; dev; dev = dev->next) 1114 /* Value comparison of device prevents object wrapping by layers */ 1115 if (loader_get_dispatch(dev->device) == loader_get_dispatch(device)) { 1116 *found_dev = dev; 1117 return icd; 1118 } 1119 } 1120 } 1121 return NULL; 1122} 1123 1124static void loader_destroy_logical_device(const struct loader_instance *inst, 1125 struct loader_device *dev) 1126{ 1127 loader_heap_free(inst, dev->app_extension_props); 1128 if (dev->activated_layer_list.count) 1129 loader_destroy_layer_list(inst, &dev->activated_layer_list); 1130 loader_heap_free(inst, dev); 1131} 1132 1133static struct loader_device *loader_add_logical_device( 1134 const struct loader_instance *inst, 1135 const VkDevice dev, 1136 struct loader_device **device_list) 1137{ 1138 struct loader_device *new_dev; 1139 1140 new_dev = loader_heap_alloc(inst, sizeof(struct loader_device), VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); 1141 if (!new_dev) { 1142 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc struct laoder-device"); 1143 return NULL; 1144 } 1145 1146 memset(new_dev, 0, sizeof(struct loader_device)); 1147 1148 new_dev->next = *device_list; 1149 new_dev->device = dev; 1150 *device_list = new_dev; 1151 return new_dev; 1152} 1153 1154void loader_remove_logical_device( 1155 const struct loader_instance *inst, 1156 struct loader_icd *icd, 1157 struct loader_device *found_dev) 1158{ 1159 struct loader_device *dev, *prev_dev; 1160 1161 if (!icd || !found_dev) 1162 return; 1163 1164 prev_dev = NULL; 1165 dev = icd->logical_device_list; 1166 while (dev && dev != found_dev) { 1167 prev_dev = dev; 1168 dev = dev->next; 1169 } 1170 1171 if (prev_dev) 1172 prev_dev->next = found_dev->next; 1173 else 1174 icd->logical_device_list = found_dev->next; 1175 loader_destroy_logical_device(inst, found_dev); 1176} 1177 1178 1179static void loader_icd_destroy( 1180 struct loader_instance *ptr_inst, 1181 struct loader_icd *icd) 1182{ 1183 ptr_inst->total_icd_count--; 1184 for (struct loader_device *dev = icd->logical_device_list; dev; ) { 1185 struct loader_device *next_dev = dev->next; 1186 loader_destroy_logical_device(ptr_inst, dev); 1187 dev = next_dev; 1188 } 1189 1190 loader_heap_free(ptr_inst, icd); 1191} 1192 1193static struct loader_icd * loader_icd_create(const struct loader_instance *inst) 1194{ 1195 struct loader_icd *icd; 1196 1197 icd = loader_heap_alloc(inst, sizeof(*icd), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1198 if (!icd) 1199 return NULL; 1200 1201 memset(icd, 0, sizeof(*icd)); 1202 1203 return icd; 1204} 1205 1206static struct loader_icd *loader_icd_add( 1207 struct loader_instance *ptr_inst, 1208 const struct loader_scanned_icds *icd_lib) 1209{ 1210 struct loader_icd *icd; 1211 1212 icd = loader_icd_create(ptr_inst); 1213 if (!icd) 1214 return NULL; 1215 1216 icd->this_icd_lib = icd_lib; 1217 icd->this_instance = ptr_inst; 1218 1219 /* prepend to the list */ 1220 icd->next = ptr_inst->icds; 1221 ptr_inst->icds = icd; 1222 ptr_inst->total_icd_count++; 1223 1224 return icd; 1225} 1226 1227void loader_scanned_icd_clear( 1228 const struct loader_instance *inst, 1229 struct loader_icd_libs *icd_libs) 1230{ 1231 if (icd_libs->capacity == 0) 1232 return; 1233 for (uint32_t i = 0; i < icd_libs->count; i++) { 1234 loader_platform_close_library(icd_libs->list[i].handle); 1235 loader_heap_free(inst, icd_libs->list[i].lib_name); 1236 } 1237 loader_heap_free(inst, icd_libs->list); 1238 icd_libs->capacity = 0; 1239 icd_libs->count = 0; 1240 icd_libs->list = NULL; 1241} 1242 1243static void loader_scanned_icd_init(const struct loader_instance *inst, 1244 struct loader_icd_libs *icd_libs) 1245{ 1246 loader_scanned_icd_clear(inst, icd_libs); 1247 icd_libs->capacity = 8 * sizeof(struct loader_scanned_icds); 1248 icd_libs->list = loader_heap_alloc(inst, icd_libs->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1249 1250} 1251 1252static void loader_scanned_icd_add( 1253 const struct loader_instance *inst, 1254 struct loader_icd_libs *icd_libs, 1255 const char *filename, 1256 uint32_t api_version) 1257{ 1258 loader_platform_dl_handle handle; 1259 PFN_vkCreateInstance fp_create_inst; 1260 PFN_vkEnumerateInstanceExtensionProperties fp_get_global_ext_props; 1261 PFN_vkGetInstanceProcAddr fp_get_proc_addr; 1262 struct loader_scanned_icds *new_node; 1263 1264 /* TODO implement ref counting of libraries, for now this function leaves 1265 libraries open and the scanned_icd_clear closes them */ 1266 // Used to call: dlopen(filename, RTLD_LAZY); 1267 handle = loader_platform_open_library(filename); 1268 if (!handle) { 1269 loader_log(VK_DBG_REPORT_WARN_BIT, 0, loader_platform_open_library_error(filename)); 1270 return; 1271 } 1272 1273#define LOOKUP_LD(func_ptr, func) do { \ 1274 func_ptr = (PFN_vk ##func) loader_platform_get_proc_address(handle, "vk" #func); \ 1275 if (!func_ptr) { \ 1276 loader_log(VK_DBG_REPORT_WARN_BIT, 0, loader_platform_get_proc_address_error("vk" #func)); \ 1277 return; \ 1278 } \ 1279} while (0) 1280 1281 LOOKUP_LD(fp_get_proc_addr, GetInstanceProcAddr); 1282 LOOKUP_LD(fp_create_inst, CreateInstance); 1283 LOOKUP_LD(fp_get_global_ext_props, EnumerateInstanceExtensionProperties); 1284 1285#undef LOOKUP_LD 1286 1287 // check for enough capacity 1288 if ((icd_libs->count * sizeof(struct loader_scanned_icds)) >= icd_libs->capacity) { 1289 1290 icd_libs->list = loader_heap_realloc(inst, 1291 icd_libs->list, 1292 icd_libs->capacity, 1293 icd_libs->capacity * 2, 1294 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1295 // double capacity 1296 icd_libs->capacity *= 2; 1297 } 1298 new_node = &(icd_libs->list[icd_libs->count]); 1299 1300 new_node->handle = handle; 1301 new_node->api_version = api_version; 1302 new_node->GetInstanceProcAddr = fp_get_proc_addr; 1303 new_node->CreateInstance = fp_create_inst; 1304 new_node->EnumerateInstanceExtensionProperties = fp_get_global_ext_props; 1305 1306 new_node->lib_name = (char *) loader_heap_alloc(inst, 1307 strlen(filename) + 1, 1308 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1309 if (!new_node->lib_name) { 1310 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Out of memory can't add icd"); 1311 return; 1312 } 1313 strcpy(new_node->lib_name, filename); 1314 icd_libs->count++; 1315} 1316 1317static bool loader_icd_init_entrys(struct loader_icd *icd, 1318 VkInstance inst, 1319 const PFN_vkGetInstanceProcAddr fp_gipa) 1320{ 1321 /* initialize entrypoint function pointers */ 1322 1323 #define LOOKUP_GIPA(func, required) do { \ 1324 icd->func = (PFN_vk ##func) fp_gipa(inst, "vk" #func); \ 1325 if (!icd->func && required) { \ 1326 loader_log(VK_DBG_REPORT_WARN_BIT, 0, \ 1327 loader_platform_get_proc_address_error("vk" #func)); \ 1328 return false; \ 1329 } \ 1330 } while (0) 1331 1332 LOOKUP_GIPA(GetDeviceProcAddr, true); 1333 LOOKUP_GIPA(DestroyInstance, true); 1334 LOOKUP_GIPA(EnumeratePhysicalDevices, true); 1335 LOOKUP_GIPA(GetPhysicalDeviceFeatures, true); 1336 LOOKUP_GIPA(GetPhysicalDeviceFormatProperties, true); 1337 LOOKUP_GIPA(GetPhysicalDeviceImageFormatProperties, true); 1338 LOOKUP_GIPA(CreateDevice, true); 1339 LOOKUP_GIPA(GetPhysicalDeviceProperties, true); 1340 LOOKUP_GIPA(GetPhysicalDeviceMemoryProperties, true); 1341 LOOKUP_GIPA(GetPhysicalDeviceQueueFamilyProperties, true); 1342 LOOKUP_GIPA(EnumerateDeviceExtensionProperties, true); 1343 LOOKUP_GIPA(GetPhysicalDeviceSparseImageFormatProperties, true); 1344 LOOKUP_GIPA(DbgCreateMsgCallback, false); 1345 LOOKUP_GIPA(DbgDestroyMsgCallback, false); 1346 LOOKUP_GIPA(GetPhysicalDeviceSurfaceSupportKHR, false); 1347 LOOKUP_GIPA(GetPhysicalDeviceSurfaceCapabilitiesKHR, false); 1348 LOOKUP_GIPA(GetPhysicalDeviceSurfaceFormatsKHR, false); 1349 LOOKUP_GIPA(GetPhysicalDeviceSurfacePresentModesKHR, false); 1350#ifdef VK_USE_PLATFORM_WIN32_KHR 1351 LOOKUP_GIPA(GetPhysicalDeviceWin32PresentationSupportKHR, false); 1352#endif 1353#ifdef VK_USE_PLATFORM_XCB_KHR 1354 LOOKUP_GIPA(GetPhysicalDeviceXcbPresentationSupportKHR, false); 1355#endif 1356 1357#undef LOOKUP_GIPA 1358 1359 return true; 1360} 1361 1362static void loader_debug_init(void) 1363{ 1364 const char *env; 1365 1366 if (g_loader_debug > 0) 1367 return; 1368 1369 g_loader_debug = 0; 1370 1371 /* parse comma-separated debug options */ 1372 env = getenv("VK_LOADER_DEBUG"); 1373 while (env) { 1374 const char *p = strchr(env, ','); 1375 size_t len; 1376 1377 if (p) 1378 len = p - env; 1379 else 1380 len = strlen(env); 1381 1382 if (len > 0) { 1383 if (strncmp(env, "all", len) == 0) { 1384 g_loader_debug = ~0u; 1385 g_loader_log_msgs = ~0u; 1386 } else if (strncmp(env, "warn", len) == 0) { 1387 g_loader_debug |= LOADER_WARN_BIT; 1388 g_loader_log_msgs |= VK_DBG_REPORT_WARN_BIT; 1389 } else if (strncmp(env, "info", len) == 0) { 1390 g_loader_debug |= LOADER_INFO_BIT; 1391 g_loader_log_msgs |= VK_DBG_REPORT_INFO_BIT; 1392 } else if (strncmp(env, "perf", len) == 0) { 1393 g_loader_debug |= LOADER_PERF_BIT; 1394 g_loader_log_msgs |= VK_DBG_REPORT_PERF_WARN_BIT; 1395 } else if (strncmp(env, "error", len) == 0) { 1396 g_loader_debug |= LOADER_ERROR_BIT; 1397 g_loader_log_msgs |= VK_DBG_REPORT_ERROR_BIT; 1398 } else if (strncmp(env, "debug", len) == 0) { 1399 g_loader_debug |= LOADER_DEBUG_BIT; 1400 g_loader_log_msgs |= VK_DBG_REPORT_DEBUG_BIT; 1401 } 1402 } 1403 1404 if (!p) 1405 break; 1406 1407 env = p + 1; 1408 } 1409} 1410 1411void loader_initialize(void) 1412{ 1413 // initialize mutexs 1414 loader_platform_thread_create_mutex(&loader_lock); 1415 loader_platform_thread_create_mutex(&loader_json_lock); 1416 1417 // initialize logging 1418 loader_debug_init(); 1419 1420 // initial cJSON to use alloc callbacks 1421 cJSON_Hooks alloc_fns = { 1422 .malloc_fn = loader_tls_heap_alloc, 1423 .free_fn = loader_tls_heap_free, 1424 }; 1425 cJSON_InitHooks(&alloc_fns); 1426} 1427 1428struct loader_manifest_files { 1429 uint32_t count; 1430 char **filename_list; 1431}; 1432 1433/** 1434 * Get next file or dirname given a string list or registry key path 1435 * 1436 * \returns 1437 * A pointer to first char in the next path. 1438 * The next path (or NULL) in the list is returned in next_path. 1439 * Note: input string is modified in some cases. PASS IN A COPY! 1440 */ 1441static char *loader_get_next_path(char *path) 1442{ 1443 uint32_t len; 1444 char *next; 1445 1446 if (path == NULL) 1447 return NULL; 1448 next = strchr(path, PATH_SEPERATOR); 1449 if (next == NULL) { 1450 len = (uint32_t) strlen(path); 1451 next = path + len; 1452 } 1453 else { 1454 *next = '\0'; 1455 next++; 1456 } 1457 1458 return next; 1459} 1460 1461/** 1462 * Given a path which is absolute or relative, expand the path if relative or 1463 * leave the path unmodified if absolute. The base path to prepend to relative 1464 * paths is given in rel_base. 1465 * 1466 * \returns 1467 * A string in out_fullpath of the full absolute path 1468 */ 1469static void loader_expand_path(const char *path, 1470 const char *rel_base, 1471 size_t out_size, 1472 char *out_fullpath) 1473{ 1474 if (loader_platform_is_path_absolute(path)) { 1475 // do not prepend a base to an absolute path 1476 rel_base = ""; 1477 } 1478 1479 loader_platform_combine_path(out_fullpath, out_size, rel_base, path, NULL); 1480} 1481 1482/** 1483 * Given a filename (file) and a list of paths (dir), try to find an existing 1484 * file in the paths. If filename already is a path then no 1485 * searching in the given paths. 1486 * 1487 * \returns 1488 * A string in out_fullpath of either the full path or file. 1489 */ 1490static void loader_get_fullpath(const char *file, 1491 const char *dirs, 1492 size_t out_size, 1493 char *out_fullpath) 1494{ 1495 if (!loader_platform_is_path(file) && *dirs) { 1496 char *dirs_copy, *dir, *next_dir; 1497 1498 dirs_copy = loader_stack_alloc(strlen(dirs) + 1); 1499 strcpy(dirs_copy, dirs); 1500 1501 //find if file exists after prepending paths in given list 1502 for (dir = dirs_copy; 1503 *dir && (next_dir = loader_get_next_path(dir)); 1504 dir = next_dir) { 1505 loader_platform_combine_path(out_fullpath, out_size, dir, file, NULL); 1506 if (loader_platform_file_exists(out_fullpath)) { 1507 return; 1508 } 1509 } 1510 } 1511 1512 snprintf(out_fullpath, out_size, "%s", file); 1513} 1514 1515/** 1516 * Read a JSON file into a buffer. 1517 * 1518 * \returns 1519 * A pointer to a cJSON object representing the JSON parse tree. 1520 * This returned buffer should be freed by caller. 1521 */ 1522static cJSON *loader_get_json(const char *filename) 1523{ 1524 FILE *file; 1525 char *json_buf; 1526 cJSON *json; 1527 uint64_t len; 1528 file = fopen(filename,"rb"); 1529 if (!file) { 1530 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Couldn't open JSON file %s", filename); 1531 return NULL; 1532 } 1533 fseek(file, 0, SEEK_END); 1534 len = ftell(file); 1535 fseek(file, 0, SEEK_SET); 1536 json_buf = (char*) loader_stack_alloc(len+1); 1537 if (json_buf == NULL) { 1538 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get JSON file"); 1539 fclose(file); 1540 return NULL; 1541 } 1542 if (fread(json_buf, sizeof(char), len, file) != len) { 1543 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "fread failed can't get JSON file"); 1544 fclose(file); 1545 return NULL; 1546 } 1547 fclose(file); 1548 json_buf[len] = '\0'; 1549 1550 //parse text from file 1551 json = cJSON_Parse(json_buf); 1552 if (json == NULL) 1553 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Can't parse JSON file %s", filename); 1554 return json; 1555} 1556 1557/** 1558 * Do a deep copy of the loader_layer_properties structure. 1559 */ 1560static void loader_copy_layer_properties( 1561 const struct loader_instance *inst, 1562 struct loader_layer_properties *dst, 1563 struct loader_layer_properties *src) 1564{ 1565 uint32_t cnt, i; 1566 memcpy(dst, src, sizeof (*src)); 1567 dst->instance_extension_list.list = loader_heap_alloc( 1568 inst, 1569 sizeof(VkExtensionProperties) * 1570 src->instance_extension_list.count, 1571 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1572 dst->instance_extension_list.capacity = sizeof(VkExtensionProperties) * 1573 src->instance_extension_list.count; 1574 memcpy(dst->instance_extension_list.list, src->instance_extension_list.list, 1575 dst->instance_extension_list.capacity); 1576 dst->device_extension_list.list = loader_heap_alloc( 1577 inst, 1578 sizeof(struct loader_dev_ext_props) * 1579 src->device_extension_list.count, 1580 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1581 1582 dst->device_extension_list.capacity = sizeof(struct loader_dev_ext_props) * 1583 src->device_extension_list.count; 1584 memcpy(dst->device_extension_list.list, src->device_extension_list.list, 1585 dst->device_extension_list.capacity); 1586 if (src->device_extension_list.count > 0 && 1587 src->device_extension_list.list->entrypoint_count > 0) { 1588 cnt = src->device_extension_list.list->entrypoint_count; 1589 dst->device_extension_list.list->entrypoints = loader_heap_alloc( 1590 inst, 1591 sizeof(char *) * cnt, 1592 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1593 for (i = 0; i < cnt; i++) { 1594 dst->device_extension_list.list->entrypoints[i] = loader_heap_alloc( 1595 inst, 1596 strlen(src->device_extension_list.list->entrypoints[i]) + 1, 1597 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1598 strcpy(dst->device_extension_list.list->entrypoints[i], 1599 src->device_extension_list.list->entrypoints[i]); 1600 } 1601 } 1602} 1603 1604/** 1605 * Given a cJSON struct (json) of the top level JSON object from layer manifest 1606 * file, add entry to the layer_list. 1607 * Fill out the layer_properties in this list entry from the input cJSON object. 1608 * 1609 * \returns 1610 * void 1611 * layer_list has a new entry and initialized accordingly. 1612 * If the json input object does not have all the required fields no entry 1613 * is added to the list. 1614 */ 1615static void loader_add_layer_properties(const struct loader_instance *inst, 1616 struct loader_layer_list *layer_instance_list, 1617 struct loader_layer_list *layer_device_list, 1618 cJSON *json, 1619 bool is_implicit, 1620 char *filename) 1621{ 1622 /* Fields in layer manifest file that are required: 1623 * (required) “file_format_version” 1624 * following are required in the "layer" object: 1625 * (required) "name" 1626 * (required) "type" 1627 * (required) “library_path” 1628 * (required) “api_version” 1629 * (required) “implementation_version” 1630 * (required) “description” 1631 * (required for implicit layers) “disable_environment” 1632 * 1633 * First get all required items and if any missing abort 1634 */ 1635 1636 cJSON *item, *layer_node, *ext_item; 1637 char *temp; 1638 char *name, *type, *library_path, *api_version; 1639 char *implementation_version, *description; 1640 cJSON *disable_environment; 1641 int i, j; 1642 VkExtensionProperties ext_prop; 1643 item = cJSON_GetObjectItem(json, "file_format_version"); 1644 if (item == NULL) { 1645 return; 1646 } 1647 char *file_vers = cJSON_PrintUnformatted(item); 1648 loader_log(VK_DBG_REPORT_INFO_BIT, 0, "Found manifest file %s, version %s", 1649 filename, file_vers); 1650 if (strcmp(file_vers, "\"1.0.0\"") != 0) 1651 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Unexpected manifest file version (expected 1.0.0), may cause errors"); 1652 loader_tls_heap_free(file_vers); 1653 1654 layer_node = cJSON_GetObjectItem(json, "layer"); 1655 if (layer_node == NULL) { 1656 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"layer\" object in manifest JSON file, skipping"); 1657 return; 1658 } 1659 1660 // loop through all "layer" objects in the file 1661 do { 1662#define GET_JSON_OBJECT(node, var) { \ 1663 var = cJSON_GetObjectItem(node, #var); \ 1664 if (var == NULL) { \ 1665 layer_node = layer_node->next; \ 1666 continue; \ 1667 } \ 1668 } 1669#define GET_JSON_ITEM(node, var) { \ 1670 item = cJSON_GetObjectItem(node, #var); \ 1671 if (item == NULL) { \ 1672 layer_node = layer_node->next; \ 1673 continue; \ 1674 } \ 1675 temp = cJSON_Print(item); \ 1676 temp[strlen(temp) - 1] = '\0'; \ 1677 var = loader_stack_alloc(strlen(temp) + 1); \ 1678 strcpy(var, &temp[1]); \ 1679 loader_tls_heap_free(temp); \ 1680 } 1681 GET_JSON_ITEM(layer_node, name) 1682 GET_JSON_ITEM(layer_node, type) 1683 GET_JSON_ITEM(layer_node, library_path) 1684 GET_JSON_ITEM(layer_node, api_version) 1685 GET_JSON_ITEM(layer_node, implementation_version) 1686 GET_JSON_ITEM(layer_node, description) 1687 if (is_implicit) { 1688 GET_JSON_OBJECT(layer_node, disable_environment) 1689 } 1690#undef GET_JSON_ITEM 1691#undef GET_JSON_OBJECT 1692 1693 // add list entry 1694 struct loader_layer_properties *props=NULL; 1695 if (!strcmp(type, "DEVICE")) { 1696 if (layer_device_list == NULL) { 1697 layer_node = layer_node->next; 1698 continue; 1699 } 1700 props = loader_get_next_layer_property(inst, layer_device_list); 1701 props->type = (is_implicit) ? VK_LAYER_TYPE_DEVICE_IMPLICIT : VK_LAYER_TYPE_DEVICE_EXPLICIT; 1702 } 1703 if (!strcmp(type, "INSTANCE")) { 1704 if (layer_instance_list == NULL) { 1705 layer_node = layer_node->next; 1706 continue; 1707 } 1708 props = loader_get_next_layer_property(inst, layer_instance_list); 1709 props->type = (is_implicit) ? VK_LAYER_TYPE_INSTANCE_IMPLICIT : VK_LAYER_TYPE_INSTANCE_EXPLICIT; 1710 } 1711 if (!strcmp(type, "GLOBAL")) { 1712 if (layer_instance_list != NULL) 1713 props = loader_get_next_layer_property(inst, layer_instance_list); 1714 else if (layer_device_list != NULL) 1715 props = loader_get_next_layer_property(inst, layer_device_list); 1716 else { 1717 layer_node = layer_node->next; 1718 continue; 1719 } 1720 props->type = (is_implicit) ? VK_LAYER_TYPE_GLOBAL_IMPLICIT : VK_LAYER_TYPE_GLOBAL_EXPLICIT; 1721 } 1722 1723 if (props == NULL) { 1724 layer_node = layer_node->next; 1725 continue; 1726 } 1727 1728 strncpy(props->info.layerName, name, sizeof (props->info.layerName)); 1729 props->info.layerName[sizeof (props->info.layerName) - 1] = '\0'; 1730 1731 char *fullpath = props->lib_name; 1732 char *rel_base; 1733 if (loader_platform_is_path(library_path)) { 1734 // a relative or absolute path 1735 char *name_copy = loader_stack_alloc(strlen(filename) + 1); 1736 strcpy(name_copy, filename); 1737 rel_base = loader_platform_dirname(name_copy); 1738 loader_expand_path(library_path, rel_base, MAX_STRING_SIZE, fullpath); 1739 } else { 1740 // a filename which is assumed in a system directory 1741 loader_get_fullpath(library_path, DEFAULT_VK_LAYERS_PATH, MAX_STRING_SIZE, fullpath); 1742 } 1743 props->info.specVersion = loader_make_version(api_version); 1744 props->info.implementationVersion = atoi(implementation_version); 1745 strncpy((char *) props->info.description, description, sizeof (props->info.description)); 1746 props->info.description[sizeof (props->info.description) - 1] = '\0'; 1747 if (is_implicit) { 1748 strncpy(props->disable_env_var.name, disable_environment->child->string, sizeof (props->disable_env_var.name)); 1749 props->disable_env_var.name[sizeof (props->disable_env_var.name) - 1] = '\0'; 1750 strncpy(props->disable_env_var.value, disable_environment->child->valuestring, sizeof (props->disable_env_var.value)); 1751 props->disable_env_var.value[sizeof (props->disable_env_var.value) - 1] = '\0'; 1752 } 1753 1754 /** 1755 * Now get all optional items and objects and put in list: 1756 * functions 1757 * instance_extensions 1758 * device_extensions 1759 * enable_environment (implicit layers only) 1760 * disable_environment (implicit_layers_only) 1761 */ 1762#define GET_JSON_OBJECT(node, var) { \ 1763 var = cJSON_GetObjectItem(node, #var); \ 1764 } 1765#define GET_JSON_ITEM(node, var) { \ 1766 item = cJSON_GetObjectItem(node, #var); \ 1767 if (item != NULL) { \ 1768 temp = cJSON_Print(item); \ 1769 temp[strlen(temp) - 1] = '\0'; \ 1770 var = loader_stack_alloc(strlen(temp) + 1);\ 1771 strcpy(var, &temp[1]); \ 1772 loader_tls_heap_free(temp); \ 1773 } \ 1774 } 1775 1776 cJSON *instance_extensions, *device_extensions, *functions, *enable_environment; 1777 cJSON *entrypoints; 1778 char *vkGetInstanceProcAddr, *vkGetDeviceProcAddr, *spec_version; 1779 char **entry_array; 1780 vkGetInstanceProcAddr = NULL; 1781 vkGetDeviceProcAddr = NULL; 1782 spec_version = NULL; 1783 entrypoints = NULL; 1784 entry_array = NULL; 1785 /** 1786 * functions 1787 * vkGetInstanceProcAddr 1788 * vkGetDeviceProcAddr 1789 */ 1790 GET_JSON_OBJECT(layer_node, functions) 1791 if (functions != NULL) { 1792 GET_JSON_ITEM(functions, vkGetInstanceProcAddr) 1793 GET_JSON_ITEM(functions, vkGetDeviceProcAddr) 1794 if (vkGetInstanceProcAddr != NULL) 1795 strncpy(props->functions.str_gipa, vkGetInstanceProcAddr, sizeof (props->functions.str_gipa)); 1796 props->functions.str_gipa[sizeof (props->functions.str_gipa) - 1] = '\0'; 1797 if (vkGetDeviceProcAddr != NULL) 1798 strncpy(props->functions.str_gdpa, vkGetDeviceProcAddr, sizeof (props->functions.str_gdpa)); 1799 props->functions.str_gdpa[sizeof (props->functions.str_gdpa) - 1] = '\0'; 1800 } 1801 /** 1802 * instance_extensions 1803 * array of 1804 * name 1805 * spec_version 1806 */ 1807 GET_JSON_OBJECT(layer_node, instance_extensions) 1808 if (instance_extensions != NULL) { 1809 int count = cJSON_GetArraySize(instance_extensions); 1810 for (i = 0; i < count; i++) { 1811 ext_item = cJSON_GetArrayItem(instance_extensions, i); 1812 GET_JSON_ITEM(ext_item, name) 1813 GET_JSON_ITEM(ext_item, spec_version) 1814 if (name != NULL) { 1815 strncpy(ext_prop.extensionName, name, sizeof (ext_prop.extensionName)); 1816 ext_prop.extensionName[sizeof (ext_prop.extensionName) - 1] = '\0'; 1817 } 1818 ext_prop.specVersion = atoi(spec_version); 1819 loader_add_to_ext_list(inst, &props->instance_extension_list, 1, &ext_prop); 1820 } 1821 } 1822 /** 1823 * device_extensions 1824 * array of 1825 * name 1826 * spec_version 1827 * entrypoints 1828 */ 1829 GET_JSON_OBJECT(layer_node, device_extensions) 1830 if (device_extensions != NULL) { 1831 int count = cJSON_GetArraySize(device_extensions); 1832 for (i = 0; i < count; i++) { 1833 ext_item = cJSON_GetArrayItem(device_extensions, i); 1834 GET_JSON_ITEM(ext_item, name) 1835 GET_JSON_ITEM(ext_item, spec_version) 1836 if (name != NULL) { 1837 strncpy(ext_prop.extensionName, name, sizeof (ext_prop.extensionName)); 1838 ext_prop.extensionName[sizeof (ext_prop.extensionName) - 1] = '\0'; 1839 } 1840 ext_prop.specVersion = atoi(spec_version); 1841 //entrypoints = cJSON_GetObjectItem(ext_item, "entrypoints"); 1842 GET_JSON_OBJECT(ext_item, entrypoints) 1843 int entry_count; 1844 if (entrypoints == NULL) 1845 continue; 1846 entry_count = cJSON_GetArraySize(entrypoints); 1847 if (entry_count) 1848 entry_array = (char **) loader_stack_alloc(sizeof(char *) * entry_count); 1849 for (j = 0; j < entry_count; j++) { 1850 ext_item = cJSON_GetArrayItem(entrypoints, j); 1851 if (ext_item != NULL) { 1852 temp = cJSON_Print(ext_item); 1853 temp[strlen(temp) - 1] = '\0'; 1854 entry_array[j] = loader_stack_alloc(strlen(temp) + 1); 1855 strcpy(entry_array[j], &temp[1]); 1856 loader_tls_heap_free(temp); 1857 } 1858 } 1859 loader_add_to_dev_ext_list(inst, &props->device_extension_list, 1860 &ext_prop, entry_count, entry_array); 1861 } 1862 } 1863 if (is_implicit) { 1864 GET_JSON_OBJECT(layer_node, enable_environment) 1865 strncpy(props->enable_env_var.name, enable_environment->child->string, sizeof (props->enable_env_var.name)); 1866 props->enable_env_var.name[sizeof (props->enable_env_var.name) - 1] = '\0'; 1867 strncpy(props->enable_env_var.value, enable_environment->child->valuestring, sizeof (props->enable_env_var.value)); 1868 props->enable_env_var.value[sizeof (props->enable_env_var.value) - 1] = '\0'; 1869 //TODO add disable_environment for implicit layers 1870 } 1871#undef GET_JSON_ITEM 1872#undef GET_JSON_OBJECT 1873 // for global layers need to add them to both device and instance list 1874 if (!strcmp(type, "GLOBAL")) { 1875 struct loader_layer_properties *dev_props; 1876 if (layer_instance_list == NULL || layer_device_list == NULL) { 1877 layer_node = layer_node->next; 1878 continue; 1879 } 1880 dev_props = loader_get_next_layer_property(inst, layer_device_list); 1881 //copy into device layer list 1882 loader_copy_layer_properties(inst, dev_props, props); 1883 } 1884 layer_node = layer_node->next; 1885 } while (layer_node != NULL); 1886 return; 1887} 1888 1889/** 1890 * Find the Vulkan library manifest files. 1891 * 1892 * This function scans the location or env_override directories/files 1893 * for a list of JSON manifest files. If env_override is non-NULL 1894 * and has a valid value. Then the location is ignored. Otherwise 1895 * location is used to look for manifest files. The location 1896 * is interpreted as Registry path on Windows and a directory path(s) 1897 * on Linux. 1898 * 1899 * \returns 1900 * A string list of manifest files to be opened in out_files param. 1901 * List has a pointer to string for each manifest filename. 1902 * When done using the list in out_files, pointers should be freed. 1903 * Location or override string lists can be either files or directories as follows: 1904 * | location | override 1905 * -------------------------------- 1906 * Win ICD | files | files 1907 * Win Layer | files | dirs 1908 * Linux ICD | dirs | files 1909 * Linux Layer| dirs | dirs 1910 */ 1911static void loader_get_manifest_files(const struct loader_instance *inst, 1912 const char *env_override, 1913 bool is_layer, 1914 const char *location, 1915 struct loader_manifest_files *out_files) 1916{ 1917 char *override = NULL; 1918 char *loc; 1919 char *file, *next_file, *name; 1920 size_t alloced_count = 64; 1921 char full_path[2048]; 1922 DIR *sysdir = NULL; 1923 bool list_is_dirs = false; 1924 struct dirent *dent; 1925 1926 out_files->count = 0; 1927 out_files->filename_list = NULL; 1928 1929 if (env_override != NULL && (override = getenv(env_override))) { 1930#if !defined(_WIN32) 1931 if (geteuid() != getuid()) { 1932 /* Don't allow setuid apps to use the env var: */ 1933 override = NULL; 1934 } 1935#endif 1936 } 1937 1938 if (location == NULL) { 1939 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, 1940 "Can't get manifest files with NULL location, env_override=%s", 1941 env_override); 1942 return; 1943 } 1944 1945#if defined(_WIN32) 1946 list_is_dirs = (is_layer && override != NULL) ? true : false; 1947#else 1948 list_is_dirs = (override == NULL || is_layer) ? true : false; 1949#endif 1950 // Make a copy of the input we are using so it is not modified 1951 // Also handle getting the location(s) from registry on Windows 1952 if (override == NULL) { 1953 loc = loader_stack_alloc(strlen(location) + 1); 1954 if (loc == NULL) { 1955 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files"); 1956 return; 1957 } 1958 strcpy(loc, location); 1959#if defined(_WIN32) 1960 loc = loader_get_registry_files(inst, loc); 1961 if (loc == NULL) { 1962 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Registry lookup failed can't get manifest files"); 1963 return; 1964 } 1965#endif 1966 } 1967 else { 1968 loc = loader_stack_alloc(strlen(override) + 1); 1969 if (loc == NULL) { 1970 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files"); 1971 return; 1972 } 1973 strcpy(loc, override); 1974 } 1975 1976 // Print out the paths being searched if debugging is enabled 1977 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, "Searching the following paths for manifest files: %s\n", loc); 1978 1979 file = loc; 1980 while (*file) { 1981 next_file = loader_get_next_path(file); 1982 if (list_is_dirs) { 1983 sysdir = opendir(file); 1984 name = NULL; 1985 if (sysdir) { 1986 dent = readdir(sysdir); 1987 if (dent == NULL) 1988 break; 1989 name = &(dent->d_name[0]); 1990 loader_get_fullpath(name, file, sizeof(full_path), full_path); 1991 name = full_path; 1992 } 1993 } 1994 else { 1995#if defined(_WIN32) 1996 name = file; 1997#else 1998 // only Linux has relative paths 1999 char *dir; 2000 // make a copy of location so it isn't modified 2001 dir = loader_stack_alloc(strlen(loc) + 1); 2002 if (dir == NULL) { 2003 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files"); 2004 return; 2005 } 2006 strcpy(dir, loc); 2007 2008 loader_get_fullpath(file, dir, sizeof(full_path), full_path); 2009 2010 name = full_path; 2011#endif 2012 } 2013 while (name) { 2014 /* Look for files ending with ".json" suffix */ 2015 uint32_t nlen = (uint32_t) strlen(name); 2016 const char *suf = name + nlen - 5; 2017 if ((nlen > 5) && !strncmp(suf, ".json", 5)) { 2018 if (out_files->count == 0) { 2019 out_files->filename_list = loader_heap_alloc(inst, 2020 alloced_count * sizeof(char *), 2021 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 2022 } 2023 else if (out_files->count == alloced_count) { 2024 out_files->filename_list = loader_heap_realloc(inst, 2025 out_files->filename_list, 2026 alloced_count * sizeof(char *), 2027 alloced_count * sizeof(char *) * 2, 2028 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 2029 alloced_count *= 2; 2030 } 2031 if (out_files->filename_list == NULL) { 2032 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't alloc manifest file list"); 2033 return; 2034 } 2035 out_files->filename_list[out_files->count] = loader_heap_alloc( 2036 inst, 2037 strlen(name) + 1, 2038 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 2039 if (out_files->filename_list[out_files->count] == NULL) { 2040 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Out of memory can't get manifest files"); 2041 return; 2042 } 2043 strcpy(out_files->filename_list[out_files->count], name); 2044 out_files->count++; 2045 } else if (!list_is_dirs) { 2046 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Skipping manifest file %s, file name must end in .json", name); 2047 } 2048 if (list_is_dirs) { 2049 dent = readdir(sysdir); 2050 if (dent == NULL) 2051 break; 2052 name = &(dent->d_name[0]); 2053 loader_get_fullpath(name, file, sizeof(full_path), full_path); 2054 name = full_path; 2055 } 2056 else { 2057 break; 2058 } 2059 } 2060 if (sysdir) 2061 closedir(sysdir); 2062 file = next_file; 2063 } 2064 return; 2065} 2066 2067void loader_init_icd_lib_list() 2068{ 2069 2070} 2071 2072void loader_destroy_icd_lib_list() 2073{ 2074 2075} 2076/** 2077 * Try to find the Vulkan ICD driver(s). 2078 * 2079 * This function scans the default system loader path(s) or path 2080 * specified by the \c VK_ICD_FILENAMES environment variable in 2081 * order to find loadable VK ICDs manifest files. From these 2082 * manifest files it finds the ICD libraries. 2083 * 2084 * \returns 2085 * a list of icds that were discovered 2086 */ 2087void loader_icd_scan( 2088 const struct loader_instance *inst, 2089 struct loader_icd_libs *icds) 2090{ 2091 char *file_str; 2092 struct loader_manifest_files manifest_files; 2093 2094 loader_scanned_icd_init(inst, icds); 2095 // Get a list of manifest files for ICDs 2096 loader_get_manifest_files(inst, "VK_ICD_FILENAMES", false, 2097 DEFAULT_VK_DRIVERS_INFO, &manifest_files); 2098 if (manifest_files.count == 0) 2099 return; 2100 loader_platform_thread_lock_mutex(&loader_json_lock); 2101 for (uint32_t i = 0; i < manifest_files.count; i++) { 2102 file_str = manifest_files.filename_list[i]; 2103 if (file_str == NULL) 2104 continue; 2105 2106 cJSON *json; 2107 json = loader_get_json(file_str); 2108 if (!json) 2109 continue; 2110 cJSON *item, *itemICD; 2111 item = cJSON_GetObjectItem(json, "file_format_version"); 2112 if (item == NULL) { 2113 loader_platform_thread_unlock_mutex(&loader_json_lock); 2114 return; 2115 } 2116 char *file_vers = cJSON_Print(item); 2117 loader_log(VK_DBG_REPORT_INFO_BIT, 0, "Found manifest file %s, version %s", 2118 file_str, file_vers); 2119 if (strcmp(file_vers, "\"1.0.0\"") != 0) 2120 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Unexpected manifest file version (expected 1.0.0), may cause errors"); 2121 loader_tls_heap_free(file_vers); 2122 itemICD = cJSON_GetObjectItem(json, "ICD"); 2123 if (itemICD != NULL) { 2124 item = cJSON_GetObjectItem(itemICD, "library_path"); 2125 if (item != NULL) { 2126 char *temp= cJSON_Print(item); 2127 if (!temp || strlen(temp) == 0) { 2128 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"library_path\" in ICD JSON file %s, skipping", file_str); 2129 loader_tls_heap_free(temp); 2130 loader_heap_free(inst, file_str); 2131 cJSON_Delete(json); 2132 continue; 2133 } 2134 //strip out extra quotes 2135 temp[strlen(temp) - 1] = '\0'; 2136 char *library_path = loader_stack_alloc(strlen(temp) + 1); 2137 strcpy(library_path, &temp[1]); 2138 loader_tls_heap_free(temp); 2139 if (!library_path || strlen(library_path) == 0) { 2140 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"library_path\" in ICD JSON file %s, skipping", file_str); 2141 loader_heap_free(inst, file_str); 2142 cJSON_Delete(json); 2143 continue; 2144 } 2145 char fullpath[MAX_STRING_SIZE]; 2146 // Print out the paths being searched if debugging is enabled 2147 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, "Searching for ICD drivers named %s default dir %s\n", library_path, DEFAULT_VK_DRIVERS_PATH); 2148 if (loader_platform_is_path(library_path)) { 2149 // a relative or absolute path 2150 char *name_copy = loader_stack_alloc(strlen(file_str) + 1); 2151 char *rel_base; 2152 strcpy(name_copy, file_str); 2153 rel_base = loader_platform_dirname(name_copy); 2154 loader_expand_path(library_path, rel_base, sizeof(fullpath), fullpath); 2155 } else { 2156 // a filename which is assumed in a system directory 2157 loader_get_fullpath(library_path, DEFAULT_VK_DRIVERS_PATH, sizeof(fullpath), fullpath); 2158 } 2159 2160 uint32_t vers = 0; 2161 item = cJSON_GetObjectItem(itemICD, "api_version"); 2162 if (item != NULL) { 2163 temp= cJSON_Print(item); 2164 vers = loader_make_version(temp); 2165 loader_tls_heap_free(temp); 2166 } 2167 loader_scanned_icd_add(inst, icds, fullpath, vers); 2168 } 2169 else 2170 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"library_path\" object in ICD JSON file %s, skipping", file_str); 2171 } 2172 else 2173 loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Can't find \"ICD\" object in ICD JSON file %s, skipping", file_str); 2174 2175 loader_heap_free(inst, file_str); 2176 cJSON_Delete(json); 2177 } 2178 loader_heap_free(inst, manifest_files.filename_list); 2179 loader_platform_thread_unlock_mutex(&loader_json_lock); 2180} 2181 2182 2183void loader_layer_scan( 2184 const struct loader_instance *inst, 2185 struct loader_layer_list *instance_layers, 2186 struct loader_layer_list *device_layers) 2187{ 2188 char *file_str; 2189 struct loader_manifest_files manifest_files; 2190 cJSON *json; 2191 uint32_t i; 2192 2193 // Get a list of manifest files for layers 2194 loader_get_manifest_files(inst, LAYERS_PATH_ENV, true, DEFAULT_VK_LAYERS_INFO, 2195 &manifest_files); 2196 if (manifest_files.count == 0) 2197 return; 2198 2199#if 0 //TODO 2200 /** 2201 * We need a list of the layer libraries, not just a list of 2202 * the layer properties (a layer library could expose more than 2203 * one layer property). This list of scanned layers would be 2204 * used to check for global and physicaldevice layer properties. 2205 */ 2206 if (!loader_init_layer_library_list(&loader.scanned_layer_libraries)) { 2207 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, 2208 "Alloc for layer list failed: %s line: %d", __FILE__, __LINE__); 2209 return; 2210 } 2211#endif 2212 2213 /* cleanup any previously scanned libraries */ 2214 loader_delete_layer_properties(inst, instance_layers); 2215 loader_delete_layer_properties(inst, device_layers); 2216 2217 loader_platform_thread_lock_mutex(&loader_json_lock); 2218 for (i = 0; i < manifest_files.count; i++) { 2219 file_str = manifest_files.filename_list[i]; 2220 if (file_str == NULL) 2221 continue; 2222 2223 // parse file into JSON struct 2224 json = loader_get_json(file_str); 2225 if (!json) { 2226 continue; 2227 } 2228 2229 //TODO pass in implicit versus explicit bool 2230 //TODO error if device layers expose instance_extensions 2231 //TODO error if instance layers expose device extensions 2232 loader_add_layer_properties(inst, 2233 instance_layers, 2234 device_layers, 2235 json, 2236 false, 2237 file_str); 2238 2239 loader_heap_free(inst, file_str); 2240 cJSON_Delete(json); 2241 } 2242 loader_heap_free(inst, manifest_files.filename_list); 2243 loader_platform_thread_unlock_mutex(&loader_json_lock); 2244} 2245 2246static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL loader_gpa_instance_internal(VkInstance inst, const char * pName) 2247{ 2248 // inst is not wrapped 2249 if (inst == VK_NULL_HANDLE) { 2250 return NULL; 2251 } 2252 VkLayerInstanceDispatchTable* disp_table = * (VkLayerInstanceDispatchTable **) inst; 2253 void *addr; 2254 2255 if (!strcmp(pName, "vkGetInstanceProcAddr")) 2256 return (void *) loader_gpa_instance_internal; 2257 2258 if (disp_table == NULL) 2259 return NULL; 2260 2261 addr = loader_lookup_instance_dispatch_table(disp_table, pName); 2262 if (addr) { 2263 return addr; 2264 } 2265 2266 if (disp_table->GetInstanceProcAddr == NULL) { 2267 return NULL; 2268 } 2269 return disp_table->GetInstanceProcAddr(inst, pName); 2270} 2271 2272/** 2273 * Initialize device_ext dispatch table entry as follows: 2274 * If dev == NULL find all logical devices created within this instance and 2275 * init the entry (given by idx) in the ext dispatch table. 2276 * If dev != NULL only initialize the entry in the given dev's dispatch table. 2277 * The initialization value is gotten by calling down the device chain with GDPA. 2278 * If GDPA returns NULL then don't initialize the dispatch table entry. 2279 */ 2280static void loader_init_dispatch_dev_ext_entry(struct loader_instance *inst, 2281 struct loader_device *dev, 2282 uint32_t idx, 2283 const char *funcName) 2284 2285 { 2286 void *gdpa_value; 2287 if (dev != NULL) { 2288 gdpa_value = dev->loader_dispatch.core_dispatch.GetDeviceProcAddr( 2289 dev->device, funcName); 2290 if (gdpa_value != NULL) 2291 dev->loader_dispatch.ext_dispatch.DevExt[idx] = (PFN_vkDevExt) gdpa_value; 2292 } else { 2293 for (uint32_t i = 0; i < inst->total_icd_count; i++) { 2294 struct loader_icd *icd = &inst->icds[i]; 2295 struct loader_device *dev = icd->logical_device_list; 2296 while (dev) { 2297 gdpa_value = dev->loader_dispatch.core_dispatch.GetDeviceProcAddr( 2298 dev->device, funcName); 2299 if (gdpa_value != NULL) 2300 dev->loader_dispatch.ext_dispatch.DevExt[idx] = 2301 (PFN_vkDevExt) gdpa_value; 2302 dev = dev->next; 2303 } 2304 } 2305 } 2306 2307} 2308 2309/** 2310 * Find all dev extension in the hash table and initialize the dispatch table 2311 * for dev for each of those extension entrypoints found in hash table. 2312 2313 */ 2314static void loader_init_dispatch_dev_ext(struct loader_instance *inst, 2315 struct loader_device *dev) 2316{ 2317 for (uint32_t i = 0; i < MAX_NUM_DEV_EXTS; i++) { 2318 if (inst->disp_hash[i].func_name != NULL) 2319 loader_init_dispatch_dev_ext_entry(inst, dev, i, 2320 inst->disp_hash[i].func_name); 2321 } 2322} 2323 2324static bool loader_check_icds_for_address(struct loader_instance *inst, 2325 const char *funcName) 2326{ 2327 struct loader_icd *icd; 2328 icd = inst->icds; 2329 while (icd) { 2330 if (icd->this_icd_lib->GetInstanceProcAddr(icd->instance, funcName)) 2331 // this icd supports funcName 2332 return true; 2333 icd = icd->next; 2334 } 2335 2336 return false; 2337} 2338 2339static void loader_free_dev_ext_table(struct loader_instance *inst) 2340{ 2341 for (uint32_t i = 0; i < MAX_NUM_DEV_EXTS; i++) { 2342 loader_heap_free(inst, inst->disp_hash[i].func_name); 2343 loader_heap_free(inst, inst->disp_hash[i].list.index); 2344 2345 } 2346 memset(inst->disp_hash, 0, sizeof(inst->disp_hash)); 2347} 2348 2349static bool loader_add_dev_ext_table(struct loader_instance *inst, 2350 uint32_t *ptr_idx, 2351 const char *funcName) 2352{ 2353 uint32_t i; 2354 uint32_t idx = *ptr_idx; 2355 struct loader_dispatch_hash_list *list = &inst->disp_hash[idx].list; 2356 2357 if (!inst->disp_hash[idx].func_name) { 2358 // no entry here at this idx, so use it 2359 assert(list->capacity == 0); 2360 inst->disp_hash[idx].func_name = (char *) loader_heap_alloc(inst, 2361 strlen(funcName) + 1, 2362 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 2363 if (inst->disp_hash[idx].func_name == NULL) { 2364 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, 2365 "loader_add_dev_ext_table() can't allocate memory for func_name"); 2366 return false; 2367 } 2368 strncpy(inst->disp_hash[idx].func_name, funcName, strlen(funcName) + 1); 2369 return true; 2370 } 2371 2372 // check for enough capacity 2373 if (list->capacity == 0) { 2374 list->index = loader_heap_alloc(inst, 8 * sizeof(*(list->index)), 2375 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 2376 if (list->index == NULL) { 2377 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, 2378 "loader_add_dev_ext_table() can't allocate list memory"); 2379 return false; 2380 } 2381 list->capacity = 8 * sizeof(*(list->index)); 2382 } else if (list->capacity < (list->count + 1) * sizeof(*(list->index))) { 2383 list->index = loader_heap_realloc(inst, list->index, list->capacity, 2384 list->capacity * 2, 2385 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 2386 if (list->index == NULL) { 2387 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, 2388 "loader_add_dev_ext_table() can't reallocate list memory"); 2389 return false; 2390 } 2391 list->capacity *= 2; 2392 } 2393 2394 //find an unused index in the hash table and use it 2395 i = (idx + 1) % MAX_NUM_DEV_EXTS; 2396 do { 2397 if (!inst->disp_hash[i].func_name) { 2398 assert(inst->disp_hash[i].list.capacity == 0); 2399 inst->disp_hash[i].func_name = (char *) loader_heap_alloc(inst, 2400 strlen(funcName) + 1, 2401 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 2402 if (inst->disp_hash[i].func_name == NULL) { 2403 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, 2404 "loader_add_dev_ext_table() can't rallocate func_name memory"); 2405 return false; 2406 } 2407 strncpy(inst->disp_hash[i].func_name, funcName, strlen(funcName) + 1); 2408 list->index[list->count] = i; 2409 list->count++; 2410 *ptr_idx = i; 2411 return true; 2412 } 2413 i = (i + 1) % MAX_NUM_DEV_EXTS; 2414 } while (i != idx); 2415 2416 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, 2417 "loader_add_dev_ext_table() couldn't insert into hash table; is it full?"); 2418 return false; 2419} 2420 2421static bool loader_name_in_dev_ext_table(struct loader_instance *inst, 2422 uint32_t *idx, 2423 const char *funcName) 2424{ 2425 uint32_t alt_idx; 2426 if (inst->disp_hash[*idx].func_name && !strcmp( 2427 inst->disp_hash[*idx].func_name, 2428 funcName)) 2429 return true; 2430 2431 // funcName wasn't at the primary spot in the hash table 2432 // search the list of secondary locations (shallow search, not deep search) 2433 for (uint32_t i = 0; i < inst->disp_hash[*idx].list.count; i++) { 2434 alt_idx = inst->disp_hash[*idx].list.index[i]; 2435 if (!strcmp(inst->disp_hash[*idx].func_name, funcName)) { 2436 *idx = alt_idx; 2437 return true; 2438 } 2439 } 2440 2441 return false; 2442} 2443 2444/** 2445 * This function returns generic trampoline code address for unknown entry points. 2446 * Presumably, these unknown entry points (as given by funcName) are device 2447 * extension entrypoints. A hash table is used to keep a list of unknown entry 2448 * points and their mapping to the device extension dispatch table 2449 * (struct loader_dev_ext_dispatch_table). 2450 * \returns 2451 * For a given entry point string (funcName), if an existing mapping is found the 2452 * trampoline address for that mapping is returned. Otherwise, this unknown entry point 2453 * has not been seen yet. Next check if a layer or ICD supports it. If so then a 2454 * new entry in the hash table is initialized and that trampoline address for 2455 * the new entry is returned. Null is returned if the hash table is full or 2456 * if no discovered layer or ICD returns a non-NULL GetProcAddr for it. 2457 */ 2458void *loader_dev_ext_gpa(struct loader_instance *inst, 2459 const char *funcName) 2460{ 2461 uint32_t idx; 2462 uint32_t seed = 0; 2463 2464 idx = murmurhash(funcName, strlen(funcName), seed) % MAX_NUM_DEV_EXTS; 2465 2466 if (loader_name_in_dev_ext_table(inst, &idx, funcName)) 2467 // found funcName already in hash 2468 return loader_get_dev_ext_trampoline(idx); 2469 2470 // Check if funcName is supported in either ICDs or a layer library 2471 if (!loader_check_icds_for_address(inst, funcName)) { 2472 // TODO Add check in layer libraries for support of address 2473 // if support found in layers continue on 2474 return NULL; 2475 } 2476 2477 if (loader_add_dev_ext_table(inst, &idx, funcName)) { 2478 // successfully added new table entry 2479 // init any dev dispatch table entrys as needed 2480 loader_init_dispatch_dev_ext_entry(inst, NULL, idx, funcName); 2481 return loader_get_dev_ext_trampoline(idx); 2482 } 2483 2484 return NULL; 2485} 2486 2487struct loader_instance *loader_get_instance(const VkInstance instance) 2488{ 2489 /* look up the loader_instance in our list by comparing dispatch tables, as 2490 * there is no guarantee the instance is still a loader_instance* after any 2491 * layers which wrap the instance object. 2492 */ 2493 const VkLayerInstanceDispatchTable *disp; 2494 struct loader_instance *ptr_instance = NULL; 2495 disp = loader_get_instance_dispatch(instance); 2496 for (struct loader_instance *inst = loader.instances; inst; inst = inst->next) { 2497 if (inst->disp == disp) { 2498 ptr_instance = inst; 2499 break; 2500 } 2501 } 2502 return ptr_instance; 2503} 2504 2505static loader_platform_dl_handle loader_add_layer_lib( 2506 const struct loader_instance *inst, 2507 const char *chain_type, 2508 struct loader_layer_properties *layer_prop) 2509{ 2510 struct loader_lib_info *new_layer_lib_list, *my_lib; 2511 size_t new_alloc_size; 2512 /* 2513 * TODO: We can now track this information in the 2514 * scanned_layer_libraries list. 2515 */ 2516 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) { 2517 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, layer_prop->lib_name) == 0) { 2518 /* Have already loaded this library, just increment ref count */ 2519 loader.loaded_layer_lib_list[i].ref_count++; 2520 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, 2521 "%s Chain: Increment layer reference count for layer library %s", 2522 chain_type, layer_prop->lib_name); 2523 return loader.loaded_layer_lib_list[i].lib_handle; 2524 } 2525 } 2526 2527 /* Haven't seen this library so load it */ 2528 new_alloc_size = 0; 2529 if (loader.loaded_layer_lib_capacity == 0) 2530 new_alloc_size = 8 * sizeof(struct loader_lib_info); 2531 else if (loader.loaded_layer_lib_capacity <= loader.loaded_layer_lib_count * 2532 sizeof(struct loader_lib_info)) 2533 new_alloc_size = loader.loaded_layer_lib_capacity * 2; 2534 2535 if (new_alloc_size) { 2536 new_layer_lib_list = loader_heap_realloc( 2537 inst, loader.loaded_layer_lib_list, 2538 loader.loaded_layer_lib_capacity, 2539 new_alloc_size, 2540 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 2541 if (!new_layer_lib_list) { 2542 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "loader: realloc failed in loader_add_layer_lib"); 2543 return NULL; 2544 } 2545 loader.loaded_layer_lib_capacity = new_alloc_size; 2546 } else 2547 new_layer_lib_list = loader.loaded_layer_lib_list; 2548 my_lib = &new_layer_lib_list[loader.loaded_layer_lib_count]; 2549 2550 strncpy(my_lib->lib_name, layer_prop->lib_name, sizeof(my_lib->lib_name)); 2551 my_lib->lib_name[sizeof(my_lib->lib_name) - 1] = '\0'; 2552 my_lib->ref_count = 0; 2553 my_lib->lib_handle = NULL; 2554 2555 if ((my_lib->lib_handle = loader_platform_open_library(my_lib->lib_name)) == NULL) { 2556 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, 2557 loader_platform_open_library_error(my_lib->lib_name)); 2558 return NULL; 2559 } else { 2560 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, 2561 "Chain: %s: Loading layer library %s", 2562 chain_type, layer_prop->lib_name); 2563 } 2564 loader.loaded_layer_lib_count++; 2565 loader.loaded_layer_lib_list = new_layer_lib_list; 2566 my_lib->ref_count++; 2567 2568 return my_lib->lib_handle; 2569} 2570 2571static void loader_remove_layer_lib( 2572 struct loader_instance *inst, 2573 struct loader_layer_properties *layer_prop) 2574{ 2575 uint32_t idx; 2576 struct loader_lib_info *new_layer_lib_list, *my_lib = NULL; 2577 2578 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) { 2579 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, layer_prop->lib_name) == 0) { 2580 /* found matching library */ 2581 idx = i; 2582 my_lib = &loader.loaded_layer_lib_list[i]; 2583 break; 2584 } 2585 } 2586 2587 if (my_lib) { 2588 my_lib->ref_count--; 2589 if (my_lib->ref_count > 0) { 2590 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, 2591 "Decrement reference count for layer library %s", layer_prop->lib_name); 2592 return; 2593 } 2594 } 2595 loader_platform_close_library(my_lib->lib_handle); 2596 loader_log(VK_DBG_REPORT_DEBUG_BIT, 0, 2597 "Unloading layer library %s", layer_prop->lib_name); 2598 2599 /* Need to remove unused library from list */ 2600 new_layer_lib_list = loader_heap_alloc(inst, 2601 loader.loaded_layer_lib_capacity, 2602 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 2603 if (!new_layer_lib_list) { 2604 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "loader: heap alloc failed loader_remove_layer_library"); 2605 return; 2606 } 2607 2608 if (idx > 0) { 2609 /* Copy records before idx */ 2610 memcpy(new_layer_lib_list, &loader.loaded_layer_lib_list[0], 2611 sizeof(struct loader_lib_info) * idx); 2612 } 2613 if (idx < (loader.loaded_layer_lib_count - 1)) { 2614 /* Copy records after idx */ 2615 memcpy(&new_layer_lib_list[idx], &loader.loaded_layer_lib_list[idx+1], 2616 sizeof(struct loader_lib_info) * (loader.loaded_layer_lib_count - idx - 1)); 2617 } 2618 2619 loader_heap_free(inst, loader.loaded_layer_lib_list); 2620 loader.loaded_layer_lib_count--; 2621 loader.loaded_layer_lib_list = new_layer_lib_list; 2622} 2623 2624 2625/** 2626 * Go through the search_list and find any layers which match type. If layer 2627 * type match is found in then add it to ext_list. 2628 */ 2629//TODO need to handle implict layer enable env var and disable env var 2630static void loader_add_layer_implicit( 2631 const struct loader_instance *inst, 2632 const enum layer_type type, 2633 struct loader_layer_list *list, 2634 const struct loader_layer_list *search_list) 2635{ 2636 uint32_t i; 2637 for (i = 0; i < search_list->count; i++) { 2638 const struct loader_layer_properties *prop = &search_list->list[i]; 2639 if (prop->type & type) { 2640 /* Found an layer with the same type, add to layer_list */ 2641 loader_add_to_layer_list(inst, list, 1, prop); 2642 } 2643 } 2644 2645} 2646 2647/** 2648 * Get the layer name(s) from the env_name environment variable. If layer 2649 * is found in search_list then add it to layer_list. But only add it to 2650 * layer_list if type matches. 2651 */ 2652static void loader_add_layer_env( 2653 const struct loader_instance *inst, 2654 const enum layer_type type, 2655 const char *env_name, 2656 struct loader_layer_list *layer_list, 2657 const struct loader_layer_list *search_list) 2658{ 2659 char *layerEnv; 2660 char *next, *name; 2661 2662 layerEnv = getenv(env_name); 2663 if (layerEnv == NULL) { 2664 return; 2665 } 2666 name = loader_stack_alloc(strlen(layerEnv) + 1); 2667 if (name == NULL) { 2668 return; 2669 } 2670 strcpy(name, layerEnv); 2671 2672 while (name && *name ) { 2673 next = loader_get_next_path(name); 2674 loader_find_layer_name_add_list(inst, name, type, search_list, layer_list); 2675 name = next; 2676 } 2677 2678 return; 2679} 2680 2681void loader_deactivate_instance_layers(struct loader_instance *instance) 2682{ 2683 if (!instance->activated_layer_list.count) { 2684 return; 2685 } 2686 2687 /* Create instance chain of enabled layers */ 2688 for (uint32_t i = 0; i < instance->activated_layer_list.count; i++) { 2689 struct loader_layer_properties *layer_prop = &instance->activated_layer_list.list[i]; 2690 2691 loader_remove_layer_lib(instance, layer_prop); 2692 } 2693 loader_destroy_layer_list(instance, &instance->activated_layer_list); 2694} 2695 2696VkResult loader_enable_instance_layers( 2697 struct loader_instance *inst, 2698 const VkInstanceCreateInfo *pCreateInfo, 2699 const struct loader_layer_list *instance_layers) 2700{ 2701 VkResult err; 2702 2703 assert(inst && "Cannot have null instance"); 2704 2705 if (!loader_init_layer_list(inst, &inst->activated_layer_list)) { 2706 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc Instance activated layer list"); 2707 return VK_ERROR_OUT_OF_HOST_MEMORY; 2708 } 2709 2710 /* Add any implicit layers first */ 2711 loader_add_layer_implicit( 2712 inst, 2713 VK_LAYER_TYPE_INSTANCE_IMPLICIT, 2714 &inst->activated_layer_list, 2715 instance_layers); 2716 2717 /* Add any layers specified via environment variable next */ 2718 loader_add_layer_env( 2719 inst, 2720 VK_LAYER_TYPE_INSTANCE_EXPLICIT, 2721 "VK_INSTANCE_LAYERS", 2722 &inst->activated_layer_list, 2723 instance_layers); 2724 2725 /* Add layers specified by the application */ 2726 err = loader_add_layer_names_to_list( 2727 inst, 2728 &inst->activated_layer_list, 2729 pCreateInfo->enabledLayerNameCount, 2730 pCreateInfo->ppEnabledLayerNames, 2731 instance_layers); 2732 2733 return err; 2734} 2735 2736uint32_t loader_activate_instance_layers(struct loader_instance *inst) 2737{ 2738 uint32_t layer_idx; 2739 VkBaseLayerObject *wrappedInstance; 2740 2741 if (inst == NULL) { 2742 return 0; 2743 } 2744 2745 // NOTE inst is unwrapped at this point in time 2746 void* baseObj = (void*) inst; 2747 void* nextObj = (void*) inst; 2748 VkBaseLayerObject *nextInstObj; 2749 PFN_vkGetInstanceProcAddr nextGPA = loader_gpa_instance_internal; 2750 2751 if (!inst->activated_layer_list.count) { 2752 loader_init_instance_core_dispatch_table(inst->disp, nextGPA, (VkInstance) nextObj, (VkInstance) baseObj); 2753 return 0; 2754 } 2755 2756 wrappedInstance = loader_stack_alloc(sizeof(VkBaseLayerObject) 2757 * inst->activated_layer_list.count); 2758 if (!wrappedInstance) { 2759 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc Instance objects for layer"); 2760 return 0; 2761 } 2762 2763 /* Create instance chain of enabled layers */ 2764 layer_idx = inst->activated_layer_list.count - 1; 2765 for (int32_t i = inst->activated_layer_list.count - 1; i >= 0; i--) { 2766 struct loader_layer_properties *layer_prop = &inst->activated_layer_list.list[i]; 2767 loader_platform_dl_handle lib_handle; 2768 2769 /* 2770 * Note: An extension's Get*ProcAddr should not return a function pointer for 2771 * any extension entry points until the extension has been enabled. 2772 * To do this requires a different behavior from Get*ProcAddr functions implemented 2773 * in layers. 2774 * The very first call to a layer will be it's Get*ProcAddr function requesting 2775 * the layer's vkGet*ProcAddr. The layer should initialize its internal dispatch table 2776 * with the wrapped object given (either Instance or Device) and return the layer's 2777 * Get*ProcAddr function. The layer should also use this opportunity to record the 2778 * baseObject so that it can find the correct local dispatch table on future calls. 2779 * Subsequent calls to Get*ProcAddr, CreateInstance, CreateDevice 2780 * will not use a wrapped object and must look up their local dispatch table from 2781 * the given baseObject. 2782 */ 2783 nextInstObj = (wrappedInstance + layer_idx); 2784 nextInstObj->pGPA = (PFN_vkGPA) nextGPA; 2785 nextInstObj->baseObject = baseObj; 2786 nextInstObj->nextObject = nextObj; 2787 nextObj = (void*) nextInstObj; 2788 2789 lib_handle = loader_add_layer_lib(inst, "instance", layer_prop); 2790 if (!lib_handle) 2791 continue; // TODO what should we do in this case 2792 if ((nextGPA = layer_prop->functions.get_instance_proc_addr) == NULL) { 2793 if (layer_prop->functions.str_gipa == NULL || strlen(layer_prop->functions.str_gipa) == 0) { 2794 nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetInstanceProcAddr"); 2795 layer_prop->functions.get_instance_proc_addr = nextGPA; 2796 } else 2797 nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gipa); 2798 if (!nextGPA) { 2799 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to find vkGetInstanceProcAddr in layer %s", layer_prop->lib_name); 2800 2801 /* TODO: Should we return nextObj, nextGPA to previous? or decrement layer_list count*/ 2802 continue; 2803 } 2804 } 2805 2806 loader_log(VK_DBG_REPORT_INFO_BIT, 0, 2807 "Insert instance layer %s (%s)", 2808 layer_prop->info.layerName, 2809 layer_prop->lib_name); 2810 2811 layer_idx--; 2812 } 2813 2814 loader_init_instance_core_dispatch_table(inst->disp, nextGPA, (VkInstance) nextObj, (VkInstance) baseObj); 2815 2816 return inst->activated_layer_list.count; 2817} 2818 2819void loader_activate_instance_layer_extensions(struct loader_instance *inst) 2820{ 2821 2822 loader_init_instance_extension_dispatch_table(inst->disp, 2823 inst->disp->GetInstanceProcAddr, 2824 (VkInstance) inst); 2825} 2826 2827static VkResult loader_enable_device_layers( 2828 const struct loader_instance *inst, 2829 struct loader_icd *icd, 2830 struct loader_device *dev, 2831 const VkDeviceCreateInfo *pCreateInfo, 2832 const struct loader_layer_list *device_layers) 2833 2834{ 2835 VkResult err; 2836 2837 assert(dev && "Cannot have null device"); 2838 2839 if (dev->activated_layer_list.list == NULL || dev->activated_layer_list.capacity == 0) { 2840 loader_init_layer_list(inst, &dev->activated_layer_list); 2841 } 2842 2843 if (dev->activated_layer_list.list == NULL) { 2844 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc device activated layer list"); 2845 return VK_ERROR_OUT_OF_HOST_MEMORY; 2846 } 2847 2848 /* Add any implicit layers first */ 2849 loader_add_layer_implicit( 2850 inst, 2851 VK_LAYER_TYPE_DEVICE_IMPLICIT, 2852 &dev->activated_layer_list, 2853 device_layers); 2854 2855 /* Add any layers specified via environment variable next */ 2856 loader_add_layer_env( 2857 inst, 2858 VK_LAYER_TYPE_DEVICE_EXPLICIT, 2859 "VK_DEVICE_LAYERS", 2860 &dev->activated_layer_list, 2861 device_layers); 2862 2863 /* Add layers specified by the application */ 2864 err = loader_add_layer_names_to_list( 2865 inst, 2866 &dev->activated_layer_list, 2867 pCreateInfo->enabledLayerNameCount, 2868 pCreateInfo->ppEnabledLayerNames, 2869 device_layers); 2870 2871 return err; 2872} 2873 2874/* 2875 * This function terminates the device chain for CreateDevice. 2876 * CreateDevice is a special case and so the loader call's 2877 * the ICD's CreateDevice before creating the chain. Since 2878 * we can't call CreateDevice twice we must terminate the 2879 * device chain with something else. 2880 */ 2881static VKAPI_ATTR VkResult VKAPI_CALL scratch_vkCreateDevice( 2882 VkPhysicalDevice physicalDevice, 2883 const VkDeviceCreateInfo *pCreateInfo, 2884 const VkAllocationCallbacks* pAllocator, 2885 VkDevice *pDevice) 2886{ 2887 return VK_SUCCESS; 2888} 2889 2890static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL loader_GetDeviceChainProcAddr(VkDevice device, const char * name) 2891{ 2892 if (!strcmp(name, "vkGetDeviceProcAddr")) 2893 return (PFN_vkVoidFunction) loader_GetDeviceChainProcAddr; 2894 if (!strcmp(name, "vkCreateDevice")) 2895 return (PFN_vkVoidFunction) scratch_vkCreateDevice; 2896 2897 struct loader_device *found_dev; 2898 struct loader_icd *icd = loader_get_icd_and_device(device, &found_dev); 2899 return icd->GetDeviceProcAddr(device, name); 2900} 2901 2902static uint32_t loader_activate_device_layers( 2903 const struct loader_instance *inst, 2904 struct loader_device *dev, 2905 VkDevice device) 2906{ 2907 if (!dev) { 2908 return 0; 2909 } 2910 2911 /* activate any layer libraries */ 2912 void* nextObj = (void*) device; 2913 void* baseObj = nextObj; 2914 VkBaseLayerObject *nextGpuObj; 2915 PFN_vkGetDeviceProcAddr nextGPA = loader_GetDeviceChainProcAddr; 2916 VkBaseLayerObject *wrappedGpus; 2917 2918 if (!dev->activated_layer_list.count) { 2919 loader_init_device_dispatch_table(&dev->loader_dispatch, nextGPA, 2920 (VkDevice) nextObj, (VkDevice) baseObj); 2921 return 0; 2922 } 2923 2924 wrappedGpus = loader_heap_alloc(inst, 2925 sizeof (VkBaseLayerObject) * dev->activated_layer_list.count, 2926 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 2927 if (!wrappedGpus) { 2928 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to alloc Gpu objects for layer"); 2929 return 0; 2930 } 2931 2932 for (int32_t i = dev->activated_layer_list.count - 1; i >= 0; i--) { 2933 2934 struct loader_layer_properties *layer_prop = &dev->activated_layer_list.list[i]; 2935 loader_platform_dl_handle lib_handle; 2936 2937 nextGpuObj = (wrappedGpus + i); 2938 nextGpuObj->pGPA = (PFN_vkGPA)nextGPA; 2939 nextGpuObj->baseObject = baseObj; 2940 nextGpuObj->nextObject = nextObj; 2941 nextObj = (void*) nextGpuObj; 2942 2943 lib_handle = loader_add_layer_lib(inst, "device", layer_prop); 2944 if ((nextGPA = layer_prop->functions.get_device_proc_addr) == NULL) { 2945 if (layer_prop->functions.str_gdpa == NULL || strlen(layer_prop->functions.str_gdpa) == 0) { 2946 nextGPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, "vkGetDeviceProcAddr"); 2947 layer_prop->functions.get_device_proc_addr = nextGPA; 2948 } else 2949 nextGPA = (PFN_vkGetDeviceProcAddr) loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gdpa); 2950 if (!nextGPA) { 2951 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, "Failed to find vkGetDeviceProcAddr in layer %s", layer_prop->lib_name); 2952 continue; 2953 } 2954 } 2955 2956 loader_log(VK_DBG_REPORT_INFO_BIT, 0, 2957 "Insert device layer library %s (%s)", 2958 layer_prop->info.layerName, 2959 layer_prop->lib_name); 2960 2961 } 2962 2963 loader_init_device_dispatch_table(&dev->loader_dispatch, nextGPA, 2964 (VkDevice) nextObj, (VkDevice) baseObj); 2965 loader_heap_free(inst, wrappedGpus); 2966 2967 return dev->activated_layer_list.count; 2968} 2969 2970VkResult loader_validate_layers( 2971 const uint32_t layer_count, 2972 const char * const *ppEnabledLayerNames, 2973 const struct loader_layer_list *list) 2974{ 2975 struct loader_layer_properties *prop; 2976 2977 for (uint32_t i = 0; i < layer_count; i++) { 2978 prop = loader_get_layer_property(ppEnabledLayerNames[i], 2979 list); 2980 if (!prop) { 2981 return VK_ERROR_LAYER_NOT_PRESENT; 2982 } 2983 } 2984 2985 return VK_SUCCESS; 2986} 2987 2988VkResult loader_validate_instance_extensions( 2989 const struct loader_extension_list *icd_exts, 2990 const struct loader_layer_list *instance_layer, 2991 const VkInstanceCreateInfo *pCreateInfo) 2992{ 2993 VkExtensionProperties *extension_prop; 2994 struct loader_layer_properties *layer_prop; 2995 2996 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) { 2997 extension_prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i], 2998 icd_exts); 2999 3000 if (extension_prop) { 3001 continue; 3002 } 3003 3004 extension_prop = NULL; 3005 3006 /* Not in global list, search layer extension lists */ 3007 for (uint32_t j = 0; j < pCreateInfo->enabledLayerNameCount; j++) { 3008 layer_prop = loader_get_layer_property(pCreateInfo->ppEnabledLayerNames[i], 3009 instance_layer); 3010 if (!layer_prop) { 3011 /* Should NOT get here, loader_validate_layers 3012 * should have already filtered this case out. 3013 */ 3014 continue; 3015 } 3016 3017 extension_prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i], 3018 &layer_prop->instance_extension_list); 3019 if (extension_prop) { 3020 /* Found the extension in one of the layers enabled by the app. */ 3021 break; 3022 } 3023 } 3024 3025 if (!extension_prop) { 3026 /* Didn't find extension name in any of the global layers, error out */ 3027 return VK_ERROR_EXTENSION_NOT_PRESENT; 3028 } 3029 } 3030 return VK_SUCCESS; 3031} 3032 3033VkResult loader_validate_device_extensions( 3034 struct loader_physical_device *phys_dev, 3035 const struct loader_layer_list *device_layer, 3036 const VkDeviceCreateInfo *pCreateInfo) 3037{ 3038 VkExtensionProperties *extension_prop; 3039 struct loader_layer_properties *layer_prop; 3040 3041 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) { 3042 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i]; 3043 extension_prop = get_extension_property(extension_name, 3044 &phys_dev->device_extension_cache); 3045 3046 if (extension_prop) { 3047 continue; 3048 } 3049 3050 /* Not in global list, search layer extension lists */ 3051 for (uint32_t j = 0; j < pCreateInfo->enabledLayerNameCount; j++) { 3052 const char *layer_name = pCreateInfo->ppEnabledLayerNames[j]; 3053 layer_prop = loader_get_layer_property(layer_name, 3054 device_layer); 3055 3056 if (!layer_prop) { 3057 /* Should NOT get here, loader_validate_instance_layers 3058 * should have already filtered this case out. 3059 */ 3060 continue; 3061 } 3062 3063 extension_prop = get_dev_extension_property(extension_name, 3064 &layer_prop->device_extension_list); 3065 if (extension_prop) { 3066 /* Found the extension in one of the layers enabled by the app. */ 3067 break; 3068 } 3069 } 3070 3071 if (!extension_prop) { 3072 /* Didn't find extension name in any of the device layers, error out */ 3073 return VK_ERROR_EXTENSION_NOT_PRESENT; 3074 } 3075 } 3076 return VK_SUCCESS; 3077} 3078 3079VKAPI_ATTR VkResult VKAPI_CALL loader_CreateInstance( 3080 const VkInstanceCreateInfo* pCreateInfo, 3081 const VkAllocationCallbacks* pAllocator, 3082 VkInstance* pInstance) 3083{ 3084 struct loader_instance *ptr_instance = *(struct loader_instance **) pInstance; 3085 struct loader_icd *icd; 3086 VkExtensionProperties *prop; 3087 char **filtered_extension_names = NULL; 3088 VkInstanceCreateInfo icd_create_info; 3089 VkResult res = VK_SUCCESS; 3090 bool success = false; 3091 3092 memcpy(&icd_create_info, pCreateInfo, sizeof(icd_create_info)); 3093 3094 icd_create_info.enabledLayerNameCount = 0; 3095 icd_create_info.ppEnabledLayerNames = NULL; 3096 3097 /* 3098 * NOTE: Need to filter the extensions to only those 3099 * supported by the ICD. 3100 * No ICD will advertise support for layers. An ICD 3101 * library could support a layer, but it would be 3102 * independent of the actual ICD, just in the same library. 3103 */ 3104 filtered_extension_names = loader_stack_alloc(pCreateInfo->enabledExtensionNameCount * sizeof(char *)); 3105 if (!filtered_extension_names) { 3106 return VK_ERROR_OUT_OF_HOST_MEMORY; 3107 } 3108 icd_create_info.ppEnabledExtensionNames = (const char * const *) filtered_extension_names; 3109 3110 for (uint32_t i = 0; i < ptr_instance->icd_libs.count; i++) { 3111 icd = loader_icd_add(ptr_instance, &ptr_instance->icd_libs.list[i]); 3112 if (icd) { 3113 icd_create_info.enabledExtensionNameCount = 0; 3114 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) { 3115 prop = get_extension_property(pCreateInfo->ppEnabledExtensionNames[i], 3116 &ptr_instance->ext_list); 3117 if (prop) { 3118 filtered_extension_names[icd_create_info.enabledExtensionNameCount] = (char *) pCreateInfo->ppEnabledExtensionNames[i]; 3119 icd_create_info.enabledExtensionNameCount++; 3120 } 3121 } 3122 3123 res = ptr_instance->icd_libs.list[i].CreateInstance(&icd_create_info, 3124 pAllocator, 3125 &(icd->instance)); 3126 if (res == VK_SUCCESS) 3127 success = loader_icd_init_entrys( 3128 icd, 3129 icd->instance, 3130 ptr_instance->icd_libs.list[i].GetInstanceProcAddr); 3131 3132 if (res != VK_SUCCESS || !success) 3133 { 3134 ptr_instance->icds = ptr_instance->icds->next; 3135 loader_icd_destroy(ptr_instance, icd); 3136 icd->instance = VK_NULL_HANDLE; 3137 loader_log(VK_DBG_REPORT_ERROR_BIT, 0, 3138 "ICD ignored: failed to CreateInstance and find entrypoints with ICD"); 3139 } 3140 } 3141 } 3142 3143 /* 3144 * If no ICDs were added to instance list and res is unchanged 3145 * from it's initial value, the loader was unable to find 3146 * a suitable ICD. 3147 */ 3148 if (ptr_instance->icds == NULL) { 3149 if (res == VK_SUCCESS) { 3150 return VK_ERROR_INCOMPATIBLE_DRIVER; 3151 } else { 3152 return res; 3153 } 3154 } 3155 3156 return VK_SUCCESS; 3157} 3158 3159VKAPI_ATTR void VKAPI_CALL loader_DestroyInstance( 3160 VkInstance instance, 3161 const VkAllocationCallbacks* pAllocator) 3162{ 3163 struct loader_instance *ptr_instance = loader_instance(instance); 3164 struct loader_icd *icds = ptr_instance->icds; 3165 struct loader_icd *next_icd; 3166 3167 // Remove this instance from the list of instances: 3168 struct loader_instance *prev = NULL; 3169 struct loader_instance *next = loader.instances; 3170 while (next != NULL) { 3171 if (next == ptr_instance) { 3172 // Remove this instance from the list: 3173 if (prev) 3174 prev->next = next->next; 3175 else 3176 loader.instances = next->next; 3177 break; 3178 } 3179 prev = next; 3180 next = next->next; 3181 } 3182 3183 while (icds) { 3184 if (icds->instance) { 3185 icds->DestroyInstance(icds->instance, pAllocator); 3186 } 3187 next_icd = icds->next; 3188 icds->instance = VK_NULL_HANDLE; 3189 loader_icd_destroy(ptr_instance, icds); 3190 3191 icds = next_icd; 3192 } 3193 loader_delete_layer_properties(ptr_instance, &ptr_instance->device_layer_list); 3194 loader_delete_layer_properties(ptr_instance, &ptr_instance->instance_layer_list); 3195 loader_scanned_icd_clear(ptr_instance, &ptr_instance->icd_libs); 3196 loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *) 3197 &ptr_instance->ext_list); 3198 for (uint32_t i = 0; i < ptr_instance->total_gpu_count; i++) 3199 loader_destroy_generic_list(ptr_instance, (struct loader_generic_list *) 3200 &ptr_instance->phys_devs[i].device_extension_cache); 3201 loader_heap_free(ptr_instance, ptr_instance->phys_devs); 3202 loader_free_dev_ext_table(ptr_instance); 3203} 3204 3205VkResult loader_init_physical_device_info(struct loader_instance *ptr_instance) 3206{ 3207 struct loader_icd *icd; 3208 uint32_t i, j, idx, count = 0; 3209 VkResult res; 3210 struct loader_phys_dev_per_icd *phys_devs; 3211 3212 ptr_instance->total_gpu_count = 0; 3213 phys_devs = (struct loader_phys_dev_per_icd *) loader_stack_alloc( 3214 sizeof(struct loader_phys_dev_per_icd) * 3215 ptr_instance->total_icd_count); 3216 if (!phys_devs) 3217 return VK_ERROR_OUT_OF_HOST_MEMORY; 3218 3219 icd = ptr_instance->icds; 3220 for (i = 0; i < ptr_instance->total_icd_count; i++) { 3221 assert(icd); 3222 res = icd->EnumeratePhysicalDevices(icd->instance, &phys_devs[i].count, NULL); 3223 if (res != VK_SUCCESS) 3224 return res; 3225 count += phys_devs[i].count; 3226 icd = icd->next; 3227 } 3228 3229 ptr_instance->phys_devs = (struct loader_physical_device *) loader_heap_alloc( 3230 ptr_instance, 3231 count * sizeof(struct loader_physical_device), 3232 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 3233 if (!ptr_instance->phys_devs) 3234 return VK_ERROR_OUT_OF_HOST_MEMORY; 3235 3236 icd = ptr_instance->icds; 3237 3238 struct loader_physical_device *inst_phys_devs = ptr_instance->phys_devs; 3239 idx = 0; 3240 for (i = 0; i < ptr_instance->total_icd_count; i++) { 3241 assert(icd); 3242 3243 phys_devs[i].phys_devs = (VkPhysicalDevice *) loader_stack_alloc( 3244 phys_devs[i].count * sizeof(VkPhysicalDevice)); 3245 if (!phys_devs[i].phys_devs) { 3246 loader_heap_free(ptr_instance, ptr_instance->phys_devs); 3247 ptr_instance->phys_devs = NULL; 3248 return VK_ERROR_OUT_OF_HOST_MEMORY; 3249 } 3250 res = icd->EnumeratePhysicalDevices( 3251 icd->instance, 3252 &(phys_devs[i].count), 3253 phys_devs[i].phys_devs); 3254 if ((res == VK_SUCCESS)) { 3255 ptr_instance->total_gpu_count += phys_devs[i].count; 3256 for (j = 0; j < phys_devs[i].count; j++) { 3257 3258 // initialize the loader's physicalDevice object 3259 loader_set_dispatch((void *) &inst_phys_devs[idx], ptr_instance->disp); 3260 inst_phys_devs[idx].this_instance = ptr_instance; 3261 inst_phys_devs[idx].this_icd = icd; 3262 inst_phys_devs[idx].phys_dev = phys_devs[i].phys_devs[j]; 3263 memset(&inst_phys_devs[idx].device_extension_cache, 0, sizeof(struct loader_extension_list)); 3264 3265 idx++; 3266 } 3267 } else { 3268 loader_heap_free(ptr_instance, ptr_instance->phys_devs); 3269 ptr_instance->phys_devs = NULL; 3270 return res; 3271 } 3272 3273 icd = icd->next; 3274 } 3275 3276 return VK_SUCCESS; 3277} 3278 3279VKAPI_ATTR VkResult VKAPI_CALL loader_EnumeratePhysicalDevices( 3280 VkInstance instance, 3281 uint32_t* pPhysicalDeviceCount, 3282 VkPhysicalDevice* pPhysicalDevices) 3283{ 3284 uint32_t i; 3285 struct loader_instance *ptr_instance = (struct loader_instance *) instance; 3286 VkResult res = VK_SUCCESS; 3287 3288 if (ptr_instance->total_gpu_count == 0) { 3289 res = loader_init_physical_device_info(ptr_instance); 3290 } 3291 3292 *pPhysicalDeviceCount = ptr_instance->total_gpu_count; 3293 if (!pPhysicalDevices) { 3294 return res; 3295 } 3296 3297 for (i = 0; i < ptr_instance->total_gpu_count; i++) { 3298 pPhysicalDevices[i] = (VkPhysicalDevice) &ptr_instance->phys_devs[i]; 3299 } 3300 3301 return res; 3302} 3303 3304VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceProperties( 3305 VkPhysicalDevice physicalDevice, 3306 VkPhysicalDeviceProperties* pProperties) 3307{ 3308 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice; 3309 struct loader_icd *icd = phys_dev->this_icd; 3310 3311 if (icd->GetPhysicalDeviceProperties) 3312 icd->GetPhysicalDeviceProperties(phys_dev->phys_dev, pProperties); 3313} 3314 3315VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceQueueFamilyProperties ( 3316 VkPhysicalDevice physicalDevice, 3317 uint32_t* pQueueFamilyPropertyCount, 3318 VkQueueFamilyProperties* pProperties) 3319{ 3320 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice; 3321 struct loader_icd *icd = phys_dev->this_icd; 3322 3323 if (icd->GetPhysicalDeviceQueueFamilyProperties) 3324 icd->GetPhysicalDeviceQueueFamilyProperties(phys_dev->phys_dev, pQueueFamilyPropertyCount, pProperties); 3325} 3326 3327VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceMemoryProperties ( 3328 VkPhysicalDevice physicalDevice, 3329 VkPhysicalDeviceMemoryProperties* pProperties) 3330{ 3331 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice; 3332 struct loader_icd *icd = phys_dev->this_icd; 3333 3334 if (icd->GetPhysicalDeviceMemoryProperties) 3335 icd->GetPhysicalDeviceMemoryProperties(phys_dev->phys_dev, pProperties); 3336} 3337 3338VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceFeatures( 3339 VkPhysicalDevice physicalDevice, 3340 VkPhysicalDeviceFeatures* pFeatures) 3341{ 3342 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice; 3343 struct loader_icd *icd = phys_dev->this_icd; 3344 3345 if (icd->GetPhysicalDeviceFeatures) 3346 icd->GetPhysicalDeviceFeatures(phys_dev->phys_dev, pFeatures); 3347} 3348 3349VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceFormatProperties( 3350 VkPhysicalDevice physicalDevice, 3351 VkFormat format, 3352 VkFormatProperties* pFormatInfo) 3353{ 3354 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice; 3355 struct loader_icd *icd = phys_dev->this_icd; 3356 3357 if (icd->GetPhysicalDeviceFormatProperties) 3358 icd->GetPhysicalDeviceFormatProperties(phys_dev->phys_dev, format, pFormatInfo); 3359} 3360 3361VKAPI_ATTR VkResult VKAPI_CALL loader_GetPhysicalDeviceImageFormatProperties( 3362 VkPhysicalDevice physicalDevice, 3363 VkFormat format, 3364 VkImageType type, 3365 VkImageTiling tiling, 3366 VkImageUsageFlags usage, 3367 VkImageCreateFlags flags, 3368 VkImageFormatProperties* pImageFormatProperties) 3369{ 3370 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice; 3371 struct loader_icd *icd = phys_dev->this_icd; 3372 3373 if (!icd->GetPhysicalDeviceImageFormatProperties) 3374 return VK_ERROR_INITIALIZATION_FAILED; 3375 3376 return icd->GetPhysicalDeviceImageFormatProperties(phys_dev->phys_dev, format, 3377 type, tiling, usage, flags, pImageFormatProperties); 3378} 3379 3380VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceSparseImageFormatProperties( 3381 VkPhysicalDevice physicalDevice, 3382 VkFormat format, 3383 VkImageType type, 3384 VkSampleCountFlagBits samples, 3385 VkImageUsageFlags usage, 3386 VkImageTiling tiling, 3387 uint32_t* pNumProperties, 3388 VkSparseImageFormatProperties* pProperties) 3389{ 3390 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice; 3391 struct loader_icd *icd = phys_dev->this_icd; 3392 3393 if (icd->GetPhysicalDeviceSparseImageFormatProperties) 3394 icd->GetPhysicalDeviceSparseImageFormatProperties(phys_dev->phys_dev, format, type, samples, usage, tiling, pNumProperties, pProperties); 3395} 3396 3397VKAPI_ATTR VkResult VKAPI_CALL loader_CreateDevice( 3398 VkPhysicalDevice physicalDevice, 3399 const VkDeviceCreateInfo* pCreateInfo, 3400 const VkAllocationCallbacks* pAllocator, 3401 VkDevice* pDevice) 3402{ 3403 struct loader_physical_device *phys_dev; 3404 struct loader_icd *icd; 3405 struct loader_device *dev; 3406 struct loader_instance *inst; 3407 VkDeviceCreateInfo device_create_info; 3408 char **filtered_extension_names = NULL; 3409 VkResult res; 3410 3411 assert(pCreateInfo->queueCreateInfoCount >= 1); 3412 3413 //TODO this only works for one physical device per instance 3414 // once CreateDevice layer bootstrapping is done via DeviceCreateInfo 3415 // hopefully don't need this anymore in trampoline code 3416 phys_dev = loader_get_physical_device(physicalDevice); 3417 icd = phys_dev->this_icd; 3418 if (!icd) 3419 return VK_ERROR_INITIALIZATION_FAILED; 3420 3421 inst = phys_dev->this_instance; 3422 3423 if (!icd->CreateDevice) { 3424 return VK_ERROR_INITIALIZATION_FAILED; 3425 } 3426 3427 /* validate any app enabled layers are available */ 3428 if (pCreateInfo->enabledLayerNameCount > 0) { 3429 res = loader_validate_layers(pCreateInfo->enabledLayerNameCount, 3430 pCreateInfo->ppEnabledLayerNames, 3431 &inst->device_layer_list); 3432 if (res != VK_SUCCESS) { 3433 return res; 3434 } 3435 } 3436 3437 /* Get the physical device extensions if they haven't been retrieved yet */ 3438 if (phys_dev->device_extension_cache.capacity == 0) { 3439 if (!loader_init_generic_list(inst, (struct loader_generic_list *) 3440 &phys_dev->device_extension_cache, 3441 sizeof(VkExtensionProperties))) { 3442 return VK_ERROR_OUT_OF_HOST_MEMORY; 3443 } 3444 res = loader_add_physical_device_extensions( 3445 inst, physicalDevice, 3446 phys_dev->this_icd->this_icd_lib->lib_name, 3447 &phys_dev->device_extension_cache); 3448 if (res != VK_SUCCESS) { 3449 return res; 3450 } 3451 } 3452 /* make sure requested extensions to be enabled are supported */ 3453 res = loader_validate_device_extensions(phys_dev, &inst->device_layer_list, pCreateInfo); 3454 if (res != VK_SUCCESS) { 3455 return res; 3456 } 3457 3458 /* 3459 * NOTE: Need to filter the extensions to only those 3460 * supported by the ICD. 3461 * No ICD will advertise support for layers. An ICD 3462 * library could support a layer, but it would be 3463 * independent of the actual ICD, just in the same library. 3464 */ 3465 filtered_extension_names = loader_stack_alloc(pCreateInfo->enabledExtensionNameCount * sizeof(char *)); 3466 if (!filtered_extension_names) { 3467 return VK_ERROR_OUT_OF_HOST_MEMORY; 3468 } 3469 3470 /* Copy user's data */ 3471 memcpy(&device_create_info, pCreateInfo, sizeof(VkDeviceCreateInfo)); 3472 3473 /* ICD's do not use layers */ 3474 device_create_info.enabledLayerNameCount = 0; 3475 device_create_info.ppEnabledLayerNames = NULL; 3476 3477 device_create_info.enabledExtensionNameCount = 0; 3478 device_create_info.ppEnabledExtensionNames = (const char * const *) filtered_extension_names; 3479 3480 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) { 3481 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i]; 3482 VkExtensionProperties *prop = get_extension_property(extension_name, 3483 &phys_dev->device_extension_cache); 3484 if (prop) { 3485 filtered_extension_names[device_create_info.enabledExtensionNameCount] = (char *) extension_name; 3486 device_create_info.enabledExtensionNameCount++; 3487 } 3488 } 3489 3490 // since physicalDevice object maybe wrapped by a layer need to get unwrapped version 3491 // we haven't yet called down the chain for the layer to unwrap the object 3492 res = icd->CreateDevice(phys_dev->phys_dev, pCreateInfo, pAllocator, pDevice); 3493 if (res != VK_SUCCESS) { 3494 return res; 3495 } 3496 3497 dev = loader_add_logical_device(inst, *pDevice, &icd->logical_device_list); 3498 if (dev == NULL) { 3499 return VK_ERROR_OUT_OF_HOST_MEMORY; 3500 } 3501 3502 loader_init_dispatch(*pDevice, &dev->loader_dispatch); 3503 3504 /* activate any layers on device chain which terminates with device*/ 3505 res = loader_enable_device_layers(inst, icd, dev, pCreateInfo, &inst->device_layer_list); 3506 if (res != VK_SUCCESS) { 3507 loader_destroy_logical_device(inst, dev); 3508 return res; 3509 } 3510 loader_activate_device_layers(inst, dev, *pDevice); 3511 3512 /* finally can call down the chain */ 3513 res = dev->loader_dispatch.core_dispatch.CreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice); 3514 3515 /* initialize any device extension dispatch entry's from the instance list*/ 3516 loader_init_dispatch_dev_ext(inst, dev); 3517 3518 /* initialize WSI device extensions as part of core dispatch since loader has 3519 * dedicated trampoline code for these*/ 3520 loader_init_device_extension_dispatch_table(&dev->loader_dispatch, 3521 dev->loader_dispatch.core_dispatch.GetDeviceProcAddr, 3522 *pDevice); 3523 dev->loader_dispatch.core_dispatch.CreateDevice = icd->CreateDevice; 3524 3525 return res; 3526} 3527 3528/** 3529 * Get an instance level or global level entry point address. 3530 * @param instance 3531 * @param pName 3532 * @return 3533 * If instance == NULL returns a global level functions only 3534 * If instance is valid returns a trampoline entry point for all dispatchable Vulkan 3535 * functions both core and extensions. 3536 */ 3537LOADER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char * pName) 3538{ 3539 3540 void *addr; 3541 3542 addr = globalGetProcAddr(pName); 3543 if (instance == VK_NULL_HANDLE) { 3544 // get entrypoint addresses that are global (no dispatchable object) 3545 3546 return addr; 3547 } else { 3548 // if a global entrypoint return NULL 3549 if (addr) 3550 return NULL; 3551 } 3552 3553 struct loader_instance *ptr_instance = loader_get_instance(instance); 3554 if (ptr_instance == NULL) 3555 return NULL; 3556 // Return trampoline code for non-global entrypoints including any extensions. 3557 // Device extensions are returned if a layer or ICD supports the extension. 3558 // Instance extensions are returned if the extension is enabled and the loader 3559 // or someone else supports the extension 3560 return trampolineGetProcAddr(ptr_instance, pName); 3561 3562} 3563 3564/** 3565 * Get a device level or global level entry point address. 3566 * @param device 3567 * @param pName 3568 * @return 3569 * If device is valid, returns a device relative entry point for device level 3570 * entry points both core and extensions. 3571 * Device relative means call down the device chain. 3572 */ 3573LOADER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char * pName) 3574{ 3575 void *addr; 3576 3577 /* for entrypoints that loader must handle (ie non-dispatchable or create object) 3578 make sure the loader entrypoint is returned */ 3579 addr = loader_non_passthrough_gdpa(pName); 3580 if (addr) { 3581 return addr; 3582 } 3583 3584 /* Although CreateDevice is on device chain it's dispatchable object isn't 3585 * a VkDevice or child of VkDevice so return NULL. 3586 */ 3587 if (!strcmp(pName, "CreateDevice")) 3588 return NULL; 3589 3590 /* return the dispatch table entrypoint for the fastest case */ 3591 const VkLayerDispatchTable *disp_table = * (VkLayerDispatchTable **) device; 3592 if (disp_table == NULL) 3593 return NULL; 3594 3595 addr = loader_lookup_device_dispatch_table(disp_table, pName); 3596 if (addr) 3597 return addr; 3598 3599 if (disp_table->GetDeviceProcAddr == NULL) 3600 return NULL; 3601 return disp_table->GetDeviceProcAddr(device, pName); 3602} 3603 3604LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties( 3605 const char* pLayerName, 3606 uint32_t* pPropertyCount, 3607 VkExtensionProperties* pProperties) 3608{ 3609 struct loader_extension_list *global_ext_list=NULL; 3610 struct loader_layer_list instance_layers; 3611 struct loader_extension_list icd_extensions; 3612 struct loader_icd_libs icd_libs; 3613 uint32_t copy_size; 3614 3615 tls_instance = NULL; 3616 memset(&icd_extensions, 0, sizeof(icd_extensions)); 3617 memset(&instance_layers, 0, sizeof(instance_layers)); 3618 loader_platform_thread_once(&once_init, loader_initialize); 3619 3620 /* get layer libraries if needed */ 3621 if (pLayerName && strlen(pLayerName) != 0) { 3622 loader_layer_scan(NULL, &instance_layers, NULL); 3623 for (uint32_t i = 0; i < instance_layers.count; i++) { 3624 struct loader_layer_properties *props = &instance_layers.list[i]; 3625 if (strcmp(props->info.layerName, pLayerName) == 0) { 3626 global_ext_list = &props->instance_extension_list; 3627 } 3628 } 3629 } 3630 else { 3631 /* Scan/discover all ICD libraries */ 3632 memset(&icd_libs, 0 , sizeof(struct loader_icd_libs)); 3633 loader_icd_scan(NULL, &icd_libs); 3634 /* get extensions from all ICD's, merge so no duplicates */ 3635 loader_get_icd_loader_instance_extensions(NULL, &icd_libs, &icd_extensions); 3636 loader_scanned_icd_clear(NULL, &icd_libs); 3637 global_ext_list = &icd_extensions; 3638 } 3639 3640 if (global_ext_list == NULL) { 3641 loader_destroy_layer_list(NULL, &instance_layers); 3642 return VK_ERROR_LAYER_NOT_PRESENT; 3643 } 3644 3645 if (pProperties == NULL) { 3646 *pPropertyCount = global_ext_list->count; 3647 loader_destroy_layer_list(NULL, &instance_layers); 3648 loader_destroy_generic_list(NULL, (struct loader_generic_list *) 3649 &icd_extensions); 3650 return VK_SUCCESS; 3651 } 3652 3653 copy_size = *pPropertyCount < global_ext_list->count ? *pPropertyCount : global_ext_list->count; 3654 for (uint32_t i = 0; i < copy_size; i++) { 3655 memcpy(&pProperties[i], 3656 &global_ext_list->list[i], 3657 sizeof(VkExtensionProperties)); 3658 } 3659 *pPropertyCount = copy_size; 3660 loader_destroy_generic_list(NULL, (struct loader_generic_list *) 3661 &icd_extensions); 3662 3663 if (copy_size < global_ext_list->count) { 3664 loader_destroy_layer_list(NULL, &instance_layers); 3665 return VK_INCOMPLETE; 3666 } 3667 3668 loader_destroy_layer_list(NULL, &instance_layers); 3669 return VK_SUCCESS; 3670} 3671 3672LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties( 3673 uint32_t* pPropertyCount, 3674 VkLayerProperties* pProperties) 3675{ 3676 3677 struct loader_layer_list instance_layer_list; 3678 tls_instance = NULL; 3679 3680 loader_platform_thread_once(&once_init, loader_initialize); 3681 3682 uint32_t copy_size; 3683 3684 /* get layer libraries */ 3685 memset(&instance_layer_list, 0, sizeof(instance_layer_list)); 3686 loader_layer_scan(NULL, &instance_layer_list, NULL); 3687 3688 if (pProperties == NULL) { 3689 *pPropertyCount = instance_layer_list.count; 3690 loader_destroy_layer_list(NULL, &instance_layer_list); 3691 return VK_SUCCESS; 3692 } 3693 3694 copy_size = (*pPropertyCount < instance_layer_list.count) ? *pPropertyCount : instance_layer_list.count; 3695 for (uint32_t i = 0; i < copy_size; i++) { 3696 memcpy(&pProperties[i], &instance_layer_list.list[i].info, sizeof(VkLayerProperties)); 3697 } 3698 *pPropertyCount = copy_size; 3699 loader_destroy_layer_list(NULL, &instance_layer_list); 3700 3701 if (copy_size < instance_layer_list.count) { 3702 return VK_INCOMPLETE; 3703 } 3704 3705 return VK_SUCCESS; 3706} 3707 3708VKAPI_ATTR VkResult VKAPI_CALL loader_EnumerateDeviceExtensionProperties( 3709 VkPhysicalDevice physicalDevice, 3710 const char* pLayerName, 3711 uint32_t* pPropertyCount, 3712 VkExtensionProperties* pProperties) 3713{ 3714 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice; 3715 uint32_t copy_size; 3716 3717 uint32_t count; 3718 struct loader_device_extension_list *dev_ext_list=NULL; 3719 3720 /* get layer libraries if needed */ 3721 if (pLayerName && strlen(pLayerName) != 0) { 3722 for (uint32_t i = 0; i < phys_dev->this_instance->device_layer_list.count; i++) { 3723 struct loader_layer_properties *props = &phys_dev->this_instance->device_layer_list.list[i]; 3724 if (strcmp(props->info.layerName, pLayerName) == 0) { 3725 dev_ext_list = &props->device_extension_list; 3726 } 3727 } 3728 } 3729 else { 3730 /* this case is during the call down the instance chain */ 3731 struct loader_icd *icd = phys_dev->this_icd; 3732 VkResult res; 3733 res = icd->EnumerateDeviceExtensionProperties(phys_dev->phys_dev, NULL, pPropertyCount, pProperties); 3734 if (pProperties != NULL && res == VK_SUCCESS) { 3735 /* initialize dev_extension list within the physicalDevice object */ 3736 res = loader_init_physical_device_extensions(phys_dev->this_instance, 3737 phys_dev, *pPropertyCount, pProperties, 3738 &phys_dev->device_extension_cache); 3739 } 3740 return res; 3741 } 3742 3743 count = (dev_ext_list == NULL) ? 0: dev_ext_list->count; 3744 if (pProperties == NULL) { 3745 *pPropertyCount = count; 3746 return VK_SUCCESS; 3747 } 3748 3749 copy_size = *pPropertyCount < count ? *pPropertyCount : count; 3750 for (uint32_t i = 0; i < copy_size; i++) { 3751 memcpy(&pProperties[i], 3752 &dev_ext_list->list[i].props, 3753 sizeof(VkExtensionProperties)); 3754 } 3755 *pPropertyCount = copy_size; 3756 3757 if (copy_size < count) { 3758 return VK_INCOMPLETE; 3759 } 3760 3761 return VK_SUCCESS; 3762} 3763 3764VKAPI_ATTR VkResult VKAPI_CALL loader_EnumerateDeviceLayerProperties( 3765 VkPhysicalDevice physicalDevice, 3766 uint32_t* pPropertyCount, 3767 VkLayerProperties* pProperties) 3768{ 3769 uint32_t copy_size; 3770 struct loader_physical_device *phys_dev = (struct loader_physical_device *) physicalDevice; 3771 3772 uint32_t count = phys_dev->this_instance->device_layer_list.count; 3773 3774 if (pProperties == NULL) { 3775 *pPropertyCount = count; 3776 return VK_SUCCESS; 3777 } 3778 3779 copy_size = (*pPropertyCount < count) ? *pPropertyCount : count; 3780 for (uint32_t i = 0; i < copy_size; i++) { 3781 memcpy(&pProperties[i], &(phys_dev->this_instance->device_layer_list.list[i].info), sizeof(VkLayerProperties)); 3782 } 3783 *pPropertyCount = copy_size; 3784 3785 if (copy_size < count) { 3786 return VK_INCOMPLETE; 3787 } 3788 3789 return VK_SUCCESS; 3790} 3791