diff --git a/Utilities/Array.h b/Utilities/Array.h index 02c80417c8..0f7df002de 100644 --- a/Utilities/Array.h +++ b/Utilities/Array.h @@ -141,7 +141,7 @@ public: virtual void SetCount(const u32 count, bool memzero = true) { if(m_count >= count) return; - + _InsertRoomEnd(count - m_count); if(memzero) memset(m_array + m_count - count, 0, sizeof(T) * (m_count - count)); diff --git a/rpcs3/Emu/Cell/PPCDecoder.h b/rpcs3/Emu/Cell/PPCDecoder.h index 053a30c2d1..81e24087dd 100644 --- a/rpcs3/Emu/Cell/PPCDecoder.h +++ b/rpcs3/Emu/Cell/PPCDecoder.h @@ -381,7 +381,11 @@ public: , m_parent(nullptr) , m_opcode(-1) { - memset(m_instrs, 0, sizeof(InstrCaller*) * count); + for(int i=0; i*) * count); } @@ -413,6 +417,14 @@ public: void set_error_func(InstrCaller* error_func) { + for(int i=0; i* instr = m_instrs[entry]; - - if(instr) - { - (*instr)(op, code); - } - else if(m_error_func) - { - (*m_error_func)(op, code); - } + (*m_instrs[entry])(op, code); } virtual void operator ()(TO* op, u32 code) const diff --git a/rpcs3/Emu/Cell/PPUInterpreter.h b/rpcs3/Emu/Cell/PPUInterpreter.h index 86d012636c..9125b4a43a 100644 --- a/rpcs3/Emu/Cell/PPUInterpreter.h +++ b/rpcs3/Emu/Cell/PPUInterpreter.h @@ -3564,7 +3564,7 @@ private: } void FNEG(u32 frd, u32 frb, bool rc) { - CPU.FPR[frd] = -CPU.FPR[frb]; + CPU.FPR[frd] = ((u64&)CPU.FPR[frb]) ^ (1ULL << 63); if(rc) UNK("fneg.");//CPU.UpdateCR1(CPU.FPR[frd]); } void FMR(u32 frd, u32 frb, bool rc) diff --git a/rpcs3/Emu/GS/GL/FragmentProgram.cpp b/rpcs3/Emu/GS/GL/FragmentProgram.cpp index a2678419ff..5ae2e41e9a 100644 --- a/rpcs3/Emu/GS/GL/FragmentProgram.cpp +++ b/rpcs3/Emu/GS/GL/FragmentProgram.cpp @@ -3,10 +3,38 @@ void FragmentDecompilerThread::AddCode(wxString code) { - if(!src0.exec_if_eq && !src0.exec_if_gr && !src0.exec_if_le) return; - if(!src0.exec_if_eq || !src0.exec_if_gr || !src0.exec_if_le) + if(!src0.exec_if_eq && !src0.exec_if_gr && !src0.exec_if_lt) return; + + wxString cond; + + if(src0.exec_if_gr) { - ConLog.Error("Bad cond! eq: %d gr: %d le: %d", src0.exec_if_eq, src0.exec_if_gr, src0.exec_if_le); + cond = ">"; + } + else if(src0.exec_if_lt) + { + cond = "<"; + } + else if(src0.exec_if_eq) + { + cond = "="; + } + + if(src0.exec_if_eq) + { + cond += "="; + } + else + { + if(src0.exec_if_gr && src0.exec_if_lt) + { + cond = "!="; + } + } + + if(cond) + { + ConLog.Error("cond! [eq: %d gr: %d lt: %d] (%s)", src0.exec_if_eq, src0.exec_if_gr, src0.exec_if_lt, cond); Emu.Pause(); return; } @@ -29,7 +57,7 @@ void FragmentDecompilerThread::AddCode(wxString code) } } - code = AddReg(dst.dest_reg) + GetMask() + " = " + code + GetMask(); + code = AddReg(dst.dest_reg, dst.fp16) + GetMask() + " = " + code + GetMask(); main += "\t" + code + ";\n"; } @@ -46,20 +74,29 @@ wxString FragmentDecompilerThread::GetMask() return ret.IsEmpty() || ret == "xyzw" ? wxEmptyString : ("." + ret); } -wxString FragmentDecompilerThread::AddReg(u32 index) +wxString FragmentDecompilerThread::AddReg(u32 index, int fp16) { //if(!index) return "gl_FragColor"; - return m_parr.AddParam(index ? PARAM_NONE : PARAM_OUT, "vec4", wxString::Format("r%d", index), index ? -1 : 0); + return m_parr.AddParam(index ? PARAM_NONE : PARAM_OUT, "vec4", + wxString::Format((fp16 ? "h%d" : "r%d"), index), (index || fp16) ? -1 : 0); } wxString FragmentDecompilerThread::AddConst() { - return m_parr.AddParam(PARAM_CONST, "vec4", wxString::Format("fc%d", m_const_index++)); + mem32_t data(m_addr + m_size + m_offset); + + m_offset += 4 * 4; + u32 x = GetData(data[0]); + u32 y = GetData(data[1]); + u32 z = GetData(data[2]); + u32 w = GetData(data[3]); + return m_parr.AddParam("vec4", wxString::Format("fc%d", m_const_index++), + wxString::Format("vec4(%f, %f, %f, %f)", (float&)x, (float&)y, (float&)z, (float&)w)); } wxString FragmentDecompilerThread::AddTex() { - return m_parr.AddParam(PARAM_CONST, "sampler2D", wxString::Format("tex_%d", dst.tex_num)); + return m_parr.AddParam(PARAM_UNIFORM, "sampler2D", wxString::Format("tex%d", dst.tex_num)); } template wxString FragmentDecompilerThread::GetSRC(T src) @@ -69,7 +106,7 @@ template wxString FragmentDecompilerThread::GetSRC(T src) switch(src.reg_type) { case 0: //tmp - ret += AddReg(src.tmp_reg_index); + ret += AddReg(src.tmp_reg_index, src.fp16); break; case 1: //input @@ -102,7 +139,6 @@ template wxString FragmentDecompilerThread::GetSRC(T src) break; case 2: //const - ConLog.Write("reg index = %d", src.tmp_reg_index); ret += AddConst(); break; @@ -157,6 +193,8 @@ void FragmentDecompilerThread::Task() src1.HEX = GetData(data[2]); src2.HEX = GetData(data[3]); + m_offset = 4 * 4; + switch(dst.opcode) { case 0x00: break; //NOP @@ -166,24 +204,24 @@ void FragmentDecompilerThread::Task() case 0x04: AddCode("(" + GetSRC(src0) + " * " + GetSRC(src1) + " + " + GetSRC(src2) + ")"); break; //MAD case 0x05: AddCode("dot(" + GetSRC(src0) + ".xyz, " + GetSRC(src1) + ".xyz)"); break; // DP3 case 0x06: AddCode("dot(" + GetSRC(src0) + ", " + GetSRC(src1) + ")"); break; // DP4 - //case 0x07: break; // DST + case 0x07: AddCode("distance(" + GetSRC(src0) + ", " + GetSRC(src1) + ")"); break; // DST case 0x08: AddCode("min(" + GetSRC(src0) + ", " + GetSRC(src1) + ")"); break; // MIN case 0x09: AddCode("max(" + GetSRC(src0) + ", " + GetSRC(src1) + ")"); break; // MAX - //case 0x0a: break; // SLT - //case 0x0b: break; // SGE - //case 0x0c: break; // SLE - //case 0x0d: break; // SGT - //case 0x0e: break; // SNE - //case 0x0f: break; // SEQ + 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 0x10: break; // FRC - //case 0x11: break; // FLR + case 0x10: AddCode("fract(" + GetSRC(src0) + ")"); break; // FRC + case 0x11: AddCode("floor(" + GetSRC(src0) + ")"); break; // FLR //case 0x12: break; // KIL //case 0x13: break; // PK4 //case 0x14: break; // UP4 case 0x15: AddCode("ddx(" + GetSRC(src0) + ")"); break; // DDX case 0x16: AddCode("ddy(" + GetSRC(src0) + ")"); break; // DDY - case 0x17: AddCode("texture(" + AddTex() + ", (" + GetSRC(src0) + ").xy)"); break; //TEX + case 0x17: AddCode("texture(" + AddTex() + ", " + GetSRC(src0) + ".xy)"); break; //TEX //case 0x18: break; // TXP //case 0x19: break; // TXD case 0x1a: AddCode("1 / (" + GetSRC(src0) + ")"); break; // RCP @@ -199,7 +237,7 @@ void FragmentDecompilerThread::Task() case 0x23: AddCode("sin(" + GetSRC(src0) + ")"); break; // SIN //case 0x24: break; // PK2 //case 0x25: break; // UP2 - //case 0x26: break; // POW + case 0x26: AddCode("pow(" + GetSRC(src0) + ", " + GetSRC(src1) +")"); break; // POW //case 0x27: break; // PKB //case 0x28: break; // UPB //case 0x29: break; // PK16 @@ -218,23 +256,23 @@ void FragmentDecompilerThread::Task() //case 0x37: break; // TIMESWTEX //case 0x38: break; // DP2 //case 0x39: break; // NRM - //case 0x3a: break; // DIV - //case 0x3b: break; // DIVSQ + case 0x3a: AddCode("(" + GetSRC(src0) + " / " + GetSRC(src1) + ")"); break; // DIV + case 0x3b: AddCode("(" + GetSRC(src0) + " / " + GetSRC(src1) + ")"); break; // DIVSQ //case 0x3c: break; // LIF - //case 0x3d: break; // FENCT - //case 0x3e: break; // FENCB + case 0x3d: break; // FENCT + case 0x3e: break; // FENCB default: - ConLog.Error("Unknown opcode 0x%x", dst.opcode); + ConLog.Error("Unknown opcode 0x%x (inst %d)", dst.opcode, m_size / (4 * 4)); Emu.Pause(); break; } - m_size += 4 * 4; + m_size += m_offset; if(dst.end) break; - data.SetOffset(4 * 4); + data.SetOffset(m_offset); } m_shader = BuildCode(); diff --git a/rpcs3/Emu/GS/GL/FragmentProgram.h b/rpcs3/Emu/GS/GL/FragmentProgram.h index e3758cd303..09955cbc95 100644 --- a/rpcs3/Emu/GS/GL/FragmentProgram.h +++ b/rpcs3/Emu/GS/GL/FragmentProgram.h @@ -100,6 +100,7 @@ struct FragmentDecompilerThread : public ThreadBase u32 m_addr; u32& m_size; u32 m_const_index; + u32 m_offset; FragmentDecompilerThread(wxString& shader, ParamArray& parr, u32 addr, u32& size) : ThreadBase(false, "Fragment Shader Decompiler Thread") @@ -115,7 +116,7 @@ struct FragmentDecompilerThread : public ThreadBase wxString GetMask(); void AddCode(wxString code); - wxString AddReg(u32 index); + wxString AddReg(u32 index, int fp16); wxString AddConst(); wxString AddTex(); diff --git a/rpcs3/Emu/GS/GL/GLGSRender.cpp b/rpcs3/Emu/GS/GL/GLGSRender.cpp index 4f1cd9973a..686f7f099f 100644 --- a/rpcs3/Emu/GS/GL/GLGSRender.cpp +++ b/rpcs3/Emu/GS/GL/GLGSRender.cpp @@ -1,8 +1,8 @@ #include "stdafx.h" #include "GLGSRender.h" #include "Emu/Cell/PPCInstrTable.h" -#define CMD_DEBUG 1 -#define DUMP_VERTEX_DATA 1 +#define CMD_DEBUG 0 +#define DUMP_VERTEX_DATA 0 #if CMD_DEBUG #define CMD_LOG ConLog.Write @@ -75,8 +75,8 @@ void GLGSFrame::SetViewport(int x, int y, u32 w, u32 h) } GLGSRender::GLGSRender() - : m_frame(NULL) - , m_rsx_thread(NULL) + : m_frame(nullptr) + , m_rsx_thread(nullptr) , m_fp_buf_num(-1) , m_vp_buf_num(-1) { @@ -122,6 +122,12 @@ void GLRSXThread::Task() glEnable(GL_TEXTURE_2D); glSwapInterval(Ini.GSVSyncEnable.GetValue() ? 1 : 0); + for(u32 i=0; iGetTexture(i); + tex.Create(); + } + bool draw = true; u32 drawed = 0; u32 skipped = 0; @@ -172,7 +178,7 @@ void GLRSXThread::Task() continue; } - ConLog.Write("addr = 0x%x", p.m_ioAddress + get); + //ConLog.Write("addr = 0x%x", p.m_ioAddress + get); const u32 cmd = Memory.Read32(p.m_ioAddress + get); const u32 count = (cmd >> 18) & 0x7ff; //if(cmd == 0) continue; @@ -251,6 +257,10 @@ void GLGSRender::Init(const u32 ioAddress, const u32 ioSize, const u32 ctrlAddre m_localAddress = localAddress; m_ctrl = (CellGcmControl*)Memory.GetMemFromAddr(m_ctrlAddress); + m_cur_vertex_prog = nullptr; + m_cur_shader_prog = nullptr; + m_cur_shader_prog_num = 0; + (m_rsx_thread = new GLRSXThread(this))->Start(); } @@ -309,7 +319,7 @@ void GLGSRender::EnableVertexData(bool indexed_draw) wxFile dump("VertexDataArray.dump", wxFile::write); #endif - for(u32 i=0; i<16; ++i) + for(u32 i=0; iconstants4.GetCount(); ++i) + for(u32 i=0; iconstants4[i]; + const TransformConstant& c = m_transform_constants[i]; const wxString& name = wxString::Format("vc%d", c.id); - //const int l = glGetUniformLocation(m_program.id, name); const int l = m_program.GetLocation(name); checkForGlError("glGetUniformLocation " + name); @@ -499,7 +508,9 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 c CMD_LOG("index = %d, offset=0x%x, location=0x%x, cubemap=0x%x, dimension=0x%x, format=0x%x, mipmap=0x%x", index, offset, location, cubemap, dimension, format, mipmap); - tex.SetOffset(GetAddress(offset, location)); + u32 tex_addr = GetAddress(offset, location); + ConLog.Warning("texture addr = 0x%x", tex_addr); + tex.SetOffset(tex_addr); tex.SetFormat(cubemap, dimension, format, mipmap); } break; @@ -810,10 +821,11 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 c case NV4097_SET_COLOR_CLEAR_VALUE: { - const u8 a = (args[0] >> 24) & 0xff; - const u8 r = (args[0] >> 16) & 0xff; - const u8 g = (args[0] >> 8) & 0xff; - const u8 b = args[0] & 0xff; + const u32 color = args[0]; + const u8 a = (color >> 24) & 0xff; + const u8 r = (color >> 16) & 0xff; + const u8 g = (color >> 8) & 0xff; + const u8 b = color & 0xff; CMD_LOG("a=%d, r=%d, g=%d, b=%d", a, r, g, b); glClearColor( (float)r / 255.0f, @@ -825,9 +837,9 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 c case NV4097_SET_SHADER_PROGRAM: { - m_shader_prog.Delete(); - m_shader_prog.addr = GetAddress(args[0] & ~0x3, (args[0] & 0x3) - 1); - //m_program.Delete(); + m_cur_shader_prog = &m_shader_progs[m_cur_shader_prog_num++]; + m_cur_shader_prog->Delete(); + m_cur_shader_prog->addr = GetAddress(args[0] & ~0x3, (args[0] & 0x3) - 1); } break; @@ -850,13 +862,14 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 c case NV4097_SET_TRANSFORM_PROGRAM_LOAD: { - //m_program.Delete(); m_cur_vertex_prog = &m_vertex_progs[args[0]]; m_cur_vertex_prog->Delete(); if(count == 2) { const u32 start = args[1]; + if(start) + ConLog.Warning("NV4097_SET_TRANSFORM_PROGRAM_LOAD: start = %d", start); } } break; @@ -899,12 +912,6 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 c break; } - if(!m_cur_vertex_prog) - { - ConLog.Warning("NV4097_SET_TRANSFORM_CONSTANT_LOAD: m_cur_vertex_prog == NULL"); - break; - } - for(u32 id = args[0], i = 1; iconstants4.AddCpy(c); + m_transform_constants.AddCpy(c); } } break; @@ -1154,13 +1156,20 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 c bool GLGSRender::LoadProgram() { - m_fp_buf_num = m_prog_buffer.SearchFp(m_shader_prog); + if(!m_cur_shader_prog) + { + ConLog.Warning("LoadProgram: m_cur_shader_prog == NULL"); - if(m_fp_buf_num == -1) m_shader_prog.Decompile(); + return false; + } + + m_fp_buf_num = m_prog_buffer.SearchFp(*m_cur_shader_prog); + + if(m_fp_buf_num == -1) m_cur_shader_prog->Decompile(); if(!m_cur_vertex_prog) { - ConLog.Warning("NV4097_SET_BEGIN_END: m_cur_vertex_prog == NULL"); + ConLog.Warning("LoadProgram: m_cur_vertex_prog == NULL"); return false; } @@ -1182,11 +1191,11 @@ bool GLGSRender::LoadProgram() if(m_fp_buf_num == -1) { ConLog.Warning("FP not found in buffer!"); - m_shader_prog.Wait(); - m_shader_prog.Compile(); + m_cur_shader_prog->Wait(); + m_cur_shader_prog->Compile(); wxFile f(wxGetCwd() + "/FragmentProgram.txt", wxFile::write); - f.Write(m_shader_prog.shader); + f.Write(m_cur_shader_prog->shader); } if(m_vp_buf_num == -1) @@ -1203,10 +1212,14 @@ bool GLGSRender::LoadProgram() m_program.id = m_prog_buffer.GetProg(m_fp_buf_num, m_vp_buf_num); } - if(!m_program.id) + if(m_program.id) { - m_program.Create(m_cur_vertex_prog->id, m_shader_prog.id); - m_prog_buffer.Add(m_program, m_shader_prog, *m_cur_vertex_prog); + m_program.Use(); + } + else + { + m_program.Create(m_cur_vertex_prog->id, m_cur_shader_prog->id); + m_prog_buffer.Add(m_program, *m_cur_shader_prog, *m_cur_vertex_prog); m_program.Use(); @@ -1270,7 +1283,12 @@ void GLGSRender::ExecCMD() glDepthRangef(m_clip_min, m_clip_max); } - for(u32 i=0; i<16; ++i) + if(m_indexed_array.m_count && m_draw_array_count) + { + ConLog.Warning("m_indexed_array.m_count && draw_array_count"); + } + + for(u32 i=0; iGetTexture(i); if(!tex.IsEnabled()) continue; @@ -1280,17 +1298,11 @@ void GLGSRender::ExecCMD() tex.Bind(); checkForGlError("tex.Bind"); m_program.SetTex(i); - checkForGlError("m_program.SetTex"); tex.Init(); checkForGlError("tex.Init"); tex.Save(); } - if(m_indexed_array.m_count && m_draw_array_count) - { - ConLog.Warning("m_indexed_array.m_count && draw_array_count"); - } - if(m_indexed_array.m_count) { LoadVertexData(m_indexed_array.index_min, m_indexed_array.index_max - m_indexed_array.index_min + 1); @@ -1347,13 +1359,20 @@ void GLGSRender::ExecCMD() void GLGSRender::Reset() { - m_program.Delete(); - //m_program.id = 0; - m_shader_prog.id = 0; + m_program.UnUse(); + + if(m_cur_shader_prog) + m_cur_shader_prog->id = 0; + if(m_cur_vertex_prog) m_cur_vertex_prog->id = 0; - memset(m_vertex_data, 0, sizeof(VertexData) * 16); + m_cur_shader_prog_num = 0; + m_transform_constants.Clear(); + for(uint i=0; i glGenTextures"); + Bind(); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + } + } + void SetRect(const u32 width, const u32 height) { m_width = width; @@ -68,21 +82,8 @@ public: void Init() { - if(!m_id) - { - glGenTextures(1, &m_id); - checkForGlError("GLTexture::Init() -> glGenTextures"); - glBindTexture(GL_TEXTURE_2D, m_id); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - } - else - { - glBindTexture(GL_TEXTURE_2D, m_id); - } - + Bind(); + ConLog.Warning("texture addr = 0x%x, width = %d, height = %d", m_offset, m_width, m_height); //TODO: safe init checkForGlError("GLTexture::Init() -> glBindTexture"); @@ -106,18 +107,17 @@ public: default: ConLog.Error("Init tex error: Bad tex format (0x%x)", m_format); break; } - //glBindTexture(GL_TEXTURE_2D, 0); + //Unbind(); } void Save(const wxString& name) { if(!m_id || !m_offset) return; - ConLog.Write("start"); u32* alldata = new u32[m_width * m_height]; - glBindTexture(GL_TEXTURE_2D, m_id); - glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, alldata); + Bind(); + glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, alldata); u8* data = new u8[m_width * m_height * 3]; u8* alpha = new u8[m_width * m_height]; @@ -133,7 +133,6 @@ public: *dst_a++ = *src++; } - ConLog.Write("end"); wxImage out; out.Create(m_width, m_height, data, alpha); out.SaveFile(name, wxBITMAP_TYPE_PNG); @@ -160,10 +159,34 @@ public: glBindTexture(GL_TEXTURE_2D, m_id); } + void Unbind() + { + glBindTexture(GL_TEXTURE_2D, 0); + } + void Enable(bool enable) { m_enabled = enable; } bool IsEnabled() const { return m_enabled; } }; +struct TransformConstant +{ + u32 id; + float x, y, z, w; + + TransformConstant() + { + } + + TransformConstant(u32 id, float x, float y, float z, float w) + : id(id) + , x(x) + , y(y) + , z(z) + , w(w) + { + } +}; + struct IndexArrayData { Array m_data; @@ -228,16 +251,25 @@ class GLGSRender , public GSRender , public ExecRSXCMDdata { +public: + static const uint m_vertex_count = 16; + static const uint m_fragment_count = 16; + static const uint m_textures_count = 16; + private: GLRSXThread* m_rsx_thread; IndexArrayData m_indexed_array; - ShaderProgram m_shader_prog; - VertexData m_vertex_data[16]; + ShaderProgram m_shader_progs[m_fragment_count]; + ShaderProgram* m_cur_shader_prog; + int m_cur_shader_prog_num; + VertexData m_vertex_data[m_vertex_count]; Array m_vdata; - VertexProgram m_vertex_progs[16]; + VertexProgram m_vertex_progs[m_vertex_count]; VertexProgram* m_cur_vertex_prog; + Array m_transform_constants; + Program m_program; int m_fp_buf_num; int m_vp_buf_num; diff --git a/rpcs3/Emu/GS/GL/Program.cpp b/rpcs3/Emu/GS/GL/Program.cpp index bc90e28628..9d74358cc0 100644 --- a/rpcs3/Emu/GS/GL/Program.cpp +++ b/rpcs3/Emu/GS/GL/Program.cpp @@ -19,7 +19,9 @@ int Program::GetLocation(const wxString& name) u32 pos = m_locations.Move(new Location()); m_locations[pos].name = name; - return m_locations[pos].loc = glGetUniformLocation(id, name); + m_locations[pos].loc = glGetUniformLocation(id, name); + checkForGlError(wxString::Format("glGetUniformLocation(0x%x, %s)", id, name)); + return m_locations[pos].loc; } bool Program::IsCreated() const @@ -72,6 +74,11 @@ void Program::Create(const u32 vp, const u32 fp) } } +void Program::UnUse() +{ + id = 0; +} + void Program::Use() { glUseProgram(id); @@ -80,8 +87,10 @@ void Program::Use() void Program::SetTex(u32 index) { - glUniform1i(GetLocation(wxString::Format("tex_%d", index)), index); - checkForGlError(wxString::Format("SetTex(%d)", index)); + int loc = GetLocation(wxString::Format("tex%d", index)); + checkForGlError(wxString::Format("GetLocation(tex%d)", index)); + glUniform1i(loc, index); + checkForGlError(wxString::Format("SetTex(%d - %d)", index, loc)); } void Program::Delete() diff --git a/rpcs3/Emu/GS/GL/Program.h b/rpcs3/Emu/GS/GL/Program.h index 4a376414b6..71fb597ff6 100644 --- a/rpcs3/Emu/GS/GL/Program.h +++ b/rpcs3/Emu/GS/GL/Program.h @@ -22,6 +22,7 @@ public: bool IsCreated() const; void Create(const u32 vp, const u32 fp); void Use(); + void UnUse(); void SetTex(u32 index); void Delete(); }; \ No newline at end of file diff --git a/rpcs3/Emu/GS/GL/ProgramBuffer.cpp b/rpcs3/Emu/GS/GL/ProgramBuffer.cpp index ee6a292e73..859bad2bce 100644 --- a/rpcs3/Emu/GS/GL/ProgramBuffer.cpp +++ b/rpcs3/Emu/GS/GL/ProgramBuffer.cpp @@ -8,7 +8,7 @@ int ProgramBuffer::SearchFp(ShaderProgram& fp) if(memcmp(&m_buf[i].fp_data[0], &Memory[fp.addr], m_buf[i].fp_data.GetCount()) != 0) continue; fp.id = m_buf[i].fp_id; - fp.shader = m_buf[i].fp_shader; + fp.shader = m_buf[i].fp_shader.GetPtr(); return i; } @@ -21,10 +21,10 @@ int ProgramBuffer::SearchVp(VertexProgram& vp) for(u32 i=0; i fp_data; Array vp_data; - wxString fp_shader; - wxString vp_shader; + ArrayString fp_shader; + ArrayString vp_shader; }; struct ProgramBuffer diff --git a/rpcs3/Emu/GS/GL/ShaderParam.h b/rpcs3/Emu/GS/GL/ShaderParam.h index f90ba43acc..553d4278a6 100644 --- a/rpcs3/Emu/GS/GL/ShaderParam.h +++ b/rpcs3/Emu/GS/GL/ShaderParam.h @@ -5,18 +5,21 @@ enum ParamFlag { PARAM_IN, PARAM_OUT, + PARAM_UNIFORM, PARAM_CONST, PARAM_NONE, }; struct ParamItem { - wxString name; - wxString location; + ArrayString name; + ArrayString location; + ArrayString value; - ParamItem(const wxString& _name, int _location) + ParamItem(const wxString& _name, int _location, const wxString& _value = wxEmptyString) : name(_name) , location(_location > -1 ? wxString::Format("layout (location = %d) ", _location) : "") + , value(_value) { } }; @@ -24,7 +27,7 @@ struct ParamItem struct ParamType { const ParamFlag flag; - wxString type; + ArrayString type; Array items; ParamType(const ParamFlag _flag, const wxString& _type) @@ -37,7 +40,7 @@ struct ParamType { for(u32 i=0; iSearchName(name)) t->items.Move(new ParamItem(name, -1, value)); + } + else + { + const u32 num = params.GetCount(); + params.Move(new ParamType(PARAM_CONST, type)); + params[num].items.Move(new ParamItem(name, -1, value)); + } + + return name; + } + wxString AddParam(const ParamFlag flag, wxString type, const wxString& name, int location = -1) { type = GetParamFlag(flag) + type; diff --git a/rpcs3/Emu/GS/GL/VertexProgram.cpp b/rpcs3/Emu/GS/GL/VertexProgram.cpp index 9938ad184f..7a9bcfcfb4 100644 --- a/rpcs3/Emu/GS/GL/VertexProgram.cpp +++ b/rpcs3/Emu/GS/GL/VertexProgram.cpp @@ -1,28 +1,36 @@ #include "stdafx.h" #include "VertexProgram.h" -wxString VertexDecompilerThread::GetVecMask() +wxString VertexDecompilerThread::GetMask(bool is_sca) { wxString ret = wxEmptyString; - if(d3.vec_writemask_x) ret += "x"; - if(d3.vec_writemask_y) ret += "y"; - if(d3.vec_writemask_z) ret += "z"; - if(d3.vec_writemask_w) ret += "w"; + if(is_sca) + { + if(d3.sca_writemask_x) ret += "x"; + if(d3.sca_writemask_y) ret += "y"; + if(d3.sca_writemask_z) ret += "z"; + if(d3.sca_writemask_w) ret += "w"; + } + else + { + if(d3.vec_writemask_x) ret += "x"; + if(d3.vec_writemask_y) ret += "y"; + if(d3.vec_writemask_z) ret += "z"; + if(d3.vec_writemask_w) ret += "w"; + } return ret.IsEmpty() || ret == "xyzw" ? wxEmptyString : ("." + ret); } +wxString VertexDecompilerThread::GetVecMask() +{ + return GetMask(false); +} + wxString VertexDecompilerThread::GetScaMask() { - wxString ret = wxEmptyString; - - if(d3.sca_writemask_x) ret += "x"; - if(d3.sca_writemask_y) ret += "y"; - if(d3.sca_writemask_z) ret += "z"; - if(d3.sca_writemask_w) ret += "w"; - - return ret.IsEmpty() || ret == "xyzw" ? wxEmptyString : ("." + ret); + return GetMask(true); } wxString VertexDecompilerThread::GetDST(bool isSca) @@ -38,26 +46,25 @@ wxString VertexDecompilerThread::GetDST(bool isSca) }; wxString ret = wxEmptyString; - u32 dst = isSca ? d3.sca_dst : d3.dst; - switch(dst) + switch(isSca ? 0x1f : d3.dst) { case 0x0: case 0x6: - ret += reg_table[dst]; + ret += reg_table[d3.dst]; break; case 0x1f: - ret += m_parr.AddParam(PARAM_NONE, "vec4", wxString::Format("tmp%d", d0.dst_tmp)); + ret += m_parr.AddParam(PARAM_NONE, "vec4", wxString::Format("tmp%d", isSca ? d3.sca_dst_tmp : d0.dst_tmp)); break; default: - if(dst < WXSIZEOF(reg_table)) + if(d3.dst < WXSIZEOF(reg_table)) { - ret += m_parr.AddParam(PARAM_OUT, "vec4", reg_table[dst]); + ret += m_parr.AddParam(PARAM_OUT, "vec4", reg_table[d3.dst]); } else { - ConLog.Error("Bad dst reg num: %d", dst); + ConLog.Error("Bad dst reg num: %d", d3.dst); ret += m_parr.AddParam(PARAM_OUT, "vec4", "unk"); } break; @@ -97,7 +104,7 @@ wxString VertexDecompilerThread::GetSRC(const u32 n, bool isSca) } break; case 3: //const - ret += m_parr.AddParam(PARAM_CONST, "vec4", wxString::Format("vc%d", d1.const_src)); + ret += m_parr.AddParam(PARAM_UNIFORM, "vec4", wxString::Format("vc%d", d1.const_src)); break; default: @@ -106,8 +113,7 @@ wxString VertexDecompilerThread::GetSRC(const u32 n, bool isSca) break; } - static const char f[4] = {'x', 'z', 'w', 'y'}; - static const char fSca[4] = {'x', 'z', 'y', 'w'}; + static const char f[4] = {'x', 'y', 'z', 'w'}; wxString swizzle = wxEmptyString; @@ -117,7 +123,7 @@ wxString VertexDecompilerThread::GetSRC(const u32 n, bool isSca) assert(src[n].swz_z == src[n].swz_w); assert(src[n].swz_x == src[n].swz_z); - ret += "." + fSca[src[n].swz_x]; + ret += "." + f[src[n].swz_x]; } else { @@ -144,34 +150,50 @@ wxString VertexDecompilerThread::GetSRC(const u32 n, bool isSca) return ret; } -void VertexDecompilerThread::AddVecCode(wxString code, bool src_mask) +void VertexDecompilerThread::AddCode(bool is_sca, wxString code, bool src_mask) { if(d0.cond == 0) return; - if(d0.cond != 7) + enum { - ConLog.Error("Bad cond! %d", d0.cond); - Emu.Pause(); - return; + lt = 0x1, + eq = 0x2, + gt = 0x4, + }; + + wxString cond; + + if(d0.cond != (lt | gt | eq)) + { + if(d0.cond & (lt | gt)) + { + cond = "!="; + } + else + { + if(d0.cond & lt) cond = "<"; + else if(d0.cond & gt) cond = ">"; + else if(d0.cond & eq) cond = "="; + + if(d0.cond & eq) cond += "="; + } + + ConLog.Error("cond! %d (%d %s %d %d)", d0.cond, d0.dst_tmp, cond, d1.input_src, d1.const_src); + cond = wxString::Format("if(tmp%d.x %s 0) ", d0.dst_tmp, cond); } - code = GetDST() + GetVecMask() + " = " + (src_mask ? code + GetVecMask() : code); + code = cond + GetDST(is_sca) + GetMask(is_sca) + " = " + (src_mask ? code + GetMask(is_sca) : code); main += "\t" + code + ";\n"; } -void VertexDecompilerThread::AddScaCode(wxString code, bool src_mask) +void VertexDecompilerThread::AddVecCode(const wxString& code, bool src_mask) { - if(d0.cond == 0) return; - if(d0.cond != 7) - { - ConLog.Error("Bad cond! %d", d0.cond); - Emu.Pause(); - return; - } + AddCode(false, code, src_mask); +} - code = GetDST(true) + GetScaMask() + " = " + (src_mask ? code + GetScaMask() : code); - - main += "\t" + code + ";\n"; +void VertexDecompilerThread::AddScaCode(const wxString& code, bool src_mask) +{ + AddCode(true, code, src_mask); } wxString VertexDecompilerThread::BuildCode() @@ -201,16 +223,18 @@ void VertexDecompilerThread::Task() d2.HEX = m_data[i++]; d3.HEX = m_data[i++]; - src[0].HEX = d2.src0l | (d1.src0h << 9); - src[1].HEX = d2.src1; - src[2].HEX = d3.src2l | (d2.src2h << 11); + src[0].src0l = d2.src0l; + src[0].src0h = d1.src0h; + src[1].src1 = d2.src1; + src[2].src2l = d3.src2l; + src[2].src2h = d2.src2h; switch(d1.sca_opcode) { case 0x00: break; // NOP case 0x01: AddScaCode(GetSRC(2, true)); break; // MOV case 0x02: AddScaCode("1 / (" + GetSRC(2, true) + ")"); break; // RCP - case 0x03: AddScaCode("clamp(1 / (" + GetSRC(2, true) + "), 5.42101e-20, 1.884467e19"); break; // RCC + case 0x03: AddScaCode("clamp(1 / (" + GetSRC(2, true) + "), 5.42101e-20, 1.884467e19)"); break; // RCC case 0x04: AddScaCode("inversesqrt(" + GetSRC(2, true) + ")"); break; // RSQ case 0x05: AddScaCode("exp(" + GetSRC(2, true) + ")"); break; // EXP case 0x06: AddScaCode("log(" + GetSRC(2, true) + ")"); break; // LOG @@ -229,7 +253,6 @@ void VertexDecompilerThread::Task() //case 0x13: break; // PSH : works differently (PSH o[1].x A0;) //case 0x14: break; // POP : works differently (POP o[1].x;) - default: ConLog.Error("Unknown vp sca_opcode 0x%x", d1.sca_opcode); Emu.Pause(); @@ -241,7 +264,7 @@ void VertexDecompilerThread::Task() case 0x00: break; //NOP case 0x01: AddVecCode(GetSRC(0)); break; //MOV case 0x02: AddVecCode("(" + GetSRC(0) + " * " + GetSRC(1) + ")"); break; //MUL - case 0x03: AddVecCode("(" + GetSRC(0) + " + " + GetSRC(1) + ")"); break; //ADD + case 0x03: AddVecCode("(" + GetSRC(0) + " + " + GetSRC(2) + ")"); break; //ADD case 0x04: AddVecCode("(" + GetSRC(0) + " * " + GetSRC(1) + " + " + GetSRC(2) + ")"); break; //MAD case 0x05: AddVecCode("dot(" + GetSRC(0) + ".xyz, " + GetSRC(1) + ".xyz)", false); break; //DP3 case 0x06: AddVecCode("(dot(" + GetSRC(0) + ".xyz, " + GetSRC(1) + ".xyz) + " + GetSRC(1) + ".w)", false); break; //DPH @@ -249,18 +272,17 @@ void VertexDecompilerThread::Task() case 0x08: AddVecCode("distance(" + GetSRC(0) + ", " + GetSRC(1) + ")"); break; //DST case 0x09: AddVecCode("min(" + GetSRC(0) + ", " + GetSRC(1) + ")"); break; //MIN case 0x0a: AddVecCode("max(" + GetSRC(0) + ", " + GetSRC(1) + ")"); break; //MAX - case 0x0b: AddVecCode("lessThan(" + GetSRC(0) + ", " + GetSRC(1) + ")"); break; //SLT - case 0x0c: AddVecCode("greaterThanEqual(" + GetSRC(0) + ", " + GetSRC(1) + ")"); break; //SGE + case 0x0b: AddVecCode("vec4(lessThan(" + GetSRC(0) + ", " + GetSRC(1) + "))"); break; //SLT + case 0x0c: AddVecCode("vec4(greaterThanEqual(" + GetSRC(0) + ", " + GetSRC(1) + "))"); break; //SGE case 0x0e: AddVecCode("fract(" + GetSRC(0) + ")"); break; //FRC case 0x0f: AddVecCode("floor(" + GetSRC(0) + ")"); break; //FLR - case 0x10: AddVecCode("equal(" + GetSRC(0) + ", " + GetSRC(1) + ")"); break; //SEQ - case 0x11: AddVecCode("vec4(0.0f, 0.0f, 0.0f, 0.0f)"); break; //SFL - case 0x12: AddVecCode("greaterThan(" + GetSRC(0) + ", " + GetSRC(1) + ")"); break; //SGT - case 0x13: AddVecCode("lessThanEqual(" + GetSRC(0) + ", " + GetSRC(1) + ")"); break; //SLE - case 0x14: AddVecCode("notEqual(" + GetSRC(0) + ", " + GetSRC(1) + ")"); break; //SNE - case 0x15: AddVecCode("vec4(1.0f, 1.0f, 1.0f, 1.0f)"); break; //STR - case 0x16: AddVecCode("sign(" + GetSRC(0) + ", " + GetSRC(1) + ")"); break; //SSG - + case 0x10: AddVecCode("vec4(equal(" + GetSRC(0) + ", " + GetSRC(1) + "))"); break; //SEQ + //case 0x11: AddVecCode("vec4(0.0f, 0.0f, 0.0f, 0.0f)"); break; //SFL + case 0x12: AddVecCode("vec4(greaterThan(" + GetSRC(0) + ", " + GetSRC(1) + "))"); break; //SGT + case 0x13: AddVecCode("vec4(lessThanEqual(" + GetSRC(0) + ", " + GetSRC(1) + "))"); break; //SLE + case 0x14: AddVecCode("vec4(notEqual(" + GetSRC(0) + ", " + GetSRC(1) + "))"); break; //SNE + //case 0x15: AddVecCode("vec4(1.0f, 1.0f, 1.0f, 1.0f)"); break; //STR + case 0x16: AddVecCode("sign(" + GetSRC(0) + ")"); break; //SSG default: ConLog.Error("Unknown vp opcode 0x%x", d1.vec_opcode); @@ -276,7 +298,7 @@ void VertexDecompilerThread::Task() } VertexProgram::VertexProgram() - : m_decompiler_thread(NULL) + : m_decompiler_thread(nullptr) , id(0) { } @@ -358,13 +380,7 @@ void VertexProgram::Compile() void VertexProgram::Delete() { data.Clear(); - for(u32 i=0; i constants4; - Array data; ParamArray parr; @@ -174,11 +187,10 @@ struct VertexData Array data; - VertexData() { memset(this, 0, sizeof(*this)); } - ~VertexData() { data.Clear(); } + VertexData(); + void Reset(); bool IsEnabled() { return size > 0; } - void Load(u32 start, u32 count); u32 GetTypeSize(); diff --git a/rpcs3/Emu/SysCalls/FuncList.cpp b/rpcs3/Emu/SysCalls/FuncList.cpp index 0dbc923703..83557bc3e3 100644 --- a/rpcs3/Emu/SysCalls/FuncList.cpp +++ b/rpcs3/Emu/SysCalls/FuncList.cpp @@ -1,7 +1,7 @@ #include "stdafx.h" #include "SysCalls.h" -#define FUNC_LOG_ERROR(x) ConLog.Error(x); return SC_ARGS_1 +#define FUNC_LOG_ERROR(x) ConLog.Error(x); return 0 s64 SysCalls::DoFunc(const u32 id) { switch(id)