mirror of
https://github.com/PCSX2/gsdx-sourceforge.git
synced 2026-02-04 03:11:19 +01:00
This commit is contained in:
@@ -24,8 +24,6 @@
|
||||
|
||||
GPUDrawScanline::GPUDrawScanline(GPUState* state)
|
||||
: m_state(state)
|
||||
, m_filter(0)
|
||||
, m_dither(1)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
@@ -34,83 +32,67 @@ GPUDrawScanline::~GPUDrawScanline()
|
||||
{
|
||||
}
|
||||
|
||||
void GPUDrawScanline::SetOptions(int filter, int dither)
|
||||
{
|
||||
m_filter = filter;
|
||||
m_dither = dither;
|
||||
}
|
||||
|
||||
// IDrawScanline
|
||||
|
||||
void GPUDrawScanline::SetupDraw(Vertex* vertices, int count, const void* texture)
|
||||
bool GPUDrawScanline::SetupDraw(const GSRasterizerData* data)
|
||||
{
|
||||
GPUDrawingEnvironment& env = m_state->m_env;
|
||||
|
||||
// m_sel
|
||||
const GPUScanlineParam* p = (const GPUScanlineParam*)data->param;
|
||||
|
||||
m_sel.dw = 0;
|
||||
m_sel.iip = env.PRIM.IIP;
|
||||
m_sel.me = env.STATUS.ME;
|
||||
m_sel.abe = env.PRIM.ABE;
|
||||
m_sel.abr = env.STATUS.ABR;
|
||||
m_sel.tge = env.PRIM.TGE;
|
||||
m_sel.tme = env.PRIM.TME;
|
||||
m_sel.tlu = env.STATUS.TP < 2;
|
||||
m_sel.twin = (env.TWIN.ai32 & 0xfffff) != 0;
|
||||
m_sel.dtd = m_dither ? env.STATUS.DTD : 0;
|
||||
m_sel.ltf = m_filter == 1 && env.PRIM.TYPE == GPU_POLYGON || m_filter == 2 ? 1 : 0;
|
||||
m_env.sel = p->sel;
|
||||
|
||||
m_dsf = m_ds[m_sel];
|
||||
m_env.mem = &m_state->m_mem;
|
||||
|
||||
// m_slenv
|
||||
|
||||
m_slenv.mem = &m_state->m_mem;
|
||||
|
||||
if(m_sel.tme)
|
||||
if(m_env.sel.tme)
|
||||
{
|
||||
m_slenv.tex = texture;
|
||||
m_slenv.clut = m_state->m_mem.GetCLUT(env.STATUS.TP, env.CLUT.X, env.CLUT.Y);
|
||||
m_env.tex = p->tex;
|
||||
m_env.clut = p->clut;
|
||||
|
||||
if(m_sel.twin)
|
||||
if(m_env.sel.twin)
|
||||
{
|
||||
DWORD u, v;
|
||||
|
||||
u = ~(env.TWIN.TWW << 3) & 0xff;
|
||||
v = ~(env.TWIN.TWH << 3) & 0xff;
|
||||
|
||||
m_slenv.u[0] = GSVector4i((u << 16) | u);
|
||||
m_slenv.v[0] = GSVector4i((v << 16) | v);
|
||||
m_env.u[0] = GSVector4i((u << 16) | u);
|
||||
m_env.v[0] = GSVector4i((v << 16) | v);
|
||||
|
||||
u = env.TWIN.TWX << 3;
|
||||
v = env.TWIN.TWY << 3;
|
||||
|
||||
m_slenv.u[1] = GSVector4i((u << 16) | u) & ~m_slenv.u[0];
|
||||
m_slenv.v[1] = GSVector4i((v << 16) | v) & ~m_slenv.v[0];
|
||||
m_env.u[1] = GSVector4i((u << 16) | u) & ~m_env.u[0];
|
||||
m_env.v[1] = GSVector4i((v << 16) | v) & ~m_env.v[0];
|
||||
}
|
||||
}
|
||||
|
||||
m_slenv.a = GSVector4i(env.PRIM.ABE ? 0xffffffff : 0);
|
||||
m_slenv.md = GSVector4i(env.STATUS.MD ? 0x80008000 : 0);
|
||||
m_env.a = GSVector4i(env.PRIM.ABE ? 0xffffffff : 0);
|
||||
m_env.md = GSVector4i(env.STATUS.MD ? 0x80008000 : 0);
|
||||
|
||||
m_dsf = m_ds[m_env.sel];
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void GPUDrawScanline::SetupPrim(PrimitiveType type, const Vertex* vertices, const Vertex& dscan)
|
||||
void GPUDrawScanline::SetupPrim(GS_PRIM_CLASS primclass, const GSVertexSW* vertices, const GSVertexSW& dscan)
|
||||
{
|
||||
if(m_sel.tme && !m_sel.twin)
|
||||
if(m_env.sel.tme && !m_env.sel.twin)
|
||||
{
|
||||
GSVector4i t;
|
||||
|
||||
switch(type)
|
||||
switch(primclass)
|
||||
{
|
||||
case Sprite:
|
||||
case GS_SPRITE_CLASS:
|
||||
t = (GSVector4i(vertices[1].t) >> 8) - GSVector4i::x00000001();
|
||||
t = t.ps32(t);
|
||||
t = t.upl16(t);
|
||||
m_slenv.u[2] = t.xxxx();
|
||||
m_slenv.v[2] = t.yyyy();
|
||||
m_env.u[2] = t.xxxx();
|
||||
m_env.v[2] = t.yyyy();
|
||||
break;
|
||||
default:
|
||||
m_slenv.u[2] = GSVector4i::x00ff();
|
||||
m_slenv.v[2] = GSVector4i::x00ff();
|
||||
m_env.u[2] = GSVector4i::x00ff();
|
||||
m_env.v[2] = GSVector4i::x00ff();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -125,22 +107,22 @@ void GPUDrawScanline::SetupPrim(PrimitiveType type, const Vertex* vertices, cons
|
||||
|
||||
GSVector4i dtc8 = GSVector4i(dt * 8.0f).ps32(GSVector4i(dc * 8.0f));
|
||||
|
||||
m_slenv.ds = GSVector4i(dt.xxxx() * ps0123).ps32(GSVector4i(dt.xxxx() * ps4567));
|
||||
m_slenv.dt = GSVector4i(dt.yyyy() * ps0123).ps32(GSVector4i(dt.yyyy() * ps4567));
|
||||
m_slenv.dst8 = dtc8.upl16(dtc8);
|
||||
m_env.ds = GSVector4i(dt.xxxx() * ps0123).ps32(GSVector4i(dt.xxxx() * ps4567));
|
||||
m_env.dt = GSVector4i(dt.yyyy() * ps0123).ps32(GSVector4i(dt.yyyy() * ps4567));
|
||||
m_env.dst8 = dtc8.upl16(dtc8);
|
||||
|
||||
m_slenv.dr = GSVector4i(dc.xxxx() * ps0123).ps32(GSVector4i(dc.xxxx() * ps4567));
|
||||
m_slenv.dg = GSVector4i(dc.yyyy() * ps0123).ps32(GSVector4i(dc.yyyy() * ps4567));
|
||||
m_slenv.db = GSVector4i(dc.zzzz() * ps0123).ps32(GSVector4i(dc.zzzz() * ps4567));
|
||||
m_slenv.dc8 = dtc8.uph16(dtc8);
|
||||
m_env.dr = GSVector4i(dc.xxxx() * ps0123).ps32(GSVector4i(dc.xxxx() * ps4567));
|
||||
m_env.dg = GSVector4i(dc.yyyy() * ps0123).ps32(GSVector4i(dc.yyyy() * ps4567));
|
||||
m_env.db = GSVector4i(dc.zzzz() * ps0123).ps32(GSVector4i(dc.zzzz() * ps4567));
|
||||
m_env.dc8 = dtc8.uph16(dtc8);
|
||||
}
|
||||
|
||||
void GPUDrawScanline::DrawScanline(int top, int left, int right, const Vertex& v)
|
||||
void GPUDrawScanline::DrawScanline(int top, int left, int right, const GSVertexSW& v)
|
||||
{
|
||||
(this->*m_dsf)(top, left, right, v);
|
||||
}
|
||||
|
||||
void GPUDrawScanline::FillRect(const GSVector4i& r, const Vertex& v)
|
||||
void GPUDrawScanline::DrawSolidRect(const GSVector4i& r, const GSVertexSW& v)
|
||||
{
|
||||
ASSERT(0);
|
||||
}
|
||||
@@ -152,8 +134,8 @@ IDrawScanline::DrawScanlinePtr GPUDrawScanline::GetDrawScanlinePtr()
|
||||
|
||||
void GPUDrawScanline::SampleTexture(int pixels, DWORD ltf, DWORD tlu, DWORD twin, GSVector4i& test, const GSVector4i& s, const GSVector4i& t, GSVector4i* c)
|
||||
{
|
||||
const void* RESTRICT tex = m_slenv.tex;
|
||||
const WORD* RESTRICT clut = m_slenv.clut;
|
||||
const void* RESTRICT tex = m_env.tex;
|
||||
const WORD* RESTRICT clut = m_env.clut;
|
||||
|
||||
if(ltf)
|
||||
{
|
||||
@@ -171,17 +153,17 @@ void GPUDrawScanline::SampleTexture(int pixels, DWORD ltf, DWORD tlu, DWORD twin
|
||||
|
||||
if(twin)
|
||||
{
|
||||
u0 = (u0 & m_slenv.u[0]).add16(m_slenv.u[1]);
|
||||
v0 = (v0 & m_slenv.v[0]).add16(m_slenv.v[1]);
|
||||
u1 = (u1 & m_slenv.u[0]).add16(m_slenv.u[1]);
|
||||
v1 = (v1 & m_slenv.v[0]).add16(m_slenv.v[1]);
|
||||
u0 = (u0 & m_env.u[0]).add16(m_env.u[1]);
|
||||
v0 = (v0 & m_env.v[0]).add16(m_env.v[1]);
|
||||
u1 = (u1 & m_env.u[0]).add16(m_env.u[1]);
|
||||
v1 = (v1 & m_env.v[0]).add16(m_env.v[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
u0 = u0.min_i16(m_slenv.u[2]);
|
||||
v0 = v0.min_i16(m_slenv.v[2]);
|
||||
u1 = u1.min_i16(m_slenv.u[2]);
|
||||
v1 = v1.min_i16(m_slenv.v[2]);
|
||||
u0 = u0.min_i16(m_env.u[2]);
|
||||
v0 = v0.min_i16(m_env.v[2]);
|
||||
u1 = u1.min_i16(m_env.u[2]);
|
||||
v1 = v1.min_i16(m_env.v[2]);
|
||||
}
|
||||
|
||||
GSVector4i addr00 = v0.sll16(8) | u0;
|
||||
@@ -298,13 +280,13 @@ void GPUDrawScanline::SampleTexture(int pixels, DWORD ltf, DWORD tlu, DWORD twin
|
||||
|
||||
if(twin)
|
||||
{
|
||||
u = (u & m_slenv.u[0]).add16(m_slenv.u[1]);
|
||||
v = (v & m_slenv.v[0]).add16(m_slenv.v[1]);
|
||||
u = (u & m_env.u[0]).add16(m_env.u[1]);
|
||||
v = (v & m_env.v[0]).add16(m_env.v[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
u = u.min_i16(m_slenv.u[2]);
|
||||
v = v.min_i16(m_slenv.v[2]);
|
||||
u = u.min_i16(m_env.u[2]);
|
||||
v = v.min_i16(m_env.v[2]);
|
||||
}
|
||||
|
||||
GSVector4i addr = v.sll16(8) | u;
|
||||
@@ -440,7 +422,7 @@ void GPUDrawScanline::WriteFrame(WORD* RESTRICT fb, const GSVector4i& test, cons
|
||||
GSVector4i b = (c[2] & 0x00f800f8) << 7;
|
||||
GSVector4i a = (c[3] & 0x00800080) << 8;
|
||||
|
||||
GSVector4i s = r | g | b | a | m_slenv.md;
|
||||
GSVector4i s = r | g | b | a | m_env.md;
|
||||
|
||||
int i = 0;
|
||||
|
||||
@@ -733,17 +715,17 @@ __declspec(align(16)) static WORD s_dither[4][16] =
|
||||
{4, 3, 5, 2, 4, 3, 5, 2, 4, 3, 5, 2, 4, 3, 5, 2},
|
||||
};
|
||||
|
||||
void GPUDrawScanline::DrawScanlineT(int top, int left, int right, const Vertex& v)
|
||||
void GPUDrawScanline::DrawScanlineT(int top, int left, int right, const GSVertexSW& v)
|
||||
{
|
||||
GSVector4i s, t;
|
||||
GSVector4i r, g, b;
|
||||
|
||||
if(m_sel.tme)
|
||||
if(m_env.sel.tme)
|
||||
{
|
||||
GSVector4i vt = GSVector4i(v.t).xxzzl();
|
||||
|
||||
s = vt.xxxx().add16(m_slenv.ds);
|
||||
t = vt.yyyy().add16(m_slenv.dt);
|
||||
s = vt.xxxx().add16(m_env.ds);
|
||||
t = vt.yyyy().add16(m_env.dt);
|
||||
}
|
||||
|
||||
GSVector4i vc = GSVector4i(v.c).xxzzl().xxzzh();
|
||||
@@ -752,23 +734,23 @@ void GPUDrawScanline::DrawScanlineT(int top, int left, int right, const Vertex&
|
||||
g = vc.yyyy();
|
||||
b = vc.zzzz();
|
||||
|
||||
if(m_sel.iip)
|
||||
if(m_env.sel.iip)
|
||||
{
|
||||
r = r.add16(m_slenv.dr);
|
||||
g = g.add16(m_slenv.dg);
|
||||
b = b.add16(m_slenv.db);
|
||||
r = r.add16(m_env.dr);
|
||||
g = g.add16(m_env.dg);
|
||||
b = b.add16(m_env.db);
|
||||
}
|
||||
|
||||
GSVector4i dither;
|
||||
|
||||
if(m_sel.dtd)
|
||||
if(m_env.sel.dtd)
|
||||
{
|
||||
dither = GSVector4i::load<false>(&s_dither[top & 3][left & 3]);
|
||||
}
|
||||
|
||||
int steps = right - left;
|
||||
|
||||
WORD* fb = m_slenv.mem->GetPixelAddress(left, top);
|
||||
WORD* fb = m_env.mem->GetPixelAddress(left, top);
|
||||
|
||||
while(1)
|
||||
{
|
||||
@@ -780,11 +762,11 @@ void GPUDrawScanline::DrawScanlineT(int top, int left, int right, const Vertex&
|
||||
|
||||
GSVector4i d = GSVector4i::zero();
|
||||
|
||||
if(m_sel.rfb) // me | abe
|
||||
if(m_env.sel.rfb) // me | abe
|
||||
{
|
||||
d = GSVector4i::load<false>(fb);
|
||||
|
||||
if(m_sel.me)
|
||||
if(m_env.sel.me)
|
||||
{
|
||||
test = d.sra16(15);
|
||||
|
||||
@@ -797,19 +779,19 @@ void GPUDrawScanline::DrawScanlineT(int top, int left, int right, const Vertex&
|
||||
|
||||
GSVector4i c[4];
|
||||
|
||||
if(m_sel.tme)
|
||||
if(m_env.sel.tme)
|
||||
{
|
||||
SampleTexture(pixels, m_sel.ltf, m_sel.tlu, m_sel.twin, test, s, t, c);
|
||||
SampleTexture(pixels, m_env.sel.ltf, m_env.sel.tlu, m_env.sel.twin, test, s, t, c);
|
||||
}
|
||||
|
||||
ColorTFX(m_sel.tfx, r, g, b, c);
|
||||
ColorTFX(m_env.sel.tfx, r, g, b, c);
|
||||
|
||||
if(m_sel.abe)
|
||||
if(m_env.sel.abe)
|
||||
{
|
||||
AlphaBlend(m_sel.abr, m_sel.tme, d, c);
|
||||
AlphaBlend(m_env.sel.abr, m_env.sel.tme, d, c);
|
||||
}
|
||||
|
||||
if(m_sel.dtd)
|
||||
if(m_env.sel.dtd)
|
||||
{
|
||||
c[0] = c[0].addus8(dither);
|
||||
c[1] = c[1].addus8(dither);
|
||||
@@ -826,17 +808,17 @@ void GPUDrawScanline::DrawScanlineT(int top, int left, int right, const Vertex&
|
||||
|
||||
fb += 8;
|
||||
|
||||
if(m_sel.tme)
|
||||
if(m_env.sel.tme)
|
||||
{
|
||||
GSVector4i dst8 = m_slenv.dst8;
|
||||
GSVector4i dst8 = m_env.dst8;
|
||||
|
||||
s = s.add16(dst8.xxxx());
|
||||
t = t.add16(dst8.yyyy());
|
||||
}
|
||||
|
||||
if(m_sel.iip)
|
||||
if(m_env.sel.iip)
|
||||
{
|
||||
GSVector4i dc8 = m_slenv.dc8;
|
||||
GSVector4i dc8 = m_env.dc8;
|
||||
|
||||
r = r.add16(dc8.xxxx());
|
||||
g = g.add16(dc8.yyyy());
|
||||
@@ -846,7 +828,7 @@ void GPUDrawScanline::DrawScanlineT(int top, int left, int right, const Vertex&
|
||||
}
|
||||
|
||||
template<DWORD sel>
|
||||
void GPUDrawScanline::DrawScanlineExT(int top, int left, int right, const Vertex& v)
|
||||
void GPUDrawScanline::DrawScanlineExT(int top, int left, int right, const GSVertexSW& v)
|
||||
{
|
||||
DWORD iip = (sel >> 0) & 1;
|
||||
DWORD me = (sel >> 1) & 1;
|
||||
@@ -865,8 +847,8 @@ void GPUDrawScanline::DrawScanlineExT(int top, int left, int right, const Vertex
|
||||
{
|
||||
GSVector4i vt = GSVector4i(v.t).xxzzl();
|
||||
|
||||
s = vt.xxxx().add16(m_slenv.ds);
|
||||
t = vt.yyyy().add16(m_slenv.dt);
|
||||
s = vt.xxxx().add16(m_env.ds);
|
||||
t = vt.yyyy().add16(m_env.dt);
|
||||
}
|
||||
|
||||
GSVector4i vc = GSVector4i(v.c).xxzzl().xxzzh();
|
||||
@@ -877,21 +859,21 @@ void GPUDrawScanline::DrawScanlineExT(int top, int left, int right, const Vertex
|
||||
|
||||
if(iip)
|
||||
{
|
||||
r = r.add16(m_slenv.dr);
|
||||
g = g.add16(m_slenv.dg);
|
||||
b = b.add16(m_slenv.db);
|
||||
r = r.add16(m_env.dr);
|
||||
g = g.add16(m_env.dg);
|
||||
b = b.add16(m_env.db);
|
||||
}
|
||||
|
||||
GSVector4i dither;
|
||||
|
||||
if(m_sel.dtd)
|
||||
if(m_env.sel.dtd)
|
||||
{
|
||||
dither = GSVector4i::load<false>(&s_dither[top & 3][left & 3]);
|
||||
}
|
||||
|
||||
int steps = right - left;
|
||||
|
||||
WORD* fb = m_slenv.mem->GetPixelAddress(left, top);
|
||||
WORD* fb = m_env.mem->GetPixelAddress(left, top);
|
||||
|
||||
while(1)
|
||||
{
|
||||
@@ -922,7 +904,7 @@ void GPUDrawScanline::DrawScanlineExT(int top, int left, int right, const Vertex
|
||||
|
||||
if(tme)
|
||||
{
|
||||
SampleTexture(pixels, m_sel.ltf, m_sel.tlu, twin, test, s, t, c);
|
||||
SampleTexture(pixels, m_env.sel.ltf, m_env.sel.tlu, twin, test, s, t, c);
|
||||
}
|
||||
|
||||
ColorTFX(tfx, r, g, b, c);
|
||||
@@ -932,7 +914,7 @@ void GPUDrawScanline::DrawScanlineExT(int top, int left, int right, const Vertex
|
||||
AlphaBlend(abr, tme, d, c);
|
||||
}
|
||||
|
||||
if(m_sel.dtd)
|
||||
if(m_env.sel.dtd)
|
||||
{
|
||||
c[0] = c[0].addus8(dither);
|
||||
c[1] = c[1].addus8(dither);
|
||||
@@ -951,7 +933,7 @@ void GPUDrawScanline::DrawScanlineExT(int top, int left, int right, const Vertex
|
||||
|
||||
if(tme)
|
||||
{
|
||||
GSVector4i dst8 = m_slenv.dst8;
|
||||
GSVector4i dst8 = m_env.dst8;
|
||||
|
||||
s = s.add16(dst8.xxxx());
|
||||
t = t.add16(dst8.yyyy());
|
||||
@@ -959,7 +941,7 @@ void GPUDrawScanline::DrawScanlineExT(int top, int left, int right, const Vertex
|
||||
|
||||
if(iip)
|
||||
{
|
||||
GSVector4i dc8 = m_slenv.dc8;
|
||||
GSVector4i dc8 = m_env.dc8;
|
||||
|
||||
r = r.add16(dc8.xxxx());
|
||||
g = g.add16(dc8.yyyy());
|
||||
|
||||
@@ -25,66 +25,74 @@
|
||||
#include "GSRasterizer.h"
|
||||
#include "GSAlignedClass.h"
|
||||
|
||||
union GPUScanlineSelector
|
||||
{
|
||||
struct
|
||||
{
|
||||
DWORD iip:1; // 0
|
||||
DWORD me:1; // 1
|
||||
DWORD abe:1; // 2
|
||||
DWORD abr:2; // 3
|
||||
DWORD tge:1; // 5
|
||||
DWORD tme:1; // 6
|
||||
DWORD twin:1; // 7
|
||||
DWORD tlu:1; // 8
|
||||
DWORD dtd:1; // 9
|
||||
DWORD ltf:1; // 10
|
||||
// DWORD dte:1: // 11
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
DWORD _pad1:1; // 0
|
||||
DWORD rfb:2; // 1
|
||||
DWORD _pad2:2; // 3
|
||||
DWORD tfx:2; // 5
|
||||
};
|
||||
|
||||
DWORD dw;
|
||||
|
||||
operator DWORD() {return dw & 0xff;}
|
||||
};
|
||||
|
||||
__declspec(align(16)) struct GPUScanlineEnvironment
|
||||
{
|
||||
GPUScanlineSelector sel;
|
||||
|
||||
GPULocalMemory* mem;
|
||||
const void* tex;
|
||||
const WORD* clut;
|
||||
|
||||
GSVector4i u[3];
|
||||
GSVector4i v[3];
|
||||
|
||||
GSVector4i a;
|
||||
GSVector4i md; // similar to gs fba
|
||||
|
||||
GSVector4i ds, dt, dst8;
|
||||
GSVector4i dr, dg, db, dc8;
|
||||
};
|
||||
|
||||
__declspec(align(16)) struct GPUScanlineParam
|
||||
{
|
||||
GPUScanlineSelector sel;
|
||||
|
||||
const void* tex;
|
||||
const WORD* clut;
|
||||
};
|
||||
|
||||
class GPUDrawScanline : public GSAlignedClass<16>, public IDrawScanline
|
||||
{
|
||||
union ScanlineSelector
|
||||
{
|
||||
struct
|
||||
{
|
||||
DWORD iip:1; // 0
|
||||
DWORD me:1; // 1
|
||||
DWORD abe:1; // 2
|
||||
DWORD abr:2; // 3
|
||||
DWORD tge:1; // 5
|
||||
DWORD tme:1; // 6
|
||||
DWORD twin:1; // 7
|
||||
DWORD tlu:1; // 8
|
||||
DWORD dtd:1; // 9
|
||||
DWORD ltf:1; // 10
|
||||
// DWORD dte:1: // 11
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
DWORD _pad1:1; // 0
|
||||
DWORD rfb:2; // 1
|
||||
DWORD _pad2:2; // 3
|
||||
DWORD tfx:2; // 5
|
||||
};
|
||||
|
||||
DWORD dw;
|
||||
|
||||
operator DWORD() {return dw & 0xff;}
|
||||
};
|
||||
|
||||
__declspec(align(16)) struct ScanlineEnvironment
|
||||
{
|
||||
GPULocalMemory* mem;
|
||||
|
||||
const void* tex;
|
||||
const WORD* clut;
|
||||
|
||||
GSVector4i u[3];
|
||||
GSVector4i v[3];
|
||||
|
||||
GSVector4i a;
|
||||
GSVector4i md; // similar to gs fba
|
||||
|
||||
GSVector4i ds, dt, dst8;
|
||||
GSVector4i dr, dg, db, dc8;
|
||||
};
|
||||
|
||||
ScanlineSelector m_sel;
|
||||
ScanlineEnvironment m_slenv;
|
||||
GPUScanlineEnvironment m_env;
|
||||
|
||||
DrawScanlinePtr m_ds[2048], m_dsf;
|
||||
|
||||
void Init();
|
||||
|
||||
void DrawScanlineT(int top, int left, int right, const Vertex& v);
|
||||
void DrawScanlineT(int top, int left, int right, const GSVertexSW& v);
|
||||
|
||||
template<DWORD sel>
|
||||
void DrawScanlineExT(int top, int left, int right, const Vertex& v);
|
||||
void DrawScanlineExT(int top, int left, int right, const GSVertexSW& v);
|
||||
|
||||
__forceinline void SampleTexture(int pixels, DWORD ltf, DWORD tlu, DWORD twin, GSVector4i& test, const GSVector4i& s, const GSVector4i& t, GSVector4i* c);
|
||||
__forceinline void ColorTFX(DWORD tfx, const GSVector4i& r, const GSVector4i& g, const GSVector4i& b, GSVector4i* c);
|
||||
@@ -100,13 +108,11 @@ public:
|
||||
GPUDrawScanline(GPUState* state);
|
||||
virtual ~GPUDrawScanline();
|
||||
|
||||
void SetOptions(int filter, int dither);
|
||||
|
||||
// IDrawScanline
|
||||
|
||||
void SetupDraw(Vertex* vertices, int count, const void* texture);
|
||||
void SetupPrim(PrimitiveType type, const Vertex* vertices, const Vertex& dscan);
|
||||
void DrawScanline(int top, int left, int right, const Vertex& v);
|
||||
void FillRect(const GSVector4i& r, const Vertex& v);
|
||||
bool SetupDraw(const GSRasterizerData* data);
|
||||
void SetupPrim(GS_PRIM_CLASS primclass, const GSVertexSW* vertices, const GSVertexSW& dscan);
|
||||
void DrawScanline(int top, int left, int right, const GSVertexSW& v);
|
||||
void DrawSolidRect(const GSVector4i& r, const GSVertexSW& v);
|
||||
DrawScanlinePtr GetDrawScanlinePtr();
|
||||
};
|
||||
|
||||
@@ -25,10 +25,8 @@
|
||||
#include "GPUDrawScanline.h"
|
||||
|
||||
template <class Device>
|
||||
class GPURendererSW : public GPURenderer<Device, GSVertexSW>, public IDrawAsync
|
||||
class GPURendererSW : public GPURenderer<Device, GSVertexSW>
|
||||
{
|
||||
typedef GSVertexSW Vertex;
|
||||
|
||||
protected:
|
||||
GSRasterizerList m_rl;
|
||||
Texture m_texture;
|
||||
@@ -73,7 +71,7 @@ protected:
|
||||
|
||||
void VertexKick()
|
||||
{
|
||||
Vertex& v = m_vl.AddTail();
|
||||
GSVertexSW& v = m_vl.AddTail();
|
||||
|
||||
// TODO: x/y + off.x/y should wrap around at +/-1024
|
||||
|
||||
@@ -92,17 +90,17 @@ protected:
|
||||
__super::VertexKick();
|
||||
}
|
||||
|
||||
void DrawingKickTriangle(Vertex* v, int& count)
|
||||
void DrawingKickTriangle(GSVertexSW* v, int& count)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
void DrawingKickLine(Vertex* v, int& count)
|
||||
void DrawingKickLine(GSVertexSW* v, int& count)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
void DrawingKickSprite(Vertex* v, int& count)
|
||||
void DrawingKickSprite(GSVertexSW* v, int& count)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
@@ -121,31 +119,52 @@ protected:
|
||||
|
||||
void Draw()
|
||||
{
|
||||
const void* texture = NULL;
|
||||
const GPUDrawingEnvironment& env = m_env;
|
||||
|
||||
if(m_env.PRIM.TME)
|
||||
//
|
||||
|
||||
GPUScanlineParam p;
|
||||
|
||||
p.sel.dw = 0;
|
||||
p.sel.iip = env.PRIM.IIP;
|
||||
p.sel.me = env.STATUS.ME;
|
||||
p.sel.abe = env.PRIM.ABE;
|
||||
p.sel.abr = env.STATUS.ABR;
|
||||
p.sel.tge = env.PRIM.TGE;
|
||||
p.sel.tme = env.PRIM.TME;
|
||||
p.sel.tlu = env.STATUS.TP < 2;
|
||||
p.sel.twin = (env.TWIN.ai32 & 0xfffff) != 0;
|
||||
p.sel.dtd = m_dither ? env.STATUS.DTD : 0;
|
||||
p.sel.ltf = m_filter == 1 && env.PRIM.TYPE == GPU_POLYGON || m_filter == 2 ? 1 : 0;
|
||||
|
||||
if(env.PRIM.TME)
|
||||
{
|
||||
texture = m_mem.GetTexture(m_env.STATUS.TP, m_env.STATUS.TX, m_env.STATUS.TY);
|
||||
const void* t = m_mem.GetTexture(env.STATUS.TP, env.STATUS.TX, env.STATUS.TY);
|
||||
|
||||
if(!texture) {ASSERT(0); return;}
|
||||
if(!t) {ASSERT(0); return;}
|
||||
|
||||
p.tex = t;
|
||||
p.clut = m_mem.GetCLUT(env.STATUS.TP, env.CLUT.X, env.CLUT.Y);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
GSRasterizerData data;
|
||||
|
||||
data.scissor = GetScissor();
|
||||
data.vertices = m_vertices;
|
||||
data.count = m_count;
|
||||
data.param = &p;
|
||||
|
||||
switch(env.PRIM.TYPE)
|
||||
{
|
||||
POSITION pos = m_rl.GetHeadPosition();
|
||||
|
||||
while(pos)
|
||||
{
|
||||
GSRasterizerMT* r = m_rl.GetNext(pos);
|
||||
|
||||
GPUDrawScanline* ds = (GPUDrawScanline*)r->GetDrawScanline();
|
||||
|
||||
ds->SetOptions(m_filter, m_dither);
|
||||
}
|
||||
case GPU_POLYGON: data.primclass = GS_TRIANGLE_CLASS; break;
|
||||
case GPU_LINE: data.primclass = GS_LINE_CLASS; break;
|
||||
case GPU_SPRITE: data.primclass = GS_SPRITE_CLASS; break;
|
||||
default: __assume(0);
|
||||
}
|
||||
|
||||
int prims = m_rl.Draw(m_vertices, m_count, texture);
|
||||
int prims = m_rl.Draw(&data);
|
||||
|
||||
m_perfmon.Put(GSPerfMon::Prim, prims);
|
||||
m_perfmon.Put(GSPerfMon::Draw, 1);
|
||||
@@ -168,7 +187,7 @@ protected:
|
||||
br = br.maxv(p);
|
||||
}
|
||||
|
||||
GSVector4i scissor = GetScissor();
|
||||
GSVector4i scissor = data.scissor;
|
||||
|
||||
CRect r;
|
||||
|
||||
@@ -217,7 +236,7 @@ public:
|
||||
GPURendererSW(const GPURendererSettings& rs, int threads)
|
||||
: GPURenderer(rs)
|
||||
{
|
||||
m_rl.Create<GPUDrawScanline>(this, this, threads);
|
||||
m_rl.Create<GPUDrawScanline>(this, threads);
|
||||
|
||||
m_fpDrawingKickHandlers[GPU_POLYGON] = (DrawingKickHandler)&GPURendererSW::DrawingKickTriangle;
|
||||
m_fpDrawingKickHandlers[GPU_LINE] = (DrawingKickHandler)&GPURendererSW::DrawingKickLine;
|
||||
|
||||
25
gsdx/GS.h
25
gsdx/GS.h
@@ -26,7 +26,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#define PLUGIN_VERSION 12
|
||||
#define PLUGIN_VERSION 13
|
||||
|
||||
#include "GSVector.h"
|
||||
|
||||
@@ -72,6 +72,15 @@ enum GS_PRIM
|
||||
GS_INVALID = 7,
|
||||
};
|
||||
|
||||
enum GS_PRIM_CLASS
|
||||
{
|
||||
GS_POINT_CLASS = 0,
|
||||
GS_LINE_CLASS = 1,
|
||||
GS_TRIANGLE_CLASS = 2,
|
||||
GS_SPRITE_CLASS = 3,
|
||||
GS_INVALID_CLASS = 7,
|
||||
};
|
||||
|
||||
enum GIF_REG
|
||||
{
|
||||
GIF_REG_PRIM = 0x00,
|
||||
@@ -508,7 +517,9 @@ REG64_(GIFReg, ALPHA)
|
||||
UINT32 _PAD1:24;
|
||||
UINT32 FIX:8;
|
||||
UINT32 _PAD2:24;
|
||||
REG_END
|
||||
REG_END2
|
||||
bool IsOpaque() const {return (A == B || C == 2 && FIX == 0) && D == 0 || (A == 0 && B == 2 && C == 2 && D == 2 && FIX == 0x80);} // output will be Cs/As
|
||||
REG_END2
|
||||
|
||||
REG64_(GIFReg, BITBLTBUF)
|
||||
UINT32 SBP:14;
|
||||
@@ -806,7 +817,15 @@ REG64_(GIFReg, TEX1)
|
||||
UINT32 _PAD3:11;
|
||||
UINT32 K:12;
|
||||
UINT32 _PAD4:20;
|
||||
REG_END
|
||||
REG_END2
|
||||
bool IsLinear() const
|
||||
{
|
||||
bool mmag = (MMAG & 1);
|
||||
bool mmin = (MMIN == 1) || (MMIN & 4);
|
||||
|
||||
return !LCM ? mmag || mmin : K <= 0 ? mmag : mmin;
|
||||
}
|
||||
REG_END2
|
||||
|
||||
REG64_(GIFReg, TEX2)
|
||||
UINT32 _PAD1:20;
|
||||
|
||||
@@ -831,50 +831,3 @@ HRESULT GSDevice10::CompileShader(UINT id, LPCSTR entry, D3D10_SHADER_MACRO* mac
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
bool GSDevice10::SaveToFileD32S8X24(ID3D10Texture2D* ds, LPCTSTR fn)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
D3D10_TEXTURE2D_DESC desc;
|
||||
|
||||
memset(&desc, 0, sizeof(desc));
|
||||
|
||||
ds->GetDesc(&desc);
|
||||
|
||||
desc.Usage = D3D10_USAGE_STAGING;
|
||||
desc.BindFlags = 0;
|
||||
desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ;
|
||||
|
||||
CComPtr<ID3D10Texture2D> src, dst;
|
||||
|
||||
hr = m_dev->CreateTexture2D(&desc, NULL, &src);
|
||||
|
||||
m_dev->CopyResource(src, ds);
|
||||
|
||||
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
|
||||
|
||||
hr = m_dev->CreateTexture2D(&desc, NULL, &dst);
|
||||
|
||||
D3D10_MAPPED_TEXTURE2D sm, dm;
|
||||
|
||||
hr = src->Map(0, D3D10_MAP_READ, 0, &sm);
|
||||
hr = dst->Map(0, D3D10_MAP_WRITE, 0, &dm);
|
||||
|
||||
BYTE* s = (BYTE*)sm.pData;
|
||||
BYTE* d = (BYTE*)dm.pData;
|
||||
|
||||
for(UINT y = 0; y < desc.Height; y++, s += sm.RowPitch, d += dm.RowPitch)
|
||||
{
|
||||
for(UINT x = 0; x < desc.Width; x++)
|
||||
{
|
||||
((UINT*)d)[x] = (UINT)(((float*)s)[x*2] * UINT_MAX);
|
||||
}
|
||||
}
|
||||
|
||||
src->Unmap(0);
|
||||
dst->Unmap(0);
|
||||
|
||||
return SUCCEEDED(D3DX10SaveTextureToFile(dst, D3DX10_IFF_BMP, fn));
|
||||
}
|
||||
|
||||
@@ -848,43 +848,6 @@ void GSDevice9::DrawPrimitive()
|
||||
m_dev->DrawPrimitiveUP(m_topology, prims, m_vb_vertices, m_vb_stride);
|
||||
}
|
||||
|
||||
bool GSDevice9::SaveToFileD24S8(IDirect3DSurface9* ds, LPCTSTR fn)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
D3DSURFACE_DESC desc;
|
||||
|
||||
ds->GetDesc(&desc);
|
||||
|
||||
if(desc.Format != D3DFMT_D32F_LOCKABLE)
|
||||
return false;
|
||||
|
||||
CComPtr<IDirect3DSurface9> surface;
|
||||
|
||||
hr = m_dev->CreateOffscreenPlainSurface(desc.Width, desc.Height, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surface, NULL);
|
||||
|
||||
D3DLOCKED_RECT slr, dlr;
|
||||
|
||||
hr = ds->LockRect(&slr, NULL, 0);;
|
||||
hr = surface->LockRect(&dlr, NULL, 0);
|
||||
|
||||
BYTE* s = (BYTE*)slr.pBits;
|
||||
BYTE* d = (BYTE*)dlr.pBits;
|
||||
|
||||
for(UINT y = 0; y < desc.Height; y++, s += slr.Pitch, d += dlr.Pitch)
|
||||
{
|
||||
for(UINT x = 0; x < desc.Width; x++)
|
||||
{
|
||||
((float*)d)[x] = ((float*)s)[x];
|
||||
}
|
||||
}
|
||||
|
||||
ds->UnlockRect();
|
||||
surface->UnlockRect();
|
||||
|
||||
return SUCCEEDED(D3DXSaveSurfaceToFile(fn, D3DXIFF_BMP, surface, NULL, NULL));
|
||||
}
|
||||
|
||||
void GSDevice9::StretchRect(Texture& st, Texture& dt, const GSVector4& dr, bool linear)
|
||||
{
|
||||
StretchRect(st, GSVector4(0, 0, 1, 1), dt, dr, linear);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -25,73 +25,87 @@
|
||||
#include "GSRasterizer.h"
|
||||
#include "GSAlignedClass.h"
|
||||
|
||||
union GSScanlineSelector
|
||||
{
|
||||
struct
|
||||
{
|
||||
DWORD fpsm:2; // 0
|
||||
DWORD zpsm:2; // 2
|
||||
DWORD ztst:2; // 4 (0: off, 1: write, 2: test (ge), 3: test (g))
|
||||
DWORD atst:3; // 6
|
||||
DWORD afail:2; // 9
|
||||
DWORD iip:1; // 11
|
||||
DWORD tfx:3; // 12
|
||||
DWORD tcc:1; // 15
|
||||
DWORD fst:1; // 16
|
||||
DWORD ltf:1; // 17
|
||||
DWORD tlu:1; // 18
|
||||
DWORD fge:1; // 19
|
||||
DWORD date:1; // 20
|
||||
DWORD abea:2; // 21
|
||||
DWORD abeb:2; // 23
|
||||
DWORD abec:2; // 25
|
||||
DWORD abed:2; // 27
|
||||
DWORD pabe:1; // 29
|
||||
DWORD rfb:1; // 30
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
DWORD _pad1:21;
|
||||
DWORD abe:8;
|
||||
DWORD _pad2:3;
|
||||
};
|
||||
|
||||
DWORD dw;
|
||||
|
||||
operator DWORD() {return dw & 0x7fffffff;}
|
||||
};
|
||||
|
||||
__declspec(align(16)) struct GSScanlineEnvironment
|
||||
{
|
||||
GSScanlineSelector sel;
|
||||
|
||||
void* vm;
|
||||
const void* tex;
|
||||
const DWORD* clut;
|
||||
DWORD tw;
|
||||
|
||||
GSVector4i* fbr;
|
||||
GSVector4i* zbr;
|
||||
int** fbc;
|
||||
int** zbc;
|
||||
|
||||
GSVector4i fm, zm;
|
||||
struct {GSVector4i min, max, mask;} t; // [u] x 4 [v] x 4
|
||||
GSVector4i datm;
|
||||
GSVector4i colclamp;
|
||||
GSVector4i fba;
|
||||
GSVector4i aref;
|
||||
GSVector4i afix, afix2;
|
||||
GSVector4i frb, fga;
|
||||
|
||||
GSVector4 dz, dz4;
|
||||
GSVector4i df, df4;
|
||||
GSVector4 dt, dt4;
|
||||
GSVector4i drb, dga, dc4;
|
||||
};
|
||||
|
||||
__declspec(align(16)) struct GSScanlineParam
|
||||
{
|
||||
GSScanlineSelector sel;
|
||||
|
||||
void* vm;
|
||||
const void* tex;
|
||||
const DWORD* clut;
|
||||
DWORD tw;
|
||||
|
||||
DWORD fm, zm;
|
||||
};
|
||||
|
||||
class GSDrawScanline : public GSAlignedClass<16>, public IDrawScanline
|
||||
{
|
||||
union ScanlineSelector
|
||||
{
|
||||
struct
|
||||
{
|
||||
DWORD fpsm:2; // 0
|
||||
DWORD zpsm:2; // 2
|
||||
DWORD ztst:2; // 4 (0: off, 1: write, 2: test (ge), 3: test (g))
|
||||
DWORD iip:1; // 6
|
||||
DWORD tfx:3; // 7
|
||||
DWORD tcc:1; // 10
|
||||
DWORD fst:1; // 11
|
||||
DWORD ltf:1; // 12
|
||||
DWORD atst:3; // 13
|
||||
DWORD afail:2; // 16
|
||||
DWORD fge:1; // 18
|
||||
DWORD date:1; // 19
|
||||
DWORD abea:2; // 20
|
||||
DWORD abeb:2; // 22
|
||||
DWORD abec:2; // 24
|
||||
DWORD abed:2; // 26
|
||||
DWORD pabe:1; // 28
|
||||
DWORD rfb:1; // 29
|
||||
DWORD wzb:1; // 30
|
||||
DWORD tlu:1; // 31
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
DWORD _pad1:20;
|
||||
DWORD abe:8;
|
||||
DWORD _pad2:4;
|
||||
};
|
||||
|
||||
DWORD dw;
|
||||
|
||||
operator DWORD() {return dw;}// & 0x7fffffff;}
|
||||
};
|
||||
|
||||
__declspec(align(16)) struct ScanlineEnvironment
|
||||
{
|
||||
void* vm;
|
||||
|
||||
const void* tex;
|
||||
const DWORD* clut;
|
||||
DWORD tw;
|
||||
|
||||
GSVector4i* fbr;
|
||||
GSVector4i* zbr;
|
||||
int** fbc;
|
||||
int** zbc;
|
||||
|
||||
GSVector4i fm, zm;
|
||||
struct {GSVector4i min, max, mask;} t; // [u] x 4 [v] x 4
|
||||
GSVector4i datm;
|
||||
GSVector4i colclamp;
|
||||
GSVector4i fba;
|
||||
GSVector4i aref;
|
||||
GSVector4i afix, afix2;
|
||||
GSVector4i frb, fga;
|
||||
|
||||
GSVector4 dz, dz4;
|
||||
GSVector4i df, df4;
|
||||
GSVector4 dt, dt4;
|
||||
GSVector4i drb, dga, dc4;
|
||||
};
|
||||
GSScanlineEnvironment m_env;
|
||||
|
||||
struct Offset
|
||||
{
|
||||
@@ -100,9 +114,6 @@ class GSDrawScanline : public GSAlignedClass<16>, public IDrawScanline
|
||||
DWORD hash;
|
||||
};
|
||||
|
||||
ScanlineSelector m_sel;
|
||||
ScanlineEnvironment m_slenv;
|
||||
|
||||
CRBMapC<DWORD, Offset*> m_omap;
|
||||
Offset* m_fbo;
|
||||
Offset* m_zbo;
|
||||
@@ -116,19 +127,20 @@ class GSDrawScanline : public GSAlignedClass<16>, public IDrawScanline
|
||||
void Init();
|
||||
|
||||
template<DWORD fpsm, DWORD zpsm, DWORD ztst, DWORD iip>
|
||||
void DrawScanlineT(int top, int left, int right, const Vertex& v);
|
||||
void DrawScanlineT(int top, int left, int right, const GSVertexSW& v);
|
||||
|
||||
template<DWORD sel>
|
||||
void DrawScanlineExT(int top, int left, int right, const Vertex& v);
|
||||
void DrawScanlineExT(int top, int left, int right, const GSVertexSW& v);
|
||||
|
||||
__forceinline GSVector4i Wrap(const GSVector4i& t);
|
||||
|
||||
__forceinline void SampleTexture(int pixels, DWORD ztst, DWORD ltf, DWORD pal, const GSVector4i& test, const GSVector4& u, const GSVector4& v, GSVector4i* c);
|
||||
__forceinline void SampleTexture(int pixels, DWORD ztst, DWORD fst, DWORD ltf, DWORD tlu, const GSVector4i& test, const GSVector4& s, const GSVector4& t, const GSVector4& q, GSVector4i* c);
|
||||
__forceinline void ColorTFX(DWORD tfx, const GSVector4i& rbf, const GSVector4i& gaf, GSVector4i& rbt, GSVector4i& gat);
|
||||
__forceinline void AlphaTFX(DWORD tfx, DWORD tcc, const GSVector4i& gaf, GSVector4i& gat);
|
||||
__forceinline void Fog(const GSVector4i& f, GSVector4i& rb, GSVector4i& ga);
|
||||
__forceinline void Fog(DWORD fge, const GSVector4i& f, GSVector4i& rb, GSVector4i& ga);
|
||||
__forceinline bool TestZ(DWORD zpsm, DWORD ztst, const GSVector4i& zs, const GSVector4i& za, GSVector4i& test);
|
||||
__forceinline bool TestAlpha(DWORD atst, DWORD afail, const GSVector4i& ga, GSVector4i& fm, GSVector4i& zm, GSVector4i& test);
|
||||
__forceinline bool TestDestAlpha(DWORD fpsm, DWORD date, const GSVector4i& d, GSVector4i& test);
|
||||
|
||||
__forceinline static DWORD ReadPixel32(DWORD* RESTRICT vm, DWORD addr);
|
||||
__forceinline static DWORD ReadPixel24(DWORD* RESTRICT vm, DWORD addr);
|
||||
@@ -150,9 +162,9 @@ public:
|
||||
|
||||
// IDrawScanline
|
||||
|
||||
void SetupDraw(Vertex* vertices, int count, const void* texture);
|
||||
void SetupPrim(PrimitiveType type, const Vertex* vertices, const Vertex& dscan);
|
||||
void DrawScanline(int top, int left, int right, const Vertex& v);
|
||||
void FillRect(const GSVector4i& r, const Vertex& v);
|
||||
bool SetupDraw(const GSRasterizerData* data);
|
||||
void SetupPrim(GS_PRIM_CLASS primclass, const GSVertexSW* vertices, const GSVertexSW& dscan);
|
||||
void DrawScanline(int top, int left, int right, const GSVertexSW& v);
|
||||
void DrawSolidRect(const GSVector4i& r, const GSVertexSW& v);
|
||||
DrawScanlinePtr GetDrawScanlinePtr();
|
||||
};
|
||||
|
||||
@@ -96,19 +96,19 @@ public:
|
||||
(int)SCISSOR.SCAY1);
|
||||
}
|
||||
|
||||
bool DepthRead()
|
||||
bool DepthRead() const
|
||||
{
|
||||
return TEST.ZTE && TEST.ZTST >= 2;
|
||||
}
|
||||
|
||||
bool DepthWrite()
|
||||
bool DepthWrite() const
|
||||
{
|
||||
if(TEST.ATE && TEST.ATST == 0 && TEST.AFAIL != 2) // alpha test, all pixels fail, z buffer is not updated
|
||||
if(TEST.ATE && TEST.ATST == ATST_NEVER && TEST.AFAIL != AFAIL_ZB_ONLY) // alpha test, all pixels fail, z buffer is not updated
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return ZBUF.ZMSK == 0;
|
||||
return ZBUF.ZMSK == 0 && TEST.ZTE != 0; // ZTE == 0 is bug on the real hardware, write is blocked then
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -35,7 +35,45 @@ GSRasterizer::~GSRasterizer()
|
||||
delete m_ds;
|
||||
}
|
||||
|
||||
void GSRasterizer::DrawPoint(Vertex* v, const GSVector4i& scissor)
|
||||
int GSRasterizer::Draw(const GSRasterizerData* data)
|
||||
{
|
||||
bool solid = m_ds->SetupDraw(data);
|
||||
|
||||
const GSVector4i scissor = data->scissor;
|
||||
const GSVertexSW* vertices = data->vertices;
|
||||
const int count = data->count;
|
||||
|
||||
int prims = 0;
|
||||
|
||||
switch(data->primclass)
|
||||
{
|
||||
case GS_POINT_CLASS:
|
||||
prims = count;
|
||||
for(int i = 0; i < count; i++) DrawPoint(&vertices[i], scissor);
|
||||
break;
|
||||
case GS_LINE_CLASS:
|
||||
ASSERT(!(count & 1));
|
||||
prims = count / 2;
|
||||
for(int i = 0; i < count; i += 2) DrawLine(&vertices[i], scissor);
|
||||
break;
|
||||
case GS_TRIANGLE_CLASS:
|
||||
ASSERT(!(count % 3));
|
||||
prims = count / 3;
|
||||
for(int i = 0; i < count; i += 3) DrawTriangle(&vertices[i], scissor);
|
||||
break;
|
||||
case GS_SPRITE_CLASS:
|
||||
ASSERT(!(count & 1));
|
||||
prims = count / 2;
|
||||
for(int i = 0; i < count; i += 2) DrawSprite(&vertices[i], scissor, solid);
|
||||
break;
|
||||
default:
|
||||
__assume(0);
|
||||
}
|
||||
|
||||
return prims;
|
||||
}
|
||||
|
||||
void GSRasterizer::DrawPoint(const GSVertexSW* v, const GSVector4i& scissor)
|
||||
{
|
||||
// TODO: round to closest for point, prestep for line
|
||||
|
||||
@@ -52,19 +90,50 @@ void GSRasterizer::DrawPoint(Vertex* v, const GSVector4i& scissor)
|
||||
}
|
||||
}
|
||||
|
||||
void GSRasterizer::DrawLine(Vertex* v, const GSVector4i& scissor)
|
||||
void GSRasterizer::DrawLine(const GSVertexSW* v, const GSVector4i& scissor)
|
||||
{
|
||||
Vertex dv = v[1] - v[0];
|
||||
GSVertexSW dv = v[1] - v[0];
|
||||
|
||||
GSVector4 dp = dv.p.abs();
|
||||
GSVector4i dpi(dp);
|
||||
|
||||
if(dpi.x == 0 && dpi.y == 0) return;
|
||||
if(dpi.y == 0)
|
||||
{
|
||||
if(dpi.x > 0)
|
||||
{
|
||||
// shortcut for horizontal lines
|
||||
|
||||
GSVector4 mask = (v[0].p > v[1].p).xxxx();
|
||||
|
||||
GSVertexSW l, dl;
|
||||
|
||||
l.p = v[0].p.blend8(v[1].p, mask);
|
||||
l.t = v[0].t.blend8(v[1].t, mask);
|
||||
l.c = v[0].c.blend8(v[1].c, mask);
|
||||
|
||||
GSVector4 r, dr;
|
||||
|
||||
r = v[1].p.blend8(v[0].p, mask);
|
||||
|
||||
GSVertexSW dscan = dv / dv.p.xxxx();
|
||||
|
||||
GSVector4i p(l.p);
|
||||
|
||||
if(scissor.y <= p.y && p.y < scissor.w)
|
||||
{
|
||||
m_ds->SetupPrim(GS_LINE_CLASS, v, dscan);
|
||||
|
||||
DrawTriangleSection(p.y, p.y + 1, l, dl, r, dr, dscan, scissor);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int i = dpi.x > dpi.y ? 0 : 1;
|
||||
|
||||
Vertex edge = v[0];
|
||||
Vertex dedge = dv / dp.v[i];
|
||||
GSVertexSW edge = v[0];
|
||||
GSVertexSW dedge = dv / dp.v[i];
|
||||
|
||||
// TODO: prestep + clip with the scissor
|
||||
|
||||
@@ -90,9 +159,9 @@ static const int s_abc[8][4] =
|
||||
{2, 1, 0, 0},
|
||||
};
|
||||
|
||||
void GSRasterizer::DrawTriangle(Vertex* vertices, const GSVector4i& scissor)
|
||||
void GSRasterizer::DrawTriangle(const GSVertexSW* vertices, const GSVector4i& scissor)
|
||||
{
|
||||
Vertex v[3];
|
||||
GSVertexSW v[3];
|
||||
|
||||
GSVector4 aabb = vertices[0].p.yyyy(vertices[1].p);
|
||||
GSVector4 bccb = vertices[1].p.yyyy(vertices[2].p).xzzx();
|
||||
@@ -126,26 +195,26 @@ void GSRasterizer::DrawTriangle(Vertex* vertices, const GSVector4i& scissor)
|
||||
}
|
||||
}
|
||||
|
||||
void GSRasterizer::DrawTriangleTop(Vertex* v, const GSVector4i& scissor)
|
||||
void GSRasterizer::DrawTriangleTop(GSVertexSW* v, const GSVector4i& scissor)
|
||||
{
|
||||
Vertex longest = v[2] - v[1];
|
||||
GSVertexSW longest = v[2] - v[1];
|
||||
|
||||
if((longest.p == GSVector4::zero()).mask() & 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Vertex dscan = longest * longest.p.xxxx().rcp();
|
||||
GSVertexSW dscan = longest * longest.p.xxxx().rcp();
|
||||
|
||||
int i = (longest.p > GSVector4::zero()).mask() & 1;
|
||||
|
||||
Vertex& l = v[0];
|
||||
GSVertexSW& l = v[0];
|
||||
GSVector4 r = v[0].p;
|
||||
|
||||
Vertex vl = v[2 - i] - l;
|
||||
GSVertexSW vl = v[2 - i] - l;
|
||||
GSVector4 vr = v[1 + i].p - r;
|
||||
|
||||
Vertex dl = vl / vl.p.yyyy();
|
||||
GSVertexSW dl = vl / vl.p.yyyy();
|
||||
GSVector4 dr = vr / vr.yyyy();
|
||||
|
||||
GSVector4i tb(l.p.xyxy(v[2].p).ceil());
|
||||
@@ -168,32 +237,32 @@ void GSRasterizer::DrawTriangleTop(Vertex* v, const GSVector4i& scissor)
|
||||
r += dr * dy;
|
||||
}
|
||||
|
||||
m_ds->SetupPrim(IDrawScanline::Triangle, v, dscan);
|
||||
m_ds->SetupPrim(GS_TRIANGLE_CLASS, v, dscan);
|
||||
|
||||
DrawTriangleSection(top, bottom, l, dl, r, dr, dscan, scissor);
|
||||
}
|
||||
}
|
||||
|
||||
void GSRasterizer::DrawTriangleBottom(Vertex* v, const GSVector4i& scissor)
|
||||
void GSRasterizer::DrawTriangleBottom(GSVertexSW* v, const GSVector4i& scissor)
|
||||
{
|
||||
Vertex longest = v[1] - v[0];
|
||||
GSVertexSW longest = v[1] - v[0];
|
||||
|
||||
if((longest.p == GSVector4::zero()).mask() & 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Vertex dscan = longest * longest.p.xxxx().rcp();
|
||||
GSVertexSW dscan = longest * longest.p.xxxx().rcp();
|
||||
|
||||
int i = (longest.p > GSVector4::zero()).mask() & 1;
|
||||
|
||||
Vertex& l = v[1 - i];
|
||||
GSVertexSW& l = v[1 - i];
|
||||
GSVector4& r = v[i].p;
|
||||
|
||||
Vertex vl = v[2] - l;
|
||||
GSVertexSW vl = v[2] - l;
|
||||
GSVector4 vr = v[2].p - r;
|
||||
|
||||
Vertex dl = vl / vl.p.yyyy();
|
||||
GSVertexSW dl = vl / vl.p.yyyy();
|
||||
GSVector4 dr = vr / vr.yyyy();
|
||||
|
||||
GSVector4i tb(l.p.xyxy(v[2].p).ceil());
|
||||
@@ -216,34 +285,34 @@ void GSRasterizer::DrawTriangleBottom(Vertex* v, const GSVector4i& scissor)
|
||||
r += dr * dy;
|
||||
}
|
||||
|
||||
m_ds->SetupPrim(IDrawScanline::Triangle, v, dscan);
|
||||
m_ds->SetupPrim(GS_TRIANGLE_CLASS, v, dscan);
|
||||
|
||||
DrawTriangleSection(top, bottom, l, dl, r, dr, dscan, scissor);
|
||||
}
|
||||
}
|
||||
|
||||
void GSRasterizer::DrawTriangleTopBottom(Vertex* v, const GSVector4i& scissor)
|
||||
void GSRasterizer::DrawTriangleTopBottom(GSVertexSW* v, const GSVector4i& scissor)
|
||||
{
|
||||
Vertex v01, v02, v12;
|
||||
GSVertexSW v01, v02, v12;
|
||||
|
||||
v01 = v[1] - v[0];
|
||||
v02 = v[2] - v[0];
|
||||
|
||||
Vertex longest = v[0] + v02 * (v01.p / v02.p).yyyy() - v[1];
|
||||
GSVertexSW longest = v[0] + v02 * (v01.p / v02.p).yyyy() - v[1];
|
||||
|
||||
if((longest.p == GSVector4::zero()).mask() & 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Vertex dscan = longest * longest.p.xxxx().rcp();
|
||||
GSVertexSW dscan = longest * longest.p.xxxx().rcp();
|
||||
|
||||
m_ds->SetupPrim(IDrawScanline::Triangle, v, dscan);
|
||||
m_ds->SetupPrim(GS_TRIANGLE_CLASS, v, dscan);
|
||||
|
||||
Vertex& l = v[0];
|
||||
GSVertexSW& l = v[0];
|
||||
GSVector4 r = v[0].p;
|
||||
|
||||
Vertex dl;
|
||||
GSVertexSW dl;
|
||||
GSVector4 dr;
|
||||
|
||||
bool b = (longest.p > GSVector4::zero()).mask() & 1;
|
||||
@@ -319,7 +388,7 @@ void GSRasterizer::DrawTriangleTopBottom(Vertex* v, const GSVector4i& scissor)
|
||||
}
|
||||
}
|
||||
|
||||
void GSRasterizer::DrawTriangleSection(int top, int bottom, Vertex& l, const Vertex& dl, GSVector4& r, const GSVector4& dr, const Vertex& dscan, const GSVector4i& scissor)
|
||||
void GSRasterizer::DrawTriangleSection(int top, int bottom, GSVertexSW& l, const GSVertexSW& dl, GSVector4& r, const GSVector4& dr, const GSVertexSW& dscan, const GSVector4i& scissor)
|
||||
{
|
||||
ASSERT(top < bottom);
|
||||
|
||||
@@ -361,7 +430,7 @@ void GSRasterizer::DrawTriangleSection(int top, int bottom, Vertex& l, const Ver
|
||||
{
|
||||
m_pixels += pixels;
|
||||
|
||||
Vertex scan = l;
|
||||
GSVertexSW scan = l;
|
||||
|
||||
float px = (float)left - l.p.x;
|
||||
|
||||
@@ -380,9 +449,9 @@ void GSRasterizer::DrawTriangleSection(int top, int bottom, Vertex& l, const Ver
|
||||
}
|
||||
}
|
||||
|
||||
void GSRasterizer::DrawSprite(Vertex* vertices, const GSVector4i& scissor, bool solid)
|
||||
void GSRasterizer::DrawSprite(const GSVertexSW* vertices, const GSVector4i& scissor, bool solid)
|
||||
{
|
||||
Vertex v[2];
|
||||
GSVertexSW v[2];
|
||||
|
||||
GSVector4 mask = vertices[0].p > vertices[1].p;
|
||||
|
||||
@@ -419,13 +488,15 @@ void GSRasterizer::DrawSprite(Vertex* vertices, const GSVector4i& scissor, bool
|
||||
|
||||
#endif
|
||||
|
||||
Vertex scan = v[0];
|
||||
GSVertexSW scan = v[0];
|
||||
|
||||
if(solid)
|
||||
{
|
||||
if(m_id == 0)
|
||||
{
|
||||
m_ds->FillRect(r, scan);
|
||||
m_ds->DrawSolidRect(r, scan);
|
||||
|
||||
m_pixels += (r.z - r.x) * (r.w - r.y);
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -433,12 +504,12 @@ void GSRasterizer::DrawSprite(Vertex* vertices, const GSVector4i& scissor, bool
|
||||
|
||||
GSVector4 zero = GSVector4::zero();
|
||||
|
||||
Vertex dedge, dscan;
|
||||
GSVertexSW dedge, dscan;
|
||||
|
||||
dedge.p = zero;
|
||||
dscan.p = zero;
|
||||
|
||||
Vertex dv = v[1] - v[0];
|
||||
GSVertexSW dv = v[1] - v[0];
|
||||
|
||||
dedge.t = (dv.t / dv.p.yyyy()).xyxy(zero).wyww();
|
||||
dscan.t = (dv.t / dv.p.xxxx()).xyxy(zero).xwww();
|
||||
@@ -446,7 +517,7 @@ void GSRasterizer::DrawSprite(Vertex* vertices, const GSVector4i& scissor, bool
|
||||
if(scan.p.y < (float)top) scan.t += dedge.t * ((float)top - scan.p.y);
|
||||
if(scan.p.x < (float)left) scan.t += dscan.t * ((float)left - scan.p.x);
|
||||
|
||||
m_ds->SetupPrim(IDrawScanline::Sprite, v, dscan);
|
||||
m_ds->SetupPrim(GS_SPRITE_CLASS, v, dscan);
|
||||
|
||||
IDrawScanline::DrawScanlinePtr dsf = m_ds->GetDrawScanlinePtr();
|
||||
|
||||
@@ -463,13 +534,13 @@ void GSRasterizer::DrawSprite(Vertex* vertices, const GSVector4i& scissor, bool
|
||||
|
||||
//
|
||||
|
||||
GSRasterizerMT::GSRasterizerMT(IDrawScanline* ds, int id, int threads, IDrawAsync* da, long* sync)
|
||||
GSRasterizerMT::GSRasterizerMT(IDrawScanline* ds, int id, int threads, long* sync)
|
||||
: GSRasterizer(ds, id, threads)
|
||||
, m_da(da)
|
||||
, m_sync(sync)
|
||||
, m_exit(false)
|
||||
, m_ThreadId(0)
|
||||
, m_hThread(NULL)
|
||||
, m_data(NULL)
|
||||
{
|
||||
if(id > 0)
|
||||
{
|
||||
@@ -492,18 +563,18 @@ GSRasterizerMT::~GSRasterizerMT()
|
||||
}
|
||||
}
|
||||
|
||||
int GSRasterizerMT::Draw(Vertex* vertices, int count, const void* texture)
|
||||
int GSRasterizerMT::Draw(const GSRasterizerData* data)
|
||||
{
|
||||
m_ds->SetupDraw(vertices, count, texture);
|
||||
|
||||
int prims = 0;
|
||||
|
||||
if(m_id == 0)
|
||||
{
|
||||
prims = m_da->DrawAsync(this);
|
||||
prims = __super::Draw(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_data = data;
|
||||
|
||||
InterlockedBitTestAndSet(m_sync, m_id);
|
||||
}
|
||||
|
||||
@@ -523,7 +594,7 @@ DWORD GSRasterizerMT::ThreadProc()
|
||||
{
|
||||
if(*m_sync & (1 << m_id))
|
||||
{
|
||||
m_da->DrawAsync(this);
|
||||
__super::Draw(m_data);
|
||||
|
||||
InterlockedBitTestAndReset(m_sync, m_id);
|
||||
}
|
||||
@@ -560,7 +631,7 @@ void GSRasterizerList::FreeRasterizers()
|
||||
}
|
||||
}
|
||||
|
||||
int GSRasterizerList::Draw(GSVertexSW* vertices, int count, const void* texture)
|
||||
int GSRasterizerList::Draw(const GSRasterizerData* data)
|
||||
{
|
||||
*m_sync = 0;
|
||||
|
||||
@@ -570,9 +641,7 @@ int GSRasterizerList::Draw(GSVertexSW* vertices, int count, const void* texture)
|
||||
|
||||
while(pos)
|
||||
{
|
||||
GSRasterizerMT* r = GetPrev(pos);
|
||||
|
||||
prims += r->Draw(vertices, count, texture);
|
||||
prims += GetPrev(pos)->Draw(data);
|
||||
}
|
||||
|
||||
while(*m_sync)
|
||||
|
||||
@@ -21,83 +21,93 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GS.h"
|
||||
#include "GSVertexSW.h"
|
||||
|
||||
#define FAST_DRAWSCANLINE
|
||||
|
||||
__declspec(align(16)) class GSRasterizerData
|
||||
{
|
||||
public:
|
||||
GSVector4i scissor;
|
||||
GS_PRIM_CLASS primclass;
|
||||
const GSVertexSW* vertices;
|
||||
int count;
|
||||
const void* param;
|
||||
};
|
||||
|
||||
class IRasterizer
|
||||
{
|
||||
public:
|
||||
virtual int Draw(const GSRasterizerData* data) = 0;
|
||||
virtual int GetPixels() = 0;
|
||||
};
|
||||
|
||||
class IDrawScanline
|
||||
{
|
||||
public:
|
||||
typedef GSVertexSW Vertex;
|
||||
typedef void (IDrawScanline::*DrawScanlinePtr)(int top, int left, int right, const Vertex& v);
|
||||
|
||||
enum PrimitiveType {Point, Line, Triangle, Sprite};
|
||||
typedef void (IDrawScanline::*DrawScanlinePtr)(int top, int left, int right, const GSVertexSW& v);
|
||||
|
||||
virtual ~IDrawScanline() {}
|
||||
|
||||
virtual void SetupDraw(Vertex* vertices, int count, const void* texture) = 0;
|
||||
virtual void SetupPrim(PrimitiveType type, const Vertex* vertices, const Vertex& dscan) = 0;
|
||||
virtual void DrawScanline(int top, int left, int right, const Vertex& v) = 0;
|
||||
virtual void FillRect(const GSVector4i& r, const Vertex& v) = 0;
|
||||
virtual bool SetupDraw(const GSRasterizerData* data) = 0;
|
||||
virtual void SetupPrim(GS_PRIM_CLASS primclass, const GSVertexSW* vertices, const GSVertexSW& dscan) = 0;
|
||||
virtual void DrawScanline(int top, int left, int right, const GSVertexSW& v) = 0;
|
||||
virtual void DrawSolidRect(const GSVector4i& r, const GSVertexSW& v) = 0;
|
||||
virtual DrawScanlinePtr GetDrawScanlinePtr() = 0;
|
||||
};
|
||||
|
||||
class GSRasterizer
|
||||
class GSRasterizer : public IRasterizer
|
||||
{
|
||||
protected:
|
||||
typedef GSVertexSW Vertex;
|
||||
|
||||
IDrawScanline* m_ds;
|
||||
int m_id;
|
||||
int m_threads;
|
||||
int m_pixels;
|
||||
|
||||
void DrawTriangleTop(Vertex* v, const GSVector4i& scissor);
|
||||
void DrawTriangleBottom(Vertex* v, const GSVector4i& scissor);
|
||||
void DrawTriangleTopBottom(Vertex* v, const GSVector4i& scissor);
|
||||
void DrawPoint(const GSVertexSW* v, const GSVector4i& scissor);
|
||||
void DrawLine(const GSVertexSW* v, const GSVector4i& scissor);
|
||||
void DrawTriangle(const GSVertexSW* v, const GSVector4i& scissor);
|
||||
void DrawSprite(const GSVertexSW* v, const GSVector4i& scissor, bool solid);
|
||||
|
||||
__forceinline void DrawTriangleSection(int top, int bottom, Vertex& l, const Vertex& dl, GSVector4& r, const GSVector4& dr, const Vertex& dscan, const GSVector4i& scissor);
|
||||
void DrawTriangleTop(GSVertexSW* v, const GSVector4i& scissor);
|
||||
void DrawTriangleBottom(GSVertexSW* v, const GSVector4i& scissor);
|
||||
void DrawTriangleTopBottom(GSVertexSW* v, const GSVector4i& scissor);
|
||||
|
||||
__forceinline void DrawTriangleSection(int top, int bottom, GSVertexSW& l, const GSVertexSW& dl, GSVector4& r, const GSVector4& dr, const GSVertexSW& dscan, const GSVector4i& scissor);
|
||||
|
||||
public:
|
||||
GSRasterizer(IDrawScanline* ds, int id = 0, int threads = 0);
|
||||
virtual ~GSRasterizer();
|
||||
|
||||
void DrawPoint(Vertex* v, const GSVector4i& scissor);
|
||||
void DrawLine(Vertex* v, const GSVector4i& scissor);
|
||||
void DrawTriangle(Vertex* v, const GSVector4i& scissor);
|
||||
void DrawSprite(Vertex* v, const GSVector4i& scissor, bool solid);
|
||||
|
||||
IDrawScanline* GetDrawScanline() {return m_ds;}
|
||||
// IRasterizer
|
||||
|
||||
int Draw(const GSRasterizerData* data);
|
||||
int GetPixels() {int pixels = m_pixels; m_pixels = 0; return pixels;}
|
||||
};
|
||||
|
||||
interface IDrawAsync
|
||||
{
|
||||
public:
|
||||
virtual int DrawAsync(GSRasterizer* r) = 0;
|
||||
};
|
||||
|
||||
class GSRasterizerMT : public GSRasterizer
|
||||
{
|
||||
IDrawAsync* m_da;
|
||||
long* m_sync;
|
||||
bool m_exit;
|
||||
DWORD m_ThreadId;
|
||||
HANDLE m_hThread;
|
||||
const GSRasterizerData* m_data;
|
||||
|
||||
static DWORD WINAPI StaticThreadProc(LPVOID lpParam);
|
||||
|
||||
DWORD ThreadProc();
|
||||
|
||||
public:
|
||||
GSRasterizerMT(IDrawScanline* ds, int id, int threads, IDrawAsync* da, long* sync);
|
||||
GSRasterizerMT(IDrawScanline* ds, int id, int threads, long* sync);
|
||||
virtual ~GSRasterizerMT();
|
||||
|
||||
int Draw(Vertex* vertices, int count, const void* texture);
|
||||
// IRasterizer
|
||||
|
||||
int Draw(const GSRasterizerData* data);
|
||||
};
|
||||
|
||||
class GSRasterizerList : public CAtlList<GSRasterizerMT*>
|
||||
class GSRasterizerList : public CAtlList<GSRasterizerMT*>, public IRasterizer
|
||||
{
|
||||
long* m_sync;
|
||||
|
||||
@@ -107,7 +117,7 @@ public:
|
||||
GSRasterizerList();
|
||||
virtual ~GSRasterizerList();
|
||||
|
||||
template<class DS, class T> void Create(T* parent, IDrawAsync* da, int threads)
|
||||
template<class DS, class T> void Create(T* parent, int threads)
|
||||
{
|
||||
FreeRasterizers();
|
||||
|
||||
@@ -115,10 +125,12 @@ public:
|
||||
|
||||
for(int i = 0; i < threads; i++)
|
||||
{
|
||||
AddTail(new GSRasterizerMT(new DS(parent), i, threads, da, m_sync));
|
||||
AddTail(new GSRasterizerMT(new DS(parent), i, threads, m_sync));
|
||||
}
|
||||
}
|
||||
|
||||
int Draw(GSVertexSW* vertices, int count, const void* texture);
|
||||
// IRasterizer
|
||||
|
||||
int Draw(const GSRasterizerData* data);
|
||||
int GetPixels();
|
||||
};
|
||||
@@ -330,7 +330,8 @@ protected:
|
||||
if(PRIM->TME && tex->m_palette) if(s_save) tex->m_palette.Save(str, true);
|
||||
str.Format(_T("c:\\temp2\\_%05d_f%I64d_rt0_%05x_%d.bmp"), s_n++, m_perfmon.GetFrame(), context->FRAME.Block(), context->FRAME.PSM);
|
||||
if(s_save) rt->m_texture.Save(str);
|
||||
// str.Format(_T("c:\\temp2\\_%05d_f%I64d_rz0_%05x_%d.bmp"), s_n-1, m_perfmon.GetFrame(), context->ZBUF.Block(), context->ZBUF.PSM);
|
||||
str.Format(_T("c:\\temp2\\_%05d_f%I64d_rz0_%05x_%d.bmp"), s_n-1, m_perfmon.GetFrame(), context->ZBUF.Block(), context->ZBUF.PSM);
|
||||
if(s_savez) ds->m_texture.Save(str);
|
||||
// if(s_savez) m_dev.SaveToFileD32S8X24(ds->m_texture, str); // TODO
|
||||
// if(s_savez) m_dev.SaveToFileD24S8(ds->m_texture, str); // TODO
|
||||
}
|
||||
@@ -353,7 +354,8 @@ protected:
|
||||
CString str;
|
||||
str.Format(_T("c:\\temp2\\_%05d_f%I64d_rt1_%05x_%d.bmp"), s_n++, m_perfmon.GetFrame(), context->FRAME.Block(), context->FRAME.PSM);
|
||||
if(s_save) rt->m_texture.Save(str);
|
||||
// str.Format(_T("c:\\temp2\\_%05d_f%I64d_rz1_%05x_%d.bmp"), s_n-1, m_perfmon.GetFrame(), context->ZBUF.Block(), context->ZBUF.PSM);
|
||||
str.Format(_T("c:\\temp2\\_%05d_f%I64d_rz1_%05x_%d.bmp"), s_n-1, m_perfmon.GetFrame(), context->ZBUF.Block(), context->ZBUF.PSM);
|
||||
if(s_savez) ds->m_texture.Save(str);
|
||||
// if(s_savez) m_dev.SaveToFileD32S8X24(ds->m_texture, str); // TODO
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,7 +220,22 @@ void GSRendererHW10::Draw(int prim, Texture& rt, Texture& ds, GSTextureCache<Dev
|
||||
{
|
||||
GSDrawingEnvironment& env = m_env;
|
||||
GSDrawingContext* context = m_context;
|
||||
/*
|
||||
if(s_dump)
|
||||
{
|
||||
TRACE(_T("\n"));
|
||||
|
||||
TRACE(_T("PRIM = %d, ZMSK = %d, ZTE = %d, ZTST = %d, ATE = %d, ATST = %d, AFAIL = %d, AREF = %02x\n"),
|
||||
PRIM->PRIM, context->ZBUF.ZMSK,
|
||||
context->TEST.ZTE, context->TEST.ZTST,
|
||||
context->TEST.ATE, context->TEST.ATST, context->TEST.AFAIL, context->TEST.AREF);
|
||||
|
||||
for(int i = 0; i < m_count; i++)
|
||||
{
|
||||
TRACE(_T("[%d] %3.0f %3.0f %3.0f %3.0f\n"), i, (float)m_vertices[i].p.x / 16, (float)m_vertices[i].p.y / 16, (float)m_vertices[i].p.z, (float)m_vertices[i].a);
|
||||
}
|
||||
}
|
||||
*/
|
||||
D3D10_PRIMITIVE_TOPOLOGY topology;
|
||||
int prims = 0;
|
||||
|
||||
|
||||
@@ -28,16 +28,37 @@
|
||||
extern const GSVector4 g_pos_scale;
|
||||
|
||||
template <class Device>
|
||||
class GSRendererSW : public GSRendererT<Device, GSVertexSW>, public IDrawAsync
|
||||
class GSRendererSW : public GSRendererT<Device, GSVertexSW>
|
||||
{
|
||||
typedef GSVertexSW Vertex;
|
||||
|
||||
protected:
|
||||
GSRasterizerList m_rl;
|
||||
GSTextureCacheSW* m_tc;
|
||||
Texture m_texture[2];
|
||||
bool m_reset;
|
||||
|
||||
__declspec(align(16)) struct VertexTrace
|
||||
{
|
||||
GSVertexSW v;
|
||||
|
||||
union
|
||||
{
|
||||
DWORD value;
|
||||
struct {DWORD s:1, t:1, q:1, _pad:1, r:1, g:1, b:1, a:1;};
|
||||
struct {DWORD stq:4, rgba:4;};
|
||||
} eq;
|
||||
|
||||
bool first;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
first = true;
|
||||
eq.value = 0xffffffff;
|
||||
}
|
||||
|
||||
VertexTrace() {Reset();}
|
||||
|
||||
} m_vtrace;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
// TODO: GSreset can come from the main thread too => crash
|
||||
@@ -45,6 +66,8 @@ protected:
|
||||
|
||||
m_reset = true;
|
||||
|
||||
m_vtrace.Reset();
|
||||
|
||||
__super::Reset();
|
||||
}
|
||||
|
||||
@@ -116,35 +139,44 @@ protected:
|
||||
|
||||
void VertexKick(bool skip)
|
||||
{
|
||||
Vertex& v = m_vl.AddTail();
|
||||
GSVertexSW v;
|
||||
|
||||
int x = (int)m_v.XYZ.X - (int)m_context->XYOFFSET.OFX;
|
||||
int y = (int)m_v.XYZ.Y - (int)m_context->XYOFFSET.OFY;
|
||||
GSVector4i p((int)m_v.XYZ.X, (int)m_v.XYZ.Y, 0, (int)m_v.FOG.F);
|
||||
GSVector4i o((int)m_context->XYOFFSET.OFX, (int)m_context->XYOFFSET.OFY);
|
||||
|
||||
v.p = GSVector4(x, y, 0, (int)m_v.FOG.F) * g_pos_scale;
|
||||
v.p = GSVector4(p - o) * g_pos_scale;
|
||||
v.p.z = (float)min(m_v.XYZ.Z, 0xffffff00); // max value which can survive the DWORD=>float=>DWORD conversion
|
||||
|
||||
v.c = (DWORD)m_v.RGBAQ.ai32[0];
|
||||
v.c *= 128.0f;
|
||||
v.c = GSVector4((DWORD)m_v.RGBAQ.ai32[0]) * 128.0f;
|
||||
|
||||
if(PRIM->TME)
|
||||
{
|
||||
if(PRIM->FST)
|
||||
{
|
||||
v.t.x = (float)(int)m_v.UV.U;
|
||||
v.t.y = (float)(int)m_v.UV.V;
|
||||
v.t *= 0x10000 >> 4;
|
||||
v.t = GSVector4(GSVector4i((int)m_v.UV.U, (int)m_v.UV.V) << (16 - 4));
|
||||
v.t.z = 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
v.t.x = m_v.ST.S;
|
||||
v.t.y = m_v.ST.T;
|
||||
v.t = GSVector4(m_v.ST.S, m_v.ST.T, 0.0f, 0.0f);
|
||||
v.t *= GSVector4((float)(0x10000 << m_context->TEX0.TW), (float)(0x10000 << m_context->TEX0.TH));
|
||||
v.t.z = m_v.RGBAQ.Q;
|
||||
}
|
||||
}
|
||||
|
||||
if(m_vtrace.first)
|
||||
{
|
||||
m_vtrace.v.t = v.t;
|
||||
m_vtrace.v.c = v.c;
|
||||
m_vtrace.first = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_vtrace.eq.value &= (m_vtrace.v.t == v.t).mask() | ((m_vtrace.v.c == v.c).mask() << 4); // v.p not needed
|
||||
}
|
||||
|
||||
m_vl.AddTail() = v;
|
||||
|
||||
__super::VertexKick(skip);
|
||||
}
|
||||
|
||||
@@ -158,7 +190,7 @@ protected:
|
||||
return (v0 | v1).mask() & 3;
|
||||
}
|
||||
|
||||
void DrawingKickPoint(Vertex* v, int& count)
|
||||
void DrawingKickPoint(GSVertexSW* v, int& count)
|
||||
{
|
||||
GSVector4 p0 = v[0].p;
|
||||
GSVector4 p1 = v[0].p;
|
||||
@@ -170,7 +202,7 @@ protected:
|
||||
}
|
||||
}
|
||||
|
||||
void DrawingKickLine(Vertex* v, int& count)
|
||||
void DrawingKickLine(GSVertexSW* v, int& count)
|
||||
{
|
||||
GSVector4 p0 = v[0].p.maxv(v[1].p);
|
||||
GSVector4 p1 = v[0].p.minv(v[1].p);
|
||||
@@ -187,7 +219,7 @@ protected:
|
||||
}
|
||||
}
|
||||
|
||||
void DrawingKickTriangle(Vertex* v, int& count)
|
||||
void DrawingKickTriangle(GSVertexSW* v, int& count)
|
||||
{
|
||||
GSVector4 p0 = v[0].p.maxv(v[1].p).maxv(v[2].p);
|
||||
GSVector4 p1 = v[0].p.minv(v[1].p).minv(v[2].p);
|
||||
@@ -205,7 +237,7 @@ protected:
|
||||
}
|
||||
}
|
||||
|
||||
void DrawingKickSprite(Vertex* v, int& count)
|
||||
void DrawingKickSprite(GSVertexSW* v, int& count)
|
||||
{
|
||||
GSVector4 p0 = v[0].p.maxv(v[1].p);
|
||||
GSVector4 p1 = v[0].p.minv(v[1].p);
|
||||
@@ -230,83 +262,286 @@ protected:
|
||||
|
||||
void Draw()
|
||||
{
|
||||
// TODO: lot to optimize here
|
||||
const GSDrawingEnvironment& env = m_env;
|
||||
const GSDrawingContext* context = m_context;
|
||||
const GS_PRIM prim = (GS_PRIM)PRIM->PRIM;
|
||||
const GS_PRIM_CLASS primclass = GSUtil::GetPrimClass(prim);
|
||||
|
||||
GSDrawingContext* context = m_context;
|
||||
//
|
||||
|
||||
// sanity check
|
||||
GSScanlineParam p;
|
||||
|
||||
p.vm = m_mem.m_vm32;
|
||||
|
||||
p.sel.dw = 0;
|
||||
|
||||
p.sel.fpsm = 3;
|
||||
p.sel.zpsm = 3;
|
||||
p.sel.atst = ATST_ALWAYS;
|
||||
p.sel.tfx = TFX_NONE;
|
||||
p.sel.abe = 255;
|
||||
|
||||
//
|
||||
|
||||
p.fm = context->FRAME.FBMSK;
|
||||
p.zm = context->ZBUF.ZMSK || context->TEST.ZTE == 0 ? 0xffffffff : 0;
|
||||
|
||||
//
|
||||
|
||||
if(context->TEST.ZTE && context->TEST.ZTST == ZTST_NEVER)
|
||||
{
|
||||
p.fm = 0xffffffff;
|
||||
p.zm = 0xffffffff;
|
||||
}
|
||||
|
||||
if(context->TEST.ATE)
|
||||
{
|
||||
bool pass = context->TEST.ATST != ATST_NEVER;
|
||||
|
||||
if((!PRIM->TME || !context->TEX0.TCC && context->TEX0.TFX != TFX_DECAL) && m_vtrace.eq.a)
|
||||
{
|
||||
// surprisingly large number of games leave alpha test on when alpha is constant
|
||||
|
||||
DWORD a = (DWORD)((int)m_vtrace.v.c.a >> 7);
|
||||
DWORD aref = context->TEST.AREF;
|
||||
|
||||
switch(context->TEST.ATST)
|
||||
{
|
||||
case ATST_NEVER: pass = false; break;
|
||||
case ATST_ALWAYS: pass = true; break;
|
||||
case ATST_LESS: pass = a < aref; break;
|
||||
case ATST_LEQUAL: pass = a <= aref; break;
|
||||
case ATST_EQUAL: pass = a == aref; break;
|
||||
case ATST_GEQUAL: pass = a >= aref; break;
|
||||
case ATST_GREATER: pass = a > aref; break;
|
||||
case ATST_NOTEQUAL: pass = a != aref; break;
|
||||
default: __assume(0);
|
||||
}
|
||||
}
|
||||
|
||||
if(!pass)
|
||||
{
|
||||
switch(context->TEST.AFAIL)
|
||||
{
|
||||
case AFAIL_KEEP: p.fm = p.zm = 0xffffffff; break;
|
||||
case AFAIL_FB_ONLY: p.zm = 0xffffffff; break;
|
||||
case AFAIL_ZB_ONLY: p.fm = 0xffffffff; break;
|
||||
case AFAIL_RGB_ONLY: p.fm |= 0xff000000; p.zm = 0xffffffff; break;
|
||||
default: __assume(0);
|
||||
}
|
||||
|
||||
// "don't care" values
|
||||
|
||||
p.sel.atst = ATST_ALWAYS;
|
||||
p.sel.afail = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
p.sel.atst = context->TEST.ATST;
|
||||
p.sel.afail = context->TEST.AFAIL;
|
||||
}
|
||||
}
|
||||
|
||||
bool fwrite = p.fm != 0xffffffff;
|
||||
bool ftest = p.sel.atst != ATST_ALWAYS || context->TEST.DATE && context->FRAME.PSM != PSM_PSMCT24;
|
||||
|
||||
if(fwrite || ftest)
|
||||
{
|
||||
p.sel.fpsm = GSUtil::EncodePSM(context->FRAME.PSM);
|
||||
|
||||
if((primclass == GS_LINE_CLASS || primclass == GS_TRIANGLE_CLASS) && m_vtrace.eq.rgba != 15)
|
||||
{
|
||||
p.sel.iip = PRIM->IIP;
|
||||
}
|
||||
|
||||
if(PRIM->TME)
|
||||
{
|
||||
p.sel.tfx = context->TEX0.TFX;
|
||||
p.sel.tcc = context->TEX0.TCC;
|
||||
p.sel.fst = PRIM->FST;
|
||||
p.sel.ltf = context->TEX1.IsLinear();
|
||||
p.sel.tlu = GSLocalMemory::m_psm[context->TEX0.PSM].pal > 0;
|
||||
|
||||
if(p.sel.iip == 0 && p.sel.tfx == TFX_MODULATE && p.sel.tcc)
|
||||
{
|
||||
if(m_vtrace.eq.rgba == 15 && (m_vtrace.v.c == GSVector4(128.0f * 128.0f)).alltrue())
|
||||
{
|
||||
// modulate does not do anything when vertex color is 0x80
|
||||
|
||||
p.sel.tfx = TFX_DECAL;
|
||||
}
|
||||
}
|
||||
|
||||
if(p.sel.fst == 0)
|
||||
{
|
||||
// skip per pixel division if q is constant
|
||||
|
||||
GSVertexSW* v = m_vertices;
|
||||
|
||||
if(m_vtrace.eq.q)
|
||||
{
|
||||
p.sel.fst = 1;
|
||||
|
||||
GSVector4 w = v[0].t.zzzz().rcpnr();
|
||||
|
||||
for(int i = 0, j = m_count; i < j; i++)
|
||||
{
|
||||
v[i].t *= w;
|
||||
}
|
||||
}
|
||||
else if(prim == GS_SPRITE)
|
||||
{
|
||||
p.sel.fst = 1;
|
||||
|
||||
for(int i = 0, j = m_count; i < j; i += 2)
|
||||
{
|
||||
GSVector4 w = v[i + 1].t.zzzz().rcpnr();
|
||||
|
||||
v[i + 0].t *= w;
|
||||
v[i + 1].t *= w;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(p.sel.fst && p.sel.ltf)
|
||||
{
|
||||
// if q is constant we can do the half pel shift for bilinear sampling on the vertices
|
||||
|
||||
GSVector4 half((float)0x8000, (float)0x8000, 0.0f, 0.0f);
|
||||
|
||||
for(int i = 0; i < m_count; i++)
|
||||
{
|
||||
m_vertices[i].t -= half;
|
||||
}
|
||||
}
|
||||
|
||||
int w = 1 << context->TEX0.TW;
|
||||
int h = 1 << context->TEX0.TH;
|
||||
|
||||
int wms = context->CLAMP.WMS;
|
||||
int wmt = context->CLAMP.WMT;
|
||||
|
||||
int minu = (int)context->CLAMP.MINU;
|
||||
int minv = (int)context->CLAMP.MINV;
|
||||
int maxu = (int)context->CLAMP.MAXU;
|
||||
int maxv = (int)context->CLAMP.MAXV;
|
||||
|
||||
CRect r = CRect(0, 0, w, h);
|
||||
|
||||
switch(wms)
|
||||
{
|
||||
case CLAMP_REPEAT: // TODO
|
||||
break;
|
||||
case CLAMP_CLAMP: // TODO
|
||||
break;
|
||||
case CLAMP_REGION_REPEAT:
|
||||
if(r.left < minu) r.left = minu;
|
||||
if(r.right > maxu + 1) r.right = maxu + 1;
|
||||
break;
|
||||
case CLAMP_REGION_CLAMP:
|
||||
r.left = maxu;
|
||||
r.right = r.left + (minu + 1);
|
||||
break;
|
||||
default:
|
||||
__assume(0);
|
||||
}
|
||||
|
||||
switch(wmt)
|
||||
{
|
||||
case CLAMP_REPEAT: // TODO
|
||||
break;
|
||||
case CLAMP_CLAMP: // TODO
|
||||
break;
|
||||
case CLAMP_REGION_REPEAT:
|
||||
if(r.top < minv) r.top = minv;
|
||||
if(r.bottom > maxv + 1) r.bottom = maxv + 1;
|
||||
break;
|
||||
case CLAMP_REGION_CLAMP:
|
||||
r.top = maxv;
|
||||
r.bottom = r.top + (minv + 1);
|
||||
break;
|
||||
default:
|
||||
__assume(0);
|
||||
}
|
||||
|
||||
r &= CRect(0, 0, w, h);
|
||||
|
||||
const GSTextureCacheSW::GSTexture* t = m_tc->Lookup(context->TEX0, env.TEXA, &r);
|
||||
|
||||
if(!t) {ASSERT(0); return;}
|
||||
|
||||
m_mem.m_clut.Read32(context->TEX0, env.TEXA);
|
||||
|
||||
p.tex = t->m_buff;
|
||||
p.clut = m_mem.m_clut;
|
||||
p.tw = t->m_tw;
|
||||
}
|
||||
|
||||
p.sel.fge = PRIM->FGE;
|
||||
|
||||
if(context->FRAME.PSM != PSM_PSMCT24)
|
||||
{
|
||||
p.sel.date = context->TEST.DATE;
|
||||
}
|
||||
|
||||
if(PRIM->ABE)
|
||||
{
|
||||
if(!context->ALPHA.IsOpaque())
|
||||
{
|
||||
p.sel.abe = context->ALPHA.ai32[0];
|
||||
p.sel.pabe = env.PABE.PABE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// printf("opaque\n");
|
||||
}
|
||||
|
||||
if(PRIM->AA1)
|
||||
{
|
||||
// TODO: automatic alpha blending (ABE=1, A=0 B=1 C=0 D=1)
|
||||
}
|
||||
}
|
||||
|
||||
if(p.sel.date
|
||||
|| p.sel.abe != 255
|
||||
|| p.sel.atst != ATST_ALWAYS && p.sel.afail == AFAIL_RGB_ONLY
|
||||
|| p.fm != 0 && p.fm != 0xffffffff)
|
||||
{
|
||||
p.sel.rfb = 1;
|
||||
}
|
||||
}
|
||||
|
||||
bool zwrite = p.zm != 0xffffffff;
|
||||
bool ztest = context->TEST.ZTE && context->TEST.ZTST > 1;
|
||||
|
||||
if(zwrite || ztest)
|
||||
{
|
||||
p.sel.zpsm = GSUtil::EncodePSM(context->ZBUF.PSM);
|
||||
p.sel.ztst = ztest ? context->TEST.ZTST : 1;
|
||||
}
|
||||
|
||||
m_vtrace.Reset();
|
||||
|
||||
if((p.fm & p.zm) == 0xffffffff)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
const GSTextureCacheSW::GSTexture* texture = NULL;
|
||||
|
||||
if(PRIM->TME)
|
||||
{
|
||||
m_mem.m_clut.Read32(context->TEX0, m_env.TEXA);
|
||||
|
||||
int w = 1 << context->TEX0.TW;
|
||||
int h = 1 << context->TEX0.TH;
|
||||
|
||||
int wms = context->CLAMP.WMS;
|
||||
int wmt = context->CLAMP.WMT;
|
||||
|
||||
int minu = (int)context->CLAMP.MINU;
|
||||
int minv = (int)context->CLAMP.MINV;
|
||||
int maxu = (int)context->CLAMP.MAXU;
|
||||
int maxv = (int)context->CLAMP.MAXV;
|
||||
|
||||
CRect r = CRect(0, 0, w, h);
|
||||
|
||||
switch(wms)
|
||||
{
|
||||
case 0: // TODO
|
||||
break;
|
||||
case 1: // TODO
|
||||
break;
|
||||
case 2:
|
||||
if(r.left < minu) r.left = minu;
|
||||
if(r.right > maxu + 1) r.right = maxu + 1;
|
||||
break;
|
||||
case 3:
|
||||
r.left = maxu;
|
||||
r.right = r.left + (minu + 1);
|
||||
break;
|
||||
default:
|
||||
__assume(0);
|
||||
}
|
||||
|
||||
switch(wmt)
|
||||
{
|
||||
case 0: // TODO
|
||||
break;
|
||||
case 1: // TODO
|
||||
break;
|
||||
case 2:
|
||||
if(r.top < minv) r.top = minv;
|
||||
if(r.bottom > maxv + 1) r.bottom = maxv + 1;
|
||||
break;
|
||||
case 3:
|
||||
r.top = maxv;
|
||||
r.bottom = r.top + (minv + 1);
|
||||
break;
|
||||
default:
|
||||
__assume(0);
|
||||
}
|
||||
|
||||
r &= CRect(0, 0, w, h);
|
||||
|
||||
texture = m_tc->Lookup(context->TEX0, m_env.TEXA, &r);
|
||||
|
||||
if(!texture) {ASSERT(0); return;}
|
||||
}
|
||||
|
||||
if(s_dump)
|
||||
{
|
||||
/*
|
||||
TRACE(_T("\n"));
|
||||
|
||||
TRACE(_T("PRIM = %d, ZMSK = %d, ZTE = %d, ZTST = %d, ATE = %d, ATST = %d, AFAIL = %d, AREF = %02x\n"),
|
||||
PRIM->PRIM, context->ZBUF.ZMSK,
|
||||
context->TEST.ZTE, context->TEST.ZTST,
|
||||
context->TEST.ATE, context->TEST.ATST, context->TEST.AFAIL, context->TEST.AREF);
|
||||
|
||||
for(int i = 0; i < m_count; i++)
|
||||
{
|
||||
TRACE(_T("[%d] %3.0f %3.0f %3.0f %3.0f\n"), i, m_vertices[i].p.x, m_vertices[i].p.y, m_vertices[i].p.z, m_vertices[i].c.w / 128);
|
||||
}
|
||||
*/
|
||||
CString str;
|
||||
str.Format(_T("c:\\temp1\\_%05d_f%I64d_tex_%05x_%d.bmp"), s_n++, m_perfmon.GetFrame(), (int)m_context->TEX0.TBP0, (int)m_context->TEX0.PSM);
|
||||
if(PRIM->TME) if(s_save) {m_mem.SaveBMP(str, m_context->TEX0.TBP0, m_context->TEX0.TBW, m_context->TEX0.PSM, 1 << m_context->TEX0.TW, 1 << m_context->TEX0.TH);}
|
||||
@@ -317,16 +552,43 @@ protected:
|
||||
}
|
||||
|
||||
//
|
||||
/*
|
||||
static FILE* s_fp = NULL;
|
||||
static UINT64 s_frame = 0;
|
||||
static __int64 s_total = 0;
|
||||
if(!s_fp) s_fp = fopen("c:\\log.txt", "w");
|
||||
UINT64 frame = m_perfmon.GetFrame();
|
||||
if(s_frame != frame)
|
||||
{
|
||||
fprintf(s_fp, "=> %I64d\n", s_total);
|
||||
s_frame = frame;
|
||||
s_total = 0;
|
||||
}
|
||||
__int64 start = __rdtsc();
|
||||
*/
|
||||
GSRasterizerData data;
|
||||
|
||||
int prims = m_rl.Draw(m_vertices, m_count, texture);
|
||||
data.scissor = GetScissor();
|
||||
data.primclass = primclass;
|
||||
data.vertices = m_vertices;
|
||||
data.count = m_count;
|
||||
data.param = &p;
|
||||
|
||||
int prims = m_rl.Draw(&data);
|
||||
|
||||
m_perfmon.Put(GSPerfMon::Prim, prims);
|
||||
m_perfmon.Put(GSPerfMon::Draw, 1);
|
||||
|
||||
int pixels = m_rl.GetPixels();
|
||||
|
||||
m_perfmon.Put(GSPerfMon::Fillrate, pixels);
|
||||
m_perfmon.Put(GSPerfMon::Fillrate, pixels);
|
||||
|
||||
/*
|
||||
__int64 diff = __rdtsc() - start;
|
||||
s_total += diff;
|
||||
//if(pixels > 50000)
|
||||
fprintf(s_fp, "[%I64d, %d, %d, %d] %08x, diff = %I64d /prim = %I64d /pixel = %I64d \n", frame, PRIM->PRIM, prims, pixels, p.sel, diff, diff / prims, pixels > 0 ? diff / pixels : 0);
|
||||
*/
|
||||
// TODO
|
||||
|
||||
{
|
||||
@@ -341,7 +603,7 @@ protected:
|
||||
br = br.maxv(p);
|
||||
}
|
||||
|
||||
GSVector4i scissor = GetScissor();
|
||||
GSVector4i scissor = data.scissor;
|
||||
|
||||
CRect r;
|
||||
|
||||
@@ -351,14 +613,18 @@ protected:
|
||||
r.bottom = max(scissor.y, min(scissor.w, (int)br.y));
|
||||
|
||||
GIFRegBITBLTBUF BITBLTBUF;
|
||||
|
||||
BITBLTBUF.DBP = context->FRAME.Block();
|
||||
|
||||
BITBLTBUF.DBW = context->FRAME.FBW;
|
||||
BITBLTBUF.DPSM = context->FRAME.PSM;
|
||||
|
||||
m_tc->InvalidateVideoMem(BITBLTBUF, r);
|
||||
if(p.fm != 0xffffffff)
|
||||
{
|
||||
BITBLTBUF.DBP = context->FRAME.Block();
|
||||
BITBLTBUF.DPSM = context->FRAME.PSM;
|
||||
|
||||
if(context->DepthWrite())
|
||||
m_tc->InvalidateVideoMem(BITBLTBUF, r);
|
||||
}
|
||||
|
||||
if(p.zm != 0xffffffff)
|
||||
{
|
||||
BITBLTBUF.DBP = context->ZBUF.Block();
|
||||
BITBLTBUF.DPSM = context->ZBUF.PSM;
|
||||
@@ -370,68 +636,13 @@ protected:
|
||||
if(s_dump)
|
||||
{
|
||||
CString str;
|
||||
str.Format(_T("c:\\temp1\\_%05d_f%I64d_rt1_%05x_%d.bmp"), s_n++, m_perfmon.GetFrame(), m_context->FRAME.Block(), m_context->FRAME.PSM);
|
||||
str.Format(_T("c:\\temp1\\_%05d_f%I64d_rt1_%05x_%d_%d.bmp"), s_n++, m_perfmon.GetFrame(), m_context->FRAME.Block(), m_context->FRAME.PSM);
|
||||
if(s_save) {m_mem.SaveBMP(str, m_context->FRAME.Block(), m_context->FRAME.FBW, m_context->FRAME.PSM, GetFrameSize(1).cx, 512);}//GetFrameSize(1).cy);
|
||||
str.Format(_T("c:\\temp1\\_%05d_f%I64d_rz1_%05x_%d.bmp"), s_n-1, m_perfmon.GetFrame(), m_context->ZBUF.Block(), m_context->ZBUF.PSM);
|
||||
if(s_savez) {m_mem.SaveBMP(str, m_context->ZBUF.Block(), m_context->FRAME.FBW, m_context->ZBUF.PSM, GetFrameSize(1).cx, 512);}
|
||||
}
|
||||
}
|
||||
|
||||
int DrawAsync(GSRasterizer* r)
|
||||
{
|
||||
GSDrawingContext* context = m_context;
|
||||
|
||||
//
|
||||
|
||||
bool solid = true;
|
||||
|
||||
if(PRIM->IIP || PRIM->TME || PRIM->ABE || PRIM->FGE
|
||||
|| context->TEST.ZTE && context->TEST.ZTST != ZTST_ALWAYS
|
||||
|| context->TEST.ATE && context->TEST.ATST != ATST_ALWAYS
|
||||
|| context->TEST.DATE
|
||||
|| m_env.DTHE.DTHE
|
||||
|| context->FRAME.FBMSK)
|
||||
{
|
||||
solid = false;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
GSVector4i scissor = GetScissor();
|
||||
|
||||
int prims = 0;
|
||||
|
||||
switch(PRIM->PRIM)
|
||||
{
|
||||
case GS_POINTLIST:
|
||||
prims = m_count;
|
||||
for(int i = 0, j = m_count; i < j; i++) r->DrawPoint(&m_vertices[i], scissor);
|
||||
break;
|
||||
case GS_LINELIST:
|
||||
case GS_LINESTRIP:
|
||||
ASSERT(!(m_count & 1));
|
||||
prims = m_count / 2;
|
||||
for(int i = 0, j = m_count; i < j; i += 2) r->DrawLine(&m_vertices[i], scissor);
|
||||
break;
|
||||
case GS_TRIANGLELIST:
|
||||
case GS_TRIANGLESTRIP:
|
||||
case GS_TRIANGLEFAN:
|
||||
ASSERT(!(m_count % 3));
|
||||
prims = m_count / 3;
|
||||
for(int i = 0, j = m_count; i < j; i += 3) r->DrawTriangle(&m_vertices[i], scissor);
|
||||
break;
|
||||
case GS_SPRITE:
|
||||
ASSERT(!(m_count & 1));
|
||||
prims = m_count / 2;
|
||||
for(int i = 0, j = m_count; i < j; i += 2) r->DrawSprite(&m_vertices[i], scissor, solid);
|
||||
break;
|
||||
default:
|
||||
__assume(0);
|
||||
}
|
||||
|
||||
return prims;
|
||||
}
|
||||
|
||||
void InvalidateVideoMem(const GIFRegBITBLTBUF& BITBLTBUF, CRect r)
|
||||
{
|
||||
m_tc->InvalidateVideoMem(BITBLTBUF, r);
|
||||
@@ -441,7 +652,7 @@ public:
|
||||
GSRendererSW(BYTE* base, bool mt, void (*irq)(), int nloophack, const GSRendererSettings& rs, int threads)
|
||||
: GSRendererT(base, mt, irq, nloophack, rs)
|
||||
{
|
||||
m_rl.Create<GSDrawScanline>(this, this, threads);
|
||||
m_rl.Create<GSDrawScanline>(this, threads);
|
||||
|
||||
m_tc = new GSTextureCacheSW(this);
|
||||
|
||||
|
||||
@@ -111,7 +111,60 @@ void GSTexture10::Unmap()
|
||||
|
||||
bool GSTexture10::Save(CString fn, bool dds)
|
||||
{
|
||||
return SUCCEEDED(D3DX10SaveTextureToFile(m_texture, dds ? D3DX10_IFF_DDS : D3DX10_IFF_BMP, fn));
|
||||
CComPtr<ID3D10Resource> res;
|
||||
|
||||
if(m_desc.BindFlags & D3D10_BIND_DEPTH_STENCIL)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
D3D10_TEXTURE2D_DESC desc;
|
||||
|
||||
memset(&desc, 0, sizeof(desc));
|
||||
|
||||
m_texture->GetDesc(&desc);
|
||||
|
||||
desc.Usage = D3D10_USAGE_STAGING;
|
||||
desc.BindFlags = 0;
|
||||
desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ;
|
||||
|
||||
CComPtr<ID3D10Texture2D> src, dst;
|
||||
|
||||
hr = m_dev->CreateTexture2D(&desc, NULL, &src);
|
||||
|
||||
m_dev->CopyResource(src, m_texture);
|
||||
|
||||
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
|
||||
|
||||
hr = m_dev->CreateTexture2D(&desc, NULL, &dst);
|
||||
|
||||
D3D10_MAPPED_TEXTURE2D sm, dm;
|
||||
|
||||
hr = src->Map(0, D3D10_MAP_READ, 0, &sm);
|
||||
hr = dst->Map(0, D3D10_MAP_WRITE, 0, &dm);
|
||||
|
||||
BYTE* s = (BYTE*)sm.pData;
|
||||
BYTE* d = (BYTE*)dm.pData;
|
||||
|
||||
for(UINT y = 0; y < desc.Height; y++, s += sm.RowPitch, d += dm.RowPitch)
|
||||
{
|
||||
for(UINT x = 0; x < desc.Width; x++)
|
||||
{
|
||||
((UINT*)d)[x] = (UINT)(((float*)s)[x*2] * UINT_MAX);
|
||||
}
|
||||
}
|
||||
|
||||
src->Unmap(0);
|
||||
dst->Unmap(0);
|
||||
|
||||
res = dst;
|
||||
}
|
||||
else
|
||||
{
|
||||
res = m_texture;
|
||||
}
|
||||
|
||||
return SUCCEEDED(D3DX10SaveTextureToFile(res, dds ? D3DX10_IFF_DDS : D3DX10_IFF_BMP, fn));
|
||||
}
|
||||
|
||||
ID3D10Texture2D* GSTexture10::operator->()
|
||||
|
||||
@@ -140,12 +140,55 @@ void GSTexture9::Unmap()
|
||||
|
||||
bool GSTexture9::Save(CString fn, bool dds)
|
||||
{
|
||||
if(CComPtr<IDirect3DSurface9> surface = *this)
|
||||
CComPtr<IDirect3DResource9> res;
|
||||
|
||||
if(m_desc.Usage & D3DUSAGE_DEPTHSTENCIL)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
D3DSURFACE_DESC desc;
|
||||
|
||||
m_surface->GetDesc(&desc);
|
||||
|
||||
if(desc.Format != D3DFMT_D32F_LOCKABLE)
|
||||
return false;
|
||||
|
||||
CComPtr<IDirect3DSurface9> surface;
|
||||
|
||||
hr = m_dev->CreateOffscreenPlainSurface(desc.Width, desc.Height, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surface, NULL);
|
||||
|
||||
D3DLOCKED_RECT slr, dlr;
|
||||
|
||||
hr = m_surface->LockRect(&slr, NULL, 0);
|
||||
hr = surface->LockRect(&dlr, NULL, 0);
|
||||
|
||||
BYTE* s = (BYTE*)slr.pBits;
|
||||
BYTE* d = (BYTE*)dlr.pBits;
|
||||
|
||||
for(UINT y = 0; y < desc.Height; y++, s += slr.Pitch, d += dlr.Pitch)
|
||||
{
|
||||
for(UINT x = 0; x < desc.Width; x++)
|
||||
{
|
||||
((float*)d)[x] = ((float*)s)[x];
|
||||
}
|
||||
}
|
||||
|
||||
m_surface->UnlockRect();
|
||||
surface->UnlockRect();
|
||||
|
||||
res = surface;
|
||||
}
|
||||
else
|
||||
{
|
||||
res = m_surface;
|
||||
}
|
||||
|
||||
if(CComQIPtr<IDirect3DSurface9> surface = res)
|
||||
{
|
||||
return SUCCEEDED(D3DXSaveSurfaceToFile(fn, dds ? D3DXIFF_DDS : D3DXIFF_BMP, surface, NULL, NULL));
|
||||
}
|
||||
|
||||
if(CComPtr<IDirect3DTexture9> texture = *this)
|
||||
if(CComQIPtr<IDirect3DTexture9> texture = res)
|
||||
{
|
||||
return SUCCEEDED(D3DXSaveTextureToFile(fn, dds ? D3DXIFF_DDS : D3DXIFF_BMP, texture, NULL));
|
||||
}
|
||||
|
||||
@@ -33,14 +33,14 @@ static struct GSUtilMaps
|
||||
|
||||
struct GSUtilMaps()
|
||||
{
|
||||
PrimClassField[GS_POINTLIST] = 0;
|
||||
PrimClassField[GS_LINELIST] = 1;
|
||||
PrimClassField[GS_LINESTRIP] = 1;
|
||||
PrimClassField[GS_TRIANGLELIST] = 2;
|
||||
PrimClassField[GS_TRIANGLESTRIP] = 2;
|
||||
PrimClassField[GS_TRIANGLEFAN] = 2;
|
||||
PrimClassField[GS_SPRITE] = 3;
|
||||
PrimClassField[GS_INVALID] = (BYTE)-1;
|
||||
PrimClassField[GS_POINTLIST] = GS_POINT_CLASS;
|
||||
PrimClassField[GS_LINELIST] = GS_LINE_CLASS;
|
||||
PrimClassField[GS_LINESTRIP] = GS_LINE_CLASS;
|
||||
PrimClassField[GS_TRIANGLELIST] = GS_TRIANGLE_CLASS;
|
||||
PrimClassField[GS_TRIANGLESTRIP] = GS_TRIANGLE_CLASS;
|
||||
PrimClassField[GS_TRIANGLEFAN] = GS_TRIANGLE_CLASS;
|
||||
PrimClassField[GS_SPRITE] = GS_SPRITE_CLASS;
|
||||
PrimClassField[GS_INVALID] = GS_INVALID_CLASS;
|
||||
|
||||
PrimVertexCount[GS_POINTLIST] = 1;
|
||||
PrimVertexCount[GS_LINELIST] = 2;
|
||||
@@ -82,9 +82,9 @@ static struct GSUtilMaps
|
||||
|
||||
} s_maps;
|
||||
|
||||
DWORD GSUtil::GetPrimClass(DWORD prim)
|
||||
GS_PRIM_CLASS GSUtil::GetPrimClass(DWORD prim)
|
||||
{
|
||||
return s_maps.PrimClassField[prim];
|
||||
return (GS_PRIM_CLASS)s_maps.PrimClassField[prim];
|
||||
}
|
||||
|
||||
DWORD GSUtil::GetPrimVertexCount(DWORD prim)
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
class GSUtil
|
||||
{
|
||||
public:
|
||||
static DWORD GetPrimClass(DWORD prim);
|
||||
static GS_PRIM_CLASS GetPrimClass(DWORD prim);
|
||||
static DWORD GetPrimVertexCount(DWORD prim);
|
||||
|
||||
static bool HasSharedBits(DWORD spsm, DWORD dpsm);
|
||||
|
||||
@@ -85,6 +85,11 @@ public:
|
||||
);
|
||||
}
|
||||
|
||||
GSVector4i(int x, int y)
|
||||
{
|
||||
m = _mm_unpacklo_epi32(_mm_cvtsi32_si128(x), _mm_cvtsi32_si128(y));
|
||||
}
|
||||
|
||||
GSVector4i(char b0, char b1, char b2, char b3, char b4, char b5, char b6, char b7, char b8, char b9, char b10, char b11, char b12, char b13, char b14, char b15)
|
||||
{
|
||||
m = _mm_set_epi8(b15, b14, b13, b12, b11, b10, b9, b8, b7, b6, b5, b4, b3, b2, b1, b0);
|
||||
@@ -1865,6 +1870,11 @@ public:
|
||||
m = _mm_cvtepi32_ps(_mm_set_epi32(w, z, y, x));
|
||||
}
|
||||
|
||||
GSVector4(int x, int y)
|
||||
{
|
||||
m = _mm_cvtepi32_ps(_mm_unpacklo_epi32(_mm_cvtsi32_si128(x), _mm_cvtsi32_si128(y)));
|
||||
}
|
||||
|
||||
GSVector4(const GSVector4& v)
|
||||
{
|
||||
m = v.m;
|
||||
@@ -2125,6 +2135,11 @@ public:
|
||||
return GSVector4(_mm_setzero_ps());
|
||||
}
|
||||
|
||||
static GSVector4 invzero()
|
||||
{
|
||||
return zero() == zero();
|
||||
}
|
||||
|
||||
static GSVector4 ps0123()
|
||||
{
|
||||
return GSVector4(m_ps0123);
|
||||
|
||||
@@ -81,6 +81,7 @@ struct GSVertexPT2
|
||||
|
||||
struct GSVertexNull
|
||||
{
|
||||
GSVector4 p;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
Reference in New Issue
Block a user