From 1f7a1e40783882d32cd7f6a247cf691ae9af37cc Mon Sep 17 00:00:00 2001 From: Vincent Lejeune Date: Sun, 31 Jan 2016 20:01:00 +0100 Subject: [PATCH] rsx/common/d3d12/gl: Fix lit and rsq behavior near 0 in vertex shaders. --- .../RSX/Common/FragmentProgramDecompiler.cpp | 2 +- .../RSX/Common/VertexProgramDecompiler.cpp | 6 ++-- rpcs3/Emu/RSX/D3D12/D3D12CommonDecompiler.cpp | 36 +++++++++++++++++++ rpcs3/Emu/RSX/D3D12/D3D12CommonDecompiler.h | 2 ++ .../D3D12/D3D12FragmentProgramDecompiler.cpp | 18 +--------- .../D3D12/D3D12VertexProgramDecompiler.cpp | 2 ++ rpcs3/Emu/RSX/GL/GLCommonDecompiler.cpp | 36 +++++++++++++++++++ rpcs3/Emu/RSX/GL/GLCommonDecompiler.h | 1 + rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp | 17 +-------- rpcs3/Emu/RSX/GL/GLVertexProgram.cpp | 2 ++ 10 files changed, 85 insertions(+), 37 deletions(-) diff --git a/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.cpp b/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.cpp index 1781969e69..108944b901 100644 --- a/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.cpp +++ b/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.cpp @@ -404,7 +404,7 @@ bool FragmentProgramDecompiler::handle_scb(u32 opcode) case RSX_FP_OPCODE_EX2: SetDst("exp2($0.xxxx)"); return true; case RSX_FP_OPCODE_FLR: SetDst("floor($0)"); return true; case RSX_FP_OPCODE_FRC: SetDst(getFunction(FUNCTION::FUNCTION_FRACT)); return true; - case RSX_FP_OPCODE_LIT: SetDst(getFloatTypeName(4) + "(1.0, $0.x, ($0.x > 0.0 ? exp($0.w * log2($0.y)) : 0.0), 1.0)"); return true; + case RSX_FP_OPCODE_LIT: SetDst("lit_legacy($0)"); return true; case RSX_FP_OPCODE_LIF: SetDst(getFloatTypeName(4) + "(1.0, $0.y, ($0.y > 0 ? pow(2.0, $0.w) : 0.0), 1.0)"); return true; case RSX_FP_OPCODE_LRP: LOG_ERROR(RSX, "Unimplemented SCB instruction: LRP"); return true; // TODO: Is this in the right category? case RSX_FP_OPCODE_LG2: SetDst("log2($0.xxxx)"); return true; diff --git a/rpcs3/Emu/RSX/Common/VertexProgramDecompiler.cpp b/rpcs3/Emu/RSX/Common/VertexProgramDecompiler.cpp index 0ca3cfd5d8..3b0e156868 100644 --- a/rpcs3/Emu/RSX/Common/VertexProgramDecompiler.cpp +++ b/rpcs3/Emu/RSX/Common/VertexProgramDecompiler.cpp @@ -562,10 +562,10 @@ std::string VertexProgramDecompiler::Decompile() case RSX_SCA_OPCODE_MOV: SetDSTSca("$s"); break; case RSX_SCA_OPCODE_RCP: SetDSTSca("(1.0 / $s)"); break; case RSX_SCA_OPCODE_RCC: SetDSTSca("clamp(1.0 / $s, 5.42101e-20, 1.884467e19)"); break; - case RSX_SCA_OPCODE_RSQ: SetDSTSca("(1.f / sqrt($s))"); break; + case RSX_SCA_OPCODE_RSQ: SetDSTSca("rsq_legacy($s)"); break; case RSX_SCA_OPCODE_EXP: SetDSTSca("exp($s)"); break; case RSX_SCA_OPCODE_LOG: SetDSTSca("log($s)"); break; - case RSX_SCA_OPCODE_LIT: SetDSTSca(getFloatTypeName(4) + "(1.0, $s.x, ($s.x > 0.0 ? exp($s.w * log2($s.y)) : 0.0), 1.0)"); break; + case RSX_SCA_OPCODE_LIT: SetDSTSca("lit_legacy($s)"); break; case RSX_SCA_OPCODE_BRA: { AddCode("$if ($cond)"); @@ -619,7 +619,7 @@ std::string VertexProgramDecompiler::Decompile() // works like BRI but shorter (RET o[1].x(TR);) AddCode("$ifcond return;"); break; - case RSX_SCA_OPCODE_LG2: SetDSTSca("log2($s)"); break; + case RSX_SCA_OPCODE_LG2: SetDSTSca("log2_legacy($s)"); break; case RSX_SCA_OPCODE_EX2: SetDSTSca("exp2($s)"); break; case RSX_SCA_OPCODE_SIN: SetDSTSca("sin($s)"); break; case RSX_SCA_OPCODE_COS: SetDSTSca("cos($s)"); break; diff --git a/rpcs3/Emu/RSX/D3D12/D3D12CommonDecompiler.cpp b/rpcs3/Emu/RSX/D3D12/D3D12CommonDecompiler.cpp index 2063a83a74..d5721cb1ed 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12CommonDecompiler.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12CommonDecompiler.cpp @@ -93,4 +93,40 @@ std::string compareFunctionImp(COMPARE f, const std::string &Op0, const std::str return "(" + Op0 + " != " + Op1 + ")"; } } + +void insert_d3d12_legacy_function(std::ostream& OS) +{ + OS << "float4 divsq_legacy(float4 num, float4 denum)\n"; + OS << "{\n"; + OS << " return num / sqrt(max(denum.xxxx, 1.E-10));\n"; + OS << "}\n"; + + OS << "float4 rcp_legacy(float4 denum)\n"; + OS << "{\n"; + OS << " return 1. / denum;\n"; + OS << "}\n"; + + OS << "float4 rsq_legacy(float4 val)\n"; + OS << "{\n"; + OS << " return float(1.0 / sqrt(max(val.x, 1.E-10))).xxxx;\n"; + OS << "}\n\n"; + + OS << "float4 log2_legacy(float4 val)\n"; + OS << "{\n"; + OS << " return log2(max(val.x, 1.E-10)).xxxx;\n"; + OS << "}\n\n"; + + OS << "float4 lit_legacy(float4 val)"; + OS << "{\n"; + OS << " float4 clamped_val = val;\n"; + OS << " clamped_val.x = max(val.x, 0);\n"; + OS << " clamped_val.y = max(val.y, 0);\n"; + OS << " float4 result;\n"; + OS << " result.x = 1.0;\n"; + OS << " result.w = 1.;\n"; + OS << " result.y = clamped_val.x;\n"; + OS << " result.z = clamped_val.x > 0.0 ? exp(clamped_val.w * log(max(clamped_val.y, 1.E-10))) : 0.0;\n"; + OS << " return result;\n"; + OS << "}\n\n"; +} #endif diff --git a/rpcs3/Emu/RSX/D3D12/D3D12CommonDecompiler.h b/rpcs3/Emu/RSX/D3D12/D3D12CommonDecompiler.h index 5aeaba5325..7f088418e4 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12CommonDecompiler.h +++ b/rpcs3/Emu/RSX/D3D12/D3D12CommonDecompiler.h @@ -5,3 +5,5 @@ std::string getFloatTypeNameImp(size_t elementCount); std::string getFunctionImp(FUNCTION f); std::string compareFunctionImp(COMPARE f, const std::string &Op0, const std::string &Op1); + +void insert_d3d12_legacy_function(std::ostream&); diff --git a/rpcs3/Emu/RSX/D3D12/D3D12FragmentProgramDecompiler.cpp b/rpcs3/Emu/RSX/D3D12/D3D12FragmentProgramDecompiler.cpp index f305fc6cd7..bfb47c14bf 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12FragmentProgramDecompiler.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12FragmentProgramDecompiler.cpp @@ -143,23 +143,7 @@ void D3D12FragmentDecompiler::insertConstants(std::stringstream & OS) void D3D12FragmentDecompiler::insertMainStart(std::stringstream & OS) { - // "lib" function - // 0.00001 is used as "some non zero very little number" - OS << "float4 divsq_legacy(float4 num, float4 denum)\n"; - OS << "{\n"; - OS << " return num / sqrt(max(denum.xxxx, 0.00001));\n"; - OS << "}\n"; - - OS << "float4 rcp_legacy(float4 denum)\n"; - OS << "{\n"; - OS << " return 1. / denum;\n"; - OS << "}\n"; - - OS << "float4 rsq_legacy(float4 denum)\n"; - OS << "{\n"; - OS << " return 1. / sqrt(max(denum, 0.00001));\n"; - OS << "}\n"; - + insert_d3d12_legacy_function(OS); const std::set output_value = { diff --git a/rpcs3/Emu/RSX/D3D12/D3D12VertexProgramDecompiler.cpp b/rpcs3/Emu/RSX/D3D12/D3D12VertexProgramDecompiler.cpp index f8f1d375be..53d44fbed7 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12VertexProgramDecompiler.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12VertexProgramDecompiler.cpp @@ -176,6 +176,8 @@ namespace void D3D12VertexProgramDecompiler::insertMainStart(std::stringstream & OS) { + insert_d3d12_legacy_function(OS); + OS << "PixelInput main(uint vertex_id : SV_VertexID)" << std::endl; OS << "{" << std::endl; diff --git a/rpcs3/Emu/RSX/GL/GLCommonDecompiler.cpp b/rpcs3/Emu/RSX/GL/GLCommonDecompiler.cpp index b88d544c9f..e28942aff1 100644 --- a/rpcs3/Emu/RSX/GL/GLCommonDecompiler.cpp +++ b/rpcs3/Emu/RSX/GL/GLCommonDecompiler.cpp @@ -84,3 +84,39 @@ std::string compareFunctionImpl(COMPARE f, const std::string &Op0, const std::st } throw EXCEPTION("Unknow compare function"); } + +void insert_glsl_legacy_function(std::ostream& OS) +{ + OS << "vec4 divsq_legacy(vec4 num, vec4 denum)\n"; + OS << "{\n"; + OS << " return num / sqrt(max(denum.xxxx, 1.E-10));\n"; + OS << "}\n"; + + OS << "vec4 rcp_legacy(vec4 denum)\n"; + OS << "{\n"; + OS << " return 1. / denum;\n"; + OS << "}\n"; + + OS << "vec4 rsq_legacy(vec4 val)\n"; + OS << "{\n"; + OS << " return float(1.0 / sqrt(max(val.x, 1.E-10))).xxxx;\n"; + OS << "}\n\n"; + + OS << "vec4 log2_legacy(vec4 val)\n"; + OS << "{\n"; + OS << " return log2(max(val.x, 1.E-10)).xxxx;\n"; + OS << "}\n\n"; + + OS << "vec4 lit_legacy(vec4 val)"; + OS << "{\n"; + OS << " vec4 clamped_val = val;\n"; + OS << " clamped_val.x = max(val.x, 0);\n"; + OS << " clamped_val.y = max(val.y, 0);\n"; + OS << " vec4 result;\n"; + OS << " result.x = 1.0;\n"; + OS << " result.w = 1.;\n"; + OS << " result.y = clamped_val.x;\n"; + OS << " result.z = clamped_val.x > 0.0 ? exp(clamped_val.w * log(max(clamped_val.y, 1.E-10))) : 0.0;\n"; + OS << " return result;\n"; + OS << "}\n\n"; +} diff --git a/rpcs3/Emu/RSX/GL/GLCommonDecompiler.h b/rpcs3/Emu/RSX/GL/GLCommonDecompiler.h index cee0d9b11c..6d4c11473a 100644 --- a/rpcs3/Emu/RSX/GL/GLCommonDecompiler.h +++ b/rpcs3/Emu/RSX/GL/GLCommonDecompiler.h @@ -4,3 +4,4 @@ std::string getFloatTypeNameImpl(size_t elementCount); std::string getFunctionImpl(FUNCTION f); std::string compareFunctionImpl(COMPARE f, const std::string &Op0, const std::string &Op1); +void insert_glsl_legacy_function(std::ostream& OS); \ No newline at end of file diff --git a/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp b/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp index e05cbb1b32..3ef0038315 100644 --- a/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp +++ b/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp @@ -101,22 +101,7 @@ void GLFragmentDecompilerThread::insertConstants(std::stringstream & OS) void GLFragmentDecompilerThread::insertMainStart(std::stringstream & OS) { - // "lib" function - // 0.00001 is used as "some non zero very little number" - OS << "vec4 divsq_legacy(vec4 num, vec4 denum)\n"; - OS << "{\n"; - OS << " return num / sqrt(max(denum.xxxx, 0.00001));\n"; - OS << "}\n"; - - OS << "vec4 rcp_legacy(vec4 denum)\n"; - OS << "{\n"; - OS << " return 1. / denum;\n"; - OS << "}\n"; - - OS << "vec4 rsq_legacy(vec4 denum)\n"; - OS << "{\n"; - OS << " return 1. / sqrt(max(denum, 0.00001));\n"; - OS << "}\n"; + insert_glsl_legacy_function(OS); OS << "void main ()" << std::endl; OS << "{" << std::endl; diff --git a/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp b/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp index c448f48091..b5e3b31f5f 100644 --- a/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp +++ b/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp @@ -158,6 +158,8 @@ void add_input(std::stringstream & OS, const ParamItem &PI, const std::vector