Skip to content

Commit

Permalink
rsx/fp: Discard shaders with undefined (non-existent) writes. On nvid…
Browse files Browse the repository at this point in the history
…ia+vulkan, undefined writes autofill with blue color
  • Loading branch information
kd-11 committed Feb 16, 2018
1 parent b67f28e commit a64bea1
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 1 deletion.
73 changes: 72 additions & 1 deletion rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,78 @@ template<typename T> std::string FragmentProgramDecompiler::GetSRC(T src)

std::string FragmentProgramDecompiler::BuildCode()
{
//main += fmt::format("\tgl_FragColor = %c0;\n", m_ctrl & 0x40 ? 'r' : 'h');
//Scan if any outputs are available
const bool use_32_bit_exports = !!(m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS);
const bool exports_depth = !!(m_ctrl & CELL_GCM_SHADER_CONTROL_DEPTH_EXPORT);
const std::set<std::string> output_values =
{
(use_32_bit_exports) ? "r0" : "h0",
"r1",
(use_32_bit_exports) ? "r2" : "h4",
(use_32_bit_exports) ? "r3" : "h6",
(use_32_bit_exports) ? "r4" : "h8",
};

bool gather_output_registers = true;
const auto float4_name = getFloatTypeName(4);
for (auto &v : output_values)
{
if (m_parr.HasParam(PF_PARAM_NONE, float4_name, v))
{
gather_output_registers = false;
break;
}
}

//Explicitly discard on encountering null shaders
if (gather_output_registers)
{
bool has_any_output = false;
bool first_output_exists = false;

if (use_32_bit_exports || exports_depth)
{
for (int reg = 0; reg < 5; ++reg)
{
if (reg == 1 && !exports_depth)
continue;

const std::string half_register = "h" + std::to_string(reg + 1);
if (m_parr.HasParam(PF_PARAM_NONE, float4_name, half_register))
{
has_any_output = true;
if (!reg) first_output_exists = true;

const std::string this_register = "r" + std::to_string(reg);
AddReg(reg, 0);
AddCode("//Register gather because output was not specified");
AddCode(this_register + ".zw = gather(" + half_register + ");");
}
}
}

if (!has_any_output)
{
properties.has_no_output = true;

LOG_ERROR(RSX, "Invalid fragment shader: No output register was updated!");

//Comment out main block as it is now useless
main = "/*\n" + main + "*/\n";
AddCode("//No output, manually abort writes (nvidia+vulkan writes garbage otherwise)");
AddCode("discard;");
}
else
{
//Requires gather operation for output...
properties.has_gather_op = true;

if (!first_output_exists)
{
LOG_WARNING(RSX, "Fragment shader does not write to first RTT and has no explicit output registers");
}
}
}

std::stringstream OS;
insertHeader(OS);
Expand Down
1 change: 1 addition & 0 deletions rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ class FragmentProgramDecompiler
bool has_lit_op = false;
bool has_gather_op = false;
bool has_wpos_input = false;
bool has_no_output = false;
}
properties;

Expand Down

0 comments on commit a64bea1

Please sign in to comment.