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:
baldurk
2018-01-11 13:48:35 +00:00
parent 32d57f4019
commit 21a16e051b
5 changed files with 151 additions and 40 deletions
@@ -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
+4 -1
View File
@@ -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",
+81 -35
View File
@@ -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)
{
+10 -3
View File
@@ -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
+17 -1
View File
@@ -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))