mirror of
https://github.com/PCSX2/gsdx-sourceforge.git
synced 2026-02-04 03:11:19 +01:00
This commit is contained in:
@@ -201,38 +201,6 @@ protected:
|
||||
}
|
||||
}
|
||||
|
||||
int DrawAsync(GSRasterizer* r)
|
||||
{
|
||||
GSVector4i scissor = GetScissor();
|
||||
|
||||
//
|
||||
|
||||
int prims = 0;
|
||||
|
||||
switch(m_env.PRIM.TYPE)
|
||||
{
|
||||
case GPU_POLYGON:
|
||||
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 GPU_LINE:
|
||||
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 GPU_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, false);
|
||||
break;
|
||||
default:
|
||||
__assume(0);
|
||||
}
|
||||
|
||||
return prims;
|
||||
}
|
||||
|
||||
public:
|
||||
GPURendererSW(const GPURendererSettings& rs, int threads)
|
||||
: GPURenderer(rs)
|
||||
|
||||
@@ -894,11 +894,11 @@ REG64_(GIFReg, UV)
|
||||
UINT32 _PAD3:32;
|
||||
REG_END
|
||||
|
||||
// GSState::GIFRegHandlerXYOFFSET will make sure that the _PAD1/2 bits are set to zero
|
||||
|
||||
REG64_(GIFReg, XYOFFSET)
|
||||
UINT32 OFX:16;
|
||||
UINT32 _PAD1:16;
|
||||
UINT32 OFY:16;
|
||||
UINT32 _PAD2:16;
|
||||
UINT32 OFX; // :16; UINT32 _PAD1:16;
|
||||
UINT32 OFY; // :16; UINT32 _PAD2:16;
|
||||
REG_END
|
||||
|
||||
REG64_(GIFReg, XYZ)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -48,6 +48,7 @@ union GSScanlineSelector
|
||||
DWORD abed:2; // 27
|
||||
DWORD pabe:1; // 29
|
||||
DWORD rfb:1; // 30
|
||||
DWORD sprite:1; // 31
|
||||
};
|
||||
|
||||
struct
|
||||
@@ -59,7 +60,19 @@ union GSScanlineSelector
|
||||
|
||||
DWORD dw;
|
||||
|
||||
operator DWORD() {return dw & 0x7fffffff;}
|
||||
operator DWORD() {return dw;}
|
||||
|
||||
bool IsSolidRect()
|
||||
{
|
||||
return sprite
|
||||
&& iip == 0
|
||||
&& tfx == TFX_NONE
|
||||
&& abe == 255
|
||||
&& ztst <= 1
|
||||
&& atst <= 1
|
||||
&& date == 0
|
||||
&& fge == 0;
|
||||
}
|
||||
};
|
||||
|
||||
__declspec(align(16)) struct GSScanlineEnvironment
|
||||
@@ -90,6 +103,7 @@ __declspec(align(16)) struct GSScanlineEnvironment
|
||||
struct {GSVector4 z, s, t, q; GSVector4i rb, ga, f, si, ti, _pad[3];} d[4];
|
||||
struct {GSVector4 z, stq; GSVector4i c, f, st;} d4;
|
||||
struct {GSVector4i rb, ga;} c;
|
||||
struct {GSVector4i z, f;} p;
|
||||
};
|
||||
|
||||
__declspec(align(16)) struct GSScanlineParam
|
||||
@@ -125,6 +139,8 @@ class GSDrawScanline : public GSAlignedClass<16>, public IDrawScanline
|
||||
GSDrawScanlineMap();
|
||||
|
||||
DrawScanlinePtr GetDefaultFunction(DWORD dw);
|
||||
|
||||
void PrintStats();
|
||||
};
|
||||
|
||||
GSDrawScanlineMap m_ds;
|
||||
|
||||
@@ -42,6 +42,7 @@ struct GSRasterizerStats
|
||||
|
||||
template<class T> class GSFunctionMap
|
||||
{
|
||||
protected:
|
||||
struct ActivePtr
|
||||
{
|
||||
UINT64 frame, frames;
|
||||
@@ -53,7 +54,6 @@ template<class T> class GSFunctionMap
|
||||
CRBMap<DWORD, ActivePtr*> m_map_active;
|
||||
ActivePtr* m_active;
|
||||
|
||||
protected:
|
||||
virtual T GetDefaultFunction(DWORD sel) = 0;
|
||||
|
||||
public:
|
||||
@@ -118,72 +118,43 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void PrintStats()
|
||||
virtual void PrintStats()
|
||||
{
|
||||
if(FILE* fp = fopen("c:\\1.txt", "w"))
|
||||
__int64 ttpf = 0;
|
||||
|
||||
POSITION pos = m_map_active.GetHeadPosition();
|
||||
|
||||
while(pos)
|
||||
{
|
||||
POSITION pos = m_map_active.GetHeadPosition();
|
||||
|
||||
while(pos)
|
||||
ActivePtr* p = m_map_active.GetNextValue(pos);
|
||||
|
||||
if(p->frames)
|
||||
{
|
||||
DWORD sel;
|
||||
ActivePtr* p;
|
||||
|
||||
m_map_active.GetNextAssoc(pos, sel, p);
|
||||
|
||||
if(m_map.Lookup(sel))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(p->frames > 30)
|
||||
{
|
||||
int tpf = (int)((p->ticks / p->frames) * 10000 / (3000000000 / 60)); // 3 GHz, 60 fps
|
||||
|
||||
if(tpf >= 500)
|
||||
{
|
||||
_ftprintf(fp, _T("InitDS_Sel(0x%08x); // %6.2f%%\n"), sel, (float)tpf / 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
{
|
||||
__int64 ttpf = 0;
|
||||
|
||||
POSITION pos = m_map_active.GetHeadPosition();
|
||||
|
||||
while(pos)
|
||||
{
|
||||
ActivePtr* p = m_map_active.GetNextValue(pos);
|
||||
|
||||
ttpf += p->ticks / p->frames;
|
||||
}
|
||||
}
|
||||
|
||||
pos = m_map_active.GetHeadPosition();
|
||||
pos = m_map_active.GetHeadPosition();
|
||||
|
||||
while(pos)
|
||||
while(pos)
|
||||
{
|
||||
DWORD sel;
|
||||
ActivePtr* p;
|
||||
|
||||
m_map_active.GetNextAssoc(pos, sel, p);
|
||||
|
||||
if(p->frames > 0)
|
||||
{
|
||||
DWORD sel;
|
||||
ActivePtr* p;
|
||||
__int64 tpp = p->pixels > 0 ? p->ticks / p->pixels : 0;
|
||||
__int64 tpf = p->frames > 0 ? p->ticks / p->frames : 0;
|
||||
__int64 ppf = p->frames > 0 ? p->pixels / p->frames : 0;
|
||||
|
||||
m_map_active.GetNextAssoc(pos, sel, p);
|
||||
|
||||
if(p->frames > 0)
|
||||
{
|
||||
__int64 tpp = p->pixels > 0 ? p->ticks / p->pixels : 0;
|
||||
__int64 tpf = p->frames > 0 ? p->ticks / p->frames : 0;
|
||||
__int64 ppf = p->frames > 0 ? p->pixels / p->frames : 0;
|
||||
|
||||
printf("[%08x]%c %6.2f%% | %5.2f%% | f %4I64d | p %10I64d | tpp %4I64d | tpf %9I64d | ppf %7I64d\n",
|
||||
sel, !m_map.Lookup(sel) ? '*' : ' ',
|
||||
(float)(tpf * 10000 / 50000000) / 100,
|
||||
(float)(tpf * 10000 / ttpf) / 100,
|
||||
p->frames, p->pixels,
|
||||
tpp, tpf, ppf);
|
||||
}
|
||||
printf("[%08x]%c %6.2f%% | %5.2f%% | f %4I64d | p %10I64d | tpp %4I64d | tpf %9I64d | ppf %7I64d\n",
|
||||
sel, !m_map.Lookup(sel) ? '*' : ' ',
|
||||
(float)(tpf * 10000 / 50000000) / 100,
|
||||
(float)(tpf * 10000 / ttpf) / 100,
|
||||
p->frames, p->pixels,
|
||||
tpp, tpf, ppf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -417,7 +417,7 @@ GSLocalMemory::Offset* GSLocalMemory::GetOffset(DWORD bp, DWORD bw, DWORD psm)
|
||||
{
|
||||
if(bw == 0) {ASSERT(0); return NULL;}
|
||||
|
||||
ASSERT(m_psm[psm].trbpp > 8); // only for 16/24/32/8h/4hh/4hl formats where all columns are the same
|
||||
ASSERT(m_psm[psm].bpp > 8); // only for 16/24/32/8h/4hh/4hl formats where all columns are the same
|
||||
|
||||
DWORD hash = bp | (bw << 14) | (psm << 20);
|
||||
|
||||
@@ -459,11 +459,14 @@ GSLocalMemory::Offset4* GSLocalMemory::GetOffset4(const GIFRegFRAME& FRAME, cons
|
||||
DWORD zpsm = ZBUF.PSM;
|
||||
DWORD bw = FRAME.FBW;
|
||||
|
||||
ASSERT(m_psm[fpsm].bpp > 8 || m_psm[zpsm].bpp > 8);
|
||||
ASSERT(m_psm[fpsm].trbpp > 8 || m_psm[zpsm].trbpp > 8);
|
||||
|
||||
// "(psm & 3) | (psm >> 3)" makes 4 bit unique identifiers for render target formats (only)
|
||||
// "(psm & 0x0f) ^ ((psm & 0xf0) >> 2)" creates 4 bit unique identifiers for render target formats (only)
|
||||
|
||||
DWORD hash = (FRAME.FBP << 0) | (ZBUF.ZBP << 9) | (bw << 18) | (((fpsm & 3) | (fpsm >> 3)) << 24) | (((zpsm & 3) | (zpsm >> 3)) << 28);
|
||||
DWORD fpsm_hash = (fpsm & 0x0f) ^ ((fpsm & 0x30) >> 2);
|
||||
DWORD zpsm_hash = (zpsm & 0x0f) ^ ((zpsm & 0x30) >> 2);
|
||||
|
||||
DWORD hash = (FRAME.FBP << 0) | (ZBUF.ZBP << 9) | (bw << 18) | (fpsm_hash << 24) | (zpsm_hash << 28);
|
||||
|
||||
if(CRBMap<DWORD, Offset4*>::CPair* pair = m_o4map.Lookup(hash))
|
||||
{
|
||||
|
||||
@@ -480,7 +480,12 @@ protected:
|
||||
PRIM->TME ? (int)m_context->TEX0.PSM : 0xff);
|
||||
*/
|
||||
|
||||
Draw();
|
||||
if(GSUtil::EncodePSM(m_context->FRAME.PSM) != 3 && GSUtil::EncodePSM(m_context->ZBUF.PSM) != 3)
|
||||
{
|
||||
// FIXME: berserk fpsm = 27 (8H)
|
||||
|
||||
Draw();
|
||||
}
|
||||
|
||||
m_count = 0;
|
||||
}
|
||||
@@ -493,12 +498,8 @@ protected:
|
||||
m_maxcount -= 100;
|
||||
}
|
||||
|
||||
template<DWORD prim> void VertexKick(bool skip)
|
||||
template<DWORD prim> __forceinline Vertex* DrawingKick(bool skip, DWORD& count)
|
||||
{
|
||||
(this->*m_fpAddVertexHandlers[PRIM->TME][PRIM->FST])();
|
||||
|
||||
DWORD count = 0;
|
||||
|
||||
switch(prim)
|
||||
{
|
||||
case GS_POINTLIST: count = 1; break;
|
||||
@@ -514,7 +515,7 @@ protected:
|
||||
|
||||
if(m_vl.GetCount() < count)
|
||||
{
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(m_count >= m_maxcount)
|
||||
@@ -566,30 +567,16 @@ protected:
|
||||
case GS_INVALID:
|
||||
ASSERT(0);
|
||||
m_vl.RemoveAll();
|
||||
return;
|
||||
return NULL;
|
||||
default:
|
||||
__assume(0);
|
||||
}
|
||||
|
||||
if(!skip)
|
||||
{
|
||||
(this->*m_fpAddPrimHandlers[prim])(v, count);
|
||||
|
||||
m_count += count;
|
||||
}
|
||||
return !skip ? v : NULL;
|
||||
}
|
||||
|
||||
virtual void Draw() = 0;
|
||||
|
||||
typedef void (GSRendererT<Device, Vertex>::*AddVertexHandler)();
|
||||
typedef void (GSRendererT<Device, Vertex>::*AddPrimHandler)(Vertex* v, DWORD& count);
|
||||
|
||||
AddVertexHandler m_fpAddVertexHandlers[2][2];
|
||||
AddPrimHandler m_fpAddPrimHandlers[8];
|
||||
|
||||
void AddVertexNull() {ASSERT(0);}
|
||||
void AddPrimNull(Vertex* v, DWORD& count) {ASSERT(0);}
|
||||
|
||||
public:
|
||||
GSRendererT(BYTE* base, bool mt, void (*irq)(), int nloophack, const GSRendererSettings& rs, bool psrr = true)
|
||||
: GSRenderer<Device>(base, mt, irq, nloophack, rs, psrr)
|
||||
@@ -597,24 +584,6 @@ public:
|
||||
, m_maxcount(0)
|
||||
, m_vertices(NULL)
|
||||
{
|
||||
m_fpVertexKickHandlers[GS_POINTLIST] = (VertexKickHandler)&GSRendererT<Device, Vertex>::VertexKick<GS_POINTLIST>;
|
||||
m_fpVertexKickHandlers[GS_LINELIST] = (VertexKickHandler)&GSRendererT<Device, Vertex>::VertexKick<GS_LINELIST>;
|
||||
m_fpVertexKickHandlers[GS_LINESTRIP] = (VertexKickHandler)&GSRendererT<Device, Vertex>::VertexKick<GS_LINESTRIP>;
|
||||
m_fpVertexKickHandlers[GS_TRIANGLELIST] = (VertexKickHandler)&GSRendererT<Device, Vertex>::VertexKick<GS_TRIANGLELIST>;
|
||||
m_fpVertexKickHandlers[GS_TRIANGLESTRIP] = (VertexKickHandler)&GSRendererT<Device, Vertex>::VertexKick<GS_TRIANGLESTRIP>;
|
||||
m_fpVertexKickHandlers[GS_TRIANGLEFAN] = (VertexKickHandler)&GSRendererT<Device, Vertex>::VertexKick<GS_TRIANGLEFAN>;
|
||||
m_fpVertexKickHandlers[GS_SPRITE] = (VertexKickHandler)&GSRendererT<Device, Vertex>::VertexKick<GS_SPRITE>;
|
||||
m_fpVertexKickHandlers[GS_INVALID] = (VertexKickHandler)&GSRendererT<Device, Vertex>::VertexKick<GS_INVALID>;
|
||||
|
||||
m_fpAddVertexHandlers[0][0] = &GSRendererT<Device, Vertex>::AddVertexNull;
|
||||
m_fpAddVertexHandlers[0][1] = &GSRendererT<Device, Vertex>::AddVertexNull;
|
||||
m_fpAddVertexHandlers[1][0] = &GSRendererT<Device, Vertex>::AddVertexNull;
|
||||
m_fpAddVertexHandlers[1][1] = &GSRendererT<Device, Vertex>::AddVertexNull;
|
||||
|
||||
for(int i = 0; i < countof(m_fpAddPrimHandlers); i++)
|
||||
{
|
||||
m_fpAddPrimHandlers[i] = &GSRendererT<Device, Vertex>::AddPrimNull;
|
||||
}
|
||||
}
|
||||
|
||||
~GSRendererT()
|
||||
|
||||
@@ -27,18 +27,7 @@
|
||||
GSRendererHW10::GSRendererHW10(BYTE* base, bool mt, void (*irq)(), int nloophack, const GSRendererSettings& rs)
|
||||
: GSRendererHW<Device, Vertex, TextureCache>(base, mt, irq, nloophack, rs, true)
|
||||
{
|
||||
m_fpAddVertexHandlers[0][0] = (AddVertexHandler)&GSRendererHW10::AddVertex<0, 0>;
|
||||
m_fpAddVertexHandlers[0][1] = (AddVertexHandler)&GSRendererHW10::AddVertex<0, 0>;
|
||||
m_fpAddVertexHandlers[1][0] = (AddVertexHandler)&GSRendererHW10::AddVertex<1, 0>;
|
||||
m_fpAddVertexHandlers[1][1] = (AddVertexHandler)&GSRendererHW10::AddVertex<1, 1>;
|
||||
|
||||
m_fpAddPrimHandlers[GS_POINTLIST] = (AddPrimHandler)&GSRendererHW10::AddPrim<GS_POINT_CLASS>;
|
||||
m_fpAddPrimHandlers[GS_LINELIST] = (AddPrimHandler)&GSRendererHW10::AddPrim<GS_LINE_CLASS>;
|
||||
m_fpAddPrimHandlers[GS_LINESTRIP] = (AddPrimHandler)&GSRendererHW10::AddPrim<GS_LINE_CLASS>;
|
||||
m_fpAddPrimHandlers[GS_TRIANGLELIST] = (AddPrimHandler)&GSRendererHW10::AddPrim<GS_TRIANGLE_CLASS>;
|
||||
m_fpAddPrimHandlers[GS_TRIANGLESTRIP] = (AddPrimHandler)&GSRendererHW10::AddPrim<GS_TRIANGLE_CLASS>;
|
||||
m_fpAddPrimHandlers[GS_TRIANGLEFAN] = (AddPrimHandler)&GSRendererHW10::AddPrim<GS_TRIANGLE_CLASS>;
|
||||
m_fpAddPrimHandlers[GS_SPRITE] = (AddPrimHandler)&GSRendererHW10::AddPrim<GS_SPRITE_CLASS>;
|
||||
InitVertexKick<GSRendererHW10>();
|
||||
}
|
||||
|
||||
bool GSRendererHW10::Create(LPCTSTR title)
|
||||
@@ -81,8 +70,8 @@ bool GSRendererHW10::Create(LPCTSTR title)
|
||||
return true;
|
||||
}
|
||||
|
||||
template<DWORD tme, DWORD fst>
|
||||
void GSRendererHW10::AddVertex()
|
||||
template<DWORD prim, DWORD tme, DWORD fst>
|
||||
void GSRendererHW10::VertexKick(bool skip)
|
||||
{
|
||||
Vertex& dst = m_vl.AddTail();
|
||||
|
||||
@@ -93,86 +82,91 @@ void GSRendererHW10::AddVertex()
|
||||
{
|
||||
GSVector4::storel(&dst.ST, m_v.GetUV());
|
||||
}
|
||||
}
|
||||
|
||||
template<int primclass>
|
||||
void GSRendererHW10::AddPrim(Vertex* v, DWORD& count)
|
||||
{
|
||||
GSVector4i scissor = m_context->scissor.dx10;
|
||||
|
||||
#if _M_SSE >= 0x401
|
||||
|
||||
GSVector4i pmin, pmax, v0, v1, v2;
|
||||
|
||||
switch(primclass)
|
||||
DWORD count = 0;
|
||||
|
||||
if(Vertex* v = DrawingKick<prim>(skip, count))
|
||||
{
|
||||
case GS_POINT_CLASS:
|
||||
v0 = GSVector4i::load((int)v[0].p.xy).upl16();
|
||||
pmin = v0;
|
||||
pmax = v0;
|
||||
break;
|
||||
case GS_LINE_CLASS:
|
||||
case GS_SPRITE_CLASS:
|
||||
v0 = GSVector4i::load((int)v[0].p.xy);
|
||||
v1 = GSVector4i::load((int)v[1].p.xy);
|
||||
pmin = v0.min_u16(v1).upl16();
|
||||
pmax = v0.max_u16(v1).upl16();
|
||||
break;
|
||||
case GS_TRIANGLE_CLASS:
|
||||
v0 = GSVector4i::load((int)v[0].p.xy);
|
||||
v1 = GSVector4i::load((int)v[1].p.xy);
|
||||
v2 = GSVector4i::load((int)v[2].p.xy);
|
||||
pmin = v0.min_u16(v1).min_u16(v2).upl16();
|
||||
pmax = v0.max_u16(v1).max_u16(v2).upl16();
|
||||
break;
|
||||
}
|
||||
GSVector4i scissor = m_context->scissor.dx10;
|
||||
|
||||
GSVector4i test = (pmax < scissor) | (pmin > scissor.zwxy());
|
||||
#if _M_SSE >= 0x401
|
||||
|
||||
if(test.mask() & 0xff)
|
||||
{
|
||||
count = 0;
|
||||
return;
|
||||
}
|
||||
GSVector4i pmin, pmax, v0, v1, v2;
|
||||
|
||||
#else
|
||||
|
||||
switch(primclass)
|
||||
{
|
||||
case GS_POINT_CLASS:
|
||||
if(v[0].p.x < scissor.x
|
||||
|| v[0].p.x > scissor.z
|
||||
|| v[0].p.y < scissor.y
|
||||
|| v[0].p.y > scissor.w)
|
||||
switch(prim)
|
||||
{
|
||||
case GS_POINTLIST:
|
||||
v0 = GSVector4i::load((int)v[0].p.xy).upl16();
|
||||
pmin = v0;
|
||||
pmax = v0;
|
||||
break;
|
||||
case GS_LINELIST:
|
||||
case GS_LINESTRIP:
|
||||
case GS_SPRITE:
|
||||
v0 = GSVector4i::load((int)v[0].p.xy);
|
||||
v1 = GSVector4i::load((int)v[1].p.xy);
|
||||
pmin = v0.min_u16(v1).upl16();
|
||||
pmax = v0.max_u16(v1).upl16();
|
||||
break;
|
||||
case GS_TRIANGLELIST:
|
||||
case GS_TRIANGLESTRIP:
|
||||
case GS_TRIANGLEFAN:
|
||||
v0 = GSVector4i::load((int)v[0].p.xy);
|
||||
v1 = GSVector4i::load((int)v[1].p.xy);
|
||||
v2 = GSVector4i::load((int)v[2].p.xy);
|
||||
pmin = v0.min_u16(v1).min_u16(v2).upl16();
|
||||
pmax = v0.max_u16(v1).max_u16(v2).upl16();
|
||||
break;
|
||||
}
|
||||
|
||||
GSVector4i test = (pmax < scissor) | (pmin > scissor.zwxy());
|
||||
|
||||
if(test.mask() & 0xff)
|
||||
{
|
||||
count = 0;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case GS_LINE_CLASS:
|
||||
case GS_SPRITE_CLASS:
|
||||
if(v[0].p.x < scissor.x && v[1].p.x < scissor.x
|
||||
|| v[0].p.x > scissor.z && v[1].p.x > scissor.z
|
||||
|| v[0].p.y < scissor.y && v[1].p.y < scissor.y
|
||||
|| v[0].p.y > scissor.w && v[1].p.y > scissor.w)
|
||||
{
|
||||
count = 0;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case GS_TRIANGLE_CLASS:
|
||||
if(v[0].p.x < scissor.x && v[1].p.x < scissor.x && v[2].p.x < scissor.x
|
||||
|| v[0].p.x > scissor.z && v[1].p.x > scissor.z && v[2].p.x > scissor.z
|
||||
|| v[0].p.y < scissor.y && v[1].p.y < scissor.y && v[2].p.y < scissor.y
|
||||
|| v[0].p.y > scissor.w && v[1].p.y > scissor.w && v[2].p.y > scissor.w)
|
||||
{
|
||||
count = 0;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#endif
|
||||
#else
|
||||
|
||||
switch(prim)
|
||||
{
|
||||
case GS_POINTLIST:
|
||||
if(v[0].p.x < scissor.x
|
||||
|| v[0].p.x > scissor.z
|
||||
|| v[0].p.y < scissor.y
|
||||
|| v[0].p.y > scissor.w)
|
||||
{
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case GS_LINELIST:
|
||||
case GS_LINESTRIP:
|
||||
case GS_SPRITE:
|
||||
if(v[0].p.x < scissor.x && v[1].p.x < scissor.x
|
||||
|| v[0].p.x > scissor.z && v[1].p.x > scissor.z
|
||||
|| v[0].p.y < scissor.y && v[1].p.y < scissor.y
|
||||
|| v[0].p.y > scissor.w && v[1].p.y > scissor.w)
|
||||
{
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case GS_TRIANGLELIST:
|
||||
case GS_TRIANGLESTRIP:
|
||||
case GS_TRIANGLEFAN:
|
||||
if(v[0].p.x < scissor.x && v[1].p.x < scissor.x && v[2].p.x < scissor.x
|
||||
|| v[0].p.x > scissor.z && v[1].p.x > scissor.z && v[2].p.x > scissor.z
|
||||
|| v[0].p.y < scissor.y && v[1].p.y < scissor.y && v[2].p.y < scissor.y
|
||||
|| v[0].p.y > scissor.w && v[1].p.y > scissor.w && v[2].p.y > scissor.w)
|
||||
{
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
m_count += count;
|
||||
}
|
||||
}
|
||||
|
||||
void GSRendererHW10::Draw(int prim, Texture& rt, Texture& ds, GSTextureCache<Device>::GSTexture* tex)
|
||||
|
||||
@@ -32,17 +32,11 @@ class GSRendererHW10 : public GSRendererHW<GSDevice10, GSVertexHW10, GSTextureCa
|
||||
typedef GSVertexHW10 Vertex;
|
||||
typedef GSTextureCache10 TextureCache;
|
||||
|
||||
bool WrapZ(DWORD maxz);
|
||||
|
||||
protected:
|
||||
GSTextureFX10 m_tfx;
|
||||
|
||||
template<DWORD tme, DWORD fst>
|
||||
void AddVertex();
|
||||
|
||||
template<int primclass>
|
||||
void AddPrim(Vertex* v, DWORD& count);
|
||||
|
||||
bool WrapZ(DWORD maxz);
|
||||
|
||||
void Draw(int prim, Texture& rt, Texture& ds, GSTextureCache<Device>::GSTexture* tex);
|
||||
|
||||
struct
|
||||
@@ -57,4 +51,6 @@ public:
|
||||
GSRendererHW10(BYTE* base, bool mt, void (*irq)(), int nloophack, const GSRendererSettings& rs);
|
||||
|
||||
bool Create(LPCTSTR title);
|
||||
|
||||
template<DWORD prim, DWORD tme, DWORD fst> void VertexKick(bool skip);
|
||||
};
|
||||
@@ -30,18 +30,7 @@ GSRendererHW9::GSRendererHW9(BYTE* base, bool mt, void (*irq)(), int nloophack,
|
||||
m_fba.enabled = !!AfxGetApp()->GetProfileInt(_T("Settings"), _T("fba"), TRUE);
|
||||
m_logz = !!AfxGetApp()->GetProfileInt(_T("Settings"), _T("logz"), FALSE);
|
||||
|
||||
m_fpAddVertexHandlers[0][0] = (AddVertexHandler)&GSRendererHW9::AddVertex<0, 0>;
|
||||
m_fpAddVertexHandlers[0][1] = (AddVertexHandler)&GSRendererHW9::AddVertex<0, 0>;
|
||||
m_fpAddVertexHandlers[1][0] = (AddVertexHandler)&GSRendererHW9::AddVertex<1, 0>;
|
||||
m_fpAddVertexHandlers[1][1] = (AddVertexHandler)&GSRendererHW9::AddVertex<1, 1>;
|
||||
|
||||
m_fpAddPrimHandlers[GS_POINTLIST] = (AddPrimHandler)&GSRendererHW9::AddPrim<GS_POINT_CLASS>;
|
||||
m_fpAddPrimHandlers[GS_LINELIST] = (AddPrimHandler)&GSRendererHW9::AddPrim<GS_LINE_CLASS>;
|
||||
m_fpAddPrimHandlers[GS_LINESTRIP] = (AddPrimHandler)&GSRendererHW9::AddPrim<GS_LINE_CLASS>;
|
||||
m_fpAddPrimHandlers[GS_TRIANGLELIST] = (AddPrimHandler)&GSRendererHW9::AddPrim<GS_TRIANGLE_CLASS>;
|
||||
m_fpAddPrimHandlers[GS_TRIANGLESTRIP] = (AddPrimHandler)&GSRendererHW9::AddPrim<GS_TRIANGLE_CLASS>;
|
||||
m_fpAddPrimHandlers[GS_TRIANGLEFAN] = (AddPrimHandler)&GSRendererHW9::AddPrim<GS_TRIANGLE_CLASS>;
|
||||
m_fpAddPrimHandlers[GS_SPRITE] = (AddPrimHandler)&GSRendererHW9::AddPrim<GS_SPRITE_CLASS>;
|
||||
InitVertexKick<GSRendererHW9>();
|
||||
}
|
||||
|
||||
bool GSRendererHW9::Create(LPCTSTR title)
|
||||
@@ -85,8 +74,8 @@ bool GSRendererHW9::Create(LPCTSTR title)
|
||||
return true;
|
||||
}
|
||||
|
||||
template<DWORD tme, DWORD fst>
|
||||
void GSRendererHW9::AddVertex()
|
||||
template<DWORD prim, DWORD tme, DWORD fst>
|
||||
void GSRendererHW9::VertexKick(bool skip)
|
||||
{
|
||||
Vertex& dst = m_vl.AddTail();
|
||||
|
||||
@@ -110,65 +99,73 @@ void GSRendererHW9::AddVertex()
|
||||
dst.p.w = m_v.RGBAQ.Q;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<int primclass>
|
||||
void GSRendererHW9::AddPrim(Vertex* v, DWORD& count)
|
||||
{
|
||||
GSVector4 scissor = m_context->scissor.dx9;
|
||||
|
||||
GSVector4 pmin, pmax;
|
||||
|
||||
switch(primclass)
|
||||
DWORD count = 0;
|
||||
|
||||
if(Vertex* v = DrawingKick<prim>(skip, count))
|
||||
{
|
||||
case GS_POINT_CLASS:
|
||||
pmin = v[0].p;
|
||||
pmax = v[0].p;
|
||||
break;
|
||||
case GS_LINE_CLASS:
|
||||
case GS_SPRITE_CLASS:
|
||||
pmin = v[0].p.minv(v[1].p);
|
||||
pmax = v[0].p.maxv(v[1].p);
|
||||
break;
|
||||
case GS_TRIANGLE_CLASS:
|
||||
pmin = v[0].p.minv(v[1].p).minv(v[2].p);
|
||||
pmax = v[0].p.maxv(v[1].p).maxv(v[2].p);
|
||||
break;
|
||||
}
|
||||
GSVector4 scissor = m_context->scissor.dx9;
|
||||
|
||||
GSVector4 test = (pmax < scissor) | (pmin > scissor.zwxy());
|
||||
GSVector4 pmin, pmax;
|
||||
|
||||
if(test.mask() & 3)
|
||||
{
|
||||
count = 0;
|
||||
return;
|
||||
}
|
||||
switch(prim)
|
||||
{
|
||||
case GS_POINTLIST:
|
||||
pmin = v[0].p;
|
||||
pmax = v[0].p;
|
||||
break;
|
||||
case GS_LINELIST:
|
||||
case GS_LINESTRIP:
|
||||
case GS_SPRITE:
|
||||
pmin = v[0].p.minv(v[1].p);
|
||||
pmax = v[0].p.maxv(v[1].p);
|
||||
break;
|
||||
case GS_TRIANGLELIST:
|
||||
case GS_TRIANGLESTRIP:
|
||||
case GS_TRIANGLEFAN:
|
||||
pmin = v[0].p.minv(v[1].p).minv(v[2].p);
|
||||
pmax = v[0].p.maxv(v[1].p).maxv(v[2].p);
|
||||
break;
|
||||
}
|
||||
|
||||
switch(primclass)
|
||||
{
|
||||
case GS_POINT_CLASS:
|
||||
break;
|
||||
case GS_LINE_CLASS:
|
||||
if(PRIM->IIP == 0) {v[0].c0 = v[1].c0;}
|
||||
break;
|
||||
case GS_SPRITE_CLASS:
|
||||
if(PRIM->IIP == 0) {v[0].c0 = v[1].c0;}
|
||||
v[0].p.z = v[1].p.z;
|
||||
v[0].p.w = v[1].p.w;
|
||||
v[0].c1 = v[1].c1;
|
||||
v[2] = v[1];
|
||||
v[3] = v[1];
|
||||
v[1].p.y = v[0].p.y;
|
||||
v[1].t.y = v[0].t.y;
|
||||
v[2].p.x = v[0].p.x;
|
||||
v[2].t.x = v[0].t.x;
|
||||
v[4] = v[1];
|
||||
v[5] = v[2];
|
||||
count += 4;
|
||||
break;
|
||||
case GS_TRIANGLE_CLASS:
|
||||
if(PRIM->IIP == 0) {v[0].c0 = v[1].c0 = v[2].c0;}
|
||||
break;
|
||||
GSVector4 test = (pmax < scissor) | (pmin > scissor.zwxy());
|
||||
|
||||
if(test.mask() & 3)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch(prim)
|
||||
{
|
||||
case GS_POINTLIST:
|
||||
break;
|
||||
case GS_LINELIST:
|
||||
case GS_LINESTRIP:
|
||||
if(PRIM->IIP == 0) {v[0].c0 = v[1].c0;}
|
||||
break;
|
||||
case GS_TRIANGLELIST:
|
||||
case GS_TRIANGLESTRIP:
|
||||
case GS_TRIANGLEFAN:
|
||||
if(PRIM->IIP == 0) {v[0].c0 = v[1].c0 = v[2].c0;}
|
||||
break;
|
||||
case GS_SPRITE:
|
||||
if(PRIM->IIP == 0) {v[0].c0 = v[1].c0;}
|
||||
v[0].p.z = v[1].p.z;
|
||||
v[0].p.w = v[1].p.w;
|
||||
v[0].c1 = v[1].c1;
|
||||
v[2] = v[1];
|
||||
v[3] = v[1];
|
||||
v[1].p.y = v[0].p.y;
|
||||
v[1].t.y = v[0].t.y;
|
||||
v[2].p.x = v[0].p.x;
|
||||
v[2].t.x = v[0].t.x;
|
||||
v[4] = v[1];
|
||||
v[5] = v[2];
|
||||
count += 4;
|
||||
break;
|
||||
}
|
||||
|
||||
m_count += count;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,18 +32,12 @@ class GSRendererHW9 : public GSRendererHW<GSDevice9, GSVertexHW9, GSTextureCache
|
||||
typedef GSVertexHW9 Vertex;
|
||||
typedef GSTextureCache9 TextureCache;
|
||||
|
||||
bool WrapZ(float maxz);
|
||||
|
||||
protected:
|
||||
GSTextureFX9 m_tfx;
|
||||
bool m_logz;
|
||||
|
||||
template<DWORD tme, DWORD fst>
|
||||
void AddVertex();
|
||||
|
||||
template<int primclass>
|
||||
void AddPrim(Vertex* v, DWORD& count);
|
||||
|
||||
bool WrapZ(float maxz);
|
||||
|
||||
void Draw(int prim, Texture& rt, Texture& ds, GSTextureCache<Device>::GSTexture* tex);
|
||||
|
||||
struct
|
||||
@@ -66,4 +60,6 @@ public:
|
||||
GSRendererHW9(BYTE* base, bool mt, void (*irq)(), int nloophack, const GSRendererSettings& rs);
|
||||
|
||||
bool Create(LPCTSTR title);
|
||||
|
||||
template<DWORD prim, DWORD tme, DWORD fst> void VertexKick(bool skip);
|
||||
};
|
||||
|
||||
@@ -27,15 +27,6 @@
|
||||
template<class Device> class GSRendererNull : public GSRendererT<Device, GSVertexNull>
|
||||
{
|
||||
protected:
|
||||
void AddVertex()
|
||||
{
|
||||
}
|
||||
|
||||
void AddPrim(GSVertexNull* v, DWORD& count)
|
||||
{
|
||||
m_perfmon.Put(GSPerfMon::Prim, 1);
|
||||
}
|
||||
|
||||
void Draw()
|
||||
{
|
||||
}
|
||||
@@ -49,14 +40,10 @@ public:
|
||||
GSRendererNull(BYTE* base, bool mt, void (*irq)(), int nloophack, const GSRendererSettings& rs)
|
||||
: GSRendererT<Device, GSVertexNull>(base, mt, irq, nloophack, rs)
|
||||
{
|
||||
m_fpAddVertexHandlers[0][0] = (AddVertexHandler)&GSRendererNull::AddVertex;
|
||||
m_fpAddVertexHandlers[0][1] = (AddVertexHandler)&GSRendererNull::AddVertex;
|
||||
m_fpAddVertexHandlers[1][0] = (AddVertexHandler)&GSRendererNull::AddVertex;
|
||||
m_fpAddVertexHandlers[1][1] = (AddVertexHandler)&GSRendererNull::AddVertex;
|
||||
InitVertexKick<GSRendererNull<Device> >();
|
||||
}
|
||||
|
||||
for(int i = 0; i < countof(m_fpAddPrimHandlers); i++)
|
||||
{
|
||||
m_fpAddPrimHandlers[i] = (AddPrimHandler)&GSRendererNull::AddPrim;
|
||||
}
|
||||
template<DWORD prim, DWORD tme, DWORD fst> void VertexKick(bool skip)
|
||||
{
|
||||
}
|
||||
};
|
||||
@@ -117,127 +117,6 @@ protected:
|
||||
return true;
|
||||
}
|
||||
|
||||
template<DWORD tme, DWORD fst> void AddVertex()
|
||||
{
|
||||
GSVertexSW v;
|
||||
|
||||
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(p - o) * g_pos_scale;
|
||||
|
||||
v.c = GSVector4(GSVector4i::load((int)m_v.RGBAQ.ai32[0]).u8to32() << 7);
|
||||
|
||||
if(tme)
|
||||
{
|
||||
float q;
|
||||
|
||||
if(fst)
|
||||
{
|
||||
v.t = GSVector4(GSVector4i(m_v.UV.U, m_v.UV.V) << (16 - 4));
|
||||
q = 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
v.t = GSVector4(m_v.ST.S, m_v.ST.T);
|
||||
v.t *= GSVector4(0x10000 << m_context->TEX0.TW, 0x10000 << m_context->TEX0.TH);
|
||||
q = m_v.RGBAQ.Q;
|
||||
}
|
||||
|
||||
v.t = v.t.xyxy(GSVector4::load(q));
|
||||
}
|
||||
|
||||
GSVertexSW& dst = m_vl.AddTail();
|
||||
|
||||
dst = v;
|
||||
|
||||
dst.p.z = (float)min(m_v.XYZ.Z, 0xffffff00); // max value which can survive the DWORD => float => DWORD conversion
|
||||
}
|
||||
|
||||
template<int primclass> void AddPrim(GSVertexSW* v, DWORD& count)
|
||||
{
|
||||
GSVector4 pmin, pmax;
|
||||
|
||||
switch(primclass)
|
||||
{
|
||||
case GS_POINT_CLASS:
|
||||
pmin = v[0].p;
|
||||
pmax = v[0].p;
|
||||
break;
|
||||
case GS_LINE_CLASS:
|
||||
pmin = v[0].p.minv(v[1].p);
|
||||
pmax = v[0].p.maxv(v[1].p);
|
||||
break;
|
||||
case GS_TRIANGLE_CLASS:
|
||||
pmin = v[0].p.minv(v[1].p).minv(v[2].p);
|
||||
pmax = v[0].p.maxv(v[1].p).maxv(v[2].p);
|
||||
break;
|
||||
case GS_SPRITE_CLASS:
|
||||
pmin = v[0].p.minv(v[1].p);
|
||||
pmax = v[0].p.maxv(v[1].p);
|
||||
break;
|
||||
}
|
||||
|
||||
GSVector4 scissor = m_context->scissor.ex;
|
||||
|
||||
GSVector4 test = (pmax < scissor) | (pmin > scissor.zwxy());
|
||||
|
||||
if(primclass != GS_POINT_CLASS && primclass != GS_LINE_CLASS)
|
||||
{
|
||||
test |= pmin.ceil() == pmax.ceil();
|
||||
}
|
||||
|
||||
if(test.mask() & 3)
|
||||
{
|
||||
count = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
m_vtrace.min.p = m_vtrace.min.p.minv(pmin);
|
||||
m_vtrace.max.p = m_vtrace.max.p.maxv(pmax);
|
||||
|
||||
switch(primclass)
|
||||
{
|
||||
case GS_POINT_CLASS:
|
||||
m_vtrace.min.t = m_vtrace.min.t.minv(v[0].t);
|
||||
m_vtrace.max.t = m_vtrace.max.t.maxv(v[0].t);
|
||||
m_vtrace.min.c = m_vtrace.min.c.minv(v[0].c);
|
||||
m_vtrace.max.c = m_vtrace.max.c.maxv(v[0].c);
|
||||
break;
|
||||
case GS_LINE_CLASS:
|
||||
if(PRIM->IIP == 0) {v[0].c = v[1].c;}
|
||||
m_vtrace.min.t = m_vtrace.min.t.minv(v[0].t).minv(v[1].t);
|
||||
m_vtrace.max.t = m_vtrace.max.t.maxv(v[0].t).maxv(v[1].t);
|
||||
m_vtrace.min.c = m_vtrace.min.c.minv(v[0].c).minv(v[1].c);
|
||||
m_vtrace.max.c = m_vtrace.max.c.maxv(v[0].c).maxv(v[1].c);
|
||||
break;
|
||||
case GS_TRIANGLE_CLASS:
|
||||
if(PRIM->IIP == 0) {v[0].c = v[2].c; v[1].c = v[2].c;}
|
||||
m_vtrace.min.t = m_vtrace.min.t.minv(v[0].t).minv(v[1].t.minv(v[2].t));
|
||||
m_vtrace.max.t = m_vtrace.max.t.maxv(v[0].t).maxv(v[1].t.maxv(v[2].t));
|
||||
m_vtrace.min.c = m_vtrace.min.c.minv(v[0].c).minv(v[1].c.minv(v[2].c));
|
||||
m_vtrace.max.c = m_vtrace.max.c.maxv(v[0].c).maxv(v[1].c.maxv(v[2].c));
|
||||
break;
|
||||
case GS_SPRITE_CLASS:
|
||||
m_vtrace.min.t = m_vtrace.min.t.minv(v[0].t).minv(v[1].t);
|
||||
m_vtrace.max.t = m_vtrace.max.t.maxv(v[0].t).maxv(v[1].t);
|
||||
m_vtrace.min.c = m_vtrace.min.c.minv(v[1].c);
|
||||
m_vtrace.max.c = m_vtrace.max.c.maxv(v[1].c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GSVector4i GetScissor()
|
||||
{
|
||||
GSVector4i v = GSVector4i(m_context->scissor.in);
|
||||
|
||||
// TODO: find a game that overflows and check which one is the right behaviour
|
||||
|
||||
v.z = min(v.z, (int)m_context->FRAME.FBW * 64);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
bool TryAlphaTest(DWORD& fm, DWORD& zm)
|
||||
{
|
||||
const GSDrawingEnvironment& env = m_env;
|
||||
@@ -388,6 +267,7 @@ protected:
|
||||
p.sel.atst = ATST_ALWAYS;
|
||||
p.sel.tfx = TFX_NONE;
|
||||
p.sel.abe = 255;
|
||||
p.sel.sprite = primclass == GS_SPRITE_CLASS ? 1 : 0;
|
||||
|
||||
p.fm = context->FRAME.FBMSK;
|
||||
p.zm = context->ZBUF.ZMSK || context->TEST.ZTE == 0 ? 0xffffffff : 0;
|
||||
@@ -625,7 +505,8 @@ protected:
|
||||
|
||||
GSRasterizerData data;
|
||||
|
||||
data.scissor = GetScissor();
|
||||
data.scissor = GSVector4i(m_context->scissor.in);
|
||||
data.scissor.z = min(data.scissor.z, (int)m_context->FRAME.FBW * 64); // TODO: find a game that overflows and check which one is the right behaviour
|
||||
data.primclass = GSUtil::GetPrimClass(PRIM->PRIM);
|
||||
data.vertices = m_vertices;
|
||||
data.count = m_count;
|
||||
@@ -813,22 +694,138 @@ public:
|
||||
|
||||
m_tc = new GSTextureCacheSW(this);
|
||||
|
||||
m_fpAddVertexHandlers[0][0] = (AddVertexHandler)&GSRendererSW::AddVertex<0, 0>;
|
||||
m_fpAddVertexHandlers[0][1] = (AddVertexHandler)&GSRendererSW::AddVertex<0, 0>;
|
||||
m_fpAddVertexHandlers[1][0] = (AddVertexHandler)&GSRendererSW::AddVertex<1, 0>;
|
||||
m_fpAddVertexHandlers[1][1] = (AddVertexHandler)&GSRendererSW::AddVertex<1, 1>;
|
||||
|
||||
m_fpAddPrimHandlers[GS_POINTLIST] = (AddPrimHandler)&GSRendererSW::AddPrim<GS_POINT_CLASS>;
|
||||
m_fpAddPrimHandlers[GS_LINELIST] = (AddPrimHandler)&GSRendererSW::AddPrim<GS_LINE_CLASS>;
|
||||
m_fpAddPrimHandlers[GS_LINESTRIP] = (AddPrimHandler)&GSRendererSW::AddPrim<GS_LINE_CLASS>;
|
||||
m_fpAddPrimHandlers[GS_TRIANGLELIST] = (AddPrimHandler)&GSRendererSW::AddPrim<GS_TRIANGLE_CLASS>;
|
||||
m_fpAddPrimHandlers[GS_TRIANGLESTRIP] = (AddPrimHandler)&GSRendererSW::AddPrim<GS_TRIANGLE_CLASS>;
|
||||
m_fpAddPrimHandlers[GS_TRIANGLEFAN] = (AddPrimHandler)&GSRendererSW::AddPrim<GS_TRIANGLE_CLASS>;
|
||||
m_fpAddPrimHandlers[GS_SPRITE] = (AddPrimHandler)&GSRendererSW::AddPrim<GS_SPRITE_CLASS>;
|
||||
InitVertexKick<GSRendererSW<Device> >();
|
||||
}
|
||||
|
||||
virtual ~GSRendererSW()
|
||||
{
|
||||
delete m_tc;
|
||||
}
|
||||
|
||||
template<DWORD prim, DWORD tme, DWORD fst>
|
||||
void VertexKick(bool skip)
|
||||
{
|
||||
const GSDrawingContext* context = m_context;
|
||||
|
||||
GSVector4i xy = GSVector4i::load((int)m_v.XYZ.ai32[0]);
|
||||
|
||||
xy = xy.insert16<3>(m_v.FOG.F);
|
||||
xy = xy.upl16();
|
||||
xy -= context->XYOFFSET;
|
||||
|
||||
GSVertexSW v;
|
||||
|
||||
v.p = GSVector4(xy) * g_pos_scale;
|
||||
|
||||
v.c = GSVector4(GSVector4i::load((int)m_v.RGBAQ.ai32[0]).u8to32() << 7);
|
||||
|
||||
if(tme)
|
||||
{
|
||||
float q;
|
||||
|
||||
if(fst)
|
||||
{
|
||||
v.t = GSVector4(((GSVector4i)m_v.UV).upl16() << (16 - 4));
|
||||
q = 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
v.t = GSVector4(m_v.ST.S, m_v.ST.T);
|
||||
v.t *= GSVector4(0x10000 << context->TEX0.TW, 0x10000 << context->TEX0.TH);
|
||||
q = m_v.RGBAQ.Q;
|
||||
}
|
||||
|
||||
v.t = v.t.xyxy(GSVector4::load(q));
|
||||
}
|
||||
|
||||
GSVertexSW& dst = m_vl.AddTail();
|
||||
|
||||
dst = v;
|
||||
|
||||
dst.p.z = (float)min(m_v.XYZ.Z, 0xffffff00); // max value which can survive the DWORD => float => DWORD conversion
|
||||
|
||||
DWORD count = 0;
|
||||
|
||||
if(GSVertexSW* v = DrawingKick<prim>(skip, count))
|
||||
{
|
||||
GSVector4 pmin, pmax;
|
||||
|
||||
switch(prim)
|
||||
{
|
||||
case GS_POINTLIST:
|
||||
pmin = v[0].p;
|
||||
pmax = v[0].p;
|
||||
break;
|
||||
case GS_LINELIST:
|
||||
case GS_LINESTRIP:
|
||||
case GS_SPRITE:
|
||||
pmin = v[0].p.minv(v[1].p);
|
||||
pmax = v[0].p.maxv(v[1].p);
|
||||
break;
|
||||
case GS_TRIANGLELIST:
|
||||
case GS_TRIANGLESTRIP:
|
||||
case GS_TRIANGLEFAN:
|
||||
pmin = v[0].p.minv(v[1].p).minv(v[2].p);
|
||||
pmax = v[0].p.maxv(v[1].p).maxv(v[2].p);
|
||||
break;
|
||||
}
|
||||
|
||||
GSVector4 scissor = context->scissor.ex;
|
||||
|
||||
GSVector4 test = (pmax < scissor) | (pmin > scissor.zwxy());
|
||||
|
||||
switch(prim)
|
||||
{
|
||||
case GS_TRIANGLELIST:
|
||||
case GS_TRIANGLESTRIP:
|
||||
case GS_TRIANGLEFAN:
|
||||
case GS_SPRITE:
|
||||
test |= pmin.ceil() == pmax.ceil();
|
||||
break;
|
||||
}
|
||||
|
||||
if(test.mask() & 3)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_vtrace.min.p = m_vtrace.min.p.minv(pmin);
|
||||
m_vtrace.max.p = m_vtrace.max.p.maxv(pmax);
|
||||
|
||||
switch(prim)
|
||||
{
|
||||
case GS_POINTLIST:
|
||||
if(tme) m_vtrace.min.t = m_vtrace.min.t.minv(v[0].t);
|
||||
if(tme) m_vtrace.max.t = m_vtrace.max.t.maxv(v[0].t);
|
||||
m_vtrace.min.c = m_vtrace.min.c.minv(v[0].c);
|
||||
m_vtrace.max.c = m_vtrace.max.c.maxv(v[0].c);
|
||||
break;
|
||||
case GS_LINELIST:
|
||||
case GS_LINESTRIP:
|
||||
if(PRIM->IIP == 0) {v[0].c = v[1].c;}
|
||||
if(tme) m_vtrace.min.t = m_vtrace.min.t.minv(v[0].t).minv(v[1].t);
|
||||
if(tme) m_vtrace.max.t = m_vtrace.max.t.maxv(v[0].t).maxv(v[1].t);
|
||||
m_vtrace.min.c = m_vtrace.min.c.minv(v[0].c).minv(v[1].c);
|
||||
m_vtrace.max.c = m_vtrace.max.c.maxv(v[0].c).maxv(v[1].c);
|
||||
break;
|
||||
case GS_TRIANGLELIST:
|
||||
case GS_TRIANGLESTRIP:
|
||||
case GS_TRIANGLEFAN:
|
||||
if(PRIM->IIP == 0) {v[0].c = v[2].c; v[1].c = v[2].c;}
|
||||
if(tme) m_vtrace.min.t = m_vtrace.min.t.minv(v[0].t).minv(v[1].t.minv(v[2].t));
|
||||
if(tme) m_vtrace.max.t = m_vtrace.max.t.maxv(v[0].t).maxv(v[1].t.maxv(v[2].t));
|
||||
m_vtrace.min.c = m_vtrace.min.c.minv(v[0].c).minv(v[1].c.minv(v[2].c));
|
||||
m_vtrace.max.c = m_vtrace.max.c.maxv(v[0].c).maxv(v[1].c.maxv(v[2].c));
|
||||
break;
|
||||
case GS_SPRITE:
|
||||
if(tme) m_vtrace.min.t = m_vtrace.min.t.minv(v[0].t).minv(v[1].t);
|
||||
if(tme) m_vtrace.max.t = m_vtrace.max.t.maxv(v[0].t).maxv(v[1].t);
|
||||
m_vtrace.min.c = m_vtrace.min.c.minv(v[1].c);
|
||||
m_vtrace.max.c = m_vtrace.max.c.maxv(v[1].c);
|
||||
break;
|
||||
}
|
||||
|
||||
m_count += count;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -34,6 +34,7 @@ GSState::GSState(BYTE* base, bool mt, void (*irq)(), int nloophack)
|
||||
, m_vprim(1)
|
||||
, m_version(5)
|
||||
, m_frameskip(0)
|
||||
, m_vkf(NULL)
|
||||
{
|
||||
m_sssize = 0;
|
||||
|
||||
@@ -516,6 +517,8 @@ void GSState::GIFRegHandlerPRIM(GIFReg* r)
|
||||
|
||||
m_context = &m_env.CTXT[PRIM->CTXT];
|
||||
|
||||
UpdateVertexKick();
|
||||
|
||||
ResetPrim();
|
||||
}
|
||||
|
||||
@@ -649,12 +652,14 @@ template<int i> void GSState::GIFRegHandlerTEX2(GIFReg* r)
|
||||
|
||||
template<int i> void GSState::GIFRegHandlerXYOFFSET(GIFReg* r)
|
||||
{
|
||||
if(!(m_env.CTXT[i].XYOFFSET == (GSVector4i)r->XYOFFSET).alltrue())
|
||||
GSVector4i o = (GSVector4i)r->XYOFFSET & GSVector4i::x0000ffff();
|
||||
|
||||
if(!(m_env.CTXT[i].XYOFFSET == o).alltrue())
|
||||
{
|
||||
Flush();
|
||||
}
|
||||
|
||||
m_env.CTXT[i].XYOFFSET = (GSVector4i)r->XYOFFSET;
|
||||
m_env.CTXT[i].XYOFFSET = o;
|
||||
|
||||
m_env.CTXT[i].UpdateScissor();
|
||||
}
|
||||
@@ -673,6 +678,8 @@ void GSState::GIFRegHandlerPRMODECONT(GIFReg* r)
|
||||
if(PRIM->PRIM == 7) TRACE(_T("Invalid PRMODECONT/PRIM\n"));
|
||||
|
||||
m_context = &m_env.CTXT[PRIM->CTXT];
|
||||
|
||||
UpdateVertexKick();
|
||||
}
|
||||
|
||||
void GSState::GIFRegHandlerPRMODE(GIFReg* r)
|
||||
@@ -687,6 +694,8 @@ void GSState::GIFRegHandlerPRMODE(GIFReg* r)
|
||||
m_env.PRMODE._PRIM = _PRIM;
|
||||
|
||||
m_context = &m_env.CTXT[PRIM->CTXT];
|
||||
|
||||
UpdateVertexKick();
|
||||
}
|
||||
|
||||
void GSState::GIFRegHandlerTEXCLUT(GIFReg* r)
|
||||
@@ -956,9 +965,9 @@ void GSState::GIFRegHandlerTRXDIR(GIFReg* r)
|
||||
|
||||
void GSState::GIFRegHandlerHWREG(GIFReg* r)
|
||||
{
|
||||
// TODO
|
||||
ASSERT(m_env.TRXDIR.XDIR == 0); // host => local
|
||||
|
||||
ASSERT(0);
|
||||
Write((BYTE*)r, 8); // hunting ground
|
||||
}
|
||||
|
||||
void GSState::GIFRegHandlerSIGNAL(GIFReg* r)
|
||||
@@ -1221,7 +1230,7 @@ template<int index> void GSState::Transfer(BYTE* mem, UINT32 size)
|
||||
|
||||
if(path.tag.PRE)
|
||||
{
|
||||
ASSERT(path.tag.FLG != GIF_FLG_IMAGE); // kingdom hearts, ffxii, tales of abyss
|
||||
ASSERT(path.tag.FLG != GIF_FLG_IMAGE); // kingdom hearts, ffxii, tales of abyss, berserk
|
||||
|
||||
if((path.tag.FLG & 2) == 0)
|
||||
{
|
||||
@@ -1530,6 +1539,9 @@ int GSState::Defrost(const GSFreezeData* fd)
|
||||
ReadState(&m_env.CTXT[i].FRAME, data);
|
||||
ReadState(&m_env.CTXT[i].ZBUF, data);
|
||||
|
||||
m_env.CTXT[i].XYOFFSET.OFX &= 0xffff;
|
||||
m_env.CTXT[i].XYOFFSET.OFY &= 0xffff;
|
||||
|
||||
if(version <= 4)
|
||||
{
|
||||
data += sizeof(DWORD) * 7; // skip
|
||||
@@ -1559,6 +1571,8 @@ int GSState::Defrost(const GSFreezeData* fd)
|
||||
|
||||
m_context = &m_env.CTXT[PRIM->CTXT];
|
||||
|
||||
UpdateVertexKick();
|
||||
|
||||
m_env.CTXT[0].UpdateScissor();
|
||||
m_env.CTXT[1].UpdateScissor();
|
||||
|
||||
|
||||
@@ -125,13 +125,59 @@ class GSState : public GSAlignedClass<16>
|
||||
protected:
|
||||
bool IsBadFrame(int& skip);
|
||||
|
||||
typedef void (GSState::*VertexKickHandler)(bool skip);
|
||||
typedef void (GSState::*VertexKickPtr)(bool skip);
|
||||
|
||||
VertexKickHandler m_fpVertexKickHandlers[8];
|
||||
VertexKickPtr m_vk[8][2][2];
|
||||
VertexKickPtr m_vkf;
|
||||
|
||||
template<class T> void InitVertexKick()
|
||||
{
|
||||
m_vk[GS_POINTLIST][0][0] = (VertexKickPtr)&T::VertexKick<GS_POINTLIST, 0, 0>;
|
||||
m_vk[GS_POINTLIST][0][1] = (VertexKickPtr)&T::VertexKick<GS_POINTLIST, 0, 0>;
|
||||
m_vk[GS_POINTLIST][1][0] = (VertexKickPtr)&T::VertexKick<GS_POINTLIST, 1, 0>;
|
||||
m_vk[GS_POINTLIST][1][1] = (VertexKickPtr)&T::VertexKick<GS_POINTLIST, 1, 1>;
|
||||
|
||||
m_vk[GS_LINELIST][0][0] = (VertexKickPtr)&T::VertexKick<GS_LINELIST, 0, 0>;
|
||||
m_vk[GS_LINELIST][0][1] = (VertexKickPtr)&T::VertexKick<GS_LINELIST, 0, 0>;
|
||||
m_vk[GS_LINELIST][1][0] = (VertexKickPtr)&T::VertexKick<GS_LINELIST, 1, 0>;
|
||||
m_vk[GS_LINELIST][1][1] = (VertexKickPtr)&T::VertexKick<GS_LINELIST, 1, 1>;
|
||||
|
||||
m_vk[GS_LINESTRIP][0][0] = (VertexKickPtr)&T::VertexKick<GS_LINESTRIP, 0, 0>;
|
||||
m_vk[GS_LINESTRIP][0][1] = (VertexKickPtr)&T::VertexKick<GS_LINESTRIP, 0, 0>;
|
||||
m_vk[GS_LINESTRIP][1][0] = (VertexKickPtr)&T::VertexKick<GS_LINESTRIP, 1, 0>;
|
||||
m_vk[GS_LINESTRIP][1][1] = (VertexKickPtr)&T::VertexKick<GS_LINESTRIP, 1, 1>;
|
||||
|
||||
m_vk[GS_TRIANGLELIST][0][0] = (VertexKickPtr)&T::VertexKick<GS_TRIANGLELIST, 0, 0>;
|
||||
m_vk[GS_TRIANGLELIST][0][1] = (VertexKickPtr)&T::VertexKick<GS_TRIANGLELIST, 0, 0>;
|
||||
m_vk[GS_TRIANGLELIST][1][0] = (VertexKickPtr)&T::VertexKick<GS_TRIANGLELIST, 1, 0>;
|
||||
m_vk[GS_TRIANGLELIST][1][1] = (VertexKickPtr)&T::VertexKick<GS_TRIANGLELIST, 1, 1>;
|
||||
|
||||
m_vk[GS_TRIANGLESTRIP][0][0] = (VertexKickPtr)&T::VertexKick<GS_TRIANGLESTRIP, 0, 0>;
|
||||
m_vk[GS_TRIANGLESTRIP][0][1] = (VertexKickPtr)&T::VertexKick<GS_TRIANGLESTRIP, 0, 0>;
|
||||
m_vk[GS_TRIANGLESTRIP][1][0] = (VertexKickPtr)&T::VertexKick<GS_TRIANGLESTRIP, 1, 0>;
|
||||
m_vk[GS_TRIANGLESTRIP][1][1] = (VertexKickPtr)&T::VertexKick<GS_TRIANGLESTRIP, 1, 1>;
|
||||
|
||||
m_vk[GS_TRIANGLEFAN][0][0] = (VertexKickPtr)&T::VertexKick<GS_TRIANGLEFAN, 0, 0>;
|
||||
m_vk[GS_TRIANGLEFAN][0][1] = (VertexKickPtr)&T::VertexKick<GS_TRIANGLEFAN, 0, 0>;
|
||||
m_vk[GS_TRIANGLEFAN][1][0] = (VertexKickPtr)&T::VertexKick<GS_TRIANGLEFAN, 1, 0>;
|
||||
m_vk[GS_TRIANGLEFAN][1][1] = (VertexKickPtr)&T::VertexKick<GS_TRIANGLEFAN, 1, 1>;
|
||||
|
||||
m_vk[GS_SPRITE][0][0] = (VertexKickPtr)&T::VertexKick<GS_SPRITE, 0, 0>;
|
||||
m_vk[GS_SPRITE][0][1] = (VertexKickPtr)&T::VertexKick<GS_SPRITE, 0, 0>;
|
||||
m_vk[GS_SPRITE][1][0] = (VertexKickPtr)&T::VertexKick<GS_SPRITE, 1, 0>;
|
||||
m_vk[GS_SPRITE][1][1] = (VertexKickPtr)&T::VertexKick<GS_SPRITE, 1, 1>;
|
||||
}
|
||||
|
||||
void UpdateVertexKick()
|
||||
{
|
||||
m_vkf = m_vk[PRIM->PRIM][PRIM->TME][PRIM->FST];
|
||||
|
||||
ASSERT(m_vkf != NULL);
|
||||
}
|
||||
|
||||
void VertexKick(bool skip)
|
||||
{
|
||||
(this->*m_fpVertexKickHandlers[PRIM->PRIM])(skip);
|
||||
(this->*m_vkf)(skip);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Reference in New Issue
Block a user