From 879c136f156308edbc2beba828d4fabb423f9a9d Mon Sep 17 00:00:00 2001 From: Jon Ashburn Date: Tue, 12 May 2015 17:26:48 -0600 Subject: loader: Activate layers on the instance chain at CreateInstance --- loader/loader.c | 269 ++++++++++++++++++++++++++++++----------------- loader/loader.h | 100 ++++++++++++++++-- loader/loader_platform.h | 4 + loader/table_ops.h | 78 +++++++++++--- loader/trampoline.c | 118 ++++++++++++++++++++- 5 files changed, 445 insertions(+), 124 deletions(-) diff --git a/loader/loader.c b/loader/loader.c index b5b6889d..66994104 100644 --- a/loader/loader.c +++ b/loader/loader.c @@ -41,19 +41,14 @@ #include #endif // WIN32 #include "loader_platform.h" -#include "table_ops.h" -#include "gpa_helper.h" #include "loader.h" +#include "gpa_helper.h" +#include "table_ops.h" #include "vkIcd.h" // The following is #included again to catch certain OS-specific functions // being used: #include "loader_platform.h" -struct loader_layers { - loader_platform_dl_handle lib_handle; - char name[256]; -}; - struct layer_name_pair { char *layer_name; const char *lib_name; @@ -93,29 +88,28 @@ struct loader_scanned_icds { struct extension_property *extensions; }; -struct loader_scanned_layers { - char *name; - uint32_t extension_count; - struct extension_property *extensions; +struct loader_struct loader = {0}; + +VkLayerInstanceDispatchTable instance_disp = { + .GetInstanceProcAddr = vkGetInstanceProcAddr, + .GetProcAddr = vkGetProcAddr, + .CreateInstance = loader_CreateInstance, + .DestroyInstance = loader_DestroyInstance, + .EnumeratePhysicalDevices = loader_EnumeratePhysicalDevices, + .GetPhysicalDeviceInfo = vkGetPhysicalDeviceInfo, + .CreateDevice = vkCreateDevice, + .GetGlobalExtensionInfo = loader_GetGlobalExtensionInfo, + .GetPhysicalDeviceExtensionInfo = vkGetPhysicalDeviceExtensionInfo, + .EnumerateLayers = vkEnumerateLayers, + .GetMultiDeviceCompatibility = vkGetMultiDeviceCompatibility, + .DbgRegisterMsgCallback = loader_DbgRegisterMsgCallback, + .DbgUnregisterMsgCallback = loader_DbgUnregisterMsgCallback, + .DbgSetGlobalOption = loader_DbgSetGlobalOption, }; -// Note: Since the following is a static structure, all members are initialized -// to zero. -static struct { - struct loader_instance *instances; - bool icds_scanned; - struct loader_scanned_icds *scanned_icd_list; - bool layer_scanned; - char *layer_dirs; - unsigned int scanned_layer_count; - struct loader_scanned_layers scanned_layers[MAX_LAYER_LIBRARIES]; - size_t scanned_ext_list_capacity; - uint32_t scanned_ext_list_count; // coalesced from all layers/drivers - struct extension_property **scanned_ext_list; -} loader; - -static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_icd); -static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_layer); -static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_exts); + +LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_icd); +LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_layer); +LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_exts); #if defined(WIN32) char *loader_get_registry_string(const HKEY hive, @@ -356,7 +350,7 @@ static void loader_add_to_ext_list(uint32_t count, } } -static bool loader_is_extension_scanned(const char *name) +bool loader_is_extension_scanned(const char *name) { uint32_t i; @@ -367,7 +361,7 @@ static bool loader_is_extension_scanned(const char *name) return false; } -static void loader_coalesce_extensions(void) +void loader_coalesce_extensions(void) { uint32_t i; struct loader_scanned_icds *icd_list = loader.scanned_icd_list; @@ -488,7 +482,7 @@ static void loader_scanned_icd_add(const char *filename) * \returns * void; but side effect is to set loader_icd_scanned to true */ -static void loader_icd_scan(void) +void loader_icd_scan(void) { const char *p, *next; char *libPaths = NULL; @@ -571,7 +565,7 @@ static void loader_icd_scan(void) } -static void layer_lib_scan(void) +void layer_lib_scan(void) { const char *p, *next; char *libPaths = NULL; @@ -720,27 +714,49 @@ static void layer_lib_scan(void) loader.layer_scanned = true; } -static void * VKAPI loader_gpa_internal(VkPhysicalDevice gpu, const char * pName) +static void* VKAPI loader_gpa_device_internal(VkPhysicalDevice physDev, const char * pName) { - if (gpu == VK_NULL_HANDLE) { - return NULL;; + if (physDev == VK_NULL_HANDLE) { + return NULL; } - VkBaseLayerObject* gpuw = (VkBaseLayerObject *) gpu; - VkLayerDispatchTable * disp_table = * (VkLayerDispatchTable **) gpuw->baseObject; + VkBaseLayerObject* physDevWrap = (VkBaseLayerObject *) physDev; + VkLayerDispatchTable* disp_table = * (VkLayerDispatchTable **) physDevWrap->baseObject; void *addr; if (disp_table == NULL) return NULL; - addr = loader_lookup_dispatch_table(disp_table, pName); + addr = loader_lookup_device_dispatch_table(disp_table, pName); if (addr) return addr; else { if (disp_table->GetProcAddr == NULL) return NULL; - if (gpuw->baseObject == gpuw->nextObject) - return gpuw->pGPA(gpuw->baseObject, pName); - return disp_table->GetProcAddr(gpuw->nextObject, pName); + if (physDevWrap->baseObject == physDevWrap->nextObject) + return physDevWrap->pGPA(physDevWrap->baseObject, pName); + return disp_table->GetProcAddr(physDevWrap->nextObject, pName); + } +} + +static void* VKAPI loader_gpa_instance_internal(VkInstance inst, const char * pName) +{ + // inst is not wrapped + if (inst == VK_NULL_HANDLE) { + return NULL; + } + VkLayerInstanceDispatchTable* disp_table = * (VkLayerInstanceDispatchTable **) inst; + void *addr; + + if (disp_table == NULL) + return NULL; + + addr = loader_lookup_instance_dispatch_table(disp_table, pName); + if (addr) + return addr; + else { + if (disp_table->GetInstanceProcAddr == NULL) + return NULL; + return disp_table->GetInstanceProcAddr(inst, pName); } } @@ -771,7 +787,7 @@ static bool loader_layers_activated(const struct loader_icd *icd, const uint32_t return false; } -static void loader_init_layer_libs(struct loader_icd *icd, uint32_t gpu_index, +static void loader_init_device_layer_libs(struct loader_icd *icd, uint32_t gpu_index, struct layer_name_pair * pLayerNames, uint32_t count) { @@ -800,7 +816,7 @@ static void loader_init_layer_libs(struct loader_icd *icd, uint32_t gpu_index, loader_log(VK_DBG_MSG_ERROR, 0, loader_platform_open_library_error(pLayerNames[i].lib_name)); continue; } else { - loader_log(VK_DBG_MSG_UNKNOWN, 0, "Inserting layer %s from library %s", + loader_log(VK_DBG_MSG_UNKNOWN, 0, "Inserting device layer %s from library %s", pLayerNames[i].layer_name, pLayerNames[i].lib_name); } free(pLayerNames[i].layer_name); @@ -809,6 +825,44 @@ static void loader_init_layer_libs(struct loader_icd *icd, uint32_t gpu_index, } } +static void loader_init_instance_layer_libs(struct loader_instance *inst, + struct layer_name_pair * pLayerNames, + uint32_t count) +{ + if (!inst) + return; + + struct loader_layers *obj; + bool foundLib; + for (uint32_t i = 0; i < count; i++) { + foundLib = false; + for (uint32_t j = 0; j < inst->layer_count; j++) { + if (inst->layer_libs[j].lib_handle && + !strcmp(inst->layer_libs[j].name, + (char *) pLayerNames[i].layer_name) && + strcmp("Validation", (char *) pLayerNames[i].layer_name)) { + foundLib = true; + break; + } + } + if (!foundLib) { + obj = &(inst->layer_libs[i]); + strncpy(obj->name, (char *) pLayerNames[i].layer_name, sizeof(obj->name) - 1); + obj->name[sizeof(obj->name) - 1] = '\0'; + // Used to call: dlopen(pLayerNames[i].lib_name, RTLD_LAZY | RTLD_DEEPBIND) + if ((obj->lib_handle = loader_platform_open_library(pLayerNames[i].lib_name)) == NULL) { + loader_log(VK_DBG_MSG_ERROR, 0, loader_platform_open_library_error(pLayerNames[i].lib_name)); + continue; + } else { + loader_log(VK_DBG_MSG_UNKNOWN, 0, "Inserting instance layer %s from library %s", + pLayerNames[i].layer_name, pLayerNames[i].lib_name); + } + free(pLayerNames[i].layer_name); + inst->layer_count++; + } + } +} + static bool find_layer_extension(const char *pExtName, uint32_t *out_count, char *lib_name[MAX_LAYER_LIBRARIES]) { @@ -977,7 +1031,9 @@ static uint32_t loader_get_layer_libs(uint32_t ext_count, const char *const* ext return count; } -static void loader_deactivate_layer(const struct loader_instance *instance) +//TODO static void loader_deactivate_device_layer(device) + +static void loader_deactivate_instance_layer(const struct loader_instance *instance) { struct loader_icd *icd; struct loader_layers *libs; @@ -1004,9 +1060,63 @@ static void loader_deactivate_layer(const struct loader_instance *instance) } icd->gpu_count = 0; } + + free(instance->wrappedInstance); } -extern uint32_t loader_activate_layers(struct loader_icd *icd, uint32_t gpu_index, uint32_t ext_count, const char *const* ext_names) +uint32_t loader_activate_instance_layers(struct loader_instance *inst) +{ + uint32_t count; + struct layer_name_pair *pLayerNames; + if (inst == NULL) + return 0; + + // NOTE inst is unwrapped at this point in time + VkObject baseObj = (VkObject) inst; + VkObject nextObj = (VkObject) inst; + VkBaseLayerObject *nextInstObj; + PFN_vkGetInstanceProcAddr nextGPA = loader_gpa_instance_internal; + + count = loader_get_layer_libs(inst->extension_count, (const char *const*) inst->extension_names, &pLayerNames); + if (!count) + return 0; + loader_init_instance_layer_libs(inst, pLayerNames, count); + + inst->wrappedInstance = malloc(sizeof(VkBaseLayerObject) * count); + if (! inst->wrappedInstance) { + loader_log(VK_DBG_MSG_ERROR, 0, "Failed to malloc Instance objects for layer"); + return 0; + } + for (int32_t i = count - 1; i >= 0; i--) { + nextInstObj = (inst->wrappedInstance + i); + nextInstObj->pGPA = nextGPA; + nextInstObj->baseObject = baseObj; + nextInstObj->nextObject = nextObj; + nextObj = (VkObject) nextInstObj; + + char funcStr[256]; + snprintf(funcStr, 256, "%sGetInstanceProcAddr",inst->layer_libs[i].name); + if ((nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(inst->layer_libs[i].lib_handle, funcStr)) == NULL) + nextGPA = (PFN_vkGetInstanceProcAddr) loader_platform_get_proc_address(inst->layer_libs[i].lib_handle, "vkGetInstanceProcAddr"); + if (!nextGPA) { + loader_log(VK_DBG_MSG_ERROR, 0, "Failed to find vkGetInstanceProcAddr in layer %s", inst->layer_libs[i].name); + continue; + } + + if (i == 0) { + loader_init_instance_dispatch_table(inst->disp, nextGPA, (VkInstance) nextObj); + //Insert the new wrapped objects into the list with loader object at head + nextInstObj = inst->wrappedInstance + inst->layer_count - 1; + nextInstObj->nextObject = baseObj; + nextInstObj->pGPA = loader_gpa_instance_internal; + } + + } + + return inst->layer_count; +} + +extern uint32_t loader_activate_device_layers(struct loader_icd *icd, uint32_t gpu_index, uint32_t ext_count, const char *const* ext_names) { uint32_t count; VkBaseLayerObject *gpu; @@ -1018,18 +1128,21 @@ extern uint32_t loader_activate_layers(struct loader_icd *icd, uint32_t gpu_inde gpu = icd->gpus + gpu_index; /* activate any layer libraries */ if (!loader_layers_activated(icd, gpu_index)) { + // Note gpu object is wrapped once already VkBaseLayerObject *gpuObj = gpu; VkBaseLayerObject *nextGpuObj, *baseObj = (VkBaseLayerObject *) gpuObj->baseObject; - PFN_vkGetProcAddr nextGPA = loader_gpa_internal; + PFN_vkGetProcAddr nextGPA = loader_gpa_device_internal; count = loader_get_layer_libs(ext_count, ext_names, &pLayerNames); if (!count) return 0; - loader_init_layer_libs(icd, gpu_index, pLayerNames, count); + loader_init_device_layer_libs(icd, gpu_index, pLayerNames, count); icd->wrappedGpus[gpu_index] = malloc(sizeof(VkBaseLayerObject) * icd->layer_count[gpu_index]); - if (! icd->wrappedGpus[gpu_index]) + if (! icd->wrappedGpus[gpu_index]) { loader_log(VK_DBG_MSG_ERROR, 0, "Failed to malloc Gpu objects for layer"); + return 0; + } for (int32_t i = icd->layer_count[gpu_index] - 1; i >= 0; i--) { nextGpuObj = (icd->wrappedGpus[gpu_index] + i); nextGpuObj->pGPA = nextGPA; @@ -1074,45 +1187,14 @@ extern uint32_t loader_activate_layers(struct loader_icd *icd, uint32_t gpu_inde return icd->layer_count[gpu_index]; } -LOADER_EXPORT VkResult VKAPI vkCreateInstance( +VkResult loader_CreateInstance( const VkInstanceCreateInfo* pCreateInfo, VkInstance* pInstance) { - struct loader_instance *ptr_instance = NULL; + struct loader_instance *ptr_instance = (struct loader_instance *) pInstance; struct loader_scanned_icds *scanned_icds; struct loader_icd *icd; - VkResult res = VK_ERROR_INITIALIZATION_FAILED; - uint32_t i; - - /* Scan/discover all ICD libraries in a single-threaded manner */ - loader_platform_thread_once(&once_icd, loader_icd_scan); - - /* get layer libraries in a single-threaded manner */ - loader_platform_thread_once(&once_layer, layer_lib_scan); - - /* merge any duplicate extensions */ - loader_platform_thread_once(&once_exts, loader_coalesce_extensions); - - ptr_instance = (struct loader_instance*) malloc(sizeof(struct loader_instance)); - if (ptr_instance == NULL) { - return VK_ERROR_OUT_OF_HOST_MEMORY; - } - memset(ptr_instance, 0, sizeof(struct loader_instance)); - ptr_instance->extension_count = pCreateInfo->extensionCount; - ptr_instance->extension_names = (ptr_instance->extension_count > 0) ? - malloc(sizeof (char *) * ptr_instance->extension_count) : NULL; - if (ptr_instance->extension_names == NULL && (ptr_instance->extension_count > 0)) - return VK_ERROR_OUT_OF_HOST_MEMORY; - for (i = 0; i < ptr_instance->extension_count; i++) { - if (!loader_is_extension_scanned(pCreateInfo->ppEnabledExtensionNames[i])) - return VK_ERROR_INVALID_EXTENSION; - ptr_instance->extension_names[i] = malloc(strlen(pCreateInfo->ppEnabledExtensionNames[i]) + 1); - if (ptr_instance->extension_names[i] == NULL) - return VK_ERROR_OUT_OF_HOST_MEMORY; - strcpy(ptr_instance->extension_names[i], pCreateInfo->ppEnabledExtensionNames[i]); - } - ptr_instance->next = loader.instances; - loader.instances = ptr_instance; + VkResult res; scanned_icds = loader.scanned_icd_list; while (scanned_icds) { @@ -1136,12 +1218,10 @@ LOADER_EXPORT VkResult VKAPI vkCreateInstance( return VK_ERROR_INCOMPATIBLE_DRIVER; } - loader_init_instance_dispatch_table(&ptr_instance->disp); - *pInstance = (VkInstance) ptr_instance; return VK_SUCCESS; } -LOADER_EXPORT VkResult VKAPI vkDestroyInstance( +VkResult loader_DestroyInstance( VkInstance instance) { struct loader_instance *ptr_instance = (struct loader_instance *) instance; @@ -1172,8 +1252,7 @@ LOADER_EXPORT VkResult VKAPI vkDestroyInstance( return VK_ERROR_INVALID_HANDLE; } - // cleanup any prior layer initializations - loader_deactivate_layer(ptr_instance); + loader_deactivate_instance_layer(ptr_instance); scanned_icds = loader.scanned_icd_list; while (scanned_icds) { @@ -1192,7 +1271,7 @@ LOADER_EXPORT VkResult VKAPI vkDestroyInstance( return VK_SUCCESS; } -LOADER_EXPORT VkResult VKAPI vkEnumeratePhysicalDevices( +VkResult loader_EnumeratePhysicalDevices( VkInstance instance, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices) @@ -1260,7 +1339,7 @@ LOADER_EXPORT VkResult VKAPI vkEnumeratePhysicalDevices( const VkLayerDispatchTable **disp; disp = (const VkLayerDispatchTable **) gpus[i]; *disp = icd->loader_dispatch + i; - loader_activate_layers(icd, i, ptr_instance->extension_count, + loader_activate_device_layers(icd, i, ptr_instance->extension_count, (const char *const*) ptr_instance->extension_names); } @@ -1313,7 +1392,7 @@ LOADER_EXPORT void * VKAPI vkGetProcAddr(VkPhysicalDevice gpu, const char * pNam if (disp_table == NULL) return NULL; - addr = loader_lookup_dispatch_table(disp_table, pName); + addr = loader_lookup_device_dispatch_table(disp_table, pName); if (addr) return addr; else { @@ -1329,7 +1408,7 @@ LOADER_EXPORT void * VKAPI vkGetProcAddr(VkPhysicalDevice gpu, const char * pNam //TODO how is layer extension going to be enabled? //Need to call createInstance on the layer or something -LOADER_EXPORT VkResult VKAPI vkGetGlobalExtensionInfo( +VkResult loader_GetGlobalExtensionInfo( VkExtensionInfoType infoType, uint32_t extensionIndex, size_t* pDataSize, @@ -1454,7 +1533,7 @@ LOADER_EXPORT VkResult VKAPI vkEnumerateLayers(VkPhysicalDevice gpu, size_t maxS return VK_SUCCESS; } -LOADER_EXPORT VkResult VKAPI vkDbgRegisterMsgCallback(VkInstance instance, VK_DBG_MSG_CALLBACK_FUNCTION pfnMsgCallback, void* pUserData) +VkResult loader_DbgRegisterMsgCallback(VkInstance instance, VK_DBG_MSG_CALLBACK_FUNCTION pfnMsgCallback, void* pUserData) { const struct loader_icd *icd; struct loader_instance *inst; @@ -1505,7 +1584,7 @@ LOADER_EXPORT VkResult VKAPI vkDbgRegisterMsgCallback(VkInstance instance, VK_DB return VK_SUCCESS; } -LOADER_EXPORT VkResult VKAPI vkDbgUnregisterMsgCallback(VkInstance instance, VK_DBG_MSG_CALLBACK_FUNCTION pfnMsgCallback) +VkResult loader_DbgUnregisterMsgCallback(VkInstance instance, VK_DBG_MSG_CALLBACK_FUNCTION pfnMsgCallback) { VkResult res = VK_SUCCESS; struct loader_instance *inst; @@ -1534,7 +1613,7 @@ LOADER_EXPORT VkResult VKAPI vkDbgUnregisterMsgCallback(VkInstance instance, VK_ return res; } -LOADER_EXPORT VkResult VKAPI vkDbgSetGlobalOption(VkInstance instance, VK_DBG_GLOBAL_OPTION dbgOption, size_t dataSize, const void* pData) +VkResult loader_DbgSetGlobalOption(VkInstance instance, VK_DBG_GLOBAL_OPTION dbgOption, size_t dataSize, const void* pData) { VkResult res = VK_SUCCESS; struct loader_instance *inst; diff --git a/loader/loader.h b/loader/loader.h index 0a92828e..c2e15a57 100644 --- a/loader/loader.h +++ b/loader/loader.h @@ -43,6 +43,45 @@ # define LOADER_EXPORT #endif +#define MAX_LAYER_LIBRARIES 64 +#define MAX_GPUS_FOR_LAYER 16 + +struct loader_scanned_layers { + char *name; + uint32_t extension_count; + struct extension_property *extensions; +}; + +struct loader_layers { + loader_platform_dl_handle lib_handle; + char name[256]; +}; + +struct loader_instance { + VkLayerInstanceDispatchTable *disp; + uint32_t layer_count; + struct loader_layers layer_libs[MAX_LAYER_LIBRARIES]; + VkBaseLayerObject *wrappedInstance; + uint32_t total_gpu_count; + struct loader_icd *icds; + struct loader_instance *next; + uint32_t extension_count; + char **extension_names; +}; + +struct loader_struct { + struct loader_instance *instances; + bool icds_scanned; + struct loader_scanned_icds *scanned_icd_list; + bool layer_scanned; + char *layer_dirs; + unsigned int scanned_layer_count; + struct loader_scanned_layers scanned_layers[MAX_LAYER_LIBRARIES]; + size_t scanned_ext_list_capacity; + uint32_t scanned_ext_list_count; // coalesced from all layers/drivers + struct extension_property **scanned_ext_list; +}; + static inline void loader_set_dispatch(VkObject obj, const void *data) { *((const void **) obj) = data; @@ -53,6 +92,11 @@ static inline VkLayerDispatchTable *loader_get_dispatch(const VkObject obj) return *((VkLayerDispatchTable **) obj); } +static inline VkLayerInstanceDispatchTable *loader_get_instance_dispatch(const VkObject obj) +{ + return *((VkLayerInstanceDispatchTable **) obj); +} + static inline void loader_init_dispatch(VkObject obj, const void *data) { #ifdef DEBUG @@ -63,17 +107,51 @@ static inline void loader_init_dispatch(VkObject obj, const void *data) loader_set_dispatch(obj, data); } -struct loader_instance { - VkLayerInstanceDispatchTable disp; - uint32_t total_gpu_count; - struct loader_icd *icds; - struct loader_instance *next; - uint32_t extension_count; - char **extension_names; -}; +/* global variables used across files */ +extern struct loader_struct loader; +extern LOADER_PLATFORM_THREAD_ONCE_DEFINITION(once_icd); +extern LOADER_PLATFORM_THREAD_ONCE_DEFINITION(once_layer); +extern LOADER_PLATFORM_THREAD_ONCE_DEFINITION(once_exts); +extern VkLayerInstanceDispatchTable instance_disp; -extern uint32_t loader_activate_layers(struct loader_icd *icd, uint32_t gpu_index, uint32_t ext_count, const char *const* ext_names); -#define MAX_LAYER_LIBRARIES 64 -#define MAX_GPUS_FOR_LAYER 16 +/* instance layer chain termination entrypoint definitions */ +VkResult loader_CreateInstance( + const VkInstanceCreateInfo* pCreateInfo, + VkInstance* pInstance); + +VkResult loader_DestroyInstance( + VkInstance instance); + +VkResult loader_EnumeratePhysicalDevices( + VkInstance instance, + uint32_t* pPhysicalDeviceCount, + VkPhysicalDevice* pPhysicalDevices); + +VkResult VKAPI loader_GetGlobalExtensionInfo( + VkExtensionInfoType infoType, + uint32_t extensionIndex, + size_t* pDataSize, + void* pData); + +VkResult loader_DbgRegisterMsgCallback( + VkInstance instance, + VK_DBG_MSG_CALLBACK_FUNCTION pfnMsgCallback, + void* pUserData); + +VkResult loader_DbgUnregisterMsgCallback( + VkInstance instance, + VK_DBG_MSG_CALLBACK_FUNCTION pfnMsgCallback); + +VkResult loader_DbgSetGlobalOption( + VkInstance instance, + VK_DBG_GLOBAL_OPTION dbgOption, + size_t dataSize, + const void* pData); +/* function definitions */ +bool loader_is_extension_scanned(const char *name); +void loader_icd_scan(void); +void layer_lib_scan(void); +void loader_coalesce_extensions(void); +uint32_t loader_activate_instance_layers(struct loader_instance *inst); #endif /* LOADER_H */ diff --git a/loader/loader_platform.h b/loader/loader_platform.h index 4bbd8b30..66b24cb3 100644 --- a/loader/loader_platform.h +++ b/loader/loader_platform.h @@ -97,6 +97,8 @@ static inline char * loader_platform_get_proc_address_error(const char *name) typedef pthread_t loader_platform_thread; #define LOADER_PLATFORM_THREAD_ONCE_DECLARATION(var) \ pthread_once_t var = PTHREAD_ONCE_INIT; +#define LOADER_PLATFORM_THREAD_ONCE_DEFINITION(var) \ + pthread_once_t var; static inline void loader_platform_thread_once(void *ctl, void (* func) (void)) { assert(func != NULL); @@ -251,6 +253,8 @@ static char * loader_platform_get_proc_address_error(const char *name) typedef HANDLE loader_platform_thread; #define LOADER_PLATFORM_THREAD_ONCE_DECLARATION(var) \ INIT_ONCE var = INIT_ONCE_STATIC_INIT; +#define LOADER_PLATFORM_THREAD_ONCE_DEFINITION(var) \ + INIT_ONCE var; static BOOL CALLBACK InitFuncWrapper(PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context) { void (*func)(void) = (void (*)(void))Parameter; diff --git a/loader/table_ops.h b/loader/table_ops.h index ca207f92..fedfb79d 100644 --- a/loader/table_ops.h +++ b/loader/table_ops.h @@ -25,13 +25,14 @@ #include #include #include +#include "loader.h" #include "loader_platform.h" static inline void loader_init_device_dispatch_table(VkLayerDispatchTable *table, PFN_vkGetProcAddr gpa, VkPhysicalDevice gpu) { - table->CreateInstance = (PFN_vkCreateInstance) gpa(gpu, "vkCreateInstance"); + table->CreateInstance = vkCreateInstance; /* non-dispatchable */ table->DestroyInstance = (PFN_vkDestroyInstance) gpa(gpu, "vkDestroyInstance"); table->EnumeratePhysicalDevices = (PFN_vkEnumeratePhysicalDevices) gpa(gpu, "vkEnumeratePhysicalDevices"); table->GetPhysicalDeviceInfo = (PFN_vkGetPhysicalDeviceInfo) gpa(gpu, "vkGetPhysicalDeviceInfo"); @@ -161,8 +162,9 @@ static inline void loader_init_device_dispatch_table(VkLayerDispatchTable *table table->QueuePresentWSI = (PFN_vkQueuePresentWSI) gpa(gpu, "vkQueuePresentWSI"); } -static inline void *loader_lookup_dispatch_table(const VkLayerDispatchTable *table, - const char *name) +static inline void *loader_lookup_device_dispatch_table( + const VkLayerDispatchTable *table, + const char *name) { if (!name || name[0] != 'v' || name[1] != 'k') return NULL; @@ -424,18 +426,62 @@ static inline void *loader_lookup_dispatch_table(const VkLayerDispatchTable *tab return NULL; } -static inline void loader_init_instance_dispatch_table(VkLayerInstanceDispatchTable *table) +static inline void loader_init_instance_dispatch_table(VkLayerInstanceDispatchTable *table, + PFN_vkGetInstanceProcAddr gpa, + VkInstance inst) { - table->DestroyInstance = vkDestroyInstance; - table->EnumeratePhysicalDevices = vkEnumeratePhysicalDevices; - table->GetPhysicalDeviceInfo = vkGetPhysicalDeviceInfo; - table->GetInstanceProcAddr = vkGetInstanceProcAddr; - table->GetProcAddr = vkGetProcAddr; - table->CreateDevice = vkCreateDevice; - table->GetPhysicalDeviceExtensionInfo = vkGetPhysicalDeviceExtensionInfo; - table->EnumerateLayers = vkEnumerateLayers; - table->GetMultiDeviceCompatibility = vkGetMultiDeviceCompatibility; - table->DbgRegisterMsgCallback = vkDbgRegisterMsgCallback; - table->DbgUnregisterMsgCallback = vkDbgUnregisterMsgCallback; - table->DbgSetGlobalOption = vkDbgSetGlobalOption; + table->CreateInstance = (PFN_vkCreateInstance) gpa(inst, "vkCreateInstance"); + table->DestroyInstance = (PFN_vkDestroyInstance) gpa(inst, "vkDestroyInstance"); + table->EnumeratePhysicalDevices = (PFN_vkEnumeratePhysicalDevices) gpa(inst, "vkEnumeratePhysicalDevices"); + table->GetPhysicalDeviceInfo = (PFN_vkGetPhysicalDeviceInfo) gpa(inst, "vkGetPhysicalDeviceInfo"); + table->GetInstanceProcAddr = (PFN_vkGetInstanceProcAddr) gpa(inst, "vkGetInstanceProcAddr"); + table->GetProcAddr = (PFN_vkGetProcAddr) gpa(inst, "vkGetProcAddr"); + table->CreateDevice = (PFN_vkCreateDevice) gpa(inst, "vkCreateDevice"); + table->GetGlobalExtensionInfo = (PFN_vkGetGlobalExtensionInfo) gpa(inst,"vkGetGlobalExtensionInfo"); + table->GetPhysicalDeviceExtensionInfo = (PFN_vkGetPhysicalDeviceExtensionInfo) gpa(inst, "vkGetPhysicalDeviceExtensionInfo"); + table->EnumerateLayers = (PFN_vkEnumerateLayers) gpa(inst, "vkEnumerateLayers"); + table->GetMultiDeviceCompatibility = (PFN_vkGetMultiDeviceCompatibility) gpa(inst, "vkGetMultiDeviceCompatibility"); + table->DbgRegisterMsgCallback = (PFN_vkDbgRegisterMsgCallback) gpa(inst, "vkDbgRegisterMsgCallback"); + table->DbgUnregisterMsgCallback = (PFN_vkDbgUnregisterMsgCallback) gpa(inst, "vkDbgUnregisterMsgCallback"); + table->DbgSetGlobalOption = (PFN_vkDbgSetGlobalOption) gpa(inst, "vkDbgSetGlobalOption"); } + +static inline void *loader_lookup_instance_dispatch_table( + const VkLayerInstanceDispatchTable *table, + const char *name) +{ + if (!name || name[0] != 'v' || name[1] != 'k') + return NULL; + + name += 2; + if (!strcmp(name, "CreateInstance")) + return (void *) table->CreateInstance; + if (!strcmp(name, "DestroyInstance")) + return (void *) table->DestroyInstance; + if (!strcmp(name, "EnumeratePhysicalDevices")) + return (void *) table->EnumeratePhysicalDevices; + if (!strcmp(name, "GetPhysicalDeviceInfo")) + return (void *) table->GetPhysicalDeviceInfo; + if (!strcmp(name, "GetInstanceProcAddr")) + return (void *) table->GetInstanceProcAddr; + if (!strcmp(name, "GetProcAddr")) + return (void *) table->GetProcAddr; + if (!strcmp(name, "CreateDevice")) + return (void *) table->CreateDevice; + if (!strcmp(name, "GetGlobalExtensionInfo")) + return (void *) table->GetGlobalExtensionInfo; + if (!strcmp(name, "GetPhysicalDeviceExtensionInfo")) + return (void *) table->GetPhysicalDeviceExtensionInfo; + if (!strcmp(name, "EnumerateLayers")) + return (void *) table->EnumerateLayers; + if (!strcmp(name, "GetMultiDeviceCompatibility")) + return (void *) table->GetMultiDeviceCompatibility; + if (!strcmp(name, "DbgRegisterMsgCallback")) + return (void *) table->DbgRegisterMsgCallback; + if (!strcmp(name, "DbgUnregisterMsgCallback")) + return (void *) table->DbgUnregisterMsgCallback; + if (!strcmp(name, "DbgSetGlobalOption")) + return (void *) table->DbgSetGlobalOption; + + return NULL; +} \ No newline at end of file diff --git a/loader/trampoline.c b/loader/trampoline.c index 082a5c2f..b7b6c58d 100644 --- a/loader/trampoline.c +++ b/loader/trampoline.c @@ -21,7 +21,10 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ +#include +#include +#include "loader_platform.h" #include "loader.h" #if defined(WIN32) @@ -31,7 +34,78 @@ #endif /* Trampoline entrypoints */ -LOADER_EXPORT VkResult VKAPI vkGetPhysicalDeviceInfo(VkPhysicalDevice gpu, VkPhysicalDeviceInfoType infoType, size_t* pDataSize, void* pData) +LOADER_EXPORT VkResult VKAPI vkCreateInstance( + const VkInstanceCreateInfo* pCreateInfo, + VkInstance* pInstance) +{ + struct loader_instance *ptr_instance = NULL; + + VkResult res = VK_ERROR_INITIALIZATION_FAILED; + uint32_t i; + + /* Scan/discover all ICD libraries in a single-threaded manner */ + loader_platform_thread_once(&once_icd, loader_icd_scan); + + /* get layer libraries in a single-threaded manner */ + loader_platform_thread_once(&once_layer, layer_lib_scan); + + /* merge any duplicate extensions */ + loader_platform_thread_once(&once_exts, loader_coalesce_extensions); + + ptr_instance = (struct loader_instance*) malloc(sizeof(struct loader_instance)); + if (ptr_instance == NULL) { + return VK_ERROR_OUT_OF_HOST_MEMORY; + } + memset(ptr_instance, 0, sizeof(struct loader_instance)); + ptr_instance->extension_count = pCreateInfo->extensionCount; + ptr_instance->extension_names = (ptr_instance->extension_count > 0) ? + malloc(sizeof (char *) * ptr_instance->extension_count) : NULL; + if (ptr_instance->extension_names == NULL && (ptr_instance->extension_count > 0)) + return VK_ERROR_OUT_OF_HOST_MEMORY; + for (i = 0; i < ptr_instance->extension_count; i++) { + if (!loader_is_extension_scanned(pCreateInfo->ppEnabledExtensionNames[i])) + return VK_ERROR_INVALID_EXTENSION; + ptr_instance->extension_names[i] = malloc(strlen(pCreateInfo->ppEnabledExtensionNames[i]) + 1); + if (ptr_instance->extension_names[i] == NULL) + return VK_ERROR_OUT_OF_HOST_MEMORY; + strcpy(ptr_instance->extension_names[i], pCreateInfo->ppEnabledExtensionNames[i]); + } + ptr_instance->next = loader.instances; + loader.instances = ptr_instance; + ptr_instance->disp = &instance_disp; + loader_activate_instance_layers(ptr_instance); + + res = instance_disp.CreateInstance(pCreateInfo, (VkInstance *) ptr_instance); + + *pInstance = (VkInstance) ptr_instance; + return res; +} + +LOADER_EXPORT VkResult VKAPI vkDestroyInstance( + VkInstance instance) +{ + const VkLayerInstanceDispatchTable *disp; + + disp = loader_get_instance_dispatch(instance); + return disp->DestroyInstance(instance); +} +LOADER_EXPORT VkResult VKAPI vkEnumeratePhysicalDevices( + VkInstance instance, + uint32_t* pPhysicalDeviceCount, + VkPhysicalDevice* pPhysicalDevices) +{ + const VkLayerInstanceDispatchTable *disp; + + disp = loader_get_instance_dispatch(instance); + return disp->EnumeratePhysicalDevices(instance, pPhysicalDeviceCount, + pPhysicalDevices); +} + +LOADER_EXPORT VkResult VKAPI vkGetPhysicalDeviceInfo( + VkPhysicalDevice gpu, + VkPhysicalDeviceInfoType infoType, + size_t* pDataSize, + void* pData) { const VkLayerDispatchTable *disp; VkResult res; @@ -68,10 +142,23 @@ LOADER_EXPORT VkResult VKAPI vkCreateDevice(VkPhysicalDevice gpu, const VkDevice LOADER_EXPORT VkResult VKAPI vkDestroyDevice(VkDevice device) { const VkLayerDispatchTable *disp; + VkResult res; disp = loader_get_dispatch(device); - return disp->DestroyDevice(device); + res = disp->DestroyDevice(device); + // TODO need to keep track of device objs to be able to get icd/gpu to deactivate + //loader_deactivate_device_layer(device); + return res; +} + +LOADER_EXPORT VkResult VKAPI vkGetGlobalExtensionInfo( + VkExtensionInfoType infoType, + uint32_t extensionIndex, + size_t* pDataSize, + void* pData) +{ + return instance_disp.GetGlobalExtensionInfo(infoType, extensionIndex, pDataSize, pData); } LOADER_EXPORT VkResult VKAPI vkGetPhysicalDeviceExtensionInfo(VkPhysicalDevice gpu, VkExtensionInfoType infoType, uint32_t extensionIndex, size_t* pDataSize, void* pData) @@ -1022,6 +1109,33 @@ LOADER_EXPORT void VKAPI vkCmdEndRenderPass(VkCmdBuffer cmdBuffer, VkRenderPass disp->CmdEndRenderPass(cmdBuffer, renderPass); } +LOADER_EXPORT VkResult VKAPI vkDbgRegisterMsgCallback(VkInstance instance, VK_DBG_MSG_CALLBACK_FUNCTION pfnMsgCallback, void* pUserData) +{ + const VkLayerInstanceDispatchTable *disp; + + disp = loader_get_instance_dispatch(instance); + + return disp->DbgRegisterMsgCallback(instance, pfnMsgCallback, pUserData); +} + +LOADER_EXPORT VkResult VKAPI vkDbgUnregisterMsgCallback(VkInstance instance, VK_DBG_MSG_CALLBACK_FUNCTION pfnMsgCallback) +{ + const VkLayerInstanceDispatchTable *disp; + + disp = loader_get_instance_dispatch(instance); + + return disp->DbgUnregisterMsgCallback(instance, pfnMsgCallback); +} + +LOADER_EXPORT VkResult VKAPI vkDbgSetGlobalOption(VkInstance instance, VK_DBG_GLOBAL_OPTION dbgOption, size_t dataSize, const void* pData) +{ + const VkLayerInstanceDispatchTable *disp; + + disp = loader_get_instance_dispatch(instance); + + return disp->DbgSetGlobalOption(instance, dbgOption, dataSize, pData); +} + LOADER_EXPORT VkResult VKAPI vkDbgSetValidationLevel(VkDevice device, VkValidationLevel validationLevel) { const VkLayerDispatchTable *disp; -- cgit v1.2.3