[GPU] Vulkan fragment shader interlock RB and related fixes/cleanup

Also fixes addressing of MSAA samples 2 and 3 for 64bpp color render targets in the ROV RB implementation on Direct3D 12.
Additionally, with FSI/ROV, alpha test and alpha to coverage are done only if the render target 0 was dynamically written to (according to the Direct3D 9 rules for writing to color render targets, though not sure if they actually apply to the alpha tests on Direct3D 9, but for safety).
There is also some code cleanup for things spotted during the development of the feature.
This commit is contained in:
Triang3l
2022-10-09 22:06:41 +03:00
parent 9ab4db285c
commit 45050b2380
24 changed files with 6168 additions and 1530 deletions

View File

@@ -1,5 +1,7 @@
// VK_KHR_get_physical_device_properties2 functions used in Xenia.
// Promoted to Vulkan 1.1 core.
XE_UI_VULKAN_FUNCTION_PROMOTED(vkGetPhysicalDeviceFeatures2KHR,
vkGetPhysicalDeviceFeatures2)
XE_UI_VULKAN_FUNCTION_PROMOTED(vkGetPhysicalDeviceMemoryProperties2KHR,
vkGetPhysicalDeviceMemoryProperties2)
XE_UI_VULKAN_FUNCTION_PROMOTED(vkGetPhysicalDeviceProperties2KHR,

View File

@@ -696,6 +696,7 @@ bool VulkanProvider::Initialize() {
device_extensions_.khr_shader_float_controls = true;
device_extensions_.khr_spirv_1_4 = true;
if (device_properties_.apiVersion >= VK_MAKE_API_VERSION(0, 1, 3, 0)) {
device_extensions_.ext_shader_demote_to_helper_invocation = true;
device_extensions_.khr_maintenance4 = true;
}
}
@@ -709,6 +710,8 @@ bool VulkanProvider::Initialize() {
{"VK_EXT_fragment_shader_interlock",
offsetof(DeviceExtensions, ext_fragment_shader_interlock)},
{"VK_EXT_memory_budget", offsetof(DeviceExtensions, ext_memory_budget)},
{"VK_EXT_shader_demote_to_helper_invocation",
offsetof(DeviceExtensions, ext_shader_demote_to_helper_invocation)},
{"VK_EXT_shader_stencil_export",
offsetof(DeviceExtensions, ext_shader_stencil_export)},
{"VK_KHR_bind_memory2", offsetof(DeviceExtensions, khr_bind_memory2)},
@@ -816,6 +819,16 @@ bool VulkanProvider::Initialize() {
// Get additional device properties.
std::memset(&device_float_controls_properties_, 0,
sizeof(device_float_controls_properties_));
device_float_controls_properties_.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES_KHR;
std::memset(&device_fragment_shader_interlock_features_, 0,
sizeof(device_fragment_shader_interlock_features_));
device_fragment_shader_interlock_features_.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT;
std::memset(&device_shader_demote_to_helper_invocation_features_, 0,
sizeof(device_shader_demote_to_helper_invocation_features_));
device_shader_demote_to_helper_invocation_features_.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT;
if (instance_extensions_.khr_get_physical_device_properties2) {
VkPhysicalDeviceProperties2KHR device_properties_2;
device_properties_2.sType =
@@ -824,8 +837,6 @@ bool VulkanProvider::Initialize() {
VkPhysicalDeviceProperties2KHR* device_properties_2_last =
&device_properties_2;
if (device_extensions_.khr_shader_float_controls) {
device_float_controls_properties_.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES_KHR;
device_float_controls_properties_.pNext = nullptr;
device_properties_2_last->pNext = &device_float_controls_properties_;
device_properties_2_last =
@@ -836,6 +847,28 @@ bool VulkanProvider::Initialize() {
ifn_.vkGetPhysicalDeviceProperties2KHR(physical_device_,
&device_properties_2);
}
VkPhysicalDeviceFeatures2KHR device_features_2;
device_features_2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR;
device_features_2.pNext = nullptr;
VkPhysicalDeviceFeatures2KHR* device_features_2_last = &device_features_2;
if (device_extensions_.ext_fragment_shader_interlock) {
device_fragment_shader_interlock_features_.pNext = nullptr;
device_features_2_last->pNext =
&device_fragment_shader_interlock_features_;
device_features_2_last = reinterpret_cast<VkPhysicalDeviceFeatures2KHR*>(
&device_fragment_shader_interlock_features_);
}
if (device_extensions_.ext_shader_demote_to_helper_invocation) {
device_shader_demote_to_helper_invocation_features_.pNext = nullptr;
device_features_2_last->pNext =
&device_shader_demote_to_helper_invocation_features_;
device_features_2_last = reinterpret_cast<VkPhysicalDeviceFeatures2KHR*>(
&device_shader_demote_to_helper_invocation_features_);
}
if (device_features_2_last != &device_features_2) {
ifn_.vkGetPhysicalDeviceFeatures2KHR(physical_device_,
&device_features_2);
}
}
// Create the device.
@@ -888,6 +921,21 @@ bool VulkanProvider::Initialize() {
device_create_info_last = reinterpret_cast<VkDeviceCreateInfo*>(
&device_portability_subset_features_);
}
if (device_extensions_.ext_fragment_shader_interlock) {
// TODO(Triang3l): Enable only needed fragment shader interlock features.
device_fragment_shader_interlock_features_.pNext = nullptr;
device_create_info_last->pNext =
&device_fragment_shader_interlock_features_;
device_create_info_last = reinterpret_cast<VkDeviceCreateInfo*>(
&device_fragment_shader_interlock_features_);
}
if (device_extensions_.ext_shader_demote_to_helper_invocation) {
device_shader_demote_to_helper_invocation_features_.pNext = nullptr;
device_create_info_last->pNext =
&device_shader_demote_to_helper_invocation_features_;
device_create_info_last = reinterpret_cast<VkDeviceCreateInfo*>(
&device_shader_demote_to_helper_invocation_features_);
}
if (ifn_.vkCreateDevice(physical_device_, &device_create_info, nullptr,
&device_) != VK_SUCCESS) {
XELOGE("Failed to create a Vulkan device");
@@ -995,8 +1043,30 @@ bool VulkanProvider::Initialize() {
XELOGVK("Vulkan device extensions:");
XELOGVK("* VK_EXT_fragment_shader_interlock: {}",
device_extensions_.ext_fragment_shader_interlock ? "yes" : "no");
if (device_extensions_.ext_fragment_shader_interlock) {
XELOGVK(
" * Sample interlock: {}",
device_fragment_shader_interlock_features_.fragmentShaderSampleInterlock
? "yes"
: "no");
XELOGVK(
" * Pixel interlock: {}",
device_fragment_shader_interlock_features_.fragmentShaderPixelInterlock
? "yes"
: "no");
}
XELOGVK("* VK_EXT_memory_budget: {}",
device_extensions_.ext_memory_budget ? "yes" : "no");
XELOGVK(
"* VK_EXT_shader_demote_to_helper_invocation: {}",
device_extensions_.ext_shader_demote_to_helper_invocation ? "yes" : "no");
if (device_extensions_.ext_shader_demote_to_helper_invocation) {
XELOGVK(" * Demote to helper invocation: {}",
device_shader_demote_to_helper_invocation_features_
.shaderDemoteToHelperInvocation
? "yes"
: "no");
}
XELOGVK("* VK_EXT_shader_stencil_export: {}",
device_extensions_.ext_shader_stencil_export ? "yes" : "no");
XELOGVK("* VK_KHR_bind_memory2: {}",

View File

@@ -133,6 +133,8 @@ class VulkanProvider : public GraphicsProvider {
struct DeviceExtensions {
bool ext_fragment_shader_interlock;
bool ext_memory_budget;
// Core since 1.3.0.
bool ext_shader_demote_to_helper_invocation;
bool ext_shader_stencil_export;
// Core since 1.1.0.
bool khr_bind_memory2;
@@ -198,6 +200,14 @@ class VulkanProvider : public GraphicsProvider {
device_float_controls_properties() const {
return device_float_controls_properties_;
}
const VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT&
device_fragment_shader_interlock_features() const {
return device_fragment_shader_interlock_features_;
}
const VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT&
device_shader_demote_to_helper_invocation_features() const {
return device_shader_demote_to_helper_invocation_features_;
}
struct Queue {
VkQueue queue = VK_NULL_HANDLE;
@@ -320,6 +330,10 @@ class VulkanProvider : public GraphicsProvider {
uint32_t queue_family_graphics_compute_;
uint32_t queue_family_sparse_binding_;
VkPhysicalDeviceFloatControlsPropertiesKHR device_float_controls_properties_;
VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT
device_fragment_shader_interlock_features_;
VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT
device_shader_demote_to_helper_invocation_features_;
VkDevice device_ = VK_NULL_HANDLE;
DeviceFunctions dfn_ = {};