From 485c21eac3adbc29258da09a16cc8067aaa9b366 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 19 Dec 2019 01:43:29 -0300 Subject: [PATCH] vk_shader_decompiler: Normalize output fragment attachments Some games write from fragment shaders to an unexistant framebuffer attachment or they don't write to one when it exists in the framebuffer. Fix this by skipping writes or adding zeroes. --- .../renderer_vulkan/vk_shader_decompiler.cpp | 21 ++++++++----------- .../renderer_vulkan/vk_shader_decompiler.h | 3 +++ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp index 93e2704b4..c84f9e4be 100644 --- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp +++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp @@ -543,7 +543,7 @@ private: } for (u32 rt = 0; rt < static_cast(frag_colors.size()); ++rt) { - if (!IsRenderTargetUsed(rt)) { + if (!specialization.enabled_rendertargets[rt]) { continue; } @@ -1868,12 +1868,18 @@ private: // rendertargets/components are skipped in the register assignment. u32 current_reg = 0; for (u32 rt = 0; rt < Maxwell::NumRenderTargets; ++rt) { + if (!specialization.enabled_rendertargets[rt]) { + // Skip rendertargets that are not enabled + continue; + } // TODO(Subv): Figure out how dual-source blending is configured in the Switch. for (u32 component = 0; component < 4; ++component) { + const Id pointer = AccessElement(t_out_float, frag_colors.at(rt), component); if (header.ps.IsColorComponentOutputEnabled(rt, component)) { - OpStore(AccessElement(t_out_float, frag_colors.at(rt), component), - SafeGetRegister(current_reg)); + OpStore(pointer, SafeGetRegister(current_reg)); ++current_reg; + } else { + OpStore(pointer, component == 3 ? v_float_one : v_float_zero); } } } @@ -2003,15 +2009,6 @@ private: return DeclareBuiltIn(builtin, spv::StorageClass::Input, type, std::move(name)); } - bool IsRenderTargetUsed(u32 rt) const { - for (u32 component = 0; component < 4; ++component) { - if (header.ps.IsColorComponentOutputEnabled(rt, component)) { - return true; - } - } - return false; - } - template Id AccessElement(Id pointer_type, Id composite, Args... elements_) { std::vector members; diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.h b/src/video_core/renderer_vulkan/vk_shader_decompiler.h index 2b01321b6..415801b6c 100644 --- a/src/video_core/renderer_vulkan/vk_shader_decompiler.h +++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.h @@ -101,6 +101,9 @@ struct Specialization final { Maxwell::TessellationSpacing spacing{}; bool clockwise{}; } tessellation; + + // Fragment specific + std::bitset<8> enabled_rendertargets; }; // Old gcc versions don't consider this trivially copyable. // static_assert(std::is_trivially_copyable_v);