[Vulkan] Expose relevant portability subset features

This commit is contained in:
Triang3l 2022-02-13 20:19:01 +03:00
parent 0590346084
commit 8ca67b8aa7
2 changed files with 104 additions and 37 deletions

View file

@ -10,7 +10,9 @@
#include "xenia/ui/vulkan/vulkan_provider.h" #include "xenia/ui/vulkan/vulkan_provider.h"
#include <cfloat> #include <cfloat>
#include <cstddef>
#include <cstring> #include <cstring>
#include <utility>
#include <vector> #include <vector>
#include "xenia/base/assert.h" #include "xenia/base/assert.h"
@ -710,51 +712,65 @@ bool VulkanProvider::Initialize() {
} }
} }
device_extensions_enabled.clear(); device_extensions_enabled.clear();
// Checking if already enabled as an optimization to do fewer and fewer
// string comparisons, as well as to skip adding extensions promoted to the
// core to device_extensions_enabled. Adding literals to
// device_extensions_enabled for the most C string lifetime safety.
static const std::pair<const char*, size_t> kUsedDeviceExtensions[] = {
{"VK_AMD_shader_info", offsetof(DeviceExtensions, amd_shader_info)},
{"VK_EXT_fragment_shader_interlock",
offsetof(DeviceExtensions, ext_fragment_shader_interlock)},
{"VK_KHR_dedicated_allocation",
offsetof(DeviceExtensions, khr_dedicated_allocation)},
{"VK_KHR_image_format_list",
offsetof(DeviceExtensions, khr_image_format_list)},
{"VK_KHR_portability_subset",
offsetof(DeviceExtensions, khr_portability_subset)},
{"VK_KHR_shader_float_controls",
offsetof(DeviceExtensions, khr_shader_float_controls)},
{"VK_KHR_spirv_1_4", offsetof(DeviceExtensions, khr_spirv_1_4)},
{"VK_KHR_swapchain", offsetof(DeviceExtensions, khr_swapchain)},
};
for (const VkExtensionProperties& device_extension : for (const VkExtensionProperties& device_extension :
device_extension_properties) { device_extension_properties) {
const char* device_extension_name = device_extension.extensionName; for (const std::pair<const char*, size_t>& used_device_extension :
// Checking if already enabled as an optimization to do fewer and fewer kUsedDeviceExtensions) {
// string comparisons, as well as to skip adding extensions promoted to bool& device_extension_flag = *reinterpret_cast<bool*>(
// the core to device_extensions_enabled. Adding literals to reinterpret_cast<char*>(&device_extensions_) +
// device_extensions_enabled for the most C string lifetime safety. used_device_extension.second);
if (!device_extensions_.amd_shader_info && if (!device_extension_flag &&
!std::strcmp(device_extension_name, "VK_AMD_shader_info")) { !std::strcmp(device_extension.extensionName,
device_extensions_enabled.push_back("VK_AMD_shader_info"); used_device_extension.first)) {
device_extensions_.amd_shader_info = true; device_extensions_enabled.push_back(used_device_extension.first);
} else if (!device_extensions_.ext_fragment_shader_interlock && device_extension_flag = true;
!std::strcmp(device_extension_name, }
"VK_EXT_fragment_shader_interlock")) {
device_extensions_enabled.push_back("VK_EXT_fragment_shader_interlock");
device_extensions_.ext_fragment_shader_interlock = true;
} else if (!device_extensions_.khr_dedicated_allocation &&
!std::strcmp(device_extension_name,
"VK_KHR_dedicated_allocation")) {
device_extensions_enabled.push_back("VK_KHR_dedicated_allocation");
device_extensions_.khr_dedicated_allocation = true;
} else if (!device_extensions_.khr_image_format_list &&
!std::strcmp(device_extension_name,
"VK_KHR_image_format_list")) {
device_extensions_enabled.push_back("VK_KHR_image_format_list");
device_extensions_.khr_image_format_list = true;
} else if (!device_extensions_.khr_shader_float_controls &&
!std::strcmp(device_extension_name,
"VK_KHR_shader_float_controls")) {
device_extensions_enabled.push_back("VK_KHR_shader_float_controls");
device_extensions_.khr_shader_float_controls = true;
} else if (!device_extensions_.khr_spirv_1_4 &&
!std::strcmp(device_extension_name, "VK_KHR_spirv_1_4")) {
device_extensions_enabled.push_back("VK_KHR_spirv_1_4");
device_extensions_.khr_spirv_1_4 = true;
} else if (!device_extensions_.khr_swapchain &&
!std::strcmp(device_extension_name, "VK_KHR_swapchain")) {
device_extensions_enabled.push_back("VK_KHR_swapchain");
device_extensions_.khr_swapchain = true;
} }
} }
if (is_surface_required_ && !device_extensions_.khr_swapchain) { if (is_surface_required_ && !device_extensions_.khr_swapchain) {
continue; continue;
} }
// Get portability subset features.
// VK_KHR_portability_subset reduces, not increases, the capabilities, skip
// the device completely if there's no way to retrieve what is actually
// unsupported. Though VK_KHR_portability_subset requires
// VK_KHR_get_physical_device_properties2, check just in case of an
// untrustworthy driver.
if (device_extensions_.khr_portability_subset) {
if (!instance_extensions_.khr_get_physical_device_properties2) {
continue;
}
device_portability_subset_features_.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_PROPERTIES_KHR;
device_portability_subset_features_.pNext = nullptr;
VkPhysicalDeviceProperties2KHR device_properties_2;
device_properties_2.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR;
device_properties_2.pNext = &device_portability_subset_features_;
ifn_.vkGetPhysicalDeviceProperties2KHR(physical_device_,
&device_properties_2);
}
// Get the memory types. // Get the memory types.
VkPhysicalDeviceMemoryProperties memory_properties; VkPhysicalDeviceMemoryProperties memory_properties;
ifn_.vkGetPhysicalDeviceMemoryProperties(physical_device_current, ifn_.vkGetPhysicalDeviceMemoryProperties(physical_device_current,
@ -851,6 +867,7 @@ bool VulkanProvider::Initialize() {
VkDeviceCreateInfo device_create_info; VkDeviceCreateInfo device_create_info;
device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
device_create_info.pNext = nullptr; device_create_info.pNext = nullptr;
VkDeviceCreateInfo* device_create_info_last = &device_create_info;
device_create_info.flags = 0; device_create_info.flags = 0;
device_create_info.queueCreateInfoCount = uint32_t(queue_create_infos.size()); device_create_info.queueCreateInfoCount = uint32_t(queue_create_infos.size());
device_create_info.pQueueCreateInfos = queue_create_infos.data(); device_create_info.pQueueCreateInfos = queue_create_infos.data();
@ -862,6 +879,13 @@ bool VulkanProvider::Initialize() {
device_create_info.ppEnabledExtensionNames = device_extensions_enabled.data(); device_create_info.ppEnabledExtensionNames = device_extensions_enabled.data();
// TODO(Triang3l): Enable only needed features. // TODO(Triang3l): Enable only needed features.
device_create_info.pEnabledFeatures = &device_features_; device_create_info.pEnabledFeatures = &device_features_;
if (device_extensions_.khr_portability_subset) {
// TODO(Triang3l): Enable only needed portability subset features.
device_portability_subset_features_.pNext = nullptr;
device_create_info_last->pNext = &device_portability_subset_features_;
device_create_info_last = reinterpret_cast<VkDeviceCreateInfo*>(
&device_portability_subset_features_);
}
if (ifn_.vkCreateDevice(physical_device_, &device_create_info, nullptr, if (ifn_.vkCreateDevice(physical_device_, &device_create_info, nullptr,
&device_) != VK_SUCCESS) { &device_) != VK_SUCCESS) {
XELOGE("Failed to create a Vulkan device"); XELOGE("Failed to create a Vulkan device");
@ -938,6 +962,34 @@ bool VulkanProvider::Initialize() {
device_extensions_.khr_dedicated_allocation ? "yes" : "no"); device_extensions_.khr_dedicated_allocation ? "yes" : "no");
XELOGVK("* VK_KHR_image_format_list: {}", XELOGVK("* VK_KHR_image_format_list: {}",
device_extensions_.khr_image_format_list ? "yes" : "no"); device_extensions_.khr_image_format_list ? "yes" : "no");
XELOGVK("* VK_KHR_portability_subset: {}",
device_extensions_.khr_portability_subset ? "yes" : "no");
if (device_extensions_.khr_portability_subset) {
XELOGVK(" * Constant alpha color blend factors: {}",
device_portability_subset_features_.constantAlphaColorBlendFactors
? "yes"
: "no");
XELOGVK(" * Image view format reinterpretation: {}",
device_portability_subset_features_.imageViewFormatReinterpretation
? "yes"
: "no");
XELOGVK(" * Image view format swizzle: {}",
device_portability_subset_features_.imageViewFormatSwizzle ? "yes"
: "no");
XELOGVK(" * Point polygons: {}",
device_portability_subset_features_.pointPolygons ? "yes" : "no");
XELOGVK(
" * Separate stencil front and back masks and reference values: {}",
device_portability_subset_features_.separateStencilMaskRef ? "yes"
: "no");
XELOGVK(" * Shader sample rate interpolation functions: {}",
device_portability_subset_features_
.shaderSampleRateInterpolationFunctions
? "yes"
: "no");
XELOGVK(" * Triangle fans: {}",
device_portability_subset_features_.triangleFans ? "yes" : "no");
}
XELOGVK("* VK_KHR_shader_float_controls: {}", XELOGVK("* VK_KHR_shader_float_controls: {}",
device_extensions_.khr_shader_float_controls ? "yes" : "no"); device_extensions_.khr_shader_float_controls ? "yes" : "no");
if (device_extensions_.khr_shader_float_controls) { if (device_extensions_.khr_shader_float_controls) {

View file

@ -39,6 +39,9 @@
#endif #endif
#endif #endif
#ifndef VK_ENABLE_BETA_EXTENSIONS
#define VK_ENABLE_BETA_EXTENSIONS 1
#endif
#ifndef VK_NO_PROTOTYPES #ifndef VK_NO_PROTOTYPES
#define VK_NO_PROTOTYPES 1 #define VK_NO_PROTOTYPES 1
#endif #endif
@ -134,6 +137,8 @@ class VulkanProvider : public GraphicsProvider {
bool khr_dedicated_allocation; bool khr_dedicated_allocation;
// Core since 1.2.0. // Core since 1.2.0.
bool khr_image_format_list; bool khr_image_format_list;
// Requires the VK_KHR_get_physical_device_properties2 instance extension.
bool khr_portability_subset;
// Core since 1.2.0. // Core since 1.2.0.
bool khr_shader_float_controls; bool khr_shader_float_controls;
// Core since 1.2.0. // Core since 1.2.0.
@ -143,6 +148,14 @@ class VulkanProvider : public GraphicsProvider {
const DeviceExtensions& device_extensions() const { const DeviceExtensions& device_extensions() const {
return device_extensions_; return device_extensions_;
} }
// Returns nullptr if the device is fully compliant with Vulkan 1.0.
const VkPhysicalDevicePortabilitySubsetFeaturesKHR*
device_portability_subset_features() const {
if (!device_extensions_.khr_portability_subset) {
return nullptr;
}
return &device_portability_subset_features_;
}
uint32_t memory_types_device_local() const { uint32_t memory_types_device_local() const {
return memory_types_device_local_; return memory_types_device_local_;
} }
@ -271,6 +284,8 @@ class VulkanProvider : public GraphicsProvider {
VkPhysicalDeviceProperties device_properties_; VkPhysicalDeviceProperties device_properties_;
VkPhysicalDeviceFeatures device_features_; VkPhysicalDeviceFeatures device_features_;
DeviceExtensions device_extensions_; DeviceExtensions device_extensions_;
VkPhysicalDevicePortabilitySubsetFeaturesKHR
device_portability_subset_features_;
uint32_t memory_types_device_local_; uint32_t memory_types_device_local_;
uint32_t memory_types_host_visible_; uint32_t memory_types_host_visible_;
uint32_t memory_types_host_coherent_; uint32_t memory_types_host_coherent_;