Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

OpenGL renderer:

- Improved Vertex & Fragment Shader Decompilers.
- Implemented fp uniform loader.
- Implemented DXT1 & DXT2 textures decompression.
- Implemented draft cellResc module.
- Updated glext.

PPU Interpreter:
- Fixed VSPLTW, VNMSUBFP, VMRGLW, VMRGLH, VMRGLB, VMRGHW, VMRGHH, VMRGHB instructions.

cellFs:
- Fixed cellFsStat syscall.
  • Loading branch information...
commit f83aa9d5aeb192c1983ba1b34d4284db0f522f4f 1 parent 234e174
@DHrpcs3 DHrpcs3 authored
Showing with 4,009 additions and 839 deletions.
  1. +1,837 −177 GL/glext.h
  2. +10 −4 Utilities/Array.h
  3. +1 −1  rpcs3/Emu/Cell/MFC.h
  4. +2 −2 rpcs3/Emu/Cell/PPUDisAsm.h
  5. +1 −1  rpcs3/Emu/Cell/PPUInstrTable.h
  6. +21 −15 rpcs3/Emu/Cell/PPUInterpreter.h
  7. +1 −1  rpcs3/Emu/Cell/PPUOpcodes.h
  8. +56 −50 rpcs3/Emu/GS/GL/FragmentProgram.cpp
  9. +24 −19 rpcs3/Emu/GS/GL/FragmentProgram.h
  10. +126 −0 rpcs3/Emu/GS/GL/GLBuffers.cpp
  11. +41 −0 rpcs3/Emu/GS/GL/GLBuffers.h
  12. +709 −165 rpcs3/Emu/GS/GL/GLGSRender.cpp
  13. +208 −25 rpcs3/Emu/GS/GL/GLGSRender.h
  14. +50 −1 rpcs3/Emu/GS/GL/GLProcTable.tbl
  15. +5 −7 rpcs3/Emu/GS/GL/Program.cpp
  16. +10 −3 rpcs3/Emu/GS/GL/ShaderParam.h
  17. +47 −24 rpcs3/Emu/GS/GL/VertexProgram.cpp
  18. +2 −2 rpcs3/Emu/GS/GL/VertexProgram.h
  19. +1 −1  rpcs3/Emu/GS/GSManager.cpp
  20. +6 −3 rpcs3/Emu/GS/GSRender.cpp
  21. +111 −1 rpcs3/Emu/GS/GSRender.h
  22. +1 −1  rpcs3/Emu/GS/Null/NullGSRender.h
  23. +131 −8 rpcs3/Emu/GS/RSXThread.h
  24. +2 −2 rpcs3/Emu/Io/Pad.cpp
  25. +12 −3 rpcs3/Emu/Io/PadHandler.h
  26. +16 −3 rpcs3/Emu/Memory/MemoryBlock.h
  27. +14 −14 rpcs3/Emu/SysCalls/FuncList.cpp
  28. +449 −4 rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp
  29. +39 −0 rpcs3/Emu/SysCalls/Modules/cellResc.cpp
  30. +1 −1  rpcs3/Emu/SysCalls/SysCalls.cpp
  31. +1 −23 rpcs3/Emu/SysCalls/SysCalls.h
  32. +33 −1 rpcs3/Emu/SysCalls/lv2/SC_Event.cpp
  33. +10 −2 rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp
  34. +1 −265 rpcs3/Emu/SysCalls/lv2/SC_GCM.cpp
  35. +6 −0 rpcs3/Emu/SysCalls/lv2/SC_Pad.cpp
  36. +4 −0 rpcs3/Emu/SysCalls/lv2/SC_Process.cpp
  37. +7 −6 rpcs3/Emu/System.cpp
  38. +4 −0 rpcs3/Emu/event.h
  39. +3 −2 rpcs3/Gui/InterpreterDisAsm.cpp
  40. +2 −2 rpcs3/Loader/ELF64.cpp
  41. +1 −0  rpcs3/rpcs3.vcxproj
  42. +3 −0  rpcs3/rpcs3.vcxproj.filters
