1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-25 12:12:50 +01:00

OpenGL Renderer fixes:

- Fixed Vertex & Fragment Shader Decompilers.
  - Fixed Transform Constants loading.
This commit is contained in:
DH 2013-08-11 00:56:24 +03:00
parent 81e874c9e2
commit f42d4b6572
15 changed files with 429 additions and 234 deletions

View File

@ -141,7 +141,7 @@ public:
virtual void SetCount(const u32 count, bool memzero = true) virtual void SetCount(const u32 count, bool memzero = true)
{ {
if(m_count >= count) return; if(m_count >= count) return;
_InsertRoomEnd(count - m_count); _InsertRoomEnd(count - m_count);
if(memzero) memset(m_array + m_count - count, 0, sizeof(T) * (m_count - count)); if(memzero) memset(m_array + m_count - count, 0, sizeof(T) * (m_count - count));

View File

@ -381,7 +381,11 @@ public:
, m_parent(nullptr) , m_parent(nullptr)
, m_opcode(-1) , m_opcode(-1)
{ {
memset(m_instrs, 0, sizeof(InstrCaller<TO>*) * count); for(int i=0; i<count; ++i)
{
m_instrs[i] = error_func;
}
memset(m_instrs_info, 0, sizeof(InstrBase<TO>*) * count); memset(m_instrs_info, 0, sizeof(InstrBase<TO>*) * count);
} }
@ -413,6 +417,14 @@ public:
void set_error_func(InstrCaller<TO>* error_func) void set_error_func(InstrCaller<TO>* error_func)
{ {
for(int i=0; i<count; ++i)
{
if(m_instrs[i] == m_error_func || !m_instrs[i])
{
m_instrs[i] = error_func;
}
}
m_error_func = error_func; m_error_func = error_func;
} }
@ -442,16 +454,7 @@ public:
void decode(TO* op, u32 entry, u32 code) const void decode(TO* op, u32 entry, u32 code) const
{ {
InstrCaller<TO>* instr = m_instrs[entry]; (*m_instrs[entry])(op, code);
if(instr)
{
(*instr)(op, code);
}
else if(m_error_func)
{
(*m_error_func)(op, code);
}
} }
virtual void operator ()(TO* op, u32 code) const virtual void operator ()(TO* op, u32 code) const

View File

@ -3564,7 +3564,7 @@ private:
} }
void FNEG(u32 frd, u32 frb, bool rc) 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]); if(rc) UNK("fneg.");//CPU.UpdateCR1(CPU.FPR[frd]);
} }
void FMR(u32 frd, u32 frb, bool rc) void FMR(u32 frd, u32 frb, bool rc)

View File

