loader.c revision 5c13d4d87fd0356003a3441e887a172b991e880f
10fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod/* 20fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * 30fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * Copyright (c) 2014-2016 The Khronos Group Inc. 40fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * Copyright (c) 2014-2016 Valve Corporation 50fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * Copyright (c) 2014-2016 LunarG, Inc. 60fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * Copyright (C) 2015 Google Inc. 70fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * 80fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * Permission is hereby granted, free of charge, to any person obtaining a copy 90fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * of this software and/or associated documentation files (the "Materials"), to 100fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * deal in the Materials without restriction, including without limitation the 110fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 120fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * sell copies of the Materials, and to permit persons to whom the Materials are 130fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * furnished to do so, subject to the following conditions: 140fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * 150fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * The above copyright notice(s) and this permission notice shall be included in 160fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * all copies or substantial portions of the Materials. 170fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * 180fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 190fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 200fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 210fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * 220fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 230fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 240fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE 250fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * USE OR OTHER DEALINGS IN THE MATERIALS. 260fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * 270fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * Author: Jon Ashburn <jon@lunarg.com> 280fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * Author: Courtney Goeltzenleuchter <courtney@LunarG.com> 290fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * 300fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod */ 310fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod 320fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#define _GNU_SOURCE 330fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#include <stdio.h> 340fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#include <stdlib.h> 350fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#include <stdarg.h> 360fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#include <stdbool.h> 370fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#include <string.h> 380fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod 390fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#include <sys/types.h> 400fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#if defined(_WIN32) 410fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#include "dirent_on_windows.h" 420fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#else // _WIN32 430fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#include <dirent.h> 440fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#endif // _WIN32 450fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#include "vk_loader_platform.h" 460fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#include "loader.h" 470fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#include "gpa_helper.h" 480fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#include "table_ops.h" 490fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#include "debug_report.h" 500fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#include "wsi.h" 510fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#include "vulkan/vk_icd.h" 520fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#include "cJSON.h" 530fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#include "murmurhash.h" 540fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod 550fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbodstatic loader_platform_dl_handle 560fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbodloader_add_layer_lib(const struct loader_instance *inst, const char *chain_type, 570fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod struct loader_layer_properties *layer_prop); 580fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod 590fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbodstatic void loader_remove_layer_lib(struct loader_instance *inst, 600fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod struct loader_layer_properties *layer_prop); 610fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod 620fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbodstruct loader_struct loader = {0}; 630fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod// TLS for instance for alloc/free callbacks 640fbb2dc83132a89201ad8b56c6909610437d2da0Behdad EsfahbodTHREAD_LOCAL_DECL struct loader_instance *tls_instance; 650fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod 660fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbodstatic bool loader_init_generic_list(const struct loader_instance *inst, 670fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod struct loader_generic_list *list_info, 680fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod size_t element_size); 690fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod 700fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbodstatic size_t loader_platform_combine_path(char *dest, size_t len, ...); 710fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod 720fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbodstruct loader_phys_dev_per_icd { 730fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod uint32_t count; 7402aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod VkPhysicalDevice *phys_devs; 750fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod}; 760fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod 770fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbodenum loader_debug { 7802aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod LOADER_INFO_BIT = 0x01, 7902aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod LOADER_WARN_BIT = 0x02, 800fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod LOADER_PERF_BIT = 0x04, 8102aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod LOADER_ERROR_BIT = 0x08, 8202aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod LOADER_DEBUG_BIT = 0x10, 830fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod}; 840fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod 8502aeca985b570763342c35e99af90025bfa088d5Behdad Esfahboduint32_t g_loader_debug = 0; 8602aeca985b570763342c35e99af90025bfa088d5Behdad Esfahboduint32_t g_loader_log_msgs = 0; 870fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod 880fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod// thread safety lock for accessing global data structures such as "loader" 890fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod// all entrypoints on the instance chain need to be locked except GPA 900fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod// additionally CreateDevice and DestroyDevice needs to be locked 910fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbodloader_platform_thread_mutex loader_lock; 920fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbodloader_platform_thread_mutex loader_json_lock; 930fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod 940fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod// This table contains the loader's instance dispatch table, which contains 950fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod// default functions if no instance layers are activated. This contains 960fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod// pointers to "terminator functions". 970fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbodconst VkLayerInstanceDispatchTable instance_disp = { 980fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod .GetInstanceProcAddr = vkGetInstanceProcAddr, 990fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod .DestroyInstance = loader_DestroyInstance, 1000fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod .EnumeratePhysicalDevices = loader_EnumeratePhysicalDevices, 1010fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod .GetPhysicalDeviceFeatures = loader_GetPhysicalDeviceFeatures, 1020fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod .GetPhysicalDeviceFormatProperties = 1030fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod loader_GetPhysicalDeviceFormatProperties, 1040fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod .GetPhysicalDeviceImageFormatProperties = 1050fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod loader_GetPhysicalDeviceImageFormatProperties, 1060fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod .GetPhysicalDeviceProperties = loader_GetPhysicalDeviceProperties, 1070fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod .GetPhysicalDeviceQueueFamilyProperties = 1080fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod loader_GetPhysicalDeviceQueueFamilyProperties, 1090fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod .GetPhysicalDeviceMemoryProperties = 1100fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod loader_GetPhysicalDeviceMemoryProperties, 1110fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod .EnumerateDeviceExtensionProperties = 1120fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod loader_EnumerateDeviceExtensionProperties, 1130fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod .EnumerateDeviceLayerProperties = loader_EnumerateDeviceLayerProperties, 1140fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod .GetPhysicalDeviceSparseImageFormatProperties = 1150fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod loader_GetPhysicalDeviceSparseImageFormatProperties, 1160fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod .DestroySurfaceKHR = loader_DestroySurfaceKHR, 1170fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod .GetPhysicalDeviceSurfaceSupportKHR = 1180fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod loader_GetPhysicalDeviceSurfaceSupportKHR, 1190fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod .GetPhysicalDeviceSurfaceCapabilitiesKHR = 1200fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod loader_GetPhysicalDeviceSurfaceCapabilitiesKHR, 1210fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod .GetPhysicalDeviceSurfaceFormatsKHR = 1220fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod loader_GetPhysicalDeviceSurfaceFormatsKHR, 1230fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod .GetPhysicalDeviceSurfacePresentModesKHR = 1240fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod loader_GetPhysicalDeviceSurfacePresentModesKHR, 1250fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod .CreateDebugReportCallbackEXT = loader_CreateDebugReportCallback, 1260fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod .DestroyDebugReportCallbackEXT = loader_DestroyDebugReportCallback, 1270fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod .DebugReportMessageEXT = loader_DebugReportMessage, 1280fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#ifdef VK_USE_PLATFORM_MIR_KHR 1290fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod .CreateMirSurfaceKHR = loader_CreateMirSurfaceKHR, 1300fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod .GetPhysicalDeviceMirPresentationSupportKHR = 1310fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod loader_GetPhysicalDeviceMirPresentationSupportKHR, 1320fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#endif 1330fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#ifdef VK_USE_PLATFORM_WAYLAND_KHR 1340fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod .CreateWaylandSurfaceKHR = loader_CreateWaylandSurfaceKHR, 13502aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod .GetPhysicalDeviceWaylandPresentationSupportKHR = 1360fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod loader_GetPhysicalDeviceWaylandPresentationSupportKHR, 1370fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#endif 13802aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod#ifdef VK_USE_PLATFORM_WIN32_KHR 1390fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod .CreateWin32SurfaceKHR = loader_CreateWin32SurfaceKHR, 1400fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod .GetPhysicalDeviceWin32PresentationSupportKHR = 1410fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod loader_GetPhysicalDeviceWin32PresentationSupportKHR, 1420fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#endif 1430fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#ifdef VK_USE_PLATFORM_XCB_KHR 1440fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod .CreateXcbSurfaceKHR = loader_CreateXcbSurfaceKHR, 1450fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod .GetPhysicalDeviceXcbPresentationSupportKHR = 1460fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod loader_GetPhysicalDeviceXcbPresentationSupportKHR, 1470fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#endif 1480fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#ifdef VK_USE_PLATFORM_XLIB_KHR 1490fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod .CreateXlibSurfaceKHR = loader_CreateXlibSurfaceKHR, 1500fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod .GetPhysicalDeviceXlibPresentationSupportKHR = 1510fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod loader_GetPhysicalDeviceXlibPresentationSupportKHR, 1520fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#endif 1530fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#ifdef VK_USE_PLATFORM_ANDROID_KHR 1540fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod .CreateAndroidSurfaceKHR = loader_CreateAndroidSurfaceKHR, 1550fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#endif 1560fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod}; 1570fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod 1580fbb2dc83132a89201ad8b56c6909610437d2da0Behdad EsfahbodLOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_init); 1590fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod 1600fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbodvoid *loader_heap_alloc(const struct loader_instance *instance, size_t size, 16102aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod VkSystemAllocationScope alloc_scope) { 1620fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod if (instance && instance->alloc_callbacks.pfnAllocation) { 1630fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod /* TODO: What should default alignment be? 1, 4, 8, other? */ 1640fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod return instance->alloc_callbacks.pfnAllocation( 1650fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod instance->alloc_callbacks.pUserData, size, sizeof(int), 1660fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod alloc_scope); 1670fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod } 1680fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod return malloc(size); 1690fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod} 1700fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod 1710fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbodvoid loader_heap_free(const struct loader_instance *instance, void *pMemory) { 1720fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod if (pMemory == NULL) 1730fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod return; 1740fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod if (instance && instance->alloc_callbacks.pfnFree) { 17502aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod instance->alloc_callbacks.pfnFree(instance->alloc_callbacks.pUserData, 17602aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod pMemory); 1770fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod return; 1780fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod } 1790fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod free(pMemory); 18002aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod} 18102aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod 1820fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbodvoid *loader_heap_realloc(const struct loader_instance *instance, void *pMemory, 1830fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod size_t orig_size, size_t size, 1840fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod VkSystemAllocationScope alloc_scope) { 1850fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod if (pMemory == NULL || orig_size == 0) 1860fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod return loader_heap_alloc(instance, size, alloc_scope); 1870fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod if (size == 0) { 1880fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod loader_heap_free(instance, pMemory); 1890fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod return NULL; 1900fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod } 1910fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod // TODO use the callback realloc function 1920fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod if (instance && instance->alloc_callbacks.pfnAllocation) { 1930fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod if (size <= orig_size) { 1940fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod memset(((uint8_t *)pMemory) + size, 0, orig_size - size); 1950fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod return pMemory; 1960fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod } 1970fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod /* TODO: What should default alignment be? 1, 4, 8, other? */ 1980fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod void *new_ptr = instance->alloc_callbacks.pfnAllocation( 1990fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod instance->alloc_callbacks.pUserData, size, sizeof(int), 2000fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod alloc_scope); 2010fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod if (!new_ptr) 2020fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod return NULL; 2030fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod memcpy(new_ptr, pMemory, orig_size); 2040fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod instance->alloc_callbacks.pfnFree(instance->alloc_callbacks.pUserData, 2050fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod pMemory); 2060fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod return new_ptr; 2070fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod } 2080fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod return realloc(pMemory, size); 2090fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod} 2100fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod 2110fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbodvoid *loader_tls_heap_alloc(size_t size) { 2120fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod return loader_heap_alloc(tls_instance, size, 2130fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 2140fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod} 2150fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod 2160fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbodvoid loader_tls_heap_free(void *pMemory) { 2170fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod loader_heap_free(tls_instance, pMemory); 2180fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod} 2190fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod 2200fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbodstatic void loader_log(const struct loader_instance *inst, VkFlags msg_type, 2210fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod int32_t msg_code, const char *format, ...) { 2220fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod char msg[512]; 22302aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod va_list ap; 2240fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod int ret; 2250fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod 2260fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod va_start(ap, format); 2270fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod ret = vsnprintf(msg, sizeof(msg), format, ap); 22802aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod if ((ret >= (int)sizeof(msg)) || ret < 0) { 2290fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod msg[sizeof(msg) - 1] = '\0'; 2300fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod } 2310fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod va_end(ap); 23202aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod 2330fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod if (inst) { 2340fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod util_DebugReportMessage(inst, msg_type, 2350fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, 2360fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod (uint64_t)inst, 0, msg_code, "loader", msg); 2370fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod } 2380fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod 2390fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod if (!(msg_type & g_loader_log_msgs)) { 2400fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod return; 2410fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod } 2420fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod 2430fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#if defined(WIN32) 2440fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod OutputDebugString(msg); 2450fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod OutputDebugString("\n"); 2460fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#endif 2470fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod fputs(msg, stderr); 2480fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod fputc('\n', stderr); 2490fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod} 2500fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod 2510fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#if defined(WIN32) 2520fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbodstatic char *loader_get_next_path(char *path); 2530fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod/** 25402aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod* Find the list of registry files (names within a key) in key "location". 2550fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod* 2560fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod* This function looks in the registry (hive = DEFAULT_VK_REGISTRY_HIVE) key as 2570fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod*given in "location" 2580fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod* for a list or name/values which are added to a returned list (function return 2590fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod*value). 2600fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod* The DWORD values within the key must be 0 or they are skipped. 2610fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod* Function return is a string with a ';' separated list of filenames. 2620fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod* Function return is NULL if no valid name/value pairs are found in the key, 2630fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod* or the key is not found. 2640fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod* 2650fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod* \returns 2660fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod* A string list of filenames as pointer. 2670fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod* When done using the returned string list, pointer should be freed. 2680fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod*/ 2690fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbodstatic char *loader_get_registry_files(const struct loader_instance *inst, 2700fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod char *location) { 2710fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod LONG rtn_value; 2720fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod HKEY hive, key; 2730fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod DWORD access_flags; 2740fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod char name[2048]; 2750fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod char *out = NULL; 2760fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod char *loc = location; 2770fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod char *next; 27802aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod DWORD idx = 0; 2790fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod DWORD name_size = sizeof(name); 28002aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod DWORD value; 2810fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod DWORD total_size = 4096; 2820fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod DWORD value_size = sizeof(value); 2830fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod 2840fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod while (*loc) { 2850fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod next = loader_get_next_path(loc); 2860fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod hive = DEFAULT_VK_REGISTRY_HIVE; 2870fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod access_flags = KEY_QUERY_VALUE; 2880fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod rtn_value = RegOpenKeyEx(hive, loc, 0, access_flags, &key); 2890fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod if (rtn_value != ERROR_SUCCESS) { 2900fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod // We still couldn't find the key, so give up: 2910fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod loc = next; 2920fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod continue; 2930fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod } 2940fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod 2950fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod while ((rtn_value = RegEnumValue(key, idx++, name, &name_size, NULL, 2960fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod NULL, (LPBYTE)&value, &value_size)) == 2970fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod ERROR_SUCCESS) { 2980fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod if (value_size == sizeof(value) && value == 0) { 2990fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod if (out == NULL) { 3000fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod out = loader_heap_alloc( 3010fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod inst, total_size, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 3020fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod out[0] = '\0'; 3030fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod } else if (strlen(out) + name_size + 1 > total_size) { 3040fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod out = loader_heap_realloc( 3050fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod inst, out, total_size, total_size * 2, 3060fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 3070fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod total_size *= 2; 3080fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod } 3090fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod if (out == NULL) { 31002aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod loader_log( 3110fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 3120fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod "Out of memory, failed loader_get_registry_files"); 3130fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod return NULL; 314 } 315 if (strlen(out) == 0) 316 snprintf(out, name_size + 1, "%s", name); 317 else 318 snprintf(out + strlen(out), name_size + 2, "%c%s", 319 PATH_SEPERATOR, name); 320 } 321 name_size = 2048; 322 } 323 loc = next; 324 } 325 326 return out; 327} 328 329#endif // WIN32 330 331/** 332 * Combine path elements, separating each element with the platform-specific 333 * directory separator, and save the combined string to a destination buffer, 334 * not exceeding the given length. Path elements are given as variadic args, 335 * with a NULL element terminating the list. 336 * 337 * \returns the total length of the combined string, not including an ASCII 338 * NUL termination character. This length may exceed the available storage: 339 * in this case, the written string will be truncated to avoid a buffer 340 * overrun, and the return value will greater than or equal to the storage 341 * size. A NULL argument may be provided as the destination buffer in order 342 * to determine the required string length without actually writing a string. 343 */ 344 345static size_t loader_platform_combine_path(char *dest, size_t len, ...) { 346 size_t required_len = 0; 347 va_list ap; 348 const char *component; 349 350 va_start(ap, len); 351 352 while ((component = va_arg(ap, const char *))) { 353 if (required_len > 0) { 354 // This path element is not the first non-empty element; prepend 355 // a directory separator if space allows 356 if (dest && required_len + 1 < len) { 357 snprintf(dest + required_len, len - required_len, "%c", 358 DIRECTORY_SYMBOL); 359 } 360 required_len++; 361 } 362 363 if (dest && required_len < len) { 364 strncpy(dest + required_len, component, len - required_len); 365 } 366 required_len += strlen(component); 367 } 368 369 va_end(ap); 370 371 // strncpy(3) won't add a NUL terminating byte in the event of truncation. 372 if (dest && required_len >= len) { 373 dest[len - 1] = '\0'; 374 } 375 376 return required_len; 377} 378 379/** 380 * Given string of three part form "maj.min.pat" convert to a vulkan version 381 * number. 382 */ 383static uint32_t loader_make_version(const char *vers_str) { 384 uint32_t vers = 0, major = 0, minor = 0, patch = 0; 385 char *minor_str = NULL; 386 char *patch_str = NULL; 387 char *cstr; 388 char *str; 389 390 if (!vers_str) 391 return vers; 392 cstr = loader_stack_alloc(strlen(vers_str) + 1); 393 strcpy(cstr, vers_str); 394 while ((str = strchr(cstr, '.')) != NULL) { 395 if (minor_str == NULL) { 396 minor_str = str + 1; 397 *str = '\0'; 398 major = atoi(cstr); 399 } else if (patch_str == NULL) { 400 patch_str = str + 1; 401 *str = '\0'; 402 minor = atoi(minor_str); 403 } else { 404 return vers; 405 } 406 cstr = str + 1; 407 } 408 patch = atoi(patch_str); 409 410 return VK_MAKE_VERSION(major, minor, patch); 411} 412 413bool compare_vk_extension_properties(const VkExtensionProperties *op1, 414 const VkExtensionProperties *op2) { 415 return strcmp(op1->extensionName, op2->extensionName) == 0 ? true : false; 416} 417 418/** 419 * Search the given ext_array for an extension 420 * matching the given vk_ext_prop 421 */ 422bool has_vk_extension_property_array(const VkExtensionProperties *vk_ext_prop, 423 const uint32_t count, 424 const VkExtensionProperties *ext_array) { 425 for (uint32_t i = 0; i < count; i++) { 426 if (compare_vk_extension_properties(vk_ext_prop, &ext_array[i])) 427 return true; 428 } 429 return false; 430} 431 432/** 433 * Search the given ext_list for an extension 434 * matching the given vk_ext_prop 435 */ 436bool has_vk_extension_property(const VkExtensionProperties *vk_ext_prop, 437 const struct loader_extension_list *ext_list) { 438 for (uint32_t i = 0; i < ext_list->count; i++) { 439 if (compare_vk_extension_properties(&ext_list->list[i], vk_ext_prop)) 440 return true; 441 } 442 return false; 443} 444 445static inline bool loader_is_layer_type_device(const enum layer_type type) { 446 if ((type & VK_LAYER_TYPE_DEVICE_EXPLICIT) || 447 (type & VK_LAYER_TYPE_DEVICE_IMPLICIT)) 448 return true; 449 return false; 450} 451 452/* 453 * Search the given layer list for a layer matching the given layer name 454 */ 455static struct loader_layer_properties * 456loader_get_layer_property(const char *name, 457 const struct loader_layer_list *layer_list) { 458 for (uint32_t i = 0; i < layer_list->count; i++) { 459 const VkLayerProperties *item = &layer_list->list[i].info; 460 if (strcmp(name, item->layerName) == 0) 461 return &layer_list->list[i]; 462 } 463 return NULL; 464} 465 466/** 467 * Get the next unused layer property in the list. Init the property to zero. 468 */ 469static struct loader_layer_properties * 470loader_get_next_layer_property(const struct loader_instance *inst, 471 struct loader_layer_list *layer_list) { 472 if (layer_list->capacity == 0) { 473 layer_list->list = 474 loader_heap_alloc(inst, sizeof(struct loader_layer_properties) * 64, 475 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 476 if (layer_list->list == NULL) { 477 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 478 "Out of memory can't add any layer properties to list"); 479 return NULL; 480 } 481 memset(layer_list->list, 0, 482 sizeof(struct loader_layer_properties) * 64); 483 layer_list->capacity = sizeof(struct loader_layer_properties) * 64; 484 } 485 486 // ensure enough room to add an entry 487 if ((layer_list->count + 1) * sizeof(struct loader_layer_properties) > 488 layer_list->capacity) { 489 layer_list->list = loader_heap_realloc( 490 inst, layer_list->list, layer_list->capacity, 491 layer_list->capacity * 2, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 492 if (layer_list->list == NULL) { 493 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 494 "realloc failed for layer list"); 495 } 496 layer_list->capacity *= 2; 497 } 498 499 layer_list->count++; 500 return &(layer_list->list[layer_list->count - 1]); 501} 502 503/** 504 * Remove all layer properties entrys from the list 505 */ 506void loader_delete_layer_properties(const struct loader_instance *inst, 507 struct loader_layer_list *layer_list) { 508 uint32_t i, j; 509 struct loader_device_extension_list *dev_ext_list; 510 if (!layer_list) 511 return; 512 513 for (i = 0; i < layer_list->count; i++) { 514 loader_destroy_generic_list( 515 inst, (struct loader_generic_list *)&layer_list->list[i] 516 .instance_extension_list); 517 dev_ext_list = &layer_list->list[i].device_extension_list; 518 if (dev_ext_list->capacity > 0 && 519 dev_ext_list->list->entrypoint_count > 0) { 520 for (j = 0; j < dev_ext_list->list->entrypoint_count; j++) { 521 loader_heap_free(inst, dev_ext_list->list->entrypoints[j]); 522 } 523 loader_heap_free(inst, dev_ext_list->list->entrypoints); 524 } 525 loader_destroy_generic_list(inst, 526 (struct loader_generic_list *)dev_ext_list); 527 } 528 layer_list->count = 0; 529 530 if (layer_list->capacity > 0) { 531 layer_list->capacity = 0; 532 loader_heap_free(inst, layer_list->list); 533 } 534} 535 536static void loader_add_instance_extensions( 537 const struct loader_instance *inst, 538 const PFN_vkEnumerateInstanceExtensionProperties fp_get_props, 539 const char *lib_name, struct loader_extension_list *ext_list) { 540 uint32_t i, count = 0; 541 VkExtensionProperties *ext_props; 542 VkResult res; 543 544 if (!fp_get_props) { 545 /* No EnumerateInstanceExtensionProperties defined */ 546 return; 547 } 548 549 res = fp_get_props(NULL, &count, NULL); 550 if (res != VK_SUCCESS) { 551 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 552 "Error getting Instance extension count from %s", lib_name); 553 return; 554 } 555 556 if (count == 0) { 557 /* No ExtensionProperties to report */ 558 return; 559 } 560 561 ext_props = loader_stack_alloc(count * sizeof(VkExtensionProperties)); 562 563 res = fp_get_props(NULL, &count, ext_props); 564 if (res != VK_SUCCESS) { 565 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 566 "Error getting Instance extensions from %s", lib_name); 567 return; 568 } 569 570 for (i = 0; i < count; i++) { 571 char spec_version[64]; 572 573 snprintf(spec_version, sizeof(spec_version), "%d.%d.%d", 574 VK_MAJOR(ext_props[i].specVersion), 575 VK_MINOR(ext_props[i].specVersion), 576 VK_PATCH(ext_props[i].specVersion)); 577 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, 578 "Instance Extension: %s (%s) version %s", 579 ext_props[i].extensionName, lib_name, spec_version); 580 loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]); 581 } 582 583 return; 584} 585 586/* 587 * Initialize ext_list with the physical device extensions. 588 * The extension properties are passed as inputs in count and ext_props. 589 */ 590static VkResult 591loader_init_device_extensions(const struct loader_instance *inst, 592 struct loader_physical_device *phys_dev, 593 uint32_t count, VkExtensionProperties *ext_props, 594 struct loader_extension_list *ext_list) { 595 VkResult res; 596 uint32_t i; 597 598 if (!loader_init_generic_list(inst, (struct loader_generic_list *)ext_list, 599 sizeof(VkExtensionProperties))) { 600 return VK_ERROR_OUT_OF_HOST_MEMORY; 601 } 602 603 for (i = 0; i < count; i++) { 604 char spec_version[64]; 605 606 snprintf(spec_version, sizeof(spec_version), "%d.%d.%d", 607 VK_MAJOR(ext_props[i].specVersion), 608 VK_MINOR(ext_props[i].specVersion), 609 VK_PATCH(ext_props[i].specVersion)); 610 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, 611 "Device Extension: %s (%s) version %s", 612 ext_props[i].extensionName, 613 phys_dev->this_icd->this_icd_lib->lib_name, spec_version); 614 res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]); 615 if (res != VK_SUCCESS) 616 return res; 617 } 618 619 return VK_SUCCESS; 620} 621 622static VkResult loader_add_device_extensions( 623 const struct loader_instance *inst, struct loader_icd *icd, 624 VkPhysicalDevice physical_device, const char *lib_name, 625 struct loader_extension_list *ext_list) { 626 uint32_t i, count; 627 VkResult res; 628 VkExtensionProperties *ext_props; 629 630 res = icd->EnumerateDeviceExtensionProperties(physical_device, NULL, &count, 631 NULL); 632 if (res == VK_SUCCESS && count > 0) { 633 ext_props = loader_stack_alloc(count * sizeof(VkExtensionProperties)); 634 if (!ext_props) 635 return VK_ERROR_OUT_OF_HOST_MEMORY; 636 res = icd->EnumerateDeviceExtensionProperties(physical_device, NULL, 637 &count, ext_props); 638 if (res != VK_SUCCESS) 639 return res; 640 for (i = 0; i < count; i++) { 641 char spec_version[64]; 642 643 snprintf(spec_version, sizeof(spec_version), "%d.%d.%d", 644 VK_MAJOR(ext_props[i].specVersion), 645 VK_MINOR(ext_props[i].specVersion), 646 VK_PATCH(ext_props[i].specVersion)); 647 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, 648 "Device Extension: %s (%s) version %s", 649 ext_props[i].extensionName, lib_name, spec_version); 650 res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]); 651 if (res != VK_SUCCESS) 652 return res; 653 } 654 } else { 655 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 656 "Error getting physical device extension info count from " 657 "library %s", 658 lib_name); 659 return res; 660 } 661 662 return VK_SUCCESS; 663} 664 665static bool loader_init_generic_list(const struct loader_instance *inst, 666 struct loader_generic_list *list_info, 667 size_t element_size) { 668 list_info->capacity = 32 * element_size; 669 list_info->list = loader_heap_alloc(inst, list_info->capacity, 670 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 671 if (list_info->list == NULL) { 672 return false; 673 } 674 memset(list_info->list, 0, list_info->capacity); 675 list_info->count = 0; 676 return true; 677} 678 679void loader_destroy_generic_list(const struct loader_instance *inst, 680 struct loader_generic_list *list) { 681 loader_heap_free(inst, list->list); 682 list->count = 0; 683 list->capacity = 0; 684} 685 686/* 687 * Append non-duplicate extension properties defined in props 688 * to the given ext_list. 689 * Return 690 * Vk_SUCCESS on success 691 */ 692VkResult loader_add_to_ext_list(const struct loader_instance *inst, 693 struct loader_extension_list *ext_list, 694 uint32_t prop_list_count, 695 const VkExtensionProperties *props) { 696 uint32_t i; 697 const VkExtensionProperties *cur_ext; 698 699 if (ext_list->list == NULL || ext_list->capacity == 0) { 700 loader_init_generic_list(inst, (struct loader_generic_list *)ext_list, 701 sizeof(VkExtensionProperties)); 702 } 703 704 if (ext_list->list == NULL) 705 return VK_ERROR_OUT_OF_HOST_MEMORY; 706 707 for (i = 0; i < prop_list_count; i++) { 708 cur_ext = &props[i]; 709 710 // look for duplicates 711 if (has_vk_extension_property(cur_ext, ext_list)) { 712 continue; 713 } 714 715 // add to list at end 716 // check for enough capacity 717 if (ext_list->count * sizeof(VkExtensionProperties) >= 718 ext_list->capacity) { 719 720 ext_list->list = loader_heap_realloc( 721 inst, ext_list->list, ext_list->capacity, 722 ext_list->capacity * 2, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 723 724 if (ext_list->list == NULL) 725 return VK_ERROR_OUT_OF_HOST_MEMORY; 726 727 // double capacity 728 ext_list->capacity *= 2; 729 } 730 731 memcpy(&ext_list->list[ext_list->count], cur_ext, 732 sizeof(VkExtensionProperties)); 733 ext_list->count++; 734 } 735 return VK_SUCCESS; 736} 737 738/* 739 * Append one extension property defined in props with entrypoints 740 * defined in entrys to the given ext_list. 741 * Return 742 * Vk_SUCCESS on success 743 */ 744VkResult 745loader_add_to_dev_ext_list(const struct loader_instance *inst, 746 struct loader_device_extension_list *ext_list, 747 const VkExtensionProperties *props, 748 uint32_t entry_count, char **entrys) { 749 uint32_t idx; 750 if (ext_list->list == NULL || ext_list->capacity == 0) { 751 loader_init_generic_list(inst, (struct loader_generic_list *)ext_list, 752 sizeof(struct loader_dev_ext_props)); 753 } 754 755 if (ext_list->list == NULL) 756 return VK_ERROR_OUT_OF_HOST_MEMORY; 757 758 idx = ext_list->count; 759 // add to list at end 760 // check for enough capacity 761 if (idx * sizeof(struct loader_dev_ext_props) >= ext_list->capacity) { 762 763 ext_list->list = loader_heap_realloc( 764 inst, ext_list->list, ext_list->capacity, ext_list->capacity * 2, 765 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 766 767 if (ext_list->list == NULL) 768 return VK_ERROR_OUT_OF_HOST_MEMORY; 769 770 // double capacity 771 ext_list->capacity *= 2; 772 } 773 774 memcpy(&ext_list->list[idx].props, props, 775 sizeof(struct loader_dev_ext_props)); 776 ext_list->list[idx].entrypoint_count = entry_count; 777 ext_list->list[idx].entrypoints = 778 loader_heap_alloc(inst, sizeof(char *) * entry_count, 779 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 780 if (ext_list->list[idx].entrypoints == NULL) 781 return VK_ERROR_OUT_OF_HOST_MEMORY; 782 for (uint32_t i = 0; i < entry_count; i++) { 783 ext_list->list[idx].entrypoints[i] = loader_heap_alloc( 784 inst, strlen(entrys[i]) + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 785 if (ext_list->list[idx].entrypoints[i] == NULL) 786 return VK_ERROR_OUT_OF_HOST_MEMORY; 787 strcpy(ext_list->list[idx].entrypoints[i], entrys[i]); 788 } 789 ext_list->count++; 790 791 return VK_SUCCESS; 792} 793 794/** 795 * Search the given search_list for any layers in the props list. 796 * Add these to the output layer_list. Don't add duplicates to the output 797 * layer_list. 798 */ 799static VkResult 800loader_add_layer_names_to_list(const struct loader_instance *inst, 801 struct loader_layer_list *output_list, 802 uint32_t name_count, const char *const *names, 803 const struct loader_layer_list *search_list) { 804 struct loader_layer_properties *layer_prop; 805 VkResult err = VK_SUCCESS; 806 807 for (uint32_t i = 0; i < name_count; i++) { 808 const char *search_target = names[i]; 809 layer_prop = loader_get_layer_property(search_target, search_list); 810 if (!layer_prop) { 811 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 812 "Unable to find layer %s", search_target); 813 err = VK_ERROR_LAYER_NOT_PRESENT; 814 continue; 815 } 816 817 loader_add_to_layer_list(inst, output_list, 1, layer_prop); 818 } 819 820 return err; 821} 822 823/* 824 * Manage lists of VkLayerProperties 825 */ 826static bool loader_init_layer_list(const struct loader_instance *inst, 827 struct loader_layer_list *list) { 828 list->capacity = 32 * sizeof(struct loader_layer_properties); 829 list->list = loader_heap_alloc(inst, list->capacity, 830 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 831 if (list->list == NULL) { 832 return false; 833 } 834 memset(list->list, 0, list->capacity); 835 list->count = 0; 836 return true; 837} 838 839void loader_destroy_layer_list(const struct loader_instance *inst, 840 struct loader_layer_list *layer_list) { 841 loader_heap_free(inst, layer_list->list); 842 layer_list->count = 0; 843 layer_list->capacity = 0; 844} 845 846/* 847 * Manage list of layer libraries (loader_lib_info) 848 */ 849static bool 850loader_init_layer_library_list(const struct loader_instance *inst, 851 struct loader_layer_library_list *list) { 852 list->capacity = 32 * sizeof(struct loader_lib_info); 853 list->list = loader_heap_alloc(inst, list->capacity, 854 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 855 if (list->list == NULL) { 856 return false; 857 } 858 memset(list->list, 0, list->capacity); 859 list->count = 0; 860 return true; 861} 862 863void loader_destroy_layer_library_list(const struct loader_instance *inst, 864 struct loader_layer_library_list *list) { 865 for (uint32_t i = 0; i < list->count; i++) { 866 loader_heap_free(inst, list->list[i].lib_name); 867 } 868 loader_heap_free(inst, list->list); 869 list->count = 0; 870 list->capacity = 0; 871} 872 873void loader_add_to_layer_library_list(const struct loader_instance *inst, 874 struct loader_layer_library_list *list, 875 uint32_t item_count, 876 const struct loader_lib_info *new_items) { 877 uint32_t i; 878 struct loader_lib_info *item; 879 880 if (list->list == NULL || list->capacity == 0) { 881 loader_init_layer_library_list(inst, list); 882 } 883 884 if (list->list == NULL) 885 return; 886 887 for (i = 0; i < item_count; i++) { 888 item = (struct loader_lib_info *)&new_items[i]; 889 890 // look for duplicates 891 for (uint32_t j = 0; j < list->count; j++) { 892 if (strcmp(list->list[i].lib_name, new_items->lib_name) == 0) { 893 continue; 894 } 895 } 896 897 // add to list at end 898 // check for enough capacity 899 if (list->count * sizeof(struct loader_lib_info) >= list->capacity) { 900 901 list->list = loader_heap_realloc( 902 inst, list->list, list->capacity, list->capacity * 2, 903 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 904 // double capacity 905 list->capacity *= 2; 906 } 907 908 memcpy(&list->list[list->count], item, sizeof(struct loader_lib_info)); 909 list->count++; 910 } 911} 912 913/* 914 * Search the given layer list for a list 915 * matching the given VkLayerProperties 916 */ 917bool has_vk_layer_property(const VkLayerProperties *vk_layer_prop, 918 const struct loader_layer_list *list) { 919 for (uint32_t i = 0; i < list->count; i++) { 920 if (strcmp(vk_layer_prop->layerName, list->list[i].info.layerName) == 0) 921 return true; 922 } 923 return false; 924} 925 926/* 927 * Search the given layer list for a layer 928 * matching the given name 929 */ 930bool has_layer_name(const char *name, const struct loader_layer_list *list) { 931 for (uint32_t i = 0; i < list->count; i++) { 932 if (strcmp(name, list->list[i].info.layerName) == 0) 933 return true; 934 } 935 return false; 936} 937 938/* 939 * Append non-duplicate layer properties defined in prop_list 940 * to the given layer_info list 941 */ 942void loader_add_to_layer_list(const struct loader_instance *inst, 943 struct loader_layer_list *list, 944 uint32_t prop_list_count, 945 const struct loader_layer_properties *props) { 946 uint32_t i; 947 struct loader_layer_properties *layer; 948 949 if (list->list == NULL || list->capacity == 0) { 950 loader_init_layer_list(inst, list); 951 } 952 953 if (list->list == NULL) 954 return; 955 956 for (i = 0; i < prop_list_count; i++) { 957 layer = (struct loader_layer_properties *)&props[i]; 958 959 // look for duplicates 960 if (has_vk_layer_property(&layer->info, list)) { 961 continue; 962 } 963 964 // add to list at end 965 // check for enough capacity 966 if (list->count * sizeof(struct loader_layer_properties) >= 967 list->capacity) { 968 969 list->list = loader_heap_realloc( 970 inst, list->list, list->capacity, list->capacity * 2, 971 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 972 // double capacity 973 list->capacity *= 2; 974 } 975 976 memcpy(&list->list[list->count], layer, 977 sizeof(struct loader_layer_properties)); 978 list->count++; 979 } 980} 981 982/** 983 * Search the search_list for any layer with a name 984 * that matches the given name and a type that matches the given type 985 * Add all matching layers to the found_list 986 * Do not add if found loader_layer_properties is already 987 * on the found_list. 988 */ 989static void 990loader_find_layer_name_add_list(const struct loader_instance *inst, 991 const char *name, const enum layer_type type, 992 const struct loader_layer_list *search_list, 993 struct loader_layer_list *found_list) { 994 bool found = false; 995 for (uint32_t i = 0; i < search_list->count; i++) { 996 struct loader_layer_properties *layer_prop = &search_list->list[i]; 997 if (0 == strcmp(layer_prop->info.layerName, name) && 998 (layer_prop->type & type)) { 999 /* Found a layer with the same name, add to found_list */ 1000 loader_add_to_layer_list(inst, found_list, 1, layer_prop); 1001 found = true; 1002 } 1003 } 1004 if (!found) { 1005 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 1006 "Warning, couldn't find layer name %s to activate", name); 1007 } 1008} 1009 1010static VkExtensionProperties * 1011get_extension_property(const char *name, 1012 const struct loader_extension_list *list) { 1013 for (uint32_t i = 0; i < list->count; i++) { 1014 if (strcmp(name, list->list[i].extensionName) == 0) 1015 return &list->list[i]; 1016 } 1017 return NULL; 1018} 1019 1020static VkExtensionProperties * 1021get_dev_extension_property(const char *name, 1022 const struct loader_device_extension_list *list) { 1023 for (uint32_t i = 0; i < list->count; i++) { 1024 if (strcmp(name, list->list[i].props.extensionName) == 0) 1025 return &list->list[i].props; 1026 } 1027 return NULL; 1028} 1029 1030/* 1031 * This function will return the pNext pointer of any 1032 * CreateInfo extensions that are not loader extensions. 1033 * This is used to skip past the loader extensions prepended 1034 * to the list during CreateInstance and CreateDevice. 1035 */ 1036void *loader_strip_create_extensions(const void *pNext) { 1037 VkLayerInstanceCreateInfo *create_info = (VkLayerInstanceCreateInfo *)pNext; 1038 1039 while ( 1040 create_info && 1041 (create_info->sType == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO || 1042 create_info->sType == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO)) { 1043 create_info = (VkLayerInstanceCreateInfo *)create_info->pNext; 1044 } 1045 1046 return create_info; 1047} 1048 1049/* 1050 * For Instance 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 1060 * GetProcAddr requests 1061 * loader_coalesce_extensions(void) - add extension records to the list of 1062 * global 1063 * extension available to the app. 1064 * instance_disp - add function pointer for terminator function to this array. 1065 * The extension itself should be in a separate file that will be 1066 * linked directly with the loader. 1067 */ 1068 1069void loader_get_icd_loader_instance_extensions( 1070 const struct loader_instance *inst, struct loader_icd_libs *icd_libs, 1071 struct loader_extension_list *inst_exts) { 1072 struct loader_extension_list icd_exts; 1073 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, 1074 "Build ICD instance extension list"); 1075 // traverse scanned icd list adding non-duplicate extensions to the list 1076 for (uint32_t i = 0; i < icd_libs->count; i++) { 1077 loader_init_generic_list(inst, (struct loader_generic_list *)&icd_exts, 1078 sizeof(VkExtensionProperties)); 1079 loader_add_instance_extensions( 1080 inst, icd_libs->list[i].EnumerateInstanceExtensionProperties, 1081 icd_libs->list[i].lib_name, &icd_exts); 1082 loader_add_to_ext_list(inst, inst_exts, icd_exts.count, icd_exts.list); 1083 loader_destroy_generic_list(inst, 1084 (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 * 1093loader_get_physical_device(const VkPhysicalDevice physdev) { 1094 uint32_t i; 1095 for (struct loader_instance *inst = loader.instances; inst; 1096 inst = inst->next) { 1097 for (i = 0; i < inst->total_gpu_count; i++) { 1098 // TODO this aliases physDevices within instances, need for this 1099 // function to go away 1100 if (inst->phys_devs[i].disp == 1101 loader_get_instance_dispatch(physdev)) { 1102 return &inst->phys_devs[i]; 1103 } 1104 } 1105 } 1106 return NULL; 1107} 1108 1109struct loader_icd *loader_get_icd_and_device(const VkDevice device, 1110 struct loader_device **found_dev) { 1111 *found_dev = NULL; 1112 for (struct loader_instance *inst = loader.instances; inst; 1113 inst = inst->next) { 1114 for (struct loader_icd *icd = inst->icds; icd; icd = icd->next) { 1115 for (struct loader_device *dev = icd->logical_device_list; dev; 1116 dev = dev->next) 1117 /* Value comparison of device prevents object wrapping by layers 1118 */ 1119 if (loader_get_dispatch(dev->device) == 1120 loader_get_dispatch(device)) { 1121 *found_dev = dev; 1122 return icd; 1123 } 1124 } 1125 } 1126 return NULL; 1127} 1128 1129static void loader_destroy_logical_device(const struct loader_instance *inst, 1130 struct loader_device *dev) { 1131 loader_heap_free(inst, dev->app_extension_props); 1132 loader_destroy_layer_list(inst, &dev->activated_layer_list); 1133 loader_heap_free(inst, dev); 1134} 1135 1136static struct loader_device * 1137loader_add_logical_device(const struct loader_instance *inst, 1138 struct loader_device **device_list) { 1139 struct loader_device *new_dev; 1140 1141 new_dev = loader_heap_alloc(inst, sizeof(struct loader_device), 1142 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); 1143 if (!new_dev) { 1144 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 1145 "Failed to alloc struct loader-device"); 1146 return NULL; 1147 } 1148 1149 memset(new_dev, 0, sizeof(struct loader_device)); 1150 1151 new_dev->next = *device_list; 1152 *device_list = new_dev; 1153 return new_dev; 1154} 1155 1156void loader_remove_logical_device(const struct loader_instance *inst, 1157 struct loader_icd *icd, 1158 struct loader_device *found_dev) { 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 1178static void loader_icd_destroy(struct loader_instance *ptr_inst, 1179 struct loader_icd *icd) { 1180 ptr_inst->total_icd_count--; 1181 for (struct loader_device *dev = icd->logical_device_list; dev;) { 1182 struct loader_device *next_dev = dev->next; 1183 loader_destroy_logical_device(ptr_inst, dev); 1184 dev = next_dev; 1185 } 1186 1187 loader_heap_free(ptr_inst, icd); 1188} 1189 1190static struct loader_icd * 1191loader_icd_create(const struct loader_instance *inst) { 1192 struct loader_icd *icd; 1193 1194 icd = loader_heap_alloc(inst, sizeof(*icd), 1195 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1196 if (!icd) 1197 return NULL; 1198 1199 memset(icd, 0, sizeof(*icd)); 1200 1201 return icd; 1202} 1203 1204static struct loader_icd * 1205loader_icd_add(struct loader_instance *ptr_inst, 1206 const struct loader_scanned_icds *icd_lib) { 1207 struct loader_icd *icd; 1208 1209 icd = loader_icd_create(ptr_inst); 1210 if (!icd) 1211 return NULL; 1212 1213 icd->this_icd_lib = icd_lib; 1214 icd->this_instance = ptr_inst; 1215 1216 /* prepend to the list */ 1217 icd->next = ptr_inst->icds; 1218 ptr_inst->icds = icd; 1219 ptr_inst->total_icd_count++; 1220 1221 return icd; 1222} 1223 1224void loader_scanned_icd_clear(const struct loader_instance *inst, 1225 struct loader_icd_libs *icd_libs) { 1226 if (icd_libs->capacity == 0) 1227 return; 1228 for (uint32_t i = 0; i < icd_libs->count; i++) { 1229 loader_platform_close_library(icd_libs->list[i].handle); 1230 loader_heap_free(inst, icd_libs->list[i].lib_name); 1231 } 1232 loader_heap_free(inst, icd_libs->list); 1233 icd_libs->capacity = 0; 1234 icd_libs->count = 0; 1235 icd_libs->list = NULL; 1236} 1237 1238static void loader_scanned_icd_init(const struct loader_instance *inst, 1239 struct loader_icd_libs *icd_libs) { 1240 loader_scanned_icd_clear(inst, icd_libs); 1241 icd_libs->capacity = 8 * sizeof(struct loader_scanned_icds); 1242 icd_libs->list = loader_heap_alloc(inst, icd_libs->capacity, 1243 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1244} 1245 1246static void loader_scanned_icd_add(const struct loader_instance *inst, 1247 struct loader_icd_libs *icd_libs, 1248 const char *filename, uint32_t api_version) { 1249 loader_platform_dl_handle handle; 1250 PFN_vkCreateInstance fp_create_inst; 1251 PFN_vkEnumerateInstanceExtensionProperties fp_get_inst_ext_props; 1252 PFN_vkGetInstanceProcAddr fp_get_proc_addr; 1253 struct loader_scanned_icds *new_node; 1254 1255 /* TODO implement ref counting of libraries, for now this function leaves 1256 libraries open and the scanned_icd_clear closes them */ 1257 // Used to call: dlopen(filename, RTLD_LAZY); 1258 handle = loader_platform_open_library(filename); 1259 if (!handle) { 1260 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 1261 loader_platform_open_library_error(filename)); 1262 return; 1263 } 1264 1265 fp_get_proc_addr = 1266 loader_platform_get_proc_address(handle, "vk_icdGetInstanceProcAddr"); 1267 if (!fp_get_proc_addr) { 1268 // Use deprecated interface 1269 fp_get_proc_addr = 1270 loader_platform_get_proc_address(handle, "vkGetInstanceProcAddr"); 1271 if (!fp_get_proc_addr) { 1272 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 1273 loader_platform_get_proc_address_error( 1274 "vk_icdGetInstanceProcAddr")); 1275 return; 1276 } else { 1277 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 1278 "Using deprecated ICD interface of " 1279 "vkGetInstanceProcAddr instead of " 1280 "vk_icdGetInstanceProcAddr"); 1281 } 1282 fp_create_inst = 1283 loader_platform_get_proc_address(handle, "vkCreateInstance"); 1284 if (!fp_create_inst) { 1285 loader_log( 1286 inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 1287 "Couldn't get vkCreateInstance via dlsym/loadlibrary from ICD"); 1288 return; 1289 } 1290 fp_get_inst_ext_props = loader_platform_get_proc_address( 1291 handle, "vkEnumerateInstanceExtensionProperties"); 1292 if (!fp_get_inst_ext_props) { 1293 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 1294 "Couldn't get vkEnumerateInstanceExtensionProperties " 1295 "via dlsym/loadlibrary from ICD"); 1296 return; 1297 } 1298 } else { 1299 // Use newer interface 1300 fp_create_inst = 1301 (PFN_vkCreateInstance)fp_get_proc_addr(NULL, "vkCreateInstance"); 1302 if (!fp_create_inst) { 1303 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 1304 "Couldn't get vkCreateInstance via " 1305 "vk_icdGetInstanceProcAddr from ICD"); 1306 return; 1307 } 1308 fp_get_inst_ext_props = 1309 (PFN_vkEnumerateInstanceExtensionProperties)fp_get_proc_addr( 1310 NULL, "vkEnumerateInstanceExtensionProperties"); 1311 if (!fp_get_inst_ext_props) { 1312 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 1313 "Couldn't get vkEnumerateInstanceExtensionProperties " 1314 "via vk_icdGetInstanceProcAddr from ICD"); 1315 return; 1316 } 1317 } 1318 1319 // check for enough capacity 1320 if ((icd_libs->count * sizeof(struct loader_scanned_icds)) >= 1321 icd_libs->capacity) { 1322 1323 icd_libs->list = loader_heap_realloc( 1324 inst, icd_libs->list, icd_libs->capacity, icd_libs->capacity * 2, 1325 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1326 // double capacity 1327 icd_libs->capacity *= 2; 1328 } 1329 new_node = &(icd_libs->list[icd_libs->count]); 1330 1331 new_node->handle = handle; 1332 new_node->api_version = api_version; 1333 new_node->GetInstanceProcAddr = fp_get_proc_addr; 1334 new_node->EnumerateInstanceExtensionProperties = fp_get_inst_ext_props; 1335 new_node->CreateInstance = fp_create_inst; 1336 1337 new_node->lib_name = (char *)loader_heap_alloc( 1338 inst, strlen(filename) + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1339 if (!new_node->lib_name) { 1340 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 1341 "Out of memory can't add icd"); 1342 return; 1343 } 1344 strcpy(new_node->lib_name, filename); 1345 icd_libs->count++; 1346} 1347 1348static bool loader_icd_init_entrys(struct loader_icd *icd, VkInstance inst, 1349 const PFN_vkGetInstanceProcAddr fp_gipa) { 1350/* initialize entrypoint function pointers */ 1351 1352#define LOOKUP_GIPA(func, required) \ 1353 do { \ 1354 icd->func = (PFN_vk##func)fp_gipa(inst, "vk" #func); \ 1355 if (!icd->func && required) { \ 1356 loader_log((struct loader_instance *)inst, \ 1357 VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, \ 1358 loader_platform_get_proc_address_error("vk" #func)); \ 1359 return false; \ 1360 } \ 1361 } while (0) 1362 1363 LOOKUP_GIPA(GetDeviceProcAddr, true); 1364 LOOKUP_GIPA(DestroyInstance, true); 1365 LOOKUP_GIPA(EnumeratePhysicalDevices, true); 1366 LOOKUP_GIPA(GetPhysicalDeviceFeatures, true); 1367 LOOKUP_GIPA(GetPhysicalDeviceFormatProperties, true); 1368 LOOKUP_GIPA(GetPhysicalDeviceImageFormatProperties, true); 1369 LOOKUP_GIPA(CreateDevice, true); 1370 LOOKUP_GIPA(GetPhysicalDeviceProperties, true); 1371 LOOKUP_GIPA(GetPhysicalDeviceMemoryProperties, true); 1372 LOOKUP_GIPA(GetPhysicalDeviceQueueFamilyProperties, true); 1373 LOOKUP_GIPA(EnumerateDeviceExtensionProperties, true); 1374 LOOKUP_GIPA(GetPhysicalDeviceSparseImageFormatProperties, true); 1375 LOOKUP_GIPA(CreateDebugReportCallbackEXT, false); 1376 LOOKUP_GIPA(DestroyDebugReportCallbackEXT, false); 1377 LOOKUP_GIPA(GetPhysicalDeviceSurfaceSupportKHR, false); 1378 LOOKUP_GIPA(GetPhysicalDeviceSurfaceCapabilitiesKHR, false); 1379 LOOKUP_GIPA(GetPhysicalDeviceSurfaceFormatsKHR, false); 1380 LOOKUP_GIPA(GetPhysicalDeviceSurfacePresentModesKHR, false); 1381#ifdef VK_USE_PLATFORM_WIN32_KHR 1382 LOOKUP_GIPA(GetPhysicalDeviceWin32PresentationSupportKHR, false); 1383#endif 1384#ifdef VK_USE_PLATFORM_XCB_KHR 1385 LOOKUP_GIPA(GetPhysicalDeviceXcbPresentationSupportKHR, false); 1386#endif 1387 1388#undef LOOKUP_GIPA 1389 1390 return true; 1391} 1392 1393static void loader_debug_init(void) { 1394 const char *env, *orig; 1395 1396 if (g_loader_debug > 0) 1397 return; 1398 1399 g_loader_debug = 0; 1400 1401 /* parse comma-separated debug options */ 1402 orig = env = loader_getenv("VK_LOADER_DEBUG"); 1403 while (env) { 1404 const char *p = strchr(env, ','); 1405 size_t len; 1406 1407 if (p) 1408 len = p - env; 1409 else 1410 len = strlen(env); 1411 1412 if (len > 0) { 1413 if (strncmp(env, "all", len) == 0) { 1414 g_loader_debug = ~0u; 1415 g_loader_log_msgs = ~0u; 1416 } else if (strncmp(env, "warn", len) == 0) { 1417 g_loader_debug |= LOADER_WARN_BIT; 1418 g_loader_log_msgs |= VK_DEBUG_REPORT_WARNING_BIT_EXT; 1419 } else if (strncmp(env, "info", len) == 0) { 1420 g_loader_debug |= LOADER_INFO_BIT; 1421 g_loader_log_msgs |= VK_DEBUG_REPORT_INFORMATION_BIT_EXT; 1422 } else if (strncmp(env, "perf", len) == 0) { 1423 g_loader_debug |= LOADER_PERF_BIT; 1424 g_loader_log_msgs |= VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT; 1425 } else if (strncmp(env, "error", len) == 0) { 1426 g_loader_debug |= LOADER_ERROR_BIT; 1427 g_loader_log_msgs |= VK_DEBUG_REPORT_ERROR_BIT_EXT; 1428 } else if (strncmp(env, "debug", len) == 0) { 1429 g_loader_debug |= LOADER_DEBUG_BIT; 1430 g_loader_log_msgs |= VK_DEBUG_REPORT_DEBUG_BIT_EXT; 1431 } 1432 } 1433 1434 if (!p) 1435 break; 1436 1437 env = p + 1; 1438 } 1439 1440 loader_free_getenv(orig); 1441} 1442 1443void loader_initialize(void) { 1444 // initialize mutexs 1445 loader_platform_thread_create_mutex(&loader_lock); 1446 loader_platform_thread_create_mutex(&loader_json_lock); 1447 1448 // initialize logging 1449 loader_debug_init(); 1450 1451 // initial cJSON to use alloc callbacks 1452 cJSON_Hooks alloc_fns = { 1453 .malloc_fn = loader_tls_heap_alloc, .free_fn = loader_tls_heap_free, 1454 }; 1455 cJSON_InitHooks(&alloc_fns); 1456} 1457 1458struct loader_manifest_files { 1459 uint32_t count; 1460 char **filename_list; 1461}; 1462 1463/** 1464 * Get next file or dirname given a string list or registry key path 1465 * 1466 * \returns 1467 * A pointer to first char in the next path. 1468 * The next path (or NULL) in the list is returned in next_path. 1469 * Note: input string is modified in some cases. PASS IN A COPY! 1470 */ 1471static char *loader_get_next_path(char *path) { 1472 uint32_t len; 1473 char *next; 1474 1475 if (path == NULL) 1476 return NULL; 1477 next = strchr(path, PATH_SEPERATOR); 1478 if (next == NULL) { 1479 len = (uint32_t)strlen(path); 1480 next = path + len; 1481 } else { 1482 *next = '\0'; 1483 next++; 1484 } 1485 1486 return next; 1487} 1488 1489/** 1490 * Given a path which is absolute or relative, expand the path if relative or 1491 * leave the path unmodified if absolute. The base path to prepend to relative 1492 * paths is given in rel_base. 1493 * 1494 * \returns 1495 * A string in out_fullpath of the full absolute path 1496 */ 1497static void loader_expand_path(const char *path, const char *rel_base, 1498 size_t out_size, char *out_fullpath) { 1499 if (loader_platform_is_path_absolute(path)) { 1500 // do not prepend a base to an absolute path 1501 rel_base = ""; 1502 } 1503 1504 loader_platform_combine_path(out_fullpath, out_size, rel_base, path, NULL); 1505} 1506 1507/** 1508 * Given a filename (file) and a list of paths (dir), try to find an existing 1509 * file in the paths. If filename already is a path then no 1510 * searching in the given paths. 1511 * 1512 * \returns 1513 * A string in out_fullpath of either the full path or file. 1514 */ 1515static void loader_get_fullpath(const char *file, const char *dirs, 1516 size_t out_size, char *out_fullpath) { 1517 if (!loader_platform_is_path(file) && *dirs) { 1518 char *dirs_copy, *dir, *next_dir; 1519 1520 dirs_copy = loader_stack_alloc(strlen(dirs) + 1); 1521 strcpy(dirs_copy, dirs); 1522 1523 // find if file exists after prepending paths in given list 1524 for (dir = dirs_copy; *dir && (next_dir = loader_get_next_path(dir)); 1525 dir = next_dir) { 1526 loader_platform_combine_path(out_fullpath, out_size, dir, file, 1527 NULL); 1528 if (loader_platform_file_exists(out_fullpath)) { 1529 return; 1530 } 1531 } 1532 } 1533 1534 snprintf(out_fullpath, out_size, "%s", file); 1535} 1536 1537/** 1538 * Read a JSON file into a buffer. 1539 * 1540 * \returns 1541 * A pointer to a cJSON object representing the JSON parse tree. 1542 * This returned buffer should be freed by caller. 1543 */ 1544static cJSON *loader_get_json(const struct loader_instance *inst, 1545 const char *filename) { 1546 FILE *file; 1547 char *json_buf; 1548 cJSON *json; 1549 size_t len; 1550 file = fopen(filename, "rb"); 1551 if (!file) { 1552 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 1553 "Couldn't open JSON file %s", filename); 1554 return NULL; 1555 } 1556 fseek(file, 0, SEEK_END); 1557 len = ftell(file); 1558 fseek(file, 0, SEEK_SET); 1559 json_buf = (char *)loader_stack_alloc(len + 1); 1560 if (json_buf == NULL) { 1561 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 1562 "Out of memory can't get JSON file"); 1563 fclose(file); 1564 return NULL; 1565 } 1566 if (fread(json_buf, sizeof(char), len, file) != len) { 1567 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 1568 "fread failed can't get JSON file"); 1569 fclose(file); 1570 return NULL; 1571 } 1572 fclose(file); 1573 json_buf[len] = '\0'; 1574 1575 // parse text from file 1576 json = cJSON_Parse(json_buf); 1577 if (json == NULL) 1578 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 1579 "Can't parse JSON file %s", filename); 1580 return json; 1581} 1582 1583/** 1584 * Do a deep copy of the loader_layer_properties structure. 1585 */ 1586static void loader_copy_layer_properties(const struct loader_instance *inst, 1587 struct loader_layer_properties *dst, 1588 struct loader_layer_properties *src) { 1589 uint32_t cnt, i; 1590 memcpy(dst, src, sizeof(*src)); 1591 dst->instance_extension_list.list = 1592 loader_heap_alloc(inst, sizeof(VkExtensionProperties) * 1593 src->instance_extension_list.count, 1594 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1595 dst->instance_extension_list.capacity = 1596 sizeof(VkExtensionProperties) * src->instance_extension_list.count; 1597 memcpy(dst->instance_extension_list.list, src->instance_extension_list.list, 1598 dst->instance_extension_list.capacity); 1599 dst->device_extension_list.list = 1600 loader_heap_alloc(inst, sizeof(struct loader_dev_ext_props) * 1601 src->device_extension_list.count, 1602 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1603 1604 dst->device_extension_list.capacity = 1605 sizeof(struct loader_dev_ext_props) * src->device_extension_list.count; 1606 memcpy(dst->device_extension_list.list, src->device_extension_list.list, 1607 dst->device_extension_list.capacity); 1608 if (src->device_extension_list.count > 0 && 1609 src->device_extension_list.list->entrypoint_count > 0) { 1610 cnt = src->device_extension_list.list->entrypoint_count; 1611 dst->device_extension_list.list->entrypoints = loader_heap_alloc( 1612 inst, sizeof(char *) * cnt, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1613 for (i = 0; i < cnt; i++) { 1614 dst->device_extension_list.list->entrypoints[i] = loader_heap_alloc( 1615 inst, 1616 strlen(src->device_extension_list.list->entrypoints[i]) + 1, 1617 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 1618 strcpy(dst->device_extension_list.list->entrypoints[i], 1619 src->device_extension_list.list->entrypoints[i]); 1620 } 1621 } 1622} 1623 1624/** 1625 * Given a cJSON struct (json) of the top level JSON object from layer manifest 1626 * file, add entry to the layer_list. 1627 * Fill out the layer_properties in this list entry from the input cJSON object. 1628 * 1629 * \returns 1630 * void 1631 * layer_list has a new entry and initialized accordingly. 1632 * If the json input object does not have all the required fields no entry 1633 * is added to the list. 1634 */ 1635static void 1636loader_add_layer_properties(const struct loader_instance *inst, 1637 struct loader_layer_list *layer_instance_list, 1638 struct loader_layer_list *layer_device_list, 1639 cJSON *json, bool is_implicit, char *filename) { 1640 /* Fields in layer manifest file that are required: 1641 * (required) “file_format_version” 1642 * following are required in the "layer" object: 1643 * (required) "name" 1644 * (required) "type" 1645 * (required) “library_path” 1646 * (required) “api_version” 1647 * (required) “implementation_version” 1648 * (required) “description” 1649 * (required for implicit layers) “disable_environment” 1650 * 1651 * First get all required items and if any missing abort 1652 */ 1653 1654 cJSON *item, *layer_node, *ext_item; 1655 char *temp; 1656 char *name, *type, *library_path, *api_version; 1657 char *implementation_version, *description; 1658 cJSON *disable_environment; 1659 int i, j; 1660 VkExtensionProperties ext_prop; 1661 item = cJSON_GetObjectItem(json, "file_format_version"); 1662 if (item == NULL) { 1663 return; 1664 } 1665 char *file_vers = cJSON_PrintUnformatted(item); 1666 loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, 1667 "Found manifest file %s, version %s", filename, file_vers); 1668 if (strcmp(file_vers, "\"1.0.0\"") != 0) 1669 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 1670 "Unexpected manifest file version (expected 1.0.0), may " 1671 "cause errors"); 1672 loader_tls_heap_free(file_vers); 1673 1674 layer_node = cJSON_GetObjectItem(json, "layer"); 1675 if (layer_node == NULL) { 1676 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 1677 "Can't find \"layer\" object in manifest JSON file, " 1678 "skipping this file"); 1679 return; 1680 } 1681 1682 // loop through all "layer" objects in the file 1683 do { 1684#define GET_JSON_OBJECT(node, var) \ 1685 { \ 1686 var = cJSON_GetObjectItem(node, #var); \ 1687 if (var == NULL) { \ 1688 layer_node = layer_node->next; \ 1689 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, \ 1690 "Didn't find required layer object %s in manifest " \ 1691 "JSON file, skipping this layer", \ 1692 #var); \ 1693 continue; \ 1694 } \ 1695 } 1696#define GET_JSON_ITEM(node, var) \ 1697 { \ 1698 item = cJSON_GetObjectItem(node, #var); \ 1699 if (item == NULL) { \ 1700 layer_node = layer_node->next; \ 1701 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, \ 1702 "Didn't find required layer value %s in manifest JSON " \ 1703 "file, skipping this layer", \ 1704 #var); \ 1705 continue; \ 1706 } \ 1707 temp = cJSON_Print(item); \ 1708 temp[strlen(temp) - 1] = '\0'; \ 1709 var = loader_stack_alloc(strlen(temp) + 1); \ 1710 strcpy(var, &temp[1]); \ 1711 loader_tls_heap_free(temp); \ 1712 } 1713 GET_JSON_ITEM(layer_node, name) 1714 GET_JSON_ITEM(layer_node, type) 1715 GET_JSON_ITEM(layer_node, library_path) 1716 GET_JSON_ITEM(layer_node, api_version) 1717 GET_JSON_ITEM(layer_node, implementation_version) 1718 GET_JSON_ITEM(layer_node, description) 1719 if (is_implicit) { 1720 GET_JSON_OBJECT(layer_node, disable_environment) 1721 } 1722#undef GET_JSON_ITEM 1723#undef GET_JSON_OBJECT 1724 1725 // add list entry 1726 struct loader_layer_properties *props = NULL; 1727 if (!strcmp(type, "DEVICE")) { 1728 if (layer_device_list == NULL) { 1729 layer_node = layer_node->next; 1730 continue; 1731 } 1732 props = loader_get_next_layer_property(inst, layer_device_list); 1733 props->type = (is_implicit) ? VK_LAYER_TYPE_DEVICE_IMPLICIT 1734 : VK_LAYER_TYPE_DEVICE_EXPLICIT; 1735 } 1736 if (!strcmp(type, "INSTANCE")) { 1737 if (layer_instance_list == NULL) { 1738 layer_node = layer_node->next; 1739 continue; 1740 } 1741 props = loader_get_next_layer_property(inst, layer_instance_list); 1742 props->type = (is_implicit) ? VK_LAYER_TYPE_INSTANCE_IMPLICIT 1743 : VK_LAYER_TYPE_INSTANCE_EXPLICIT; 1744 } 1745 if (!strcmp(type, "GLOBAL")) { 1746 if (layer_instance_list != NULL) 1747 props = 1748 loader_get_next_layer_property(inst, layer_instance_list); 1749 else if (layer_device_list != NULL) 1750 props = loader_get_next_layer_property(inst, layer_device_list); 1751 else { 1752 layer_node = layer_node->next; 1753 continue; 1754 } 1755 props->type = (is_implicit) ? VK_LAYER_TYPE_GLOBAL_IMPLICIT 1756 : VK_LAYER_TYPE_GLOBAL_EXPLICIT; 1757 } 1758 1759 if (props == NULL) { 1760 layer_node = layer_node->next; 1761 continue; 1762 } 1763 1764 strncpy(props->info.layerName, name, sizeof(props->info.layerName)); 1765 props->info.layerName[sizeof(props->info.layerName) - 1] = '\0'; 1766 1767 char *fullpath = props->lib_name; 1768 char *rel_base; 1769 if (loader_platform_is_path(library_path)) { 1770 // a relative or absolute path 1771 char *name_copy = loader_stack_alloc(strlen(filename) + 1); 1772 strcpy(name_copy, filename); 1773 rel_base = loader_platform_dirname(name_copy); 1774 loader_expand_path(library_path, rel_base, MAX_STRING_SIZE, 1775 fullpath); 1776 } else { 1777 // a filename which is assumed in a system directory 1778 loader_get_fullpath(library_path, DEFAULT_VK_LAYERS_PATH, 1779 MAX_STRING_SIZE, fullpath); 1780 } 1781 props->info.specVersion = loader_make_version(api_version); 1782 props->info.implementationVersion = atoi(implementation_version); 1783 strncpy((char *)props->info.description, description, 1784 sizeof(props->info.description)); 1785 props->info.description[sizeof(props->info.description) - 1] = '\0'; 1786 if (is_implicit) { 1787 strncpy(props->disable_env_var.name, 1788 disable_environment->child->string, 1789 sizeof(props->disable_env_var.name)); 1790 props->disable_env_var 1791 .name[sizeof(props->disable_env_var.name) - 1] = '\0'; 1792 strncpy(props->disable_env_var.value, 1793 disable_environment->child->valuestring, 1794 sizeof(props->disable_env_var.value)); 1795 props->disable_env_var 1796 .value[sizeof(props->disable_env_var.value) - 1] = '\0'; 1797 } 1798 1799/** 1800 * Now get all optional items and objects and put in list: 1801 * functions 1802 * instance_extensions 1803 * device_extensions 1804 * enable_environment (implicit layers only) 1805 */ 1806#define GET_JSON_OBJECT(node, var) \ 1807 { var = cJSON_GetObjectItem(node, #var); } 1808#define GET_JSON_ITEM(node, var) \ 1809 { \ 1810 item = cJSON_GetObjectItem(node, #var); \ 1811 if (item != NULL) { \ 1812 temp = cJSON_Print(item); \ 1813 temp[strlen(temp) - 1] = '\0'; \ 1814 var = loader_stack_alloc(strlen(temp) + 1); \ 1815 strcpy(var, &temp[1]); \ 1816 loader_tls_heap_free(temp); \ 1817 } \ 1818 } 1819 1820 cJSON *instance_extensions, *device_extensions, *functions, 1821 *enable_environment; 1822 cJSON *entrypoints; 1823 char *vkGetInstanceProcAddr, *vkGetDeviceProcAddr, *spec_version; 1824 char **entry_array; 1825 vkGetInstanceProcAddr = NULL; 1826 vkGetDeviceProcAddr = NULL; 1827 spec_version = NULL; 1828 entrypoints = NULL; 1829 entry_array = NULL; 1830 /** 1831 * functions 1832 * vkGetInstanceProcAddr 1833 * vkGetDeviceProcAddr 1834 */ 1835 GET_JSON_OBJECT(layer_node, functions) 1836 if (functions != NULL) { 1837 GET_JSON_ITEM(functions, vkGetInstanceProcAddr) 1838 GET_JSON_ITEM(functions, vkGetDeviceProcAddr) 1839 if (vkGetInstanceProcAddr != NULL) 1840 strncpy(props->functions.str_gipa, vkGetInstanceProcAddr, 1841 sizeof(props->functions.str_gipa)); 1842 props->functions.str_gipa[sizeof(props->functions.str_gipa) - 1] = 1843 '\0'; 1844 if (vkGetDeviceProcAddr != NULL) 1845 strncpy(props->functions.str_gdpa, vkGetDeviceProcAddr, 1846 sizeof(props->functions.str_gdpa)); 1847 props->functions.str_gdpa[sizeof(props->functions.str_gdpa) - 1] = 1848 '\0'; 1849 } 1850 /** 1851 * instance_extensions 1852 * array of 1853 * name 1854 * spec_version 1855 */ 1856 GET_JSON_OBJECT(layer_node, instance_extensions) 1857 if (instance_extensions != NULL) { 1858 int count = cJSON_GetArraySize(instance_extensions); 1859 for (i = 0; i < count; i++) { 1860 ext_item = cJSON_GetArrayItem(instance_extensions, i); 1861 GET_JSON_ITEM(ext_item, name) 1862 GET_JSON_ITEM(ext_item, spec_version) 1863 if (name != NULL) { 1864 strncpy(ext_prop.extensionName, name, 1865 sizeof(ext_prop.extensionName)); 1866 ext_prop.extensionName[sizeof(ext_prop.extensionName) - 1] = 1867 '\0'; 1868 } 1869 ext_prop.specVersion = atoi(spec_version); 1870 loader_add_to_ext_list(inst, &props->instance_extension_list, 1, 1871 &ext_prop); 1872 } 1873 } 1874 /** 1875 * device_extensions 1876 * array of 1877 * name 1878 * spec_version 1879 * entrypoints 1880 */ 1881 GET_JSON_OBJECT(layer_node, device_extensions) 1882 if (device_extensions != NULL) { 1883 int count = cJSON_GetArraySize(device_extensions); 1884 for (i = 0; i < count; i++) { 1885 ext_item = cJSON_GetArrayItem(device_extensions, i); 1886 GET_JSON_ITEM(ext_item, name) 1887 GET_JSON_ITEM(ext_item, spec_version) 1888 if (name != NULL) { 1889 strncpy(ext_prop.extensionName, name, 1890 sizeof(ext_prop.extensionName)); 1891 ext_prop.extensionName[sizeof(ext_prop.extensionName) - 1] = 1892 '\0'; 1893 } 1894 ext_prop.specVersion = atoi(spec_version); 1895 // entrypoints = cJSON_GetObjectItem(ext_item, "entrypoints"); 1896 GET_JSON_OBJECT(ext_item, entrypoints) 1897 int entry_count; 1898 if (entrypoints == NULL) { 1899 loader_add_to_dev_ext_list(inst, &props->device_extension_list, 1900 &ext_prop, 0, NULL); 1901 continue; 1902 } 1903 entry_count = cJSON_GetArraySize(entrypoints); 1904 if (entry_count) 1905 entry_array = (char **)loader_stack_alloc(sizeof(char *) * 1906 entry_count); 1907 for (j = 0; j < entry_count; j++) { 1908 ext_item = cJSON_GetArrayItem(entrypoints, j); 1909 if (ext_item != NULL) { 1910 temp = cJSON_Print(ext_item); 1911 temp[strlen(temp) - 1] = '\0'; 1912 entry_array[j] = loader_stack_alloc(strlen(temp) + 1); 1913 strcpy(entry_array[j], &temp[1]); 1914 loader_tls_heap_free(temp); 1915 } 1916 } 1917 loader_add_to_dev_ext_list(inst, &props->device_extension_list, 1918 &ext_prop, entry_count, entry_array); 1919 } 1920 } 1921 if (is_implicit) { 1922 GET_JSON_OBJECT(layer_node, enable_environment) 1923 1924 // enable_environment is optional 1925 if (enable_environment) { 1926 strncpy(props->enable_env_var.name, 1927 enable_environment->child->string, 1928 sizeof(props->enable_env_var.name)); 1929 props->enable_env_var 1930 .name[sizeof(props->enable_env_var.name) - 1] = '\0'; 1931 strncpy(props->enable_env_var.value, 1932 enable_environment->child->valuestring, 1933 sizeof(props->enable_env_var.value)); 1934 props->enable_env_var 1935 .value[sizeof(props->enable_env_var.value) - 1] = '\0'; 1936 } 1937 } 1938#undef GET_JSON_ITEM 1939#undef GET_JSON_OBJECT 1940 // for global layers need to add them to both device and instance list 1941 if (!strcmp(type, "GLOBAL")) { 1942 struct loader_layer_properties *dev_props; 1943 if (layer_instance_list == NULL || layer_device_list == NULL) { 1944 layer_node = layer_node->next; 1945 continue; 1946 } 1947 dev_props = loader_get_next_layer_property(inst, layer_device_list); 1948 // copy into device layer list 1949 loader_copy_layer_properties(inst, dev_props, props); 1950 } 1951 layer_node = layer_node->next; 1952 } while (layer_node != NULL); 1953 return; 1954} 1955 1956/** 1957 * Find the Vulkan library manifest files. 1958 * 1959 * This function scans the location or env_override directories/files 1960 * for a list of JSON manifest files. If env_override is non-NULL 1961 * and has a valid value. Then the location is ignored. Otherwise 1962 * location is used to look for manifest files. The location 1963 * is interpreted as Registry path on Windows and a directory path(s) 1964 * on Linux. 1965 * 1966 * \returns 1967 * A string list of manifest files to be opened in out_files param. 1968 * List has a pointer to string for each manifest filename. 1969 * When done using the list in out_files, pointers should be freed. 1970 * Location or override string lists can be either files or directories as 1971 *follows: 1972 * | location | override 1973 * -------------------------------- 1974 * Win ICD | files | files 1975 * Win Layer | files | dirs 1976 * Linux ICD | dirs | files 1977 * Linux Layer| dirs | dirs 1978 */ 1979static void loader_get_manifest_files(const struct loader_instance *inst, 1980 const char *env_override, bool is_layer, 1981 const char *location, 1982 struct loader_manifest_files *out_files) { 1983 char *override = NULL; 1984 char *loc; 1985 char *file, *next_file, *name; 1986 size_t alloced_count = 64; 1987 char full_path[2048]; 1988 DIR *sysdir = NULL; 1989 bool list_is_dirs = false; 1990 struct dirent *dent; 1991 1992 out_files->count = 0; 1993 out_files->filename_list = NULL; 1994 1995 if (env_override != NULL && (override = loader_getenv(env_override))) { 1996#if !defined(_WIN32) 1997 if (geteuid() != getuid()) { 1998 /* Don't allow setuid apps to use the env var: */ 1999 loader_free_getenv(override); 2000 override = NULL; 2001 } 2002#endif 2003 } 2004 2005 if (location == NULL) { 2006 loader_log( 2007 inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2008 "Can't get manifest files with NULL location, env_override=%s", 2009 env_override); 2010 return; 2011 } 2012 2013#if defined(_WIN32) 2014 list_is_dirs = (is_layer && override != NULL) ? true : false; 2015#else 2016 list_is_dirs = (override == NULL || is_layer) ? true : false; 2017#endif 2018 // Make a copy of the input we are using so it is not modified 2019 // Also handle getting the location(s) from registry on Windows 2020 if (override == NULL) { 2021 loc = loader_stack_alloc(strlen(location) + 1); 2022 if (loc == NULL) { 2023 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2024 "Out of memory can't get manifest files"); 2025 return; 2026 } 2027 strcpy(loc, location); 2028#if defined(_WIN32) 2029 loc = loader_get_registry_files(inst, loc); 2030 if (loc == NULL) { 2031 if (!is_layer) { 2032 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2033 "Registry lookup failed can't get ICD manifest " 2034 "files, do you have a Vulkan driver installed"); 2035 } else { 2036 // warning only for layers 2037 loader_log( 2038 inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 2039 "Registry lookup failed can't get layer manifest files"); 2040 } 2041 return; 2042 } 2043#endif 2044 } else { 2045 loc = loader_stack_alloc(strlen(override) + 1); 2046 if (loc == NULL) { 2047 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2048 "Out of memory can't get manifest files"); 2049 return; 2050 } 2051 strcpy(loc, override); 2052 loader_free_getenv(override); 2053 } 2054 2055 // Print out the paths being searched if debugging is enabled 2056 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, 2057 "Searching the following paths for manifest files: %s\n", loc); 2058 2059 file = loc; 2060 while (*file) { 2061 next_file = loader_get_next_path(file); 2062 if (list_is_dirs) { 2063 sysdir = opendir(file); 2064 name = NULL; 2065 if (sysdir) { 2066 dent = readdir(sysdir); 2067 if (dent == NULL) 2068 break; 2069 name = &(dent->d_name[0]); 2070 loader_get_fullpath(name, file, sizeof(full_path), full_path); 2071 name = full_path; 2072 } 2073 } else { 2074#if defined(_WIN32) 2075 name = file; 2076#else 2077 // only Linux has relative paths 2078 char *dir; 2079 // make a copy of location so it isn't modified 2080 dir = loader_stack_alloc(strlen(loc) + 1); 2081 if (dir == NULL) { 2082 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2083 "Out of memory can't get manifest files"); 2084 return; 2085 } 2086 strcpy(dir, loc); 2087 2088 loader_get_fullpath(file, dir, sizeof(full_path), full_path); 2089 2090 name = full_path; 2091#endif 2092 } 2093 while (name) { 2094 /* Look for files ending with ".json" suffix */ 2095 uint32_t nlen = (uint32_t)strlen(name); 2096 const char *suf = name + nlen - 5; 2097 if ((nlen > 5) && !strncmp(suf, ".json", 5)) { 2098 if (out_files->count == 0) { 2099 out_files->filename_list = 2100 loader_heap_alloc(inst, alloced_count * sizeof(char *), 2101 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 2102 } else if (out_files->count == alloced_count) { 2103 out_files->filename_list = 2104 loader_heap_realloc(inst, out_files->filename_list, 2105 alloced_count * sizeof(char *), 2106 alloced_count * sizeof(char *) * 2, 2107 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 2108 alloced_count *= 2; 2109 } 2110 if (out_files->filename_list == NULL) { 2111 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2112 "Out of memory can't alloc manifest file list"); 2113 return; 2114 } 2115 out_files->filename_list[out_files->count] = loader_heap_alloc( 2116 inst, strlen(name) + 1, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 2117 if (out_files->filename_list[out_files->count] == NULL) { 2118 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2119 "Out of memory can't get manifest files"); 2120 return; 2121 } 2122 strcpy(out_files->filename_list[out_files->count], name); 2123 out_files->count++; 2124 } else if (!list_is_dirs) { 2125 loader_log( 2126 inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 2127 "Skipping manifest file %s, file name must end in .json", 2128 name); 2129 } 2130 if (list_is_dirs) { 2131 dent = readdir(sysdir); 2132 if (dent == NULL) 2133 break; 2134 name = &(dent->d_name[0]); 2135 loader_get_fullpath(name, file, sizeof(full_path), full_path); 2136 name = full_path; 2137 } else { 2138 break; 2139 } 2140 } 2141 if (sysdir) 2142 closedir(sysdir); 2143 file = next_file; 2144 } 2145 return; 2146} 2147 2148void loader_init_icd_lib_list() {} 2149 2150void loader_destroy_icd_lib_list() {} 2151/** 2152 * Try to find the Vulkan ICD driver(s). 2153 * 2154 * This function scans the default system loader path(s) or path 2155 * specified by the \c VK_ICD_FILENAMES environment variable in 2156 * order to find loadable VK ICDs manifest files. From these 2157 * manifest files it finds the ICD libraries. 2158 * 2159 * \returns 2160 * a list of icds that were discovered 2161 */ 2162void loader_icd_scan(const struct loader_instance *inst, 2163 struct loader_icd_libs *icds) { 2164 char *file_str; 2165 struct loader_manifest_files manifest_files; 2166 2167 loader_scanned_icd_init(inst, icds); 2168 // Get a list of manifest files for ICDs 2169 loader_get_manifest_files(inst, "VK_ICD_FILENAMES", false, 2170 DEFAULT_VK_DRIVERS_INFO, &manifest_files); 2171 if (manifest_files.count == 0) 2172 return; 2173 loader_platform_thread_lock_mutex(&loader_json_lock); 2174 for (uint32_t i = 0; i < manifest_files.count; i++) { 2175 file_str = manifest_files.filename_list[i]; 2176 if (file_str == NULL) 2177 continue; 2178 2179 cJSON *json; 2180 json = loader_get_json(inst, file_str); 2181 if (!json) 2182 continue; 2183 cJSON *item, *itemICD; 2184 item = cJSON_GetObjectItem(json, "file_format_version"); 2185 if (item == NULL) { 2186 loader_platform_thread_unlock_mutex(&loader_json_lock); 2187 return; 2188 } 2189 char *file_vers = cJSON_Print(item); 2190 loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, 2191 "Found manifest file %s, version %s", file_str, file_vers); 2192 if (strcmp(file_vers, "\"1.0.0\"") != 0) 2193 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 2194 "Unexpected manifest file version (expected 1.0.0), may " 2195 "cause errors"); 2196 loader_tls_heap_free(file_vers); 2197 itemICD = cJSON_GetObjectItem(json, "ICD"); 2198 if (itemICD != NULL) { 2199 item = cJSON_GetObjectItem(itemICD, "library_path"); 2200 if (item != NULL) { 2201 char *temp = cJSON_Print(item); 2202 if (!temp || strlen(temp) == 0) { 2203 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 2204 "Can't find \"library_path\" in ICD JSON file " 2205 "%s, skipping", 2206 file_str); 2207 loader_tls_heap_free(temp); 2208 loader_heap_free(inst, file_str); 2209 cJSON_Delete(json); 2210 continue; 2211 } 2212 // strip out extra quotes 2213 temp[strlen(temp) - 1] = '\0'; 2214 char *library_path = loader_stack_alloc(strlen(temp) + 1); 2215 strcpy(library_path, &temp[1]); 2216 loader_tls_heap_free(temp); 2217 if (!library_path || strlen(library_path) == 0) { 2218 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 2219 "Can't find \"library_path\" in ICD JSON file " 2220 "%s, skipping", 2221 file_str); 2222 loader_heap_free(inst, file_str); 2223 cJSON_Delete(json); 2224 continue; 2225 } 2226 char fullpath[MAX_STRING_SIZE]; 2227 // Print out the paths being searched if debugging is enabled 2228 loader_log( 2229 inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, 2230 "Searching for ICD drivers named %s default dir %s\n", 2231 library_path, DEFAULT_VK_DRIVERS_PATH); 2232 if (loader_platform_is_path(library_path)) { 2233 // a relative or absolute path 2234 char *name_copy = loader_stack_alloc(strlen(file_str) + 1); 2235 char *rel_base; 2236 strcpy(name_copy, file_str); 2237 rel_base = loader_platform_dirname(name_copy); 2238 loader_expand_path(library_path, rel_base, sizeof(fullpath), 2239 fullpath); 2240 } else { 2241 // a filename which is assumed in a system directory 2242 loader_get_fullpath(library_path, DEFAULT_VK_DRIVERS_PATH, 2243 sizeof(fullpath), fullpath); 2244 } 2245 2246 uint32_t vers = 0; 2247 item = cJSON_GetObjectItem(itemICD, "api_version"); 2248 if (item != NULL) { 2249 temp = cJSON_Print(item); 2250 vers = loader_make_version(temp); 2251 loader_tls_heap_free(temp); 2252 } 2253 loader_scanned_icd_add(inst, icds, fullpath, vers); 2254 } else 2255 loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 2256 "Can't find \"library_path\" object in ICD JSON " 2257 "file %s, skipping", 2258 file_str); 2259 } else 2260 loader_log( 2261 inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, 2262 "Can't find \"ICD\" object in ICD JSON file %s, skipping", 2263 file_str); 2264 2265 loader_heap_free(inst, file_str); 2266 cJSON_Delete(json); 2267 } 2268 loader_heap_free(inst, manifest_files.filename_list); 2269 loader_platform_thread_unlock_mutex(&loader_json_lock); 2270} 2271 2272void loader_layer_scan(const struct loader_instance *inst, 2273 struct loader_layer_list *instance_layers, 2274 struct loader_layer_list *device_layers) { 2275 char *file_str; 2276 struct loader_manifest_files 2277 manifest_files[2]; // [0] = explicit, [1] = implicit 2278 cJSON *json; 2279 uint32_t i; 2280 uint32_t implicit; 2281 2282 // Get a list of manifest files for layers 2283 loader_get_manifest_files(inst, LAYERS_PATH_ENV, true, 2284 DEFAULT_VK_ELAYERS_INFO, &manifest_files[0]); 2285 // Pass NULL for environment variable override - implicit layers are not 2286 // overridden by LAYERS_PATH_ENV 2287 loader_get_manifest_files(inst, NULL, true, DEFAULT_VK_ILAYERS_INFO, 2288 &manifest_files[1]); 2289 if (manifest_files[0].count == 0 && manifest_files[1].count == 0) 2290 return; 2291 2292#if 0 // TODO 2293 /** 2294 * We need a list of the layer libraries, not just a list of 2295 * the layer properties (a layer library could expose more than 2296 * one layer property). This list of scanned layers would be 2297 * used to check for global and physicaldevice layer properties. 2298 */ 2299 if (!loader_init_layer_library_list(&loader.scanned_layer_libraries)) { 2300 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2301 "Alloc for layer list failed: %s line: %d", __FILE__, __LINE__); 2302 return; 2303 } 2304#endif 2305 2306 /* cleanup any previously scanned libraries */ 2307 loader_delete_layer_properties(inst, instance_layers); 2308 loader_delete_layer_properties(inst, device_layers); 2309 2310 loader_platform_thread_lock_mutex(&loader_json_lock); 2311 for (implicit = 0; implicit < 2; implicit++) { 2312 for (i = 0; i < manifest_files[implicit].count; i++) { 2313 file_str = manifest_files[implicit].filename_list[i]; 2314 if (file_str == NULL) 2315 continue; 2316 2317 // parse file into JSON struct 2318 json = loader_get_json(inst, file_str); 2319 if (!json) { 2320 continue; 2321 } 2322 2323 // TODO error if device layers expose instance_extensions 2324 // TODO error if instance layers expose device extensions 2325 loader_add_layer_properties(inst, instance_layers, device_layers, 2326 json, (implicit == 1), file_str); 2327 2328 loader_heap_free(inst, file_str); 2329 cJSON_Delete(json); 2330 } 2331 } 2332 if (manifest_files[0].count != 0) 2333 loader_heap_free(inst, manifest_files[0].filename_list); 2334 2335 if (manifest_files[1].count != 0) 2336 loader_heap_free(inst, manifest_files[1].filename_list); 2337 loader_platform_thread_unlock_mutex(&loader_json_lock); 2338} 2339 2340static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL 2341loader_gpa_instance_internal(VkInstance inst, const char *pName) { 2342 if (!strcmp(pName, "vkGetInstanceProcAddr")) 2343 return (void *)loader_gpa_instance_internal; 2344 if (!strcmp(pName, "vkCreateInstance")) 2345 return (void *)loader_CreateInstance; 2346 if (!strcmp(pName, "vkCreateDevice")) 2347 return (void *)loader_create_device_terminator; 2348 2349 // inst is not wrapped 2350 if (inst == VK_NULL_HANDLE) { 2351 return NULL; 2352 } 2353 VkLayerInstanceDispatchTable *disp_table = 2354 *(VkLayerInstanceDispatchTable **)inst; 2355 void *addr; 2356 2357 if (disp_table == NULL) 2358 return NULL; 2359 2360 addr = loader_lookup_instance_dispatch_table(disp_table, pName); 2361 if (addr) { 2362 return addr; 2363 } 2364 2365 if (disp_table->GetInstanceProcAddr == NULL) { 2366 return NULL; 2367 } 2368 return disp_table->GetInstanceProcAddr(inst, pName); 2369} 2370 2371/** 2372 * Initialize device_ext dispatch table entry as follows: 2373 * If dev == NULL find all logical devices created within this instance and 2374 * init the entry (given by idx) in the ext dispatch table. 2375 * If dev != NULL only initialize the entry in the given dev's dispatch table. 2376 * The initialization value is gotten by calling down the device chain with 2377 * GDPA. 2378 * If GDPA returns NULL then don't initialize the dispatch table entry. 2379 */ 2380static void loader_init_dispatch_dev_ext_entry(struct loader_instance *inst, 2381 struct loader_device *dev, 2382 uint32_t idx, 2383 const char *funcName) 2384 2385{ 2386 void *gdpa_value; 2387 if (dev != NULL) { 2388 gdpa_value = dev->loader_dispatch.core_dispatch.GetDeviceProcAddr( 2389 dev->device, funcName); 2390 if (gdpa_value != NULL) 2391 dev->loader_dispatch.ext_dispatch.DevExt[idx] = 2392 (PFN_vkDevExt)gdpa_value; 2393 } else { 2394 for (uint32_t i = 0; i < inst->total_icd_count; i++) { 2395 struct loader_icd *icd = &inst->icds[i]; 2396 struct loader_device *dev = icd->logical_device_list; 2397 while (dev) { 2398 gdpa_value = 2399 dev->loader_dispatch.core_dispatch.GetDeviceProcAddr( 2400 dev->device, funcName); 2401 if (gdpa_value != NULL) 2402 dev->loader_dispatch.ext_dispatch.DevExt[idx] = 2403 (PFN_vkDevExt)gdpa_value; 2404 dev = dev->next; 2405 } 2406 } 2407 } 2408} 2409 2410/** 2411 * Find all dev extension in the hash table and initialize the dispatch table 2412 * for dev for each of those extension entrypoints found in hash table. 2413 2414 */ 2415static void loader_init_dispatch_dev_ext(struct loader_instance *inst, 2416 struct loader_device *dev) { 2417 for (uint32_t i = 0; i < MAX_NUM_DEV_EXTS; i++) { 2418 if (inst->disp_hash[i].func_name != NULL) 2419 loader_init_dispatch_dev_ext_entry(inst, dev, i, 2420 inst->disp_hash[i].func_name); 2421 } 2422} 2423 2424static bool loader_check_icds_for_address(struct loader_instance *inst, 2425 const char *funcName) { 2426 struct loader_icd *icd; 2427 icd = inst->icds; 2428 while (icd) { 2429 if (icd->this_icd_lib->GetInstanceProcAddr(icd->instance, funcName)) 2430 // this icd supports funcName 2431 return true; 2432 icd = icd->next; 2433 } 2434 2435 return false; 2436} 2437 2438static void loader_free_dev_ext_table(struct loader_instance *inst) { 2439 for (uint32_t i = 0; i < MAX_NUM_DEV_EXTS; i++) { 2440 loader_heap_free(inst, inst->disp_hash[i].func_name); 2441 loader_heap_free(inst, inst->disp_hash[i].list.index); 2442 } 2443 memset(inst->disp_hash, 0, sizeof(inst->disp_hash)); 2444} 2445 2446static bool loader_add_dev_ext_table(struct loader_instance *inst, 2447 uint32_t *ptr_idx, const char *funcName) { 2448 uint32_t i; 2449 uint32_t idx = *ptr_idx; 2450 struct loader_dispatch_hash_list *list = &inst->disp_hash[idx].list; 2451 2452 if (!inst->disp_hash[idx].func_name) { 2453 // no entry here at this idx, so use it 2454 assert(list->capacity == 0); 2455 inst->disp_hash[idx].func_name = (char *)loader_heap_alloc( 2456 inst, strlen(funcName) + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 2457 if (inst->disp_hash[idx].func_name == NULL) { 2458 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2459 "loader_add_dev_ext_table() can't allocate memory for " 2460 "func_name"); 2461 return false; 2462 } 2463 strncpy(inst->disp_hash[idx].func_name, funcName, strlen(funcName) + 1); 2464 return true; 2465 } 2466 2467 // check for enough capacity 2468 if (list->capacity == 0) { 2469 list->index = loader_heap_alloc(inst, 8 * sizeof(*(list->index)), 2470 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 2471 if (list->index == NULL) { 2472 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2473 "loader_add_dev_ext_table() can't allocate list memory"); 2474 return false; 2475 } 2476 list->capacity = 8 * sizeof(*(list->index)); 2477 } else if (list->capacity < (list->count + 1) * sizeof(*(list->index))) { 2478 list->index = loader_heap_realloc(inst, list->index, list->capacity, 2479 list->capacity * 2, 2480 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 2481 if (list->index == NULL) { 2482 loader_log( 2483 inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2484 "loader_add_dev_ext_table() can't reallocate list memory"); 2485 return false; 2486 } 2487 list->capacity *= 2; 2488 } 2489 2490 // find an unused index in the hash table and use it 2491 i = (idx + 1) % MAX_NUM_DEV_EXTS; 2492 do { 2493 if (!inst->disp_hash[i].func_name) { 2494 assert(inst->disp_hash[i].list.capacity == 0); 2495 inst->disp_hash[i].func_name = 2496 (char *)loader_heap_alloc(inst, strlen(funcName) + 1, 2497 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 2498 if (inst->disp_hash[i].func_name == NULL) { 2499 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2500 "loader_add_dev_ext_table() can't rallocate " 2501 "func_name memory"); 2502 return false; 2503 } 2504 strncpy(inst->disp_hash[i].func_name, funcName, 2505 strlen(funcName) + 1); 2506 list->index[list->count] = i; 2507 list->count++; 2508 *ptr_idx = i; 2509 return true; 2510 } 2511 i = (i + 1) % MAX_NUM_DEV_EXTS; 2512 } while (i != idx); 2513 2514 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2515 "loader_add_dev_ext_table() couldn't insert into hash table; is " 2516 "it full?"); 2517 return false; 2518} 2519 2520static bool loader_name_in_dev_ext_table(struct loader_instance *inst, 2521 uint32_t *idx, const char *funcName) { 2522 uint32_t alt_idx; 2523 if (inst->disp_hash[*idx].func_name && 2524 !strcmp(inst->disp_hash[*idx].func_name, funcName)) 2525 return true; 2526 2527 // funcName wasn't at the primary spot in the hash table 2528 // search the list of secondary locations (shallow search, not deep search) 2529 for (uint32_t i = 0; i < inst->disp_hash[*idx].list.count; i++) { 2530 alt_idx = inst->disp_hash[*idx].list.index[i]; 2531 if (!strcmp(inst->disp_hash[*idx].func_name, funcName)) { 2532 *idx = alt_idx; 2533 return true; 2534 } 2535 } 2536 2537 return false; 2538} 2539 2540/** 2541 * This function returns generic trampoline code address for unknown entry 2542 * points. 2543 * Presumably, these unknown entry points (as given by funcName) are device 2544 * extension entrypoints. A hash table is used to keep a list of unknown entry 2545 * points and their mapping to the device extension dispatch table 2546 * (struct loader_dev_ext_dispatch_table). 2547 * \returns 2548 * For a given entry point string (funcName), if an existing mapping is found 2549 * the 2550 * trampoline address for that mapping is returned. Otherwise, this unknown 2551 * entry point 2552 * has not been seen yet. Next check if a layer or ICD supports it. If so then 2553 * a 2554 * new entry in the hash table is initialized and that trampoline address for 2555 * the new entry is returned. Null is returned if the hash table is full or 2556 * if no discovered layer or ICD returns a non-NULL GetProcAddr for it. 2557 */ 2558void *loader_dev_ext_gpa(struct loader_instance *inst, const char *funcName) { 2559 uint32_t idx; 2560 uint32_t seed = 0; 2561 2562 idx = murmurhash(funcName, strlen(funcName), seed) % MAX_NUM_DEV_EXTS; 2563 2564 if (loader_name_in_dev_ext_table(inst, &idx, funcName)) 2565 // found funcName already in hash 2566 return loader_get_dev_ext_trampoline(idx); 2567 2568 // Check if funcName is supported in either ICDs or a layer library 2569 if (!loader_check_icds_for_address(inst, funcName)) { 2570 // TODO Add check in layer libraries for support of address 2571 // if support found in layers continue on 2572 return NULL; 2573 } 2574 2575 if (loader_add_dev_ext_table(inst, &idx, funcName)) { 2576 // successfully added new table entry 2577 // init any dev dispatch table entrys as needed 2578 loader_init_dispatch_dev_ext_entry(inst, NULL, idx, funcName); 2579 return loader_get_dev_ext_trampoline(idx); 2580 } 2581 2582 return NULL; 2583} 2584 2585struct loader_instance *loader_get_instance(const VkInstance instance) { 2586 /* look up the loader_instance in our list by comparing dispatch tables, as 2587 * there is no guarantee the instance is still a loader_instance* after any 2588 * layers which wrap the instance object. 2589 */ 2590 const VkLayerInstanceDispatchTable *disp; 2591 struct loader_instance *ptr_instance = NULL; 2592 disp = loader_get_instance_dispatch(instance); 2593 for (struct loader_instance *inst = loader.instances; inst; 2594 inst = inst->next) { 2595 if (inst->disp == disp) { 2596 ptr_instance = inst; 2597 break; 2598 } 2599 } 2600 return ptr_instance; 2601} 2602 2603static loader_platform_dl_handle 2604loader_add_layer_lib(const struct loader_instance *inst, const char *chain_type, 2605 struct loader_layer_properties *layer_prop) { 2606 struct loader_lib_info *new_layer_lib_list, *my_lib; 2607 size_t new_alloc_size; 2608 /* 2609 * TODO: We can now track this information in the 2610 * scanned_layer_libraries list. 2611 */ 2612 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) { 2613 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, 2614 layer_prop->lib_name) == 0) { 2615 /* Have already loaded this library, just increment ref count */ 2616 loader.loaded_layer_lib_list[i].ref_count++; 2617 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, 2618 "%s Chain: Increment layer reference count for layer " 2619 "library %s", 2620 chain_type, layer_prop->lib_name); 2621 return loader.loaded_layer_lib_list[i].lib_handle; 2622 } 2623 } 2624 2625 /* Haven't seen this library so load it */ 2626 new_alloc_size = 0; 2627 if (loader.loaded_layer_lib_capacity == 0) 2628 new_alloc_size = 8 * sizeof(struct loader_lib_info); 2629 else if (loader.loaded_layer_lib_capacity <= 2630 loader.loaded_layer_lib_count * sizeof(struct loader_lib_info)) 2631 new_alloc_size = loader.loaded_layer_lib_capacity * 2; 2632 2633 if (new_alloc_size) { 2634 new_layer_lib_list = loader_heap_realloc( 2635 inst, loader.loaded_layer_lib_list, 2636 loader.loaded_layer_lib_capacity, new_alloc_size, 2637 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 2638 if (!new_layer_lib_list) { 2639 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2640 "loader: realloc failed in loader_add_layer_lib"); 2641 return NULL; 2642 } 2643 loader.loaded_layer_lib_capacity = new_alloc_size; 2644 loader.loaded_layer_lib_list = new_layer_lib_list; 2645 } else 2646 new_layer_lib_list = loader.loaded_layer_lib_list; 2647 my_lib = &new_layer_lib_list[loader.loaded_layer_lib_count]; 2648 2649 strncpy(my_lib->lib_name, layer_prop->lib_name, sizeof(my_lib->lib_name)); 2650 my_lib->lib_name[sizeof(my_lib->lib_name) - 1] = '\0'; 2651 my_lib->ref_count = 0; 2652 my_lib->lib_handle = NULL; 2653 2654 if ((my_lib->lib_handle = loader_platform_open_library(my_lib->lib_name)) == 2655 NULL) { 2656 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2657 loader_platform_open_library_error(my_lib->lib_name)); 2658 return NULL; 2659 } else { 2660 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, 2661 "Chain: %s: Loading layer library %s", chain_type, 2662 layer_prop->lib_name); 2663 } 2664 loader.loaded_layer_lib_count++; 2665 my_lib->ref_count++; 2666 2667 return my_lib->lib_handle; 2668} 2669 2670static void 2671loader_remove_layer_lib(struct loader_instance *inst, 2672 struct loader_layer_properties *layer_prop) { 2673 uint32_t idx = loader.loaded_layer_lib_count; 2674 struct loader_lib_info *new_layer_lib_list, *my_lib = NULL; 2675 2676 for (uint32_t i = 0; i < loader.loaded_layer_lib_count; i++) { 2677 if (strcmp(loader.loaded_layer_lib_list[i].lib_name, 2678 layer_prop->lib_name) == 0) { 2679 /* found matching library */ 2680 idx = i; 2681 my_lib = &loader.loaded_layer_lib_list[i]; 2682 break; 2683 } 2684 } 2685 2686 if (idx == loader.loaded_layer_lib_count) { 2687 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2688 "Unable to unref library %s", layer_prop->lib_name); 2689 return; 2690 } 2691 2692 if (my_lib) { 2693 my_lib->ref_count--; 2694 if (my_lib->ref_count > 0) { 2695 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, 2696 "Decrement reference count for layer library %s", 2697 layer_prop->lib_name); 2698 return; 2699 } 2700 } 2701 loader_platform_close_library(my_lib->lib_handle); 2702 loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, 2703 "Unloading layer library %s", layer_prop->lib_name); 2704 2705 /* Need to remove unused library from list */ 2706 new_layer_lib_list = 2707 loader_heap_alloc(inst, loader.loaded_layer_lib_capacity, 2708 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 2709 if (!new_layer_lib_list) { 2710 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2711 "loader: heap alloc failed loader_remove_layer_library"); 2712 return; 2713 } 2714 2715 if (idx > 0) { 2716 /* Copy records before idx */ 2717 memcpy(new_layer_lib_list, &loader.loaded_layer_lib_list[0], 2718 sizeof(struct loader_lib_info) * idx); 2719 } 2720 if (idx < (loader.loaded_layer_lib_count - 1)) { 2721 /* Copy records after idx */ 2722 memcpy(&new_layer_lib_list[idx], &loader.loaded_layer_lib_list[idx + 1], 2723 sizeof(struct loader_lib_info) * 2724 (loader.loaded_layer_lib_count - idx - 1)); 2725 } 2726 2727 loader_heap_free(inst, loader.loaded_layer_lib_list); 2728 loader.loaded_layer_lib_count--; 2729 loader.loaded_layer_lib_list = new_layer_lib_list; 2730} 2731 2732/** 2733 * Go through the search_list and find any layers which match type. If layer 2734 * type match is found in then add it to ext_list. 2735 */ 2736static void 2737loader_add_layer_implicit(const struct loader_instance *inst, 2738 const enum layer_type type, 2739 struct loader_layer_list *list, 2740 const struct loader_layer_list *search_list) { 2741 bool enable; 2742 char *env_value; 2743 uint32_t i; 2744 for (i = 0; i < search_list->count; i++) { 2745 const struct loader_layer_properties *prop = &search_list->list[i]; 2746 if (prop->type & type) { 2747 /* Found an implicit layer, see if it should be enabled */ 2748 enable = false; 2749 2750 // if no enable_environment variable is specified, this implicit 2751 // layer 2752 // should always be enabled. Otherwise check if the variable is set 2753 if (prop->enable_env_var.name[0] == 0) { 2754 enable = true; 2755 } else { 2756 env_value = loader_getenv(prop->enable_env_var.name); 2757 if (env_value && !strcmp(prop->enable_env_var.value, env_value)) 2758 enable = true; 2759 loader_free_getenv(env_value); 2760 } 2761 2762 // disable_environment has priority, i.e. if both enable and disable 2763 // environment variables are set, the layer is disabled. Implicit 2764 // layers 2765 // are required to have a disable_environment variables 2766 env_value = loader_getenv(prop->disable_env_var.name); 2767 if (env_value) 2768 enable = false; 2769 loader_free_getenv(env_value); 2770 2771 if (enable) 2772 loader_add_to_layer_list(inst, list, 1, prop); 2773 } 2774 } 2775} 2776 2777/** 2778 * Get the layer name(s) from the env_name environment variable. If layer 2779 * is found in search_list then add it to layer_list. But only add it to 2780 * layer_list if type matches. 2781 */ 2782static void loader_add_layer_env(const struct loader_instance *inst, 2783 const enum layer_type type, 2784 const char *env_name, 2785 struct loader_layer_list *layer_list, 2786 const struct loader_layer_list *search_list) { 2787 char *layerEnv; 2788 char *next, *name; 2789 2790 layerEnv = loader_getenv(env_name); 2791 if (layerEnv == NULL) { 2792 return; 2793 } 2794 name = loader_stack_alloc(strlen(layerEnv) + 1); 2795 if (name == NULL) { 2796 return; 2797 } 2798 strcpy(name, layerEnv); 2799 2800 loader_free_getenv(layerEnv); 2801 2802 while (name && *name) { 2803 next = loader_get_next_path(name); 2804 loader_find_layer_name_add_list(inst, name, type, search_list, 2805 layer_list); 2806 name = next; 2807 } 2808 2809 return; 2810} 2811 2812void loader_deactivate_instance_layers(struct loader_instance *instance) { 2813 /* Create instance chain of enabled layers */ 2814 for (uint32_t i = 0; i < instance->activated_layer_list.count; i++) { 2815 struct loader_layer_properties *layer_prop = 2816 &instance->activated_layer_list.list[i]; 2817 2818 loader_remove_layer_lib(instance, layer_prop); 2819 } 2820 loader_destroy_layer_list(instance, &instance->activated_layer_list); 2821} 2822 2823VkResult 2824loader_enable_instance_layers(struct loader_instance *inst, 2825 const VkInstanceCreateInfo *pCreateInfo, 2826 const struct loader_layer_list *instance_layers) { 2827 VkResult err; 2828 2829 assert(inst && "Cannot have null instance"); 2830 2831 if (!loader_init_layer_list(inst, &inst->activated_layer_list)) { 2832 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2833 "Failed to alloc Instance activated layer list"); 2834 return VK_ERROR_OUT_OF_HOST_MEMORY; 2835 } 2836 2837 /* Add any implicit layers first */ 2838 loader_add_layer_implicit(inst, VK_LAYER_TYPE_INSTANCE_IMPLICIT, 2839 &inst->activated_layer_list, instance_layers); 2840 2841 /* Add any layers specified via environment variable next */ 2842 loader_add_layer_env(inst, VK_LAYER_TYPE_INSTANCE_EXPLICIT, 2843 "VK_INSTANCE_LAYERS", &inst->activated_layer_list, 2844 instance_layers); 2845 2846 /* Add layers specified by the application */ 2847 err = loader_add_layer_names_to_list( 2848 inst, &inst->activated_layer_list, pCreateInfo->enabledLayerCount, 2849 pCreateInfo->ppEnabledLayerNames, instance_layers); 2850 2851 return err; 2852} 2853 2854/* 2855 * Given the list of layers to activate in the loader_instance 2856 * structure. This function will add a VkLayerInstanceCreateInfo 2857 * structure to the VkInstanceCreateInfo.pNext pointer. 2858 * Each activated layer will have it's own VkLayerInstanceLink 2859 * structure that tells the layer what Get*ProcAddr to call to 2860 * get function pointers to the next layer down. 2861 * Once the chain info has been created this function will 2862 * execute the CreateInstance call chain. Each layer will 2863 * then have an opportunity in it's CreateInstance function 2864 * to setup it's dispatch table when the lower layer returns 2865 * successfully. 2866 * Each layer can wrap or not-wrap the returned VkInstance object 2867 * as it sees fit. 2868 * The instance chain is terminated by a loader function 2869 * that will call CreateInstance on all available ICD's and 2870 * cache those VkInstance objects for future use. 2871 */ 2872VkResult loader_create_instance_chain(const VkInstanceCreateInfo *pCreateInfo, 2873 const VkAllocationCallbacks *pAllocator, 2874 struct loader_instance *inst, 2875 VkInstance *created_instance) { 2876 uint32_t activated_layers = 0; 2877 VkLayerInstanceCreateInfo chain_info; 2878 VkLayerInstanceLink *layer_instance_link_info = NULL; 2879 VkInstanceCreateInfo loader_create_info; 2880 VkResult res; 2881 2882 PFN_vkGetInstanceProcAddr nextGIPA = loader_gpa_instance_internal; 2883 PFN_vkGetInstanceProcAddr fpGIPA = loader_gpa_instance_internal; 2884 2885 memcpy(&loader_create_info, pCreateInfo, sizeof(VkInstanceCreateInfo)); 2886 2887 if (inst->activated_layer_list.count > 0) { 2888 2889 chain_info.u.pLayerInfo = NULL; 2890 chain_info.pNext = pCreateInfo->pNext; 2891 chain_info.sType = VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO; 2892 chain_info.function = VK_LAYER_LINK_INFO; 2893 loader_create_info.pNext = &chain_info; 2894 2895 layer_instance_link_info = loader_stack_alloc( 2896 sizeof(VkLayerInstanceLink) * inst->activated_layer_list.count); 2897 if (!layer_instance_link_info) { 2898 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2899 "Failed to alloc Instance objects for layer"); 2900 return VK_ERROR_OUT_OF_HOST_MEMORY; 2901 } 2902 2903 /* Create instance chain of enabled layers */ 2904 for (int32_t i = inst->activated_layer_list.count - 1; i >= 0; i--) { 2905 struct loader_layer_properties *layer_prop = 2906 &inst->activated_layer_list.list[i]; 2907 loader_platform_dl_handle lib_handle; 2908 2909 lib_handle = loader_add_layer_lib(inst, "instance", layer_prop); 2910 if (!lib_handle) 2911 continue; 2912 if ((fpGIPA = layer_prop->functions.get_instance_proc_addr) == 2913 NULL) { 2914 if (layer_prop->functions.str_gipa == NULL || 2915 strlen(layer_prop->functions.str_gipa) == 0) { 2916 fpGIPA = (PFN_vkGetInstanceProcAddr) 2917 loader_platform_get_proc_address( 2918 lib_handle, "vkGetInstanceProcAddr"); 2919 layer_prop->functions.get_instance_proc_addr = fpGIPA; 2920 } else 2921 fpGIPA = (PFN_vkGetInstanceProcAddr) 2922 loader_platform_get_proc_address( 2923 lib_handle, layer_prop->functions.str_gipa); 2924 if (!fpGIPA) { 2925 loader_log( 2926 inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 2927 "Failed to find vkGetInstanceProcAddr in layer %s", 2928 layer_prop->lib_name); 2929 continue; 2930 } 2931 } 2932 2933 layer_instance_link_info[activated_layers].pNext = 2934 chain_info.u.pLayerInfo; 2935 layer_instance_link_info[activated_layers] 2936 .pfnNextGetInstanceProcAddr = nextGIPA; 2937 chain_info.u.pLayerInfo = 2938 &layer_instance_link_info[activated_layers]; 2939 nextGIPA = fpGIPA; 2940 2941 loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, 2942 "Insert instance layer %s (%s)", 2943 layer_prop->info.layerName, layer_prop->lib_name); 2944 2945 activated_layers++; 2946 } 2947 } 2948 2949 PFN_vkCreateInstance fpCreateInstance = 2950 (PFN_vkCreateInstance)nextGIPA(*created_instance, "vkCreateInstance"); 2951 if (fpCreateInstance) { 2952 VkLayerInstanceCreateInfo instance_create_info; 2953 2954 instance_create_info.sType = 2955 VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO; 2956 instance_create_info.function = VK_LAYER_INSTANCE_INFO; 2957 2958 instance_create_info.u.instanceInfo.instance_info = inst; 2959 instance_create_info.u.instanceInfo.pfnNextGetInstanceProcAddr = 2960 nextGIPA; 2961 2962 instance_create_info.pNext = loader_create_info.pNext; 2963 loader_create_info.pNext = &instance_create_info; 2964 2965 res = fpCreateInstance(&loader_create_info, pAllocator, 2966 created_instance); 2967 } else { 2968 // Couldn't find CreateInstance function! 2969 res = VK_ERROR_INITIALIZATION_FAILED; 2970 } 2971 2972 if (res != VK_SUCCESS) { 2973 // TODO: Need to clean up here 2974 } else { 2975 loader_init_instance_core_dispatch_table(inst->disp, nextGIPA, 2976 *created_instance); 2977 } 2978 2979 return res; 2980} 2981 2982void loader_activate_instance_layer_extensions(struct loader_instance *inst, 2983 VkInstance created_inst) { 2984 2985 loader_init_instance_extension_dispatch_table( 2986 inst->disp, inst->disp->GetInstanceProcAddr, created_inst); 2987} 2988 2989static VkResult 2990loader_enable_device_layers(const struct loader_instance *inst, 2991 struct loader_icd *icd, 2992 struct loader_layer_list *activated_layer_list, 2993 const VkDeviceCreateInfo *pCreateInfo, 2994 const struct loader_layer_list *device_layers) 2995 2996{ 2997 VkResult err; 2998 2999 assert(activated_layer_list && "Cannot have null output layer list"); 3000 3001 if (activated_layer_list->list == NULL || 3002 activated_layer_list->capacity == 0) { 3003 loader_init_layer_list(inst, activated_layer_list); 3004 } 3005 3006 if (activated_layer_list->list == NULL) { 3007 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 3008 "Failed to alloc device activated layer list"); 3009 return VK_ERROR_OUT_OF_HOST_MEMORY; 3010 } 3011 3012 /* Add any implicit layers first */ 3013 loader_add_layer_implicit(inst, VK_LAYER_TYPE_DEVICE_IMPLICIT, 3014 activated_layer_list, device_layers); 3015 3016 /* Add any layers specified via environment variable next */ 3017 loader_add_layer_env(inst, VK_LAYER_TYPE_DEVICE_EXPLICIT, 3018 "VK_DEVICE_LAYERS", activated_layer_list, 3019 device_layers); 3020 3021 /* Add layers specified by the application */ 3022 err = loader_add_layer_names_to_list( 3023 inst, activated_layer_list, pCreateInfo->enabledLayerCount, 3024 pCreateInfo->ppEnabledLayerNames, device_layers); 3025 3026 return err; 3027} 3028 3029VKAPI_ATTR VkResult VKAPI_CALL 3030loader_create_device_terminator(VkPhysicalDevice physicalDevice, 3031 const VkDeviceCreateInfo *pCreateInfo, 3032 const VkAllocationCallbacks *pAllocator, 3033 VkDevice *pDevice) { 3034 struct loader_physical_device *phys_dev; 3035 phys_dev = loader_get_physical_device(physicalDevice); 3036 3037 VkLayerDeviceCreateInfo *chain_info = 3038 (VkLayerDeviceCreateInfo *)pCreateInfo->pNext; 3039 while (chain_info && 3040 !(chain_info->sType == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO && 3041 chain_info->function == VK_LAYER_DEVICE_INFO)) { 3042 chain_info = (VkLayerDeviceCreateInfo *)chain_info->pNext; 3043 } 3044 assert(chain_info != NULL); 3045 3046 struct loader_device *dev = 3047 (struct loader_device *)chain_info->u.deviceInfo.device_info; 3048 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = 3049 chain_info->u.deviceInfo.pfnNextGetInstanceProcAddr; 3050 PFN_vkCreateDevice fpCreateDevice = 3051 (PFN_vkCreateDevice)fpGetInstanceProcAddr(phys_dev->this_icd->instance, 3052 "vkCreateDevice"); 3053 if (fpCreateDevice == NULL) { 3054 return VK_ERROR_INITIALIZATION_FAILED; 3055 } 3056 3057 VkDeviceCreateInfo localCreateInfo; 3058 memcpy(&localCreateInfo, pCreateInfo, sizeof(localCreateInfo)); 3059 localCreateInfo.pNext = loader_strip_create_extensions(pCreateInfo->pNext); 3060 3061 /* 3062 * NOTE: Need to filter the extensions to only those 3063 * supported by the ICD. 3064 * No ICD will advertise support for layers. An ICD 3065 * library could support a layer, but it would be 3066 * independent of the actual ICD, just in the same library. 3067 */ 3068 char **filtered_extension_names = NULL; 3069 filtered_extension_names = loader_stack_alloc(pCreateInfo->enabledExtensionCount * sizeof(char *)); 3070 if (!filtered_extension_names) { 3071 return VK_ERROR_OUT_OF_HOST_MEMORY; 3072 } 3073 3074 localCreateInfo.enabledLayerCount = 0; 3075 localCreateInfo.ppEnabledLayerNames = NULL; 3076 3077 localCreateInfo.enabledExtensionCount = 0; 3078 localCreateInfo.ppEnabledExtensionNames = (const char * const *) filtered_extension_names; 3079 3080 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) { 3081 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i]; 3082 VkExtensionProperties *prop = get_extension_property(extension_name, 3083 &phys_dev->device_extension_cache); 3084 if (prop) { 3085 filtered_extension_names[localCreateInfo.enabledExtensionCount] = (char *) extension_name; 3086 localCreateInfo.enabledExtensionCount++; 3087 } 3088 } 3089 3090 VkDevice localDevice; 3091 // TODO: Why does fpCreateDevice behave differently than 3092 // this_icd->CreateDevice? 3093 // VkResult res = fpCreateDevice(phys_dev->phys_dev, &localCreateInfo, 3094 // pAllocator, &localDevice); 3095 VkResult res = phys_dev->this_icd->CreateDevice( 3096 phys_dev->phys_dev, &localCreateInfo, pAllocator, &localDevice); 3097 3098 if (res != VK_SUCCESS) { 3099 return res; 3100 } 3101 3102 *pDevice = localDevice; 3103 3104 /* Init dispatch pointer in new device object */ 3105 loader_init_dispatch(*pDevice, &dev->loader_dispatch); 3106 3107 return res; 3108} 3109 3110VkResult loader_create_device_chain(VkPhysicalDevice physicalDevice, 3111 const VkDeviceCreateInfo *pCreateInfo, 3112 const VkAllocationCallbacks *pAllocator, 3113 struct loader_instance *inst, 3114 struct loader_icd *icd, 3115 struct loader_device *dev) { 3116 uint32_t activated_layers = 0; 3117 VkLayerDeviceLink *layer_device_link_info; 3118 VkLayerDeviceCreateInfo chain_info; 3119 VkLayerDeviceCreateInfo device_info; 3120 VkDeviceCreateInfo loader_create_info; 3121 VkResult res; 3122 3123 PFN_vkGetDeviceProcAddr fpGDPA, nextGDPA = icd->GetDeviceProcAddr; 3124 PFN_vkGetInstanceProcAddr fpGIPA, nextGIPA = loader_gpa_instance_internal; 3125 3126 memcpy(&loader_create_info, pCreateInfo, sizeof(VkDeviceCreateInfo)); 3127 3128 chain_info.sType = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO; 3129 chain_info.function = VK_LAYER_LINK_INFO; 3130 chain_info.u.pLayerInfo = NULL; 3131 chain_info.pNext = pCreateInfo->pNext; 3132 3133 layer_device_link_info = loader_stack_alloc( 3134 sizeof(VkLayerDeviceLink) * dev->activated_layer_list.count); 3135 if (!layer_device_link_info) { 3136 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 3137 "Failed to alloc Device objects for layer"); 3138 return VK_ERROR_OUT_OF_HOST_MEMORY; 3139 } 3140 3141 /* 3142 * This structure is used by loader_create_device_terminator 3143 * so that it can intialize the device dispatch table pointer 3144 * in the device object returned by the ICD. Without this 3145 * structure the code wouldn't know where the loader's device_info 3146 * structure is located. 3147 */ 3148 device_info.sType = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO; 3149 device_info.function = VK_LAYER_DEVICE_INFO; 3150 device_info.pNext = &chain_info; 3151 device_info.u.deviceInfo.device_info = dev; 3152 device_info.u.deviceInfo.pfnNextGetInstanceProcAddr = 3153 icd->this_icd_lib->GetInstanceProcAddr; 3154 3155 loader_create_info.pNext = &device_info; 3156 3157 if (dev->activated_layer_list.count > 0) { 3158 /* Create instance chain of enabled layers */ 3159 for (int32_t i = dev->activated_layer_list.count - 1; i >= 0; i--) { 3160 struct loader_layer_properties *layer_prop = 3161 &dev->activated_layer_list.list[i]; 3162 loader_platform_dl_handle lib_handle; 3163 3164 lib_handle = loader_add_layer_lib(inst, "device", layer_prop); 3165 if (!lib_handle) 3166 continue; 3167 if ((fpGIPA = layer_prop->functions.get_instance_proc_addr) == 3168 NULL) { 3169 if (layer_prop->functions.str_gipa == NULL || 3170 strlen(layer_prop->functions.str_gipa) == 0) { 3171 fpGIPA = (PFN_vkGetInstanceProcAddr) 3172 loader_platform_get_proc_address( 3173 lib_handle, "vkGetInstanceProcAddr"); 3174 layer_prop->functions.get_instance_proc_addr = fpGIPA; 3175 } else 3176 fpGIPA = (PFN_vkGetInstanceProcAddr) 3177 loader_platform_get_proc_address( 3178 lib_handle, layer_prop->functions.str_gipa); 3179 if (!fpGIPA) { 3180 loader_log( 3181 inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 3182 "Failed to find vkGetInstanceProcAddr in layer %s", 3183 layer_prop->lib_name); 3184 continue; 3185 } 3186 } 3187 if ((fpGDPA = layer_prop->functions.get_device_proc_addr) == NULL) { 3188 if (layer_prop->functions.str_gdpa == NULL || 3189 strlen(layer_prop->functions.str_gdpa) == 0) { 3190 fpGDPA = (PFN_vkGetDeviceProcAddr) 3191 loader_platform_get_proc_address(lib_handle, 3192 "vkGetDeviceProcAddr"); 3193 layer_prop->functions.get_device_proc_addr = fpGDPA; 3194 } else 3195 fpGDPA = (PFN_vkGetDeviceProcAddr) 3196 loader_platform_get_proc_address( 3197 lib_handle, layer_prop->functions.str_gdpa); 3198 if (!fpGDPA) { 3199 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 3200 "Failed to find vkGetDeviceProcAddr in layer %s", 3201 layer_prop->lib_name); 3202 continue; 3203 } 3204 } 3205 3206 layer_device_link_info[activated_layers].pNext = 3207 chain_info.u.pLayerInfo; 3208 layer_device_link_info[activated_layers] 3209 .pfnNextGetInstanceProcAddr = nextGIPA; 3210 layer_device_link_info[activated_layers].pfnNextGetDeviceProcAddr = 3211 nextGDPA; 3212 chain_info.u.pLayerInfo = &layer_device_link_info[activated_layers]; 3213 nextGIPA = fpGIPA; 3214 nextGDPA = fpGDPA; 3215 3216 loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, 3217 "Insert device layer %s (%s)", 3218 layer_prop->info.layerName, layer_prop->lib_name); 3219 3220 activated_layers++; 3221 } 3222 } 3223 3224 PFN_vkCreateDevice fpCreateDevice = 3225 (PFN_vkCreateDevice)nextGIPA((VkInstance)inst, "vkCreateDevice"); 3226 if (fpCreateDevice) { 3227 res = fpCreateDevice(physicalDevice, &loader_create_info, pAllocator, 3228 &dev->device); 3229 } else { 3230 // Couldn't find CreateDevice function! 3231 return VK_ERROR_INITIALIZATION_FAILED; 3232 } 3233 3234 /* Initialize device dispatch table */ 3235 loader_init_device_dispatch_table(&dev->loader_dispatch, nextGDPA, 3236 dev->device); 3237 3238 return res; 3239} 3240 3241VkResult loader_validate_layers(const struct loader_instance *inst, 3242 const uint32_t layer_count, 3243 const char *const *ppEnabledLayerNames, 3244 const struct loader_layer_list *list) { 3245 struct loader_layer_properties *prop; 3246 3247 for (uint32_t i = 0; i < layer_count; i++) { 3248 VkStringErrorFlags result = vk_string_validate(MaxLoaderStringLength, ppEnabledLayerNames[i]); 3249 if (result != VK_STRING_ERROR_NONE) { 3250 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 3251 "Loader: Device ppEnabledLayerNames contains string that is too long or is badly formed"); 3252 return VK_ERROR_LAYER_NOT_PRESENT; 3253 } 3254 3255 prop = loader_get_layer_property(ppEnabledLayerNames[i], list); 3256 if (!prop) { 3257 return VK_ERROR_LAYER_NOT_PRESENT; 3258 } 3259 } 3260 return VK_SUCCESS; 3261} 3262 3263VkResult loader_validate_instance_extensions( 3264 const struct loader_instance *inst, 3265 const struct loader_extension_list *icd_exts, 3266 const struct loader_layer_list *instance_layer, 3267 const VkInstanceCreateInfo *pCreateInfo) { 3268 3269 VkExtensionProperties *extension_prop; 3270 struct loader_layer_properties *layer_prop; 3271 3272 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) { 3273 VkStringErrorFlags result = vk_string_validate(MaxLoaderStringLength, pCreateInfo->ppEnabledExtensionNames[i]); 3274 if (result != VK_STRING_ERROR_NONE) { 3275 loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 3276 "Loader: Instance ppEnabledExtensionNames contains string that is too long or is badly formed"); 3277 return VK_ERROR_EXTENSION_NOT_PRESENT; 3278 } 3279 3280 extension_prop = get_extension_property( 3281 pCreateInfo->ppEnabledExtensionNames[i], icd_exts); 3282 3283 if (extension_prop) { 3284 continue; 3285 } 3286 3287 extension_prop = NULL; 3288 3289 /* Not in global list, search layer extension lists */ 3290 for (uint32_t j = 0; j < pCreateInfo->enabledLayerCount; j++) { 3291 layer_prop = loader_get_layer_property( 3292 pCreateInfo->ppEnabledLayerNames[i], instance_layer); 3293 if (!layer_prop) { 3294 /* Should NOT get here, loader_validate_layers 3295 * should have already filtered this case out. 3296 */ 3297 continue; 3298 } 3299 3300 extension_prop = 3301 get_extension_property(pCreateInfo->ppEnabledExtensionNames[i], 3302 &layer_prop->instance_extension_list); 3303 if (extension_prop) { 3304 /* Found the extension in one of the layers enabled by the app. 3305 */ 3306 break; 3307 } 3308 } 3309 3310 if (!extension_prop) { 3311 /* Didn't find extension name in any of the global layers, error out 3312 */ 3313 return VK_ERROR_EXTENSION_NOT_PRESENT; 3314 } 3315 } 3316 return VK_SUCCESS; 3317} 3318 3319VkResult loader_validate_device_extensions( 3320 struct loader_physical_device *phys_dev, 3321 const struct loader_layer_list *activated_device_layers, 3322 const VkDeviceCreateInfo *pCreateInfo) { 3323 VkExtensionProperties *extension_prop; 3324 struct loader_layer_properties *layer_prop; 3325 3326 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) { 3327 3328 VkStringErrorFlags result = vk_string_validate(MaxLoaderStringLength, pCreateInfo->ppEnabledExtensionNames[i]); 3329 if (result != VK_STRING_ERROR_NONE) { 3330 loader_log(phys_dev->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 3331 "Loader: Device ppEnabledExtensionNames contains string that is too long or is badly formed"); 3332 return VK_ERROR_EXTENSION_NOT_PRESENT; 3333 } 3334 3335 const char *extension_name = pCreateInfo->ppEnabledExtensionNames[i]; 3336 extension_prop = get_extension_property( 3337 extension_name, &phys_dev->device_extension_cache); 3338 3339 if (extension_prop) { 3340 continue; 3341 } 3342 3343 /* Not in global list, search activated layer extension lists */ 3344 for (uint32_t j = 0; j < activated_device_layers->count; j++) { 3345 layer_prop = &activated_device_layers->list[j]; 3346 3347 extension_prop = get_dev_extension_property( 3348 extension_name, &layer_prop->device_extension_list); 3349 if (extension_prop) { 3350 /* Found the extension in one of the layers enabled by the app. 3351 */ 3352 break; 3353 } 3354 } 3355 3356 if (!extension_prop) { 3357 /* Didn't find extension name in any of the device layers, error out 3358 */ 3359 return VK_ERROR_EXTENSION_NOT_PRESENT; 3360 } 3361 } 3362 return VK_SUCCESS; 3363} 3364 3365VKAPI_ATTR VkResult VKAPI_CALL 3366loader_CreateInstance(const VkInstanceCreateInfo *pCreateInfo, 3367 const VkAllocationCallbacks *pAllocator, 3368 VkInstance *pInstance) { 3369 struct loader_icd *icd; 3370 VkExtensionProperties *prop; 3371 char **filtered_extension_names = NULL; 3372 VkInstanceCreateInfo icd_create_info; 3373 VkResult res = VK_SUCCESS; 3374 bool success = false; 3375 3376 VkLayerInstanceCreateInfo *chain_info = 3377 (VkLayerInstanceCreateInfo *)pCreateInfo->pNext; 3378 while ( 3379 chain_info && 3380 !(chain_info->sType == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO && 3381 chain_info->function == VK_LAYER_INSTANCE_INFO)) { 3382 chain_info = (VkLayerInstanceCreateInfo *)chain_info->pNext; 3383 } 3384 assert(chain_info != NULL); 3385 3386 struct loader_instance *ptr_instance = 3387 (struct loader_instance *)chain_info->u.instanceInfo.instance_info; 3388 memcpy(&icd_create_info, pCreateInfo, sizeof(icd_create_info)); 3389 3390 icd_create_info.enabledLayerCount = 0; 3391 icd_create_info.ppEnabledLayerNames = NULL; 3392 3393 // strip off the VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO entries 3394 icd_create_info.pNext = loader_strip_create_extensions(pCreateInfo->pNext); 3395 3396 /* 3397 * NOTE: Need to filter the extensions to only those 3398 * supported by the ICD. 3399 * No ICD will advertise support for layers. An ICD 3400 * library could support a layer, but it would be 3401 * independent of the actual ICD, just in the same library. 3402 */ 3403 filtered_extension_names = 3404 loader_stack_alloc(pCreateInfo->enabledExtensionCount * sizeof(char *)); 3405 if (!filtered_extension_names) { 3406 return VK_ERROR_OUT_OF_HOST_MEMORY; 3407 } 3408 icd_create_info.ppEnabledExtensionNames = 3409 (const char *const *)filtered_extension_names; 3410 3411 for (uint32_t i = 0; i < ptr_instance->icd_libs.count; i++) { 3412 icd = loader_icd_add(ptr_instance, &ptr_instance->icd_libs.list[i]); 3413 if (icd) { 3414 icd_create_info.enabledExtensionCount = 0; 3415 struct loader_extension_list icd_exts; 3416 3417 loader_log(ptr_instance, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, 3418 "Build ICD instance extension list"); 3419 // traverse scanned icd list adding non-duplicate extensions to the 3420 // list 3421 loader_init_generic_list(ptr_instance, 3422 (struct loader_generic_list *)&icd_exts, 3423 sizeof(VkExtensionProperties)); 3424 loader_add_instance_extensions( 3425 ptr_instance, 3426 icd->this_icd_lib->EnumerateInstanceExtensionProperties, 3427 icd->this_icd_lib->lib_name, &icd_exts); 3428 3429 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) { 3430 prop = get_extension_property( 3431 pCreateInfo->ppEnabledExtensionNames[i], &icd_exts); 3432 if (prop) { 3433 filtered_extension_names[icd_create_info 3434 .enabledExtensionCount] = 3435 (char *)pCreateInfo->ppEnabledExtensionNames[i]; 3436 icd_create_info.enabledExtensionCount++; 3437 } 3438 } 3439 3440 loader_destroy_generic_list( 3441 ptr_instance, (struct loader_generic_list *)&icd_exts); 3442 3443 res = ptr_instance->icd_libs.list[i].CreateInstance( 3444 &icd_create_info, pAllocator, &(icd->instance)); 3445 if (res == VK_SUCCESS) 3446 success = loader_icd_init_entrys( 3447 icd, icd->instance, 3448 ptr_instance->icd_libs.list[i].GetInstanceProcAddr); 3449 3450 if (res != VK_SUCCESS || !success) { 3451 ptr_instance->icds = ptr_instance->icds->next; 3452 loader_icd_destroy(ptr_instance, icd); 3453 loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 3454 "ICD ignored: failed to CreateInstance and find " 3455 "entrypoints with ICD"); 3456 } 3457 } 3458 } 3459 3460 /* 3461 * If no ICDs were added to instance list and res is unchanged 3462 * from it's initial value, the loader was unable to find 3463 * a suitable ICD. 3464 */ 3465 if (ptr_instance->icds == NULL) { 3466 if (res == VK_SUCCESS) { 3467 return VK_ERROR_INCOMPATIBLE_DRIVER; 3468 } else { 3469 return res; 3470 } 3471 } 3472 3473 return VK_SUCCESS; 3474} 3475 3476VKAPI_ATTR void VKAPI_CALL 3477loader_DestroyInstance(VkInstance instance, 3478 const VkAllocationCallbacks *pAllocator) { 3479 struct loader_instance *ptr_instance = loader_instance(instance); 3480 struct loader_icd *icds = ptr_instance->icds; 3481 struct loader_icd *next_icd; 3482 3483 // Remove this instance from the list of instances: 3484 struct loader_instance *prev = NULL; 3485 struct loader_instance *next = loader.instances; 3486 while (next != NULL) { 3487 if (next == ptr_instance) { 3488 // Remove this instance from the list: 3489 if (prev) 3490 prev->next = next->next; 3491 else 3492 loader.instances = next->next; 3493 break; 3494 } 3495 prev = next; 3496 next = next->next; 3497 } 3498 3499 while (icds) { 3500 if (icds->instance) { 3501 icds->DestroyInstance(icds->instance, pAllocator); 3502 } 3503 next_icd = icds->next; 3504 icds->instance = VK_NULL_HANDLE; 3505 loader_icd_destroy(ptr_instance, icds); 3506 3507 icds = next_icd; 3508 } 3509 loader_delete_layer_properties(ptr_instance, 3510 &ptr_instance->device_layer_list); 3511 loader_delete_layer_properties(ptr_instance, 3512 &ptr_instance->instance_layer_list); 3513 loader_scanned_icd_clear(ptr_instance, &ptr_instance->icd_libs); 3514 loader_destroy_generic_list( 3515 ptr_instance, (struct loader_generic_list *)&ptr_instance->ext_list); 3516 for (uint32_t i = 0; i < ptr_instance->total_gpu_count; i++) 3517 loader_destroy_generic_list( 3518 ptr_instance, 3519 (struct loader_generic_list *)&ptr_instance->phys_devs[i] 3520 .device_extension_cache); 3521 loader_heap_free(ptr_instance, ptr_instance->phys_devs); 3522 loader_free_dev_ext_table(ptr_instance); 3523} 3524 3525VkResult 3526loader_init_physical_device_info(struct loader_instance *ptr_instance) { 3527 struct loader_icd *icd; 3528 uint32_t i, j, idx, count = 0; 3529 VkResult res; 3530 struct loader_phys_dev_per_icd *phys_devs; 3531 3532 ptr_instance->total_gpu_count = 0; 3533 phys_devs = (struct loader_phys_dev_per_icd *)loader_stack_alloc( 3534 sizeof(struct loader_phys_dev_per_icd) * ptr_instance->total_icd_count); 3535 if (!phys_devs) 3536 return VK_ERROR_OUT_OF_HOST_MEMORY; 3537 3538 icd = ptr_instance->icds; 3539 for (i = 0; i < ptr_instance->total_icd_count; i++) { 3540 assert(icd); 3541 res = icd->EnumeratePhysicalDevices(icd->instance, &phys_devs[i].count, 3542 NULL); 3543 if (res != VK_SUCCESS) 3544 return res; 3545 count += phys_devs[i].count; 3546 icd = icd->next; 3547 } 3548 3549 ptr_instance->phys_devs = 3550 (struct loader_physical_device *)loader_heap_alloc( 3551 ptr_instance, count * sizeof(struct loader_physical_device), 3552 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 3553 if (!ptr_instance->phys_devs) 3554 return VK_ERROR_OUT_OF_HOST_MEMORY; 3555 3556 icd = ptr_instance->icds; 3557 3558 struct loader_physical_device *inst_phys_devs = ptr_instance->phys_devs; 3559 idx = 0; 3560 for (i = 0; i < ptr_instance->total_icd_count; i++) { 3561 assert(icd); 3562 3563 phys_devs[i].phys_devs = (VkPhysicalDevice *)loader_stack_alloc( 3564 phys_devs[i].count * sizeof(VkPhysicalDevice)); 3565 if (!phys_devs[i].phys_devs) { 3566 loader_heap_free(ptr_instance, ptr_instance->phys_devs); 3567 ptr_instance->phys_devs = NULL; 3568 return VK_ERROR_OUT_OF_HOST_MEMORY; 3569 } 3570 res = icd->EnumeratePhysicalDevices( 3571 icd->instance, &(phys_devs[i].count), phys_devs[i].phys_devs); 3572 if ((res == VK_SUCCESS)) { 3573 ptr_instance->total_gpu_count += phys_devs[i].count; 3574 for (j = 0; j < phys_devs[i].count; j++) { 3575 3576 // initialize the loader's physicalDevice object 3577 loader_set_dispatch((void *)&inst_phys_devs[idx], 3578 ptr_instance->disp); 3579 inst_phys_devs[idx].this_instance = ptr_instance; 3580 inst_phys_devs[idx].this_icd = icd; 3581 inst_phys_devs[idx].phys_dev = phys_devs[i].phys_devs[j]; 3582 memset(&inst_phys_devs[idx].device_extension_cache, 0, 3583 sizeof(struct loader_extension_list)); 3584 3585 idx++; 3586 } 3587 } else { 3588 loader_heap_free(ptr_instance, ptr_instance->phys_devs); 3589 ptr_instance->phys_devs = NULL; 3590 return res; 3591 } 3592 3593 icd = icd->next; 3594 } 3595 3596 return VK_SUCCESS; 3597} 3598 3599VKAPI_ATTR VkResult VKAPI_CALL 3600loader_EnumeratePhysicalDevices(VkInstance instance, 3601 uint32_t *pPhysicalDeviceCount, 3602 VkPhysicalDevice *pPhysicalDevices) { 3603 uint32_t i; 3604 uint32_t copy_count = 0; 3605 struct loader_instance *ptr_instance = (struct loader_instance *)instance; 3606 VkResult res = VK_SUCCESS; 3607 3608 if (ptr_instance->total_gpu_count == 0) { 3609 res = loader_init_physical_device_info(ptr_instance); 3610 } 3611 3612 *pPhysicalDeviceCount = ptr_instance->total_gpu_count; 3613 if (!pPhysicalDevices) { 3614 return res; 3615 } 3616 3617 copy_count = (ptr_instance->total_gpu_count < *pPhysicalDeviceCount) 3618 ? ptr_instance->total_gpu_count 3619 : *pPhysicalDeviceCount; 3620 for (i = 0; i < copy_count; i++) { 3621 pPhysicalDevices[i] = (VkPhysicalDevice)&ptr_instance->phys_devs[i]; 3622 } 3623 *pPhysicalDeviceCount = copy_count; 3624 3625 if (copy_count < ptr_instance->total_gpu_count) { 3626 return VK_INCOMPLETE; 3627 } 3628 3629 return res; 3630} 3631 3632VKAPI_ATTR void VKAPI_CALL 3633loader_GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, 3634 VkPhysicalDeviceProperties *pProperties) { 3635 struct loader_physical_device *phys_dev = 3636 (struct loader_physical_device *)physicalDevice; 3637 struct loader_icd *icd = phys_dev->this_icd; 3638 3639 if (icd->GetPhysicalDeviceProperties) 3640 icd->GetPhysicalDeviceProperties(phys_dev->phys_dev, pProperties); 3641} 3642 3643VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceQueueFamilyProperties( 3644 VkPhysicalDevice physicalDevice, uint32_t *pQueueFamilyPropertyCount, 3645 VkQueueFamilyProperties *pProperties) { 3646 struct loader_physical_device *phys_dev = 3647 (struct loader_physical_device *)physicalDevice; 3648 struct loader_icd *icd = phys_dev->this_icd; 3649 3650 if (icd->GetPhysicalDeviceQueueFamilyProperties) 3651 icd->GetPhysicalDeviceQueueFamilyProperties( 3652 phys_dev->phys_dev, pQueueFamilyPropertyCount, pProperties); 3653} 3654 3655VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceMemoryProperties( 3656 VkPhysicalDevice physicalDevice, 3657 VkPhysicalDeviceMemoryProperties *pProperties) { 3658 struct loader_physical_device *phys_dev = 3659 (struct loader_physical_device *)physicalDevice; 3660 struct loader_icd *icd = phys_dev->this_icd; 3661 3662 if (icd->GetPhysicalDeviceMemoryProperties) 3663 icd->GetPhysicalDeviceMemoryProperties(phys_dev->phys_dev, pProperties); 3664} 3665 3666VKAPI_ATTR void VKAPI_CALL 3667loader_GetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice, 3668 VkPhysicalDeviceFeatures *pFeatures) { 3669 struct loader_physical_device *phys_dev = 3670 (struct loader_physical_device *)physicalDevice; 3671 struct loader_icd *icd = phys_dev->this_icd; 3672 3673 if (icd->GetPhysicalDeviceFeatures) 3674 icd->GetPhysicalDeviceFeatures(phys_dev->phys_dev, pFeatures); 3675} 3676 3677VKAPI_ATTR void VKAPI_CALL 3678loader_GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, 3679 VkFormat format, 3680 VkFormatProperties *pFormatInfo) { 3681 struct loader_physical_device *phys_dev = 3682 (struct loader_physical_device *)physicalDevice; 3683 struct loader_icd *icd = phys_dev->this_icd; 3684 3685 if (icd->GetPhysicalDeviceFormatProperties) 3686 icd->GetPhysicalDeviceFormatProperties(phys_dev->phys_dev, format, 3687 pFormatInfo); 3688} 3689 3690VKAPI_ATTR VkResult VKAPI_CALL loader_GetPhysicalDeviceImageFormatProperties( 3691 VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, 3692 VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, 3693 VkImageFormatProperties *pImageFormatProperties) { 3694 struct loader_physical_device *phys_dev = 3695 (struct loader_physical_device *)physicalDevice; 3696 struct loader_icd *icd = phys_dev->this_icd; 3697 3698 if (!icd->GetPhysicalDeviceImageFormatProperties) 3699 return VK_ERROR_INITIALIZATION_FAILED; 3700 3701 return icd->GetPhysicalDeviceImageFormatProperties( 3702 phys_dev->phys_dev, format, type, tiling, usage, flags, 3703 pImageFormatProperties); 3704} 3705 3706VKAPI_ATTR void VKAPI_CALL loader_GetPhysicalDeviceSparseImageFormatProperties( 3707 VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, 3708 VkSampleCountFlagBits samples, VkImageUsageFlags usage, 3709 VkImageTiling tiling, uint32_t *pNumProperties, 3710 VkSparseImageFormatProperties *pProperties) { 3711 struct loader_physical_device *phys_dev = 3712 (struct loader_physical_device *)physicalDevice; 3713 struct loader_icd *icd = phys_dev->this_icd; 3714 3715 if (icd->GetPhysicalDeviceSparseImageFormatProperties) 3716 icd->GetPhysicalDeviceSparseImageFormatProperties( 3717 phys_dev->phys_dev, format, type, samples, usage, tiling, 3718 pNumProperties, pProperties); 3719} 3720 3721VKAPI_ATTR VkResult VKAPI_CALL 3722loader_CreateDevice(VkPhysicalDevice physicalDevice, 3723 const VkDeviceCreateInfo *pCreateInfo, 3724 const VkAllocationCallbacks *pAllocator, 3725 VkDevice *pDevice) { 3726 struct loader_physical_device *phys_dev; 3727 struct loader_icd *icd; 3728 struct loader_device *dev; 3729 struct loader_instance *inst; 3730 struct loader_layer_list activated_layer_list = {0}; 3731 VkResult res; 3732 3733 assert(pCreateInfo->queueCreateInfoCount >= 1); 3734 3735 // TODO this only works for one physical device per instance 3736 // once CreateDevice layer bootstrapping is done via DeviceCreateInfo 3737 // hopefully don't need this anymore in trampoline code 3738 phys_dev = loader_get_physical_device(physicalDevice); 3739 icd = phys_dev->this_icd; 3740 if (!icd) 3741 return VK_ERROR_INITIALIZATION_FAILED; 3742 3743 inst = phys_dev->this_instance; 3744 3745 if (!icd->CreateDevice) { 3746 return VK_ERROR_INITIALIZATION_FAILED; 3747 } 3748 3749 /* validate any app enabled layers are available */ 3750 if (pCreateInfo->enabledLayerCount > 0) { 3751 res = loader_validate_layers(inst, 3752 pCreateInfo->enabledLayerCount, 3753 pCreateInfo->ppEnabledLayerNames, 3754 &inst->device_layer_list); 3755 if (res != VK_SUCCESS) { 3756 return res; 3757 } 3758 } 3759 3760 /* Get the physical device extensions if they haven't been retrieved yet */ 3761 if (phys_dev->device_extension_cache.capacity == 0) { 3762 if (!loader_init_generic_list( 3763 inst, 3764 (struct loader_generic_list *)&phys_dev->device_extension_cache, 3765 sizeof(VkExtensionProperties))) { 3766 return VK_ERROR_OUT_OF_HOST_MEMORY; 3767 } 3768 3769 res = loader_add_device_extensions( 3770 inst, icd, phys_dev->phys_dev, 3771 phys_dev->this_icd->this_icd_lib->lib_name, 3772 &phys_dev->device_extension_cache); 3773 if (res != VK_SUCCESS) { 3774 return res; 3775 } 3776 } 3777 3778 /* fetch a list of all layers activated, explicit and implicit */ 3779 res = loader_enable_device_layers(inst, icd, &activated_layer_list, 3780 pCreateInfo, &inst->device_layer_list); 3781 if (res != VK_SUCCESS) { 3782 return res; 3783 } 3784 3785 /* make sure requested extensions to be enabled are supported */ 3786 res = loader_validate_device_extensions(phys_dev, &activated_layer_list, 3787 pCreateInfo); 3788 if (res != VK_SUCCESS) { 3789 loader_destroy_generic_list( 3790 inst, (struct loader_generic_list *)&activated_layer_list); 3791 return res; 3792 } 3793 3794 dev = loader_add_logical_device(inst, &icd->logical_device_list); 3795 if (dev == NULL) { 3796 loader_destroy_generic_list( 3797 inst, (struct loader_generic_list *)&activated_layer_list); 3798 return VK_ERROR_OUT_OF_HOST_MEMORY; 3799 } 3800 3801 /* move the locally filled layer list into the device, and pass ownership of 3802 * the memory */ 3803 dev->activated_layer_list.capacity = activated_layer_list.capacity; 3804 dev->activated_layer_list.count = activated_layer_list.count; 3805 dev->activated_layer_list.list = activated_layer_list.list; 3806 memset(&activated_layer_list, 0, sizeof(activated_layer_list)); 3807 3808 /* activate any layers on device chain which terminates with device*/ 3809 res = loader_enable_device_layers(inst, icd, &dev->activated_layer_list, 3810 pCreateInfo, &inst->device_layer_list); 3811 if (res != VK_SUCCESS) { 3812 loader_remove_logical_device(inst, icd, dev); 3813 return res; 3814 } 3815 3816 res = loader_create_device_chain(physicalDevice, pCreateInfo, pAllocator, 3817 inst, icd, dev); 3818 if (res != VK_SUCCESS) { 3819 loader_remove_logical_device(inst, icd, dev); 3820 return res; 3821 } 3822 3823 *pDevice = dev->device; 3824 3825 /* initialize any device extension dispatch entry's from the instance list*/ 3826 loader_init_dispatch_dev_ext(inst, dev); 3827 3828 /* initialize WSI device extensions as part of core dispatch since loader 3829 * has 3830 * dedicated trampoline code for these*/ 3831 loader_init_device_extension_dispatch_table( 3832 &dev->loader_dispatch, 3833 dev->loader_dispatch.core_dispatch.GetDeviceProcAddr, *pDevice); 3834 3835 return res; 3836} 3837 3838/** 3839 * Get an instance level or global level entry point address. 3840 * @param instance 3841 * @param pName 3842 * @return 3843 * If instance == NULL returns a global level functions only 3844 * If instance is valid returns a trampoline entry point for all dispatchable 3845 * Vulkan 3846 * functions both core and extensions. 3847 */ 3848LOADER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL 3849vkGetInstanceProcAddr(VkInstance instance, const char *pName) { 3850 3851 void *addr; 3852 3853 addr = globalGetProcAddr(pName); 3854 if (instance == VK_NULL_HANDLE) { 3855 // get entrypoint addresses that are global (no dispatchable object) 3856 3857 return addr; 3858 } else { 3859 // if a global entrypoint return NULL 3860 if (addr) 3861 return NULL; 3862 } 3863 3864 struct loader_instance *ptr_instance = loader_get_instance(instance); 3865 if (ptr_instance == NULL) 3866 return NULL; 3867 // Return trampoline code for non-global entrypoints including any 3868 // extensions. 3869 // Device extensions are returned if a layer or ICD supports the extension. 3870 // Instance extensions are returned if the extension is enabled and the 3871 // loader 3872 // or someone else supports the extension 3873 return trampolineGetProcAddr(ptr_instance, pName); 3874} 3875 3876/** 3877 * Get a device level or global level entry point address. 3878 * @param device 3879 * @param pName 3880 * @return 3881 * If device is valid, returns a device relative entry point for device level 3882 * entry points both core and extensions. 3883 * Device relative means call down the device chain. 3884 */ 3885LOADER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL 3886vkGetDeviceProcAddr(VkDevice device, const char *pName) { 3887 void *addr; 3888 3889 /* for entrypoints that loader must handle (ie non-dispatchable or create 3890 object) 3891 make sure the loader entrypoint is returned */ 3892 addr = loader_non_passthrough_gdpa(pName); 3893 if (addr) { 3894 return addr; 3895 } 3896 3897 /* Although CreateDevice is on device chain it's dispatchable object isn't 3898 * a VkDevice or child of VkDevice so return NULL. 3899 */ 3900 if (!strcmp(pName, "CreateDevice")) 3901 return NULL; 3902 3903 /* return the dispatch table entrypoint for the fastest case */ 3904 const VkLayerDispatchTable *disp_table = *(VkLayerDispatchTable **)device; 3905 if (disp_table == NULL) 3906 return NULL; 3907 3908 addr = loader_lookup_device_dispatch_table(disp_table, pName); 3909 if (addr) 3910 return addr; 3911 3912 if (disp_table->GetDeviceProcAddr == NULL) 3913 return NULL; 3914 return disp_table->GetDeviceProcAddr(device, pName); 3915} 3916 3917LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL 3918vkEnumerateInstanceExtensionProperties(const char *pLayerName, 3919 uint32_t *pPropertyCount, 3920 VkExtensionProperties *pProperties) { 3921 struct loader_extension_list *global_ext_list = NULL; 3922 struct loader_layer_list instance_layers; 3923 struct loader_extension_list icd_extensions; 3924 struct loader_icd_libs icd_libs; 3925 uint32_t copy_size; 3926 3927 tls_instance = NULL; 3928 memset(&icd_extensions, 0, sizeof(icd_extensions)); 3929 memset(&instance_layers, 0, sizeof(instance_layers)); 3930 loader_platform_thread_once(&once_init, loader_initialize); 3931 3932 /* get layer libraries if needed */ 3933 if (pLayerName && strlen(pLayerName) != 0) { 3934 if (vk_string_validate(MaxLoaderStringLength, pLayerName) == VK_STRING_ERROR_NONE) { 3935 loader_layer_scan(NULL, &instance_layers, NULL); 3936 for (uint32_t i = 0; i < instance_layers.count; i++) { 3937 struct loader_layer_properties *props = &instance_layers.list[i]; 3938 if (strcmp(props->info.layerName, pLayerName) == 0) { 3939 global_ext_list = &props->instance_extension_list; 3940 } 3941 } 3942 } else { 3943 assert(VK_FALSE && "vkEnumerateInstanceExtensionProperties: pLayerName is too long or is badly formed"); 3944 return VK_ERROR_EXTENSION_NOT_PRESENT; 3945 } 3946 } else { 3947 /* Scan/discover all ICD libraries */ 3948 memset(&icd_libs, 0, sizeof(struct loader_icd_libs)); 3949 loader_icd_scan(NULL, &icd_libs); 3950 /* get extensions from all ICD's, merge so no duplicates */ 3951 loader_get_icd_loader_instance_extensions(NULL, &icd_libs, 3952 &icd_extensions); 3953 loader_scanned_icd_clear(NULL, &icd_libs); 3954 global_ext_list = &icd_extensions; 3955 } 3956 3957 if (global_ext_list == NULL) { 3958 loader_destroy_layer_list(NULL, &instance_layers); 3959 return VK_ERROR_LAYER_NOT_PRESENT; 3960 } 3961 3962 if (pProperties == NULL) { 3963 *pPropertyCount = global_ext_list->count; 3964 loader_destroy_layer_list(NULL, &instance_layers); 3965 loader_destroy_generic_list( 3966 NULL, (struct loader_generic_list *)&icd_extensions); 3967 return VK_SUCCESS; 3968 } 3969 3970 copy_size = *pPropertyCount < global_ext_list->count 3971 ? *pPropertyCount 3972 : global_ext_list->count; 3973 for (uint32_t i = 0; i < copy_size; i++) { 3974 memcpy(&pProperties[i], &global_ext_list->list[i], 3975 sizeof(VkExtensionProperties)); 3976 } 3977 *pPropertyCount = copy_size; 3978 loader_destroy_generic_list(NULL, 3979 (struct loader_generic_list *)&icd_extensions); 3980 3981 if (copy_size < global_ext_list->count) { 3982 loader_destroy_layer_list(NULL, &instance_layers); 3983 return VK_INCOMPLETE; 3984 } 3985 3986 loader_destroy_layer_list(NULL, &instance_layers); 3987 return VK_SUCCESS; 3988} 3989 3990LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL 3991vkEnumerateInstanceLayerProperties(uint32_t *pPropertyCount, 3992 VkLayerProperties *pProperties) { 3993 3994 struct loader_layer_list instance_layer_list; 3995 tls_instance = NULL; 3996 3997 loader_platform_thread_once(&once_init, loader_initialize); 3998 3999 uint32_t copy_size; 4000 4001 /* get layer libraries */ 4002 memset(&instance_layer_list, 0, sizeof(instance_layer_list)); 4003 loader_layer_scan(NULL, &instance_layer_list, NULL); 4004 4005 if (pProperties == NULL) { 4006 *pPropertyCount = instance_layer_list.count; 4007 loader_destroy_layer_list(NULL, &instance_layer_list); 4008 return VK_SUCCESS; 4009 } 4010 4011 copy_size = (*pPropertyCount < instance_layer_list.count) 4012 ? *pPropertyCount 4013 : instance_layer_list.count; 4014 for (uint32_t i = 0; i < copy_size; i++) { 4015 memcpy(&pProperties[i], &instance_layer_list.list[i].info, 4016 sizeof(VkLayerProperties)); 4017 } 4018 4019 *pPropertyCount = copy_size; 4020 loader_destroy_layer_list(NULL, &instance_layer_list); 4021 4022 if (copy_size < instance_layer_list.count) { 4023 return VK_INCOMPLETE; 4024 } 4025 4026 return VK_SUCCESS; 4027} 4028 4029VKAPI_ATTR VkResult VKAPI_CALL 4030loader_EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, 4031 const char *pLayerName, 4032 uint32_t *pPropertyCount, 4033 VkExtensionProperties *pProperties) { 4034 struct loader_physical_device *phys_dev; 4035 uint32_t copy_size; 4036 4037 uint32_t count; 4038 struct loader_device_extension_list *dev_ext_list = NULL; 4039 struct loader_layer_list implicit_layer_list; 4040 4041 // TODO fix this aliases physical devices 4042 phys_dev = loader_get_physical_device(physicalDevice); 4043 4044 /* get layer libraries if needed */ 4045 if (pLayerName && strlen(pLayerName) != 0) { 4046 if (vk_string_validate(MaxLoaderStringLength, pLayerName) == VK_STRING_ERROR_NONE) { 4047 for (uint32_t i = 0; 4048 i < phys_dev->this_instance->device_layer_list.count; i++) { 4049 struct loader_layer_properties *props = 4050 &phys_dev->this_instance->device_layer_list.list[i]; 4051 if (strcmp(props->info.layerName, pLayerName) == 0) { 4052 dev_ext_list = &props->device_extension_list; 4053 } 4054 } 4055 count = (dev_ext_list == NULL) ? 0: dev_ext_list->count; 4056 if (pProperties == NULL) { 4057 *pPropertyCount = count; 4058 return VK_SUCCESS; 4059 } 4060 4061 copy_size = *pPropertyCount < count ? *pPropertyCount : count; 4062 for (uint32_t i = 0; i < copy_size; i++) { 4063 memcpy(&pProperties[i], &dev_ext_list->list[i].props, 4064 sizeof(VkExtensionProperties)); 4065 } 4066 *pPropertyCount = copy_size; 4067 4068 if (copy_size < count) { 4069 return VK_INCOMPLETE; 4070 } 4071 } else { 4072 loader_log(phys_dev->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, 4073 "vkEnumerateDeviceExtensionProperties: pLayerName is too long or is badly formed"); 4074 return VK_ERROR_EXTENSION_NOT_PRESENT; 4075 } 4076 return VK_SUCCESS; 4077 } else { 4078 /* this case is during the call down the instance chain with pLayerName 4079 * == NULL*/ 4080 struct loader_icd *icd = phys_dev->this_icd; 4081 uint32_t icd_ext_count = *pPropertyCount; 4082 VkResult res; 4083 4084 /* get device extensions */ 4085 res = icd->EnumerateDeviceExtensionProperties( 4086 phys_dev->phys_dev, NULL, &icd_ext_count, pProperties); 4087 if (res != VK_SUCCESS) 4088 return res; 4089 4090 loader_init_layer_list(phys_dev->this_instance, &implicit_layer_list); 4091 4092 loader_add_layer_implicit( 4093 phys_dev->this_instance, VK_LAYER_TYPE_INSTANCE_IMPLICIT, 4094 &implicit_layer_list, 4095 &phys_dev->this_instance->instance_layer_list); 4096 /* we need to determine which implicit layers are active, 4097 * and then add their extensions. This can't be cached as 4098 * it depends on results of environment variables (which can change). 4099 */ 4100 if (pProperties != NULL) { 4101 /* initialize dev_extension list within the physicalDevice object */ 4102 res = loader_init_device_extensions( 4103 phys_dev->this_instance, phys_dev, icd_ext_count, pProperties, 4104 &phys_dev->device_extension_cache); 4105 if (res != VK_SUCCESS) 4106 return res; 4107 4108 /* we need to determine which implicit layers are active, 4109 * and then add their extensions. This can't be cached as 4110 * it depends on results of environment variables (which can 4111 * change). 4112 */ 4113 struct loader_extension_list all_exts = {0}; 4114 loader_add_to_ext_list(phys_dev->this_instance, &all_exts, 4115 phys_dev->device_extension_cache.count, 4116 phys_dev->device_extension_cache.list); 4117 4118 loader_init_layer_list(phys_dev->this_instance, 4119 &implicit_layer_list); 4120 4121 loader_add_layer_implicit( 4122 phys_dev->this_instance, VK_LAYER_TYPE_INSTANCE_IMPLICIT, 4123 &implicit_layer_list, 4124 &phys_dev->this_instance->instance_layer_list); 4125 4126 for (uint32_t i = 0; i < implicit_layer_list.count; i++) { 4127 for ( 4128 uint32_t j = 0; 4129 j < implicit_layer_list.list[i].device_extension_list.count; 4130 j++) { 4131 loader_add_to_ext_list(phys_dev->this_instance, &all_exts, 4132 1, 4133 &implicit_layer_list.list[i] 4134 .device_extension_list.list[j] 4135 .props); 4136 } 4137 } 4138 uint32_t capacity = *pPropertyCount; 4139 VkExtensionProperties *props = pProperties; 4140 4141 for (uint32_t i = 0; i < all_exts.count && i < capacity; i++) { 4142 props[i] = all_exts.list[i]; 4143 } 4144 /* wasn't enough space for the extensions, we did partial copy now 4145 * return VK_INCOMPLETE */ 4146 if (capacity < all_exts.count) { 4147 res = VK_INCOMPLETE; 4148 } else { 4149 *pPropertyCount = all_exts.count; 4150 } 4151 loader_destroy_generic_list( 4152 phys_dev->this_instance, 4153 (struct loader_generic_list *)&all_exts); 4154 } else { 4155 /* just return the count; need to add in the count of implicit layer 4156 * extensions 4157 * don't worry about duplicates being added in the count */ 4158 *pPropertyCount = icd_ext_count; 4159 4160 for (uint32_t i = 0; i < implicit_layer_list.count; i++) { 4161 *pPropertyCount += 4162 implicit_layer_list.list[i].device_extension_list.count; 4163 } 4164 res = VK_SUCCESS; 4165 } 4166 4167 loader_destroy_generic_list( 4168 phys_dev->this_instance, 4169 (struct loader_generic_list *)&implicit_layer_list); 4170 return res; 4171 } 4172} 4173 4174VKAPI_ATTR VkResult VKAPI_CALL 4175loader_EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, 4176 uint32_t *pPropertyCount, 4177 VkLayerProperties *pProperties) { 4178 uint32_t copy_size; 4179 struct loader_physical_device *phys_dev; 4180 // TODO fix this, aliases physical devices 4181 phys_dev = loader_get_physical_device(physicalDevice); 4182 uint32_t count = phys_dev->this_instance->device_layer_list.count; 4183 4184 if (pProperties == NULL) { 4185 *pPropertyCount = count; 4186 return VK_SUCCESS; 4187 } 4188 4189 copy_size = (*pPropertyCount < count) ? *pPropertyCount : count; 4190 for (uint32_t i = 0; i < copy_size; i++) { 4191 memcpy(&pProperties[i], 4192 &(phys_dev->this_instance->device_layer_list.list[i].info), 4193 sizeof(VkLayerProperties)); 4194 } 4195 *pPropertyCount = copy_size; 4196 4197 if (copy_size < count) { 4198 return VK_INCOMPLETE; 4199 } 4200 4201 return VK_SUCCESS; 4202} 4203 4204VkStringErrorFlags vk_string_validate(const int max_length, const char *utf8) 4205{ 4206 VkStringErrorFlags result = VK_STRING_ERROR_NONE; 4207 int num_char_bytes; 4208 int i,j; 4209 4210 for (i = 0; i < max_length; i++) 4211 { 4212 if (utf8[i] == 0) { 4213 break; 4214 } else if ((utf8[i] > 0x20) && (utf8[i] < 0x7f)) { 4215 num_char_bytes = 0; 4216 } else if ((utf8[i] & UTF8_ONE_BYTE_MASK) == UTF8_ONE_BYTE_CODE) { 4217 num_char_bytes = 1; 4218 } else if ((utf8[i] & UTF8_TWO_BYTE_MASK) == UTF8_TWO_BYTE_CODE) { 4219 num_char_bytes = 2; 4220 } else if ((utf8[i] & UTF8_THREE_BYTE_MASK) == UTF8_THREE_BYTE_CODE) { 4221 num_char_bytes = 3; 4222 } else { 4223 result = VK_STRING_ERROR_BAD_DATA; 4224 } 4225 4226 // Validate the following num_char_bytes of data 4227 for (j = 0; (j < num_char_bytes) && (i < max_length); j++) { 4228 if (++i == max_length) { 4229 result |= VK_STRING_ERROR_LENGTH; 4230 break; 4231 } 4232 if ((utf8[i] & UTF8_DATA_BYTE_MASK) != UTF8_DATA_BYTE_CODE) { 4233 result |= VK_STRING_ERROR_BAD_DATA; 4234 } 4235 } 4236 } 4237 return result; 4238} 4239 4240