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;
|
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
|
class physical_device
|
||||||
{
|
{
|
||||||
VkInstance parent = VK_NULL_HANDLE;
|
VkInstance parent = VK_NULL_HANDLE;
|
||||||
VkPhysicalDevice dev = VK_NULL_HANDLE;
|
VkPhysicalDevice dev = VK_NULL_HANDLE;
|
||||||
VkPhysicalDeviceProperties props;
|
VkPhysicalDeviceProperties props;
|
||||||
|
VkPhysicalDeviceFeatures features;
|
||||||
VkPhysicalDeviceMemoryProperties memory_properties;
|
VkPhysicalDeviceMemoryProperties memory_properties;
|
||||||
std::vector<VkQueueFamilyProperties> queue_props;
|
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:
|
public:
|
||||||
|
|
||||||
physical_device() = default;
|
physical_device() = default;
|
||||||
~physical_device() = default;
|
~physical_device() = default;
|
||||||
|
|
||||||
void create(VkInstance context, VkPhysicalDevice pdev)
|
void create(VkInstance context, VkPhysicalDevice pdev, bool allow_extensions)
|
||||||
{
|
{
|
||||||
dev = pdev;
|
dev = pdev;
|
||||||
parent = context;
|
parent = context;
|
||||||
vkGetPhysicalDeviceProperties(pdev, &props);
|
vkGetPhysicalDeviceProperties(pdev, &props);
|
||||||
vkGetPhysicalDeviceMemoryProperties(pdev, &memory_properties);
|
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());
|
LOG_NOTICE(RSX, "Found vulkan-compatible GPU: '%s' running on driver %s", get_name(), get_driver_version());
|
||||||
}
|
}
|
||||||
|
@ -436,6 +538,8 @@ namespace vk
|
||||||
}
|
}
|
||||||
|
|
||||||
driver_vendor get_driver_vendor() const
|
driver_vendor get_driver_vendor() const
|
||||||
|
{
|
||||||
|
if (!driver_properties.driverID)
|
||||||
{
|
{
|
||||||
const auto gpu_name = get_name();
|
const auto gpu_name = get_name();
|
||||||
if (gpu_name.find("Radeon") != std::string::npos)
|
if (gpu_name.find("Radeon") != std::string::npos)
|
||||||
|
@ -460,6 +564,26 @@ namespace vk
|
||||||
|
|
||||||
return driver_vendor::unknown;
|
return driver_vendor::unknown;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string get_driver_version() const
|
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
|
class render_device
|
||||||
{
|
{
|
||||||
physical_device *pgpu = nullptr;
|
physical_device *pgpu = nullptr;
|
||||||
memory_type_mapping memory_map{};
|
memory_type_mapping memory_map{};
|
||||||
std::unordered_map<VkFormat, VkFormatProperties> m_format_properties;
|
|
||||||
gpu_formats_support m_formats_support{};
|
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;
|
std::unique_ptr<mem_allocator_base> m_allocator;
|
||||||
VkDevice dev = VK_NULL_HANDLE;
|
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:
|
public:
|
||||||
render_device() = default;
|
render_device() = default;
|
||||||
~render_device() = default;
|
~render_device() = default;
|
||||||
|
@ -651,10 +692,8 @@ namespace vk
|
||||||
// 1. Anisotropic sampling
|
// 1. Anisotropic sampling
|
||||||
// 2. DXT support
|
// 2. DXT support
|
||||||
// 3. Indexable storage buffers
|
// 3. Indexable storage buffers
|
||||||
VkPhysicalDeviceFeatures available_features;
|
VkPhysicalDeviceFeatures available_features = pgpu->features;
|
||||||
get_physical_device_features(available_features);
|
if (pgpu->shader_types_support.allow_float16)
|
||||||
|
|
||||||
if (m_shader_types_support.allow_float16)
|
|
||||||
{
|
{
|
||||||
requested_extensions.push_back("VK_KHR_shader_float16_int8");
|
requested_extensions.push_back("VK_KHR_shader_float16_int8");
|
||||||
}
|
}
|
||||||
|
@ -675,7 +714,7 @@ namespace vk
|
||||||
device.pEnabledFeatures = &available_features;
|
device.pEnabledFeatures = &available_features;
|
||||||
|
|
||||||
VkPhysicalDeviceFloat16Int8FeaturesKHR shader_support_info{};
|
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
|
// Allow use of f16 type in shaders if possible
|
||||||
shader_support_info.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR;
|
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)
|
const VkFormatProperties get_format_properties(VkFormat format)
|
||||||
{
|
{
|
||||||
auto found = m_format_properties.find(format);
|
auto found = pgpu->format_properties.find(format);
|
||||||
if (found != m_format_properties.end())
|
if (found != pgpu->format_properties.end())
|
||||||
{
|
{
|
||||||
return found->second;
|
return found->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& props = m_format_properties[format];
|
auto& props = pgpu->format_properties[format];
|
||||||
vkGetPhysicalDeviceFormatProperties(*pgpu, format, &props);
|
vkGetPhysicalDeviceFormatProperties(*pgpu, format, &props);
|
||||||
return props;
|
return props;
|
||||||
}
|
}
|
||||||
|
@ -772,12 +811,12 @@ namespace vk
|
||||||
|
|
||||||
const gpu_shader_types_support& get_shader_types_support() const
|
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
|
bool get_shader_stencil_export_support() const
|
||||||
{
|
{
|
||||||
return m_stencil_export_support;
|
return pgpu->stencil_export_support;
|
||||||
}
|
}
|
||||||
|
|
||||||
mem_allocator_base* get_allocator() const
|
mem_allocator_base* get_allocator() const
|
||||||
|
@ -2263,6 +2302,7 @@ public:
|
||||||
VkDebugReportCallbackEXT m_debugger = nullptr;
|
VkDebugReportCallbackEXT m_debugger = nullptr;
|
||||||
|
|
||||||
bool loader_exists = false;
|
bool loader_exists = false;
|
||||||
|
bool extensions_loaded = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -2337,6 +2377,7 @@ public:
|
||||||
|
|
||||||
if (!fast)
|
if (!fast)
|
||||||
{
|
{
|
||||||
|
extensions_loaded = true;
|
||||||
supported_extensions support(supported_extensions::instance);
|
supported_extensions support(supported_extensions::instance);
|
||||||
|
|
||||||
extensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
|
extensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
|
||||||
|
@ -2440,7 +2481,7 @@ public:
|
||||||
CHECK_RESULT(vkEnumeratePhysicalDevices(m_instance, &num_gpus, pdevs.data()));
|
CHECK_RESULT(vkEnumeratePhysicalDevices(m_instance, &num_gpus, pdevs.data()));
|
||||||
|
|
||||||
for (u32 i = 0; i < num_gpus; ++i)
|
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;
|
return gpus;
|
||||||
|
|
Loading…
Reference in New Issue