From 437bf0a199e5e0c56a313cd8bc11708d7e9b367f Mon Sep 17 00:00:00 2001 From: baldurk Date: Thu, 8 Dec 2016 18:27:19 +0000 Subject: [PATCH] Add simple support for NV_external_memory family of extensions * This might not precisely reflect the contents of memory from external APIs, but it will at least run without crashing and allow programs that rely on the extension to function and capture for inspecting internal vulkan work. --- renderdoc/driver/vulkan/vk_common.cpp | 36 +++-- renderdoc/driver/vulkan/vk_core.cpp | 123 +++++++++++++----- renderdoc/driver/vulkan/vk_core.h | 12 ++ renderdoc/driver/vulkan/vk_dispatchtables.cpp | 4 +- renderdoc/driver/vulkan/vk_hookset_defs.h | 88 ++++++++----- renderdoc/driver/vulkan/vk_resources.h | 4 +- renderdoc/driver/vulkan/vk_tracelayer.cpp | 13 +- .../vulkan/wrappers/vk_device_funcs.cpp | 34 ++++- .../driver/vulkan/wrappers/vk_get_funcs.cpp | 21 +++ .../driver/vulkan/wrappers/vk_queue_funcs.cpp | 72 +++++++++- 10 files changed, 318 insertions(+), 89 deletions(-) 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 =