1 #include <cstring>
2 #include "../../AppConfig.h"
3 #include "GSH_VulkanDeviceInfo.h"
4 #include "GSH_Vulkan.h"
5 #include "string_format.h"
6
7 using namespace GSH_Vulkan;
8
CDeviceInfo()9 CDeviceInfo::CDeviceInfo()
10 {
11 CAppConfig::GetInstance().RegisterPreferenceInteger(PREF_CGSH_VULKAN_DEVICEID, 0);
12 CAppConfig::GetInstance().RegisterPreferenceInteger(PREF_CGSH_VULKAN_VENDORID, 0);
13
14 PopulateDevices();
15
16 m_selectedDevice.deviceId = CAppConfig::GetInstance().GetPreferenceInteger(PREF_CGSH_VULKAN_DEVICEID);
17 m_selectedDevice.vendorId = CAppConfig::GetInstance().GetPreferenceInteger(PREF_CGSH_VULKAN_VENDORID);
18
19 bool needsReset = (m_selectedDevice.deviceId == 0 || m_selectedDevice.vendorId == 0);
20 needsReset |= !HasDevice(m_selectedDevice);
21
22 if(needsReset && HasAvailableDevices())
23 {
24 SetSelectedDevice(m_devices[0]);
25 }
26 }
27
PopulateDevices()28 void CDeviceInfo::PopulateDevices()
29 {
30 assert(m_log.empty());
31
32 try
33 {
34 auto result = VK_SUCCESS;
35
36 //Create instance without validation layers to be as minimalist as possible
37 auto instance = CGSH_Vulkan::CreateInstance(false);
38
39 uint32_t physicalDeviceCount = 0;
40 result = instance.vkEnumeratePhysicalDevices(instance, &physicalDeviceCount, nullptr);
41 CHECKVULKANERROR(result);
42
43 std::vector<VkPhysicalDevice> physicalDevices(physicalDeviceCount);
44 result = instance.vkEnumeratePhysicalDevices(instance, &physicalDeviceCount, physicalDevices.data());
45 CHECKVULKANERROR(result);
46
47 for(const auto& physicalDevice : physicalDevices)
48 {
49 VkPhysicalDeviceProperties physicalDeviceProperties = {};
50 instance.vkGetPhysicalDeviceProperties(physicalDevice, &physicalDeviceProperties);
51
52 m_log += "------------------------------------------\r\n";
53 m_log += "Physical Device Info:\r\n";
54 m_log += string_format("Driver Version: %d\r\n", physicalDeviceProperties.driverVersion);
55 m_log += string_format("Vendor ID: %d\r\n", physicalDeviceProperties.vendorID);
56 m_log += string_format("Device ID: %d\r\n", physicalDeviceProperties.deviceID);
57 m_log += string_format("Device Name: %s\r\n", physicalDeviceProperties.deviceName);
58 m_log += string_format("Device Type: %d\r\n", physicalDeviceProperties.deviceType);
59 m_log += string_format("API Version: %d.%d.%d\r\n",
60 VK_VERSION_MAJOR(physicalDeviceProperties.apiVersion),
61 VK_VERSION_MINOR(physicalDeviceProperties.apiVersion),
62 VK_VERSION_PATCH(physicalDeviceProperties.apiVersion));
63
64 uint32_t propertyCount = 0;
65 result = instance.vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &propertyCount, nullptr);
66 CHECKVULKANERROR(result);
67
68 std::vector<VkExtensionProperties> properties(propertyCount);
69 result = instance.vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &propertyCount, properties.data());
70 CHECKVULKANERROR(result);
71
72 auto propertyIterator = std::find_if(properties.begin(), properties.end(), [](const auto& property) { return (strcmp(property.extensionName, VK_EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME) == 0); });
73 if(propertyIterator == std::end(properties))
74 {
75 m_log += "Device not suitable: Doesn't support " VK_EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME ".";
76 }
77 else
78 {
79 m_devices.push_back({physicalDeviceProperties.deviceName, physicalDeviceProperties.vendorID, physicalDeviceProperties.deviceID});
80 }
81
82 m_log += "\r\n\r\n";
83 }
84 }
85 catch(const std::exception& exception)
86 {
87 m_log += string_format("Got exception while scanning devices: %s.\r\n", exception.what());
88 }
89 }
90
HasDevice(const VULKAN_DEVICE & deviceToTest) const91 bool CDeviceInfo::HasDevice(const VULKAN_DEVICE& deviceToTest) const
92 {
93 for(const auto& device : m_devices)
94 {
95 if(
96 (device.deviceId == deviceToTest.deviceId) &&
97 (device.vendorId == deviceToTest.vendorId))
98 {
99 return true;
100 }
101 }
102 return false;
103 }
104
GetAvailableDevices() const105 DeviceList CDeviceInfo::GetAvailableDevices() const
106 {
107 return m_devices;
108 }
109
GetSelectedDevice() const110 VULKAN_DEVICE CDeviceInfo::GetSelectedDevice() const
111 {
112 assert(HasDevice(m_selectedDevice));
113 return m_selectedDevice;
114 }
115
SetSelectedDevice(const VULKAN_DEVICE & device)116 void CDeviceInfo::SetSelectedDevice(const VULKAN_DEVICE& device)
117 {
118 m_selectedDevice = device;
119 CAppConfig::GetInstance().SetPreferenceInteger(PREF_CGSH_VULKAN_DEVICEID, m_selectedDevice.deviceId);
120 CAppConfig::GetInstance().SetPreferenceInteger(PREF_CGSH_VULKAN_VENDORID, m_selectedDevice.vendorId);
121 }
122
HasAvailableDevices() const123 bool CDeviceInfo::HasAvailableDevices() const
124 {
125 return !m_devices.empty();
126 }
127
GetLog() const128 std::string CDeviceInfo::GetLog() const
129 {
130 return m_log;
131 }
132