diff --git a/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.cpp b/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.cpp index 482f5ea390..0831194f15 100644 --- a/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.cpp +++ b/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.cpp @@ -319,11 +319,6 @@ std::string FragmentProgramDecompiler::BuildCode() { //main += fmt::format("\tgl_FragColor = %c0;\n", m_ctrl & 0x40 ? 'r' : 'h'); - if (m_ctrl & 0xe) - { - main += m_ctrl & 0x40 ? "\tgl_FragDepth = r1.z;\n" : "\tgl_FragDepth = h0.z;\n"; - } - std::stringstream OS; insertHeader(OS); OS << std::endl; diff --git a/rpcs3/Emu/RSX/D3D12/D3D12FragmentProgramDecompiler.cpp b/rpcs3/Emu/RSX/D3D12/D3D12FragmentProgramDecompiler.cpp index ef46afafc5..8e5daf93ee 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12FragmentProgramDecompiler.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12FragmentProgramDecompiler.cpp @@ -88,10 +88,10 @@ void D3D12FragmentDecompiler::insertOutputs(std::stringstream & OS) OS << "{" << std::endl; const std::pair table[] = { - { "ocol0", m_ctrl & 0x40 ? "r0" : "h0" }, - { "ocol1", m_ctrl & 0x40 ? "r2" : "h4" }, - { "ocol2", m_ctrl & 0x40 ? "r3" : "h6" }, - { "ocol3", m_ctrl & 0x40 ? "r4" : "h8" }, + { "ocol0", m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS ? "r0" : "h0" }, + { "ocol1", m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS ? "r2" : "h4" }, + { "ocol2", m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS ? "r3" : "h6" }, + { "ocol3", m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS ? "r4" : "h8" }, }; for (int i = 0; i < sizeof(table) / sizeof(*table); ++i) @@ -99,6 +99,8 @@ void D3D12FragmentDecompiler::insertOutputs(std::stringstream & OS) if (m_parr.HasParam(PF_PARAM_NONE, "float4", table[i].second)) OS << " " << "float4" << " " << table[i].first << " : SV_TARGET" << i << ";" << std::endl; } + if (m_ctrl & CELL_GCM_SHADER_CONTROL_DEPTH_EXPORT) + OS << " float depth : SV_Depth;" << std::endl; OS << "};" << std::endl; } @@ -166,19 +168,27 @@ void D3D12FragmentDecompiler::insertMainEnd(std::stringstream & OS) { const std::pair table[] = { - { "ocol0", m_ctrl & 0x40 ? "r0" : "h0" }, - { "ocol1", m_ctrl & 0x40 ? "r2" : "h4" }, - { "ocol2", m_ctrl & 0x40 ? "r3" : "h6" }, - { "ocol3", m_ctrl & 0x40 ? "r4" : "h8" }, + { "ocol0", m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS ? "r0" : "h0" }, + { "ocol1", m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS ? "r2" : "h4" }, + { "ocol2", m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS ? "r3" : "h6" }, + { "ocol3", m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS ? "r4" : "h8" }, }; OS << " PixelOutput Out;" << std::endl; + size_t num_output = 0; for (int i = 0; i < sizeof(table) / sizeof(*table); ++i) { if (m_parr.HasParam(PF_PARAM_NONE, "float4", table[i].second)) + { OS << " Out." << table[i].first << " = " << table[i].second << ";" << std::endl; + num_output++; + } } - OS << " if (isAlphaTested && Out.ocol0.a <= alphaRef) discard;" << std::endl; + if (m_ctrl & CELL_GCM_SHADER_CONTROL_DEPTH_EXPORT) + OS << " Out.depth = " << ((m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS) ? "r1.z;" : "h0.z;") << std::endl; + // Shaders don't always output colors (for instance if they write to depth only) + if (num_output > 0) + OS << " if (isAlphaTested && Out.ocol0.a <= alphaRef) discard;" << std::endl; OS << " return Out;" << std::endl; OS << "}" << std::endl; } diff --git a/rpcs3/Emu/RSX/GCM.h b/rpcs3/Emu/RSX/GCM.h index 16d9fe09cd..156b69837c 100644 --- a/rpcs3/Emu/RSX/GCM.h +++ b/rpcs3/Emu/RSX/GCM.h @@ -454,6 +454,12 @@ enum CELL_GCM_FALSE = 0 }; +enum +{ + CELL_GCM_SHADER_CONTROL_DEPTH_EXPORT = 0xe, ///< shader program exports the depth of the shaded fragment + CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS = 0x40 ///< shader program exports 32 bits registers values (instead of 16 bits ones) +}; + // GCM Reports enum { diff --git a/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp b/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp index 3ece495c60..2bf09ea511 100644 --- a/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp +++ b/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp @@ -5,6 +5,7 @@ #include "GLFragmentProgram.h" #include "GLCommonDecompiler.h" +#include "../GCM.h" std::string GLFragmentDecompilerThread::getFloatTypeName(size_t elementCount) { @@ -44,10 +45,10 @@ void GLFragmentDecompilerThread::insertOutputs(std::stringstream & OS) { const std::pair table[] = { - { "ocol0", m_ctrl & 0x40 ? "r0" : "h0" }, - { "ocol1", m_ctrl & 0x40 ? "r2" : "h4" }, - { "ocol2", m_ctrl & 0x40 ? "r3" : "h6" }, - { "ocol3", m_ctrl & 0x40 ? "r4" : "h8" }, + { "ocol0", m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS ? "r0" : "h0" }, + { "ocol1", m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS ? "r2" : "h4" }, + { "ocol2", m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS ? "r3" : "h6" }, + { "ocol3", m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS ? "r4" : "h8" }, }; for (int i = 0; i < sizeof(table) / sizeof(*table); ++i) @@ -103,10 +104,10 @@ void GLFragmentDecompilerThread::insertMainEnd(std::stringstream & OS) { const std::pair table[] = { - { "ocol0", m_ctrl & 0x40 ? "r0" : "h0" }, - { "ocol1", m_ctrl & 0x40 ? "r2" : "h4" }, - { "ocol2", m_ctrl & 0x40 ? "r3" : "h6" }, - { "ocol3", m_ctrl & 0x40 ? "r4" : "h8" }, + { "ocol0", m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS ? "r0" : "h0" }, + { "ocol1", m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS ? "r2" : "h4" }, + { "ocol2", m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS ? "r3" : "h6" }, + { "ocol3", m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS ? "r4" : "h8" }, }; for (int i = 0; i < sizeof(table) / sizeof(*table); ++i) @@ -115,6 +116,9 @@ void GLFragmentDecompilerThread::insertMainEnd(std::stringstream & OS) OS << " " << table[i].first << " = " << table[i].second << ";" << std::endl; } + if (m_ctrl & CELL_GCM_SHADER_CONTROL_DEPTH_EXPORT) + OS << ((m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS) ? "\tgl_FragDepth = r1.z;\n" : "\tgl_FragDepth = h0.z;\n") << std::endl; + OS << "}" << std::endl; }