Use KHR_driver_properties and versions to better match physical devices

This commit is contained in:
baldurk
2019-05-27 17:22:38 +01:00
parent 2ff6adb659
commit 395fb3ed50
3 changed files with 200 additions and 28 deletions
+5
View File
@@ -270,6 +270,11 @@ bool VkInitParams::IsSupportedVersion(uint64_t ver)
if(ver == CurrentVersion)
return true;
// 0xF -> 0x10 - added serialisation of VkPhysicalDeviceDriverPropertiesKHR into enumerated
// physical devices
if(ver == 0xF)
return true;
// 0xE -> 0xF - serialisation of VkPhysicalDeviceVulkanMemoryModelFeaturesKHR changed in vulkan
// 1.1.99, adding a new field
if(ver == 0xE)
+1 -1
View File
@@ -52,7 +52,7 @@ struct VkInitParams
uint64_t GetSerialiseSize();
// check if a frame capture section version is supported
static const uint64_t CurrentVersion = 0xF;
static const uint64_t CurrentVersion = 0x10;
static bool IsSupportedVersion(uint64_t ver);
};
@@ -871,6 +871,10 @@ bool WrappedVulkan::Serialise_vkEnumeratePhysicalDevices(SerialiserType &ser, Vk
uint32_t queueCount = 0;
VkQueueFamilyProperties queueProps[16] = {};
VkPhysicalDeviceDriverPropertiesKHR driverProps = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR,
};
if(ser.IsWriting())
{
memcpy(memIdxMap, GetRecord(*pPhysicalDevices)->memIdxMap, sizeof(memIdxMap));
@@ -890,6 +894,33 @@ bool WrappedVulkan::Serialise_vkEnumeratePhysicalDevices(SerialiserType &ser, Vk
ObjDisp(instance)->GetPhysicalDeviceQueueFamilyProperties(Unwrap(*pPhysicalDevices),
&queueCount, queueProps);
if(GetExtensions(GetRecord(instance)).ext_KHR_get_physical_device_properties2)
{
uint32_t count = 0;
ObjDisp(*pPhysicalDevices)
->EnumerateDeviceExtensionProperties(Unwrap(*pPhysicalDevices), NULL, &count, NULL);
VkExtensionProperties *props = new VkExtensionProperties[count];
ObjDisp(*pPhysicalDevices)
->EnumerateDeviceExtensionProperties(Unwrap(*pPhysicalDevices), NULL, &count, props);
for(uint32_t e = 0; e < count; e++)
{
if(!strcmp(props[e].extensionName, VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME))
{
VkPhysicalDeviceProperties2 physProps2 = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
};
physProps2.pNext = &driverProps;
ObjDisp(instance)->GetPhysicalDeviceProperties2(Unwrap(*pPhysicalDevices), &physProps2);
break;
}
}
SAFE_DELETE_ARRAY(props);
}
}
SERIALISE_ELEMENT(memIdxMap);
@@ -899,20 +930,28 @@ bool WrappedVulkan::Serialise_vkEnumeratePhysicalDevices(SerialiserType &ser, Vk
SERIALISE_ELEMENT(queueCount);
SERIALISE_ELEMENT(queueProps);
// serialisation of the driver properties was added in 0x10
if(ser.VersionAtLeast(0x10))
{
SERIALISE_ELEMENT(driverProps);
// we don't need any special handling if this is missing - the properties will be empty which is
// the same as a new capture if we can't query the properties
}
VkPhysicalDevice pd = VK_NULL_HANDLE;
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
bool firstTime = true;
for(bool used : m_ReplayPhysicalDevicesUsed)
if(used)
firstTime = false;
{
VkDriverInfo capturedVersion(physProps);
RDCLOG("Capture describes physical device %u:", PhysicalDeviceIndex);
RDCLOG(" - %s (ver %u.%u patch 0x%x) - %04x:%04x", physProps.deviceName,
capturedVersion.Major(), capturedVersion.Minor(), capturedVersion.Patch(),
physProps.vendorID, physProps.deviceID);
if(PhysicalDeviceIndex >= m_OriginalPhysicalDevices.size())
m_OriginalPhysicalDevices.resize(PhysicalDeviceIndex + 1);
@@ -931,31 +970,81 @@ bool WrappedVulkan::Serialise_vkEnumeratePhysicalDevices(SerialiserType &ser, Vk
// bad side-effects as e.g. we have to pick one memidxmap, but this is as good as we can do.
uint32_t bestIdx = 0;
VkPhysicalDeviceProperties bestPhysProps;
VkPhysicalDeviceMemoryProperties bestMemProps;
VkPhysicalDeviceProperties bestPhysProps = {};
VkPhysicalDeviceDriverPropertiesKHR bestDriverProps = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR,
};
pd = m_ReplayPhysicalDevices[bestIdx];
ObjDisp(pd)->GetPhysicalDeviceProperties(Unwrap(pd), &bestPhysProps);
ObjDisp(pd)->GetPhysicalDeviceMemoryProperties(Unwrap(pd), &bestMemProps);
for(uint32_t i = 1; i < (uint32_t)m_ReplayPhysicalDevices.size(); i++)
for(uint32_t i = 0; i < (uint32_t)m_ReplayPhysicalDevices.size(); i++)
{
VkPhysicalDeviceProperties compPhysProps;
VkPhysicalDeviceMemoryProperties compMemProps;
VkPhysicalDeviceProperties compPhysProps = {};
VkPhysicalDeviceDriverPropertiesKHR compDriverProps = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR,
};
pd = m_ReplayPhysicalDevices[i];
// find the best possible match for this physical device
ObjDisp(pd)->GetPhysicalDeviceProperties(Unwrap(pd), &compPhysProps);
ObjDisp(pd)->GetPhysicalDeviceMemoryProperties(Unwrap(pd), &compMemProps);
if(m_EnabledExtensions.ext_KHR_get_physical_device_properties2)
{
uint32_t count = 0;
ObjDisp(pd)->EnumerateDeviceExtensionProperties(Unwrap(pd), NULL, &count, NULL);
VkExtensionProperties *props = new VkExtensionProperties[count];
ObjDisp(pd)->EnumerateDeviceExtensionProperties(Unwrap(pd), NULL, &count, props);
for(uint32_t e = 0; e < count; e++)
{
if(!strcmp(props[e].extensionName, VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME))
{
VkPhysicalDeviceProperties2 physProps2 = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
};
physProps2.pNext = &compDriverProps;
ObjDisp(pd)->GetPhysicalDeviceProperties2(Unwrap(pd), &physProps2);
break;
}
}
SAFE_DELETE_ARRAY(props);
}
if(firstTime)
{
VkDriverInfo runningVersion(compPhysProps);
RDCLOG("Replay has physical device %u available:", i);
RDCLOG(" - %s (ver %u.%u patch 0x%x) - %04x:%04x", compPhysProps.deviceName,
runningVersion.Major(), runningVersion.Minor(), runningVersion.Patch(),
compPhysProps.vendorID, compPhysProps.deviceID);
if(compDriverProps.driverID != 0)
{
RDCLOG(
" - %s driver: %s (%s) - CTS %d.%d.%d.%d", ToStr(compDriverProps.driverID).c_str(),
compDriverProps.driverName, compDriverProps.driverInfo,
compDriverProps.conformanceVersion.major, compDriverProps.conformanceVersion.minor,
compDriverProps.conformanceVersion.subminor, compDriverProps.conformanceVersion.patch);
}
}
// the first is the best at the start
if(i == 0)
{
bestPhysProps = compPhysProps;
bestDriverProps = compDriverProps;
continue;
}
// an exact vendorID match is a better match than not
if(compPhysProps.vendorID == physProps.vendorID && bestPhysProps.vendorID != physProps.vendorID)
{
bestIdx = i;
bestPhysProps = compPhysProps;
bestMemProps = compMemProps;
bestDriverProps = compDriverProps;
continue;
}
else if(compPhysProps.vendorID != physProps.vendorID)
@@ -968,7 +1057,7 @@ bool WrappedVulkan::Serialise_vkEnumeratePhysicalDevices(SerialiserType &ser, Vk
{
bestIdx = i;
bestPhysProps = compPhysProps;
bestMemProps = compMemProps;
bestDriverProps = compDriverProps;
continue;
}
else if(compPhysProps.deviceID != physProps.deviceID)
@@ -976,13 +1065,45 @@ bool WrappedVulkan::Serialise_vkEnumeratePhysicalDevices(SerialiserType &ser, Vk
continue;
}
// driver matching. Only do this if both capture and replay gave us valid driver info to
// compare
if(compDriverProps.driverID && driverProps.driverID)
{
// check for a better driverID match
if(compDriverProps.driverID == driverProps.driverID &&
bestDriverProps.driverID != driverProps.driverID)
{
bestIdx = i;
bestPhysProps = compPhysProps;
bestDriverProps = compDriverProps;
continue;
}
else if(compDriverProps.driverID != driverProps.driverID)
{
continue;
}
}
// if we have an exact driver version match, prefer that
if(compPhysProps.driverVersion == physProps.driverVersion &&
bestPhysProps.driverVersion != physProps.driverVersion)
{
bestIdx = i;
bestPhysProps = compPhysProps;
bestDriverProps = compDriverProps;
continue;
}
else if(compPhysProps.driverVersion != physProps.driverVersion)
{
continue;
}
// if we have multiple identical devices, which isn't uncommon, favour the one
// that hasn't been assigned
if(m_ReplayPhysicalDevicesUsed[bestIdx] && !m_ReplayPhysicalDevicesUsed[i])
{
bestIdx = i;
bestPhysProps = compPhysProps;
bestMemProps = compMemProps;
continue;
}
@@ -990,12 +1111,22 @@ bool WrappedVulkan::Serialise_vkEnumeratePhysicalDevices(SerialiserType &ser, Vk
}
{
VkDriverInfo runningVersion(bestPhysProps);
VkDriverInfo capturedVersion(physProps);
RDCLOG("Mapping during replay to physical device %u:", bestIdx);
RDCLOG(" - %s (ver %u.%u patch 0x%x) - %04x:%04x", bestPhysProps.deviceName,
runningVersion.Major(), runningVersion.Minor(), runningVersion.Patch(),
bestPhysProps.vendorID, bestPhysProps.deviceID);
RDCLOG("Found capture physical device %u:", PhysicalDeviceIndex);
RDCLOG(" - %s (ver %u.%u patch 0x%x) - %04x:%04x", physProps.deviceName,
capturedVersion.Major(), capturedVersion.Minor(), capturedVersion.Patch(),
physProps.vendorID, physProps.deviceID);
if(driverProps.driverID != 0)
{
RDCLOG(" - %s driver: %s (%s) - CTS %d.%d.%d.%d", ToStr(driverProps.driverID).c_str(),
driverProps.driverName, driverProps.driverInfo, driverProps.conformanceVersion.major,
driverProps.conformanceVersion.minor, driverProps.conformanceVersion.subminor,
driverProps.conformanceVersion.patch);
}
RDCLOG("Mapping during replay to best-match physical device %u", bestIdx);
}
pd = m_ReplayPhysicalDevices[bestIdx];
@@ -1030,7 +1161,7 @@ bool WrappedVulkan::Serialise_vkEnumeratePhysicalDevices(SerialiserType &ser, Vk
if(m_ReplayPhysicalDevicesUsed[bestIdx])
{
// error if we're remapping multiple physical devices to the same best match
RDCERR(
RDCWARN(
"Mapping multiple capture-time physical devices to a single replay-time physical device."
"This means the HW has changed between capture and replay and may cause bugs.");
}
@@ -1289,6 +1420,13 @@ bool WrappedVulkan::Serialise_vkCreateDevice(SerialiserType &ser, VkPhysicalDevi
RDCLOG("Enabling VK_MVK_moltenvk");
}
// enable VK_KHR_driver_properties if it's available, to match up to capture-time
if(supportedExtensions.find(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME) != supportedExtensions.end())
{
Extensions.push_back(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME);
RDCLOG("Enabling VK_KHR_driver_properties");
}
bool xfb = false;
// enable VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME if it's available, to fetch mesh output in
@@ -2273,6 +2411,35 @@ VkResult WrappedVulkan::vkCreateDevice(VkPhysicalDevice physicalDevice,
}
}
std::vector<const char *> Extensions(
createInfo.ppEnabledExtensionNames,
createInfo.ppEnabledExtensionNames + createInfo.enabledExtensionCount);
// enable VK_KHR_driver_properties if it's available
{
uint32_t count = 0;
ObjDisp(physicalDevice)
->EnumerateDeviceExtensionProperties(Unwrap(physicalDevice), NULL, &count, NULL);
VkExtensionProperties *props = new VkExtensionProperties[count];
ObjDisp(physicalDevice)
->EnumerateDeviceExtensionProperties(Unwrap(physicalDevice), NULL, &count, props);
for(uint32_t e = 0; e < count; e++)
{
if(!strcmp(props[e].extensionName, VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME))
{
Extensions.push_back(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME);
break;
}
}
SAFE_DELETE_ARRAY(props);
}
createInfo.ppEnabledExtensionNames = Extensions.data();
createInfo.enabledExtensionCount = (uint32_t)Extensions.size();
uint32_t qCount = 0;
VkResult vkr = VK_SUCCESS;