diff --git a/renderdoc/driver/vulkan/official/vk_layer.h b/renderdoc/driver/vulkan/official/vk_layer.h index a7ac29150..147dcd43a 100644 --- a/renderdoc/driver/vulkan/official/vk_layer.h +++ b/renderdoc/driver/vulkan/official/vk_layer.h @@ -48,6 +48,8 @@ #define CURRENT_LOADER_LAYER_INTERFACE_VERSION 2 #define MIN_SUPPORTED_LOADER_LAYER_INTERFACE_VERSION 1 +#define VK_CURRENT_CHAIN_VERSION 1 + // Version negotiation values typedef enum VkNegotiateLayerStructType { LAYER_NEGOTIATE_UNINTIALIZED = 0, @@ -138,6 +140,43 @@ extern "C" { VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct); +typedef enum VkChainType { + VK_CHAIN_TYPE_UNKNOWN = 0, + VK_CHAIN_TYPE_ENUMERATE_INSTANCE_EXTENSION_PROPERTIES = 1, + VK_CHAIN_TYPE_ENUMERATE_INSTANCE_LAYER_PROPERTIES = 2, +} VkChainType; + +typedef struct VkChainHeader { + VkChainType type; + uint32_t version; + uint32_t size; +} VkChainHeader; + +typedef struct VkEnumerateInstanceExtensionPropertiesChain { + VkChainHeader header; + VkResult(VKAPI_PTR *pfnNextLayer)(const struct VkEnumerateInstanceExtensionPropertiesChain *, const char *, uint32_t *, + VkExtensionProperties *); + const struct VkEnumerateInstanceExtensionPropertiesChain *pNextLink; + +#if defined(__cplusplus) + inline VkResult CallDown(const char *pLayerName, uint32_t *pPropertyCount, VkExtensionProperties *pProperties) const { + return pfnNextLayer(pNextLink, pLayerName, pPropertyCount, pProperties); + } +#endif +} VkEnumerateInstanceExtensionPropertiesChain; + +typedef struct VkEnumerateInstanceLayerPropertiesChain { + VkChainHeader header; + VkResult(VKAPI_PTR *pfnNextLayer)(const struct VkEnumerateInstanceLayerPropertiesChain *, uint32_t *, VkLayerProperties *); + const struct VkEnumerateInstanceLayerPropertiesChain *pNextLink; + +#if defined(__cplusplus) + inline VkResult CallDown(uint32_t *pPropertyCount, VkLayerProperties *pProperties) const { + return pfnNextLayer(pNextLink, pPropertyCount, pProperties); + } +#endif +} VkEnumerateInstanceLayerPropertiesChain; + #ifdef __cplusplus } #endif diff --git a/renderdoc/driver/vulkan/renderdoc.json b/renderdoc/driver/vulkan/renderdoc.json index fd1acfdf9..872b70c00 100644 --- a/renderdoc/driver/vulkan/renderdoc.json +++ b/renderdoc/driver/vulkan/renderdoc.json @@ -1,5 +1,5 @@ { - "file_format_version" : "1.0.0", + "file_format_version" : "1.1.2", "layer" : { "name": "VK_LAYER_RENDERDOC_Capture", "type": "GLOBAL", @@ -11,6 +11,9 @@ "vkGetInstanceProcAddr": "VK_LAYER_RENDERDOC_CaptureGetInstanceProcAddr", "vkGetDeviceProcAddr": "VK_LAYER_RENDERDOC_CaptureGetDeviceProcAddr" }, + "pre_instance_functions": { + "vkEnumerateInstanceExtensionProperties": "VK_LAYER_RENDERDOC_CaptureEnumerateInstanceExtensionProperties" + }, "device_extensions": [ { "name": "VK_EXT_debug_marker", diff --git a/renderdoc/driver/vulkan/vk_core.cpp b/renderdoc/driver/vulkan/vk_core.cpp index ebed63868..cd3abaaf7 100644 --- a/renderdoc/driver/vulkan/vk_core.cpp +++ b/renderdoc/driver/vulkan/vk_core.cpp @@ -487,7 +487,8 @@ static VkResult FillPropertyCountAndList(const VkExtensionProperties *src, uint3 *dstCount = RDCMIN(numExts, dstSpace); // copy as much as there's space for, up to how many there are - memcpy(dstProps, src, sizeof(VkExtensionProperties) * RDCMIN(numExts, dstSpace)); + if(src) + memcpy(dstProps, src, sizeof(VkExtensionProperties) * RDCMIN(numExts, dstSpace)); // if there was enough space, return success, else incomplete if(dstSpace >= numExts) @@ -681,7 +682,7 @@ static const VkExtensionProperties supportedExtensions[] = { }; // this is the list of extensions we provide - regardless of whether the ICD supports them -static const VkExtensionProperties renderdocProvidedExtensions[] = { +static const VkExtensionProperties renderdocProvidedDeviceExtensions[] = { {VK_EXT_DEBUG_MARKER_EXTENSION_NAME, VK_EXT_DEBUG_MARKER_SPEC_VERSION}, }; @@ -694,34 +695,9 @@ bool WrappedVulkan::IsSupportedExtension(const char *extName) return false; } -VkResult WrappedVulkan::FilterDeviceExtensionProperties(VkPhysicalDevice physDev, - uint32_t *pPropertyCount, - VkExtensionProperties *pProperties) +void WrappedVulkan::FilterToSupportedExtensions(std::vector &exts, + std::vector &filtered) { - VkResult vkr; - - // first fetch the list of extensions ourselves - uint32_t numExts; - vkr = ObjDisp(physDev)->EnumerateDeviceExtensionProperties(Unwrap(physDev), NULL, &numExts, NULL); - - if(vkr != VK_SUCCESS) - return vkr; - - vector exts(numExts); - vkr = ObjDisp(physDev)->EnumerateDeviceExtensionProperties(Unwrap(physDev), NULL, &numExts, - &exts[0]); - - if(vkr != VK_SUCCESS) - return vkr; - - // filter the list of extensions to only the ones we support. - - // sort the reported extensions - std::sort(exts.begin(), exts.end()); - - std::vector filtered; - filtered.reserve(exts.size()); - // now we can step through both lists with two pointers, // instead of doing an O(N*M) lookup searching through each // supported extension for each reported extension. @@ -753,24 +729,94 @@ VkResult WrappedVulkan::FilterDeviceExtensionProperties(VkPhysicalDevice physDev ++i; } } +} + +VkResult WrappedVulkan::FilterDeviceExtensionProperties(VkPhysicalDevice physDev, + uint32_t *pPropertyCount, + VkExtensionProperties *pProperties) +{ + VkResult vkr; + + // first fetch the list of extensions ourselves + uint32_t numExts; + vkr = ObjDisp(physDev)->EnumerateDeviceExtensionProperties(Unwrap(physDev), NULL, &numExts, NULL); + + if(vkr != VK_SUCCESS) + return vkr; + + std::vector exts(numExts); + vkr = ObjDisp(physDev)->EnumerateDeviceExtensionProperties(Unwrap(physDev), NULL, &numExts, + &exts[0]); + + if(vkr != VK_SUCCESS) + return vkr; + + // filter the list of extensions to only the ones we support. + + // sort the reported extensions + std::sort(exts.begin(), exts.end()); + + std::vector filtered; + filtered.reserve(exts.size()); + FilterToSupportedExtensions(exts, filtered); // now we can add extensions that we provide ourselves (note this isn't sorted, but we // don't have to sort the results, the sorting was just so we could filter optimally). - filtered.insert(filtered.end(), &renderdocProvidedExtensions[0], - &renderdocProvidedExtensions[0] + ARRAY_COUNT(renderdocProvidedExtensions)); + filtered.insert( + filtered.end(), &renderdocProvidedDeviceExtensions[0], + &renderdocProvidedDeviceExtensions[0] + ARRAY_COUNT(renderdocProvidedDeviceExtensions)); return FillPropertyCountAndList(&filtered[0], (uint32_t)filtered.size(), pPropertyCount, pProperties); } -VkResult WrappedVulkan::GetProvidedExtensionProperties(uint32_t *pPropertyCount, - VkExtensionProperties *pProperties) +VkResult WrappedVulkan::FilterInstanceExtensionProperties( + const VkEnumerateInstanceExtensionPropertiesChain *pChain, const char *pLayerName, + uint32_t *pPropertyCount, VkExtensionProperties *pProperties) { - return FillPropertyCountAndList(renderdocProvidedExtensions, - (uint32_t)ARRAY_COUNT(renderdocProvidedExtensions), + VkResult vkr; + + // first fetch the list of extensions ourselves + uint32_t numExts; + vkr = pChain->CallDown(pLayerName, &numExts, NULL); + + if(vkr != VK_SUCCESS) + return vkr; + + std::vector exts(numExts); + vkr = pChain->CallDown(pLayerName, &numExts, &exts[0]); + + if(vkr != VK_SUCCESS) + return vkr; + + // filter the list of extensions to only the ones we support. + + // sort the reported extensions + std::sort(exts.begin(), exts.end()); + + std::vector filtered; + filtered.reserve(exts.size()); + + FilterToSupportedExtensions(exts, filtered); + + return FillPropertyCountAndList(&filtered[0], (uint32_t)filtered.size(), pPropertyCount, + pProperties); +} + +VkResult WrappedVulkan::GetProvidedDeviceExtensionProperties(uint32_t *pPropertyCount, + VkExtensionProperties *pProperties) +{ + return FillPropertyCountAndList(renderdocProvidedDeviceExtensions, + (uint32_t)ARRAY_COUNT(renderdocProvidedDeviceExtensions), pPropertyCount, pProperties); } +VkResult WrappedVulkan::GetProvidedInstanceExtensionProperties(uint32_t *pPropertyCount, + VkExtensionProperties *pProperties) +{ + return FillPropertyCountAndList(NULL, 0, pPropertyCount, pProperties); +} + template bool WrappedVulkan::Serialise_CaptureScope(SerialiserType &ser) { diff --git a/renderdoc/driver/vulkan/vk_core.h b/renderdoc/driver/vulkan/vk_core.h index a0f0db32d..aefd0c3c0 100644 --- a/renderdoc/driver/vulkan/vk_core.h +++ b/renderdoc/driver/vulkan/vk_core.h @@ -807,11 +807,18 @@ public: VulkanRenderState &GetRenderState() { return m_RenderState; } void SetDrawcallCB(VulkanDrawcallCallback *cb) { m_DrawcallCallback = cb; } - bool IsSupportedExtension(const char *extName); + static bool IsSupportedExtension(const char *extName); + static void FilterToSupportedExtensions(std::vector &exts, + std::vector &filtered); VkResult FilterDeviceExtensionProperties(VkPhysicalDevice physDev, uint32_t *pPropertyCount, VkExtensionProperties *pProperties); - static VkResult GetProvidedExtensionProperties(uint32_t *pPropertyCount, - VkExtensionProperties *pProperties); + static VkResult FilterInstanceExtensionProperties( + const VkEnumerateInstanceExtensionPropertiesChain *pChain, const char *pLayerName, + uint32_t *pPropertyCount, VkExtensionProperties *pProperties); + static VkResult GetProvidedDeviceExtensionProperties(uint32_t *pPropertyCount, + VkExtensionProperties *pProperties); + static VkResult GetProvidedInstanceExtensionProperties(uint32_t *pPropertyCount, + VkExtensionProperties *pProperties); const VkPhysicalDeviceFeatures &GetDeviceFeatures() { return m_PhysicalDeviceData.features; } // Device initialization diff --git a/renderdoc/driver/vulkan/vk_layer.cpp b/renderdoc/driver/vulkan/vk_layer.cpp index d75e7eb02..b9542e1f4 100644 --- a/renderdoc/driver/vulkan/vk_layer.cpp +++ b/renderdoc/driver/vulkan/vk_layer.cpp @@ -186,6 +186,9 @@ void VKAPI_CALL hooked_vkDestroyInstance(VkInstance instance, const VkAllocation #pragma comment( \ linker, \ "/EXPORT:VK_LAYER_RENDERDOC_CaptureEnumerateDeviceExtensionProperties=_VK_LAYER_RENDERDOC_CaptureEnumerateDeviceExtensionProperties@16") +#pragma comment( \ + linker, \ + "/EXPORT:VK_LAYER_RENDERDOC_CaptureEnumerateInstanceExtensionProperties=_VK_LAYER_RENDERDOC_CaptureEnumerateInstanceExtensionProperties@16") #pragma comment( \ linker, \ "/EXPORT:VK_LAYER_RENDERDOC_CaptureGetDeviceProcAddr=_VK_LAYER_RENDERDOC_CaptureGetDeviceProcAddr@8") @@ -239,7 +242,18 @@ VK_LAYER_EXPORT VkResult VKAPI_CALL VK_LAYER_RENDERDOC_CaptureEnumerateDeviceExt return CoreDisp(physicalDevice) ->FilterDeviceExtensionProperties(physicalDevice, pPropertyCount, pProperties); - return WrappedVulkan::GetProvidedExtensionProperties(pPropertyCount, pProperties); + return WrappedVulkan::GetProvidedDeviceExtensionProperties(pPropertyCount, pProperties); +} + +VK_LAYER_EXPORT VkResult VKAPI_CALL VK_LAYER_RENDERDOC_CaptureEnumerateInstanceExtensionProperties( + const VkEnumerateInstanceExtensionPropertiesChain *pChain, const char *pLayerName, + uint32_t *pPropertyCount, VkExtensionProperties *pProperties) +{ + if(pLayerName && !strcmp(pLayerName, RENDERDOC_LAYER_NAME)) + return WrappedVulkan::GetProvidedInstanceExtensionProperties(pPropertyCount, pProperties); + + return WrappedVulkan::FilterInstanceExtensionProperties(pChain, pLayerName, pPropertyCount, + pProperties); } #undef HookInit @@ -290,6 +304,8 @@ VK_LAYER_RENDERDOC_CaptureGetInstanceProcAddr(VkInstance instance, const char *p return (PFN_vkVoidFunction)&VK_LAYER_RENDERDOC_CaptureEnumerateDeviceLayerProperties; if(!strcmp("vkEnumerateDeviceExtensionProperties", pName)) return (PFN_vkVoidFunction)&VK_LAYER_RENDERDOC_CaptureEnumerateDeviceExtensionProperties; + if(!strcmp("vkEnumerateInstanceExtensionProperties", pName)) + return (PFN_vkVoidFunction)&VK_LAYER_RENDERDOC_CaptureEnumerateInstanceExtensionProperties; if(!strcmp("vkGetDeviceProcAddr", pName)) return (PFN_vkVoidFunction)&VK_LAYER_RENDERDOC_CaptureGetDeviceProcAddr; if(!strcmp("vkCreateDevice", pName))