Vulkan: Provide a more accurate method of detecting drivers/vendors

This is needed to differentiate between the open-source Mesa drivers and
their binary counterparts for Intel and AMD.
This commit is contained in:
Stenzek 2017-09-19 21:11:33 +10:00
parent f7ff634e4f
commit db810956ec
4 changed files with 80 additions and 38 deletions

View File

@ -352,11 +352,7 @@ std::unique_ptr<VulkanContext> VulkanContext::Create(VkInstance instance, VkPhys
std::unique_ptr<VulkanContext> context = std::make_unique<VulkanContext>(instance, gpu); std::unique_ptr<VulkanContext> context = std::make_unique<VulkanContext>(instance, gpu);
// Initialize DriverDetails so that we can check for bugs to disable features if needed. // Initialize DriverDetails so that we can check for bugs to disable features if needed.
DriverDetails::Init(DriverDetails::API_VULKAN, context->InitDriverDetails();
DriverDetails::TranslatePCIVendorID(context->m_device_properties.vendorID),
DriverDetails::DRIVER_UNKNOWN,
static_cast<double>(context->m_device_properties.driverVersion),
DriverDetails::Family::UNKNOWN);
// Enable debug reports if the "Host GPU" log category is enabled. // Enable debug reports if the "Host GPU" log category is enabled.
if (enable_debug_reports) if (enable_debug_reports)
@ -761,4 +757,82 @@ u32 VulkanContext::GetReadbackMemoryType(u32 bits, bool* is_coherent, bool* is_c
return type_index; return type_index;
} }
void VulkanContext::InitDriverDetails()
{
DriverDetails::Vendor vendor;
DriverDetails::Driver driver;
// String comparisons aren't ideal, but there doesn't seem to be any other way to tell
// which vendor a driver is for. These names are based on the reports submitted to
// vulkan.gpuinfo.org, as of 19/09/2017.
std::string device_name = m_device_properties.deviceName;
u32 vendor_id = m_device_properties.vendorID;
if (vendor_id == 0x10DE)
{
// Currently, there is only the official NV binary driver.
// "NVIDIA" does not appear in the device name.
vendor = DriverDetails::VENDOR_NVIDIA;
driver = DriverDetails::DRIVER_NVIDIA;
}
else if (vendor_id == 0x1002 || vendor_id == 0x1022 ||
device_name.find("AMD") != std::string::npos)
{
// RADV always advertises its name in the device string.
// If not RADV, assume the AMD binary driver.
if (device_name.find("RADV") != std::string::npos)
{
vendor = DriverDetails::VENDOR_MESA;
driver = DriverDetails::DRIVER_R600;
}
else
{
vendor = DriverDetails::VENDOR_ATI;
driver = DriverDetails::DRIVER_ATI;
}
}
else if (vendor_id == 0x8086 || vendor_id == 0x8087 ||
device_name.find("Intel") != std::string::npos)
{
// Apart from the driver version, Intel does not appear to provide a way to
// differentiate between anv and the binary driver (Skylake+). Assume to be
// using anv if we not running on Windows.
#ifdef WIN32
vendor = DriverDetails::VENDOR_INTEL;
driver = DriverDetails::DRIVER_INTEL;
#else
vendor = DriverDetails::VENDOR_MESA;
driver = DriverDetails::DRIVER_I965;
#endif
}
else if (vendor_id == 0x5143 || device_name.find("Adreno") != std::string::npos)
{
// Currently only the Qualcomm binary driver exists for Adreno.
vendor = DriverDetails::VENDOR_QUALCOMM;
driver = DriverDetails::DRIVER_QUALCOMM;
}
else if (vendor_id == 0x13B6 || device_name.find("Mali") != std::string::npos)
{
// Currently only the ARM binary driver exists for Mali.
vendor = DriverDetails::VENDOR_ARM;
driver = DriverDetails::DRIVER_ARM;
}
else if (vendor_id == 0x1010 || device_name.find("PowerVR") != std::string::npos)
{
// Currently only the binary driver exists for PowerVR.
vendor = DriverDetails::VENDOR_IMGTEC;
driver = DriverDetails::DRIVER_IMGTEC;
}
else
{
WARN_LOG(VIDEO, "Unknown Vulkan driver vendor, please report it to us.");
WARN_LOG(VIDEO, "Vendor ID: 0x%X, Device Name: %s", vendor_id, device_name.c_str());
vendor = DriverDetails::VENDOR_UNKNOWN;
driver = DriverDetails::DRIVER_UNKNOWN;
}
DriverDetails::Init(DriverDetails::API_VULKAN, vendor, driver,
static_cast<double>(m_device_properties.driverVersion),
DriverDetails::Family::UNKNOWN);
}
} }

View File

@ -114,6 +114,7 @@ private:
bool SelectDeviceExtensions(ExtensionList* extension_list, bool enable_surface); bool SelectDeviceExtensions(ExtensionList* extension_list, bool enable_surface);
bool SelectDeviceFeatures(); bool SelectDeviceFeatures();
bool CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer); bool CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer);
void InitDriverDetails();
VkInstance m_instance = VK_NULL_HANDLE; VkInstance m_instance = VK_NULL_HANDLE;
VkPhysicalDevice m_physical_device = VK_NULL_HANDLE; VkPhysicalDevice m_physical_device = VK_NULL_HANDLE;

View File

@ -165,34 +165,4 @@ bool HasBug(Bug bug)
return false; return false;
return it->second.m_hasbug; return it->second.m_hasbug;
} }
Vendor TranslatePCIVendorID(u32 vendor_id)
{
switch (vendor_id)
{
case 0x10DE:
return VENDOR_NVIDIA;
case 0x1002:
case 0x1022:
return VENDOR_ATI;
case 0x8086:
case 0x8087:
return VENDOR_INTEL;
// TODO: Is this correct for Mali?
case 0x13B6:
return VENDOR_ARM;
case 0x5143:
return VENDOR_QUALCOMM;
case 0x1010:
return VENDOR_IMGTEC;
default:
return VENDOR_UNKNOWN;
}
}
} }

View File

@ -285,7 +285,4 @@ void Init(API api, Vendor vendor, Driver driver, const double version, const Fam
// Once Vendor and driver version is set, this will return if it has the applicable bug passed to // Once Vendor and driver version is set, this will return if it has the applicable bug passed to
// it. // it.
bool HasBug(Bug bug); bool HasBug(Bug bug);
// Attempts to map a PCI vendor ID to our Vendor enumeration
Vendor TranslatePCIVendorID(u32 vendor_id);
} }