diff --git a/renderdoc/driver/vulkan/official/vk_ext_debug_report.h b/renderdoc/driver/vulkan/official/vk_ext_debug_report.h index 84f32299c..a9c2a5695 100644 --- a/renderdoc/driver/vulkan/official/vk_ext_debug_report.h +++ b/renderdoc/driver/vulkan/official/vk_ext_debug_report.h @@ -44,11 +44,11 @@ extern "C" * DebugReport Vulkan Extension API *************************************************************************************************** */ + #define VK_EXT_debug_report 1 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugReportCallbackEXT) -#define VK_EXT_DEBUG_REPORT_REVISION 2 -#define VK_EXT_DEBUG_REPORT_EXTENSION_NUMBER 11 +#define VK_EXT_DEBUG_REPORT_SPEC_VERSION 1 #define VK_EXT_DEBUG_REPORT_EXTENSION_NAME "VK_EXT_debug_report" @@ -85,10 +85,11 @@ typedef enum VkDebugReportObjectTypeEXT { } VkDebugReportObjectTypeEXT; typedef enum VkDebugReportErrorEXT { - VK_DEBUG_REPORT_ERROR_NONE = 0, - VK_DEBUG_REPORT_ERROR_CALLBACK_REF = 1, + VK_DEBUG_REPORT_ERROR_NONE_EXT = 0, + VK_DEBUG_REPORT_ERROR_CALLBACK_REF_EXT = 1, } VkDebugReportErrorEXT; + typedef enum VkDebugReportFlagBitsEXT { VK_DEBUG_REPORT_INFO_BIT_EXT = 0x00000001, VK_DEBUG_REPORT_WARN_BIT_EXT = 0x00000002, @@ -106,15 +107,15 @@ typedef VkBool32 (VKAPI_PTR *PFN_vkDebugReportCallbackEXT)( int32_t messageCode, const char* pLayerPrefix, const char* pMessage, - const void* pUserData); + void* pUserData); typedef struct VkDebugReportCallbackCreateInfoEXT { - VkStructureType sType; - const void* pNext; - VkDebugReportFlagsEXT flags; - PFN_vkDebugReportCallbackEXT pfnCallback; - const void* pUserData; + VkStructureType sType; + const void* pNext; + VkDebugReportFlagsEXT flags; + PFN_vkDebugReportCallbackEXT pfnCallback; + void* pUserData; } VkDebugReportCallbackCreateInfoEXT; typedef VkResult (VKAPI_PTR *PFN_vkCreateDebugReportCallbackEXT)(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugReportCallbackEXT* pCallback); diff --git a/renderdoc/driver/vulkan/official/vk_layer.h b/renderdoc/driver/vulkan/official/vk_layer.h index a78ae22e8..34b115078 100644 --- a/renderdoc/driver/vulkan/official/vk_layer.h +++ b/renderdoc/driver/vulkan/official/vk_layer.h @@ -15,18 +15,11 @@ # define VK_LAYER_EXPORT #endif -typedef void * (VKAPI_PTR *PFN_vkGPA)(void* obj, const char * pName); -typedef struct VkBaseLayerObject_ -{ - PFN_vkGPA pGPA; - void* nextObject; - void* baseObject; -} VkBaseLayerObject; + typedef struct VkLayerDispatchTable_ { PFN_vkGetDeviceProcAddr GetDeviceProcAddr; - PFN_vkCreateDevice CreateDevice; PFN_vkDestroyDevice DestroyDevice; PFN_vkGetDeviceQueue GetDeviceQueue; PFN_vkQueueSubmit QueueSubmit; @@ -157,7 +150,6 @@ typedef struct VkLayerDispatchTable_ typedef struct VkLayerInstanceDispatchTable_ { PFN_vkGetInstanceProcAddr GetInstanceProcAddr; - PFN_vkCreateInstance CreateInstance; PFN_vkDestroyInstance DestroyInstance; PFN_vkEnumeratePhysicalDevices EnumeratePhysicalDevices; PFN_vkGetPhysicalDeviceFeatures GetPhysicalDeviceFeatures; @@ -208,7 +200,7 @@ typedef struct VkLayerDbgFunctionNode_ VkDebugReportCallbackEXT msgCallback; PFN_vkDebugReportCallbackEXT pfnMsgCallback; VkFlags msgFlags; - const void *pUserData; + void *pUserData; struct VkLayerDbgFunctionNode_ *pNext; } VkLayerDbgFunctionNode; @@ -221,5 +213,70 @@ typedef enum VkLayerDbgAction_ VK_DBG_LAYER_ACTION_DEBUG_OUTPUT = 0x8, } VkLayerDbgAction; +// ------------------------------------------------------------------------------------------------ +// CreateInstance and CreateDevice support structures + +typedef enum VkLayerFunction_ +{ + VK_LAYER_LINK_INFO = 0, + VK_LAYER_DEVICE_INFO = 1, + VK_LAYER_INSTANCE_INFO = 2 +} VkLayerFunction; + +/* + * When creating the device chain the loader needs to pass + * down information about it's device structure needed at + * the end of the chain. Passing the data via the + * VkLayerInstanceInfo avoids issues with finding the + * exact instance being used. + */ +typedef struct VkLayerInstanceInfo_ { + void *instance_info; + PFN_vkGetInstanceProcAddr pfnNextGetInstanceProcAddr; +} VkLayerInstanceInfo; + +typedef struct VkLayerInstanceLink_ { + struct VkLayerInstanceLink_* pNext; + PFN_vkGetInstanceProcAddr pfnNextGetInstanceProcAddr; +} VkLayerInstanceLink; + +/* + * When creating the device chain the loader needs to pass + * down information about it's device structure needed at + * the end of the chain. Passing the data via the + * VkLayerDeviceInfo avoids issues with finding the + * exact instance being used. + */ +typedef struct VkLayerDeviceInfo_ { + void *device_info; + PFN_vkGetInstanceProcAddr pfnNextGetInstanceProcAddr; +} VkLayerDeviceInfo; + +typedef struct { + VkStructureType sType; // VK_STRUCTURE_TYPE_LAYER_INSTANCE_CREATE_INFO + const void* pNext; + VkLayerFunction function; + union { + VkLayerInstanceLink* pLayerInfo; + VkLayerInstanceInfo instanceInfo; + } u; +} VkLayerInstanceCreateInfo; + +typedef struct VkLayerDeviceLink_ { + struct VkLayerDeviceLink_* pNext; + PFN_vkGetInstanceProcAddr pfnNextGetInstanceProcAddr; + PFN_vkGetDeviceProcAddr pfnNextGetDeviceProcAddr; +} VkLayerDeviceLink; + +typedef struct { + VkStructureType sType; // VK_STRUCTURE_TYPE_LAYER_DEVICE_CREATE_INFO + const void* pNext; + VkLayerFunction function; + union { + VkLayerDeviceLink* pLayerInfo; + VkLayerDeviceInfo deviceInfo; + } u; +} VkLayerDeviceCreateInfo; + // ------------------------------------------------------------------------------------------------ // API functions diff --git a/renderdoc/driver/vulkan/official/vulkan.h b/renderdoc/driver/vulkan/official/vulkan.h index e87081330..688291356 100644 --- a/renderdoc/driver/vulkan/official/vulkan.h +++ b/renderdoc/driver/vulkan/official/vulkan.h @@ -41,7 +41,7 @@ extern "C" { ((major << 22) | (minor << 12) | patch) // Vulkan API version supported by this file -#define VK_API_VERSION VK_MAKE_VERSION(1, 0, 1) +#define VK_API_VERSION VK_MAKE_VERSION(1, 0, 2) #define VK_NULL_HANDLE 0 @@ -144,10 +144,10 @@ typedef enum VkResult { VK_ERROR_TOO_MANY_OBJECTS = -10, VK_ERROR_FORMAT_NOT_SUPPORTED = -11, VK_ERROR_SURFACE_LOST_KHR = -1000000000, + VK_ERROR_NATIVE_WINDOW_IN_USE_KHR = -1000000001, VK_SUBOPTIMAL_KHR = 1000001003, VK_ERROR_OUT_OF_DATE_KHR = -1000001004, VK_ERROR_INCOMPATIBLE_DISPLAY_KHR = -1000003001, - VK_ERROR_NATIVE_WINDOW_IN_USE_KHR = -1000008000, VK_ERROR_VALIDATION_FAILED_EXT = -1000011001, VK_RESULT_BEGIN_RANGE = VK_ERROR_FORMAT_NOT_SUPPORTED, VK_RESULT_END_RANGE = VK_INCOMPLETE, @@ -814,6 +814,7 @@ typedef enum VkFormatFeatureFlagBits { VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000200, VK_FORMAT_FEATURE_BLIT_SRC_BIT = 0x00000400, VK_FORMAT_FEATURE_BLIT_DST_BIT = 0x00000800, + VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT = 0x00001000, } VkFormatFeatureFlagBits; typedef VkFlags VkFormatFeatureFlags; @@ -3140,7 +3141,7 @@ VKAPI_ATTR void VKAPI_CALL vkCmdExecuteCommands( #define VK_KHR_surface 1 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSurfaceKHR) -#define VK_KHR_SURFACE_SPEC_VERSION 24 +#define VK_KHR_SURFACE_SPEC_VERSION 25 #define VK_KHR_SURFACE_EXTENSION_NAME "VK_KHR_surface" @@ -3615,7 +3616,7 @@ VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceMirPresentationSupportKHR( #define VK_KHR_android_surface 1 #include -#define VK_KHR_ANDROID_SURFACE_SPEC_VERSION 5 +#define VK_KHR_ANDROID_SURFACE_SPEC_VERSION 6 #define VK_KHR_ANDROID_SURFACE_EXTENSION_NAME "VK_KHR_android_surface" typedef VkFlags VkAndroidSurfaceCreateFlagsKHR; diff --git a/renderdoc/driver/vulkan/vk_core.h b/renderdoc/driver/vulkan/vk_core.h index 096def07b..a99c9e028 100644 --- a/renderdoc/driver/vulkan/vk_core.h +++ b/renderdoc/driver/vulkan/vk_core.h @@ -519,7 +519,7 @@ private: int32_t messageCode, const char* pLayerPrefix, const char* pMessage, - const void* pUserData) + void* pUserData) { return ((WrappedVulkan *)pUserData)->DebugCallback(flags, objectType, object, location, messageCode, pLayerPrefix, pMessage); } diff --git a/renderdoc/driver/vulkan/vk_dispatchtables.cpp b/renderdoc/driver/vulkan/vk_dispatchtables.cpp index 1258cc814..055361ef2 100644 --- a/renderdoc/driver/vulkan/vk_dispatchtables.cpp +++ b/renderdoc/driver/vulkan/vk_dispatchtables.cpp @@ -153,10 +153,10 @@ static void *GetKey(void *obj) return (void *)*tablePtr; } -void InitDeviceTable(const VkBaseLayerObject *obj) +void InitDeviceTable(VkDevice dev, PFN_vkGetDeviceProcAddr gpa) { - void *key = GetKey(obj->baseObject); - + void *key = GetKey(dev); + VkLayerDispatchTableExtended *table = NULL; { @@ -165,19 +165,18 @@ void InitDeviceTable(const VkBaseLayerObject *obj) table = &devlookup[key]; } - // init the GetDeviceProcAddr function first - table->GetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)obj->pGPA((VkDevice)obj->nextObject, "vkGetDeviceProcAddr"); - + table->GetDeviceProcAddr = gpa; + // fetch the rest of the functions #undef HookInit - #define HookInit(name) if(table->name == NULL) table->name = (CONCAT(PFN_vk, name))obj->pGPA((VkDevice)obj->baseObject, STRINGIZE(CONCAT(vk, name))) + #define HookInit(name) if(table->name == NULL) table->name = (CONCAT(PFN_vk, name))gpa(dev, STRINGIZE(CONCAT(vk, name))) HookInitVulkanDevice(); } -void InitInstanceTable(const VkBaseLayerObject *obj) +void InitInstanceTable(VkInstance inst, PFN_vkGetInstanceProcAddr gpa) { - void *key = GetKey(obj->baseObject); + void *key = GetKey(inst); VkLayerInstanceDispatchTableExtended *table = NULL; @@ -188,14 +187,14 @@ void InitInstanceTable(const VkBaseLayerObject *obj) } // init the GetInstanceProcAddr function first - table->GetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)obj->pGPA((VkInstance)obj->nextObject, "vkGetInstanceProcAddr"); - + table->GetInstanceProcAddr = gpa; + // fetch the rest of the functions #undef HookInit - #define HookInit(name) if(table->name == NULL) table->name = (CONCAT(PFN_vk, name))obj->pGPA((VkInstance)obj->baseObject, STRINGIZE(CONCAT(vk, name))) + #define HookInit(name) if(table->name == NULL) table->name = (CONCAT(PFN_vk, name))gpa(inst, STRINGIZE(CONCAT(vk, name))) HookInitVulkanInstance(); - + // we also need these functions for layer handling HookInit(EnumerateDeviceExtensionProperties); HookInit(EnumerateDeviceLayerProperties); diff --git a/renderdoc/driver/vulkan/vk_hookset_defs.h b/renderdoc/driver/vulkan/vk_hookset_defs.h index 817944989..0f2227607 100644 --- a/renderdoc/driver/vulkan/vk_hookset_defs.h +++ b/renderdoc/driver/vulkan/vk_hookset_defs.h @@ -405,11 +405,19 @@ struct VkLayerInstanceDispatchTableExtended : VkLayerInstanceDispatchTable { + // for consistency & ease, we declare the CreateInstance pointer here + // even though it won't actually ever get used + PFN_vkCreateInstance CreateInstance; + // extensions here }; struct VkLayerDispatchTableExtended : VkLayerDispatchTable { + // for consistency & ease, we declare the CreateDevice pointer here + // even though it won't actually ever get used + PFN_vkCreateDevice CreateDevice; + // VK_LUNARG_DEBUG_MARKER PFN_vkCmdDbgMarkerBegin CmdDbgMarkerBegin; PFN_vkCmdDbgMarkerEnd CmdDbgMarkerEnd; diff --git a/renderdoc/driver/vulkan/vk_tracelayer.cpp b/renderdoc/driver/vulkan/vk_tracelayer.cpp index 034925cd6..5dfd70861 100644 --- a/renderdoc/driver/vulkan/vk_tracelayer.cpp +++ b/renderdoc/driver/vulkan/vk_tracelayer.cpp @@ -47,9 +47,6 @@ #define VK_LAYER_EXPORT extern "C" __declspec(dllexport) #endif -void InitDeviceTable(const VkBaseLayerObject *obj); -void InitInstanceTable(const VkBaseLayerObject *obj); - // in vk_.cpp bool LayerRegistered(); @@ -170,7 +167,7 @@ VkResult getProps(uint32_t *dstCount, void *dstProps, uint32_t srcCount, void *s extern "C" { -VK_LAYER_EXPORT VkResult VKAPI_CALL RenderDocEnumerateDeviceLayerProperties( +VK_LAYER_EXPORT VkResult VKAPI_CALL RenderDoc_EnumerateDeviceLayerProperties( VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkLayerProperties* pProperties) @@ -178,7 +175,7 @@ VK_LAYER_EXPORT VkResult VKAPI_CALL RenderDocEnumerateDeviceLayerProperties( return getProps(pPropertyCount, pProperties, ARRAY_COUNT(physLayers), (void *)physLayers, sizeof(VkLayerProperties)); } -VK_LAYER_EXPORT VkResult VKAPI_CALL RenderDocEnumerateDeviceExtensionProperties( +VK_LAYER_EXPORT VkResult VKAPI_CALL RenderDoc_EnumerateDeviceExtensionProperties( VkPhysicalDevice physicalDevice, const char *pLayerName, uint32_t *pPropertyCount, @@ -207,65 +204,43 @@ VK_LAYER_EXPORT VkResult VKAPI_CALL RenderDocEnumerateDeviceExtensionProperties( VK_LAYER_EXPORT PFN_vkVoidFunction VKAPI_CALL RenderDoc_GetDeviceProcAddr(VkDevice device, const char* pName) { - if (device == NULL) - return NULL; - - /* loader uses this to force layer initialization; device object is wrapped */ - if (!strcmp("vkGetDeviceProcAddr", pName)) { - InitDeviceTable((const VkBaseLayerObject *) device); + if(!strcmp("vkGetDeviceProcAddr", pName)) return (PFN_vkVoidFunction) &RenderDoc_GetDeviceProcAddr; - } - - if (!strcmp("vkCreateDevice", pName)) + if(!strcmp("vkCreateDevice", pName)) return (PFN_vkVoidFunction) &hooked_vkCreateDevice; - if (!strcmp("vkDestroyDevice", pName)) + if(!strcmp("vkDestroyDevice", pName)) return (PFN_vkVoidFunction) &hooked_vkDestroyDevice; HookInitVulkanDevice(); + + if(device == VK_NULL_HANDLE) + return NULL; InstanceDeviceInfo *instDevInfo = GetRecord(device)->instDevInfo; HookInitVulkanDeviceExts(); - if (GetDeviceDispatchTable(device)->GetDeviceProcAddr == NULL) + if(GetDeviceDispatchTable(device)->GetDeviceProcAddr == NULL) return NULL; return GetDeviceDispatchTable(device)->GetDeviceProcAddr(Unwrap(device), pName); } VK_LAYER_EXPORT PFN_vkVoidFunction VKAPI_CALL RenderDoc_GetInstanceProcAddr(VkInstance instance, const char* pName) { - if (instance == NULL) - return NULL; - - /* loader uses this to force layer initialization; instance object is wrapped */ - if (!strcmp("vkGetInstanceProcAddr", pName)) { - InitInstanceTable((const VkBaseLayerObject *) instance); + if(!strcmp("vkGetInstanceProcAddr", pName)) return (PFN_vkVoidFunction) &RenderDoc_GetInstanceProcAddr; - } - - if (!strcmp("vkEnumerateDeviceLayerProperties", pName)) - return (PFN_vkVoidFunction) &RenderDocEnumerateDeviceLayerProperties; - if (!strcmp("vkEnumerateDeviceExtensionProperties", pName)) - return (PFN_vkVoidFunction) &RenderDocEnumerateDeviceExtensionProperties; + if(!strcmp("vkEnumerateDeviceLayerProperties", pName)) + return (PFN_vkVoidFunction) &RenderDoc_EnumerateDeviceLayerProperties; + if(!strcmp("vkEnumerateDeviceExtensionProperties", pName)) + return (PFN_vkVoidFunction) &RenderDoc_EnumerateDeviceExtensionProperties; HookInitVulkanInstance(); + + if(instance == VK_NULL_HANDLE) + return NULL; InstanceDeviceInfo *instDevInfo = GetRecord(instance)->instDevInfo; - // TEMPORARY HACK until loader is patched - InstanceDeviceInfo dummy; - dummy.VK_KHR_xlib_surface = true; - dummy.VK_KHR_xcb_surface = true; - dummy.VK_KHR_win32_surface = true; - dummy.VK_KHR_surface = true; - dummy.VK_KHR_swapchain = true; - - if(!WrappedVkInstance::IsAlloc(instance)) - { - RDCLOG("Doing workaround for non-wrapped instance passed to GIPA"); - instDevInfo = &dummy; - } - HookInitVulkanInstanceExts(); // GetInstanceProcAddr must also unconditionally return all device functions @@ -277,7 +252,7 @@ VK_LAYER_EXPORT PFN_vkVoidFunction VKAPI_CALL RenderDoc_GetInstanceProcAddr(VkIn HookInitVulkanDeviceExts(); - if (GetInstanceDispatchTable(instance)->GetInstanceProcAddr == NULL) + if(GetInstanceDispatchTable(instance)->GetInstanceProcAddr == NULL) return NULL; return GetInstanceDispatchTable(instance)->GetInstanceProcAddr(Unwrap(instance), pName); } diff --git a/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp index 132f76072..336c36fe0 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp @@ -25,6 +25,10 @@ #include "../vk_core.h" #include "../vk_debug.h" +// vk_dispatchtables.cpp +void InitDeviceTable(VkDevice dev, PFN_vkGetDeviceProcAddr gpa); +void InitInstanceTable(VkInstance inst, PFN_vkGetInstanceProcAddr gpa); + // Init/shutdown order: // // On capture, WrappedVulkan is new'd and delete'd before vkCreateInstance() and after vkDestroyInstance() @@ -138,11 +142,34 @@ VkResult WrappedVulkan::vkCreateInstance( // don't support any extensions for this createinfo RDCASSERT(pCreateInfo->pApplicationInfo == NULL || pCreateInfo->pApplicationInfo->pNext == NULL); - RDCASSERT(pCreateInfo->pNext == NULL); + + VkLayerInstanceCreateInfo *layerCreateInfo = (VkLayerInstanceCreateInfo *)pCreateInfo->pNext; + + // step through the chain of pNext until we get to the link info + while(layerCreateInfo && + (layerCreateInfo->sType != VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO || + layerCreateInfo->function != VK_LAYER_LINK_INFO) + ) + { + // we don't handle any pNext elements other than this create info struct + RDCASSERT(layerCreateInfo->sType == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO); + layerCreateInfo = (VkLayerInstanceCreateInfo *)layerCreateInfo->pNext; + } + RDCASSERT(layerCreateInfo); + // make sure there are no elements after this, that we don't handle + RDCASSERT(layerCreateInfo->pNext == NULL); + + PFN_vkGetInstanceProcAddr gpa = layerCreateInfo->u.pLayerInfo->pfnNextGetInstanceProcAddr; + // move chain on for next layer + layerCreateInfo->u.pLayerInfo = layerCreateInfo->u.pLayerInfo->pNext; + + PFN_vkCreateInstance createFunc = (PFN_vkCreateInstance)gpa(VK_NULL_HANDLE, "vkCreateInstance"); + + VkResult ret = createFunc(pCreateInfo, pAllocator, pInstance); m_Instance = *pInstance; - VkResult ret = GetInstanceDispatchTable(*pInstance)->CreateInstance(pCreateInfo, pAllocator, &m_Instance); + InitInstanceTable(m_Instance, gpa); GetResourceManager()->WrapResource(m_Instance, m_Instance); @@ -726,7 +753,37 @@ VkResult WrappedVulkan::vkCreateDevice( m_QueueFamilies[family][q] = VK_NULL_HANDLE; } - VkResult ret = GetDeviceDispatchTable(*pDevice)->CreateDevice(Unwrap(physicalDevice), &createInfo, pAllocator, pDevice); + VkLayerDeviceCreateInfo *layerCreateInfo = (VkLayerDeviceCreateInfo *)pCreateInfo->pNext; + + // step through the chain of pNext until we get to the link info + while(layerCreateInfo && + (layerCreateInfo->sType != VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO || + layerCreateInfo->function != VK_LAYER_LINK_INFO) + ) + { + // we don't handle any pNext elements other than this create info struct + RDCASSERT(layerCreateInfo->sType == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO); + layerCreateInfo = (VkLayerDeviceCreateInfo *)layerCreateInfo->pNext; + } + RDCASSERT(layerCreateInfo); + + // make sure there are no elements after this, that we don't handle + RDCASSERT(layerCreateInfo->pNext == NULL); + + PFN_vkGetDeviceProcAddr gdpa = layerCreateInfo->u.pLayerInfo->pfnNextGetDeviceProcAddr; + PFN_vkGetInstanceProcAddr gipa = layerCreateInfo->u.pLayerInfo->pfnNextGetInstanceProcAddr; + // move chain on for next layer + layerCreateInfo->u.pLayerInfo = layerCreateInfo->u.pLayerInfo->pNext; + + PFN_vkCreateDevice createFunc = (PFN_vkCreateDevice)gipa(VK_NULL_HANDLE, "vkCreateDevice"); + + VkResult ret = createFunc(Unwrap(physicalDevice), &createInfo, pAllocator, pDevice); + + // don't serialise out any of the pNext stuff for layer initialisation + // (note that we asserted above that there was nothing else in the chain) + createInfo.pNext = NULL; + + InitDeviceTable(*pDevice, gdpa); if(ret == VK_SUCCESS) {