loader: implement new layer init method
New layer init method requires the construction of
Link information for CreateInstance and CreateDevice
that is accessible to layers via the CreateInfo.pNext pointer.
The layer can then use the Get*ProcAddr from the Link
structure to initialize their dispatch table if the
call down the chain returns successfully.
This removes the need to do special initialization work
at Get*ProcAddr time.
Layer Get*ProcAddr now return their internal function
pointers regardless of the value of instance or device.
Only need to have valid instance & device when looking
up extensions or when passing the request down the chain.
This mechanism allows us to remove object wrapping used
by the loader previously. Also simplifies the dispatch table
setup.
Conflicts:
layers/device_limits.cpp
layers/draw_state.cpp
loader/loader.c
loader/trampoline.c
diff --git a/layers/mem_tracker.cpp b/layers/mem_tracker.cpp
index b621c6e..afcc7cd 100644
--- a/layers/mem_tracker.cpp
+++ b/layers/mem_tracker.cpp
@@ -1119,19 +1119,35 @@
const VkAllocationCallbacks* pAllocator,
VkInstance* pInstance)
{
- layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
- VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table;
- VkResult result = pTable->CreateInstance(pCreateInfo, pAllocator, pInstance);
+ VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
- if (result == VK_SUCCESS) {
- my_data->report_data = debug_report_create_instance(
- pTable,
- *pInstance,
- pCreateInfo->enabledExtensionCount,
- pCreateInfo->ppEnabledExtensionNames);
-
- init_mem_tracker(my_data, pAllocator);
+ assert(chain_info->u.pLayerInfo);
+ PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
+ PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance) fpGetInstanceProcAddr(NULL, "vkCreateInstance");
+ if (fpCreateInstance == NULL) {
+ return VK_ERROR_INITIALIZATION_FAILED;
}
+
+ // Advance the link info for the next element on the chain
+ chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
+
+ VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
+ if (result != VK_SUCCESS) {
+ return result;
+ }
+
+ layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
+ my_data->instance_dispatch_table = new VkLayerInstanceDispatchTable;
+ layer_init_instance_dispatch_table(*pInstance, my_data->instance_dispatch_table, fpGetInstanceProcAddr);
+
+ my_data->report_data = debug_report_create_instance(
+ my_data->instance_dispatch_table,
+ *pInstance,
+ pCreateInfo->enabledExtensionCount,
+ pCreateInfo->ppEnabledExtensionNames);
+
+ init_mem_tracker(my_data, pAllocator);
+
return result;
}
@@ -1161,15 +1177,35 @@
const VkAllocationCallbacks *pAllocator,
VkDevice *pDevice)
{
- layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
- VkLayerDispatchTable *pDeviceTable = my_device_data->device_dispatch_table;
- VkResult result = pDeviceTable->CreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
- if (result == VK_SUCCESS) {
- layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(gpu), layer_data_map);
- my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
- createDeviceRegisterExtensions(pCreateInfo, *pDevice);
- my_instance_data->instance_dispatch_table->GetPhysicalDeviceProperties(gpu, &my_device_data->properties);
+ VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
+
+ assert(chain_info->u.pLayerInfo);
+ PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
+ PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
+ PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice) fpGetInstanceProcAddr(NULL, "vkCreateDevice");
+ if (fpCreateDevice == NULL) {
+ return VK_ERROR_INITIALIZATION_FAILED;
}
+
+ // Advance the link info for the next element on the chain
+ chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
+
+ VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
+ if (result != VK_SUCCESS) {
+ return result;
+ }
+
+ layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(gpu), layer_data_map);
+ layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
+
+ // Setup device dispatch table
+ my_device_data->device_dispatch_table = new VkLayerDispatchTable;
+ layer_init_device_dispatch_table(*pDevice, my_device_data->device_dispatch_table, fpGetDeviceProcAddr);
+
+ my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
+ createDeviceRegisterExtensions(pCreateInfo, *pDevice);
+ my_instance_data->instance_dispatch_table->GetPhysicalDeviceProperties(gpu, &my_device_data->properties);
+
return result;
}
@@ -3192,20 +3228,8 @@
VkDevice dev,
const char *funcName)
{
- if (dev == NULL)
- return NULL;
-
- layer_data *my_data;
- /* loader uses this to force layer initialization; device object is wrapped */
- if (!strcmp(funcName, "vkGetDeviceProcAddr")) {
- VkBaseLayerObject* wrapped_dev = (VkBaseLayerObject*) dev;
- my_data = get_my_data_ptr(get_dispatch_key(wrapped_dev->baseObject), layer_data_map);
- my_data->device_dispatch_table = new VkLayerDispatchTable;
- layer_initialize_dispatch_table(my_data->device_dispatch_table, wrapped_dev);
+ if (!strcmp(funcName, "vkGetDeviceProcAddr"))
return (PFN_vkVoidFunction) vkGetDeviceProcAddr;
- }
- if (!strcmp(funcName, "vkCreateDevice"))
- return (PFN_vkVoidFunction) vkCreateDevice;
if (!strcmp(funcName, "vkDestroyDevice"))
return (PFN_vkVoidFunction) vkDestroyDevice;
if (!strcmp(funcName, "vkQueueSubmit"))
@@ -3332,6 +3356,10 @@
return (PFN_vkVoidFunction) vkDestroyFramebuffer;
+ if (dev == NULL)
+ return NULL;
+
+ layer_data *my_data;
my_data = get_my_data_ptr(get_dispatch_key(dev), layer_data_map);
if (my_data->wsi_enabled)
{
@@ -3358,25 +3386,19 @@
const char *funcName)
{
PFN_vkVoidFunction fptr;
- if (instance == NULL)
- return NULL;
- layer_data *my_data;
- /* loader uses this to force layer initialization; instance object is wrapped */
- if (!strcmp(funcName, "vkGetInstanceProcAddr")) {
- VkBaseLayerObject* wrapped_inst = (VkBaseLayerObject*) instance;
- my_data = get_my_data_ptr(get_dispatch_key(wrapped_inst->baseObject), layer_data_map);
- my_data->instance_dispatch_table = new VkLayerInstanceDispatchTable;
- layer_init_instance_dispatch_table(my_data->instance_dispatch_table, wrapped_inst);
+ if (!strcmp(funcName, "vkGetInstanceProcAddr"))
return (PFN_vkVoidFunction) vkGetInstanceProcAddr;
- }
- my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
+ if (!strcmp(funcName, "vkGetDeviceProcAddr"))
+ return (PFN_vkVoidFunction) vkGetDeviceProcAddr;
if (!strcmp(funcName, "vkDestroyInstance"))
return (PFN_vkVoidFunction) vkDestroyInstance;
if (!strcmp(funcName, "vkCreateInstance"))
return (PFN_vkVoidFunction) vkCreateInstance;
if (!strcmp(funcName, "vkGetPhysicalDeviceMemoryProperties"))
return (PFN_vkVoidFunction) vkGetPhysicalDeviceMemoryProperties;
+ if (!strcmp(funcName, "vkCreateDevice"))
+ return (PFN_vkVoidFunction) vkCreateDevice;
if (!strcmp(funcName, "vkEnumerateInstanceLayerProperties"))
return (PFN_vkVoidFunction) vkEnumerateInstanceLayerProperties;
if (!strcmp(funcName, "vkEnumerateInstanceExtensionProperties"))
@@ -3386,14 +3408,16 @@
if (!strcmp(funcName, "vkEnumerateDeviceExtensionProperties"))
return (PFN_vkVoidFunction) vkEnumerateDeviceExtensionProperties;
- fptr = debug_report_get_instance_proc_addr(my_data->report_data, funcName);
- if (fptr)
- return fptr;
+ if (instance == NULL) return NULL;
- {
- VkLayerInstanceDispatchTable* pTable = my_data->instance_dispatch_table;
- if (pTable->GetInstanceProcAddr == NULL)
- return NULL;
- return pTable->GetInstanceProcAddr(instance, funcName);
- }
+ layer_data *my_data;
+ my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
+
+ fptr = debug_report_get_instance_proc_addr(my_data->report_data, funcName);
+ if (fptr) return fptr;
+
+ VkLayerInstanceDispatchTable* pTable = my_data->instance_dispatch_table;
+ if (pTable->GetInstanceProcAddr == NULL)
+ return NULL;
+ return pTable->GetInstanceProcAddr(instance, funcName);
}