Browse Source

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.
nce_cpp
ReinUsesLisp 6 years ago
parent
commit
a328090680
  1. 21
      src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
  2. 3
      src/video_core/renderer_vulkan/vk_shader_decompiler.h

21
src/video_core/renderer_vulkan/vk_shader_decompiler.cpp

@ -543,7 +543,7 @@ private:
}
for (u32 rt = 0; rt < static_cast<u32>(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 <typename... Args>
Id AccessElement(Id pointer_type, Id composite, Args... elements_) {
std::vector<Id> members;

3
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<Specialization>);

Loading…
Cancel
Save