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.
master
ReinUsesLisp 2019-12-19 01:43:29 +07:00
parent abb33d4aec
commit 485c21eac3
No known key found for this signature in database
GPG Key ID: 2DFC508897B39CFE
2 changed files with 12 additions and 12 deletions

@ -543,7 +543,7 @@ private:
} }
for (u32 rt = 0; rt < static_cast<u32>(frag_colors.size()); ++rt) { for (u32 rt = 0; rt < static_cast<u32>(frag_colors.size()); ++rt) {
if (!IsRenderTargetUsed(rt)) { if (!specialization.enabled_rendertargets[rt]) {
continue; continue;
} }
@ -1868,12 +1868,18 @@ private:
// rendertargets/components are skipped in the register assignment. // rendertargets/components are skipped in the register assignment.
u32 current_reg = 0; u32 current_reg = 0;
for (u32 rt = 0; rt < Maxwell::NumRenderTargets; ++rt) { 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. // TODO(Subv): Figure out how dual-source blending is configured in the Switch.
for (u32 component = 0; component < 4; ++component) { 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)) { if (header.ps.IsColorComponentOutputEnabled(rt, component)) {
OpStore(AccessElement(t_out_float, frag_colors.at(rt), component), OpStore(pointer, SafeGetRegister(current_reg));
SafeGetRegister(current_reg));
++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)); 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 <typename... Args> template <typename... Args>
Id AccessElement(Id pointer_type, Id composite, Args... elements_) { Id AccessElement(Id pointer_type, Id composite, Args... elements_) {
std::vector<Id> members; std::vector<Id> members;

@ -101,6 +101,9 @@ struct Specialization final {
Maxwell::TessellationSpacing spacing{}; Maxwell::TessellationSpacing spacing{};
bool clockwise{}; bool clockwise{};
} tessellation; } tessellation;
// Fragment specific
std::bitset<8> enabled_rendertargets;
}; };
// Old gcc versions don't consider this trivially copyable. // Old gcc versions don't consider this trivially copyable.
// static_assert(std::is_trivially_copyable_v<Specialization>); // static_assert(std::is_trivially_copyable_v<Specialization>);