mirror of
https://git.suyu.dev/suyu/suyu.git
synced 2024-11-25 22:57:22 +00:00
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:
parent
79e0991d9b
commit
1690f1adba
3 changed files with 16 additions and 19 deletions
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
OpStore(pointer, SafeGetRegister(current_reg));
|
|
||||||
++current_reg;
|
|
||||||
} else {
|
|
||||||
OpStore(pointer, component == 3 ? v_float_one : v_float_zero);
|
|
||||||
}
|
}
|
||||||
|
const Id pointer = AccessElement(t_out_float, frag_colors[rt], component);
|
||||||
|
OpStore(pointer, SafeGetRegister(current_reg));
|
||||||
|
++current_reg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (header.ps.omap.depth) {
|
if (header.ps.omap.depth) {
|
||||||
|
|
|
@ -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>);
|
||||||
|
|
Loading…
Reference in a new issue