vk_shader_decompiler: Disable default values on unwritten render targets

Some games like The Legend of Zelda: Breath of the Wild assign
render targets without writing them from the fragment shader. This
generates Vulkan validation errors, so silence these I previously
introduced a commit to set "vec4(0, 0, 0, 1)" for these attachments. The
problem is that this is not what games expect. This commit reverts that
change.
This commit is contained in:
ReinUsesLisp 2020-01-24 01:15:50 -03:00
parent 79e0991d9b
commit 1690f1adba
3 changed files with 16 additions and 19 deletions

View file

@ -325,9 +325,6 @@ VKPipelineCache::DecompileShaders(const GraphicsPipelineCacheKey& key) {
specialization.tessellation.primitive = fixed_state.tessellation.primitive; specialization.tessellation.primitive = fixed_state.tessellation.primitive;
specialization.tessellation.spacing = fixed_state.tessellation.spacing; specialization.tessellation.spacing = fixed_state.tessellation.spacing;
specialization.tessellation.clockwise = fixed_state.tessellation.clockwise; specialization.tessellation.clockwise = fixed_state.tessellation.clockwise;
for (const auto& rt : key.renderpass_params.color_attachments) {
specialization.enabled_rendertargets.set(rt.index);
}
SPIRVProgram program; SPIRVProgram program;
std::vector<vk::DescriptorSetLayoutBinding> bindings; std::vector<vk::DescriptorSetLayoutBinding> bindings;

View file

@ -542,11 +542,10 @@ private:
return; return;
} }
for (u32 rt = 0; rt < static_cast<u32>(frag_colors.size()); ++rt) { for (u32 rt = 0; rt < static_cast<u32>(std::size(frag_colors)); ++rt) {
if (!specialization.enabled_rendertargets[rt]) { if (!IsRenderTargetEnabled(rt)) {
continue; continue;
} }
const Id id = AddGlobalVariable(OpVariable(t_out_float4, spv::StorageClass::Output)); const Id id = AddGlobalVariable(OpVariable(t_out_float4, spv::StorageClass::Output));
Name(id, fmt::format("frag_color{}", rt)); Name(id, fmt::format("frag_color{}", rt));
Decorate(id, spv::Decoration::Location, rt); Decorate(id, spv::Decoration::Location, rt);
@ -852,6 +851,15 @@ private:
return binding; return binding;
} }
bool IsRenderTargetEnabled(u32 rt) const {
for (u32 component = 0; component < 4; ++component) {
if (header.ps.IsColorComponentOutputEnabled(rt, component)) {
return true;
}
}
return false;
}
bool IsInputAttributeArray() const { bool IsInputAttributeArray() const {
return stage == ShaderType::TesselationControl || stage == ShaderType::TesselationEval || return stage == ShaderType::TesselationControl || stage == ShaderType::TesselationEval ||
stage == ShaderType::Geometry; stage == ShaderType::Geometry;
@ -1889,19 +1897,14 @@ 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)) { continue;
}
const Id pointer = AccessElement(t_out_float, frag_colors[rt], component);
OpStore(pointer, SafeGetRegister(current_reg)); OpStore(pointer, SafeGetRegister(current_reg));
++current_reg; ++current_reg;
} else {
OpStore(pointer, component == 3 ? v_float_one : v_float_zero);
}
} }
} }
if (header.ps.omap.depth) { if (header.ps.omap.depth) {

View file

@ -102,9 +102,6 @@ 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>);