@ -3,10 +3,38 @@
void FragmentDecompilerThread::AddCode(wxString code) 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_lt) return;
if(!src0.exec_if_eq || !src0.exec_if_gr || !src0.exec_if_le)
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(); Emu.Pause();
return; 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"; main += "\t" + code + ";\n";
} }
@ -46,20 +74,29 @@ wxString FragmentDecompilerThread::GetMask()
return ret.IsEmpty() || ret == "xyzw" ? wxEmptyString : ("." + ret); return ret.IsEmpty() || ret == "xyzw" ? wxEmptyString : ("." + ret);
} }
wxString FragmentDecompilerThread::AddReg(u32 index) wxString FragmentDecompilerThread::AddReg(u32 index, int fp16)
{ {
//if(!index) return "gl_FragColor"; //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() 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() 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<typename T> wxString FragmentDecompilerThread::GetSRC(T src) template<typename T> wxString FragmentDecompilerThread::GetSRC(T src)
@ -69,7 +106,7 @@ template<typename T> wxString FragmentDecompilerThread::GetSRC(T src)
switch(src.reg_type) switch(src.reg_type)
{ {
case 0: //tmp case 0: //tmp
ret += AddReg(src.tmp_reg_index); ret += AddReg(src.tmp_reg_index, src.fp16);
break; break;
case 1: //input case 1: //input
@ -102,7 +139,6 @@ template<typename T> wxString FragmentDecompilerThread::GetSRC(T src)
break; break;
case 2: //const case 2: //const
ConLog.Write("reg index = %d", src.tmp_reg_index);
ret += AddConst(); ret += AddConst();
break; break;
@ -157,6 +193,8 @@ void FragmentDecompilerThread::Task()
src1.HEX = GetData(data[2]); src1.HEX = GetData(data[2]);
src2.HEX = GetData(data[3]); src2.HEX = GetData(data[3]);
m_offset = 4 * 4;
switch(dst.opcode) switch(dst.opcode)
{ {
case 0x00: break; //NOP case 0x00: break; //NOP
@ -166,24 +204,24 @@ void FragmentDecompilerThread::Task()
case 0x04: AddCode("(" + GetSRC(src0) + " * " + GetSRC(src1) + " + " + GetSRC(src2) + ")"); break; //MAD case 0x04: AddCode("(" + GetSRC(src0) + " * " + GetSRC(src1) + " + " + GetSRC(src2) + ")"); break; //MAD
case 0x05: AddCode("dot(" + GetSRC(src0) + ".xyz, " + GetSRC(src1) + ".xyz)"); break; // DP3 case 0x05: AddCode("dot(" + GetSRC(src0) + ".xyz, " + GetSRC(src1) + ".xyz)"); break; // DP3
case 0x06: AddCode("dot(" + GetSRC(src0) + ", " + GetSRC(src1) + ")"); break; // DP4 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 0x08: AddCode("min(" + GetSRC(src0) + ", " + GetSRC(src1) + ")"); break; // MIN
case 0x09: AddCode("max(" + GetSRC(src0) + ", " + GetSRC(src1) + ")"); break; // MAX case 0x09: AddCode("max(" + GetSRC(src0) + ", " + GetSRC(src1) + ")"); break; // MAX
//case 0x0a: break; // SLT case 0x0a: AddCode("vec4(lessThan(" + GetSRC(src0) + ", " + GetSRC(src1) + "))"); break; // SLT
//case 0x0b: break; // SGE case 0x0b: AddCode("vec4(greaterThanEqual(" + GetSRC(src0) + ", " + GetSRC(src1) + "))"); break; // SGE
//case 0x0c: break; // SLE case 0x0c: AddCode("vec4(lessThanEqual(" + GetSRC(src0) + ", " + GetSRC(src1) + "))"); break; // SLE
//case 0x0d: break; // SGT case 0x0d: AddCode("vec4(greaterThan(" + GetSRC(src0) + ", " + GetSRC(src1) + "))"); break; // SGT
//case 0x0e: break; // SNE case 0x0e: AddCode("vec4(notEqual(" + GetSRC(src0) + ", " + GetSRC(src1) + "))"); break; // SNE
//case 0x0f: break; // SEQ case 0x0f: AddCode("vec4(equal(" + GetSRC(src0) + ", " + GetSRC(src1) + "))"); break; // SEQ
//case 0x10: break; // FRC case 0x10: AddCode("fract(" + GetSRC(src0) + ")"); break; // FRC
//case 0x11: break; // FLR case 0x11: AddCode("floor(" + GetSRC(src0) + ")"); break; // FLR
//case 0x12: break; // KIL //case 0x12: break; // KIL
//case 0x13: break; // PK4 //case 0x13: break; // PK4
//case 0x14: break; // UP4 //case 0x14: break; // UP4
case 0x15: AddCode("ddx(" + GetSRC(src0) + ")"); break; // DDX case 0x15: AddCode("ddx(" + GetSRC(src0) + ")"); break; // DDX
case 0x16: AddCode("ddy(" + GetSRC(src0) + ")"); break; // DDY 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 0x18: break; // TXP
//case 0x19: break; // TXD //case 0x19: break; // TXD
case 0x1a: AddCode("1 / (" + GetSRC(src0) + ")"); break; // RCP case 0x1a: AddCode("1 / (" + GetSRC(src0) + ")"); break; // RCP
@ -199,7 +237,7 @@ void FragmentDecompilerThread::Task()
case 0x23: AddCode("sin(" + GetSRC(src0) + ")"); break; // SIN case 0x23: AddCode("sin(" + GetSRC(src0) + ")"); break; // SIN
//case 0x24: break; // PK2 //case 0x24: break; // PK2
//case 0x25: break; // UP2 //case 0x25: break; // UP2
//case 0x26: break; // POW case 0x26: AddCode("pow(" + GetSRC(src0) + ", " + GetSRC(src1) +")"); break; // POW
//case 0x27: break; // PKB //case 0x27: break; // PKB
//case 0x28: break; // UPB //case 0x28: break; // UPB
//case 0x29: break; // PK16 //case 0x29: break; // PK16
@ -218,23 +256,23 @@ void FragmentDecompilerThread::Task()
//case 0x37: break; // TIMESWTEX //case 0x37: break; // TIMESWTEX
//case 0x38: break; // DP2 //case 0x38: break; // DP2
//case 0x39: break; // NRM //case 0x39: break; // NRM
//case 0x3a: break; // DIV case 0x3a: AddCode("(" + GetSRC(src0) + " / " + GetSRC(src1) + ")"); break; // DIV
//case 0x3b: break; // DIVSQ case 0x3b: AddCode("(" + GetSRC(src0) + " / " + GetSRC(src1) + ")"); break; // DIVSQ
//case 0x3c: break; // LIF //case 0x3c: break; // LIF
//case 0x3d: break; // FENCT case 0x3d: break; // FENCT
//case 0x3e: break; // FENCB case 0x3e: break; // FENCB
default: 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(); Emu.Pause();
break; break;
} }
m_size += 4 * 4; m_size += m_offset;
if(dst.end) break; if(dst.end) break;
data.SetOffset(4 * 4); data.SetOffset(m_offset);
} }
m_shader = BuildCode(); m_shader = BuildCode();

View File

@ -100,6 +100,7 @@ struct FragmentDecompilerThread : public ThreadBase
u32 m_addr; u32 m_addr;
u32& m_size; u32& m_size;
u32 m_const_index; u32 m_const_index;
u32 m_offset;
FragmentDecompilerThread(wxString& shader, ParamArray& parr, u32 addr, u32& size) FragmentDecompilerThread(wxString& shader, ParamArray& parr, u32 addr, u32& size)
: ThreadBase(false, "Fragment Shader Decompiler Thread") : ThreadBase(false, "Fragment Shader Decompiler Thread")
@ -115,7 +116,7 @@ struct FragmentDecompilerThread : public ThreadBase
wxString GetMask(); wxString GetMask();
void AddCode(wxString code); void AddCode(wxString code);
wxString AddReg(u32 index); wxString AddReg(u32 index, int fp16);
wxString AddConst(); wxString AddConst();
wxString AddTex(); wxString AddTex();

View File

@ -1,8 +1,8 @@
#include "stdafx.h" #include "stdafx.h"
#include "GLGSRender.h" #include "GLGSRender.h"
#include "Emu/Cell/PPCInstrTable.h" #include "Emu/Cell/PPCInstrTable.h"
#define CMD_DEBUG 1 #define CMD_DEBUG 0
#define DUMP_VERTEX_DATA 1 #define DUMP_VERTEX_DATA 0
#if CMD_DEBUG #if CMD_DEBUG
#define CMD_LOG ConLog.Write #define CMD_LOG ConLog.Write
@ -75,8 +75,8 @@ void GLGSFrame::SetViewport(int x, int y, u32 w, u32 h)
} }
GLGSRender::GLGSRender() GLGSRender::GLGSRender()
: m_frame(NULL) : m_frame(nullptr)
, m_rsx_thread(NULL) , m_rsx_thread(nullptr)
, m_fp_buf_num(-1) , m_fp_buf_num(-1)
, m_vp_buf_num(-1) , m_vp_buf_num(-1)
{ {
@ -122,6 +122,12 @@ void GLRSXThread::Task()
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
glSwapInterval(Ini.GSVSyncEnable.GetValue() ? 1 : 0); glSwapInterval(Ini.GSVSyncEnable.GetValue() ? 1 : 0);
for(u32 i=0; i<p.m_textures_count; ++i)
{
GLTexture& tex = p.m_frame->GetTexture(i);
tex.Create();
}
bool draw = true; bool draw = true;
u32 drawed = 0; u32 drawed = 0;
u32 skipped = 0; u32 skipped = 0;
@ -172,7 +178,7 @@ void GLRSXThread::Task()
continue; 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 cmd = Memory.Read32(p.m_ioAddress + get);
const u32 count = (cmd >> 18) & 0x7ff; const u32 count = (cmd >> 18) & 0x7ff;
//if(cmd == 0) continue; //if(cmd == 0) continue;
@ -251,6 +257,10 @@ void GLGSRender::Init(const u32 ioAddress, const u32 ioSize, const u32 ctrlAddre
m_localAddress = localAddress; m_localAddress = localAddress;
m_ctrl = (CellGcmControl*)Memory.GetMemFromAddr(m_ctrlAddress); 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(); (m_rsx_thread = new GLRSXThread(this))->Start();
} }
@ -309,7 +319,7 @@ void GLGSRender::EnableVertexData(bool indexed_draw)
wxFile dump("VertexDataArray.dump", wxFile::write); wxFile dump("VertexDataArray.dump", wxFile::write);
#endif #endif
for(u32 i=0; i<16; ++i) for(u32 i=0; i<m_vertex_count; ++i)
{ {
if(!m_vertex_data[i].IsEnabled()) continue; if(!m_vertex_data[i].IsEnabled()) continue;
@ -409,7 +419,7 @@ void GLGSRender::EnableVertexData(bool indexed_draw)
void GLGSRender::DisableVertexData() void GLGSRender::DisableVertexData()
{ {
m_vdata.Clear(); m_vdata.Clear();
for(u32 i=0; i<16; ++i) for(u32 i=0; i<m_vertex_count; ++i)
{ {
if(!m_vertex_data[i].IsEnabled()) continue; if(!m_vertex_data[i].IsEnabled()) continue;
m_vertex_data[i].data.Clear(); m_vertex_data[i].data.Clear();
@ -419,7 +429,7 @@ void GLGSRender::DisableVertexData()
void GLGSRender::LoadVertexData(u32 first, u32 count) void GLGSRender::LoadVertexData(u32 first, u32 count)
{ {
for(u32 i=0; i<16; ++i) for(u32 i=0; i<m_vertex_count; ++i)
{ {
if(!m_vertex_data[i].IsEnabled()) continue; if(!m_vertex_data[i].IsEnabled()) continue;
@ -429,11 +439,10 @@ void GLGSRender::LoadVertexData(u32 first, u32 count)
void GLGSRender::InitVertexData() void GLGSRender::InitVertexData()
{ {
for(u32 i=0; i<m_cur_vertex_prog->constants4.GetCount(); ++i) for(u32 i=0; i<m_transform_constants.GetCount(); ++i)
{ {
const VertexProgram::Constant4& c = m_cur_vertex_prog->constants4[i]; const TransformConstant& c = m_transform_constants[i];
const wxString& name = wxString::Format("vc%d", c.id); const wxString& name = wxString::Format("vc%d", c.id);
//const int l = glGetUniformLocation(m_program.id, name);
const int l = m_program.GetLocation(name); const int l = m_program.GetLocation(name);
checkForGlError("glGetUniformLocation " + 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", 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); 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); tex.SetFormat(cubemap, dimension, format, mipmap);
} }
break; 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: case NV4097_SET_COLOR_CLEAR_VALUE:
{ {
const u8 a = (args[0] >> 24) & 0xff; const u32 color = args[0];
const u8 r = (args[0] >> 16) & 0xff; const u8 a = (color >> 24) & 0xff;
const u8 g = (args[0] >> 8) & 0xff; const u8 r = (color >> 16) & 0xff;
const u8 b = args[0] & 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); CMD_LOG("a=%d, r=%d, g=%d, b=%d", a, r, g, b);
glClearColor( glClearColor(
(float)r / 255.0f, (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: case NV4097_SET_SHADER_PROGRAM:
{ {
m_shader_prog.Delete(); m_cur_shader_prog = &m_shader_progs[m_cur_shader_prog_num++];
m_shader_prog.addr = GetAddress(args[0] & ~0x3, (args[0] & 0x3) - 1); m_cur_shader_prog->Delete();
//m_program.Delete(); m_cur_shader_prog->addr = GetAddress(args[0] & ~0x3, (args[0] & 0x3) - 1);
} }
break; 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: case NV4097_SET_TRANSFORM_PROGRAM_LOAD:
{ {
//m_program.Delete();
m_cur_vertex_prog = &m_vertex_progs[args[0]]; m_cur_vertex_prog = &m_vertex_progs[args[0]];
m_cur_vertex_prog->Delete(); m_cur_vertex_prog->Delete();
if(count == 2) if(count == 2)
{ {
const u32 start = args[1]; const u32 start = args[1];
if(start)
ConLog.Warning("NV4097_SET_TRANSFORM_PROGRAM_LOAD: start = %d", start);
} }
} }
break; break;
@ -899,12 +912,6 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 c
break; 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; i<count; ++id) for(u32 id = args[0], i = 1; i<count; ++id)
{ {
const u32 x = args[i++]; const u32 x = args[i++];
@ -912,15 +919,10 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 c
const u32 z = args[i++]; const u32 z = args[i++];
const u32 w = args[i++]; const u32 w = args[i++];
VertexProgram::Constant4 c; TransformConstant c(id, (float&)x, (float&)y, (float&)z, (float&)w);
c.id = id;
c.x = (float&)x;
c.y = (float&)y;
c.z = (float&)z;
c.w = (float&)w;
CMD_LOG("SET_TRANSFORM_CONSTANT_LOAD[%d : %d] = (%f, %f, %f, %f)", i, id, c.x, c.y, c.z, c.w); CMD_LOG("SET_TRANSFORM_CONSTANT_LOAD[%d : %d] = (%f, %f, %f, %f)", i, id, c.x, c.y, c.z, c.w);
m_cur_vertex_prog->constants4.AddCpy(c); m_transform_constants.AddCpy(c);
} }
} }
break; break;
@ -1154,13 +1156,20 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 c
bool GLGSRender::LoadProgram() 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) 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; return false;
} }
@ -1182,11 +1191,11 @@ bool GLGSRender::LoadProgram()
if(m_fp_buf_num == -1) if(m_fp_buf_num == -1)
{ {
ConLog.Warning("FP not found in buffer!"); ConLog.Warning("FP not found in buffer!");
m_shader_prog.Wait(); m_cur_shader_prog->Wait();
m_shader_prog.Compile(); m_cur_shader_prog->Compile();
wxFile f(wxGetCwd() + "/FragmentProgram.txt", wxFile::write); 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) 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); 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_program.Use();
m_prog_buffer.Add(m_program, m_shader_prog, *m_cur_vertex_prog); }
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(); m_program.Use();
@ -1270,7 +1283,12 @@ void GLGSRender::ExecCMD()
glDepthRangef(m_clip_min, m_clip_max); 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; i<m_textures_count; ++i)
{ {
GLTexture& tex = m_frame->GetTexture(i); GLTexture& tex = m_frame->GetTexture(i);
if(!tex.IsEnabled()) continue; if(!tex.IsEnabled()) continue;
@ -1280,17 +1298,11 @@ void GLGSRender::ExecCMD()
tex.Bind(); tex.Bind();
checkForGlError("tex.Bind"); checkForGlError("tex.Bind");
m_program.SetTex(i); m_program.SetTex(i);
checkForGlError("m_program.SetTex");
tex.Init(); tex.Init();
checkForGlError("tex.Init"); checkForGlError("tex.Init");
tex.Save(); 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) if(m_indexed_array.m_count)
{ {
LoadVertexData(m_indexed_array.index_min, m_indexed_array.index_max - m_indexed_array.index_min + 1); 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() void GLGSRender::Reset()
{ {
m_program.Delete(); m_program.UnUse();
//m_program.id = 0;
m_shader_prog.id = 0; if(m_cur_shader_prog)
m_cur_shader_prog->id = 0;
if(m_cur_vertex_prog) if(m_cur_vertex_prog)
m_cur_vertex_prog->id = 0; 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<m_vertex_count; ++i)
{
m_vertex_data[i].Reset();
}
if(m_vbo.IsCreated()) if(m_vbo.IsCreated())
{ {

View File

@ -38,6 +38,20 @@ public:
{ {
} }
void Create()
{
if(!m_id)
{
glGenTextures(1, &m_id);
checkForGlError("GLTexture::Init() -> 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) void SetRect(const u32 width, const u32 height)
{ {
m_width = width; m_width = width;
@ -68,21 +82,8 @@ public:
void Init() void Init()
{ {
if(!m_id) Bind();
{ ConLog.Warning("texture addr = 0x%x, width = %d, height = %d", m_offset, m_width, m_height);
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);
}
//TODO: safe init //TODO: safe init
checkForGlError("GLTexture::Init() -> glBindTexture"); checkForGlError("GLTexture::Init() -> glBindTexture");
@ -106,18 +107,17 @@ public:
default: ConLog.Error("Init tex error: Bad tex format (0x%x)", m_format); break; 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) void Save(const wxString& name)
{ {
if(!m_id || !m_offset) return; if(!m_id || !m_offset) return;
ConLog.Write("start");
u32* alldata = new u32[m_width * m_height]; u32* alldata = new u32[m_width * m_height];
glBindTexture(GL_TEXTURE_2D, m_id); Bind();
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, alldata); 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* data = new u8[m_width * m_height * 3];
u8* alpha = new u8[m_width * m_height]; u8* alpha = new u8[m_width * m_height];
@ -133,7 +133,6 @@ public:
*dst_a++ = *src++; *dst_a++ = *src++;
} }
ConLog.Write("end");
wxImage out; wxImage out;
out.Create(m_width, m_height, data, alpha); out.Create(m_width, m_height, data, alpha);
out.SaveFile(name, wxBITMAP_TYPE_PNG); out.SaveFile(name, wxBITMAP_TYPE_PNG);
@ -160,10 +159,34 @@ public:
glBindTexture(GL_TEXTURE_2D, m_id); glBindTexture(GL_TEXTURE_2D, m_id);
} }
void Unbind()
{
glBindTexture(GL_TEXTURE_2D, 0);
}
void Enable(bool enable) { m_enabled = enable; } void Enable(bool enable) { m_enabled = enable; }
bool IsEnabled() const { return m_enabled; } 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 struct IndexArrayData
{ {
Array<u8> m_data; Array<u8> m_data;
@ -228,16 +251,25 @@ class GLGSRender
, public GSRender , public GSRender
, public ExecRSXCMDdata , 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: private:
GLRSXThread* m_rsx_thread; GLRSXThread* m_rsx_thread;
IndexArrayData m_indexed_array; IndexArrayData m_indexed_array;
ShaderProgram m_shader_prog; ShaderProgram m_shader_progs[m_fragment_count];
VertexData m_vertex_data[16]; ShaderProgram* m_cur_shader_prog;
int m_cur_shader_prog_num;
VertexData m_vertex_data[m_vertex_count];
Array<u8> m_vdata; Array<u8> m_vdata;
VertexProgram m_vertex_progs[16]; VertexProgram m_vertex_progs[m_vertex_count];
VertexProgram* m_cur_vertex_prog; VertexProgram* m_cur_vertex_prog;
Array<TransformConstant> m_transform_constants;
Program m_program; Program m_program;
int m_fp_buf_num; int m_fp_buf_num;
int m_vp_buf_num; int m_vp_buf_num;

View File

@ -19,7 +19,9 @@ int Program::GetLocation(const wxString& name)
u32 pos = m_locations.Move(new Location()); u32 pos = m_locations.Move(new Location());
m_locations[pos].name = name; 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 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() void Program::Use()
{ {
glUseProgram(id); glUseProgram(id);
@ -80,8 +87,10 @@ void Program::Use()
void Program::SetTex(u32 index) void Program::SetTex(u32 index)
{ {
glUniform1i(GetLocation(wxString::Format("tex_%d", index)), index); int loc = GetLocation(wxString::Format("tex%d", index));
checkForGlError(wxString::Format("SetTex(%d)", index)); checkForGlError(wxString::Format("GetLocation(tex%d)", index));
glUniform1i(loc, index);
checkForGlError(wxString::Format("SetTex(%d - %d)", index, loc));
} }
void Program::Delete() void Program::Delete()

View File

@ -22,6 +22,7 @@ public:
bool IsCreated() const; bool IsCreated() const;
void Create(const u32 vp, const u32 fp); void Create(const u32 vp, const u32 fp);
void Use(); void Use();
void UnUse();
void SetTex(u32 index); void SetTex(u32 index);
void Delete(); void Delete();
}; };

View File

@ -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; 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.id = m_buf[i].fp_id;
fp.shader = m_buf[i].fp_shader; fp.shader = m_buf[i].fp_shader.GetPtr();
return i; return i;
} }
@ -21,10 +21,10 @@ int ProgramBuffer::SearchVp(VertexProgram& vp)
for(u32 i=0; i<m_buf.GetCount(); ++i) for(u32 i=0; i<m_buf.GetCount(); ++i)
{ {
if(m_buf[i].vp_data.GetCount() != vp.data.GetCount()) continue; if(m_buf[i].vp_data.GetCount() != vp.data.GetCount()) continue;
if(memcmp(&m_buf[i].vp_data[0], &vp.data[0], vp.data.GetCount() * 4) != 0) continue; if(memcmp(m_buf[i].vp_data.GetPtr(), vp.data.GetPtr(), vp.data.GetCount() * 4) != 0) continue;
vp.id = m_buf[i].vp_id; vp.id = m_buf[i].vp_id;
vp.shader = m_buf[i].vp_shader; vp.shader = m_buf[i].vp_shader.GetPtr();
return i; return i;
} }
@ -35,18 +35,30 @@ int ProgramBuffer::SearchVp(VertexProgram& vp)
bool ProgramBuffer::CmpVP(const u32 a, const u32 b) const bool ProgramBuffer::CmpVP(const u32 a, const u32 b) const
{ {
if(m_buf[a].vp_data.GetCount() != m_buf[b].vp_data.GetCount()) return false; if(m_buf[a].vp_data.GetCount() != m_buf[b].vp_data.GetCount()) return false;
return memcmp(&m_buf[a].vp_data[0], &m_buf[b].vp_data[0], m_buf[a].vp_data.GetCount() * 4) == 0; return memcmp(m_buf[a].vp_data.GetPtr(), m_buf[b].vp_data.GetPtr(), m_buf[a].vp_data.GetCount() * 4) == 0;
} }
bool ProgramBuffer::CmpFP(const u32 a, const u32 b) const bool ProgramBuffer::CmpFP(const u32 a, const u32 b) const
{ {
if(m_buf[a].fp_data.GetCount() != m_buf[b].fp_data.GetCount()) return false; if(m_buf[a].fp_data.GetCount() != m_buf[b].fp_data.GetCount()) return false;
return memcmp(&m_buf[a].fp_data[0], &m_buf[b].fp_data[0], m_buf[a].fp_data.GetCount()) == 0; return memcmp(m_buf[a].fp_data.GetPtr(), m_buf[b].fp_data.GetPtr(), m_buf[a].fp_data.GetCount()) == 0;
} }
u32 ProgramBuffer::GetProg(u32 fp, u32 vp) const u32 ProgramBuffer::GetProg(u32 fp, u32 vp) const
{ {
if(fp == vp) return m_buf[fp].prog_id; if(fp == vp)
{
/*
ConLog.Write("Get program (%d):", fp);
ConLog.Write("*** prog id = %d", m_buf[fp].prog_id);
ConLog.Write("*** vp id = %d", m_buf[fp].vp_id);
ConLog.Write("*** fp id = %d", m_buf[fp].fp_id);
ConLog.Write("*** vp shader = \n%s", m_buf[fp].vp_shader);
ConLog.Write("*** fp shader = \n%s", m_buf[fp].fp_shader);
*/
return m_buf[fp].prog_id;
}
for(u32 i=0; i<m_buf.GetCount(); ++i) for(u32 i=0; i<m_buf.GetCount(); ++i)
{ {
@ -54,13 +66,15 @@ u32 ProgramBuffer::GetProg(u32 fp, u32 vp) const
if(CmpVP(vp, i) && CmpFP(fp, i)) if(CmpVP(vp, i) && CmpFP(fp, i))
{ {
/*
ConLog.Write("Get program (%d):", i); ConLog.Write("Get program (%d):", i);
ConLog.Write("*** prog id = %d", m_buf[i].prog_id); ConLog.Write("*** prog id = %d", m_buf[i].prog_id);
ConLog.Write("*** vp id = %d", m_buf[i].vp_id); ConLog.Write("*** vp id = %d", m_buf[i].vp_id);
ConLog.Write("*** fp id = %d", m_buf[i].fp_id); ConLog.Write("*** fp id = %d", m_buf[i].fp_id);
ConLog.Write("*** vp shader = %s\n", m_buf[i].vp_shader); ConLog.Write("*** vp shader = \n%s", m_buf[i].vp_shader);
ConLog.Write("*** fp shader = %s\n", m_buf[i].fp_shader); ConLog.Write("*** fp shader = \n%s", m_buf[i].fp_shader);
*/
return m_buf[i].prog_id; return m_buf[i].prog_id;
} }
} }
@ -79,8 +93,8 @@ void ProgramBuffer::Add(Program& prog, ShaderProgram& fp, VertexProgram& vp)
ConLog.Write("*** vp data size = %d", vp.data.GetCount() * 4); ConLog.Write("*** vp data size = %d", vp.data.GetCount() * 4);
ConLog.Write("*** fp data size = %d", fp.size); ConLog.Write("*** fp data size = %d", fp.size);
ConLog.Write("*** vp shader = %s\n", vp.shader); ConLog.Write("*** vp shader = \n%s", vp.shader);
ConLog.Write("*** fp shader = %s\n", fp.shader); ConLog.Write("*** fp shader = \n%s", fp.shader);
new_buf.prog_id = prog.id; new_buf.prog_id = prog.id;
new_buf.vp_id = vp.id; new_buf.vp_id = vp.id;

View File

@ -8,8 +8,8 @@ struct BufferInfo
u32 vp_id; u32 vp_id;
Array<u8> fp_data; Array<u8> fp_data;
Array<u32> vp_data; Array<u32> vp_data;
wxString fp_shader; ArrayString fp_shader;
wxString vp_shader; ArrayString vp_shader;
}; };
struct ProgramBuffer struct ProgramBuffer

View File

@ -5,18 +5,21 @@ enum ParamFlag
{ {
PARAM_IN, PARAM_IN,
PARAM_OUT, PARAM_OUT,
PARAM_UNIFORM,
PARAM_CONST, PARAM_CONST,
PARAM_NONE, PARAM_NONE,
}; };
struct ParamItem struct ParamItem
{ {
wxString name; ArrayString name;
wxString location; ArrayString location;
ArrayString value;
ParamItem(const wxString& _name, int _location) ParamItem(const wxString& _name, int _location, const wxString& _value = wxEmptyString)
: name(_name) : name(_name)
, location(_location > -1 ? wxString::Format("layout (location = %d) ", _location) : "") , location(_location > -1 ? wxString::Format("layout (location = %d) ", _location) : "")
, value(_value)
{ {
} }
}; };
@ -24,7 +27,7 @@ struct ParamItem
struct ParamType struct ParamType
{ {
const ParamFlag flag; const ParamFlag flag;
wxString type; ArrayString type;
Array<ParamItem> items; Array<ParamItem> items;
ParamType(const ParamFlag _flag, const wxString& _type) ParamType(const ParamFlag _flag, const wxString& _type)
@ -37,7 +40,7 @@ struct ParamType
{ {
for(u32 i=0; i<items.GetCount(); ++i) for(u32 i=0; i<items.GetCount(); ++i)
{ {
if(items[i].name.Cmp(name) == 0) return true; if(name.Cmp(items[i].name.GetPtr()) == 0) return true;
} }
return false; return false;
@ -49,10 +52,15 @@ struct ParamType
for(u32 n=0; n<items.GetCount(); ++n) for(u32 n=0; n<items.GetCount(); ++n)
{ {
ret += items[n].location; ret += items[n].location.GetPtr();
ret += type; ret += type.GetPtr();
ret += " "; ret += " ";
ret += items[n].name; ret += items[n].name.GetPtr();
if(items[n].value.GetCount())
{
ret += " = ";
ret += items[n].value.GetPtr();
}
ret += ";\n"; ret += ";\n";
} }
@ -68,10 +76,10 @@ struct ParamArray
{ {
for(u32 i=0; i<params.GetCount(); ++i) for(u32 i=0; i<params.GetCount(); ++i)
{ {
if(params[i].type.Cmp(type) == 0) return &params[i]; if(type.Cmp(params[i].type.GetPtr()) == 0) return &params[i];
} }
return NULL; return nullptr;
} }
wxString GetParamFlag(const ParamFlag flag) wxString GetParamFlag(const ParamFlag flag)
@ -80,12 +88,32 @@ struct ParamArray
{ {
case PARAM_OUT: return "out "; case PARAM_OUT: return "out ";
case PARAM_IN: return "in "; case PARAM_IN: return "in ";
case PARAM_CONST: return "uniform "; case PARAM_UNIFORM: return "uniform ";
case PARAM_CONST: return "const ";
} }
return wxEmptyString; return wxEmptyString;
} }
wxString AddParam(wxString type, const wxString& name, const wxString& value)
{
type = GetParamFlag(PARAM_CONST) + type;
ParamType* t = SearchParam(type);
if(t)
{
if(!t->SearchName(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) wxString AddParam(const ParamFlag flag, wxString type, const wxString& name, int location = -1)
{ {
type = GetParamFlag(flag) + type; type = GetParamFlag(flag) + type;

View File

@ -1,28 +1,36 @@
#include "stdafx.h" #include "stdafx.h"
#include "VertexProgram.h" #include "VertexProgram.h"
wxString VertexDecompilerThread::GetVecMask() wxString VertexDecompilerThread::GetMask(bool is_sca)
{ {
wxString ret = wxEmptyString; wxString ret = wxEmptyString;
if(d3.vec_writemask_x) ret += "x"; if(is_sca)
if(d3.vec_writemask_y) ret += "y"; {
if(d3.vec_writemask_z) ret += "z"; if(d3.sca_writemask_x) ret += "x";
if(d3.vec_writemask_w) ret += "w"; 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); return ret.IsEmpty() || ret == "xyzw" ? wxEmptyString : ("." + ret);
} }
wxString VertexDecompilerThread::GetVecMask()
{
return GetMask(false);
}
wxString VertexDecompilerThread::GetScaMask() wxString VertexDecompilerThread::GetScaMask()
{ {
wxString ret = wxEmptyString; return GetMask(true);
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);
} }
wxString VertexDecompilerThread::GetDST(bool isSca) wxString VertexDecompilerThread::GetDST(bool isSca)
@ -38,26 +46,25 @@ wxString VertexDecompilerThread::GetDST(bool isSca)
}; };
wxString ret = wxEmptyString; wxString ret = wxEmptyString;
u32 dst = isSca ? d3.sca_dst : d3.dst;
switch(dst) switch(isSca ? 0x1f : d3.dst)
{ {
case 0x0: case 0x6: case 0x0: case 0x6:
ret += reg_table[dst]; ret += reg_table[d3.dst];
break; break;
case 0x1f: 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; break;
default: 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 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"); ret += m_parr.AddParam(PARAM_OUT, "vec4", "unk");
} }
break; break;
@ -97,7 +104,7 @@ wxString VertexDecompilerThread::GetSRC(const u32 n, bool isSca)
} }
break; break;
case 3: //const 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; break;
default: default:
@ -106,8 +113,7 @@ wxString VertexDecompilerThread::GetSRC(const u32 n, bool isSca)
break; break;
} }
static const char f[4] = {'x', 'z', 'w', 'y'}; static const char f[4] = {'x', 'y', 'z', 'w'};
static const char fSca[4] = {'x', 'z', 'y', 'w'};
wxString swizzle = wxEmptyString; 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_z == src[n].swz_w);
assert(src[n].swz_x == src[n].swz_z); assert(src[n].swz_x == src[n].swz_z);
ret += "." + fSca[src[n].swz_x]; ret += "." + f[src[n].swz_x];
} }
else else
{ {
@ -144,34 +150,50 @@ wxString VertexDecompilerThread::GetSRC(const u32 n, bool isSca)
return ret; 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 == 0) return;
if(d0.cond != 7) enum
{ {
ConLog.Error("Bad cond! %d", d0.cond); lt = 0x1,
Emu.Pause(); eq = 0x2,
return; 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"; 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; AddCode(false, code, src_mask);
if(d0.cond != 7) }
{
ConLog.Error("Bad cond! %d", d0.cond);
Emu.Pause();
return;
}
code = GetDST(true) + GetScaMask() + " = " + (src_mask ? code + GetScaMask() : code); void VertexDecompilerThread::AddScaCode(const wxString& code, bool src_mask)
{
main += "\t" + code + ";\n"; AddCode(true, code, src_mask);
} }
wxString VertexDecompilerThread::BuildCode() wxString VertexDecompilerThread::BuildCode()
@ -201,16 +223,18 @@ void VertexDecompilerThread::Task()
d2.HEX = m_data[i++]; d2.HEX = m_data[i++];
d3.HEX = m_data[i++]; d3.HEX = m_data[i++];
src[0].HEX = d2.src0l | (d1.src0h << 9); src[0].src0l = d2.src0l;
src[1].HEX = d2.src1; src[0].src0h = d1.src0h;
src[2].HEX = d3.src2l | (d2.src2h << 11); src[1].src1 = d2.src1;
src[2].src2l = d3.src2l;
src[2].src2h = d2.src2h;
switch(d1.sca_opcode) switch(d1.sca_opcode)
{ {
case 0x00: break; // NOP case 0x00: break; // NOP
case 0x01: AddScaCode(GetSRC(2, true)); break; // MOV case 0x01: AddScaCode(GetSRC(2, true)); break; // MOV
case 0x02: AddScaCode("1 / (" + GetSRC(2, true) + ")"); break; // RCP 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 0x04: AddScaCode("inversesqrt(" + GetSRC(2, true) + ")"); break; // RSQ
case 0x05: AddScaCode("exp(" + GetSRC(2, true) + ")"); break; // EXP case 0x05: AddScaCode("exp(" + GetSRC(2, true) + ")"); break; // EXP
case 0x06: AddScaCode("log(" + GetSRC(2, true) + ")"); break; // LOG 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 0x13: break; // PSH : works differently (PSH o[1].x A0;)
//case 0x14: break; // POP : works differently (POP o[1].x;) //case 0x14: break; // POP : works differently (POP o[1].x;)
default: default:
ConLog.Error("Unknown vp sca_opcode 0x%x", d1.sca_opcode); ConLog.Error("Unknown vp sca_opcode 0x%x", d1.sca_opcode);
Emu.Pause(); Emu.Pause();
@ -241,7 +264,7 @@ void VertexDecompilerThread::Task()
case 0x00: break; //NOP case 0x00: break; //NOP
case 0x01: AddVecCode(GetSRC(0)); break; //MOV case 0x01: AddVecCode(GetSRC(0)); break; //MOV
case 0x02: AddVecCode("(" + GetSRC(0) + " * " + GetSRC(1) + ")"); break; //MUL 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 0x04: AddVecCode("(" + GetSRC(0) + " * " + GetSRC(1) + " + " + GetSRC(2) + ")"); break; //MAD
case 0x05: AddVecCode("dot(" + GetSRC(0) + ".xyz, " + GetSRC(1) + ".xyz)", false); break; //DP3 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 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 0x08: AddVecCode("distance(" + GetSRC(0) + ", " + GetSRC(1) + ")"); break; //DST
case 0x09: AddVecCode("min(" + GetSRC(0) + ", " + GetSRC(1) + ")"); break; //MIN case 0x09: AddVecCode("min(" + GetSRC(0) + ", " + GetSRC(1) + ")"); break; //MIN
case 0x0a: AddVecCode("max(" + GetSRC(0) + ", " + GetSRC(1) + ")"); break; //MAX case 0x0a: AddVecCode("max(" + GetSRC(0) + ", " + GetSRC(1) + ")"); break; //MAX
case 0x0b: AddVecCode("lessThan(" + GetSRC(0) + ", " + GetSRC(1) + ")"); break; //SLT case 0x0b: AddVecCode("vec4(lessThan(" + GetSRC(0) + ", " + GetSRC(1) + "))"); break; //SLT
case 0x0c: AddVecCode("greaterThanEqual(" + GetSRC(0) + ", " + GetSRC(1) + ")"); break; //SGE case 0x0c: AddVecCode("vec4(greaterThanEqual(" + GetSRC(0) + ", " + GetSRC(1) + "))"); break; //SGE
case 0x0e: AddVecCode("fract(" + GetSRC(0) + ")"); break; //FRC case 0x0e: AddVecCode("fract(" + GetSRC(0) + ")"); break; //FRC
case 0x0f: AddVecCode("floor(" + GetSRC(0) + ")"); break; //FLR case 0x0f: AddVecCode("floor(" + GetSRC(0) + ")"); break; //FLR
case 0x10: AddVecCode("equal(" + GetSRC(0) + ", " + GetSRC(1) + ")"); break; //SEQ 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 0x11: AddVecCode("vec4(0.0f, 0.0f, 0.0f, 0.0f)"); break; //SFL
case 0x12: AddVecCode("greaterThan(" + GetSRC(0) + ", " + GetSRC(1) + ")"); break; //SGT case 0x12: AddVecCode("vec4(greaterThan(" + GetSRC(0) + ", " + GetSRC(1) + "))"); break; //SGT
case 0x13: AddVecCode("lessThanEqual(" + GetSRC(0) + ", " + GetSRC(1) + ")"); break; //SLE case 0x13: AddVecCode("vec4(lessThanEqual(" + GetSRC(0) + ", " + GetSRC(1) + "))"); break; //SLE
case 0x14: AddVecCode("notEqual(" + GetSRC(0) + ", " + GetSRC(1) + ")"); break; //SNE 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 0x15: AddVecCode("vec4(1.0f, 1.0f, 1.0f, 1.0f)"); break; //STR
case 0x16: AddVecCode("sign(" + GetSRC(0) + ", " + GetSRC(1) + ")"); break; //SSG case 0x16: AddVecCode("sign(" + GetSRC(0) + ")"); break; //SSG
default: default:
ConLog.Error("Unknown vp opcode 0x%x", d1.vec_opcode); ConLog.Error("Unknown vp opcode 0x%x", d1.vec_opcode);
@ -276,7 +298,7 @@ void VertexDecompilerThread::Task()
} }
VertexProgram::VertexProgram() VertexProgram::VertexProgram()
: m_decompiler_thread(NULL) : m_decompiler_thread(nullptr)
, id(0) , id(0)
{ {
} }
@ -358,13 +380,7 @@ void VertexProgram::Compile()
void VertexProgram::Delete() void VertexProgram::Delete()
{ {
data.Clear(); data.Clear();
for(u32 i=0; i<parr.params.GetCount(); ++i)
{
parr.params[i].items.Clear();
parr.params[i].type.Clear();
}
parr.params.Clear(); parr.params.Clear();
constants4.Clear();
shader.Clear(); shader.Clear();
if(id) if(id)
@ -374,6 +390,28 @@ void VertexProgram::Delete()
} }
} }
VertexData::VertexData()
: index(0)
, frequency(0)
, stride(0)
, size(0)
, type(0)
, addr(0)
, data()
{
}
void VertexData::Reset()
{
index = 0;
frequency = 0;
stride = 0;
size = 0;
type = 0;
addr = 0;
data.ClearF();
}
void VertexData::Load(u32 start, u32 count) void VertexData::Load(u32 start, u32 count)
{ {
const u32 tsize = GetTypeSize(); const u32 tsize = GetTypeSize();

View File

@ -72,8 +72,7 @@ struct VertexDecompilerThread : public ThreadBase
u32 end : 1; u32 end : 1;
u32 index_const : 1; u32 index_const : 1;
u32 dst : 5; u32 dst : 5;
u32 sca_dst : 5; u32 sca_dst_tmp : 6;
u32 sca_result : 1;
u32 vec_writemask_w : 1; u32 vec_writemask_w : 1;
u32 vec_writemask_z : 1; u32 vec_writemask_z : 1;
u32 vec_writemask_y : 1; u32 vec_writemask_y : 1;
@ -93,17 +92,37 @@ struct VertexDecompilerThread : public ThreadBase
union SRC union SRC
{ {
u16 HEX; union
{
u32 HEX;
struct
{
u32 src0l : 9;
u32 src0h : 8;
};
struct
{
u32 src1 : 17;
};
struct
{
u32 src2l : 11;
u32 src2h : 6;
};
};
struct struct
{ {
u16 reg_type : 2; u32 reg_type : 2;
u16 tmp_src : 5; u32 tmp_src : 6;
u16 swz_w : 2; u32 swz_w : 2;
u16 swz_z : 2; u32 swz_z : 2;
u16 swz_y : 2; u32 swz_y : 2;
u16 swz_x : 2; u32 swz_x : 2;
u16 neg : 1; u32 neg : 1;
}; };
} src[3]; } src[3];
@ -120,12 +139,14 @@ struct VertexDecompilerThread : public ThreadBase
{ {
} }
wxString GetMask(bool is_sca);
wxString GetVecMask(); wxString GetVecMask();
wxString GetScaMask(); wxString GetScaMask();
wxString GetDST(bool isSca = false); wxString GetDST(bool is_sca = false);
wxString GetSRC(const u32 n, bool isSca = false); wxString GetSRC(const u32 n, bool is_sca = false);
void AddVecCode(wxString code, bool src_mask = true); void AddCode(bool is_sca, wxString code, bool src_mask = true);
void AddScaCode(wxString code, bool src_mask = true); void AddVecCode(const wxString& code, bool src_mask = true);
void AddScaCode(const wxString& code, bool src_mask = true);
wxString BuildCode(); wxString BuildCode();
virtual void Task(); virtual void Task();
@ -140,14 +161,6 @@ struct VertexProgram
VertexProgram(); VertexProgram();
~VertexProgram(); ~VertexProgram();
struct Constant4
{
u32 id;
float x, y, z, w;
};
Array<Constant4> constants4;
Array<u32> data; Array<u32> data;
ParamArray parr; ParamArray parr;
@ -174,11 +187,10 @@ struct VertexData
Array<u8> data; Array<u8> data;
VertexData() { memset(this, 0, sizeof(*this)); } VertexData();
~VertexData() { data.Clear(); }
void Reset();
bool IsEnabled() { return size > 0; } bool IsEnabled() { return size > 0; }
void Load(u32 start, u32 count); void Load(u32 start, u32 count);
u32 GetTypeSize(); u32 GetTypeSize();

View File

@ -1,7 +1,7 @@
#include "stdafx.h" #include "stdafx.h"
#include "SysCalls.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) s64 SysCalls::DoFunc(const u32 id)
{ {
switch(id) switch(id)