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:
parent
81e874c9e2
commit
f42d4b6572
@ -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));
|
||||
|
@ -381,7 +381,11 @@ public:
|
||||
, m_parent(nullptr)
|
||||
, 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);
|
||||
}
|
||||
|
||||
@ -413,6 +417,14 @@ public:
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -442,16 +454,7 @@ public:
|
||||
|
||||
void decode(TO* op, u32 entry, u32 code) const
|
||||
{
|
||||
InstrCaller<TO>* 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
|
||||
|
@ -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)
|
||||
|
@ -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<typename T> wxString FragmentDecompilerThread::GetSRC(T src)
|
||||
@ -69,7 +106,7 @@ template<typename T> 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<typename T> 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();
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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; i<p.m_textures_count; ++i)
|
||||
{
|
||||
GLTexture& tex = p.m_frame->GetTexture(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; i<m_vertex_count; ++i)
|
||||
{
|
||||
if(!m_vertex_data[i].IsEnabled()) continue;
|
||||
|
||||
@ -409,7 +419,7 @@ void GLGSRender::EnableVertexData(bool indexed_draw)
|
||||
void GLGSRender::DisableVertexData()
|
||||
{
|
||||
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;
|
||||
m_vertex_data[i].data.Clear();
|
||||
@ -419,7 +429,7 @@ void GLGSRender::DisableVertexData()
|
||||
|
||||
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;
|
||||
|
||||
@ -429,11 +439,10 @@ void GLGSRender::LoadVertexData(u32 first, u32 count)
|
||||
|
||||
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 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; i<count; ++id)
|
||||
{
|
||||
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 w = args[i++];
|
||||
|
||||
VertexProgram::Constant4 c;
|
||||
c.id = id;
|
||||
c.x = (float&)x;
|
||||
c.y = (float&)y;
|
||||
c.z = (float&)z;
|
||||
c.w = (float&)w;
|
||||
TransformConstant c(id, (float&)x, (float&)y, (float&)z, (float&)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;
|
||||
@ -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; i<m_textures_count; ++i)
|
||||
{
|
||||
GLTexture& tex = m_frame->GetTexture(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<m_vertex_count; ++i)
|
||||
{
|
||||
m_vertex_data[i].Reset();
|
||||
}
|
||||
|
||||
if(m_vbo.IsCreated())
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
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<u8> 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<u8> m_vdata;
|
||||
VertexProgram m_vertex_progs[16];
|
||||
VertexProgram m_vertex_progs[m_vertex_count];
|
||||
VertexProgram* m_cur_vertex_prog;
|
||||
Array<TransformConstant> m_transform_constants;
|
||||
|
||||
Program m_program;
|
||||
int m_fp_buf_num;
|
||||
int m_vp_buf_num;
|
||||
|
@ -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()
|
||||
|
@ -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();
|
||||
};
|
@ -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<m_buf.GetCount(); ++i)
|
||||
{
|
||||
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.shader = m_buf[i].vp_shader;
|
||||
vp.shader = m_buf[i].vp_shader.GetPtr();
|
||||
|
||||
return i;
|
||||
}
|
||||
@ -35,18 +35,30 @@ int ProgramBuffer::SearchVp(VertexProgram& vp)
|
||||
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;
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
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)
|
||||
{
|
||||
@ -54,13 +66,15 @@ u32 ProgramBuffer::GetProg(u32 fp, u32 vp) const
|
||||
|
||||
if(CmpVP(vp, i) && CmpFP(fp, i))
|
||||
{
|
||||
/*
|
||||
ConLog.Write("Get program (%d):", i);
|
||||
ConLog.Write("*** prog id = %d", m_buf[i].prog_id);
|
||||
ConLog.Write("*** vp id = %d", m_buf[i].vp_id);
|
||||
ConLog.Write("*** fp id = %d", m_buf[i].fp_id);
|
||||
|
||||
ConLog.Write("*** vp shader = %s\n", m_buf[i].vp_shader);
|
||||
ConLog.Write("*** fp shader = %s\n", m_buf[i].fp_shader);
|
||||
ConLog.Write("*** vp shader = \n%s", m_buf[i].vp_shader);
|
||||
ConLog.Write("*** fp shader = \n%s", m_buf[i].fp_shader);
|
||||
*/
|
||||
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("*** fp data size = %d", fp.size);
|
||||
|
||||
ConLog.Write("*** vp shader = %s\n", vp.shader);
|
||||
ConLog.Write("*** fp shader = %s\n", fp.shader);
|
||||
ConLog.Write("*** vp shader = \n%s", vp.shader);
|
||||
ConLog.Write("*** fp shader = \n%s", fp.shader);
|
||||
|
||||
new_buf.prog_id = prog.id;
|
||||
new_buf.vp_id = vp.id;
|
||||
|
@ -8,8 +8,8 @@ struct BufferInfo
|
||||
u32 vp_id;
|
||||
Array<u8> fp_data;
|
||||
Array<u32> vp_data;
|
||||
wxString fp_shader;
|
||||
wxString vp_shader;
|
||||
ArrayString fp_shader;
|
||||
ArrayString vp_shader;
|
||||
};
|
||||
|
||||
struct ProgramBuffer
|
||||
|
@ -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<ParamItem> items;
|
||||
|
||||
ParamType(const ParamFlag _flag, const wxString& _type)
|
||||
@ -37,7 +40,7 @@ struct ParamType
|
||||
{
|
||||
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;
|
||||
@ -49,10 +52,15 @@ struct ParamType
|
||||
|
||||
for(u32 n=0; n<items.GetCount(); ++n)
|
||||
{
|
||||
ret += items[n].location;
|
||||
ret += type;
|
||||
ret += items[n].location.GetPtr();
|
||||
ret += type.GetPtr();
|
||||
ret += " ";
|
||||
ret += items[n].name;
|
||||
ret += items[n].name.GetPtr();
|
||||
if(items[n].value.GetCount())
|
||||
{
|
||||
ret += " = ";
|
||||
ret += items[n].value.GetPtr();
|
||||
}
|
||||
ret += ";\n";
|
||||
}
|
||||
|
||||
@ -68,10 +76,10 @@ struct ParamArray
|
||||
{
|
||||
for(u32 i=0; i<params.GetCount(); ++i)
|
||||
{
|
||||
if(params[i].type.Cmp(type) == 0) return ¶ms[i];
|
||||
if(type.Cmp(params[i].type.GetPtr()) == 0) return ¶ms[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
wxString GetParamFlag(const ParamFlag flag)
|
||||
@ -80,12 +88,32 @@ struct ParamArray
|
||||
{
|
||||
case PARAM_OUT: return "out ";
|
||||
case PARAM_IN: return "in ";
|
||||
case PARAM_CONST: return "uniform ";
|
||||
case PARAM_UNIFORM: return "uniform ";
|
||||
case PARAM_CONST: return "const ";
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
type = GetParamFlag(flag) + type;
|
||||
|
@ -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<parr.params.GetCount(); ++i)
|
||||
{
|
||||
parr.params[i].items.Clear();
|
||||
parr.params[i].type.Clear();
|
||||
}
|
||||
parr.params.Clear();
|
||||
constants4.Clear();
|
||||
shader.Clear();
|
||||
|
||||
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)
|
||||
{
|
||||
const u32 tsize = GetTypeSize();
|
||||
|
@ -72,8 +72,7 @@ struct VertexDecompilerThread : public ThreadBase
|
||||
u32 end : 1;
|
||||
u32 index_const : 1;
|
||||
u32 dst : 5;
|
||||
u32 sca_dst : 5;
|
||||
u32 sca_result : 1;
|
||||
u32 sca_dst_tmp : 6;
|
||||
u32 vec_writemask_w : 1;
|
||||
u32 vec_writemask_z : 1;
|
||||
u32 vec_writemask_y : 1;
|
||||
@ -93,17 +92,37 @@ struct VertexDecompilerThread : public ThreadBase
|
||||
|
||||
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
|
||||
{
|
||||
u16 reg_type : 2;
|
||||
u16 tmp_src : 5;
|
||||
u16 swz_w : 2;
|
||||
u16 swz_z : 2;
|
||||
u16 swz_y : 2;
|
||||
u16 swz_x : 2;
|
||||
u16 neg : 1;
|
||||
u32 reg_type : 2;
|
||||
u32 tmp_src : 6;
|
||||
u32 swz_w : 2;
|
||||
u32 swz_z : 2;
|
||||
u32 swz_y : 2;
|
||||
u32 swz_x : 2;
|
||||
u32 neg : 1;
|
||||
};
|
||||
} src[3];
|
||||
|
||||
@ -120,12 +139,14 @@ struct VertexDecompilerThread : public ThreadBase
|
||||
{
|
||||
}
|
||||
|
||||
wxString GetMask(bool is_sca);
|
||||
wxString GetVecMask();
|
||||
wxString GetScaMask();
|
||||
wxString GetDST(bool isSca = false);
|
||||
wxString GetSRC(const u32 n, bool isSca = false);
|
||||
void AddVecCode(wxString code, bool src_mask = true);
|
||||
void AddScaCode(wxString code, bool src_mask = true);
|
||||
wxString GetDST(bool is_sca = false);
|
||||
wxString GetSRC(const u32 n, bool is_sca = false);
|
||||
void AddCode(bool is_sca, 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();
|
||||
|
||||
virtual void Task();
|
||||
@ -140,14 +161,6 @@ struct VertexProgram
|
||||
VertexProgram();
|
||||
~VertexProgram();
|
||||
|
||||
struct Constant4
|
||||
{
|
||||
u32 id;
|
||||
float x, y, z, w;
|
||||
};
|
||||
|
||||
Array<Constant4> constants4;
|
||||
|
||||
Array<u32> data;
|
||||
ParamArray parr;
|
||||
|
||||
@ -174,11 +187,10 @@ struct VertexData
|
||||
|
||||
Array<u8> 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();
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user