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.
This commit is contained in:
parent
abb33d4aec
commit
485c21eac3
|
@ -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>);
|
||||||
|
|
Reference in New Issue