View
2,014 GL/glext.h
1,837 additions, 177 deletions not shown
View
14 Utilities/Array.h
@@ -88,11 +88,14 @@ template<typename T> class Array
return m_count - 1;
}
- inline bool AddCpy(const u32 pos, const T* data, u64 count = 1)
+ inline bool AddCpy(const u32 pos, const T* data, u32 count = 1)
{
if(!InsertRoom(pos, count)) return false;
- memcpy(m_array + pos, data, sizeof(T) * count);
+ for(u32 i=0; i<count; ++i)
+ {
+ new (m_array + pos + i) T(data[i]);
+ }
return true;
}
@@ -102,11 +105,14 @@ template<typename T> class Array
return AddCpy(pos, &data);
}
- inline u32 AddCpy(const T* data, u64 count = 1)
+ inline u32 AddCpy(const T* data, u32 count = 1)
{
_InsertRoomEnd(count);
- memcpy(m_array + m_count - count, data, sizeof(T)*count);
+ for(u32 i=0; i<count; ++i)
+ {
+ new (m_array + m_count - count + i) T(data[i]);
+ }
return m_count - count;
}
View
2  rpcs3/Emu/Cell/MFC.h
@@ -236,7 +236,7 @@ struct MFC
break;
default:
- ConLog.Error("Unknown MFC cmd.");
+ ConLog.Error("Unknown MFC cmd. (opcode=0x%x, cmd=0x%x)", op, cmd);
break;
}
}
View
4 rpcs3/Emu/Cell/PPUDisAsm.h
@@ -426,9 +426,9 @@ class PPU_DisAsm
{
DisAsm_V3("vmulouh", vd, va, vb);
}
- void VNMSUBFP(u32 vd, u32 va, u32 vb, u32 vc)
+ void VNMSUBFP(u32 vd, u32 va, u32 vc, u32 vb)
{
- DisAsm_V4("vnmsubfp", vd, va, vb, vc);
+ DisAsm_V4("vnmsubfp", vd, va, vc, vb);
}
void VNOR(u32 vd, u32 va, u32 vb)
{
View
2  rpcs3/Emu/Cell/PPUInstrTable.h
@@ -273,7 +273,7 @@ namespace PPU_instr
bind_instr(g04_list, VMSUMUBM, VD, VA, VB, VC);
bind_instr(g04_list, VMSUMUHM, VD, VA, VB, VC);
bind_instr(g04_list, VMSUMUHS, VD, VA, VB, VC);
- bind_instr(g04_list, VNMSUBFP, VD, VA, VB, VC);
+ bind_instr(g04_list, VNMSUBFP, VD, VA, VC, VB);
bind_instr(g04_list, VPERM, VD, VA, VB, VC);
bind_instr(g04_list, VSEL, VD, VA, VB, VC);
bind_instr(g04_list, VSLDOI, VD, VA, VB, VSH);
View
36 rpcs3/Emu/Cell/PPUInterpreter.h
@@ -949,50 +949,56 @@ class PPU_Interpreter : public PPU_Opcodes
}
void VMRGHB(u32 vd, u32 va, u32 vb)
{
+ VPR_reg VA = CPU.VPR[va];
+ VPR_reg VB = CPU.VPR[vb];
for (uint h = 0; h < 8; h++)
{
- CPU.VPR[vd]._u8[h*2] = CPU.VPR[va]._u8[h];
- CPU.VPR[vd]._u8[h*2 + 1] = CPU.VPR[vb]._u8[h];
+ CPU.VPR[vd]._u8[15 - h*2] = VA._u8[15 - h];
+ CPU.VPR[vd]._u8[15 - h*2 - 1] = VB._u8[15 - h];
}
}
void VMRGHH(u32 vd, u32 va, u32 vb)
{
+ VPR_reg VA = CPU.VPR[va];
+ VPR_reg VB = CPU.VPR[vb];
for (uint w = 0; w < 4; w++)
{
- CPU.VPR[vd]._u16[w*2] = CPU.VPR[va]._u16[w];
- CPU.VPR[vd]._u16[w*2 + 1] = CPU.VPR[vb]._u16[w];
+ CPU.VPR[vd]._u16[7 - w*2] = VA._u16[7 - w];
+ CPU.VPR[vd]._u16[7 - w*2 - 1] = VB._u16[7 - w];
}
}
void VMRGHW(u32 vd, u32 va, u32 vb)
{
+ VPR_reg VA = CPU.VPR[va];
+ VPR_reg VB = CPU.VPR[vb];
for (uint d = 0; d < 2; d++)
{
- CPU.VPR[vd]._u32[d*2] = CPU.VPR[va]._u32[d];
- CPU.VPR[vd]._u32[d*2 + 1] = CPU.VPR[vb]._u32[d];
+ CPU.VPR[vd]._u32[3 - d*2] = VA._u32[3 - d];
+ CPU.VPR[vd]._u32[3 - d*2 - 1] = VB._u32[3 - d];
}
}
void VMRGLB(u32 vd, u32 va, u32 vb)
{
for (uint h = 0; h < 8; h++)
{
- CPU.VPR[vd]._u8[h*2] = CPU.VPR[va]._u8[h + 8];
- CPU.VPR[vd]._u8[h*2 + 1] = CPU.VPR[vb]._u8[h + 8];
+ CPU.VPR[vd]._u8[15 - h*2] = CPU.VPR[va]._u8[7 - h];
+ CPU.VPR[vd]._u8[15 - h*2 - 1] = CPU.VPR[vb]._u8[7 - h];
}
}
void VMRGLH(u32 vd, u32 va, u32 vb)
{
for (uint w = 0; w < 4; w++)
{
- CPU.VPR[vd]._u16[w*2] = CPU.VPR[va]._u16[w + 4];
- CPU.VPR[vd]._u16[w*2 + 1] = CPU.VPR[vb]._u16[w + 4];
+ CPU.VPR[vd]._u16[7 - w*2] = CPU.VPR[va]._u16[3 - w];
+ CPU.VPR[vd]._u16[7 - w*2 - 1] = CPU.VPR[vb]._u16[3 - w];
}
}
void VMRGLW(u32 vd, u32 va, u32 vb)
{
for (uint d = 0; d < 2; d++)
{
- CPU.VPR[vd]._u32[d*2] = CPU.VPR[va]._u32[d + 2];
- CPU.VPR[vd]._u32[d*2 + 1] = CPU.VPR[vb]._u32[d + 2];
+ CPU.VPR[vd]._u32[3 - d*2] = CPU.VPR[va]._u32[1 - d];
+ CPU.VPR[vd]._u32[3 - d*2 - 1] = CPU.VPR[vb]._u32[1 - d];
}
}
void VMSUMMBM(u32 vd, u32 va, u32 vb, u32 vc)
@@ -1166,11 +1172,11 @@ class PPU_Interpreter : public PPU_Opcodes
CPU.VPR[vd]._u32[w] = (u32)CPU.VPR[va]._u16[w*2] * (u32)CPU.VPR[vb]._u16[w*2];
}
}
- void VNMSUBFP(u32 vd, u32 va, u32 vb, u32 vc)
+ void VNMSUBFP(u32 vd, u32 va, u32 vc, u32 vb)
{
for (uint w = 0; w < 4; w++)
{
- CPU.VPR[vd]._f[w] = (double)CPU.VPR[vb]._f[w] - (double)CPU.VPR[va]._f[w] * (double)CPU.VPR[vc]._f[w];
+ CPU.VPR[vd]._f[w] = -(CPU.VPR[va]._f[w] * CPU.VPR[vc]._f[w] - CPU.VPR[vb]._f[w]);
}
}
void VNOR(u32 vd, u32 va, u32 vb)
@@ -1611,7 +1617,7 @@ class PPU_Interpreter : public PPU_Opcodes
{
assert(uimm5 < 4);
- u32 word = CPU.VPR[vb]._u32[uimm5];
+ u32 word = CPU.VPR[vb]._u32[3 - uimm5];
for (uint w = 0; w < 4; w++)
{
View
2  rpcs3/Emu/Cell/PPUOpcodes.h
@@ -535,7 +535,7 @@ class PPU_Opcodes
virtual void VMULOSH(u32 vd, u32 va, u32 vb) = 0;
virtual void VMULOUB(u32 vd, u32 va, u32 vb) = 0;
virtual void VMULOUH(u32 vd, u32 va, u32 vb) = 0;
- virtual void VNMSUBFP(u32 vd, u32 va, u32 vb, u32 vc) = 0;
+ virtual void VNMSUBFP(u32 vd, u32 va, u32 vc, u32 vb) = 0;
virtual void VNOR(u32 vd, u32 va, u32 vb) = 0;
virtual void VOR(u32 vd, u32 va, u32 vb) = 0;
virtual void VPERM(u32 vd, u32 va, u32 vb, u32 vc) = 0;
View
106 rpcs3/Emu/GS/GL/FragmentProgram.cpp
@@ -1,50 +1,49 @@
#include "stdafx.h"
#include "FragmentProgram.h"
-void FragmentDecompilerThread::AddCode(wxString code)
+void FragmentDecompilerThread::AddCode(wxString code, bool append_mask)
{
if(!src0.exec_if_eq && !src0.exec_if_gr && !src0.exec_if_lt) return;
+ const wxString mask = GetMask();
wxString cond = wxEmptyString;
if(!src0.exec_if_gr || !src0.exec_if_lt || !src0.exec_if_eq)
{
- if(src0.exec_if_gr)
+ static const char f[4] = {'x', 'y', 'z', 'w'};
+
+ wxString swizzle = wxEmptyString;
+ swizzle += f[src0.cond_swizzle_x];
+ swizzle += f[src0.cond_swizzle_y];
+ swizzle += f[src0.cond_swizzle_z];
+ swizzle += f[src0.cond_swizzle_w];
+
+ if(src0.exec_if_gr && src0.exec_if_eq)
{
- cond = ">";
+ cond = "greaterThanEqual";
}
- else if(src0.exec_if_lt)
+ else if(src0.exec_if_lt && src0.exec_if_eq)
{
- cond = "<";
+ cond = "lessThanEqual";
}
- else if(src0.exec_if_eq)
+ else if(src0.exec_if_gr && src0.exec_if_lt)
{
- cond = "=";
+ cond = "notEqual";
}
-
- if(src0.exec_if_eq)
+ else if(src0.exec_if_gr)
{
- cond += "=";
+ cond = "greaterThan";
}
- else
+ else if(src0.exec_if_lt)
{
- if(src0.exec_if_gr && src0.exec_if_lt)
- {
- cond = "!=";
- }
+ cond = "lessThan";
+ }
+ else //if(src0.exec_if_eq)
+ {
+ cond = "equal";
}
- }
-
- if(cond.Len())
- {
- static const char f[4] = {'x', 'y', 'z', 'w'};
- wxString swizzle = wxEmptyString;
- swizzle += f[src0.cond_swizzle_x];
- swizzle += f[src0.cond_swizzle_y];
- swizzle += f[src0.cond_swizzle_z];
- swizzle += f[src0.cond_swizzle_w];
- cond = wxString::Format("if(rc.%s %s 0.0) ", swizzle, cond);
+ cond = wxString::Format("if(all(%s(%s.%s, vec4(0, 0, 0, 0)))) ", cond, AddCond(dst.no_dest), swizzle);
//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;
@@ -73,7 +72,8 @@ void FragmentDecompilerThread::AddCode(wxString code)
code = "clamp(" + code + ", 0.0, 1.0)";
}
- code = cond + (dst.set_cond ? AddCond(dst.fp16) : AddReg(dst.dest_reg, dst.fp16)) + GetMask() + " = " + code + GetMask();
+ code = cond + (dst.set_cond ? AddCond(dst.fp16) : AddReg(dst.dest_reg, dst.fp16)) + mask
+ + " = " + code + (append_mask ? mask : wxEmptyString);
main += "\t" + code + ";\n";
}
@@ -82,25 +82,30 @@ wxString FragmentDecompilerThread::GetMask()
{
wxString ret = wxEmptyString;
- static const char dst_mask[2][4] =
+ static const char dst_mask[4] =
{
- {'x', 'y', 'z', 'w'},
- {'r', 'g', 'b', 'a'}
+ 'x', 'y', 'z', 'w',
};
- if(dst.mask_x) ret += dst_mask[dst.dest_reg == 0][0];
- if(dst.mask_y) ret += dst_mask[dst.dest_reg == 0][1];
- if(dst.mask_z) ret += dst_mask[dst.dest_reg == 0][2];
- if(dst.mask_w) ret += dst_mask[dst.dest_reg == 0][3];
+ if(dst.mask_x) ret += dst_mask[0];
+ if(dst.mask_y) ret += dst_mask[1];
+ if(dst.mask_z) ret += dst_mask[2];
+ if(dst.mask_w) ret += dst_mask[3];
- return ret.IsEmpty() || strncmp(ret, dst_mask[dst.dest_reg == 0], 4) == 0 ? wxEmptyString : ("." + ret);
+ return ret.IsEmpty() || strncmp(ret, dst_mask, 4) == 0 ? wxEmptyString : ("." + ret);
}
wxString FragmentDecompilerThread::AddReg(u32 index, int fp16)
{
- //if(!index) return "gl_FragColor";
+ //if(!index && !fp16) return "gl_FragColor";
return m_parr.AddParam((index || fp16) ? PARAM_NONE : PARAM_OUT, "vec4",
- wxString::Format((fp16 ? "h%d" : "r%d"), index), (index || fp16) ? -1 : 0);
+ wxString::Format((fp16 ? "h%u" : "r%u"), index), (index || fp16) ? -1 : 0);
+}
+
+bool FragmentDecompilerThread::HasReg(u32 index, int fp16)
+{
+ return m_parr.HasParam((index || fp16) ? PARAM_NONE : PARAM_OUT, "vec4",
+ wxString::Format((fp16 ? "h%u" : "r%u"), index));
}
wxString FragmentDecompilerThread::AddCond(int fp16)
@@ -117,7 +122,7 @@ wxString FragmentDecompilerThread::AddConst()
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++),
+ return m_parr.AddParam(PARAM_UNIFORM, "vec4", wxString::Format("fc%u", m_size + 4 * 4),
wxString::Format("vec4(%f, %f, %f, %f)", (float&)x, (float&)y, (float&)z, (float&)w));
}
@@ -130,8 +135,6 @@ template<typename T> wxString FragmentDecompilerThread::GetSRC(T src)
{
wxString ret = wxEmptyString;
- bool is_color = src.reg_type == 0 || (src.reg_type == 1 && dst.src_attr_reg_num >= 1 && dst.src_attr_reg_num <= 3);
-
switch(src.reg_type)
{
case 0: //tmp
@@ -177,9 +180,7 @@ template<typename T> wxString FragmentDecompilerThread::GetSRC(T src)
break;
}
- static const char f_pos[4] = {'x', 'y', 'z', 'w'};
- static const char f_col[4] = {'r', 'g', 'b', 'a'};
- const char *f = is_color ? f_col : f_pos;
+ static const char f[4] = {'x', 'y', 'z', 'w'};
wxString swizzle = wxEmptyString;
swizzle += f[src.swizzle_x];
@@ -199,6 +200,11 @@ wxString FragmentDecompilerThread::BuildCode()
{
wxString p = wxEmptyString;
+ if(!m_parr.HasParam(PARAM_OUT, "vec4", "r0") && m_parr.HasParam(PARAM_NONE, "vec4", "h0"))
+ {
+ main += "\t" + m_parr.AddParam(PARAM_OUT, "vec4", "r0", 0) + " = " + "h0;\n";
+ }
+
for(u32 i=0; i<m_parr.params.GetCount(); ++i)
{
p += m_parr.params[i].Format();
@@ -227,16 +233,16 @@ void FragmentDecompilerThread::Task()
m_offset = 4 * 4;
- switch(dst.opcode)
+ switch(dst.opcode | (src1.opcode_is_branch << 6))
{
case 0x00: break; //NOP
case 0x01: AddCode(GetSRC(src0)); break; //MOV
case 0x02: AddCode("(" + GetSRC(src0) + " * " + GetSRC(src1) + ")"); break; //MUL
case 0x03: AddCode("(" + GetSRC(src0) + " + " + GetSRC(src1) + ")"); break; //ADD
case 0x04: AddCode("(" + GetSRC(src0) + " * " + GetSRC(src1) + " + " + GetSRC(src2) + ")"); break; //MAD
- case 0x05: AddCode("dot(" + GetSRC(src0) + ".xyz, " + GetSRC(src1) + ".xyz)"); break; // DP3
- case 0x06: AddCode("dot(" + GetSRC(src0) + ", " + GetSRC(src1) + ")"); break; // DP4
- case 0x07: AddCode("distance(" + GetSRC(src0) + ", " + GetSRC(src1) + ")"); break; // DST
+ case 0x05: AddCode("vec4(dot(" + GetSRC(src0) + ".xyz, " + GetSRC(src1) + ".xyz)).xxxx"); break; // DP3
+ case 0x06: AddCode("vec4(dot(" + GetSRC(src0) + ", " + GetSRC(src1) + ")).xxxx"); break; // DP4
+ case 0x07: AddCode("vec4(distance(" + GetSRC(src0) + ", " + GetSRC(src1) + ")).xxxx"); break; // DST
case 0x08: AddCode("min(" + GetSRC(src0) + ", " + GetSRC(src1) + ")"); break; // MIN
case 0x09: AddCode("max(" + GetSRC(src0) + ", " + GetSRC(src1) + ")"); break; // MAX
case 0x0a: AddCode("vec4(lessThan(" + GetSRC(src0) + ", " + GetSRC(src1) + "))"); break; // SLT
@@ -286,10 +292,10 @@ void FragmentDecompilerThread::Task()
//case 0x35: break; // BEMLUM
//case 0x36: break; // REFL
//case 0x37: break; // TIMESWTEX
- //case 0x38: break; // DP2
- //case 0x39: break; // NRM
+ case 0x38: AddCode("vec4(dot(" + GetSRC(src0) + ".xy, " + GetSRC(src1) + ".xy)).xxxx"); break; // DP2
+ case 0x39: AddCode("normalize(" + GetSRC(src0) + ".xyz)"); break; // NRM
case 0x3a: AddCode("(" + GetSRC(src0) + " / " + GetSRC(src1) + ")"); break; // DIV
- case 0x3b: AddCode("(" + GetSRC(src0) + " / " + GetSRC(src1) + ")"); break; // DIVSQ
+ case 0x3b: AddCode("(" + GetSRC(src0) + " / sqrt(" + GetSRC(src1) + "))"); break; // DIVSQ
//case 0x3c: break; // LIF
case 0x3d: break; // FENCT
case 0x3e: break; // FENCB
View
43 rpcs3/Emu/GS/GL/FragmentProgram.h
@@ -33,22 +33,24 @@ struct FragmentDecompilerThread : public ThreadBase
struct
{
- u32 reg_type : 2;
- u32 tmp_reg_index : 6;
- u32 fp16 : 1;
- u32 swizzle_x : 2;
- u32 swizzle_y : 2;
- u32 swizzle_z : 2;
- u32 swizzle_w : 2;
- u32 neg : 1;
- u32 exec_if_lt : 1;
- u32 exec_if_eq : 1;
- u32 exec_if_gr : 1;
- u32 cond_swizzle_x : 2;
- u32 cond_swizzle_y : 2;
- u32 cond_swizzle_z : 2;
- u32 cond_swizzle_w : 2;
- u32 abs : 1;
+ u32 reg_type : 2;
+ u32 tmp_reg_index : 6;
+ u32 fp16 : 1;
+ u32 swizzle_x : 2;
+ u32 swizzle_y : 2;
+ u32 swizzle_z : 2;
+ u32 swizzle_w : 2;
+ u32 neg : 1;
+ u32 exec_if_lt : 1;
+ u32 exec_if_eq : 1;
+ u32 exec_if_gr : 1;
+ u32 cond_swizzle_x : 2;
+ u32 cond_swizzle_y : 2;
+ u32 cond_swizzle_z : 2;
+ u32 cond_swizzle_w : 2;
+ u32 abs : 1;
+ u32 cond_mod_reg_index : 1;
+ u32 cond_reg_index : 1;
};
} src0;
@@ -67,8 +69,8 @@ struct FragmentDecompilerThread : public ThreadBase
u32 swizzle_w : 2;
u32 neg : 1;
u32 abs : 1;
- u32 input_prec : 2;
- u32 : 7;
+ u32 input_mod_src0 : 3;
+ u32 : 6;
u32 scale : 3;
u32 opcode_is_branch : 1;
};
@@ -91,6 +93,7 @@ struct FragmentDecompilerThread : public ThreadBase
u32 abs : 1;
u32 addr_reg : 11;
u32 use_index_reg : 1;
+ u32 perspective_corr: 1;
};
} src2;
@@ -115,8 +118,9 @@ struct FragmentDecompilerThread : public ThreadBase
wxString GetMask();
- void AddCode(wxString code);
+ void AddCode(wxString code, bool append_mask = true);
wxString AddReg(u32 index, int fp16);
+ bool HasReg(u32 index, int fp16);
wxString AddCond(int fp16);
wxString AddConst();
wxString AddTex();
@@ -140,6 +144,7 @@ struct ShaderProgram
u32 size;
u32 addr;
+ u32 offset;
wxString shader;
u32 id;
View
126 rpcs3/Emu/GS/GL/GLBuffers.cpp
@@ -123,4 +123,130 @@ void GLvao::Delete()
bool GLvao::IsCreated() const
{
return m_id != 0;
+}
+
+GLrbo::GLrbo()
+{
+}
+
+GLrbo::~GLrbo()
+{
+}
+
+void GLrbo::Create(u32 count)
+{
+ if(m_id.GetCount())
+ {
+ return;
+ }
+
+ m_id.SetCount(count);
+ glGenRenderbuffers(count, m_id.GetPtr());
+}
+
+void GLrbo::Bind(u32 num) const
+{
+ assert(num < m_id.GetCount());
+
+ glBindRenderbuffer(GL_RENDERBUFFER, m_id[num]);
+}
+
+void GLrbo::Storage(u32 format, u32 width, u32 height)
+{
+ glRenderbufferStorage(GL_RENDERBUFFER, format, width, height);
+}
+
+void GLrbo::Unbind()
+{
+ glBindRenderbuffer(GL_RENDERBUFFER, 0);
+}
+
+void GLrbo::Delete()
+{
+ glDeleteRenderbuffers(m_id.GetCount(), m_id.GetPtr());
+ m_id.Clear();
+}
+
+bool GLrbo::IsCreated() const
+{
+ return m_id.GetCount();
+}
+
+u32 GLrbo::GetId(u32 num) const
+{
+ assert(num < m_id.GetCount());
+ return m_id[num];
+}
+
+GLfbo::GLfbo()
+{
+}
+
+GLfbo::~GLfbo()
+{
+}
+
+void GLfbo::Create()
+{
+ if(m_id)
+ {
+ return;
+ }
+
+ glGenFramebuffers(1, &m_id);
+}
+
+void GLfbo::Bind(u32 type, int id)
+{
+ if(id != -1)
+ assert(m_id);
+
+ m_type = type;
+ glBindFramebuffer(m_type, id == -1 ? m_id : id);
+}
+
+void GLfbo::Texture1D(u32 attachment, u32 texture, int level)
+{
+ glFramebufferTexture1D(m_type, attachment, GL_TEXTURE_1D, texture, level);
+}
+
+void GLfbo::Texture2D(u32 attachment, u32 texture, int level)
+{
+ glFramebufferTexture2D(m_type, attachment, GL_TEXTURE_2D, texture, level);
+}
+
+void GLfbo::Texture3D(u32 attachment, u32 texture, int zoffset, int level)
+{
+ glFramebufferTexture3D(m_type, attachment, GL_TEXTURE_3D, texture, level, zoffset);
+}
+
+void GLfbo::Renderbuffer(u32 attachment, u32 renderbuffer)
+{
+ glFramebufferRenderbuffer(m_type, attachment, GL_RENDERBUFFER, renderbuffer);
+}
+
+void GLfbo::Blit(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, u32 mask, u32 filter)
+{
+ glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
+}
+
+void GLfbo::Unbind()
+{
+ Unbind(m_type);
+}
+
+void GLfbo::Unbind(u32 type)
+{
+ glBindFramebuffer(type, 0);
+}
+
+void GLfbo::Delete()
+{
+ glDeleteFramebuffers(1, &m_id);
+ m_id = 0;
+}
+
+bool GLfbo::IsCreated() const
+{
+ return m_id != 0;
}
View
41 rpcs3/Emu/GS/GL/GLBuffers.h
@@ -46,4 +46,45 @@ class GLvao
static void Unbind();
void Delete();
bool IsCreated() const;
+};
+
+class GLrbo
+{
+protected:
+ Array<GLuint> m_id;
+
+public:
+ GLrbo();
+ ~GLrbo();
+
+ void Create(u32 count = 1);
+ void Bind(u32 num = 0) const;
+ void Storage(u32 format, u32 width, u32 height);
+ static void Unbind();
+ void Delete();
+ bool IsCreated() const;
+ u32 GetId(u32 num) const;
+};
+
+class GLfbo
+{
+protected:
+ GLuint m_id;
+ GLuint m_type;
+
+public:
+ GLfbo();
+ ~GLfbo();
+
+ void Create();
+ void Bind(u32 type = GL_FRAMEBUFFER, int id = -1);
+ void Texture1D(u32 attachment, u32 texture, int level = 0);
+ void Texture2D(u32 attachment, u32 texture, int level = 0);
+ void Texture3D(u32 attachment, u32 texture, int zoffset = 0, int level = 0);
+ void Renderbuffer(u32 attachment, u32 renderbuffer);
+ void Blit(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, u32 mask, u32 filter);
+ void Unbind();
+ static void Unbind(u32 type);
+ void Delete();
+ bool IsCreated() const;
};
View
874 rpcs3/Emu/GS/GL/GLGSRender.cpp
@@ -3,7 +3,7 @@
#include "Emu/Cell/PPCInstrTable.h"
#define CMD_DEBUG 0
-#define DUMP_VERTEX_DATA 0
+#define DUMP_VERTEX_DATA 1
#if CMD_DEBUG
#define CMD_LOG ConLog.Write
@@ -32,7 +32,7 @@ void checkForGlError(const char* situation)
#endif
GLGSFrame::GLGSFrame()
- : GSFrame(NULL, "GSFrame[OpenGL]")
+ : GSFrame(nullptr, "GSFrame[OpenGL]")
, m_frames(0)
{
canvas = new wxGLCanvas(this, wxID_ANY, NULL);
@@ -80,7 +80,8 @@ void GLGSFrame::SetViewport(int x, int y, u32 w, u32 h)
}
GLGSRender::GLGSRender()
- : m_frame(nullptr)
+ : GSRender()
+ , m_frame(nullptr)
, m_rsx_thread(nullptr)
, m_fp_buf_num(-1)
, m_vp_buf_num(-1)
@@ -125,14 +126,9 @@ void GLRSXThread::Task()
InitProcTable();
glEnable(GL_TEXTURE_2D);
+ glEnable(GL_SCISSOR_TEST);
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;
@@ -145,49 +141,10 @@ void GLRSXThread::Task()
const u32 get = re(p.m_ctrl->get);
const u32 put = re(p.m_ctrl->put);
- if(put <= get || !Emu.IsRunned())
+ if(put == get || !Emu.IsRunned())
{
- SemaphorePostAndWait(p.m_sem_flush);
-
- if(p.m_draw)
- {
- p.m_draw = false;
-
- if(p.m_skip_frames)
- {
- if(!draw)
- {
- if(skipped++ >= p.m_skip_frames)
- {
- skipped = 0;
- draw = true;
- }
- }
- else
- {
- if(drawed++ >= p.m_draw_frames)
- {
- drawed = 0;
- draw = false;
- }
- }
- }
-
- if(draw)
- {
- p.m_frame->Flip();
- }
-
- p.m_gcm_current_buffer = ++p.m_gcm_current_buffer % p.m_gcm_buffers_count;
- p.m_flip_status = 0;
- if(p.m_flip_handler)
- {
- p.m_flip_handler.Handle(1, 0, 0);
- p.m_flip_handler.Branch(false);
- }
-
- if(SemaphorePostAndWait(p.m_sem_flip)) continue;
- }
+ if(put == get)
+ SemaphorePostAndWait(p.m_sem_flush);
Sleep(1);
continue;
@@ -197,27 +154,29 @@ void GLRSXThread::Task()
const u32 cmd = Memory.Read32(p.m_ioAddress + get);
const u32 count = (cmd >> 18) & 0x7ff;
//if(cmd == 0) continue;
+
if(cmd & CELL_GCM_METHOD_FLAG_JUMP)
{
u32 addr = cmd & ~(CELL_GCM_METHOD_FLAG_JUMP | CELL_GCM_METHOD_FLAG_NON_INCREMENT);
- addr -= 0x1000;
- ConLog.Warning("rsx jump(0x%x) #addr=0x%x, cmd=0x%x, get=0x%x, put=0x%x", addr, p.m_ioAddress + get, cmd, get, put);
+ //ConLog.Warning("rsx jump(0x%x) #addr=0x%x, cmd=0x%x, get=0x%x, put=0x%x", addr, p.m_ioAddress + get, cmd, get, put);
re(p.m_ctrl->get, addr);
continue;
}
if(cmd & CELL_GCM_METHOD_FLAG_CALL)
{
call_stack.Push(get + 4);
- u32 addr = cmd & ~CELL_GCM_METHOD_FLAG_CALL;
- ConLog.Warning("rsx call(0x%x) #0x%x - 0x%x", addr, cmd, get);
- p.m_ctrl->get = re32(addr);
+ u32 offs = cmd & ~CELL_GCM_METHOD_FLAG_CALL;
+ u32 addr = p.m_ioAddress + offs;
+ //ConLog.Warning("rsx call(0x%x) #0x%x - 0x%x - 0x%x", offs, addr, cmd, get);
+ p.m_ctrl->get = re32(offs);
continue;
}
- if(cmd & CELL_GCM_METHOD_FLAG_RETURN)
+ if(cmd == CELL_GCM_METHOD_FLAG_RETURN)
{
- u32 addr = call_stack.Pop();
- p.m_ctrl->get = re32(addr);
- ConLog.Warning("rsx return(0x%x)", addr);
+ //ConLog.Warning("rsx return!");
+ u32 get = call_stack.Pop();
+ //ConLog.Warning("rsx return(0x%x)", get);
+ p.m_ctrl->get = re32(get);
continue;
}
if(cmd & CELL_GCM_METHOD_FLAG_NON_INCREMENT)
@@ -262,13 +221,15 @@ void GLGSRender::Init(const u32 ioAddress, const u32 ioSize, const u32 ctrlAddre
m_draw_frames = 1;
m_skip_frames = 0;
+ m_width = 720;
+ m_height = 576;
m_frame->Show();
m_ioAddress = ioAddress;
m_ioSize = ioSize;
m_ctrlAddress = ctrlAddress;
- m_localAddress = localAddress;
+ m_local_mem_addr = localAddress;
m_ctrl = (CellGcmControl*)Memory.GetMemFromAddr(m_ctrlAddress);
m_cur_vertex_prog = nullptr;
@@ -298,18 +259,18 @@ void GLGSRender::Close()
void GLGSRender::EnableVertexData(bool indexed_draw)
{
- Array<u32> offset_list;
+ static u32 offset_list[16];
u32 cur_offset = 0;
for(u32 i=0; i<16; ++i)
{
- offset_list.AddCpy(cur_offset);
+ offset_list[i] = cur_offset;
- if(!m_vertex_data[i].IsEnabled()) continue;
+ if(!m_vertex_data[i].IsEnabled() || !m_vertex_data[i].addr) continue;
cur_offset += m_vertex_data[i].data.GetCount();
const u32 pos = m_vdata.GetCount();
- m_vdata.SetCount(pos + m_vertex_data[i].data.GetCount());
+ m_vdata.InsertRoomEnd(m_vertex_data[i].data.GetCount());
memcpy(&m_vdata[pos], &m_vertex_data[i].data[0], m_vertex_data[i].data.GetCount());
}
@@ -419,13 +380,49 @@ void GLGSRender::EnableVertexData(bool indexed_draw)
if(m_vertex_data[i].type >= 1 && m_vertex_data[i].type <= 7)
{
- u32 gltype = gl_types[m_vertex_data[i].type - 1];
- bool normalized = gl_normalized[m_vertex_data[i].type - 1];
+ if(!m_vertex_data[i].addr)
+ {
+ switch(m_vertex_data[i].type)
+ {
+ case 5:
+ case 1:
+ switch(m_vertex_data[i].size)
+ {
+ case 1: glVertexAttrib1s(i, (GLshort&)m_vertex_data[i].data[0]); break;
+ case 2: glVertexAttrib2sv(i, (GLshort*)&m_vertex_data[i].data[0]); break;
+ case 3: glVertexAttrib3sv(i, (GLshort*)&m_vertex_data[i].data[0]); break;
+ case 4: glVertexAttrib4sv(i, (GLshort*)&m_vertex_data[i].data[0]); break;
+ }
+ break;
+
+ case 2:
+ switch(m_vertex_data[i].size)
+ {
+ case 1: glVertexAttrib1f(i, (GLfloat&)m_vertex_data[i].data[0]); break;
+ case 2: glVertexAttrib2fv(i, (GLfloat*)&m_vertex_data[i].data[0]); break;
+ case 3: glVertexAttrib3fv(i, (GLfloat*)&m_vertex_data[i].data[0]); break;
+ case 4: glVertexAttrib4fv(i, (GLfloat*)&m_vertex_data[i].data[0]); break;
+ }
+ break;
+
+ case 6:
+ case 4:
+ glVertexAttrib4ubv(i, (GLubyte*)&m_vertex_data[i].data[0]);
+ break;
+ }
- glEnableVertexAttribArray(i);
- checkForGlError("glEnableVertexAttribArray");
- glVertexAttribPointer(i, m_vertex_data[i].size, gltype, normalized, 0, (void*)offset_list[i]);
- checkForGlError("glVertexAttribPointer");
+ checkForGlError("glVertexAttrib");
+ }
+ else
+ {
+ u32 gltype = gl_types[m_vertex_data[i].type - 1];
+ bool normalized = gl_normalized[m_vertex_data[i].type - 1];
+
+ glEnableVertexAttribArray(i);
+ checkForGlError("glEnableVertexAttribArray");
+ glVertexAttribPointer(i, m_vertex_data[i].size, gltype, normalized, 0, (void*)offset_list[i]);
+ checkForGlError("glVertexAttribPointer");
+ }
}
}
}
@@ -435,9 +432,10 @@ void GLGSRender::DisableVertexData()
m_vdata.Clear();
for(u32 i=0; i<m_vertex_count; ++i)
{
- if(!m_vertex_data[i].IsEnabled()) continue;
+ if(!m_vertex_data[i].IsEnabled() || !m_vertex_data[i].addr) continue;
m_vertex_data[i].data.Clear();
glDisableVertexAttribArray(i);
+ checkForGlError("glDisableVertexAttribArray");
}
m_vao.Unbind();
}
@@ -457,13 +455,39 @@ void GLGSRender::InitVertexData()
for(u32 i=0; i<m_transform_constants.GetCount(); ++i)
{
const TransformConstant& c = m_transform_constants[i];
- const wxString& name = wxString::Format("vc%d", c.id);
+ const wxString name = wxString::Format("vc%u", c.id);
+ const int l = m_program.GetLocation(name);
+ checkForGlError("glGetUniformLocation " + name);
+
+ //ConLog.Write(name + " x: %.02f y: %.02f z: %.02f w: %.02f", c.x, c.y, c.z, c.w);
+ glUniform4f(l, c.x, c.y, c.z, c.w);
+ checkForGlError("glUniform4f " + name + wxString::Format(" %d [%f %f %f %f]", l, c.x, c.y, c.z, c.w));
+ }
+}
+
+void GLGSRender::InitFragmentData()
+{
+ if(!m_cur_shader_prog)
+ {
+ ConLog.Error("InitFragmentData: m_cur_shader_prog == NULL");
+ return;
+ }
+
+ for(u32 i=0; i<m_fragment_constants.GetCount(); ++i)
+ {
+ const TransformConstant& c = m_fragment_constants[i];
+
+ u32 id = c.id - m_cur_shader_prog->offset;
+ if(id < 32)
+ id = 32;
+
+ const wxString name = wxString::Format("fc%u", id);
const int l = m_program.GetLocation(name);
checkForGlError("glGetUniformLocation " + name);
//ConLog.Write(name + " x: %.02f y: %.02f z: %.02f w: %.02f", c.x, c.y, c.z, c.w);
glUniform4f(l, c.x, c.y, c.z, c.w);
- checkForGlError("glUniform4f " + name);
+ checkForGlError("glUniform4f " + name + wxString::Format(" %d [%f %f %f %f]", l, c.x, c.y, c.z, c.w));
}
}
@@ -496,14 +520,72 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 c
ConLog.Write(debug);
#endif
- //static int draw_mode = 0;
- static u32 semaphore_offset = 0;
u32 index = 0;
//static u32 draw_array_count = 0;
switch(cmd)
{
+ case 0x3fead:
+ //if(cmd == 0xfeadffff)
+ {
+ //if(p.m_draw)
+ {
+ //p.m_draw = false;
+ /*
+ if(m_skip_frames)
+ {
+ if(!draw)
+ {
+ if(skipped++ >= m_skip_frames)
+ {
+ skipped = 0;
+ draw = true;
+ }
+ }
+ else
+ {
+ if(drawed++ >= m_draw_frames)
+ {
+ drawed = 0;
+ draw = false;
+ }
+ }
+ }*/
+
+ //if(draw)
+ {
+ //if(m_frame->GetClientSize() != wxSize(m_viewport_w, m_viewport_h))
+ // m_frame->SetClientSize(m_viewport_w, m_viewport_h);
+
+ if(m_fbo.IsCreated())
+ {
+ m_fbo.Bind(GL_READ_FRAMEBUFFER);
+ m_fbo.Bind(GL_DRAW_FRAMEBUFFER, 0);
+ m_fbo.Blit(
+ 0, 0, m_width, m_height,
+ 0, 0, m_width, m_height,
+ GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
+ m_fbo.Bind();
+ }
+
+ m_frame->Flip();
+ }
+
+ m_gcm_current_buffer = args[0];
+
+ m_flip_status = 0;
+ if(m_flip_handler)
+ {
+ m_flip_handler.Handle(1, 0, 0);
+ m_flip_handler.Branch(false);
+ }
+
+ SemaphorePostAndWait(m_sem_flip);
+ }
+ }
+ break;
+
case NV4097_NO_OPERATION:
break;
@@ -515,16 +597,22 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 c
{
GLTexture& tex = m_frame->GetTexture(index);
const u32 offset = args[0];
- const u8 location = args[1] & 0x3 - 1;
- const bool cubemap = (args[1] >> 2) & 0x1;
- const u8 dimension = (args[1] >> 4) & 0xf;
- const u8 format = (args[1] >> 8) & 0xff;
- const u16 mipmap = (args[1] >> 16) & 0xffff;
+ u32 a1 = args[1];
+ u8 location = (a1 & 0x3) - 1;
+ const bool cubemap = (a1 >> 2) & 0x1;
+ const u8 dimension = (a1 >> 4) & 0xf;
+ const u8 format = (a1 >> 8) & 0xff;
+ const u16 mipmap = (a1 >> 16) & 0xffff;
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);
+ if(location == 2)
+ {
+ ConLog.Error("Bad texture location.");
+ location = 1;
+ }
u32 tex_addr = GetAddress(offset, location);
- //ConLog.Warning("texture addr = 0x%x", tex_addr);
+ //ConLog.Warning("texture addr = 0x%x #offset = 0x%x, location=%d", tex_addr, offset, location);
tex.SetOffset(tex_addr);
tex.SetFormat(cubemap, dimension, format, mipmap);
}
@@ -533,10 +621,15 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 c
case_16(NV4097_SET_TEXTURE_CONTROL0, 0x20):
{
GLTexture& tex = m_frame->GetTexture(index);
- tex.Enable(args[0] >> 31 ? true : false);
+ u32 a0 = args[0];
+ bool enable = a0 >> 31 ? true : false;
+ u16 minlod = (a0 >> 19) & 0xfff;
+ u16 maxlod = (a0 >> 7) & 0xfff;
+ u8 maxaniso = (a0 >> 2) & 0x7;
+ tex.SetControl0(enable, minlod, maxlod, maxaniso);
}
break;
-
+
case_16(NV4097_SET_VERTEX_DATA4UB_M, 4):
{
u32 v = args[0];
@@ -545,21 +638,73 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 c
u8 v2 = v >> 16;
u8 v3 = v >> 24;
- m_vertex_data[index].type = 7;
+ m_vertex_data[index].size = 4;
+ m_vertex_data[index].type = 4;
m_vertex_data[index].data.AddCpy(v0);
m_vertex_data[index].data.AddCpy(v1);
m_vertex_data[index].data.AddCpy(v2);
m_vertex_data[index].data.AddCpy(v3);
- ConLog.Warning("index = %d, v0 = 0x%x, v1 = 0x%x, v2 = 0x%x, v3 = 0x%x", index, v0, v1, v2, v3);
+ //ConLog.Warning("index = %d, v0 = 0x%x, v1 = 0x%x, v2 = 0x%x, v3 = 0x%x", index, v0, v1, v2, v3);
+ }
+ break;
+
+ case_16(NV4097_SET_VERTEX_DATA2F_M, 8):
+ {
+ u32 a0 = args[0];
+ u32 a1 = args[1];
+
+ float v0 = (float&)a0;
+ float v1 = (float&)a1;
+
+ m_vertex_data[index].type = 2;
+ m_vertex_data[index].size = 2;
+ m_vertex_data[index].data.SetCount(sizeof(float) * 2);
+ (float&)m_vertex_data[index].data[sizeof(float)*0] = v0;
+ (float&)m_vertex_data[index].data[sizeof(float)*1] = v1;
+
+ //ConLog.Warning("index = %d, v0 = %f, v1 = %f", index, v0, v1);
+ }
+ break;
+
+ case_16(NV4097_SET_VERTEX_DATA4F_M, 16):
+ {
+ u32 a0 = args[0];
+ u32 a1 = args[1];
+ u32 a2 = args[2];
+ u32 a3 = args[3];
+
+ float v0 = (float&)a0;
+ float v1 = (float&)a1;
+ float v2 = (float&)a2;
+ float v3 = (float&)a3;
+
+ m_vertex_data[index].type = 2;
+ m_vertex_data[index].size = 4;
+ m_vertex_data[index].data.SetCount(sizeof(float) * 4);
+ (float&)m_vertex_data[index].data[sizeof(float)*0] = v0;
+ (float&)m_vertex_data[index].data[sizeof(float)*1] = v1;
+ (float&)m_vertex_data[index].data[sizeof(float)*2] = v2;
+ (float&)m_vertex_data[index].data[sizeof(float)*3] = v3;
+
+ //ConLog.Warning("index = %d, v0 = %f, v1 = %f, v2 = %f, v3 = %f", index, v0, v1, v2, v3);
}
break;
case_16(NV4097_SET_TEXTURE_CONTROL1, 0x20):
- //TODO
+ {
+ GLTexture& tex = m_frame->GetTexture(index);
+ tex.SetControl1(args[0]);
+ }
break;
case_16(NV4097_SET_TEXTURE_CONTROL3, 4):
- //TODO
+ {
+ GLTexture& tex = m_frame->GetTexture(index);
+ u32 a0 = args[0];
+ u32 pitch = a0 & 0xFFFFF;
+ u16 depth = a0 >> 20;
+ tex.SetControl3(pitch, depth);
+ }
break;
case_16(NV4097_SET_TEXTURE_FILTER, 0x20):
@@ -567,7 +712,21 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 c
break;
case_16(NV4097_SET_TEXTURE_ADDRESS, 0x20):
- //TODO
+ {
+ GLTexture& tex = m_frame->GetTexture(index);
+
+ u32 a0 = args[0];
+ u8 wraps = a0 & 0xf;
+ u8 aniso_bias = (a0 >> 4) & 0xf;
+ u8 wrapt = (a0 >> 8) & 0xf;
+ u8 unsigned_remap = (a0 >> 12) & 0xf;
+ u8 wrapr = (a0 >> 16) & 0xf;
+ u8 gamma = (a0 >> 20) & 0xf;
+ u8 signed_remap = (a0 >> 24) & 0xf;
+ u8 zfunc = a0 >> 28;
+
+ tex.SetAddress(wraps, wrapt, wrapr, unsigned_remap, zfunc, gamma, aniso_bias, signed_remap);
+ }
break;
case_16(NV4097_SET_TEX_COORD_CONTROL, 4):
@@ -587,20 +746,81 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 c
case NV4097_SET_SURFACE_FORMAT:
{
- const u32 color_format = args[0] & 0x1f;
- const u32 depth_format = (args[0] >> 5) & 0x7;
- const u32 type = (args[0] >> 8) & 0xf;
- const u32 antialias = (args[0] >> 12) & 0xf;
- const u32 width = (args[0] >> 16) & 0xff;
- const u32 height = (args[0] >> 24) & 0xff;
- const u32 pitch_a = args[1];
- const u32 offset_a = args[2];
- const u32 offset_z = args[3];
- const u32 offset_b = args[4];
- const u32 pitch_b = args[5];
+ u32 a0 = args[0];
+ m_set_surface_format = true;
+ m_surface_color_format = a0 & 0x1f;
+ m_surface_depth_format = (a0 >> 5) & 0x7;
+ m_surface_type = (a0 >> 8) & 0xf;
+ m_surface_antialias = (a0 >> 12) & 0xf;
+ m_surface_width = (a0 >> 16) & 0xff;
+ m_surface_height = (a0 >> 24) & 0xff;
+ m_surface_pitch_a = args[1];
+ m_surface_offset_a = args[2];
+ m_surface_offset_z = args[3];
+ m_surface_offset_b = args[4];
+ m_surface_pitch_b = args[5];
+
+ /*
+ ConLog.Write("surface color format: 0x%x", m_surface_color_format);
+ ConLog.Write("surface depth format: 0x%x", m_surface_depth_format);
+ ConLog.Write("surface type: 0x%x", m_surface_type);
+ ConLog.Write("surface antialias: 0x%x", m_surface_antialias);
+ ConLog.Write("surface width: 0x%x", m_surface_width);
+ ConLog.Write("surface height: 0x%x", m_surface_height);
+ ConLog.Write("surface pitch a: 0x%x", m_surface_pitch_a);
+ ConLog.Write("surface offset a: 0x%x", m_surface_offset_a);
+ ConLog.Write("surface offset z: 0x%x", m_surface_offset_z);
+ ConLog.Write("surface offset b: 0x%x", m_surface_offset_b);
+ ConLog.Write("surface pitch b: 0x%x", m_surface_pitch_b);
+ if(m_surface_offset_a && m_set_context_dma_color_a)
+ {
+ u32 surface_addr = GetAddress(m_surface_offset_a, (m_context_dma_color_a - 0xfeed0000));
+ auto& surface = (const CellGcmSurface&)Memory[surface_addr];
+ ConLog.Write("context_dma_color_a=0x%x", m_context_dma_color_a);
+ ConLog.Write("context a: color format: 0x%x", surface.color_format);
+ ConLog.Write("context a: depth format: 0x%x", surface.depth_format);
+ ConLog.Write("context a: type: 0x%x", surface.type);
+ ConLog.Write("context a: antialias: 0x%x", surface.antialias);
+ ConLog.Write("context a: width: 0x%x", surface.width);
+ ConLog.Write("context a: height: 0x%x", surface.height);
+ }
+ else if(m_surface_offset_z && m_set_context_dma_z)
+ {
+ u32 surface_addr = GetAddress(m_surface_offset_z, m_context_dma_z);
+ auto& surface = (const CellGcmSurface&)Memory[surface_addr];
+ ConLog.Write("m_surface_offset_z=0x%x", m_surface_offset_z);
+ ConLog.Write("context x: color format: 0x%x", surface.color_format);
+ ConLog.Write("context z: depth format: 0x%x", surface.depth_format);
+ ConLog.Write("context z: type: 0x%x", surface.type);
+ ConLog.Write("context z: antialias: 0x%x", surface.antialias);
+ ConLog.Write("context z: width: 0x%x", surface.width);
+ ConLog.Write("context z: height: 0x%x", surface.height);
+
+ m_width = surface.width;
+ m_height = surface.height;
+ }
+ */
- CMD_LOG("color_format=%d, depth_format=%d, type=%d, antialias=%d, width=%d, height=%d, pitch_a=%d, offset_a=0x%x, offset_z=0x%x, offset_b=0x%x, pitch_b=%d",
- color_format, depth_format, type, antialias, width, height, pitch_a, offset_a, offset_z, offset_b, pitch_b);
+ if(0)
+ {
+ m_rbo.Create(2);
+ checkForGlError("m_rbo.Create");
+ m_rbo.Bind(0);
+ m_rbo.Storage(GL_RGBA, m_width, m_height);
+ checkForGlError("m_rbo.Storage(GL_RGBA)");
+ m_rbo.Bind(1);
+ m_rbo.Storage(GL_DEPTH_STENCIL, m_width, m_height);
+ checkForGlError("m_rbo.Storage(GL_DEPTH24_STENCIL8)");
+ m_fbo.Create();
+ checkForGlError("m_fbo.Create");
+ m_fbo.Bind();
+ m_fbo.Renderbuffer(GL_COLOR_ATTACHMENT0, m_rbo.GetId(0));
+ checkForGlError("m_fbo.Renderbuffer(GL_COLOR_ATTACHMENT0)");
+ m_fbo.Renderbuffer(GL_DEPTH_STENCIL_ATTACHMENT, m_rbo.GetId(1));
+ checkForGlError("m_fbo.Renderbuffer(GL_DEPTH_STENCIL_ATTACHMENT)");
+ }
+ //CMD_LOG("color_format=%d, depth_format=%d, type=%d, antialias=%d, width=%d, height=%d, pitch_a=%d, offset_a=0x%x, offset_z=0x%x, offset_b=0x%x, pitch_b=%d",
+ // color_format, depth_format, type, antialias, width, height, pitch_a, offset_a, offset_z, offset_b, pitch_b);
}
break;
@@ -663,9 +883,6 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 c
}
CMD_LOG("x=%d, y=%d, w=%d, h=%d", m_viewport_x, m_viewport_y, m_viewport_w, m_viewport_h);
-
- //m_frame->SetViewport(m_viewport_x, m_viewport_y, m_viewport_w, m_viewport_h);
- //glViewport(x, y, w, h);
}
break;
@@ -699,8 +916,23 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 c
case NV4097_CLEAR_SURFACE:
{
- m_set_clear_surface = true;
- m_clear_surface_mask = args[0];
+ u32 a0 = args[0];
+ GLbitfield f = 0;
+ if (a0 & 0x1) f |= GL_DEPTH_BUFFER_BIT;
+ if (a0 & 0x2) f |= GL_STENCIL_BUFFER_BIT;
+ if (a0 & 0xF0) f |= GL_COLOR_BUFFER_BIT;
+ glClear(f);
+ /*
+ if(m_set_clear_surface)
+ {
+ m_clear_surface_mask |= args[0];
+ }
+ else
+ {
+ m_clear_surface_mask = args[0];
+ m_set_clear_surface = true;
+ }
+ */
}
break;
@@ -731,23 +963,22 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 c
{
const u32 addr = GetAddress(args[0] & 0x7fffffff, args[0] >> 31);
CMD_LOG("num=%d, addr=0x%x", index, addr);
-
m_vertex_data[index].addr = addr;
}
break;
case_16(NV4097_SET_VERTEX_DATA_ARRAY_FORMAT, 4):
{
- const u16 frequency = args[0] >> 16;
- const u8 stride = (args[0] >> 8) & 0xff;
- const u8 size = (args[0] >> 4) & 0xf;
- const u8 type = args[0] & 0xf;
+ u32 a0 = args[0];
+ const u16 frequency = a0 >> 16;
+ const u8 stride = (a0 >> 8) & 0xff;
+ const u8 size = (a0 >> 4) & 0xf;
+ const u8 type = a0 & 0xf;
CMD_LOG("index=%d, frequency=%d, stride=%d, size=%d, type=%d",
index, frequency, stride, size, type);
VertexData& cv = m_vertex_data[index];
-
cv.frequency = frequency;
cv.stride = stride;
cv.size = size;
@@ -846,16 +1077,17 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 c
case NV4097_SET_COLOR_CLEAR_VALUE:
{
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);
+ //m_set_clear_color = true;
+ m_clear_color_a = (color >> 24) & 0xff;
+ m_clear_color_r = (color >> 16) & 0xff;
+ m_clear_color_g = (color >> 8) & 0xff;
+ m_clear_color_b = color & 0xff;
+
glClearColor(
- (float)r / 255.0f,
- (float)g / 255.0f,
- (float)b / 255.0f,
- (float)a / 255.0f);
+ m_clear_color_r / 255.0f,
+ m_clear_color_g / 255.0f,
+ m_clear_color_b / 255.0f,
+ m_clear_color_a / 255.0f);
}
break;
@@ -863,7 +1095,9 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 c
{
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);
+ u32 a0 = args[0];
+ m_cur_shader_prog->offset = a0 & ~0x3;
+ m_cur_shader_prog->addr = GetAddress(m_cur_shader_prog->offset, (a0 & 0x3) - 1);
}
break;
@@ -1015,7 +1249,54 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 c
break;
case NV4097_SET_TWO_SIDED_STENCIL_TEST_ENABLE:
- if(args[0]) ConLog.Error("NV4097_SET_TWO_SIDED_STENCIL_TEST_ENABLE");
+ m_set_two_sided_stencil_test_enable = args[0] ? true : false;
+ break;
+
+ case NV4097_SET_BACK_STENCIL_MASK:
+ m_set_back_stencil_mask = true;
+ m_back_stencil_mask = args[0];
+ break;
+
+ case NV4097_SET_BACK_STENCIL_FUNC:
+ m_set_back_stencil_func = true;
+ m_back_stencil_func = args[0];
+ if(count >= 2)
+ {
+ m_set_back_stencil_func_ref = true;
+ m_back_stencil_func_ref = args[1];
+
+ if(count >= 3)
+ {
+ m_set_back_stencil_func_mask = true;
+ m_back_stencil_func_mask = args[2];
+ }
+ }
+ break;
+
+ case NV4097_SET_BACK_STENCIL_FUNC_REF:
+ m_set_back_stencil_func_ref = true;
+ m_back_stencil_func_ref = args[0];
+ break;
+
+ case NV4097_SET_BACK_STENCIL_FUNC_MASK:
+ m_set_back_stencil_func_mask = true;
+ m_back_stencil_func_mask = args[0];
+ break;
+
+ case NV4097_SET_BACK_STENCIL_OP_FAIL:
+ m_set_stencil_fail = true;
+ m_stencil_fail = args[0];
+ if(count >= 2)
+ {
+ m_set_back_stencil_zfail = true;
+ m_back_stencil_zfail = args[1];
+
+ if(count >= 3)
+ {
+ m_set_back_stencil_zpass = true;
+ m_back_stencil_zpass = args[2];
+ }
+ }
break;
case NV4097_SET_POLY_OFFSET_FILL_ENABLE:
@@ -1038,7 +1319,7 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 c
break;
case NV4097_SET_POLY_SMOOTH_ENABLE:
- if(args[0]) ConLog.Error("NV4097_SET_POLY_SMOOTH_ENABLE");
+ m_set_poly_smooth = args[0] ? true : false;
break;
case NV4097_SET_BLEND_COLOR:
@@ -1099,19 +1380,36 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 c
}
break;
- case NV4097_BACK_END_WRITE_SEMAPHORE_RELEASE:
+ case NV4097_SET_SEMAPHORE_OFFSET:
+ case NV406E_SEMAPHORE_OFFSET:
{
- //TODO
+ m_set_semaphore_offset = true;
+ m_semaphore_offset = args[0];
}
break;
- case NV4097_SET_SEMAPHORE_OFFSET:
- case NV406E_SEMAPHORE_OFFSET:
+ case NV4097_BACK_END_WRITE_SEMAPHORE_RELEASE:
{
- semaphore_offset = args[0];
+ if(m_set_semaphore_offset)
+ {
+ m_set_semaphore_offset = false;
+ u32 value = args[0];
+ value = (value & 0xff00ff00) | ((value & 0xff) << 16) | ((value >> 16) & 0xff);
+
+ Memory.Write32(Memory.RSXCMDMem.GetStartAddr() + m_semaphore_offset, value);
+ }
}
break;
+ case NV406E_SEMAPHORE_RELEASE:
+ case NV4097_TEXTURE_READ_SEMAPHORE_RELEASE:
+ if(m_set_semaphore_offset)
+ {
+ m_set_semaphore_offset = false;
+ Memory.Write32(Memory.RSXCMDMem.GetStartAddr() + m_semaphore_offset, args[0]);
+ }
+ break;
+
case NV406E_SEMAPHORE_ACQUIRE:
{
//TODO
@@ -1129,27 +1427,32 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 c
//TODO
}
break;
+
case NV4097_SET_CONTEXT_DMA_COLOR_A:
{
- //TODO
+ m_set_context_dma_color_a = true;
+ m_context_dma_color_a = args[0];
}
break;
case NV4097_SET_CONTEXT_DMA_COLOR_B:
{
- //TODO
+ m_set_context_dma_color_b = true;
+ m_context_dma_color_b = args[0];
}
break;
case NV4097_SET_CONTEXT_DMA_COLOR_C:
{
- //TODO
+ m_set_context_dma_color_c = true;
+ m_context_dma_color_c = args[0];
}
break;
case NV4097_SET_CONTEXT_DMA_ZETA:
{
- //TODO
+ m_set_context_dma_z = true;
+ m_context_dma_z = args[0];
}
break;
@@ -1183,9 +1486,30 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 c
}
break;
+ case NV4097_SET_SURFACE_CLIP_VERTICAL:
+ {
+ u32 a0 = args[0];
+ m_set_surface_clip_vertical = true;
+ m_surface_clip_y = a0;
+ m_surface_clip_h = a0 >> 16;
+ }
+ break;
+
case NV4097_SET_SURFACE_CLIP_HORIZONTAL:
{
- //TODO
+ u32 a0 = args[0];
+
+ m_set_surface_clip_horizontal = true;
+ m_surface_clip_x = a0;
+ m_surface_clip_w = a0 >> 16;
+
+ if(count >= 2)
+ {
+ u32 a1 = args[1];
+ m_set_surface_clip_vertical = true;
+ m_surface_clip_y = a1;
+ m_surface_clip_h = a1 >> 16;
+ }
}
break;
@@ -1242,11 +1566,159 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 c
break;
default:
+ data = 0;
ConLog.Error("NV4097_GET_REPORT: bad type %d", type);
break;
}
- Memory.Write64(m_localAddress + offset, data);
+ Memory.Write64(m_local_mem_addr + offset, data);
+ }
+ break;
+
+ case NV3062_SET_OFFSET_DESTIN:
+ m_dst_offset = args[0];
+ break;
+
+ case NV308A_COLOR:
+ {
+ TransformConstant c;
+ c.id = m_dst_offset;
+
+ if(count >= 1)
+ {
+ u32 a = args[0];
+ a = a << 16 | a >> 16;
+ c.x = (float&)a;
+ }
+
+ if(count >= 2)
+ {
+ u32 a = args[1];
+ a = a << 16 | a >> 16;
+ c.y = (float&)a;
+ }
+
+ if(count >= 3)
+ {
+ u32 a = args[2];
+ a = a << 16 | a >> 16;
+ c.z = (float&)a;
+ }
+
+ if(count >= 4)
+ {
+ u32 a = args[3];
+ a = a << 16 | a >> 16;
+ c.w = (float&)a;
+ }
+
+ if(count >= 5)
+ {
+ ConLog.Warning("NV308A_COLOR: count = %d", count);
+ }
+
+ //ConLog.Warning("NV308A_COLOR: [%d]: %f, %f, %f, %f", c.id, c.x, c.y, c.z, c.w);
+ m_fragment_constants.AddCpy(c);
+ }
+ break;
+
+ case NV308A_POINT:
+ //TODO
+ break;
+
+ case NV3062_SET_COLOR_FORMAT:
+ {
+ m_color_format = args[0];
+ m_color_format_src_pitch = args[1];
+ m_color_format_dst_pitch = args[1] >> 16;
+ }
+ break;
+
+ case NV3089_SET_COLOR_CONVERSION:
+ {
+ m_color_conv = args[0];
+ m_color_conv_fmt = args[1];
+ m_color_conv_op = args[2];
+ m_color_conv_in_x = args[3];
+ m_color_conv_in_y = args[3] >> 16;
+ m_color_conv_in_w = args[4];
+ m_color_conv_in_h = args[4] >> 16;
+ m_color_conv_out_x = args[5];
+ m_color_conv_out_y = args[5] >> 16;
+ m_color_conv_out_w = args[6];
+ m_color_conv_out_h = args[6] >> 16;
+ m_color_conv_dsdx = args[7];
+ m_color_conv_dtdy = args[8];
+ }
+ break;
+
+ case NV3089_IMAGE_IN_SIZE:
+ {
+ u16 w = args[0];
+ u16 h = args[0] >> 16;
+ u16 pitch = args[1];
+ u8 origin = args[1] >> 16;
+ u8 inter = args[1] >> 24;
+ u32 offset = args[2];
+ u16 u = args[3];
+ u16 v = args[3] >> 16;
+
+ u8* pixels_src = &Memory[GetAddress(offset, m_context_dma_img_src - 0xfeed0000)];
+ u8* pixels_dst = &Memory[GetAddress(m_dst_offset, m_context_dma_img_dst - 0xfeed0000)];
+
+ for(u16 y=0; y<m_color_conv_in_h; ++y)
+ {
+ for(u16 x=0; x<m_color_format_src_pitch/4/*m_color_conv_in_w*/; ++x)
+ {
+ const u32 src_offset = (m_color_conv_in_y + y) * m_color_format_src_pitch + (m_color_conv_in_x + x) * 4;
+ const u32 dst_offset = (m_color_conv_out_y + y) * m_color_format_dst_pitch + (m_color_conv_out_x + x) * 4;
+ (u32&)pixels_dst[dst_offset] = (u32&)pixels_src[src_offset];
+ }
+ }
+ }
+ break;
+
+ case NV3089_SET_CONTEXT_DMA_IMAGE:
+ m_context_dma_img_src = args[0];
+ break;
+
+ case NV3062_SET_CONTEXT_DMA_IMAGE_DESTIN:
+ m_context_dma_img_dst = args[0];
+ break;
+
+
+ case NV3089_SET_CONTEXT_SURFACE:
+ if(args[0] != 0x313371C3)
+ {
+ ConLog.Warning("NV3089_SET_CONTEXT_SURFACE: Unsupported surface (0x%x)", args[0]);
+ }
+ break;
+
+ case NV4097_SET_FOG_MODE:
+ m_set_fog_mode = true;
+ m_fog_mode = args[0];
+ break;
+
+ case NV4097_SET_USER_CLIP_PLANE_CONTROL:
+ {
+ u32 a0 = args[0];
+ m_set_clip_plane = true;
+ m_clip_plane_0 = a0 & 0xf;
+ m_clip_plane_1 = (a0 >> 4) & 0xf;
+ m_clip_plane_2 = (a0 >> 8) & 0xf;
+ m_clip_plane_3 = (a0 >> 12) & 0xf;
+ m_clip_plane_4 = (a0 >> 16) & 0xf;
+ m_clip_plane_5 = a0 >> 20;
+ }
+ break;
+
+ case NV4097_SET_FOG_PARAMS:
+ {
+ m_set_fog_params = true;
+ u32 a0 = args[0];
+ u32 a1 = args[1];
+ m_fog_param0 = (float&)a0;
+ m_fog_param1 = (float&)a1;
}
break;
@@ -1359,36 +1831,53 @@ void GLGSRender::ExecCMD()
{
if(LoadProgram())
{
- if(m_set_clear_surface)
+ if(m_set_surface_clip_horizontal && m_set_surface_clip_vertical)
{
- GLbitfield f = 0;
- if (m_clear_surface_mask & 0x1) f |= GL_DEPTH_BUFFER_BIT;
- if (m_clear_surface_mask & 0x2) f |= GL_STENCIL_BUFFER_BIT;
- if (m_clear_surface_mask & 0x10) f |= GL_COLOR_BUFFER_BIT;
- glClear(f);
+ m_width = m_surface_clip_w;
+ m_height = m_surface_clip_h;
+ //ConLog.Write("width: %d, height: %d, x: %d, y: %d", m_width, m_height, m_surface_clip_x, m_surface_clip_y);
}
if(m_set_color_mask)
{
glColorMask(m_color_mask_r, m_color_mask_g, m_color_mask_b, m_color_mask_a);
+ checkForGlError("glColorMask");
}
if(m_set_viewport_horizontal && m_set_viewport_vertical)
{
- glViewport(m_viewport_x, m_viewport_y, m_viewport_w, m_viewport_h);
- if(m_frame->GetClientSize() != wxSize(m_viewport_w, m_viewport_h))
- m_frame->SetClientSize(m_viewport_w, m_viewport_h);
- //m_frame->SetViewport(m_viewport_x, m_viewport_y, m_viewport_w, m_viewport_h);
+ glViewport(m_scissor_x, m_height-m_viewport_y-m_viewport_h, m_viewport_w, m_viewport_h);
+ checkForGlError("glViewport");
}
if(m_set_scissor_horizontal && m_set_scissor_vertical)
{
- glScissor(m_scissor_x, m_scissor_y, m_scissor_w, m_scissor_h);
+ glScissor(m_scissor_x, m_height-m_scissor_y-m_scissor_h, m_scissor_w, m_scissor_h);
+ checkForGlError("glScissor");
+ }
+
+ if(m_set_clear_color)
+ {
+ glClearColor(
+ m_clear_color_r / 255.0f,
+ m_clear_color_g / 255.0f,
+ m_clear_color_b / 255.0f,
+ m_clear_color_a / 255.0f);
+ }
+
+ if(m_set_clear_surface)
+ {
+ GLbitfield f = 0;
+ if (m_clear_surface_mask & 0x1) f |= GL_DEPTH_BUFFER_BIT;
+ if (m_clear_surface_mask & 0x2) f |= GL_STENCIL_BUFFER_BIT;
+ if (m_clear_surface_mask & 0xF0) f |= GL_COLOR_BUFFER_BIT;
+ glClear(f);
}
if(m_set_front_polygon_mode)
{
glPolygonMode(GL_FRONT, m_front_polygon_mode);
+ checkForGlError("glPolygonMode");
}
Enable(m_depth_test_enable, GL_DEPTH_TEST);
@@ -1400,60 +1889,117 @@ void GLGSRender::ExecCMD()
Enable(m_set_dither, GL_DITHER);
Enable(m_set_stencil_test, GL_STENCIL_TEST);
Enable(m_set_line_smooth, GL_LINE_SMOOTH);
+ Enable(m_set_poly_smooth, GL_POLYGON_SMOOTH);
+ checkForGlError("glEnable");
- if(m_set_stencil_mask)
+ if(m_set_clip_plane)
{
- glStencilMask(m_stencil_mask);
+ Enable(m_clip_plane_0, GL_CLIP_PLANE0);
+ Enable(m_clip_plane_1, GL_CLIP_PLANE1);
+ Enable(m_clip_plane_2, GL_CLIP_PLANE2);
+ Enable(m_clip_plane_3, GL_CLIP_PLANE3);
+ Enable(m_clip_plane_4, GL_CLIP_PLANE4);
+ Enable(m_clip_plane_5, GL_CLIP_PLANE5);
+
+ checkForGlError("m_set_clip_plane");
}
- if(m_set_stencil_func && m_set_stencil_func_ref && m_set_stencil_func_mask)
+ if(m_set_two_sided_stencil_test_enable)
{
- glStencilFunc(m_stencil_func, m_stencil_func_ref, m_stencil_func_mask);
+ if(m_set_back_stencil_fail && m_set_back_stencil_zfail && m_set_back_stencil_zpass)
+ {
+ glStencilOpSeparate(GL_BACK, m_back_stencil_fail, m_back_stencil_zfail, m_back_stencil_zpass);
+ checkForGlError("glStencilOpSeparate(GL_BACK)");
+ }
+
+ if(m_set_back_stencil_mask)
+ {
+ glStencilMaskSeparate(GL_BACK, m_back_stencil_mask);
+ checkForGlError("glStencilMaskSeparate(GL_BACK)");
+ }
+
+ if(m_set_back_stencil_func && m_set_back_stencil_func_ref && m_set_back_stencil_func_mask)
+ {
+ glStencilFuncSeparate(GL_BACK, m_back_stencil_func, m_back_stencil_func_ref, m_back_stencil_func_mask);
+ checkForGlError("glStencilFuncSeparate(GL_BACK)");
+ }
}
if(m_set_stencil_fail && m_set_stencil_zfail && m_set_stencil_zpass)
{
- glStencilOp(m_stencil_fail, m_stencil_zfail, m_stencil_zpass);
+ glStencilOpSeparate(GL_FRONT, m_stencil_fail, m_stencil_zfail, m_stencil_zpass);
+ checkForGlError("glStencilOpSeparate(GL_FRONT)");
+ }
+
+ if(m_set_stencil_mask)
+ {
+ glStencilMaskSeparate(GL_FRONT, m_stencil_mask);
+ checkForGlError("glStencilMaskSeparate(GL_FRONT)");
+ }
+
+ if(m_set_stencil_func && m_set_stencil_func_ref && m_set_stencil_func_mask)
+ {
+ glStencilFuncSeparate(GL_FRONT, m_stencil_func, m_stencil_func_ref, m_stencil_func_mask);
+ checkForGlError("glStencilFuncSeparate(GL_FRONT)");
}
if(m_set_shade_mode)
{
glShadeModel(m_shade_mode);
+ checkForGlError("glShadeModel");
}
if(m_set_depth_mask)
{
glDepthMask(m_depth_mask);
+ checkForGlError("glDepthMask");
}
if(m_set_depth_func)
{
glDepthFunc(m_depth_func);
+ checkForGlError("glDepthFunc");
}
if(m_set_clip)
{
glDepthRangef(m_clip_min, m_clip_max);
+ checkForGlError("glDepthRangef");
}
if(m_set_line_width)
{
glLineWidth(m_line_width / 255.f);
+ checkForGlError("glLineWidth");
}
if(m_set_blend_equation)
{
glBlendEquationSeparate(m_blend_equation_rgb, m_blend_equation_alpha);
+ checkForGlError("glBlendEquationSeparate");
}
if(m_set_blend_sfactor && m_set_blend_dfactor)
{
glBlendFuncSeparate(m_blend_sfactor_rgb, m_blend_dfactor_rgb, m_blend_sfactor_alpha, m_blend_dfactor_alpha);
+ checkForGlError("glBlendFuncSeparate");
}
if(m_set_blend_color)
{
glBlendColor(m_blend_color_r, m_blend_color_g, m_blend_color_b, m_blend_color_a);
+ checkForGlError("glBlendColor");
+ }
+
+ if(m_set_fog_mode)
+ {
+ glFogi(GL_FOG_MODE, m_fog_mode);
+ }
+
+ if(m_set_fog_params)
+ {
+ glFogf(GL_FOG_START, m_fog_param0);
+ glFogf(GL_FOG_END, m_fog_param1);
}
if(m_indexed_array.m_count && m_draw_array_count)
@@ -1477,28 +2023,29 @@ void GLGSRender::ExecCMD()
//tex.Save();
}
+ m_vao.Bind();
if(m_indexed_array.m_count)
{
LoadVertexData(m_indexed_array.index_min, m_indexed_array.index_max - m_indexed_array.index_min + 1);
- EnableVertexData(true);
- InitVertexData();
+ }
- wxFile log("IndexedDrawLog.txt", wxFile::write);
- log.Write(wxString::Format("Draw mode: %d\n", m_draw_mode));
+ EnableVertexData(m_indexed_array.m_count ? true : false);
- m_vao.Bind();
+ InitVertexData();
+ InitFragmentData();
+
+ if(m_indexed_array.m_count)
+ {
switch(m_indexed_array.m_type)
{
case 0:
glDrawElements(m_draw_mode, m_indexed_array.m_count, GL_UNSIGNED_INT, nullptr);
checkForGlError("glDrawElements #4");
- //for(uint i=0; i<m_indexed_array.m_count; i+=4) log.Write(wxString::Format("index 4: %d\n", (u32&)m_indexed_array.m_data[i]));
break;
case 1:
glDrawElements(m_draw_mode, m_indexed_array.m_count, GL_UNSIGNED_SHORT, nullptr);
checkForGlError("glDrawElements #2");
- //for(uint i=0; i<m_indexed_array.m_count; i+=2) log.Write(wxString::Format("index 2: %d\n", (u16&)m_indexed_array.m_data[i]));
break;
default:
@@ -1508,20 +2055,17 @@ void GLGSRender::ExecCMD()
DisableVertexData();
m_indexed_array.Reset();
- //Emu.Pause();
}
if(m_draw_array_count)
{
- EnableVertexData();
- InitVertexData();
- m_vao.Bind();
-
glDrawArrays(m_draw_mode, 0, m_draw_array_count);
checkForGlError("glDrawArrays");
DisableVertexData();
m_draw_array_count = 0;
}
+
+ m_fragment_constants.Clear();
}
else
{
@@ -1535,7 +2079,7 @@ void GLGSRender::ExecCMD()
void GLGSRender::Reset()
{
m_program.UnUse();
-
+ //m_prog_buffer.Clear();
if(m_cur_shader_prog)
m_cur_shader_prog->id = 0;
View
233 rpcs3/Emu/GS/GL/GLGSRender.h
@@ -24,18 +24,39 @@ class GLTexture
u8 m_dimension;
u32 m_format;
u16 m_mipmap;
+
+ u32 m_pitch;
+ u16 m_depth;
+
+ u16 m_minlod;
+ u16 m_maxlod;
+ u8 m_maxaniso;
+
+ u8 m_wraps;
+ u8 m_wrapt;
+ u8 m_wrapr;
+ u8 m_unsigned_remap;
+ u8 m_zfunc;
+ u8 m_gamma;
+ u8 m_aniso_bias;
+ u8 m_signed_remap;
+
+ u32 m_remap;
public:
GLTexture()
- : m_width(0), m_height(0),
- m_id(0),
- m_offset(0),
- m_enabled(false),
-
- m_cubemap(false),
- m_dimension(0),
- m_format(0),
- m_mipmap(0)
+ : m_width(0), m_height(0)
+ , m_id(0)
+ , m_offset(0)
+ , m_enabled(false)
+
+ , m_cubemap(false)
+ , m_dimension(0)
+ , m_format(0)
+ , m_mipmap(0)
+ , m_minlod(0)
+ , m_maxlod(1000)
+ , m_maxaniso(0)
{
}
@@ -51,10 +72,11 @@ class GLTexture
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);
+
+ //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);
}
}
@@ -74,6 +96,37 @@ class GLTexture
m_mipmap = mipmap;
}
+ void SetAddress(u8 wraps, u8 wrapt, u8 wrapr, u8 unsigned_remap, u8 zfunc, u8 gamma, u8 aniso_bias, u8 signed_remap)
+ {
+ m_wraps = wraps;
+ m_wrapt = wrapt;
+ m_wrapr = wrapr;
+ m_unsigned_remap = unsigned_remap;
+ m_zfunc = zfunc;
+ m_gamma = gamma;
+ m_aniso_bias = aniso_bias;
+ m_signed_remap = signed_remap;
+ }
+
+ void SetControl0(const bool enable, const u16 minlod, const u16 maxlod, const u8 maxaniso)
+ {
+ m_enabled = enable;
+ m_minlod = minlod;
+ m_maxlod = maxlod;
+ m_maxaniso = maxaniso;
+ }
+
+ void SetControl1(u32 remap)
+ {
+ m_remap = remap;
+ }
+
+ void SetControl3(u16 depth, u32 pitch)
+ {
+ m_depth = depth;
+ m_pitch = pitch;
+ }
+
u32 GetFormat() const { return m_format; }
void SetOffset(const u32 offset)
@@ -86,44 +139,163 @@ class GLTexture
return wxSize(m_width, m_height);
}
+ int GetGlWrap(int wrap)
+ {
+ switch(wrap)
+ {
+ case 1: return GL_REPEAT;
+ case 2: return GL_MIRRORED_REPEAT;
+ case 3: return GL_CLAMP_TO_EDGE;
+ case 4: return GL_TEXTURE_BORDER;
+ case 5: return GL_CLAMP_TO_EDGE;//GL_CLAMP;
+ //case 6: return GL_MIRROR_CLAMP_TO_EDGE_EXT;
+ }
+
+ ConLog.Error("Texture wrap error: bad wrap (%d).", wrap);
+ return GL_REPEAT;
+ }
+
void Init()
{
Bind();
- //ConLog.Warning("texture addr = 0x%x, width = %d, height = %d", m_offset, m_width, m_height);
+ if(!Memory.IsGoodAddr(m_offset))
+ {
+ ConLog.Error("Bad texture address=0x%x", m_offset);
+ return;
+ }
+ //ConLog.Warning("texture addr = 0x%x, width = %d, height = %d, max_aniso=%d, mipmap=%d, remap=0x%x, zfunc=0x%x, wraps=0x%x, wrapt=0x%x, wrapr=0x%x, minlod=0x%x, maxlod=0x%x",
+ // m_offset, m_width, m_height, m_maxaniso, m_mipmap, m_remap, m_zfunc, m_wraps, m_wrapt, m_wrapr, m_minlod, m_maxlod);
//TODO: safe init
checkForGlError("GLTexture::Init() -> glBindTexture");
- switch(m_format & ~(0x20 | 0x40))
+ glPixelStorei(GL_PACK_ROW_LENGTH, m_pitch);
+
+ int format = m_format & ~(0x20 | 0x40);
+ bool is_swizzled = (m_format & 0x20) == 0;
+
+ char* pixels = (char*)Memory.GetMemFromAddr(m_offset);
+
+ switch(format)
{
case 0x81:
-
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_BLUE, GL_UNSIGNED_BYTE, Memory.GetMemFromAddr(m_offset));
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_BLUE, GL_UNSIGNED_BYTE, pixels);
checkForGlError("GLTexture::Init() -> glTexImage2D");
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_BLUE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_BLUE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_BLUE);
-
+
checkForGlError("GLTexture::Init() -> glTexParameteri");
break;
case 0x85:
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, Memory.GetMemFromAddr(m_offset));
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, pixels);
checkForGlError("GLTexture::Init() -> glTexImage2D");
break;
- case 0x94://FIXME
- glTexImage2D(GL_TEXTURE_2D, 0, GL_R16, m_width, m_height, 0, GL_RED, GL_SHORT, Memory.GetMemFromAddr(m_offset));
+ case 0x86:
+ {
+ u32 size = ((m_width + 3) / 4) * ((m_height + 3) / 4) * 8;
+
+ glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, m_width, m_height, 0, size, pixels);
+ checkForGlError("GLTexture::Init() -> glCompressedTexImage2D");
+ }
+ break;
+
+ case 0x87:
+ {
+ u32 size = ((m_width + 3) / 4) * ((m_height + 3) / 4) * 16;
+
+ glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, m_width, m_height, 0, size, pixels);
+ checkForGlError("GLTexture::Init() -> glCompressedTexImage2D");
+ }
+ break;
+
+ case 0x88:
+ {
+ u32 size = ((m_width + 3) / 4) * ((m_height + 3) / 4) * 16;
+
+ glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, m_width, m_height, 0, size, pixels);
+ checkForGlError("GLTexture::Init() -> glCompressedTexImage2D");
+ }
+ break;
+
+ case 0x94:
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RED, GL_SHORT, pixels);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_ONE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_ONE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_ONE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_RED);
checkForGlError("GLTexture::Init() -> glTexImage2D");
break;
- default: ConLog.Error("Init tex error: Bad tex format (0x%x)", m_format); break;
+ case 0x9a:
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_BGRA, GL_HALF_FLOAT, pixels);
+ checkForGlError("GLTexture::Init() -> glTexImage2D");
+ break;
+
+ case 0x9e:
+ {
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, pixels);
+ checkForGlError("GLTexture::Init() -> glTexImage2D");
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ONE);
}
+ break;
+ default: ConLog.Error("Init tex error: Bad tex format (0x%x | 0x%x | 0x%x)", format, m_format & 0x20, m_format & 0x40); break;
+ }
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ if(m_mipmap > 1)
+ {
+ glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
+ }
+
+ if(format != 0x81 && format != 0x94)
+ {
+ u8 remap_a = m_remap & 0x3;
+ u8 remap_r = (m_remap >> 2) & 0x3;
+ u8 remap_g = (m_remap >> 4) & 0x3;
+ u8 remap_b = (m_remap >> 6) & 0x3;
+
+ static const int gl_remap[] =
+ {
+ GL_ALPHA,
+ GL_RED,
+ GL_GREEN,
+ GL_BLUE,
+ };
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, gl_remap[remap_a]);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, gl_remap[remap_r]);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, gl_remap[remap_g]);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, gl_remap[remap_b]);
+ }
+
+ static const int gl_tex_zfunc[] =
+ {
+ GL_NEVER,
+ GL_LESS,
+ GL_EQUAL,
+ GL_LEQUAL,
+ GL_GREATER,
+ GL_NOTEQUAL,
+ GL_GEQUAL,
+ GL_ALWAYS,
+ };
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GetGlWrap(m_wraps));
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GetGlWrap(m_wrapt));
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GetGlWrap(m_wrapr));
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, gl_tex_zfunc[m_zfunc]);
+
+ glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, m_aniso_bias);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, m_minlod);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, m_maxlod);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, m_maxaniso);
+
+ //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);