aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJon Ashburn <jon@lunarg.com>2015-05-12 17:26:48 -0600
committerCourtney Goeltzenleuchter <courtney@LunarG.com>2015-06-17 19:47:02 -0600
commit879c136f156308edbc2beba828d4fabb423f9a9d (patch)
treeaae5c80638409ace3d7bc677d354a8d27d88c798
parentfc1b02ddb65594ad2de9c6077f3462385cb7f6d8 (diff)
downloadusermoji-879c136f156308edbc2beba828d4fabb423f9a9d.tar.xz
loader: Activate layers on the instance chain at CreateInstance
-rw-r--r--loader/loader.c269
-rw-r--r--loader/loader.h100
-rw-r--r--loader/loader_platform.h4
-rw-r--r--loader/table_ops.h78
-rw-r--r--loader/trampoline.c118
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 <dirent.h>
#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 <vulkan.h>
#include <vkLayer.h>
#include <string.h>
+#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 <stdlib.h>
+#include <string.h>
+#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;