mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-08-15 11:06:54 +00:00
Add support for pre-instance layer functions
* Added to the vulkan loader after 1.0.65, this lets us intercept the enumeration of instance extensions (before our layer is actually initialised) so that we can filter out unsupported extensions.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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<VkExtensionProperties> &exts,
|
||||
std::vector<VkExtensionProperties> &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<VkExtensionProperties> 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<VkExtensionProperties> 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<VkExtensionProperties> 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<VkExtensionProperties> 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<VkExtensionProperties> 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<VkExtensionProperties> 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 <typename SerialiserType>
|
||||
bool WrappedVulkan::Serialise_CaptureScope(SerialiserType &ser)
|
||||
{
|
||||
|
||||
@@ -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<VkExtensionProperties> &exts,
|
||||
std::vector<VkExtensionProperties> &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
|
||||
|
||||
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user