From f8e8e2f624199adf5e994f1b20deab9b0ee05923 Mon Sep 17 00:00:00 2001 From: DH Date: Sat, 7 Jun 2014 17:15:49 +0300 Subject: [PATCH] Improved Fragment Shader Decompiler - Implemented LIT, RFL, LIF, BRK, IF, LOOP, REP - Fixed KIL, RCP, RSQ, DP2A Implemented fmt::replace_first & fmt::replace_all --- Utilities/StrFmt.cpp | 23 +++ Utilities/StrFmt.h | 53 ++++- rpcs3/Emu/GS/GL/GLFragmentProgram.cpp | 283 +++++++++++++++++--------- rpcs3/Emu/GS/GL/GLFragmentProgram.h | 26 ++- rpcs3/Emu/GS/GL/GLGSRender.cpp | 2 +- rpcs3/Emu/GS/GL/GLVertexProgram.cpp | 6 +- 6 files changed, 294 insertions(+), 99 deletions(-) diff --git a/Utilities/StrFmt.cpp b/Utilities/StrFmt.cpp index fc469c7b79..2bd595992d 100644 --- a/Utilities/StrFmt.cpp +++ b/Utilities/StrFmt.cpp @@ -31,6 +31,29 @@ std::string fmt::FormatV(std::string fmt, va_list args) return str; } +std::string replace_first(const std::string& src, const std::string& from, const std::string& to) +{ + auto pos = src.find(from); + + if (pos == std::string::npos) + { + return src; + } + + return (pos ? src.substr(0, pos) + to : to) + std::string(src.c_str() + pos + from.length()); +} + +std::string replace_all(std::string src, const std::string& from, const std::string& to) +{ + for (auto pos = src.find(from); pos != std::string::npos; src.find(from, pos + 1)) + { + src = (pos ? src.substr(0, pos) + to : to) + std::string(src.c_str() + pos + from.length()); + pos += to.length(); + } + + return src; +} + //convert a wxString to a std::string encoded in utf8 //CAUTION, only use this to interface with wxWidgets classes std::string fmt::ToUTF8(const wxString& right) diff --git a/Utilities/StrFmt.h b/Utilities/StrFmt.h index 744d6ea189..9116c26227 100644 --- a/Utilities/StrFmt.h +++ b/Utilities/StrFmt.h @@ -76,7 +76,7 @@ namespace fmt{ //wrapper to deal with advance sprintf formating options with automatic length finding template - string Format(const string &fmt, Args&& ... parameters) + string Format(const string &fmt, Args ... parameters) { size_t length = 256; string str; @@ -98,6 +98,57 @@ namespace fmt{ return str; } + std::string replace_first(const std::string& src, const std::string& from, const std::string& to); + std::string replace_all(std::string src, const std::string& from, const std::string& to); + + template + std::string replace_all(std::string src, const std::pair(&list)[list_size]) + { + for (size_t pos = 0; pos < src.length(); ++pos) + { + for (size_t i = 0; i < list_size; ++i) + { + const size_t comp_length = list[i].first.length(); + + if (src.length() - pos < comp_length) + continue; + + if (src.substr(pos, comp_length) == list[i].first) + { + src = (pos ? src.substr(0, pos) + list[i].second : list[i].second) + std::string(src.c_str() + pos + comp_length); + pos += list[i].second.length(); + break; + } + } + } + + return src; + } + + template + std::string replace_all(std::string src, const std::pair>(&list)[list_size]) + { + for (size_t pos = 0; pos < src.length(); ++pos) + { + for (size_t i = 0; i < list_size; ++i) + { + const size_t comp_length = list[i].first.length(); + + if (src.length() - pos < comp_length) + continue; + + if (src.substr(pos, comp_length) == list[i].first) + { + src = (pos ? src.substr(0, pos) + list[i].second() : list[i].second()) + std::string(src.c_str() + pos + comp_length); + pos += list[i].second().length(); + break; + } + } + } + + return src; + } + //convert a wxString to a std::string encoded in utf8 //CAUTION, only use this to interface with wxWidgets classes std::string ToUTF8(const wxString& right); diff --git a/rpcs3/Emu/GS/GL/GLFragmentProgram.cpp b/rpcs3/Emu/GS/GL/GLFragmentProgram.cpp index d6edee385f..995a16112d 100644 --- a/rpcs3/Emu/GS/GL/GLFragmentProgram.cpp +++ b/rpcs3/Emu/GS/GL/GLFragmentProgram.cpp @@ -4,7 +4,7 @@ #include "Emu/System.h" #include "GLFragmentProgram.h" -void GLFragmentDecompilerThread::AddCode(std::string code, bool append_mask) +void GLFragmentDecompilerThread::SetDst(std::string code, bool append_mask) { if(!src0.exec_if_eq && !src0.exec_if_gr && !src0.exec_if_lt) return; @@ -13,59 +13,23 @@ void GLFragmentDecompilerThread::AddCode(std::string code, bool append_mask) if(!src0.exec_if_gr || !src0.exec_if_lt || !src0.exec_if_eq) { - static const char f[4] = {'x', 'y', 'z', 'w'}; - - std::string swizzle; - swizzle += f[src0.cond_swizzle_x]; - swizzle += f[src0.cond_swizzle_y]; - swizzle += f[src0.cond_swizzle_z]; - swizzle += f[src0.cond_swizzle_w]; - swizzle = swizzle == "xyzw" ? "" : "." + swizzle; - - if(src0.exec_if_gr && src0.exec_if_eq) - { - cond = "greaterThanEqual"; - } - else if(src0.exec_if_lt && src0.exec_if_eq) - { - cond = "lessThanEqual"; - } - else if(src0.exec_if_gr && src0.exec_if_lt) - { - cond = "notEqual"; - } - else if(src0.exec_if_gr) - { - cond = "greaterThan"; - } - else if(src0.exec_if_lt) - { - cond = "lessThan"; - } - else //if(src0.exec_if_eq) - { - cond = "equal"; - } - - cond = "if(all(" + cond + "(" + AddCond(dst.no_dest) + swizzle + ", vec4(0.0)))) "; + cond = "if(" + GetCond() + ") "; } - if(src1.scale) + switch(src1.scale) { - switch(src1.scale) - { - case 1: code = "(" + code + " * 2)"; break; - case 2: code = "(" + code + " * 4)"; break; - case 3: code = "(" + code + " * 8)"; break; - case 5: code = "(" + code + " / 2)"; break; - case 6: code = "(" + code + " / 4)"; break; - case 7: code = "(" + code + " / 8)"; break; + case 0: break; + case 1: code = "(" + code + " * 2.0)"; break; + case 2: code = "(" + code + " * 4.0)"; break; + case 3: code = "(" + code + " * 8.0)"; break; + case 5: code = "(" + code + " / 2.0)"; break; + case 6: code = "(" + code + " / 4.0)"; break; + case 7: code = "(" + code + " / 8.0)"; break; - default: - ConLog.Error("Bad scale: %d", fmt::by_value(src1.scale)); - Emu.Pause(); - break; - } + default: + ConLog.Error("Bad scale: %d", fmt::by_value(src1.scale)); + Emu.Pause(); + break; } if(dst.saturate) @@ -87,9 +51,12 @@ void GLFragmentDecompilerThread::AddCode(std::string code, bool append_mask) dest = AddReg(dst.dest_reg, dst.fp16); } - code = cond + (dest.length() ? dest + mask + " = " : "") + code + (append_mask ? mask : ""); + AddCode(cond + (dest.length() ? dest + mask + " = " : "") + code + (append_mask ? mask : "") + ";"); +} - main += "\t" + code + ";\n"; +void GLFragmentDecompilerThread::AddCode(const std::string& code) +{ + main.append(m_code_level, '\t') += Format(code) + "\n"; } std::string GLFragmentDecompilerThread::GetMask() @@ -125,7 +92,7 @@ std::string GLFragmentDecompilerThread::AddReg(u32 index, int fp16) bool GLFragmentDecompilerThread::HasReg(u32 index, int fp16) { - return m_parr.HasParam((index >= 2 && index <= 4) ? PARAM_OUT : PARAM_NONE, "vec4", + return m_parr.HasParam(PARAM_NONE, "vec4", std::string(fp16 ? "h" : "r") + std::to_string(index)); } @@ -159,6 +126,70 @@ std::string GLFragmentDecompilerThread::AddTex() return m_parr.AddParam(PARAM_UNIFORM, "sampler2D", std::string("tex") + std::to_string(dst.tex_num)); } +std::string GLFragmentDecompilerThread::Format(std::string code) +{ + const std::pair> repl_list[] = + { + { "$$", []() -> std::string { return "$"; } }, + { "$0", std::bind(std::mem_fn(&GLFragmentDecompilerThread::GetSRC), this, src0) }, + { "$1", std::bind(std::mem_fn(&GLFragmentDecompilerThread::GetSRC), this, src1) }, + { "$2", std::bind(std::mem_fn(&GLFragmentDecompilerThread::GetSRC), this, src2) }, + { "$t", std::bind(std::mem_fn(&GLFragmentDecompilerThread::AddTex), this) }, + { "$cond", std::bind(std::mem_fn(&GLFragmentDecompilerThread::GetCond), this) }, + { "$c", std::bind(std::mem_fn(&GLFragmentDecompilerThread::AddConst), this) } + }; + + return fmt::replace_all(code, repl_list); +} + +std::string GLFragmentDecompilerThread::GetCond() +{ + if (src0.exec_if_gr && src0.exec_if_lt && src0.exec_if_eq) + { + return "true"; + } + else if (!src0.exec_if_gr && !src0.exec_if_lt && !src0.exec_if_eq) + { + return "false"; + } + + static const char f[4] = { 'x', 'y', 'z', 'w' }; + + std::string swizzle, cond; + swizzle += f[src0.cond_swizzle_x]; + swizzle += f[src0.cond_swizzle_y]; + swizzle += f[src0.cond_swizzle_z]; + swizzle += f[src0.cond_swizzle_w]; + swizzle = swizzle == "xyzw" ? "" : "." + swizzle; + + if (src0.exec_if_gr && src0.exec_if_eq) + { + cond = "greaterThanEqual"; + } + else if (src0.exec_if_lt && src0.exec_if_eq) + { + cond = "lessThanEqual"; + } + else if (src0.exec_if_gr && src0.exec_if_lt) + { + cond = "notEqual"; + } + else if (src0.exec_if_gr) + { + cond = "greaterThan"; + } + else if (src0.exec_if_lt) + { + cond = "lessThan"; + } + else //if(src0.exec_if_eq) + { + cond = "equal"; + } + + return "any(" + cond + "(" + AddCond(dst.no_dest) + swizzle + ", vec4(0.0)))"; +} + template std::string GLFragmentDecompilerThread::GetSRC(T src) { std::string ret = ""; @@ -227,7 +258,21 @@ template std::string GLFragmentDecompilerThread::GetSRC(T src) std::string GLFragmentDecompilerThread::BuildCode() { //main += fmt::Format("\tgl_FragColor = %c0;\n", m_ctrl & 0x40 ? 'r' : 'h'); - main += "\t" + m_parr.AddParam(PARAM_OUT, "vec4", "ocol", 0) + " = " + (m_ctrl & 0x40 ? "r0" : "h0") + ";\n"; + static const std::pair table[] = + { + { "ocol0", m_ctrl & 0x40 ? "r0" : "h0" }, + { "ocol1", m_ctrl & 0x40 ? "r1" : "h2" }, + { "ocol2", m_ctrl & 0x40 ? "r2" : "h4" }, + { "ocol3", m_ctrl & 0x40 ? "r3" : "h6" }, + { "ocol4", m_ctrl & 0x40 ? "r4" : "h8" }, + }; + + for (int i = 0; i < sizeof(table) / sizeof(*table); ++i) + { + if (m_parr.HasParam(PARAM_NONE, "vec4", table[i].second)) + AddCode(m_parr.AddParam(PARAM_OUT, "vec4", table[i].first, i) + " = " + table[i].second + ";"); + } + if(m_ctrl & 0xe) main += "\tgl_FragDepth = r1.z;\n"; std::string p; @@ -248,9 +293,33 @@ void GLFragmentDecompilerThread::Task() mem32_ptr_t data(m_addr); m_size = 0; m_location = 0; + m_loop_count = 0; + m_code_level = 1; while(true) { + auto finded = std::find(m_end_offsets.begin(), m_end_offsets.end(), m_size); + + if (finded != m_end_offsets.end()) + { + m_end_offsets.erase(finded); + m_code_level--; + AddCode("}"); + m_loop_count--; + } + + finded = std::find(m_else_offsets.begin(), m_else_offsets.end(), m_size); + + if (finded != m_else_offsets.end()) + { + m_else_offsets.erase(finded); + m_code_level--; + AddCode("}"); + AddCode("else"); + AddCode("{"); + m_code_level++; + } + dst.HEX = GetData(data[0]); src0.HEX = GetData(data[1]); src1.HEX = GetData(data[2]); @@ -263,46 +332,46 @@ void GLFragmentDecompilerThread::Task() switch(opcode) { case 0x00: break; //NOP - case 0x01: AddCode(GetSRC(src0)); break; //MOV - case 0x02: AddCode("(" + GetSRC(src0) + " * " + GetSRC(src1) + ")"); break; //MUL - case 0x03: AddCode("(" + GetSRC(src0) + " + " + GetSRC(src1) + ")"); break; //ADD - case 0x04: AddCode("(" + GetSRC(src0) + " * " + GetSRC(src1) + " + " + GetSRC(src2) + ")"); break; //MAD - case 0x05: AddCode("vec2(dot(" + GetSRC(src0) + ".xyz, " + GetSRC(src1) + ".xyz), 0).xxxx"); break; // DP3 - case 0x06: AddCode("vec2(dot(" + GetSRC(src0) + ", " + GetSRC(src1) + "), 0).xxxx"); break; // DP4 - case 0x07: AddCode("vec2(distance(" + GetSRC(src0) + ", " + GetSRC(src1) + "), 0).xxxx"); break; // DST - case 0x08: AddCode("min(" + GetSRC(src0) + ", " + GetSRC(src1) + ")"); break; // MIN - case 0x09: AddCode("max(" + GetSRC(src0) + ", " + GetSRC(src1) + ")"); break; // MAX - case 0x0a: AddCode("vec4(lessThan(" + GetSRC(src0) + ", " + GetSRC(src1) + "))"); break; // SLT - case 0x0b: AddCode("vec4(greaterThanEqual(" + GetSRC(src0) + ", " + GetSRC(src1) + "))"); break; // SGE - case 0x0c: AddCode("vec4(lessThanEqual(" + GetSRC(src0) + ", " + GetSRC(src1) + "))"); break; // SLE - case 0x0d: AddCode("vec4(greaterThan(" + GetSRC(src0) + ", " + GetSRC(src1) + "))"); break; // SGT - case 0x0e: AddCode("vec4(notEqual(" + GetSRC(src0) + ", " + GetSRC(src1) + "))"); break; // SNE - case 0x0f: AddCode("vec4(equal(" + GetSRC(src0) + ", " + GetSRC(src1) + "))"); break; // SEQ + case 0x01: SetDst("$0"); break; //MOV + case 0x02: SetDst("($0 * $1)"); break; //MUL + case 0x03: SetDst("($0 + $1)"); break; //ADD + case 0x04: SetDst("($0 * $1 + $2)"); break; //MAD + case 0x05: SetDst("vec2(dot($0.xyz, $1.xyz), 0).xxxx"); break; // DP3 + case 0x06: SetDst("vec2(dot($0, $1), 0).xxxx"); break; // DP4 + case 0x07: SetDst("vec2(distance($0, $1), 0).xxxx"); break; // DST + case 0x08: SetDst("min($0, $1)"); break; // MIN + case 0x09: SetDst("max($0, $1)"); break; // MAX + case 0x0a: SetDst("vec4(lessThan($0, $1))"); break; // SLT + case 0x0b: SetDst("vec4(greaterThanEqual($0, $1))"); break; // SGE + case 0x0c: SetDst("vec4(lessThanEqual($0, $1))"); break; // SLE + case 0x0d: SetDst("vec4(greaterThan($0, $1))"); break; // SGT + case 0x0e: SetDst("vec4(notEqual($0, $1))"); break; // SNE + case 0x0f: SetDst("vec4(equal($0, $1))"); break; // SEQ - case 0x10: AddCode("fract(" + GetSRC(src0) + ")"); break; // FRC - case 0x11: AddCode("floor(" + GetSRC(src0) + ")"); break; // FLR - //case 0x12: AddCode("clip(" + GetSRC(src0) + ")"); break; // KIL (kill fragment) + case 0x10: SetDst("fract($0)"); break; // FRC + case 0x11: SetDst("floor($0)"); break; // FLR + case 0x12: SetDst("discard"); break; // KIL (kill fragment) //case 0x13: break; // PK4 (pack four signed 8-bit values) //case 0x14: break; // UP4 (unpack four signed 8-bit values) - case 0x15: AddCode("dFdx(" + GetSRC(src0) + ")"); break; // DDX - case 0x16: AddCode("dFdy(" + GetSRC(src0) + ")"); break; // DDY - case 0x17: AddCode("texture(" + AddTex() + ", " + GetSRC(src0) + ".xy)"); break; // TEX (texture lookup) + case 0x15: SetDst("dFdx($0)"); break; // DDX + case 0x16: SetDst("dFdy($0)"); break; // DDY + case 0x17: SetDst("texture($t, $0.xy)"); break; // TEX (texture lookup) //case 0x18: break; // TXP (projective texture lookup) //case 0x19: break; // TXD (texture lookup with derivatives) - case 0x1a: AddCode("1 / (" + GetSRC(src0) + ")"); break; // RCP - case 0x1b: AddCode("inversesqrt(" + GetSRC(src0) + ")"); break; // RSQ - case 0x1c: AddCode("exp2(" + GetSRC(src0) + ")"); break; // EX2 - case 0x1d: AddCode("log2(" + GetSRC(src0) + ")"); break; // LG2 - //case 0x1e: break; // LIT (compute light coefficients) - case 0x1f: AddCode("(" + GetSRC(src0) + " * (" + GetSRC(src1) + " - " + GetSRC(src2) + ") +" + GetSRC(src2) + ")"); break; // LRP (linear interpolation) + case 0x1a: SetDst("(1 / $0)"); break; // RCP + case 0x1b: SetDst("inversesqrt(abs($0))"); break; // RSQ + case 0x1c: SetDst("exp2($0)"); break; // EX2 + case 0x1d: SetDst("log2($0)"); break; // LG2 + case 0x1e: SetDst("vec4(1.0, $0.x, ($0.x > 0 ? exp($0.w * log($0.y)) : 0.0), 1.0)"); break; // LIT (compute light coefficients) + case 0x1f: SetDst("($0 * ($1 - $2) + $2)"); break; // LRP (linear interpolation) - case 0x20: AddCode("vec4(equal(" + GetSRC(src0) + ", vec4(1)))"); break; // STR (set on true) - case 0x21: AddCode("vec4(equal(" + GetSRC(src0) + ", vec4(0)))"); break; // SFL (set on false) - case 0x22: AddCode("cos(" + GetSRC(src0) + ")"); break; // COS - case 0x23: AddCode("sin(" + GetSRC(src0) + ")"); break; // SIN + case 0x20: SetDst("vec4(equal($0, vec4(1.0)))"); break; // STR (set on true) + case 0x21: SetDst("vec4(equal($0, vec4(0.0)))"); break; // SFL (set on false) + case 0x22: SetDst("cos($0)"); break; // COS + case 0x23: SetDst("sin($0)"); break; // SIN //case 0x24: break; // PK2 (pack two 16-bit floats) //case 0x25: break; // UP2 (unpack two 16-bit floats) - case 0x26: AddCode("pow(" + GetSRC(src0) + ", " + GetSRC(src1) +")"); break; // POW + case 0x26: SetDst("pow($0, $1)"); break; // POW //case 0x27: break; // PKB //case 0x28: break; // UPB //case 0x29: break; // PK16 @@ -310,7 +379,7 @@ void GLFragmentDecompilerThread::Task() //case 0x2b: break; // BEM //case 0x2c: break; // PKG //case 0x2d: break; // UPG - case 0x2e: AddCode("(" + GetSRC(src0) + " * " + GetSRC(src1) + " + " + GetSRC(src0) + " * " + GetSRC(src1) + " + " + GetSRC(src2) + ")"); break; // DP2A (2-component dot product and add) + case 0x2e: SetDst("($0.x * $1.x + $0.y * $1.y + $2.x)"); break; // DP2A (2-component dot product and add) //case 0x2f: break; // TXL (texture lookup with LOD) //case 0x30: break; @@ -318,16 +387,44 @@ void GLFragmentDecompilerThread::Task() //case 0x33: break; // TEXBEM //case 0x34: break; // TXPBEM //case 0x35: break; // BEMLUM - //case 0x36: break; // RFL (reflection vector) + case 0x36: SetDst("($0 - 2.0 * $1 * dot($0, $1))"); break; // RFL (reflection vector) //case 0x37: break; // TIMESWTEX - case 0x38: AddCode("vec2(dot(" + GetSRC(src0) + ".xy, " + GetSRC(src1) + ".xy)).xxxx"); break; // DP2 - case 0x39: AddCode("normalize(" + GetSRC(src0) + ".xyz)"); break; // NRM - case 0x3a: AddCode("(" + GetSRC(src0) + " / " + GetSRC(src1) + ")"); break; // DIV - case 0x3b: AddCode("(" + GetSRC(src0) + " / sqrt(" + GetSRC(src1) + "))"); break; // DIVSQ - //case 0x3c: break; // LIF + case 0x38: SetDst("vec2(dot($0.xy, $1.xy)).xxxx"); break; // DP2 + case 0x39: SetDst("normalize($0.xyz)"); break; // NRM + case 0x3a: SetDst("($0 / $1)"); break; // DIV + case 0x3b: SetDst("($0 / sqrt($1))"); break; // DIVSQ + case 0x3c: SetDst("vec4(1.0, $0.y, ($0.y > 0 ? pow(2.0, $0.w) : 0.0), 1.0)"); break; // LIF case 0x3d: break; // FENCT case 0x3e: break; // FENCB + case 0x40: SetDst("break"); break; //BRK + //case 0x41: break; //CAL + case 0x42: + AddCode("if($cond)"); //IF + m_else_offsets.push_back(src1.else_offset << 2); + m_end_offsets.push_back(src2.end_offset << 2); + AddCode("{"); + m_code_level++; + break; + + case 0x43: //LOOP + AddCode(fmt::Format("if($cond) for(int i%u = %u; i%u < %u; i%u += %u) //LOOP", + m_loop_count, src1.rep2, m_loop_count, src1.rep1, m_loop_count, src1.rep3)); + m_loop_count++; + m_end_offsets.push_back(src2.end_offset << 2); + AddCode("{"); + m_code_level++; + break; + case 0x44: //REP + AddCode(fmt::Format("if($cond) for(int i%u = %u; i%u < %u; i%u += %u) //REP", + m_loop_count, src1.rep2, m_loop_count, src1.rep1, m_loop_count, src1.rep3)); + m_loop_count++; + m_end_offsets.push_back(src2.end_offset << 2); + AddCode("{"); + m_code_level++; + break; + //case 0x45: SetDst("return"); break; //RET + default: ConLog.Error("Unknown fp opcode 0x%x (inst %d)", opcode, m_size / (4 * 4)); //Emu.Pause(); diff --git a/rpcs3/Emu/GS/GL/GLFragmentProgram.h b/rpcs3/Emu/GS/GL/GLFragmentProgram.h index 77397ae3da..9148444886 100644 --- a/rpcs3/Emu/GS/GL/GLFragmentProgram.h +++ b/rpcs3/Emu/GS/GL/GLFragmentProgram.h @@ -75,12 +75,29 @@ struct GLFragmentDecompilerThread : public ThreadBase u32 scale : 3; u32 opcode_is_branch : 1; }; + + struct + { + u32 else_offset : 31; + u32 : 1; + }; + + struct + { + u32 : 2; + u32 rep1 : 8; + u32 rep2 : 8; + u32 : 1; + u32 rep3 : 8; + }; } src1; union SRC2 { u32 HEX; + u32 end_offset; + struct { u32 reg_type : 2; @@ -107,6 +124,10 @@ struct GLFragmentDecompilerThread : public ThreadBase u32 m_offset; u32 m_location; u32 m_ctrl; + u32 m_loop_count; + int m_code_level; + std::vector m_end_offsets; + std::vector m_else_offsets; GLFragmentDecompilerThread(std::string& shader, GLParamArray& parr, u32 addr, u32& size, u32 ctrl) : ThreadBase("Fragment Shader Decompiler Thread") @@ -123,13 +144,16 @@ struct GLFragmentDecompilerThread : public ThreadBase std::string GetMask(); - void AddCode(std::string code, bool append_mask = true); + void SetDst(std::string code, bool append_mask = true); + void AddCode(const std::string& code); std::string AddReg(u32 index, int fp16); bool HasReg(u32 index, int fp16); std::string AddCond(int fp16); std::string AddConst(); std::string AddTex(); + std::string Format(std::string code); + std::string GetCond(); template std::string GetSRC(T src); std::string BuildCode(); diff --git a/rpcs3/Emu/GS/GL/GLGSRender.cpp b/rpcs3/Emu/GS/GL/GLGSRender.cpp index b8aa47e6ad..6a3ad40d37 100644 --- a/rpcs3/Emu/GS/GL/GLGSRender.cpp +++ b/rpcs3/Emu/GS/GL/GLGSRender.cpp @@ -372,7 +372,7 @@ void GLGSRender::InitFragmentData() checkForGlError("glGetUniformLocation " + name); glUniform4f(l, c.x, c.y, c.z, c.w); - checkForGlError("glUniform4f " + name + fmt::Format(" %d [%f %f %f %f]", l, c.x, c.y, c.z, c.w)); + checkForGlError("glUniform4f " + name + fmt::Format(" %u [%f %f %f %f]", l, c.x, c.y, c.z, c.w)); } //if(m_fragment_constants.GetCount()) diff --git a/rpcs3/Emu/GS/GL/GLVertexProgram.cpp b/rpcs3/Emu/GS/GL/GLVertexProgram.cpp index 3847469ade..a9fbd960b7 100644 --- a/rpcs3/Emu/GS/GL/GLVertexProgram.cpp +++ b/rpcs3/Emu/GS/GL/GLVertexProgram.cpp @@ -192,7 +192,7 @@ void GLVertexDecompilerThread::AddCode(bool is_sca, const std::string& pCode, bo swizzle = swizzle == "xyzw" ? "" : "." + swizzle; - cond = fmt::Format("if(all(%s(rc%s, vec4(0.0)%s))) ", cond_string_table[d0.cond], swizzle.c_str(), swizzle.c_str()); + cond = fmt::Format("if(any(%s(rc%s, vec4(0.0)%s))) ", cond_string_table[d0.cond], swizzle.c_str(), swizzle.c_str()); } std::string mask = GetMask(is_sca); @@ -372,10 +372,10 @@ void GLVertexDecompilerThread::Task() case 0x01: AddScaCode(GetSRC(2, true)); break; // MOV case 0x02: AddScaCode("1.0 / " + GetSRC(2, true)); break; // RCP case 0x03: AddScaCode("clamp(1.0 / " + GetSRC(2, true) + ", 5.42101e-20, 1.884467e19)"); break; // RCC - case 0x04: AddScaCode("inversesqrt(" + GetSRC(2, true) + ")"); break; // RSQ + case 0x04: AddScaCode("inversesqrt(abs(" + GetSRC(2, true) + "))"); break; // RSQ case 0x05: AddScaCode("exp(" + GetSRC(2, true) + ")"); break; // EXP case 0x06: AddScaCode("log(" + GetSRC(2, true) + ")"); break; // LOG - //case 0x07: break; // LIT + //case 0x07: AddVecCode("vec4(1.0, max(0.0, " + GetSRC(2, true) + ".x), ((" + GetSRC(2, true) + ".x > 0) ? pow(max(0.0, " + GetSRC(2, true) + ".y), " + GetSRC(2, true) + ".z) : 0), 1.0)"); break; // LIT case 0x08: AddScaCode("{ /*BRA*/ " + GetFunc() + "; return; }", false, true); break; // BRA case 0x09: AddScaCode("{ " + GetFunc() + "; return; }", false, true); break; // BRI : works differently (BRI o[1].x(TR) L0;) case 0x0a: AddScaCode("/*CAL*/ " + GetFunc(), false, true); break; // CAL : works same as BRI