diff --git a/renderdoc/driver/vulkan/vk_common.cpp b/renderdoc/driver/vulkan/vk_common.cpp index 9f576de4b..d180dfdb2 100644 --- a/renderdoc/driver/vulkan/vk_common.cpp +++ b/renderdoc/driver/vulkan/vk_common.cpp @@ -2762,11 +2762,37 @@ static void SerialiseNext(Serialiser *ser, VkStructureType &sType, const void *& { ser->Serialise("sType", sType); - // we don't support any extensions, so pNext must always be NULL if(ser->IsReading()) + { pNext = NULL; + } else - RDCASSERT(pNext == NULL); + { + if(pNext == NULL) + return; + + VkGenericStruct *next = (VkGenericStruct *)pNext; + + while(next) + { + // we can ignore this entirely, we don't need to serialise or replay it as we won't + // actually use external memory. Unwrapping, if necessary, happens elsewhere + if(next->sType == VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_NV || + next->sType == VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV || + next->sType == VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_NV || + next->sType == VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_NV || + next->sType == VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV) + { + // do nothing + } + else + { + RDCERR("Unrecognised extension structure type %d", next->sType); + } + + next = (VkGenericStruct *)next->pNext; + } + } } template @@ -2788,12 +2814,6 @@ void SerialiseOptionalObject(Serialiser *ser, const char *name, T *&el) } } -template <> -void Serialiser::Serialise(const char *name, VkGenericStruct &el) -{ - ScopedContext scope(this, name, "NextStructure", 0, true); -} - template <> void Serialiser::Serialise(const char *name, VkDeviceQueueCreateInfo &el) { diff --git a/renderdoc/driver/vulkan/vk_core.cpp b/renderdoc/driver/vulkan/vk_core.cpp index ae91ba7e8..6ad5b8631 100644 --- a/renderdoc/driver/vulkan/vk_core.cpp +++ b/renderdoc/driver/vulkan/vk_core.cpp @@ -682,11 +682,101 @@ bool operator<(const VkExtensionProperties &a, const VkExtensionProperties &b) return strcmp(a.extensionName, b.extensionName) < 0; } +// This list must be kept sorted according to the above sort operator! +static const VkExtensionProperties supportedExtensions[] = { + // this extension is 'free' - it just marks SPIR-V extension availability + { + VK_AMD_GCN_SHADER_EXTENSION_NAME, VK_AMD_GCN_SHADER_SPEC_VERSION, + }, + // this extension is 'free' - it just marks SPIR-V extension availability + { + VK_AMD_SHADER_BALLOT_EXTENSION_NAME, VK_AMD_SHADER_BALLOT_SPEC_VERSION, + }, + // this extension is 'free' - it just marks SPIR-V extension availability + { + VK_AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_EXTENSION_NAME, + VK_AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_SPEC_VERSION, + }, + // this extension is 'free' - it just marks SPIR-V extension availability + { + VK_AMD_SHADER_TRINARY_MINMAX_EXTENSION_NAME, VK_AMD_SHADER_TRINARY_MINMAX_SPEC_VERSION, + }, + { + VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION, + }, +#ifdef VK_KHR_android_surface + { + VK_KHR_ANDROID_SURFACE_EXTENSION_NAME, VK_KHR_ANDROID_SURFACE_SPEC_VERSION, + }, +#endif +#ifdef VK_KHR_display + { + VK_KHR_DISPLAY_EXTENSION_NAME, VK_KHR_DISPLAY_SPEC_VERSION, + }, +#endif +#ifdef VK_KHR_display_swapchain + { + VK_KHR_DISPLAY_SWAPCHAIN_EXTENSION_NAME, VK_KHR_DISPLAY_SWAPCHAIN_SPEC_VERSION, + }, +#endif + { + VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME, + VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_SPEC_VERSION, + }, + { + VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_SURFACE_SPEC_VERSION, + }, + { + VK_KHR_SWAPCHAIN_EXTENSION_NAME, VK_KHR_SWAPCHAIN_SPEC_VERSION, + }, +#ifdef VK_KHR_win32_surface + { + VK_KHR_WIN32_SURFACE_EXTENSION_NAME, VK_KHR_WIN32_SURFACE_SPEC_VERSION, + }, +#endif +#ifdef VK_KHR_xcb_surface + { + VK_KHR_XCB_SURFACE_EXTENSION_NAME, VK_KHR_XCB_SURFACE_SPEC_VERSION, + }, +#endif +#ifdef VK_KHR_xlib_surface + { + VK_KHR_XLIB_SURFACE_EXTENSION_NAME, VK_KHR_XLIB_SURFACE_SPEC_VERSION, + }, +#endif + { + VK_NV_EXTERNAL_MEMORY_EXTENSION_NAME, VK_NV_EXTERNAL_MEMORY_SPEC_VERSION, + }, + { + VK_NV_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME, + VK_NV_EXTERNAL_MEMORY_CAPABILITIES_SPEC_VERSION, + }, +#ifdef VK_NV_external_memory_win32 + { + VK_NV_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME, VK_NV_EXTERNAL_MEMORY_WIN32_SPEC_VERSION, + }, +#endif +#ifdef VK_NV_win32_keyed_mutex + { + VK_NV_WIN32_KEYED_MUTEX_EXTENSION_NAME, VK_NV_WIN32_KEYED_MUTEX_SPEC_VERSION, + }, +#endif +}; + // this is the list of extensions we provide - regardless of whether the ICD supports them static const VkExtensionProperties renderdocProvidedExtensions[] = { {VK_EXT_DEBUG_MARKER_EXTENSION_NAME, VK_EXT_DEBUG_MARKER_SPEC_VERSION}, }; +bool WrappedVulkan::IsSupportedExtension(const char *extName) +{ + for(size_t i = 0; i < ARRAY_COUNT(supportedExtensions); i++) + if(!strcmp(supportedExtensions[i].extensionName, extName)) + return true; + + return false; +} + VkResult WrappedVulkan::FilterDeviceExtensionProperties(VkPhysicalDevice physDev, uint32_t *pPropertyCount, VkExtensionProperties *pProperties) @@ -707,38 +797,7 @@ VkResult WrappedVulkan::FilterDeviceExtensionProperties(VkPhysicalDevice physDev if(vkr != VK_SUCCESS) return vkr; - // filter the list of extensions to only the ones we support. Note it's important that - // this list is kept sorted according to the above sort operator! - const VkExtensionProperties supportedExtensions[] = { - { - VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION, - }, - { - VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME, - VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_SPEC_VERSION, - }, - { - VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_SURFACE_SPEC_VERSION, - }, - { - VK_KHR_SWAPCHAIN_EXTENSION_NAME, VK_KHR_SWAPCHAIN_SPEC_VERSION, - }, -#ifdef VK_KHR_win32_surface - { - VK_KHR_WIN32_SURFACE_EXTENSION_NAME, VK_KHR_WIN32_SURFACE_SPEC_VERSION, - }, -#endif -#ifdef VK_KHR_xcb_surface - { - VK_KHR_XCB_SURFACE_EXTENSION_NAME, VK_KHR_XCB_SURFACE_SPEC_VERSION, - }, -#endif -#ifdef VK_KHR_xlib_surface - { - VK_KHR_XLIB_SURFACE_EXTENSION_NAME, VK_KHR_XLIB_SURFACE_SPEC_VERSION, - }, -#endif - }; + // filter the list of extensions to only the ones we support. // sort the reported extensions std::sort(exts.begin(), exts.end()); diff --git a/renderdoc/driver/vulkan/vk_core.h b/renderdoc/driver/vulkan/vk_core.h index d5a896162..1e47c1f72 100644 --- a/renderdoc/driver/vulkan/vk_core.h +++ b/renderdoc/driver/vulkan/vk_core.h @@ -714,6 +714,7 @@ public: VulkanRenderState &GetRenderState() { return m_RenderState; } void SetDrawcallCB(VulkanDrawcallCallback *cb) { m_DrawcallCallback = cb; } + bool IsSupportedExtension(const char *extName); VkResult FilterDeviceExtensionProperties(VkPhysicalDevice physDev, uint32_t *pPropertyCount, VkExtensionProperties *pProperties); static VkResult GetProvidedExtensionProperties(uint32_t *pPropertyCount, @@ -1322,6 +1323,10 @@ public: VkBool32 vkGetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex); + + // VK_NV_external_memory_win32 + VkResult vkGetMemoryWin32HandleNV(VkDevice device, VkDeviceMemory memory, + VkExternalMemoryHandleTypeFlagsNV handleType, HANDLE *pHandle); #endif #if defined(VK_USE_PLATFORM_ANDROID_KHR) @@ -1384,4 +1389,11 @@ public: const VkSwapchainCreateInfoKHR *pCreateInfos, const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchains); + + // VK_NV_external_memory_capabilities + VkResult vkGetPhysicalDeviceExternalImageFormatPropertiesNV( + VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, + VkImageUsageFlags usage, VkImageCreateFlags flags, + VkExternalMemoryHandleTypeFlagsNV externalHandleType, + VkExternalImageFormatPropertiesNV *pExternalImageFormatProperties); }; diff --git a/renderdoc/driver/vulkan/vk_dispatchtables.cpp b/renderdoc/driver/vulkan/vk_dispatchtables.cpp index f514a4e45..61acfbeb1 100644 --- a/renderdoc/driver/vulkan/vk_dispatchtables.cpp +++ b/renderdoc/driver/vulkan/vk_dispatchtables.cpp @@ -115,7 +115,7 @@ void InitInstanceExtensionTables(VkInstance instance) #undef HookInitExtension #define HookInitExtension(ext, func) \ - if(info->ext) \ + if(info->ext_##ext) \ { \ InstanceGPA(func); \ } @@ -150,7 +150,7 @@ void InitDeviceExtensionTables(VkDevice device) #undef HookInitExtension #define HookInitExtension(ext, func) \ - if(info->ext) \ + if(info->ext_##ext) \ { \ DeviceGPA(func); \ } diff --git a/renderdoc/driver/vulkan/vk_hookset_defs.h b/renderdoc/driver/vulkan/vk_hookset_defs.h index 2940129d4..69999c390 100644 --- a/renderdoc/driver/vulkan/vk_hookset_defs.h +++ b/renderdoc/driver/vulkan/vk_hookset_defs.h @@ -24,37 +24,31 @@ #pragma once -// since we don't use these macros, we undefine them so they don't interfere -// with bool names etc -#undef VK_KHR_xlib_surface -#undef VK_KHR_xcb_surface -#undef VK_KHR_win32_surface -#undef VK_KHR_android_surface -#undef VK_KHR_surface -#undef VK_KHR_swapchain -#undef VK_KHR_display -#undef VK_KHR_display_swapchain -#undef VK_EXT_debug_report -#undef VK_EXT_debug_marker - #if defined(VK_USE_PLATFORM_WIN32_KHR) #define HookInitInstance_PlatformSpecific() \ HookInitExtension(VK_KHR_win32_surface, CreateWin32SurfaceKHR); \ HookInitExtension(VK_KHR_win32_surface, GetPhysicalDeviceWin32PresentationSupportKHR); +#define HookInitDevice_PlatformSpecific() \ + HookInitExtension(VK_NV_win32_keyed_mutex, GetMemoryWin32HandleNV); + #define HookDefine_PlatformSpecific() \ HookDefine4(VkResult, vkCreateWin32SurfaceKHR, VkInstance, instance, \ const VkWin32SurfaceCreateInfoKHR *, pCreateInfo, const VkAllocationCallbacks *, \ pAllocator, VkSurfaceKHR *, pSurface); \ HookDefine2(VkBool32, vkGetPhysicalDeviceWin32PresentationSupportKHR, VkPhysicalDevice, \ - physicalDevice, uint32_t, queueFamilyIndex); + physicalDevice, uint32_t, queueFamilyIndex); \ + HookDefine4(VkResult, vkGetMemoryWin32HandleNV, VkDevice, device, VkDeviceMemory, memory, \ + VkExternalMemoryHandleTypeFlagsNV, handleType, HANDLE *, pHandle); #elif defined(VK_USE_PLATFORM_ANDROID_KHR) #define HookInitInstance_PlatformSpecific() \ HookInitExtension(VK_KHR_android_surface, CreateAndroidSurfaceKHR); +#define HookInitDevice_PlatformSpecific() + #define HookDefine_PlatformSpecific() \ HookDefine4(VkResult, vkCreateAndroidSurfaceKHR, VkInstance, instance, \ const VkAndroidSurfaceCreateInfoKHR *, pCreateInfo, const VkAllocationCallbacks *, \ @@ -105,6 +99,7 @@ #define HookInitInstance_PlatformSpecific() \ HookInitInstance_PlatformSpecific_Xcb() HookInitInstance_PlatformSpecific_Xlib() +#define HookInitDevice_PlatformSpecific() #define HookDefine_PlatformSpecific() \ HookDefine_PlatformSpecific_Xcb() HookDefine_PlatformSpecific_Xlib() @@ -252,13 +247,23 @@ // for simplicity and since the check itself is platform agnostic, // these aren't protected in platform defines -#define CheckInstanceExts() \ - CheckExt(VK_KHR_xlib_surface) CheckExt(VK_KHR_xcb_surface) CheckExt(VK_KHR_win32_surface) \ - CheckExt(VK_KHR_android_surface) CheckExt(VK_KHR_surface) CheckExt(VK_EXT_debug_report) \ - CheckExt(VK_KHR_display) +#define CheckInstanceExts() \ + CheckExt(VK_KHR_xlib_surface); \ + CheckExt(VK_KHR_xcb_surface); \ + CheckExt(VK_KHR_win32_surface); \ + CheckExt(VK_KHR_android_surface); \ + CheckExt(VK_KHR_surface); \ + CheckExt(VK_EXT_debug_report); \ + CheckExt(VK_KHR_display); \ + CheckExt(VK_NV_external_memory_capabilities); -#define CheckDeviceExts() \ - CheckExt(VK_EXT_debug_marker) CheckExt(VK_KHR_swapchain) CheckExt(VK_KHR_display_swapchain) +#define CheckDeviceExts() \ + CheckExt(VK_EXT_debug_marker); \ + CheckExt(VK_KHR_swapchain); \ + CheckExt(VK_KHR_display_swapchain); \ + CheckExt(VK_NV_external_memory); \ + CheckExt(VK_NV_external_memory_win32); \ + CheckExt(VK_NV_win32_keyed_mutex); #define HookInitVulkanInstanceExts() \ HookInitExtension(VK_KHR_surface, DestroySurfaceKHR); \ @@ -276,20 +281,23 @@ HookInitExtension(VK_KHR_display, CreateDisplayModeKHR); \ HookInitExtension(VK_KHR_display, GetDisplayPlaneCapabilitiesKHR); \ HookInitExtension(VK_KHR_display, CreateDisplayPlaneSurfaceKHR); \ + HookInitExtension(VK_NV_external_memory_capabilities, \ + GetPhysicalDeviceExternalImageFormatPropertiesNV); \ HookInitInstance_PlatformSpecific() -#define HookInitVulkanDeviceExts() \ - HookInitExtension(VK_EXT_debug_marker, DebugMarkerSetObjectTagEXT); \ - HookInitExtension(VK_EXT_debug_marker, DebugMarkerSetObjectNameEXT); \ - HookInitExtension(VK_EXT_debug_marker, CmdDebugMarkerBeginEXT); \ - HookInitExtension(VK_EXT_debug_marker, CmdDebugMarkerEndEXT); \ - HookInitExtension(VK_EXT_debug_marker, CmdDebugMarkerInsertEXT); \ - HookInitExtension(VK_KHR_swapchain, CreateSwapchainKHR); \ - HookInitExtension(VK_KHR_swapchain, DestroySwapchainKHR); \ - HookInitExtension(VK_KHR_swapchain, GetSwapchainImagesKHR); \ - HookInitExtension(VK_KHR_swapchain, AcquireNextImageKHR); \ - HookInitExtension(VK_KHR_swapchain, QueuePresentKHR); \ - HookInitExtension(VK_KHR_display_swapchain, CreateSharedSwapchainsKHR); +#define HookInitVulkanDeviceExts() \ + HookInitExtension(VK_EXT_debug_marker, DebugMarkerSetObjectTagEXT); \ + HookInitExtension(VK_EXT_debug_marker, DebugMarkerSetObjectNameEXT); \ + HookInitExtension(VK_EXT_debug_marker, CmdDebugMarkerBeginEXT); \ + HookInitExtension(VK_EXT_debug_marker, CmdDebugMarkerEndEXT); \ + HookInitExtension(VK_EXT_debug_marker, CmdDebugMarkerInsertEXT); \ + HookInitExtension(VK_KHR_swapchain, CreateSwapchainKHR); \ + HookInitExtension(VK_KHR_swapchain, DestroySwapchainKHR); \ + HookInitExtension(VK_KHR_swapchain, GetSwapchainImagesKHR); \ + HookInitExtension(VK_KHR_swapchain, AcquireNextImageKHR); \ + HookInitExtension(VK_KHR_swapchain, QueuePresentKHR); \ + HookInitExtension(VK_KHR_display_swapchain, CreateSharedSwapchainsKHR); \ + HookInitDevice_PlatformSpecific() #define DefineHooks() \ HookDefine3(VkResult, vkEnumeratePhysicalDevices, VkInstance, instance, uint32_t *, \ @@ -636,8 +644,18 @@ HookDefine5(VkResult, vkCreateSharedSwapchainsKHR, VkDevice, device, uint32_t, swapchainCount, \ const VkSwapchainCreateInfoKHR *, pCreateInfos, const VkAllocationCallbacks *, \ pAllocator, VkSwapchainKHR *, pSwapchains); \ + HookDefine8(VkResult, vkGetPhysicalDeviceExternalImageFormatPropertiesNV, VkPhysicalDevice, \ + physicalDevice, VkFormat, format, VkImageType, type, VkImageTiling, tiling, \ + VkImageUsageFlags, usage, VkImageCreateFlags, flags, \ + VkExternalMemoryHandleTypeFlagsNV, externalHandleType, \ + VkExternalImageFormatPropertiesNV *, pExternalImageFormatProperties); \ HookDefine_PlatformSpecific() +// define function pointers for other platforms to make things easier +#ifndef VK_NV_external_memory_win32 +#define PFN_vkGetMemoryWin32HandleNV PFN_vkVoidFunction +#endif + struct VkLayerInstanceDispatchTableExtended : VkLayerInstanceDispatchTable { // for consistency & ease, we declare the CreateInstance pointer here @@ -648,7 +666,8 @@ struct VkLayerInstanceDispatchTableExtended : VkLayerInstanceDispatchTable PFN_vkEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties; PFN_vkEnumerateInstanceLayerProperties EnumerateInstanceLayerProperties; - // extensions here + // VK_NV_external_memory_capabilities + PFN_vkGetPhysicalDeviceExternalImageFormatPropertiesNV GetPhysicalDeviceExternalImageFormatPropertiesNV; }; struct VkLayerDispatchTableExtended : VkLayerDispatchTable @@ -663,4 +682,7 @@ struct VkLayerDispatchTableExtended : VkLayerDispatchTable PFN_vkCmdDebugMarkerBeginEXT CmdDebugMarkerBeginEXT; PFN_vkCmdDebugMarkerEndEXT CmdDebugMarkerEndEXT; PFN_vkCmdDebugMarkerInsertEXT CmdDebugMarkerInsertEXT; + + // VK_NV_external_memory_win32 + PFN_vkGetMemoryWin32HandleNV GetMemoryWin32HandleNV; }; diff --git a/renderdoc/driver/vulkan/vk_resources.h b/renderdoc/driver/vulkan/vk_resources.h index de57ac6b9..361af17e0 100644 --- a/renderdoc/driver/vulkan/vk_resources.h +++ b/renderdoc/driver/vulkan/vk_resources.h @@ -827,7 +827,7 @@ struct SwapchainInfo struct InstanceDeviceInfo { #undef CheckExt -#define CheckExt(name) name = false; +#define CheckExt(name) ext_##name = false; InstanceDeviceInfo() { CheckDeviceExts(); @@ -835,7 +835,7 @@ struct InstanceDeviceInfo } #undef CheckExt -#define CheckExt(name) bool name; +#define CheckExt(name) bool ext_##name; CheckDeviceExts(); CheckInstanceExts(); diff --git a/renderdoc/driver/vulkan/vk_tracelayer.cpp b/renderdoc/driver/vulkan/vk_tracelayer.cpp index 52e3ff8ad..0fbe8b870 100644 --- a/renderdoc/driver/vulkan/vk_tracelayer.cpp +++ b/renderdoc/driver/vulkan/vk_tracelayer.cpp @@ -248,14 +248,11 @@ VK_LAYER_EXPORT VkResult VKAPI_CALL VK_LAYER_RENDERDOC_CaptureEnumerateDeviceExt return (PFN_vkVoidFunction)&CONCAT(hooked_vk, function); #undef HookInitExtension -#define HookInitExtension(ext, function) \ - if(!strcmp(pName, STRINGIZE(CONCAT(vk, function)))) \ - { \ - if(instDevInfo->ext) \ - return (PFN_vkVoidFunction)&CONCAT(hooked_vk, function); \ - else \ - RDCWARN("Requested function %s but extension %s is not enabled!", STRINGIZE(function), \ - STRINGIZE(ext)); \ +#define HookInitExtension(ext, function) \ + if(!strcmp(pName, STRINGIZE(CONCAT(vk, function)))) \ + { \ + if(instDevInfo->ext_##ext) \ + return (PFN_vkVoidFunction)&CONCAT(hooked_vk, function); \ } // proc addr routines diff --git a/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp index 2560bc409..c9ecd57f6 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp @@ -279,6 +279,33 @@ VkResult WrappedVulkan::vkCreateInstance(const VkInstanceCreateInfo *pCreateInfo VkInstanceCreateInfo modifiedCreateInfo; modifiedCreateInfo = *pCreateInfo; + for(uint32_t i = 0; i < modifiedCreateInfo.enabledExtensionCount; i++) + { + if(!IsSupportedExtension(modifiedCreateInfo.ppEnabledExtensionNames[i])) + { + RDCERR("RenderDoc does not support instance extension '%s'.", + modifiedCreateInfo.ppEnabledExtensionNames[i]); + RDCERR("File an issue on github to request support: https://github.com/baldurk/renderdoc"); + + // see if any debug report callbacks were passed in the pNext chain + VkDebugReportCallbackCreateInfoEXT *report = + (VkDebugReportCallbackCreateInfoEXT *)pCreateInfo->pNext; + + while(report) + { + if(report && report->sType == VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT) + report->pfnCallback(VK_DEBUG_REPORT_ERROR_BIT_EXT, + VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, 0, 1, 1, "RDOC", + "RenderDoc does not support a requested instance extension.", + report->pUserData); + + report = (VkDebugReportCallbackCreateInfoEXT *)report->pNext; + } + + return VK_ERROR_EXTENSION_NOT_PRESENT; + } + } + const char **addedExts = new const char *[modifiedCreateInfo.enabledExtensionCount + 1]; for(uint32_t i = 0; i < modifiedCreateInfo.enabledExtensionCount; i++) @@ -311,7 +338,7 @@ VkResult WrappedVulkan::vkCreateInstance(const VkInstanceCreateInfo *pCreateInfo #define CheckExt(name) \ if(!strcmp(modifiedCreateInfo.ppEnabledExtensionNames[i], STRINGIZE(name))) \ { \ - record->instDevInfo->name = true; \ + record->instDevInfo->ext_##name = true; \ } for(uint32_t i = 0; i < modifiedCreateInfo.enabledExtensionCount; i++) @@ -1233,7 +1260,8 @@ VkResult WrappedVulkan::vkCreateDevice(VkPhysicalDevice physicalDevice, record->instDevInfo = new InstanceDeviceInfo(); #undef CheckExt -#define CheckExt(name) record->instDevInfo->name = GetRecord(m_Instance)->instDevInfo->name; +#define CheckExt(name) \ + record->instDevInfo->ext_##name = GetRecord(m_Instance)->instDevInfo->ext_##name; // inherit extension enablement from instance, that way GetDeviceProcAddress can check // for enabled extensions for instance functions @@ -1243,7 +1271,7 @@ VkResult WrappedVulkan::vkCreateDevice(VkPhysicalDevice physicalDevice, #define CheckExt(name) \ if(!strcmp(createInfo.ppEnabledExtensionNames[i], STRINGIZE(name))) \ { \ - record->instDevInfo->name = true; \ + record->instDevInfo->ext_##name = true; \ } for(uint32_t i = 0; i < createInfo.enabledExtensionCount; i++) diff --git a/renderdoc/driver/vulkan/wrappers/vk_get_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_get_funcs.cpp index 9cbd49d36..494196397 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_get_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_get_funcs.cpp @@ -233,3 +233,24 @@ VkResult WrappedVulkan::vkMergePipelineCaches(VkDevice device, VkPipelineCache d // do nothing, our pipeline caches are always dummies return VK_SUCCESS; } + +VkResult WrappedVulkan::vkGetPhysicalDeviceExternalImageFormatPropertiesNV( + VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, + VkImageUsageFlags usage, VkImageCreateFlags flags, + VkExternalMemoryHandleTypeFlagsNV externalHandleType, + VkExternalImageFormatPropertiesNV *pExternalImageFormatProperties) +{ + return ObjDisp(physicalDevice) + ->GetPhysicalDeviceExternalImageFormatPropertiesNV(Unwrap(physicalDevice), format, type, + tiling, usage, flags, externalHandleType, + pExternalImageFormatProperties); +} + +#if defined(VK_USE_PLATFORM_WIN32_KHR) +VkResult WrappedVulkan::vkGetMemoryWin32HandleNV(VkDevice device, VkDeviceMemory memory, + VkExternalMemoryHandleTypeFlagsNV handleType, + HANDLE *pHandle) +{ + return ObjDisp(device)->GetMemoryWin32HandleNV(Unwrap(device), Unwrap(memory), handleType, pHandle); +} +#endif diff --git a/renderdoc/driver/vulkan/wrappers/vk_queue_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_queue_funcs.cpp index 11b4999e3..2ffe65671 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_queue_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_queue_funcs.cpp @@ -462,6 +462,33 @@ VkResult WrappedVulkan::vkQueueSubmit(VkQueue queue, uint32_t submitCount, tempmemSize += pSubmits[i].commandBufferCount * sizeof(VkCommandBuffer); tempmemSize += pSubmits[i].signalSemaphoreCount * sizeof(VkSemaphore); tempmemSize += pSubmits[i].waitSemaphoreCount * sizeof(VkSemaphore); + + VkGenericStruct *next = (VkGenericStruct *)pSubmits[i].pNext; + while(next) + { + if(next->sType == VK_STRUCTURE_TYPE_MAX_ENUM) + { + RDCERR("Invalid extension structure"); + } + else if(next->sType == VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV) + { +#ifdef VK_NV_win32_keyed_mutex + tempmemSize += sizeof(VkWin32KeyedMutexAcquireReleaseInfoNV); + + VkWin32KeyedMutexAcquireReleaseInfoNV *info = (VkWin32KeyedMutexAcquireReleaseInfoNV *)next; + tempmemSize += info->acquireCount * sizeof(VkDeviceMemory); + tempmemSize += info->releaseCount * sizeof(VkDeviceMemory); +#else + RDCERR("Support for VK_NV_win32_keyed_mutex not compiled in"); +#endif + } + else + { + RDCERR("Unexpected extension structure %d", next->sType); + } + + next = (VkGenericStruct *)next->pNext; + } } byte *memory = GetTempMemory(tempmemSize); @@ -471,7 +498,7 @@ VkResult WrappedVulkan::vkQueueSubmit(VkQueue queue, uint32_t submitCount, for(uint32_t i = 0; i < submitCount; i++) { - RDCASSERT(pSubmits[i].sType == VK_STRUCTURE_TYPE_SUBMIT_INFO && pSubmits[i].pNext == NULL); + RDCASSERT(pSubmits[i].sType == VK_STRUCTURE_TYPE_SUBMIT_INFO); unwrappedSubmits[i] = pSubmits[i]; VkSemaphore *unwrappedWaitSems = (VkSemaphore *)memory; @@ -498,6 +525,49 @@ VkResult WrappedVulkan::vkQueueSubmit(VkQueue queue, uint32_t submitCount, unwrappedSubmits[i].signalSemaphoreCount ? unwrappedSignalSems : NULL; for(uint32_t o = 0; o < unwrappedSubmits[i].signalSemaphoreCount; o++) unwrappedSignalSems[o] = Unwrap(pSubmits[i].pSignalSemaphores[o]); + + VkGenericStruct **nextptr = (VkGenericStruct **)&unwrappedSubmits[i].pNext; + while(*nextptr) + { + VkGenericStruct *next = *nextptr; + +#ifdef VK_NV_win32_keyed_mutex + if(next->sType == VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV) + { + // allocate local unwrapped struct + VkWin32KeyedMutexAcquireReleaseInfoNV *unwrappedMutexInfoNV = + (VkWin32KeyedMutexAcquireReleaseInfoNV *)memory; + memory += sizeof(VkWin32KeyedMutexAcquireReleaseInfoNV); + + // copy over info from original struct + VkWin32KeyedMutexAcquireReleaseInfoNV *wrappedMutexInfoNV = + (VkWin32KeyedMutexAcquireReleaseInfoNV *)next; + *unwrappedMutexInfoNV = *wrappedMutexInfoNV; + + // allocate unwrapped arrays + VkDeviceMemory *unwrappedAcquires = (VkDeviceMemory *)memory; + memory += sizeof(VkDeviceMemory) * unwrappedMutexInfoNV->acquireCount; + VkDeviceMemory *unwrappedReleases = (VkDeviceMemory *)memory; + memory += sizeof(VkDeviceMemory) * unwrappedMutexInfoNV->releaseCount; + + // unwrap the arrays + for(uint32_t mem = 0; mem < unwrappedMutexInfoNV->acquireCount; mem++) + unwrappedAcquires[mem] = Unwrap(wrappedMutexInfoNV->pAcquireSyncs[mem]); + for(uint32_t mem = 0; mem < unwrappedMutexInfoNV->releaseCount; mem++) + unwrappedReleases[mem] = Unwrap(wrappedMutexInfoNV->pReleaseSyncs[mem]); + + unwrappedMutexInfoNV->pAcquireSyncs = unwrappedAcquires; + unwrappedMutexInfoNV->pReleaseSyncs = unwrappedReleases; + + // insert this struct into the chain. + // nextptr is pointing to the address of the pNext, so we can overwrite it to point to our + // locally-allocated unwrapped struct + *nextptr = (VkGenericStruct *)unwrappedMutexInfoNV; + } +#endif + + nextptr = (VkGenericStruct **)&next->pNext; + } } VkResult ret =