mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-14 05:50:51 +00:00
Filter out unsupported vulkan ICD extensions before they reach the user
This commit is contained in:
@@ -567,6 +567,147 @@ Serialiser *WrappedVulkan::GetThreadSerialiser()
|
||||
return ser;
|
||||
}
|
||||
|
||||
static VkResult FillPropertyCountAndList(const VkExtensionProperties *src, uint32_t numExts, uint32_t *dstCount, VkExtensionProperties *dstProps)
|
||||
{
|
||||
if(dstCount && !dstProps)
|
||||
{
|
||||
// just returning the number of extensions
|
||||
*dstCount = numExts;
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
else if(dstCount && dstProps)
|
||||
{
|
||||
uint32_t dstSpace = *dstCount;
|
||||
|
||||
// copy as much as there's space for, up to how many there are
|
||||
memcpy(dstProps, src, sizeof(VkExtensionProperties)*RDCMIN(numExts, dstSpace));
|
||||
|
||||
// if there was enough space, return success, else incomplete
|
||||
if(dstSpace >= numExts)
|
||||
return VK_SUCCESS;
|
||||
else
|
||||
return VK_INCOMPLETE;
|
||||
}
|
||||
|
||||
// both parameters were NULL, return incomplete
|
||||
return VK_INCOMPLETE;
|
||||
}
|
||||
|
||||
bool operator <(const VkExtensionProperties &a, const VkExtensionProperties &b)
|
||||
{
|
||||
// assume a given extension name is unique, ie. an implementation won't report the
|
||||
// same extension with two different spec versions.
|
||||
return strcmp(a.extensionName, b.extensionName) < 0;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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. 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
|
||||
};
|
||||
|
||||
// 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.
|
||||
size_t i = 0;
|
||||
for(auto it=exts.begin(); it != exts.end() && i < ARRAY_COUNT(supportedExtensions); )
|
||||
{
|
||||
int nameCompare = strcmp(it->extensionName, supportedExtensions[i].extensionName);
|
||||
// if neither is less than the other, the extensions are equal
|
||||
if(nameCompare == 0)
|
||||
{
|
||||
// warn on spec version mismatch, but allow it.
|
||||
if(supportedExtensions[i].specVersion != it->specVersion)
|
||||
RDCWARN("Spec versions are different between supported extension (%d) and reported (%d)!", supportedExtensions[i].specVersion, it->specVersion);
|
||||
|
||||
filtered.push_back(*it);
|
||||
++it;
|
||||
++i;
|
||||
}
|
||||
else if(nameCompare < 0)
|
||||
{
|
||||
// reported extension was less. It's not supported - skip past it and continue
|
||||
++it;
|
||||
}
|
||||
else if(nameCompare > 0)
|
||||
{
|
||||
// supported extension was less. Check the next supported extension
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
return FillPropertyCountAndList(&filtered[0], (uint32_t)filtered.size(), pPropertyCount, pProperties);
|
||||
}
|
||||
|
||||
VkResult WrappedVulkan::GetProvidedExtensionProperties(uint32_t *pPropertyCount, VkExtensionProperties *pProperties)
|
||||
{
|
||||
// this is the list of extensions we provide - regardless of whether the ICD supports them
|
||||
const VkExtensionProperties providedExtensions[] = {
|
||||
{
|
||||
DEBUG_MARKER_EXTENSION_NAME,
|
||||
VK_DEBUG_MARKER_EXTENSION_REVISION
|
||||
},
|
||||
};
|
||||
|
||||
return FillPropertyCountAndList(providedExtensions, (uint32_t)ARRAY_COUNT(providedExtensions), pPropertyCount, pProperties);
|
||||
}
|
||||
|
||||
void WrappedVulkan::Serialise_CaptureScope(uint64_t offset)
|
||||
{
|
||||
uint32_t FrameNumber = m_FrameCounter;
|
||||
|
||||
@@ -580,6 +580,9 @@ public:
|
||||
|
||||
void SetDrawcallCB(DrawcallCallback *cb) { m_DrawcallCallback = cb; }
|
||||
|
||||
VkResult FilterDeviceExtensionProperties(VkPhysicalDevice physDev, uint32_t *pPropertyCount, VkExtensionProperties *pProperties);
|
||||
VkResult GetProvidedExtensionProperties(uint32_t *pPropertyCount, VkExtensionProperties *pProperties);
|
||||
|
||||
// Device initialization
|
||||
|
||||
IMPLEMENT_FUNCTION_SERIALISED(VkResult, vkCreateInstance,
|
||||
|
||||
@@ -120,51 +120,6 @@ void VKAPI_CALL hooked_vkDestroyInstance(VkInstance instance, const VkAllocation
|
||||
|
||||
// Layer Intercepts
|
||||
|
||||
static const VkLayerProperties physLayers[] = {
|
||||
{
|
||||
RENDERDOC_LAYER_NAME,
|
||||
VK_API_VERSION,
|
||||
VK_MAKE_VERSION(RENDERDOC_VERSION_MAJOR, RENDERDOC_VERSION_MINOR, 0),
|
||||
"Debugging capture layer for RenderDoc",
|
||||
}
|
||||
};
|
||||
|
||||
static const VkExtensionProperties physExts[] = {
|
||||
{
|
||||
DEBUG_MARKER_EXTENSION_NAME,
|
||||
VK_MAKE_VERSION(0, 1, 0),
|
||||
}
|
||||
};
|
||||
|
||||
static const VkLayerProperties globalLayers[] = {
|
||||
{
|
||||
RENDERDOC_LAYER_NAME,
|
||||
VK_API_VERSION,
|
||||
VK_MAKE_VERSION(RENDERDOC_VERSION_MAJOR, RENDERDOC_VERSION_MINOR, 0),
|
||||
"Debugging capture layer for RenderDoc",
|
||||
}
|
||||
};
|
||||
|
||||
VkResult getProps(uint32_t *dstCount, void *dstProps, uint32_t srcCount, void *srcProps, size_t elemSize)
|
||||
{
|
||||
if(dstCount == NULL)
|
||||
return VK_RESULT_MAX_ENUM;
|
||||
|
||||
if(dstProps == NULL)
|
||||
{
|
||||
*dstCount = srcCount;
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
memcpy(dstProps, srcProps, elemSize*RDCMIN(srcCount, *dstCount));
|
||||
if(*dstCount < srcCount)
|
||||
return VK_INCOMPLETE;
|
||||
|
||||
*dstCount = srcCount;
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
#if defined(RENDERDOC_PLATFORM_WIN32) && !defined(RDC64BIT)
|
||||
|
||||
// Win32 __stdcall will still mangle even with extern "C", set up aliases
|
||||
@@ -183,7 +138,34 @@ VK_LAYER_EXPORT VkResult VKAPI_CALL VK_LAYER_RENDERDOC_CaptureEnumerateDeviceLay
|
||||
uint32_t* pPropertyCount,
|
||||
VkLayerProperties* pProperties)
|
||||
{
|
||||
return getProps(pPropertyCount, pProperties, ARRAY_COUNT(physLayers), (void *)physLayers, sizeof(VkLayerProperties));
|
||||
// must have a property count, either to fill out or use as a size
|
||||
if(pPropertyCount == NULL)
|
||||
return VK_INCOMPLETE;
|
||||
|
||||
// if we're not writing the properties, just say we have one layer
|
||||
if(pProperties == NULL)
|
||||
{
|
||||
*pPropertyCount = 1;
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
// if the property count is somehow zero, return incomplete
|
||||
if(*pPropertyCount == 0)
|
||||
return VK_INCOMPLETE;
|
||||
|
||||
const VkLayerProperties layerProperties = {
|
||||
RENDERDOC_LAYER_NAME,
|
||||
VK_API_VERSION_1_0,
|
||||
VK_MAKE_VERSION(RENDERDOC_VERSION_MAJOR, RENDERDOC_VERSION_MINOR, 0),
|
||||
"Debugging capture layer for RenderDoc",
|
||||
};
|
||||
|
||||
// set the one layer property
|
||||
*pProperties = layerProperties;
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
VK_LAYER_EXPORT VkResult VKAPI_CALL VK_LAYER_RENDERDOC_CaptureEnumerateDeviceExtensionProperties(
|
||||
@@ -195,9 +177,9 @@ VK_LAYER_EXPORT VkResult VKAPI_CALL VK_LAYER_RENDERDOC_CaptureEnumerateDeviceExt
|
||||
// if pLayerName is NULL we're calling down through the layer chain to the ICD.
|
||||
// This is our chance to filter out any reported extensions that we don't support
|
||||
if(pLayerName == NULL)
|
||||
return ObjDisp(physicalDevice)->EnumerateDeviceExtensionProperties(Unwrap(physicalDevice), pLayerName, pPropertyCount, pProperties);
|
||||
return CoreDisp(physicalDevice)->FilterDeviceExtensionProperties(physicalDevice, pPropertyCount, pProperties);
|
||||
|
||||
return getProps(pPropertyCount, pProperties, ARRAY_COUNT(physExts), (void *)physExts, sizeof(VkExtensionProperties));
|
||||
return CoreDisp(physicalDevice)->GetProvidedExtensionProperties(pPropertyCount, pProperties);
|
||||
}
|
||||
|
||||
#undef HookInit
|
||||
|
||||
Reference in New Issue
Block a user