mirror of https://github.com/RPCS3/rpcs3.git
vk: Refactor device management and improve driver detection
This commit is contained in:
parent
25bba9bf56
commit
b645ebdb04
|
@ -407,25 +407,127 @@ namespace vk
|
|||
mem_allocator_base::mem_handle_t m_mem_handle;
|
||||
};
|
||||
|
||||
class supported_extensions
|
||||
{
|
||||
private:
|
||||
std::vector<VkExtensionProperties> m_vk_exts;
|
||||
|
||||
public:
|
||||
enum enumeration_class
|
||||
{
|
||||
instance = 0,
|
||||
device = 1
|
||||
};
|
||||
|
||||
supported_extensions(enumeration_class _class, const char* layer_name = nullptr, VkPhysicalDevice pdev = VK_NULL_HANDLE)
|
||||
{
|
||||
uint32_t count;
|
||||
if (_class == enumeration_class::instance)
|
||||
{
|
||||
if (vkEnumerateInstanceExtensionProperties(layer_name, &count, nullptr) != VK_SUCCESS)
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
verify(HERE), pdev;
|
||||
if (vkEnumerateDeviceExtensionProperties(pdev, layer_name, &count, nullptr) != VK_SUCCESS)
|
||||
return;
|
||||
}
|
||||
|
||||
m_vk_exts.resize(count);
|
||||
if (_class == enumeration_class::instance)
|
||||
{
|
||||
vkEnumerateInstanceExtensionProperties(layer_name, &count, m_vk_exts.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
vkEnumerateDeviceExtensionProperties(pdev, layer_name, &count, m_vk_exts.data());
|
||||
}
|
||||
}
|
||||
|
||||
bool is_supported(const char *ext)
|
||||
{
|
||||
return std::any_of(m_vk_exts.cbegin(), m_vk_exts.cend(),
|
||||
[&](const VkExtensionProperties& p) { return std::strcmp(p.extensionName, ext) == 0; });
|
||||
}
|
||||
};
|
||||
|
||||
class physical_device
|
||||
{
|
||||
VkInstance parent = VK_NULL_HANDLE;
|
||||
VkPhysicalDevice dev = VK_NULL_HANDLE;
|
||||
VkPhysicalDeviceProperties props;
|
||||
VkPhysicalDeviceFeatures features;
|
||||
VkPhysicalDeviceMemoryProperties memory_properties;
|
||||
std::vector<VkQueueFamilyProperties> queue_props;
|
||||
|
||||
std::unordered_map<VkFormat, VkFormatProperties> format_properties;
|
||||
gpu_shader_types_support shader_types_support{};
|
||||
VkPhysicalDeviceDriverPropertiesKHR driver_properties{};
|
||||
bool stencil_export_support = false;
|
||||
|
||||
friend class render_device;
|
||||
private:
|
||||
void get_physical_device_features(bool allow_extensions)
|
||||
{
|
||||
if (!allow_extensions)
|
||||
{
|
||||
vkGetPhysicalDeviceFeatures(dev, &features);
|
||||
return;
|
||||
}
|
||||
|
||||
supported_extensions instance_extensions(supported_extensions::instance);
|
||||
supported_extensions device_extensions(supported_extensions::device, nullptr, dev);
|
||||
|
||||
if (!instance_extensions.is_supported("VK_KHR_get_physical_device_properties2"))
|
||||
{
|
||||
vkGetPhysicalDeviceFeatures(dev, &features);
|
||||
}
|
||||
else
|
||||
{
|
||||
VkPhysicalDeviceFeatures2KHR features2;
|
||||
features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
|
||||
features2.pNext = nullptr;
|
||||
|
||||
VkPhysicalDeviceFloat16Int8FeaturesKHR shader_support_info{};
|
||||
|
||||
if (device_extensions.is_supported("VK_KHR_shader_float16_int8"))
|
||||
{
|
||||
shader_support_info.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR;
|
||||
features2.pNext = &shader_support_info;
|
||||
}
|
||||
|
||||
if (device_extensions.is_supported("VK_KHR_driver_properties"))
|
||||
{
|
||||
driver_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR;
|
||||
driver_properties.pNext = features2.pNext;
|
||||
features2.pNext = &driver_properties;
|
||||
}
|
||||
|
||||
auto getPhysicalDeviceFeatures2KHR = (PFN_vkGetPhysicalDeviceFeatures2KHR)vkGetInstanceProcAddr(parent, "vkGetPhysicalDeviceFeatures2KHR");
|
||||
verify("vkGetInstanceProcAddress failed to find entry point!" HERE), getPhysicalDeviceFeatures2KHR;
|
||||
getPhysicalDeviceFeatures2KHR(dev, &features2);
|
||||
|
||||
shader_types_support.allow_float16 = !!shader_support_info.shaderFloat16;
|
||||
shader_types_support.allow_int8 = !!shader_support_info.shaderInt8;
|
||||
features = features2.features;
|
||||
}
|
||||
|
||||
stencil_export_support = device_extensions.is_supported("VK_EXT_shader_stencil_export");
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
physical_device() = default;
|
||||
~physical_device() = default;
|
||||
|
||||
void create(VkInstance context, VkPhysicalDevice pdev)
|
||||
void create(VkInstance context, VkPhysicalDevice pdev, bool allow_extensions)
|
||||
{
|
||||
dev = pdev;
|
||||
parent = context;
|
||||
vkGetPhysicalDeviceProperties(pdev, &props);
|
||||
vkGetPhysicalDeviceMemoryProperties(pdev, &memory_properties);
|
||||
get_physical_device_features(allow_extensions);
|
||||
|
||||
LOG_NOTICE(RSX, "Found vulkan-compatible GPU: '%s' running on driver %s", get_name(), get_driver_version());
|
||||
}
|
||||
|
@ -437,28 +539,50 @@ namespace vk
|
|||
|
||||
driver_vendor get_driver_vendor() const
|
||||
{
|
||||
const auto gpu_name = get_name();
|
||||
if (gpu_name.find("Radeon") != std::string::npos)
|
||||
if (!driver_properties.driverID)
|
||||
{
|
||||
return driver_vendor::AMD;
|
||||
}
|
||||
const auto gpu_name = get_name();
|
||||
if (gpu_name.find("Radeon") != std::string::npos)
|
||||
{
|
||||
return driver_vendor::AMD;
|
||||
}
|
||||
|
||||
if (gpu_name.find("NVIDIA") != std::string::npos || gpu_name.find("GeForce") != std::string::npos)
|
||||
if (gpu_name.find("NVIDIA") != std::string::npos || gpu_name.find("GeForce") != std::string::npos)
|
||||
{
|
||||
return driver_vendor::NVIDIA;
|
||||
}
|
||||
|
||||
if (gpu_name.find("RADV") != std::string::npos)
|
||||
{
|
||||
return driver_vendor::RADV;
|
||||
}
|
||||
|
||||
if (gpu_name.find("Intel") != std::string::npos)
|
||||
{
|
||||
return driver_vendor::INTEL;
|
||||
}
|
||||
|
||||
return driver_vendor::unknown;
|
||||
}
|
||||
else
|
||||
{
|
||||
return driver_vendor::NVIDIA;
|
||||
switch (driver_properties.driverID)
|
||||
{
|
||||
case VK_DRIVER_ID_AMD_PROPRIETARY_KHR:
|
||||
case VK_DRIVER_ID_AMD_OPEN_SOURCE_KHR:
|
||||
return driver_vendor::AMD;
|
||||
case VK_DRIVER_ID_MESA_RADV_KHR:
|
||||
return driver_vendor::RADV;
|
||||
case VK_DRIVER_ID_NVIDIA_PROPRIETARY_KHR:
|
||||
return driver_vendor::NVIDIA;
|
||||
case VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS_KHR:
|
||||
case VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA_KHR:
|
||||
return driver_vendor::INTEL;
|
||||
default:
|
||||
// Mobile
|
||||
return driver_vendor::unknown;
|
||||
}
|
||||
}
|
||||
|
||||
if (gpu_name.find("RADV") != std::string::npos)
|
||||
{
|
||||
return driver_vendor::RADV;
|
||||
}
|
||||
|
||||
if (gpu_name.find("Intel") != std::string::npos)
|
||||
{
|
||||
return driver_vendor::INTEL;
|
||||
}
|
||||
|
||||
return driver_vendor::unknown;
|
||||
}
|
||||
|
||||
std::string get_driver_version() const
|
||||
|
@ -533,97 +657,14 @@ namespace vk
|
|||
}
|
||||
};
|
||||
|
||||
class supported_extensions
|
||||
{
|
||||
private:
|
||||
std::vector<VkExtensionProperties> m_vk_exts;
|
||||
|
||||
public:
|
||||
enum enumeration_class
|
||||
{
|
||||
instance = 0,
|
||||
device = 1
|
||||
};
|
||||
|
||||
supported_extensions(enumeration_class _class, const char* layer_name = nullptr, physical_device* pgpu = nullptr)
|
||||
{
|
||||
uint32_t count;
|
||||
if (_class == enumeration_class::instance)
|
||||
{
|
||||
if (vkEnumerateInstanceExtensionProperties(layer_name, &count, nullptr) != VK_SUCCESS)
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
verify(HERE), pgpu;
|
||||
if (vkEnumerateDeviceExtensionProperties(*pgpu, layer_name, &count, nullptr) != VK_SUCCESS)
|
||||
return;
|
||||
}
|
||||
|
||||
m_vk_exts.resize(count);
|
||||
if (_class == enumeration_class::instance)
|
||||
{
|
||||
vkEnumerateInstanceExtensionProperties(layer_name, &count, m_vk_exts.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
vkEnumerateDeviceExtensionProperties(*pgpu, layer_name, &count, m_vk_exts.data());
|
||||
}
|
||||
}
|
||||
|
||||
bool is_supported(const char *ext)
|
||||
{
|
||||
return std::any_of(m_vk_exts.cbegin(), m_vk_exts.cend(),
|
||||
[&](const VkExtensionProperties& p) { return std::strcmp(p.extensionName, ext) == 0; });
|
||||
}
|
||||
};
|
||||
|
||||
class render_device
|
||||
{
|
||||
physical_device *pgpu = nullptr;
|
||||
memory_type_mapping memory_map{};
|
||||
std::unordered_map<VkFormat, VkFormatProperties> m_format_properties;
|
||||
gpu_formats_support m_formats_support{};
|
||||
gpu_shader_types_support m_shader_types_support{};
|
||||
bool m_stencil_export_support = false;
|
||||
std::unique_ptr<mem_allocator_base> m_allocator;
|
||||
VkDevice dev = VK_NULL_HANDLE;
|
||||
|
||||
void get_physical_device_features(VkPhysicalDeviceFeatures& features)
|
||||
{
|
||||
supported_extensions instance_extensions(supported_extensions::instance);
|
||||
supported_extensions device_extensions(supported_extensions::device, nullptr, pgpu);
|
||||
|
||||
if (!instance_extensions.is_supported("VK_KHR_get_physical_device_properties2"))
|
||||
{
|
||||
vkGetPhysicalDeviceFeatures(*pgpu, &features);
|
||||
}
|
||||
else
|
||||
{
|
||||
VkPhysicalDeviceFeatures2KHR features2;
|
||||
features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
|
||||
features2.pNext = nullptr;
|
||||
|
||||
VkPhysicalDeviceFloat16Int8FeaturesKHR shader_support_info{};
|
||||
|
||||
if (device_extensions.is_supported("VK_KHR_shader_float16_int8"))
|
||||
{
|
||||
shader_support_info.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR;
|
||||
features2.pNext = &shader_support_info;
|
||||
}
|
||||
|
||||
auto getPhysicalDeviceFeatures2KHR = (PFN_vkGetPhysicalDeviceFeatures2KHR)vkGetInstanceProcAddr(*pgpu, "vkGetPhysicalDeviceFeatures2KHR");
|
||||
verify("vkGetInstanceProcAddress failed to find entry point!" HERE), getPhysicalDeviceFeatures2KHR;
|
||||
getPhysicalDeviceFeatures2KHR(*pgpu, &features2);
|
||||
|
||||
m_shader_types_support.allow_float16 = !!shader_support_info.shaderFloat16;
|
||||
m_shader_types_support.allow_int8 = !!shader_support_info.shaderInt8;
|
||||
features = features2.features;
|
||||
}
|
||||
|
||||
m_stencil_export_support = device_extensions.is_supported("VK_EXT_shader_stencil_export");
|
||||
}
|
||||
|
||||
public:
|
||||
render_device() = default;
|
||||
~render_device() = default;
|
||||
|
@ -651,10 +692,8 @@ namespace vk
|
|||
// 1. Anisotropic sampling
|
||||
// 2. DXT support
|
||||
// 3. Indexable storage buffers
|
||||
VkPhysicalDeviceFeatures available_features;
|
||||
get_physical_device_features(available_features);
|
||||
|
||||
if (m_shader_types_support.allow_float16)
|
||||
VkPhysicalDeviceFeatures available_features = pgpu->features;
|
||||
if (pgpu->shader_types_support.allow_float16)
|
||||
{
|
||||
requested_extensions.push_back("VK_KHR_shader_float16_int8");
|
||||
}
|
||||
|
@ -675,7 +714,7 @@ namespace vk
|
|||
device.pEnabledFeatures = &available_features;
|
||||
|
||||
VkPhysicalDeviceFloat16Int8FeaturesKHR shader_support_info{};
|
||||
if (m_shader_types_support.allow_float16)
|
||||
if (pgpu->shader_types_support.allow_float16)
|
||||
{
|
||||
// Allow use of f16 type in shaders if possible
|
||||
shader_support_info.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR;
|
||||
|
@ -719,13 +758,13 @@ namespace vk
|
|||
|
||||
const VkFormatProperties get_format_properties(VkFormat format)
|
||||
{
|
||||
auto found = m_format_properties.find(format);
|
||||
if (found != m_format_properties.end())
|
||||
auto found = pgpu->format_properties.find(format);
|
||||
if (found != pgpu->format_properties.end())
|
||||
{
|
||||
return found->second;
|
||||
}
|
||||
|
||||
auto& props = m_format_properties[format];
|
||||
auto& props = pgpu->format_properties[format];
|
||||
vkGetPhysicalDeviceFormatProperties(*pgpu, format, &props);
|
||||
return props;
|
||||
}
|
||||
|
@ -772,12 +811,12 @@ namespace vk
|
|||
|
||||
const gpu_shader_types_support& get_shader_types_support() const
|
||||
{
|
||||
return m_shader_types_support;
|
||||
return pgpu->shader_types_support;
|
||||
}
|
||||
|
||||
bool get_shader_stencil_export_support() const
|
||||
{
|
||||
return m_stencil_export_support;
|
||||
return pgpu->stencil_export_support;
|
||||
}
|
||||
|
||||
mem_allocator_base* get_allocator() const
|
||||
|
@ -2263,6 +2302,7 @@ public:
|
|||
VkDebugReportCallbackEXT m_debugger = nullptr;
|
||||
|
||||
bool loader_exists = false;
|
||||
bool extensions_loaded = false;
|
||||
|
||||
public:
|
||||
|
||||
|
@ -2337,6 +2377,7 @@ public:
|
|||
|
||||
if (!fast)
|
||||
{
|
||||
extensions_loaded = true;
|
||||
supported_extensions support(supported_extensions::instance);
|
||||
|
||||
extensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
|
||||
|
@ -2440,7 +2481,7 @@ public:
|
|||
CHECK_RESULT(vkEnumeratePhysicalDevices(m_instance, &num_gpus, pdevs.data()));
|
||||
|
||||
for (u32 i = 0; i < num_gpus; ++i)
|
||||
gpus[i].create(m_instance, pdevs[i]);
|
||||
gpus[i].create(m_instance, pdevs[i], extensions_loaded);
|
||||
}
|
||||
|
||||
return gpus;
|
||||
|
|
Loading…
Reference in New Issue