summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2019-12-09 01:04:48 -0300
committerGravatar ReinUsesLisp2019-12-09 01:04:48 -0300
commit19ce0d4f1a149787a48c56ad3d400de1cdb19ad6 (patch)
tree5a4d90d94218035d3c0ddc0e94ca69d6e0c56503
parentMerge pull request #3198 from ReinUsesLisp/tessellation-maxwell (diff)
downloadyuzu-19ce0d4f1a149787a48c56ad3d400de1cdb19ad6.tar.gz
yuzu-19ce0d4f1a149787a48c56ad3d400de1cdb19ad6.tar.xz
yuzu-19ce0d4f1a149787a48c56ad3d400de1cdb19ad6.zip
vk_device: Misc changes
- Setup more features and requirements. - Improve logging for missing features. - Collect telemetry parameters. - Add queries for more image formats. - Query push constants limits. - Optionally enable some extensions.
-rw-r--r--src/video_core/renderer_vulkan/vk_device.cpp299
-rw-r--r--src/video_core/renderer_vulkan/vk_device.h94
2 files changed, 276 insertions, 117 deletions
diff --git a/src/video_core/renderer_vulkan/vk_device.cpp b/src/video_core/renderer_vulkan/vk_device.cpp
index 6e58736a3..92854a4b3 100644
--- a/src/video_core/renderer_vulkan/vk_device.cpp
+++ b/src/video_core/renderer_vulkan/vk_device.cpp
@@ -3,6 +3,7 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <bitset> 5#include <bitset>
6#include <cstdlib>
6#include <optional> 7#include <optional>
7#include <set> 8#include <set>
8#include <string_view> 9#include <string_view>
@@ -15,6 +16,15 @@ namespace Vulkan {
15 16
16namespace { 17namespace {
17 18
19namespace Alternatives {
20
21constexpr std::array Depth24UnormS8Uint = {vk::Format::eD32SfloatS8Uint,
22 vk::Format::eD16UnormS8Uint, vk::Format{}};
23constexpr std::array Depth16UnormS8Uint = {vk::Format::eD24UnormS8Uint,
24 vk::Format::eD32SfloatS8Uint, vk::Format{}};
25
26} // namespace Alternatives
27
18template <typename T> 28template <typename T>
19void SetNext(void**& next, T& data) { 29void SetNext(void**& next, T& data) {
20 *next = &data; 30 *next = &data;
@@ -22,7 +32,7 @@ void SetNext(void**& next, T& data) {
22} 32}
23 33
24template <typename T> 34template <typename T>
25T GetFeatures(vk::PhysicalDevice physical, vk::DispatchLoaderDynamic dldi) { 35T GetFeatures(vk::PhysicalDevice physical, const vk::DispatchLoaderDynamic& dldi) {
26 vk::PhysicalDeviceFeatures2 features; 36 vk::PhysicalDeviceFeatures2 features;
27 T extension_features; 37 T extension_features;
28 features.pNext = &extension_features; 38 features.pNext = &extension_features;
@@ -30,17 +40,14 @@ T GetFeatures(vk::PhysicalDevice physical, vk::DispatchLoaderDynamic dldi) {
30 return extension_features; 40 return extension_features;
31} 41}
32 42
33} // Anonymous namespace 43template <typename T>
34 44T GetProperties(vk::PhysicalDevice physical, const vk::DispatchLoaderDynamic& dldi) {
35namespace Alternatives { 45 vk::PhysicalDeviceProperties2 properties;
36 46 T extension_properties;
37constexpr std::array Depth24UnormS8Uint = {vk::Format::eD32SfloatS8Uint, 47 properties.pNext = &extension_properties;
38 vk::Format::eD16UnormS8Uint, vk::Format{}}; 48 physical.getProperties2(&properties, dldi);
39constexpr std::array Depth16UnormS8Uint = {vk::Format::eD24UnormS8Uint, 49 return extension_properties;
40 vk::Format::eD32SfloatS8Uint, vk::Format{}}; 50}
41constexpr std::array Astc = {vk::Format::eA8B8G8R8UnormPack32, vk::Format{}};
42
43} // namespace Alternatives
44 51
45constexpr const vk::Format* GetFormatAlternatives(vk::Format format) { 52constexpr const vk::Format* GetFormatAlternatives(vk::Format format) {
46 switch (format) { 53 switch (format) {
@@ -66,11 +73,13 @@ vk::FormatFeatureFlags GetFormatFeatures(vk::FormatProperties properties, Format
66 } 73 }
67} 74}
68 75
76} // Anonymous namespace
77
69VKDevice::VKDevice(const vk::DispatchLoaderDynamic& dldi, vk::PhysicalDevice physical, 78VKDevice::VKDevice(const vk::DispatchLoaderDynamic& dldi, vk::PhysicalDevice physical,
70 vk::SurfaceKHR surface) 79 vk::SurfaceKHR surface)
71 : physical{physical}, format_properties{GetFormatProperties(dldi, physical)} { 80 : physical{physical}, properties{physical.getProperties(dldi)},
81 format_properties{GetFormatProperties(dldi, physical)} {
72 SetupFamilies(dldi, surface); 82 SetupFamilies(dldi, surface);
73 SetupProperties(dldi);
74 SetupFeatures(dldi); 83 SetupFeatures(dldi);
75} 84}
76 85
@@ -88,12 +97,22 @@ bool VKDevice::Create(const vk::DispatchLoaderDynamic& dldi, vk::Instance instan
88 features.depthClamp = true; 97 features.depthClamp = true;
89 features.samplerAnisotropy = true; 98 features.samplerAnisotropy = true;
90 features.largePoints = true; 99 features.largePoints = true;
100 features.multiViewport = true;
101 features.depthBiasClamp = true;
102 features.geometryShader = true;
103 features.tessellationShader = true;
104 features.fragmentStoresAndAtomics = true;
105 features.shaderImageGatherExtended = true;
106 features.shaderStorageImageWriteWithoutFormat = true;
91 features.textureCompressionASTC_LDR = is_optimal_astc_supported; 107 features.textureCompressionASTC_LDR = is_optimal_astc_supported;
92 108
93 vk::PhysicalDeviceVertexAttributeDivisorFeaturesEXT vertex_divisor; 109 vk::PhysicalDevice16BitStorageFeaturesKHR bit16_storage;
94 vertex_divisor.vertexAttributeInstanceRateDivisor = true; 110 bit16_storage.uniformAndStorageBuffer16BitAccess = true;
95 vertex_divisor.vertexAttributeInstanceRateZeroDivisor = true; 111 SetNext(next, bit16_storage);
96 SetNext(next, vertex_divisor); 112
113 vk::PhysicalDevice8BitStorageFeaturesKHR bit8_storage;
114 bit8_storage.uniformAndStorageBuffer8BitAccess = true;
115 SetNext(next, bit8_storage);
97 116
98 vk::PhysicalDeviceFloat16Int8FeaturesKHR float16_int8; 117 vk::PhysicalDeviceFloat16Int8FeaturesKHR float16_int8;
99 if (is_float16_supported) { 118 if (is_float16_supported) {
@@ -119,6 +138,10 @@ bool VKDevice::Create(const vk::DispatchLoaderDynamic& dldi, vk::Instance instan
119 LOG_INFO(Render_Vulkan, "Device doesn't support uint8 indexes"); 138 LOG_INFO(Render_Vulkan, "Device doesn't support uint8 indexes");
120 } 139 }
121 140
141 if (!ext_depth_range_unrestricted) {
142 LOG_INFO(Render_Vulkan, "Device doesn't support depth range unrestricted");
143 }
144
122 vk::DeviceCreateInfo device_ci({}, static_cast<u32>(queue_cis.size()), queue_cis.data(), 0, 145 vk::DeviceCreateInfo device_ci({}, static_cast<u32>(queue_cis.size()), queue_cis.data(), 0,
123 nullptr, static_cast<u32>(extensions.size()), extensions.data(), 146 nullptr, static_cast<u32>(extensions.size()), extensions.data(),
124 nullptr); 147 nullptr);
@@ -134,16 +157,7 @@ bool VKDevice::Create(const vk::DispatchLoaderDynamic& dldi, vk::Instance instan
134 logical = UniqueDevice( 157 logical = UniqueDevice(
135 dummy_logical, vk::ObjectDestroy<vk::NoParent, vk::DispatchLoaderDynamic>(nullptr, dld)); 158 dummy_logical, vk::ObjectDestroy<vk::NoParent, vk::DispatchLoaderDynamic>(nullptr, dld));
136 159
137 if (khr_driver_properties) { 160 CollectTelemetryParameters();
138 vk::PhysicalDeviceDriverPropertiesKHR driver;
139 vk::PhysicalDeviceProperties2 properties;
140 properties.pNext = &driver;
141 physical.getProperties2(&properties, dld);
142 driver_id = driver.driverID;
143 LOG_INFO(Render_Vulkan, "Driver: {} {}", driver.driverName, driver.driverInfo);
144 } else {
145 LOG_INFO(Render_Vulkan, "Driver: Unknown");
146 }
147 161
148 graphics_queue = logical->getQueue(graphics_family, 0, dld); 162 graphics_queue = logical->getQueue(graphics_family, 0, dld);
149 present_queue = logical->getQueue(present_family, 0, dld); 163 present_queue = logical->getQueue(present_family, 0, dld);
@@ -189,6 +203,18 @@ vk::Format VKDevice::GetSupportedFormat(vk::Format wanted_format,
189 203
190bool VKDevice::IsOptimalAstcSupported(const vk::PhysicalDeviceFeatures& features, 204bool VKDevice::IsOptimalAstcSupported(const vk::PhysicalDeviceFeatures& features,
191 const vk::DispatchLoaderDynamic& dldi) const { 205 const vk::DispatchLoaderDynamic& dldi) const {
206 // Disable for now to avoid converting ASTC twice.
207 return false;
208 static constexpr std::array astc_formats = {
209 vk::Format::eAstc4x4SrgbBlock, vk::Format::eAstc8x8SrgbBlock,
210 vk::Format::eAstc8x5SrgbBlock, vk::Format::eAstc5x4SrgbBlock,
211 vk::Format::eAstc5x5UnormBlock, vk::Format::eAstc5x5SrgbBlock,
212 vk::Format::eAstc10x8UnormBlock, vk::Format::eAstc10x8SrgbBlock,
213 vk::Format::eAstc6x6UnormBlock, vk::Format::eAstc6x6SrgbBlock,
214 vk::Format::eAstc10x10UnormBlock, vk::Format::eAstc10x10SrgbBlock,
215 vk::Format::eAstc12x12UnormBlock, vk::Format::eAstc12x12SrgbBlock,
216 vk::Format::eAstc8x6UnormBlock, vk::Format::eAstc8x6SrgbBlock,
217 vk::Format::eAstc6x5UnormBlock, vk::Format::eAstc6x5SrgbBlock};
192 if (!features.textureCompressionASTC_LDR) { 218 if (!features.textureCompressionASTC_LDR) {
193 return false; 219 return false;
194 } 220 }
@@ -196,12 +222,6 @@ bool VKDevice::IsOptimalAstcSupported(const vk::PhysicalDeviceFeatures& features
196 vk::FormatFeatureFlagBits::eSampledImage | vk::FormatFeatureFlagBits::eBlitSrc | 222 vk::FormatFeatureFlagBits::eSampledImage | vk::FormatFeatureFlagBits::eBlitSrc |
197 vk::FormatFeatureFlagBits::eBlitDst | vk::FormatFeatureFlagBits::eTransferSrc | 223 vk::FormatFeatureFlagBits::eBlitDst | vk::FormatFeatureFlagBits::eTransferSrc |
198 vk::FormatFeatureFlagBits::eTransferDst}; 224 vk::FormatFeatureFlagBits::eTransferDst};
199 constexpr std::array astc_formats = {
200 vk::Format::eAstc4x4UnormBlock, vk::Format::eAstc4x4SrgbBlock,
201 vk::Format::eAstc8x8SrgbBlock, vk::Format::eAstc8x6SrgbBlock,
202 vk::Format::eAstc5x4SrgbBlock, vk::Format::eAstc5x5UnormBlock,
203 vk::Format::eAstc5x5SrgbBlock, vk::Format::eAstc10x8UnormBlock,
204 vk::Format::eAstc10x8SrgbBlock};
205 for (const auto format : astc_formats) { 225 for (const auto format : astc_formats) {
206 const auto format_properties{physical.getFormatProperties(format, dldi)}; 226 const auto format_properties{physical.getFormatProperties(format, dldi)};
207 if (!(format_properties.optimalTilingFeatures & format_feature_usage)) { 227 if (!(format_properties.optimalTilingFeatures & format_feature_usage)) {
@@ -224,11 +244,17 @@ bool VKDevice::IsFormatSupported(vk::Format wanted_format, vk::FormatFeatureFlag
224 244
225bool VKDevice::IsSuitable(const vk::DispatchLoaderDynamic& dldi, vk::PhysicalDevice physical, 245bool VKDevice::IsSuitable(const vk::DispatchLoaderDynamic& dldi, vk::PhysicalDevice physical,
226 vk::SurfaceKHR surface) { 246 vk::SurfaceKHR surface) {
227 LOG_INFO(Render_Vulkan, "{}", physical.getProperties(dldi).deviceName);
228 bool is_suitable = true; 247 bool is_suitable = true;
229 248
230 constexpr std::array required_extensions = {VK_KHR_SWAPCHAIN_EXTENSION_NAME, 249 constexpr std::array required_extensions = {
231 VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME}; 250 VK_KHR_SWAPCHAIN_EXTENSION_NAME,
251 VK_KHR_16BIT_STORAGE_EXTENSION_NAME,
252 VK_KHR_8BIT_STORAGE_EXTENSION_NAME,
253 VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME,
254 VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME,
255 VK_EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME,
256 VK_EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME,
257 };
232 std::bitset<required_extensions.size()> available_extensions{}; 258 std::bitset<required_extensions.size()> available_extensions{};
233 259
234 for (const auto& prop : physical.enumerateDeviceExtensionProperties(nullptr, dldi)) { 260 for (const auto& prop : physical.enumerateDeviceExtensionProperties(nullptr, dldi)) {
@@ -245,7 +271,7 @@ bool VKDevice::IsSuitable(const vk::DispatchLoaderDynamic& dldi, vk::PhysicalDev
245 if (available_extensions[i]) { 271 if (available_extensions[i]) {
246 continue; 272 continue;
247 } 273 }
248 LOG_INFO(Render_Vulkan, "Missing required extension: {}", required_extensions[i]); 274 LOG_ERROR(Render_Vulkan, "Missing required extension: {}", required_extensions[i]);
249 is_suitable = false; 275 is_suitable = false;
250 } 276 }
251 } 277 }
@@ -262,7 +288,7 @@ bool VKDevice::IsSuitable(const vk::DispatchLoaderDynamic& dldi, vk::PhysicalDev
262 has_present |= physical.getSurfaceSupportKHR(i, surface, dldi) != 0; 288 has_present |= physical.getSurfaceSupportKHR(i, surface, dldi) != 0;
263 } 289 }
264 if (!has_graphics || !has_present) { 290 if (!has_graphics || !has_present) {
265 LOG_INFO(Render_Vulkan, "Device lacks a graphics and present queue"); 291 LOG_ERROR(Render_Vulkan, "Device lacks a graphics and present queue");
266 is_suitable = false; 292 is_suitable = false;
267 } 293 }
268 294
@@ -272,8 +298,15 @@ bool VKDevice::IsSuitable(const vk::DispatchLoaderDynamic& dldi, vk::PhysicalDev
272 298
273 constexpr u32 required_ubo_size = 65536; 299 constexpr u32 required_ubo_size = 65536;
274 if (limits.maxUniformBufferRange < required_ubo_size) { 300 if (limits.maxUniformBufferRange < required_ubo_size) {
275 LOG_INFO(Render_Vulkan, "Device UBO size {} is too small, {} is required)", 301 LOG_ERROR(Render_Vulkan, "Device UBO size {} is too small, {} is required",
276 limits.maxUniformBufferRange, required_ubo_size); 302 limits.maxUniformBufferRange, required_ubo_size);
303 is_suitable = false;
304 }
305
306 constexpr u32 required_num_viewports = 16;
307 if (limits.maxViewports < required_num_viewports) {
308 LOG_INFO(Render_Vulkan, "Device number of viewports {} is too small, {} is required",
309 limits.maxViewports, required_num_viewports);
277 is_suitable = false; 310 is_suitable = false;
278 } 311 }
279 312
@@ -284,24 +317,32 @@ bool VKDevice::IsSuitable(const vk::DispatchLoaderDynamic& dldi, vk::PhysicalDev
284 std::make_pair(features.depthClamp, "depthClamp"), 317 std::make_pair(features.depthClamp, "depthClamp"),
285 std::make_pair(features.samplerAnisotropy, "samplerAnisotropy"), 318 std::make_pair(features.samplerAnisotropy, "samplerAnisotropy"),
286 std::make_pair(features.largePoints, "largePoints"), 319 std::make_pair(features.largePoints, "largePoints"),
320 std::make_pair(features.multiViewport, "multiViewport"),
321 std::make_pair(features.depthBiasClamp, "depthBiasClamp"),
322 std::make_pair(features.geometryShader, "geometryShader"),
323 std::make_pair(features.tessellationShader, "tessellationShader"),
324 std::make_pair(features.fragmentStoresAndAtomics, "fragmentStoresAndAtomics"),
325 std::make_pair(features.shaderImageGatherExtended, "shaderImageGatherExtended"),
326 std::make_pair(features.shaderStorageImageWriteWithoutFormat,
327 "shaderStorageImageWriteWithoutFormat"),
287 }; 328 };
288 for (const auto& [supported, name] : feature_report) { 329 for (const auto& [supported, name] : feature_report) {
289 if (supported) { 330 if (supported) {
290 continue; 331 continue;
291 } 332 }
292 LOG_INFO(Render_Vulkan, "Missing required feature: {}", name); 333 LOG_ERROR(Render_Vulkan, "Missing required feature: {}", name);
293 is_suitable = false; 334 is_suitable = false;
294 } 335 }
295 336
337 if (!is_suitable) {
338 LOG_ERROR(Render_Vulkan, "{} is not suitable", properties.deviceName);
339 }
340
296 return is_suitable; 341 return is_suitable;
297} 342}
298 343
299std::vector<const char*> VKDevice::LoadExtensions(const vk::DispatchLoaderDynamic& dldi) { 344std::vector<const char*> VKDevice::LoadExtensions(const vk::DispatchLoaderDynamic& dldi) {
300 std::vector<const char*> extensions; 345 std::vector<const char*> extensions;
301 extensions.reserve(7);
302 extensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
303 extensions.push_back(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME);
304
305 const auto Test = [&](const vk::ExtensionProperties& extension, 346 const auto Test = [&](const vk::ExtensionProperties& extension,
306 std::optional<std::reference_wrapper<bool>> status, const char* name, 347 std::optional<std::reference_wrapper<bool>> status, const char* name,
307 bool push) { 348 bool push) {
@@ -316,13 +357,30 @@ std::vector<const char*> VKDevice::LoadExtensions(const vk::DispatchLoaderDynami
316 } 357 }
317 }; 358 };
318 359
360 extensions.reserve(13);
361 extensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
362 extensions.push_back(VK_KHR_16BIT_STORAGE_EXTENSION_NAME);
363 extensions.push_back(VK_KHR_8BIT_STORAGE_EXTENSION_NAME);
364 extensions.push_back(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME);
365 extensions.push_back(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME);
366 extensions.push_back(VK_EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME);
367 extensions.push_back(VK_EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME);
368
369 [[maybe_unused]] const bool nsight =
370 std::getenv("NVTX_INJECTION64_PATH") || std::getenv("NSIGHT_LAUNCHED");
319 bool khr_shader_float16_int8{}; 371 bool khr_shader_float16_int8{};
372 bool ext_subgroup_size_control{};
320 for (const auto& extension : physical.enumerateDeviceExtensionProperties(nullptr, dldi)) { 373 for (const auto& extension : physical.enumerateDeviceExtensionProperties(nullptr, dldi)) {
321 Test(extension, khr_uniform_buffer_standard_layout, 374 Test(extension, khr_uniform_buffer_standard_layout,
322 VK_KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_EXTENSION_NAME, true); 375 VK_KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_EXTENSION_NAME, true);
323 Test(extension, ext_index_type_uint8, VK_EXT_INDEX_TYPE_UINT8_EXTENSION_NAME, true);
324 Test(extension, khr_driver_properties, VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME, true);
325 Test(extension, khr_shader_float16_int8, VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME, false); 376 Test(extension, khr_shader_float16_int8, VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME, false);
377 Test(extension, ext_depth_range_unrestricted,
378 VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME, true);
379 Test(extension, ext_index_type_uint8, VK_EXT_INDEX_TYPE_UINT8_EXTENSION_NAME, true);
380 Test(extension, ext_shader_viewport_index_layer,
381 VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME, true);
382 Test(extension, ext_subgroup_size_control, VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME,
383 false);
326 } 384 }
327 385
328 if (khr_shader_float16_int8) { 386 if (khr_shader_float16_int8) {
@@ -331,6 +389,23 @@ std::vector<const char*> VKDevice::LoadExtensions(const vk::DispatchLoaderDynami
331 extensions.push_back(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME); 389 extensions.push_back(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME);
332 } 390 }
333 391
392 if (ext_subgroup_size_control) {
393 const auto features =
394 GetFeatures<vk::PhysicalDeviceSubgroupSizeControlFeaturesEXT>(physical, dldi);
395 const auto properties =
396 GetProperties<vk::PhysicalDeviceSubgroupSizeControlPropertiesEXT>(physical, dldi);
397
398 is_warp_potentially_bigger = properties.maxSubgroupSize > GuestWarpSize;
399
400 if (features.subgroupSizeControl && properties.minSubgroupSize <= GuestWarpSize &&
401 properties.maxSubgroupSize >= GuestWarpSize) {
402 extensions.push_back(VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME);
403 guest_warp_stages = properties.requiredSubgroupSizeStages;
404 }
405 } else {
406 is_warp_potentially_bigger = true;
407 }
408
334 return extensions; 409 return extensions;
335} 410}
336 411
@@ -357,19 +432,23 @@ void VKDevice::SetupFamilies(const vk::DispatchLoaderDynamic& dldi, vk::SurfaceK
357 present_family = *present_family_; 432 present_family = *present_family_;
358} 433}
359 434
360void VKDevice::SetupProperties(const vk::DispatchLoaderDynamic& dldi) {
361 const auto props = physical.getProperties(dldi);
362 device_type = props.deviceType;
363 uniform_buffer_alignment = static_cast<u64>(props.limits.minUniformBufferOffsetAlignment);
364 storage_buffer_alignment = static_cast<u64>(props.limits.minStorageBufferOffsetAlignment);
365 max_storage_buffer_range = static_cast<u64>(props.limits.maxStorageBufferRange);
366}
367
368void VKDevice::SetupFeatures(const vk::DispatchLoaderDynamic& dldi) { 435void VKDevice::SetupFeatures(const vk::DispatchLoaderDynamic& dldi) {
369 const auto supported_features{physical.getFeatures(dldi)}; 436 const auto supported_features{physical.getFeatures(dldi)};
370 is_optimal_astc_supported = IsOptimalAstcSupported(supported_features, dldi); 437 is_optimal_astc_supported = IsOptimalAstcSupported(supported_features, dldi);
371} 438}
372 439
440void VKDevice::CollectTelemetryParameters() {
441 const auto driver = GetProperties<vk::PhysicalDeviceDriverPropertiesKHR>(physical, dld);
442 driver_id = driver.driverID;
443 vendor_name = driver.driverName;
444
445 const auto extensions = physical.enumerateDeviceExtensionProperties(nullptr, dld);
446 reported_extensions.reserve(std::size(extensions));
447 for (const auto& extension : extensions) {
448 reported_extensions.push_back(extension.extensionName);
449 }
450}
451
373std::vector<vk::DeviceQueueCreateInfo> VKDevice::GetDeviceQueueCreateInfos() const { 452std::vector<vk::DeviceQueueCreateInfo> VKDevice::GetDeviceQueueCreateInfos() const {
374 static const float QUEUE_PRIORITY = 1.0f; 453 static const float QUEUE_PRIORITY = 1.0f;
375 454
@@ -384,50 +463,70 @@ std::vector<vk::DeviceQueueCreateInfo> VKDevice::GetDeviceQueueCreateInfos() con
384 463
385std::unordered_map<vk::Format, vk::FormatProperties> VKDevice::GetFormatProperties( 464std::unordered_map<vk::Format, vk::FormatProperties> VKDevice::GetFormatProperties(
386 const vk::DispatchLoaderDynamic& dldi, vk::PhysicalDevice physical) { 465 const vk::DispatchLoaderDynamic& dldi, vk::PhysicalDevice physical) {
387 constexpr std::array formats{vk::Format::eA8B8G8R8UnormPack32, 466 static constexpr std::array formats{vk::Format::eA8B8G8R8UnormPack32,
388 vk::Format::eA8B8G8R8SnormPack32, 467 vk::Format::eA8B8G8R8SnormPack32,
389 vk::Format::eA8B8G8R8SrgbPack32, 468 vk::Format::eA8B8G8R8SrgbPack32,
390 vk::Format::eB5G6R5UnormPack16, 469 vk::Format::eB5G6R5UnormPack16,
391 vk::Format::eA2B10G10R10UnormPack32, 470 vk::Format::eA2B10G10R10UnormPack32,
392 vk::Format::eR32G32B32A32Sfloat, 471 vk::Format::eA1R5G5B5UnormPack16,
393 vk::Format::eR16G16B16A16Uint, 472 vk::Format::eR32G32B32A32Sfloat,
394 vk::Format::eR16G16Unorm, 473 vk::Format::eR32G32B32A32Uint,
395 vk::Format::eR16G16Snorm, 474 vk::Format::eR32G32Sfloat,
396 vk::Format::eR16G16Sfloat, 475 vk::Format::eR32G32Uint,
397 vk::Format::eR16Unorm, 476 vk::Format::eR16G16B16A16Uint,
398 vk::Format::eR8G8B8A8Srgb, 477 vk::Format::eR16G16B16A16Unorm,
399 vk::Format::eR8G8Unorm, 478 vk::Format::eR16G16Unorm,
400 vk::Format::eR8G8Snorm, 479 vk::Format::eR16G16Snorm,
401 vk::Format::eR8Unorm, 480 vk::Format::eR16G16Sfloat,
402 vk::Format::eB10G11R11UfloatPack32, 481 vk::Format::eR16Unorm,
403 vk::Format::eR32Sfloat, 482 vk::Format::eR8G8B8A8Srgb,
404 vk::Format::eR16Sfloat, 483 vk::Format::eR8G8Unorm,
405 vk::Format::eR16G16B16A16Sfloat, 484 vk::Format::eR8G8Snorm,
406 vk::Format::eB8G8R8A8Unorm, 485 vk::Format::eR8Unorm,
407 vk::Format::eD32Sfloat, 486 vk::Format::eR8Uint,
408 vk::Format::eD16Unorm, 487 vk::Format::eB10G11R11UfloatPack32,
409 vk::Format::eD16UnormS8Uint, 488 vk::Format::eR32Sfloat,
410 vk::Format::eD24UnormS8Uint, 489 vk::Format::eR32Uint,
411 vk::Format::eD32SfloatS8Uint, 490 vk::Format::eR16Sfloat,
412 vk::Format::eBc1RgbaUnormBlock, 491 vk::Format::eR16G16B16A16Sfloat,
413 vk::Format::eBc2UnormBlock, 492 vk::Format::eB8G8R8A8Unorm,
414 vk::Format::eBc3UnormBlock, 493 vk::Format::eR4G4B4A4UnormPack16,
415 vk::Format::eBc4UnormBlock, 494 vk::Format::eD32Sfloat,
416 vk::Format::eBc5UnormBlock, 495 vk::Format::eD16Unorm,
417 vk::Format::eBc5SnormBlock, 496 vk::Format::eD16UnormS8Uint,
418 vk::Format::eBc7UnormBlock, 497 vk::Format::eD24UnormS8Uint,
419 vk::Format::eBc1RgbaSrgbBlock, 498 vk::Format::eD32SfloatS8Uint,
420 vk::Format::eBc3SrgbBlock, 499 vk::Format::eBc1RgbaUnormBlock,
421 vk::Format::eBc7SrgbBlock, 500 vk::Format::eBc2UnormBlock,
422 vk::Format::eAstc4x4UnormBlock, 501 vk::Format::eBc3UnormBlock,
423 vk::Format::eAstc4x4SrgbBlock, 502 vk::Format::eBc4UnormBlock,
424 vk::Format::eAstc8x8SrgbBlock, 503 vk::Format::eBc5UnormBlock,
425 vk::Format::eAstc8x6SrgbBlock, 504 vk::Format::eBc5SnormBlock,
426 vk::Format::eAstc5x4SrgbBlock, 505 vk::Format::eBc7UnormBlock,
427 vk::Format::eAstc5x5UnormBlock, 506 vk::Format::eBc6HUfloatBlock,
428 vk::Format::eAstc5x5SrgbBlock, 507 vk::Format::eBc6HSfloatBlock,
429 vk::Format::eAstc10x8UnormBlock, 508 vk::Format::eBc1RgbaSrgbBlock,
430 vk::Format::eAstc10x8SrgbBlock}; 509 vk::Format::eBc3SrgbBlock,
510 vk::Format::eBc7SrgbBlock,
511 vk::Format::eAstc4x4SrgbBlock,
512 vk::Format::eAstc8x8SrgbBlock,
513 vk::Format::eAstc8x5SrgbBlock,
514 vk::Format::eAstc5x4SrgbBlock,
515 vk::Format::eAstc5x5UnormBlock,
516 vk::Format::eAstc5x5SrgbBlock,
517 vk::Format::eAstc10x8UnormBlock,
518 vk::Format::eAstc10x8SrgbBlock,
519 vk::Format::eAstc6x6UnormBlock,
520 vk::Format::eAstc6x6SrgbBlock,
521 vk::Format::eAstc10x10UnormBlock,
522 vk::Format::eAstc10x10SrgbBlock,
523 vk::Format::eAstc12x12UnormBlock,
524 vk::Format::eAstc12x12SrgbBlock,
525 vk::Format::eAstc8x6UnormBlock,
526 vk::Format::eAstc8x6SrgbBlock,
527 vk::Format::eAstc6x5UnormBlock,
528 vk::Format::eAstc6x5SrgbBlock,
529 vk::Format::eE5B9G9R9UfloatPack32};
431 std::unordered_map<vk::Format, vk::FormatProperties> format_properties; 530 std::unordered_map<vk::Format, vk::FormatProperties> format_properties;
432 for (const auto format : formats) { 531 for (const auto format : formats) {
433 format_properties.emplace(format, physical.getFormatProperties(format, dldi)); 532 format_properties.emplace(format, physical.getFormatProperties(format, dldi));
diff --git a/src/video_core/renderer_vulkan/vk_device.h b/src/video_core/renderer_vulkan/vk_device.h
index 010d4c3d6..a844c52df 100644
--- a/src/video_core/renderer_vulkan/vk_device.h
+++ b/src/video_core/renderer_vulkan/vk_device.h
@@ -4,6 +4,8 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <string>
8#include <string_view>
7#include <unordered_map> 9#include <unordered_map>
8#include <vector> 10#include <vector>
9#include "common/common_types.h" 11#include "common/common_types.h"
@@ -14,6 +16,9 @@ namespace Vulkan {
14/// Format usage descriptor. 16/// Format usage descriptor.
15enum class FormatType { Linear, Optimal, Buffer }; 17enum class FormatType { Linear, Optimal, Buffer };
16 18
19/// Subgroup size of the guest emulated hardware (Nvidia has 32 threads per subgroup).
20const u32 GuestWarpSize = 32;
21
17/// Handles data specific to a physical device. 22/// Handles data specific to a physical device.
18class VKDevice final { 23class VKDevice final {
19public: 24public:
@@ -71,7 +76,22 @@ public:
71 76
72 /// Returns true if the device is integrated with the host CPU. 77 /// Returns true if the device is integrated with the host CPU.
73 bool IsIntegrated() const { 78 bool IsIntegrated() const {
74 return device_type == vk::PhysicalDeviceType::eIntegratedGpu; 79 return properties.deviceType == vk::PhysicalDeviceType::eIntegratedGpu;
80 }
81
82 /// Returns the current Vulkan API version provided in Vulkan-formatted version numbers.
83 u32 GetApiVersion() const {
84 return properties.apiVersion;
85 }
86
87 /// Returns the current driver version provided in Vulkan-formatted version numbers.
88 u32 GetDriverVersion() const {
89 return properties.driverVersion;
90 }
91
92 /// Returns the device name.
93 std::string_view GetModelName() const {
94 return properties.deviceName;
75 } 95 }
76 96
77 /// Returns the driver ID. 97 /// Returns the driver ID.
@@ -80,18 +100,23 @@ public:
80 } 100 }
81 101
82 /// Returns uniform buffer alignment requeriment. 102 /// Returns uniform buffer alignment requeriment.
83 u64 GetUniformBufferAlignment() const { 103 vk::DeviceSize GetUniformBufferAlignment() const {
84 return uniform_buffer_alignment; 104 return properties.limits.minUniformBufferOffsetAlignment;
85 } 105 }
86 106
87 /// Returns storage alignment requeriment. 107 /// Returns storage alignment requeriment.
88 u64 GetStorageBufferAlignment() const { 108 vk::DeviceSize GetStorageBufferAlignment() const {
89 return storage_buffer_alignment; 109 return properties.limits.minStorageBufferOffsetAlignment;
90 } 110 }
91 111
92 /// Returns the maximum range for storage buffers. 112 /// Returns the maximum range for storage buffers.
93 u64 GetMaxStorageBufferRange() const { 113 vk::DeviceSize GetMaxStorageBufferRange() const {
94 return max_storage_buffer_range; 114 return properties.limits.maxStorageBufferRange;
115 }
116
117 /// Returns the maximum size for push constants.
118 vk::DeviceSize GetMaxPushConstantsSize() const {
119 return properties.limits.maxPushConstantsSize;
95 } 120 }
96 121
97 /// Returns true if ASTC is natively supported. 122 /// Returns true if ASTC is natively supported.
@@ -104,6 +129,16 @@ public:
104 return is_float16_supported; 129 return is_float16_supported;
105 } 130 }
106 131
132 /// Returns true if the device warp size can potentially be bigger than guest's warp size.
133 bool IsWarpSizePotentiallyBiggerThanGuest() const {
134 return is_warp_potentially_bigger;
135 }
136
137 /// Returns true if the device can be forced to use the guest warp size.
138 bool IsGuestWarpSizeSupported(vk::ShaderStageFlagBits stage) const {
139 return (guest_warp_stages & stage) != vk::ShaderStageFlags{};
140 }
141
107 /// Returns true if the device supports VK_EXT_scalar_block_layout. 142 /// Returns true if the device supports VK_EXT_scalar_block_layout.
108 bool IsKhrUniformBufferStandardLayoutSupported() const { 143 bool IsKhrUniformBufferStandardLayoutSupported() const {
109 return khr_uniform_buffer_standard_layout; 144 return khr_uniform_buffer_standard_layout;
@@ -114,6 +149,26 @@ public:
114 return ext_index_type_uint8; 149 return ext_index_type_uint8;
115 } 150 }
116 151
152 /// Returns true if the device supports VK_EXT_depth_range_unrestricted.
153 bool IsExtDepthRangeUnrestrictedSupported() const {
154 return ext_depth_range_unrestricted;
155 }
156
157 /// Returns true if the device supports VK_EXT_shader_viewport_index_layer.
158 bool IsExtShaderViewportIndexLayerSupported() const {
159 return ext_shader_viewport_index_layer;
160 }
161
162 /// Returns the vendor name reported from Vulkan.
163 std::string_view GetVendorName() const {
164 return vendor_name;
165 }
166
167 /// Returns the list of available extensions.
168 const std::vector<std::string>& GetAvailableExtensions() const {
169 return reported_extensions;
170 }
171
117 /// Checks if the physical device is suitable. 172 /// Checks if the physical device is suitable.
118 static bool IsSuitable(const vk::DispatchLoaderDynamic& dldi, vk::PhysicalDevice physical, 173 static bool IsSuitable(const vk::DispatchLoaderDynamic& dldi, vk::PhysicalDevice physical,
119 vk::SurfaceKHR surface); 174 vk::SurfaceKHR surface);
@@ -125,12 +180,12 @@ private:
125 /// Sets up queue families. 180 /// Sets up queue families.
126 void SetupFamilies(const vk::DispatchLoaderDynamic& dldi, vk::SurfaceKHR surface); 181 void SetupFamilies(const vk::DispatchLoaderDynamic& dldi, vk::SurfaceKHR surface);
127 182
128 /// Sets up device properties.
129 void SetupProperties(const vk::DispatchLoaderDynamic& dldi);
130
131 /// Sets up device features. 183 /// Sets up device features.
132 void SetupFeatures(const vk::DispatchLoaderDynamic& dldi); 184 void SetupFeatures(const vk::DispatchLoaderDynamic& dldi);
133 185
186 /// Collects telemetry information from the device.
187 void CollectTelemetryParameters();
188
134 /// Returns a list of queue initialization descriptors. 189 /// Returns a list of queue initialization descriptors.
135 std::vector<vk::DeviceQueueCreateInfo> GetDeviceQueueCreateInfos() const; 190 std::vector<vk::DeviceQueueCreateInfo> GetDeviceQueueCreateInfos() const;
136 191
@@ -148,23 +203,28 @@ private:
148 203
149 const vk::PhysicalDevice physical; ///< Physical device. 204 const vk::PhysicalDevice physical; ///< Physical device.
150 vk::DispatchLoaderDynamic dld; ///< Device function pointers. 205 vk::DispatchLoaderDynamic dld; ///< Device function pointers.
206 vk::PhysicalDeviceProperties properties; ///< Device properties.
151 UniqueDevice logical; ///< Logical device. 207 UniqueDevice logical; ///< Logical device.
152 vk::Queue graphics_queue; ///< Main graphics queue. 208 vk::Queue graphics_queue; ///< Main graphics queue.
153 vk::Queue present_queue; ///< Main present queue. 209 vk::Queue present_queue; ///< Main present queue.
154 u32 graphics_family{}; ///< Main graphics queue family index. 210 u32 graphics_family{}; ///< Main graphics queue family index.
155 u32 present_family{}; ///< Main present queue family index. 211 u32 present_family{}; ///< Main present queue family index.
156 vk::PhysicalDeviceType device_type; ///< Physical device type.
157 vk::DriverIdKHR driver_id{}; ///< Driver ID. 212 vk::DriverIdKHR driver_id{}; ///< Driver ID.
158 u64 uniform_buffer_alignment{}; ///< Uniform buffer alignment requeriment. 213 vk::ShaderStageFlags guest_warp_stages{}; ///< Stages where the guest warp size can be forced.
159 u64 storage_buffer_alignment{}; ///< Storage buffer alignment requeriment.
160 u64 max_storage_buffer_range{}; ///< Max storage buffer size.
161 bool is_optimal_astc_supported{}; ///< Support for native ASTC. 214 bool is_optimal_astc_supported{}; ///< Support for native ASTC.
162 bool is_float16_supported{}; ///< Support for float16 arithmetics. 215 bool is_float16_supported{}; ///< Support for float16 arithmetics.
216 bool is_warp_potentially_bigger{}; ///< Host warp size can be bigger than guest.
163 bool khr_uniform_buffer_standard_layout{}; ///< Support for std430 on UBOs. 217 bool khr_uniform_buffer_standard_layout{}; ///< Support for std430 on UBOs.
164 bool ext_index_type_uint8{}; ///< Support for VK_EXT_index_type_uint8. 218 bool ext_index_type_uint8{}; ///< Support for VK_EXT_index_type_uint8.
165 bool khr_driver_properties{}; ///< Support for VK_KHR_driver_properties. 219 bool ext_depth_range_unrestricted{}; ///< Support for VK_EXT_depth_range_unrestricted.
166 std::unordered_map<vk::Format, vk::FormatProperties> 220 bool ext_shader_viewport_index_layer{}; ///< Support for VK_EXT_shader_viewport_index_layer.
167 format_properties; ///< Format properties dictionary. 221
222 // Telemetry parameters
223 std::string vendor_name; ///< Device's driver name.
224 std::vector<std::string> reported_extensions; ///< Reported Vulkan extensions.
225
226 /// Format properties dictionary.
227 std::unordered_map<vk::Format, vk::FormatProperties> format_properties;
168}; 228};
169 229
170} // namespace Vulkan 230} // namespace Vulkan