GS/Vulkan: Drop feedback loop extension

Apparently this causes GPU crashes on RDNA3, and didn't provide any
tangible benefit for NVIDIA.

I'll replace this at some point with dynamic rendering local reads,
either before or after the GPUDevice transition.
This commit is contained in:
Stenzek 2024-04-23 00:05:21 +10:00 committed by Connor McLaughlin
parent d824ae6e0c
commit fe0e71f586
4 changed files with 23 additions and 88 deletions

View File

@ -349,7 +349,7 @@ layout(set = 1, binding = 1) uniform texture2D Palette;
#endif
#if PS_FEEDBACK_LOOP_IS_NEEDED
#if defined(DISABLE_TEXTURE_BARRIER) || defined(HAS_FEEDBACK_LOOP_LAYOUT)
#if defined(DISABLE_TEXTURE_BARRIER)
layout(set = 1, binding = 2) uniform texture2D RtSampler;
vec4 sample_from_rt() { return texelFetch(RtSampler, ivec2(gl_FragCoord.xy), 0); }
#else

View File

@ -375,8 +375,6 @@ bool GSDeviceVK::SelectDeviceExtensions(ExtensionList* extension_list, bool enab
m_optional_extensions.vk_ext_rasterization_order_attachment_access =
SupportsExtension(VK_EXT_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_EXTENSION_NAME, false) ||
SupportsExtension(VK_ARM_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_EXTENSION_NAME, false);
m_optional_extensions.vk_ext_attachment_feedback_loop_layout =
SupportsExtension(VK_EXT_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_EXTENSION_NAME, false);
m_optional_extensions.vk_ext_line_rasterization = SupportsExtension(VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME,
require_line_rasterization);
m_optional_extensions.vk_khr_driver_properties = SupportsExtension(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME, false);
@ -575,8 +573,6 @@ bool GSDeviceVK::CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_EXT};
VkPhysicalDeviceLineRasterizationFeaturesEXT line_rasterization_feature = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT};
VkPhysicalDeviceAttachmentFeedbackLoopLayoutFeaturesEXT attachment_feedback_loop_feature = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_FEATURES_EXT};
if (m_optional_extensions.vk_ext_provoking_vertex)
{
@ -593,11 +589,6 @@ bool GSDeviceVK::CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer
rasterization_order_access_feature.rasterizationOrderColorAttachmentAccess = VK_TRUE;
Vulkan::AddPointerToChain(&device_info, &rasterization_order_access_feature);
}
if (m_optional_extensions.vk_ext_attachment_feedback_loop_layout)
{
attachment_feedback_loop_feature.attachmentFeedbackLoopLayout = VK_TRUE;
Vulkan::AddPointerToChain(&device_info, &attachment_feedback_loop_feature);
}
VkResult res = vkCreateDevice(m_physical_device, &device_info, nullptr, &m_device);
if (res != VK_SUCCESS)
@ -673,8 +664,6 @@ bool GSDeviceVK::ProcessDeviceExtensions()
Vulkan::AddPointerToChain(&features2, &line_rasterization_feature);
if (m_optional_extensions.vk_ext_rasterization_order_attachment_access)
Vulkan::AddPointerToChain(&features2, &rasterization_order_access_feature);
if (m_optional_extensions.vk_ext_attachment_feedback_loop_layout)
Vulkan::AddPointerToChain(&features2, &attachment_feedback_loop_feature);
// query
vkGetPhysicalDeviceFeatures2(m_physical_device, &features2);
@ -683,8 +672,6 @@ bool GSDeviceVK::ProcessDeviceExtensions()
m_optional_extensions.vk_ext_provoking_vertex &= (provoking_vertex_features.provokingVertexLast == VK_TRUE);
m_optional_extensions.vk_ext_rasterization_order_attachment_access &=
(rasterization_order_access_feature.rasterizationOrderColorAttachmentAccess == VK_TRUE);
m_optional_extensions.vk_ext_attachment_feedback_loop_layout &=
(attachment_feedback_loop_feature.attachmentFeedbackLoopLayout == VK_TRUE);
VkPhysicalDeviceProperties2 properties2 = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2};
@ -762,8 +749,6 @@ bool GSDeviceVK::ProcessDeviceExtensions()
m_optional_extensions.vk_ext_calibrated_timestamps ? "supported" : "NOT supported");
Console.WriteLn("VK_EXT_rasterization_order_attachment_access is %s",
m_optional_extensions.vk_ext_rasterization_order_attachment_access ? "supported" : "NOT supported");
Console.WriteLn("VK_EXT_attachment_feedback_loop_layout is %s",
m_optional_extensions.vk_ext_attachment_feedback_loop_layout ? "supported" : "NOT supported");
Console.WriteLn("VK_EXT_full_screen_exclusive is %s",
m_optional_extensions.vk_ext_full_screen_exclusive ? "supported" : "NOT supported");
Console.WriteLn("VK_KHR_driver_properties is %s",
@ -1568,10 +1553,7 @@ VkRenderPass GSDeviceVK::CreateCachedRenderPass(RenderPassCacheKey key)
u32 num_attachments = 0;
if (key.color_format != VK_FORMAT_UNDEFINED)
{
const VkImageLayout layout =
key.color_feedback_loop ? (UseFeedbackLoopLayout() ? VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT :
VK_IMAGE_LAYOUT_GENERAL) :
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
const VkImageLayout layout = key.color_feedback_loop ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
attachments[num_attachments] = {0, static_cast<VkFormat>(key.color_format), VK_SAMPLE_COUNT_1_BIT,
static_cast<VkAttachmentLoadOp>(key.color_load_op), static_cast<VkAttachmentStoreOp>(key.color_store_op),
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, layout, layout};
@ -1580,13 +1562,10 @@ VkRenderPass GSDeviceVK::CreateCachedRenderPass(RenderPassCacheKey key)
color_reference_ptr = &color_reference;
if (key.color_feedback_loop)
{
if (!UseFeedbackLoopLayout())
{
input_reference.attachment = num_attachments;
input_reference.layout = layout;
input_reference_ptr = &input_reference;
}
if (!m_features.framebuffer_fetch)
{
@ -1595,13 +1574,9 @@ VkRenderPass GSDeviceVK::CreateCachedRenderPass(RenderPassCacheKey key)
subpass_dependency.dstSubpass = 0;
subpass_dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
subpass_dependency.dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
subpass_dependency.srcAccessMask =
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
subpass_dependency.dstAccessMask =
UseFeedbackLoopLayout() ? VK_ACCESS_SHADER_READ_BIT : VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
subpass_dependency.dependencyFlags =
UseFeedbackLoopLayout() ? (VK_DEPENDENCY_BY_REGION_BIT | VK_DEPENDENCY_FEEDBACK_LOOP_BIT_EXT) :
VK_DEPENDENCY_BY_REGION_BIT;
subpass_dependency.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
subpass_dependency.dstAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
subpass_dependency.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
subpass_dependency_ptr = &subpass_dependency;
}
}
@ -1610,10 +1585,7 @@ VkRenderPass GSDeviceVK::CreateCachedRenderPass(RenderPassCacheKey key)
}
if (key.depth_format != VK_FORMAT_UNDEFINED)
{
const VkImageLayout layout =
key.depth_sampling ? (UseFeedbackLoopLayout() ? VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT :
VK_IMAGE_LAYOUT_GENERAL) :
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
const VkImageLayout layout = key.depth_sampling ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
attachments[num_attachments] = {0, static_cast<VkFormat>(key.depth_format), VK_SAMPLE_COUNT_1_BIT,
static_cast<VkAttachmentLoadOp>(key.depth_load_op), static_cast<VkAttachmentStoreOp>(key.depth_store_op),
static_cast<VkAttachmentLoadOp>(key.stencil_load_op),
@ -3664,8 +3636,6 @@ static void AddShaderHeader(std::stringstream& ss)
if (!features.texture_barrier)
ss << "#define DISABLE_TEXTURE_BARRIER 1\n";
if (features.texture_barrier && dev->UseFeedbackLoopLayout())
ss << "#define HAS_FEEDBACK_LOOP_LAYOUT 1\n";
}
static void AddShaderStageMacro(std::stringstream& ss, bool vs, bool gs, bool fs)
@ -3820,8 +3790,7 @@ bool GSDeviceVK::CreatePipelineLayouts()
dslb.AddBinding(TFX_TEXTURE_TEXTURE, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
dslb.AddBinding(TFX_TEXTURE_PALETTE, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
dslb.AddBinding(TFX_TEXTURE_RT,
(m_features.texture_barrier && !UseFeedbackLoopLayout()) ? VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT :
VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
m_features.texture_barrier ? VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT : VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
1, VK_SHADER_STAGE_FRAGMENT_BIT);
dslb.AddBinding(TFX_TEXTURE_PRIMID, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
if ((m_tfx_texture_ds_layout = dslb.Create(dev)) == VK_NULL_HANDLE)
@ -5454,7 +5423,7 @@ bool GSDeviceVK::ApplyTFXState(bool already_execed)
}
if (flags & DIRTY_FLAG_TFX_TEXTURE_RT)
{
if (m_features.texture_barrier && !UseFeedbackLoopLayout())
if (m_features.texture_barrier)
{
dsub.AddInputAttachmentDescriptorWrite(
VK_NULL_HANDLE, TFX_TEXTURE_RT, m_tfx_textures[TFX_TEXTURE_RT]->GetView(), VK_IMAGE_LAYOUT_GENERAL);
@ -5993,21 +5962,12 @@ void GSDeviceVK::UploadHWDrawVerticesAndIndices(const GSHWDrawConfig& config)
VkImageMemoryBarrier GSDeviceVK::GetColorBufferBarrier(GSTextureVK* rt) const
{
const VkImageLayout layout =
UseFeedbackLoopLayout() ? VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT : VK_IMAGE_LAYOUT_GENERAL;
const VkAccessFlags dst_access =
UseFeedbackLoopLayout() ? VK_ACCESS_SHADER_READ_BIT : VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
return {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, nullptr,
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, dst_access, layout, layout,
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL,
VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, rt->GetImage(), {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u}};
}
VkDependencyFlags GSDeviceVK::GetColorBufferBarrierFlags() const
{
return UseFeedbackLoopLayout() ? (VK_DEPENDENCY_BY_REGION_BIT | VK_DEPENDENCY_FEEDBACK_LOOP_BIT_EXT) :
VK_DEPENDENCY_BY_REGION_BIT;
}
void GSDeviceVK::SendHWDraw(const GSHWDrawConfig& config, GSTextureVK* draw_rt, bool skip_first_barrier)
{
if (config.drawlist)
@ -6019,7 +5979,6 @@ void GSDeviceVK::SendHWDraw(const GSHWDrawConfig& config, GSTextureVK* draw_rt,
const u32 indices_per_prim = config.indices_per_prim;
const u32 draw_list_size = static_cast<u32>(config.drawlist->size());
const VkImageMemoryBarrier barrier = GetColorBufferBarrier(draw_rt);
const VkDependencyFlags barrier_flags = GetColorBufferBarrierFlags();
u32 p = 0;
u32 n = 0;
@ -6034,7 +5993,7 @@ void GSDeviceVK::SendHWDraw(const GSHWDrawConfig& config, GSTextureVK* draw_rt,
for (; n < draw_list_size; n++)
{
vkCmdPipelineBarrier(GetCurrentCommandBuffer(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, barrier_flags, 0, nullptr, 0, nullptr, 1, &barrier);
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1, &barrier);
const u32 count = (*config.drawlist)[n] * indices_per_prim;
DrawIndexedPrimitive(p, count);
@ -6047,7 +6006,6 @@ void GSDeviceVK::SendHWDraw(const GSHWDrawConfig& config, GSTextureVK* draw_rt,
if (m_features.texture_barrier && m_pipeline_selector.ps.IsFeedbackLoop())
{
const VkImageMemoryBarrier barrier = GetColorBufferBarrier(draw_rt);
const VkDependencyFlags barrier_flags = GetColorBufferBarrierFlags();
if (config.require_full_barrier)
{
@ -6067,7 +6025,7 @@ void GSDeviceVK::SendHWDraw(const GSHWDrawConfig& config, GSTextureVK* draw_rt,
for (; p < config.nindices; p += indices_per_prim)
{
vkCmdPipelineBarrier(GetCurrentCommandBuffer(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, barrier_flags, 0, nullptr, 0, nullptr, 1, &barrier);
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1, &barrier);
DrawIndexedPrimitive(p, indices_per_prim);
}
@ -6079,7 +6037,7 @@ void GSDeviceVK::SendHWDraw(const GSHWDrawConfig& config, GSTextureVK* draw_rt,
{
g_perfmon.Put(GSPerfMon::Barriers, 1);
vkCmdPipelineBarrier(GetCurrentCommandBuffer(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, barrier_flags, 0, nullptr, 0, nullptr, 1, &barrier);
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1, &barrier);
}
}

View File

@ -39,7 +39,6 @@ public:
bool vk_ext_memory_budget : 1;
bool vk_ext_calibrated_timestamps : 1;
bool vk_ext_rasterization_order_attachment_access : 1;
bool vk_ext_attachment_feedback_loop_layout : 1;
bool vk_ext_full_screen_exclusive : 1;
bool vk_ext_line_rasterization : 1;
bool vk_khr_driver_properties : 1;
@ -56,13 +55,6 @@ public:
__fi const VkPhysicalDeviceProperties& GetDeviceProperties() const { return m_device_properties; }
__fi const OptionalExtensions& GetOptionalExtensions() const { return m_optional_extensions; }
// The interaction between raster order attachment access and fbfetch is unclear.
__fi bool UseFeedbackLoopLayout() const
{
return (m_optional_extensions.vk_ext_attachment_feedback_loop_layout &&
!m_optional_extensions.vk_ext_rasterization_order_attachment_access);
}
// Helpers for getting constants
__fi u32 GetBufferCopyOffsetAlignment() const
{
@ -593,7 +585,6 @@ public:
void UpdateHWPipelineSelector(GSHWDrawConfig& config, PipelineSelector& pipe);
void UploadHWDrawVerticesAndIndices(const GSHWDrawConfig& config);
VkImageMemoryBarrier GetColorBufferBarrier(GSTextureVK* rt) const;
VkDependencyFlags GetColorBufferBarrierFlags() const;
void SendHWDraw(const GSHWDrawConfig& config, GSTextureVK* draw_rt, bool skip_first_barrier);
//////////////////////////////////////////////////////////////////////////

View File

@ -32,15 +32,7 @@ static VkImageLayout GetVkImageLayout(GSTextureVK::Layout layout)
VK_IMAGE_LAYOUT_GENERAL, // ComputeReadWriteImage
VK_IMAGE_LAYOUT_GENERAL, // General
}};
return (layout == GSTextureVK::Layout::FeedbackLoop && GSDeviceVK::GetInstance()->UseFeedbackLoopLayout()) ?
VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT :
s_vk_layout_mapping[static_cast<u32>(layout)];
}
static VkAccessFlagBits GetFeedbackLoopInputAccessBits()
{
return GSDeviceVK::GetInstance()->UseFeedbackLoopLayout() ? VK_ACCESS_SHADER_READ_BIT :
VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
return s_vk_layout_mapping[static_cast<u32>(layout)];
}
GSTextureVK::GSTextureVK(Type type, Format format, int width, int height, int levels, VkImage image,
@ -99,22 +91,16 @@ std::unique_ptr<GSTextureVK> GSTextureVK::Create(Type type, Format format, int w
case Type::RenderTarget:
{
pxAssert(levels == 1);
ici.usage =
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT |
(GSDeviceVK::GetInstance()->UseFeedbackLoopLayout() ? VK_IMAGE_USAGE_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT :
VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT);
ici.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
}
break;
case Type::DepthStencil:
{
pxAssert(levels == 1);
ici.usage =
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT |
(GSDeviceVK::GetInstance()->UseFeedbackLoopLayout() ? VK_IMAGE_USAGE_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT :
0);
ici.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
vci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
}
break;
@ -640,7 +626,7 @@ void GSTextureVK::TransitionSubresourcesToLayout(
case Layout::FeedbackLoop:
barrier.srcAccessMask = (aspect == VK_IMAGE_ASPECT_COLOR_BIT) ?
(VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
GetFeedbackLoopInputAccessBits()) :
VK_ACCESS_INPUT_ATTACHMENT_READ_BIT) :
(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT);
srcStageMask = (aspect == VK_IMAGE_ASPECT_COLOR_BIT) ?
@ -716,7 +702,7 @@ void GSTextureVK::TransitionSubresourcesToLayout(
case Layout::FeedbackLoop:
barrier.dstAccessMask = (aspect == VK_IMAGE_ASPECT_COLOR_BIT) ?
(VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
GetFeedbackLoopInputAccessBits()) :
VK_ACCESS_INPUT_ATTACHMENT_READ_BIT) :
(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT);
dstStageMask = (aspect == VK_IMAGE_ASPECT_COLOR_BIT) ?