summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2019-09-13 01:55:28 -0300
committerGravatar ReinUsesLisp2019-09-13 02:10:07 -0300
commit01d96e113699b61ba65e6cb8a444dbec4826476e (patch)
tree3c98b0adf6b4bf12347b6d4d4b116dc217c58026 /src
parentexternals: Update Vulkan headers (diff)
downloadyuzu-01d96e113699b61ba65e6cb8a444dbec4826476e.tar.gz
yuzu-01d96e113699b61ba65e6cb8a444dbec4826476e.tar.xz
yuzu-01d96e113699b61ba65e6cb8a444dbec4826476e.zip
vk_device: Add miscellaneous features and minor style changes
* Increase minimum Vulkan requirements * Require VK_EXT_vertex_attribute_divisor * Require depthClamp, samplerAnisotropy and largePoints features * Search and expose VK_KHR_uniform_buffer_standard_layout * Search and expose VK_EXT_index_type_uint8 * Search and expose native float16 arithmetics * Track current driver with VK_KHR_driver_properties * Query and expose SSBO alignment * Query more image formats * Improve logging overall * Minor style changes * Minor rephrasing of commentaries
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_vulkan/vk_device.cpp301
-rw-r--r--src/video_core/renderer_vulkan/vk_device.h62
-rw-r--r--src/video_core/renderer_vulkan/vk_shader_decompiler.cpp6
3 files changed, 258 insertions, 111 deletions
diff --git a/src/video_core/renderer_vulkan/vk_device.cpp b/src/video_core/renderer_vulkan/vk_device.cpp
index 3b966ddc3..897cbb4e8 100644
--- a/src/video_core/renderer_vulkan/vk_device.cpp
+++ b/src/video_core/renderer_vulkan/vk_device.cpp
@@ -2,9 +2,10 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <map> 5#include <bitset>
6#include <optional> 6#include <optional>
7#include <set> 7#include <set>
8#include <string_view>
8#include <vector> 9#include <vector>
9#include "common/assert.h" 10#include "common/assert.h"
10#include "video_core/renderer_vulkan/declarations.h" 11#include "video_core/renderer_vulkan/declarations.h"
@@ -12,13 +13,32 @@
12 13
13namespace Vulkan { 14namespace Vulkan {
14 15
16namespace {
17
18template <typename T>
19void SetNext(void**& next, T& data) {
20 *next = &data;
21 next = &data.pNext;
22}
23
24template <typename T>
25T GetFeatures(vk::PhysicalDevice physical, vk::DispatchLoaderDynamic dldi) {
26 vk::PhysicalDeviceFeatures2 features;
27 T extension_features;
28 features.pNext = &extension_features;
29 physical.getFeatures2(&features, dldi);
30 return extension_features;
31}
32
33} // Anonymous namespace
34
15namespace Alternatives { 35namespace Alternatives {
16 36
17constexpr std::array<vk::Format, 3> Depth24UnormS8Uint = { 37constexpr std::array Depth24UnormS8Uint = {vk::Format::eD32SfloatS8Uint,
18 vk::Format::eD32SfloatS8Uint, vk::Format::eD16UnormS8Uint, {}}; 38 vk::Format::eD16UnormS8Uint, vk::Format{}};
19constexpr std::array<vk::Format, 3> Depth16UnormS8Uint = { 39constexpr std::array Depth16UnormS8Uint = {vk::Format::eD24UnormS8Uint,
20 vk::Format::eD24UnormS8Uint, vk::Format::eD32SfloatS8Uint, {}}; 40 vk::Format::eD32SfloatS8Uint, vk::Format{}};
21constexpr std::array<vk::Format, 2> Astc = {vk::Format::eA8B8G8R8UnormPack32, {}}; 41constexpr std::array Astc = {vk::Format::eA8B8G8R8UnormPack32, vk::Format{}};
22 42
23} // namespace Alternatives 43} // namespace Alternatives
24 44
@@ -58,16 +78,53 @@ VKDevice::VKDevice(const vk::DispatchLoaderDynamic& dldi, vk::PhysicalDevice phy
58VKDevice::~VKDevice() = default; 78VKDevice::~VKDevice() = default;
59 79
60bool VKDevice::Create(const vk::DispatchLoaderDynamic& dldi, vk::Instance instance) { 80bool VKDevice::Create(const vk::DispatchLoaderDynamic& dldi, vk::Instance instance) {
61 vk::PhysicalDeviceFeatures device_features;
62 device_features.vertexPipelineStoresAndAtomics = true;
63 device_features.independentBlend = true;
64 device_features.textureCompressionASTC_LDR = is_optimal_astc_supported;
65
66 const auto queue_cis = GetDeviceQueueCreateInfos(); 81 const auto queue_cis = GetDeviceQueueCreateInfos();
67 const std::vector<const char*> extensions = LoadExtensions(dldi); 82 const std::vector extensions = LoadExtensions(dldi);
68 const vk::DeviceCreateInfo device_ci({}, static_cast<u32>(queue_cis.size()), queue_cis.data(), 83
69 0, nullptr, static_cast<u32>(extensions.size()), 84 vk::PhysicalDeviceFeatures2 features2;
70 extensions.data(), &device_features); 85 void** next = &features2.pNext;
86 auto& features = features2.features;
87 features.vertexPipelineStoresAndAtomics = true;
88 features.independentBlend = true;
89 features.depthClamp = true;
90 features.samplerAnisotropy = true;
91 features.largePoints = true;
92 features.textureCompressionASTC_LDR = is_optimal_astc_supported;
93
94 vk::PhysicalDeviceVertexAttributeDivisorFeaturesEXT vertex_divisor;
95 vertex_divisor.vertexAttributeInstanceRateDivisor = true;
96 vertex_divisor.vertexAttributeInstanceRateZeroDivisor = true;
97 SetNext(next, vertex_divisor);
98
99 vk::PhysicalDeviceFloat16Int8FeaturesKHR float16_int8;
100 if (is_float16_supported) {
101 float16_int8.shaderFloat16 = true;
102 SetNext(next, float16_int8);
103 } else {
104 LOG_INFO(Render_Vulkan, "Device doesn't support float16 natively");
105 }
106
107 vk::PhysicalDeviceUniformBufferStandardLayoutFeaturesKHR std430_layout;
108 if (khr_uniform_buffer_standard_layout) {
109 std430_layout.uniformBufferStandardLayout = true;
110 SetNext(next, std430_layout);
111 } else {
112 LOG_INFO(Render_Vulkan, "Device doesn't support packed UBOs");
113 }
114
115 vk::PhysicalDeviceIndexTypeUint8FeaturesEXT index_type_uint8;
116 if (ext_index_type_uint8) {
117 index_type_uint8.indexTypeUint8 = true;
118 SetNext(next, index_type_uint8);
119 } else {
120 LOG_INFO(Render_Vulkan, "Device doesn't support uint8 indexes");
121 }
122
123 vk::DeviceCreateInfo device_ci({}, static_cast<u32>(queue_cis.size()), queue_cis.data(), 0,
124 nullptr, static_cast<u32>(extensions.size()), extensions.data(),
125 nullptr);
126 device_ci.pNext = &features2;
127
71 vk::Device dummy_logical; 128 vk::Device dummy_logical;
72 if (physical.createDevice(&device_ci, nullptr, &dummy_logical, dldi) != vk::Result::eSuccess) { 129 if (physical.createDevice(&device_ci, nullptr, &dummy_logical, dldi) != vk::Result::eSuccess) {
73 LOG_CRITICAL(Render_Vulkan, "Logical device failed to be created!"); 130 LOG_CRITICAL(Render_Vulkan, "Logical device failed to be created!");
@@ -78,6 +135,17 @@ bool VKDevice::Create(const vk::DispatchLoaderDynamic& dldi, vk::Instance instan
78 logical = UniqueDevice( 135 logical = UniqueDevice(
79 dummy_logical, vk::ObjectDestroy<vk::NoParent, vk::DispatchLoaderDynamic>(nullptr, dld)); 136 dummy_logical, vk::ObjectDestroy<vk::NoParent, vk::DispatchLoaderDynamic>(nullptr, dld));
80 137
138 if (khr_driver_properties) {
139 vk::PhysicalDeviceDriverPropertiesKHR driver;
140 vk::PhysicalDeviceProperties2 properties;
141 properties.pNext = &driver;
142 physical.getProperties2(&properties, dld);
143 driver_id = driver.driverID;
144 LOG_INFO(Render_Vulkan, "Driver: {} {}", driver.driverName, driver.driverInfo);
145 } else {
146 LOG_INFO(Render_Vulkan, "Driver: Unknown");
147 }
148
81 graphics_queue = logical->getQueue(graphics_family, 0, dld); 149 graphics_queue = logical->getQueue(graphics_family, 0, dld);
82 present_queue = logical->getQueue(present_family, 0, dld); 150 present_queue = logical->getQueue(present_family, 0, dld);
83 return true; 151 return true;
@@ -92,20 +160,19 @@ vk::Format VKDevice::GetSupportedFormat(vk::Format wanted_format,
92 // The wanted format is not supported by hardware, search for alternatives 160 // The wanted format is not supported by hardware, search for alternatives
93 const vk::Format* alternatives = GetFormatAlternatives(wanted_format); 161 const vk::Format* alternatives = GetFormatAlternatives(wanted_format);
94 if (alternatives == nullptr) { 162 if (alternatives == nullptr) {
95 LOG_CRITICAL(Render_Vulkan, 163 UNREACHABLE_MSG("Format={} with usage={} and type={} has no defined alternatives and host "
96 "Format={} with usage={} and type={} has no defined alternatives and host " 164 "hardware does not support it",
97 "hardware does not support it", 165 vk::to_string(wanted_format), vk::to_string(wanted_usage),
98 vk::to_string(wanted_format), vk::to_string(wanted_usage), 166 static_cast<u32>(format_type));
99 static_cast<u32>(format_type));
100 UNREACHABLE();
101 return wanted_format; 167 return wanted_format;
102 } 168 }
103 169
104 std::size_t i = 0; 170 std::size_t i = 0;
105 for (vk::Format alternative = alternatives[0]; alternative != vk::Format{}; 171 for (vk::Format alternative = alternatives[0]; alternative != vk::Format{};
106 alternative = alternatives[++i]) { 172 alternative = alternatives[++i]) {
107 if (!IsFormatSupported(alternative, wanted_usage, format_type)) 173 if (!IsFormatSupported(alternative, wanted_usage, format_type)) {
108 continue; 174 continue;
175 }
109 LOG_WARNING(Render_Vulkan, 176 LOG_WARNING(Render_Vulkan,
110 "Emulating format={} with alternative format={} with usage={} and type={}", 177 "Emulating format={} with alternative format={} with usage={} and type={}",
111 static_cast<u32>(wanted_format), static_cast<u32>(alternative), 178 static_cast<u32>(wanted_format), static_cast<u32>(alternative),
@@ -114,12 +181,10 @@ vk::Format VKDevice::GetSupportedFormat(vk::Format wanted_format,
114 } 181 }
115 182
116 // No alternatives found, panic 183 // No alternatives found, panic
117 LOG_CRITICAL(Render_Vulkan, 184 UNREACHABLE_MSG("Format={} with usage={} and type={} is not supported by the host hardware and "
118 "Format={} with usage={} and type={} is not supported by the host hardware and " 185 "doesn't support any of the alternatives",
119 "doesn't support any of the alternatives", 186 static_cast<u32>(wanted_format), static_cast<u32>(wanted_usage),
120 static_cast<u32>(wanted_format), static_cast<u32>(wanted_usage), 187 static_cast<u32>(format_type));
121 static_cast<u32>(format_type));
122 UNREACHABLE();
123 return wanted_format; 188 return wanted_format;
124} 189}
125 190
@@ -132,7 +197,7 @@ bool VKDevice::IsOptimalAstcSupported(const vk::PhysicalDeviceFeatures& features
132 vk::FormatFeatureFlagBits::eSampledImage | vk::FormatFeatureFlagBits::eBlitSrc | 197 vk::FormatFeatureFlagBits::eSampledImage | vk::FormatFeatureFlagBits::eBlitSrc |
133 vk::FormatFeatureFlagBits::eBlitDst | vk::FormatFeatureFlagBits::eTransferSrc | 198 vk::FormatFeatureFlagBits::eBlitDst | vk::FormatFeatureFlagBits::eTransferSrc |
134 vk::FormatFeatureFlagBits::eTransferDst}; 199 vk::FormatFeatureFlagBits::eTransferDst};
135 constexpr std::array<vk::Format, 9> astc_formats = { 200 constexpr std::array astc_formats = {
136 vk::Format::eAstc4x4UnormBlock, vk::Format::eAstc4x4SrgbBlock, 201 vk::Format::eAstc4x4UnormBlock, vk::Format::eAstc4x4SrgbBlock,
137 vk::Format::eAstc8x8SrgbBlock, vk::Format::eAstc8x6SrgbBlock, 202 vk::Format::eAstc8x8SrgbBlock, vk::Format::eAstc8x6SrgbBlock,
138 vk::Format::eAstc5x4SrgbBlock, vk::Format::eAstc5x5UnormBlock, 203 vk::Format::eAstc5x4SrgbBlock, vk::Format::eAstc5x5UnormBlock,
@@ -151,76 +216,120 @@ bool VKDevice::IsFormatSupported(vk::Format wanted_format, vk::FormatFeatureFlag
151 FormatType format_type) const { 216 FormatType format_type) const {
152 const auto it = format_properties.find(wanted_format); 217 const auto it = format_properties.find(wanted_format);
153 if (it == format_properties.end()) { 218 if (it == format_properties.end()) {
154 LOG_CRITICAL(Render_Vulkan, "Unimplemented format query={}", vk::to_string(wanted_format)); 219 UNIMPLEMENTED_MSG("Unimplemented format query={}", vk::to_string(wanted_format));
155 UNREACHABLE();
156 return true; 220 return true;
157 } 221 }
158 const vk::FormatFeatureFlags supported_usage = GetFormatFeatures(it->second, format_type); 222 const auto supported_usage = GetFormatFeatures(it->second, format_type);
159 return (supported_usage & wanted_usage) == wanted_usage; 223 return (supported_usage & wanted_usage) == wanted_usage;
160} 224}
161 225
162bool VKDevice::IsSuitable(const vk::DispatchLoaderDynamic& dldi, vk::PhysicalDevice physical, 226bool VKDevice::IsSuitable(const vk::DispatchLoaderDynamic& dldi, vk::PhysicalDevice physical,
163 vk::SurfaceKHR surface) { 227 vk::SurfaceKHR surface) {
164 bool has_swapchain{}; 228 LOG_INFO(Render_Vulkan, "{}", physical.getProperties(dldi).deviceName);
229 bool is_suitable = true;
230
231 constexpr std::array required_extensions = {VK_KHR_SWAPCHAIN_EXTENSION_NAME,
232 VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME};
233 std::bitset<required_extensions.size()> available_extensions{};
234
165 for (const auto& prop : physical.enumerateDeviceExtensionProperties(nullptr, dldi)) { 235 for (const auto& prop : physical.enumerateDeviceExtensionProperties(nullptr, dldi)) {
166 has_swapchain |= prop.extensionName == std::string(VK_KHR_SWAPCHAIN_EXTENSION_NAME); 236 for (std::size_t i = 0; i < required_extensions.size(); ++i) {
237 if (available_extensions[i]) {
238 continue;
239 }
240 available_extensions[i] =
241 required_extensions[i] == std::string_view{prop.extensionName};
242 }
167 } 243 }
168 if (!has_swapchain) { 244 if (!available_extensions.all()) {
169 // The device doesn't support creating swapchains. 245 for (std::size_t i = 0; i < required_extensions.size(); ++i) {
170 return false; 246 if (available_extensions[i]) {
247 continue;
248 }
249 LOG_INFO(Render_Vulkan, "Missing required extension: {}", required_extensions[i]);
250 is_suitable = false;
251 }
171 } 252 }
172 253
173 bool has_graphics{}, has_present{}; 254 bool has_graphics{}, has_present{};
174 const auto queue_family_properties = physical.getQueueFamilyProperties(dldi); 255 const auto queue_family_properties = physical.getQueueFamilyProperties(dldi);
175 for (u32 i = 0; i < static_cast<u32>(queue_family_properties.size()); ++i) { 256 for (u32 i = 0; i < static_cast<u32>(queue_family_properties.size()); ++i) {
176 const auto& family = queue_family_properties[i]; 257 const auto& family = queue_family_properties[i];
177 if (family.queueCount == 0) 258 if (family.queueCount == 0) {
178 continue; 259 continue;
179 260 }
180 has_graphics |= 261 has_graphics |=
181 (family.queueFlags & vk::QueueFlagBits::eGraphics) != static_cast<vk::QueueFlagBits>(0); 262 (family.queueFlags & vk::QueueFlagBits::eGraphics) != static_cast<vk::QueueFlagBits>(0);
182 has_present |= physical.getSurfaceSupportKHR(i, surface, dldi) != 0; 263 has_present |= physical.getSurfaceSupportKHR(i, surface, dldi) != 0;
183 } 264 }
184 if (!has_graphics || !has_present) { 265 if (!has_graphics || !has_present) {
185 // The device doesn't have a graphics and present queue. 266 LOG_INFO(Render_Vulkan, "Device lacks a graphics and present queue");
186 return false; 267 is_suitable = false;
187 } 268 }
188 269
189 // TODO(Rodrigo): Check if the device matches all requeriments. 270 // TODO(Rodrigo): Check if the device matches all requeriments.
190 const auto properties{physical.getProperties(dldi)}; 271 const auto properties{physical.getProperties(dldi)};
191 const auto limits{properties.limits}; 272 const auto& limits{properties.limits};
192 if (limits.maxUniformBufferRange < 65536) { 273
193 return false; 274 constexpr u32 required_ubo_size = 65536;
275 if (limits.maxUniformBufferRange < required_ubo_size) {
276 LOG_INFO(Render_Vulkan, "Device UBO size {} is too small, {} is required)",
277 limits.maxUniformBufferRange, required_ubo_size);
278 is_suitable = false;
194 } 279 }
195 280
196 const vk::PhysicalDeviceFeatures features{physical.getFeatures(dldi)}; 281 const auto features{physical.getFeatures(dldi)};
197 if (!features.vertexPipelineStoresAndAtomics || !features.independentBlend) { 282 const std::array feature_report = {
198 return false; 283 std::make_pair(features.vertexPipelineStoresAndAtomics, "vertexPipelineStoresAndAtomics"),
284 std::make_pair(features.independentBlend, "independentBlend"),
285 std::make_pair(features.depthClamp, "depthClamp"),
286 std::make_pair(features.samplerAnisotropy, "samplerAnisotropy"),
287 std::make_pair(features.largePoints, "largePoints"),
288 };
289 for (const auto& [supported, name] : feature_report) {
290 if (supported) {
291 continue;
292 }
293 LOG_INFO(Render_Vulkan, "Missing required feature: {}", name);
294 is_suitable = false;
199 } 295 }
200 296
201 // Device is suitable. 297 return is_suitable;
202 return true;
203} 298}
204 299
205std::vector<const char*> VKDevice::LoadExtensions(const vk::DispatchLoaderDynamic& dldi) { 300std::vector<const char*> VKDevice::LoadExtensions(const vk::DispatchLoaderDynamic& dldi) {
206 std::vector<const char*> extensions; 301 std::vector<const char*> extensions;
207 extensions.reserve(2); 302 extensions.reserve(7);
208 extensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME); 303 extensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
304 extensions.push_back(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME);
209 305
210 const auto Test = [&](const vk::ExtensionProperties& extension, 306 const auto Test = [&](const vk::ExtensionProperties& extension,
211 std::optional<std::reference_wrapper<bool>> status, const char* name, 307 std::optional<std::reference_wrapper<bool>> status, const char* name,
212 u32 revision) { 308 bool push) {
213 if (extension.extensionName != std::string(name)) { 309 if (extension.extensionName != std::string_view(name)) {
214 return; 310 return;
215 } 311 }
216 extensions.push_back(name); 312 if (push) {
313 extensions.push_back(name);
314 }
217 if (status) { 315 if (status) {
218 status->get() = true; 316 status->get() = true;
219 } 317 }
220 }; 318 };
221 319
320 bool khr_shader_float16_int8{};
222 for (const auto& extension : physical.enumerateDeviceExtensionProperties(nullptr, dldi)) { 321 for (const auto& extension : physical.enumerateDeviceExtensionProperties(nullptr, dldi)) {
223 Test(extension, ext_scalar_block_layout, VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME, 1); 322 Test(extension, khr_uniform_buffer_standard_layout,
323 VK_KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_EXTENSION_NAME, true);
324 Test(extension, ext_index_type_uint8, VK_EXT_INDEX_TYPE_UINT8_EXTENSION_NAME, true);
325 Test(extension, khr_driver_properties, VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME, true);
326 Test(extension, khr_shader_float16_int8, VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME, false);
327 }
328
329 if (khr_shader_float16_int8) {
330 is_float16_supported =
331 GetFeatures<vk::PhysicalDeviceFloat16Int8FeaturesKHR>(physical, dldi).shaderFloat16;
332 extensions.push_back(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME);
224 } 333 }
225 334
226 return extensions; 335 return extensions;
@@ -250,9 +359,10 @@ void VKDevice::SetupFamilies(const vk::DispatchLoaderDynamic& dldi, vk::SurfaceK
250} 359}
251 360
252void VKDevice::SetupProperties(const vk::DispatchLoaderDynamic& dldi) { 361void VKDevice::SetupProperties(const vk::DispatchLoaderDynamic& dldi) {
253 const vk::PhysicalDeviceProperties props = physical.getProperties(dldi); 362 const auto props = physical.getProperties(dldi);
254 device_type = props.deviceType; 363 device_type = props.deviceType;
255 uniform_buffer_alignment = static_cast<u64>(props.limits.minUniformBufferOffsetAlignment); 364 uniform_buffer_alignment = static_cast<u64>(props.limits.minUniformBufferOffsetAlignment);
365 storage_buffer_alignment = static_cast<u64>(props.limits.minStorageBufferOffsetAlignment);
256 max_storage_buffer_range = static_cast<u64>(props.limits.maxStorageBufferRange); 366 max_storage_buffer_range = static_cast<u64>(props.limits.maxStorageBufferRange);
257} 367}
258 368
@@ -273,42 +383,53 @@ std::vector<vk::DeviceQueueCreateInfo> VKDevice::GetDeviceQueueCreateInfos() con
273 return queue_cis; 383 return queue_cis;
274} 384}
275 385
276std::map<vk::Format, vk::FormatProperties> VKDevice::GetFormatProperties( 386std::unordered_map<vk::Format, vk::FormatProperties> VKDevice::GetFormatProperties(
277 const vk::DispatchLoaderDynamic& dldi, vk::PhysicalDevice physical) { 387 const vk::DispatchLoaderDynamic& dldi, vk::PhysicalDevice physical) {
278 static constexpr std::array formats{vk::Format::eA8B8G8R8UnormPack32, 388 constexpr std::array formats{vk::Format::eA8B8G8R8UnormPack32,
279 vk::Format::eB5G6R5UnormPack16, 389 vk::Format::eA8B8G8R8SnormPack32,
280 vk::Format::eA2B10G10R10UnormPack32, 390 vk::Format::eA8B8G8R8SrgbPack32,
281 vk::Format::eR32G32B32A32Sfloat, 391 vk::Format::eB5G6R5UnormPack16,
282 vk::Format::eR16G16Unorm, 392 vk::Format::eA2B10G10R10UnormPack32,
283 vk::Format::eR16G16Snorm, 393 vk::Format::eR32G32B32A32Sfloat,
284 vk::Format::eR8G8B8A8Srgb, 394 vk::Format::eR16G16B16A16Uint,
285 vk::Format::eR8Unorm, 395 vk::Format::eR16G16Unorm,
286 vk::Format::eB10G11R11UfloatPack32, 396 vk::Format::eR16G16Snorm,
287 vk::Format::eR32Sfloat, 397 vk::Format::eR16G16Sfloat,
288 vk::Format::eR16Sfloat, 398 vk::Format::eR16Unorm,
289 vk::Format::eR16G16B16A16Sfloat, 399 vk::Format::eR8G8B8A8Srgb,
290 vk::Format::eD32Sfloat, 400 vk::Format::eR8G8Unorm,
291 vk::Format::eD16Unorm, 401 vk::Format::eR8G8Snorm,
292 vk::Format::eD16UnormS8Uint, 402 vk::Format::eR8Unorm,
293 vk::Format::eD24UnormS8Uint, 403 vk::Format::eB10G11R11UfloatPack32,
294 vk::Format::eD32SfloatS8Uint, 404 vk::Format::eR32Sfloat,
295 vk::Format::eBc1RgbaUnormBlock, 405 vk::Format::eR16Sfloat,
296 vk::Format::eBc2UnormBlock, 406 vk::Format::eR16G16B16A16Sfloat,
297 vk::Format::eBc3UnormBlock, 407 vk::Format::eB8G8R8A8Unorm,
298 vk::Format::eBc4UnormBlock, 408 vk::Format::eD32Sfloat,
299 vk::Format::eBc5UnormBlock, 409 vk::Format::eD16Unorm,
300 vk::Format::eBc5SnormBlock, 410 vk::Format::eD16UnormS8Uint,
301 vk::Format::eBc7UnormBlock, 411 vk::Format::eD24UnormS8Uint,
302 vk::Format::eAstc4x4UnormBlock, 412 vk::Format::eD32SfloatS8Uint,
303 vk::Format::eAstc4x4SrgbBlock, 413 vk::Format::eBc1RgbaUnormBlock,
304 vk::Format::eAstc8x8SrgbBlock, 414 vk::Format::eBc2UnormBlock,
305 vk::Format::eAstc8x6SrgbBlock, 415 vk::Format::eBc3UnormBlock,
306 vk::Format::eAstc5x4SrgbBlock, 416 vk::Format::eBc4UnormBlock,
307 vk::Format::eAstc5x5UnormBlock, 417 vk::Format::eBc5UnormBlock,
308 vk::Format::eAstc5x5SrgbBlock, 418 vk::Format::eBc5SnormBlock,
309 vk::Format::eAstc10x8UnormBlock, 419 vk::Format::eBc7UnormBlock,
310 vk::Format::eAstc10x8SrgbBlock}; 420 vk::Format::eBc1RgbaSrgbBlock,
311 std::map<vk::Format, vk::FormatProperties> format_properties; 421 vk::Format::eBc3SrgbBlock,
422 vk::Format::eBc7SrgbBlock,
423 vk::Format::eAstc4x4UnormBlock,
424 vk::Format::eAstc4x4SrgbBlock,
425 vk::Format::eAstc8x8SrgbBlock,
426 vk::Format::eAstc8x6SrgbBlock,
427 vk::Format::eAstc5x4SrgbBlock,
428 vk::Format::eAstc5x5UnormBlock,
429 vk::Format::eAstc5x5SrgbBlock,
430 vk::Format::eAstc10x8UnormBlock,
431 vk::Format::eAstc10x8SrgbBlock};
432 std::unordered_map<vk::Format, vk::FormatProperties> format_properties;
312 for (const auto format : formats) { 433 for (const auto format : formats) {
313 format_properties.emplace(format, physical.getFormatProperties(format, dldi)); 434 format_properties.emplace(format, physical.getFormatProperties(format, dldi));
314 } 435 }
diff --git a/src/video_core/renderer_vulkan/vk_device.h b/src/video_core/renderer_vulkan/vk_device.h
index 537825d8b..010d4c3d6 100644
--- a/src/video_core/renderer_vulkan/vk_device.h
+++ b/src/video_core/renderer_vulkan/vk_device.h
@@ -4,7 +4,7 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <map> 7#include <unordered_map>
8#include <vector> 8#include <vector>
9#include "common/common_types.h" 9#include "common/common_types.h"
10#include "video_core/renderer_vulkan/declarations.h" 10#include "video_core/renderer_vulkan/declarations.h"
@@ -69,16 +69,26 @@ public:
69 return present_family; 69 return present_family;
70 } 70 }
71 71
72 /// Returns if the device is integrated with the host CPU. 72 /// Returns true if the device is integrated with the host CPU.
73 bool IsIntegrated() const { 73 bool IsIntegrated() const {
74 return device_type == vk::PhysicalDeviceType::eIntegratedGpu; 74 return device_type == vk::PhysicalDeviceType::eIntegratedGpu;
75 } 75 }
76 76
77 /// Returns the driver ID.
78 vk::DriverIdKHR GetDriverID() const {
79 return driver_id;
80 }
81
77 /// Returns uniform buffer alignment requeriment. 82 /// Returns uniform buffer alignment requeriment.
78 u64 GetUniformBufferAlignment() const { 83 u64 GetUniformBufferAlignment() const {
79 return uniform_buffer_alignment; 84 return uniform_buffer_alignment;
80 } 85 }
81 86
87 /// Returns storage alignment requeriment.
88 u64 GetStorageBufferAlignment() const {
89 return storage_buffer_alignment;
90 }
91
82 /// Returns the maximum range for storage buffers. 92 /// Returns the maximum range for storage buffers.
83 u64 GetMaxStorageBufferRange() const { 93 u64 GetMaxStorageBufferRange() const {
84 return max_storage_buffer_range; 94 return max_storage_buffer_range;
@@ -89,9 +99,19 @@ public:
89 return is_optimal_astc_supported; 99 return is_optimal_astc_supported;
90 } 100 }
91 101
102 /// Returns true if the device supports float16 natively
103 bool IsFloat16Supported() const {
104 return is_float16_supported;
105 }
106
92 /// Returns true if the device supports VK_EXT_scalar_block_layout. 107 /// Returns true if the device supports VK_EXT_scalar_block_layout.
93 bool IsExtScalarBlockLayoutSupported() const { 108 bool IsKhrUniformBufferStandardLayoutSupported() const {
94 return ext_scalar_block_layout; 109 return khr_uniform_buffer_standard_layout;
110 }
111
112 /// Returns true if the device supports VK_EXT_index_type_uint8.
113 bool IsExtIndexTypeUint8Supported() const {
114 return ext_index_type_uint8;
95 } 115 }
96 116
97 /// Checks if the physical device is suitable. 117 /// Checks if the physical device is suitable.
@@ -123,22 +143,28 @@ private:
123 FormatType format_type) const; 143 FormatType format_type) const;
124 144
125 /// Returns the device properties for Vulkan formats. 145 /// Returns the device properties for Vulkan formats.
126 static std::map<vk::Format, vk::FormatProperties> GetFormatProperties( 146 static std::unordered_map<vk::Format, vk::FormatProperties> GetFormatProperties(
127 const vk::DispatchLoaderDynamic& dldi, vk::PhysicalDevice physical); 147 const vk::DispatchLoaderDynamic& dldi, vk::PhysicalDevice physical);
128 148
129 const vk::PhysicalDevice physical; ///< Physical device. 149 const vk::PhysicalDevice physical; ///< Physical device.
130 vk::DispatchLoaderDynamic dld; ///< Device function pointers. 150 vk::DispatchLoaderDynamic dld; ///< Device function pointers.
131 UniqueDevice logical; ///< Logical device. 151 UniqueDevice logical; ///< Logical device.
132 vk::Queue graphics_queue; ///< Main graphics queue. 152 vk::Queue graphics_queue; ///< Main graphics queue.
133 vk::Queue present_queue; ///< Main present queue. 153 vk::Queue present_queue; ///< Main present queue.
134 u32 graphics_family{}; ///< Main graphics queue family index. 154 u32 graphics_family{}; ///< Main graphics queue family index.
135 u32 present_family{}; ///< Main present queue family index. 155 u32 present_family{}; ///< Main present queue family index.
136 vk::PhysicalDeviceType device_type; ///< Physical device type. 156 vk::PhysicalDeviceType device_type; ///< Physical device type.
137 u64 uniform_buffer_alignment{}; ///< Uniform buffer alignment requeriment. 157 vk::DriverIdKHR driver_id{}; ///< Driver ID.
138 u64 max_storage_buffer_range{}; ///< Max storage buffer size. 158 u64 uniform_buffer_alignment{}; ///< Uniform buffer alignment requeriment.
139 bool is_optimal_astc_supported{}; ///< Support for native ASTC. 159 u64 storage_buffer_alignment{}; ///< Storage buffer alignment requeriment.
140 bool ext_scalar_block_layout{}; ///< Support for VK_EXT_scalar_block_layout. 160 u64 max_storage_buffer_range{}; ///< Max storage buffer size.
141 std::map<vk::Format, vk::FormatProperties> format_properties; ///< Format properties dictionary. 161 bool is_optimal_astc_supported{}; ///< Support for native ASTC.
162 bool is_float16_supported{}; ///< Support for float16 arithmetics.
163 bool khr_uniform_buffer_standard_layout{}; ///< Support for std430 on UBOs.
164 bool ext_index_type_uint8{}; ///< Support for VK_EXT_index_type_uint8.
165 bool khr_driver_properties{}; ///< Support for VK_KHR_driver_properties.
166 std::unordered_map<vk::Format, vk::FormatProperties>
167 format_properties; ///< Format properties dictionary.
142}; 168};
143 169
144} // namespace Vulkan 170} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
index a35b45c9c..73640cc19 100644
--- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
+++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
@@ -370,8 +370,8 @@ private:
370 u32 binding = const_buffers_base_binding; 370 u32 binding = const_buffers_base_binding;
371 for (const auto& entry : ir.GetConstantBuffers()) { 371 for (const auto& entry : ir.GetConstantBuffers()) {
372 const auto [index, size] = entry; 372 const auto [index, size] = entry;
373 const Id type = 373 const Id type = device.IsKhrUniformBufferStandardLayoutSupported() ? t_cbuf_scalar_ubo
374 device.IsExtScalarBlockLayoutSupported() ? t_cbuf_scalar_ubo : t_cbuf_std140_ubo; 374 : t_cbuf_std140_ubo;
375 const Id id = OpVariable(type, spv::StorageClass::Uniform); 375 const Id id = OpVariable(type, spv::StorageClass::Uniform);
376 AddGlobalVariable(Name(id, fmt::format("cbuf_{}", index))); 376 AddGlobalVariable(Name(id, fmt::format("cbuf_{}", index)));
377 377
@@ -565,7 +565,7 @@ private:
565 const Id buffer_id = constant_buffers.at(cbuf->GetIndex()); 565 const Id buffer_id = constant_buffers.at(cbuf->GetIndex());
566 566
567 Id pointer{}; 567 Id pointer{};
568 if (device.IsExtScalarBlockLayoutSupported()) { 568 if (device.IsKhrUniformBufferStandardLayoutSupported()) {
569 const Id buffer_offset = Emit(OpShiftRightLogical( 569 const Id buffer_offset = Emit(OpShiftRightLogical(
570 t_uint, BitcastTo<Type::Uint>(Visit(offset)), Constant(t_uint, 2u))); 570 t_uint, BitcastTo<Type::Uint>(Visit(offset)), Constant(t_uint, 2u)));
571 pointer = Emit( 571 pointer = Emit(