1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-22 02:32:36 +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

@ -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

View File

@ -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)

View File

@ -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();

View File

@ -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();

View File

@ -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())
{

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)
{
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;

View File

@ -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()

View File

@ -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();
};

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;
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;

View File

@ -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

View File

@ -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 &params[i];
if(type.Cmp(params[i].type.GetPtr()) == 0) return &params[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;

View File

@ -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();

View File

@ -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();

View File

@ -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)