GregMiscellaneous: zzogl-pg:

* use a size of 4 for the gsvertex array (allow compiler to optimize a % into an and)
* Reuse previous computed vertex for _strip & _fan primitives


git-svn-id: http://pcsx2.googlecode.com/svn/branches/GregMiscellaneous@3973 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
gregory.hainaut@gmail.com 2010-10-26 21:14:15 +00:00
parent 9f2e92f31b
commit 3c6dd04c19
6 changed files with 88 additions and 38 deletions

View File

@ -471,14 +471,16 @@ typedef struct
typedef struct typedef struct
{ {
Vertex gsvertex[3]; Vertex gsvertex[4]; // circular buffer that contains the vertex
u32 rgba; Vertex gsTriFanVertex; // Base of triangle fan primitive vertex
u32 rgba; // global color for flat shading texture
float q; float q;
Vertex vertexregs; Vertex vertexregs; // accumulation buffer that collect current vertex data
int primC; // number of verts current storing int primC; // number of verts current storing
int primIndex; // current prim index int primIndex; // current prim index
int nTriFanVert; int nTriFanVert; // remember the index of the base of triangle fan
int new_tri_fan; // 1 if we process a new triangle fan primitive. 0 otherwise
int prac; int prac;
int dthe; int dthe;
@ -512,12 +514,14 @@ typedef struct
GSClut clut_buffer; GSClut clut_buffer;
int primNext(int inc = 1) int primNext(int inc = 1)
{ {
// Note: ARRAY_SIZE(gsvertex) == 2^n => modulo is replaced by an and instruction
return ((primIndex + inc) % ARRAY_SIZE(gsvertex)); return ((primIndex + inc) % ARRAY_SIZE(gsvertex));
} }
int primPrev(int dec = 1) int primPrev(int dec = 1)
{ {
// Note: assert( dec <= ARRAY_SIZE(gsvertex) ); // Note: assert( dec <= ARRAY_SIZE(gsvertex) );
// Note: ARRAY_SIZE(gsvertex) == 2^n => modulo is replaced by an and instruction
return ((primIndex + (ARRAY_SIZE(gsvertex) - dec)) % ARRAY_SIZE(gsvertex)); return ((primIndex + (ARRAY_SIZE(gsvertex) - dec)) % ARRAY_SIZE(gsvertex));
} }
@ -535,7 +539,12 @@ typedef struct
vertexregs.y = y; vertexregs.y = y;
vertexregs.z = z; vertexregs.z = z;
vertexregs.f = f; vertexregs.f = f;
gsvertex[primIndex] = vertexregs; if (likely(!new_tri_fan)) {
gsvertex[primIndex] = vertexregs;
} else {
gsTriFanVertex = vertexregs;
new_tri_fan = false;
}
} }
inline void add_vertex(u16 x, u16 y, u32 z) inline void add_vertex(u16 x, u16 y, u32 z)
@ -543,7 +552,12 @@ typedef struct
vertexregs.x = x; vertexregs.x = x;
vertexregs.y = y; vertexregs.y = y;
vertexregs.z = z; vertexregs.z = z;
gsvertex[primIndex] = vertexregs; if (likely(!new_tri_fan)) {
gsvertex[primIndex] = vertexregs;
} else {
gsTriFanVertex = vertexregs;
new_tri_fan = false;
}
} }
} GSinternal; } GSinternal;

View File

@ -309,7 +309,6 @@ void CALLBACK GSreset()
gs.prac = 1; gs.prac = 1;
prim = &gs._prim[0]; prim = &gs._prim[0];
gs.nTriFanVert = -1;
gs.imageTransfer = -1; gs.imageTransfer = -1;
gs.q = 1; gs.q = 1;
} }
@ -324,7 +323,6 @@ void CALLBACK GSgifSoftReset(u32 mask)
gs.imageTransfer = -1; gs.imageTransfer = -1;
gs.q = 1; gs.q = 1;
gs.nTriFanVert = -1;
} }
s32 CALLBACK GSinit() s32 CALLBACK GSinit()

View File

@ -305,12 +305,14 @@ void __gifCall GIFRegHandlerPRIM(const u32 *data)
gs.primC = 0; gs.primC = 0;
prim->prim = (data[0]) & 0x7; u16 prim_type = (data[0]) & 0x7;
gs._prim[0].prim = (data[0]) & 0x7; prim->prim = prim_type;
gs._prim[1].prim = (data[0]) & 0x7; gs._prim[0].prim = prim_type;
gs._prim[1].prim = prim_type;
gs._prim[1]._val = (data[0] >> 3) & 0xff; gs._prim[1]._val = (data[0] >> 3) & 0xff;
gs.nTriFanVert = gs.primIndex; gs.new_tri_fan = !(prim_type ^ PRIM_TRIANGLE_FAN);
ZZKick->DirtyValidPrevPrim();
Prim(); Prim();
} }

View File

@ -57,18 +57,11 @@ void __forceinline Kick::KickVertex(bool adc)
if (++gs.primC >= (int)g_primmult[prim->prim]) if (++gs.primC >= (int)g_primmult[prim->prim])
{ {
if (!adc && NoHighlights(prim->ctxt)) DrawPrim(prim->prim); if (!adc && NoHighlights(prim->ctxt)) DrawPrim(prim->prim);
else DirtyValidPrevPrim();
gs.primC -= g_primsub[prim->prim]; gs.primC -= g_primsub[prim->prim];
gs.primIndex = gs.primNext();
if (prim->prim == 5)
{
/* tri fans need special processing */
if (gs.nTriFanVert == gs.primIndex) gs.primIndex = gs.primNext();
} }
} else { gs.primIndex = gs.primNext();
gs.primIndex = gs.primNext();
}
} }
template<bool DO_Z_FOG> template<bool DO_Z_FOG>
@ -111,7 +104,7 @@ void Kick::Set_Vertex(VertexGPU *p, Vertex & gsvertex)
__forceinline void Kick::Output_Vertex(VertexGPU vert, u32 id) __forceinline void Kick::Output_Vertex(VertexGPU vert, u32 id)
{ {
#ifdef WRITE_PRIM_LOGS #ifdef WRITE_PRIM_LOGS
ZZLog::Prim_Log("%c%d(%d): xyzf=(%4d,%4d,0x%x,%3d), rgba=0x%8.8x, stq = (%2.5f,%2.5f,%2.5f)\n", ZZLog::Prim_Log("%c%d(%d): xyzf=(%4d,%4d,0x%x,%3d), rgba=0x%8.8x, stq = (%2.5f,%2.5f,%2.5f)",
id == 0 ? '*' : ' ', id, prim->prim, vert.x / 8, vert.y / 8, vert.z, vert.f / 128, id == 0 ? '*' : ' ', id, prim->prim, vert.x / 8, vert.y / 8, vert.z, vert.f / 128,
vert.rgba, Clamp(vert.s, -10, 10), Clamp(vert.t, -10, 10), Clamp(vert.q, -10, 10)); vert.rgba, Clamp(vert.s, -10, 10), Clamp(vert.t, -10, 10), Clamp(vert.q, -10, 10));
#endif #endif
@ -140,35 +133,70 @@ void Kick::DrawPrim(u32 prim_type)
u32 last; u32 last;
switch(prim_type) { switch(prim_type) {
case PRIM_POINT: case PRIM_POINT:
assert(gs.primC >= 1);
Set_Vertex<true>(&p[0], gs.gsvertex[gs.primIndex]); Set_Vertex<true>(&p[0], gs.gsvertex[gs.primIndex]);
curvb.nCount ++; curvb.nCount ++;
break; break;
case PRIM_LINE: case PRIM_LINE:
case PRIM_LINE_STRIP:
assert(gs.primC >= 2);
Set_Vertex<true>(&p[0], gs.gsvertex[gs.primPrev()]); Set_Vertex<true>(&p[0], gs.gsvertex[gs.primPrev()]);
Set_Vertex<true>(&p[1], gs.gsvertex[gs.primIndex]); Set_Vertex<true>(&p[1], gs.gsvertex[gs.primIndex]);
curvb.nCount += 2; curvb.nCount += 2;
break; break;
case PRIM_TRIANGLE: case PRIM_LINE_STRIP:
case PRIM_TRIANGLE_STRIP: if (likely(ValidPrevPrim)) {
case PRIM_TRIANGLE_FAN: assert(curvb.nCount >= 1);
assert(gs.primC >= 3); p[0] = p[-1];
} else {
Set_Vertex<true>(&p[0], gs.gsvertex[gs.primPrev()]);
ValidPrevPrim = true;
}
Set_Vertex<true>(&p[0], gs.gsvertex[0]); Set_Vertex<true>(&p[1], gs.gsvertex[gs.primIndex]);
Set_Vertex<true>(&p[1], gs.gsvertex[1]); curvb.nCount += 2;
Set_Vertex<true>(&p[2], gs.gsvertex[2]); break;
case PRIM_TRIANGLE:
Set_Vertex<true>(&p[0], gs.gsvertex[gs.primPrev(2)]);
Set_Vertex<true>(&p[1], gs.gsvertex[gs.primPrev()]);
Set_Vertex<true>(&p[2], gs.gsvertex[gs.primIndex]);
curvb.nCount += 3;
break;
case PRIM_TRIANGLE_STRIP:
if (likely(ValidPrevPrim)) {
assert(curvb.nCount >= 2);
p[0] = p[-2];
p[1] = p[-1];
} else {
Set_Vertex<true>(&p[0], gs.gsvertex[gs.primPrev(2)]);
Set_Vertex<true>(&p[1], gs.gsvertex[gs.primPrev()]);
ValidPrevPrim = true;
}
Set_Vertex<true>(&p[2], gs.gsvertex[gs.primIndex]);
curvb.nCount += 3;
break;
case PRIM_TRIANGLE_FAN:
if (likely(ValidPrevPrim)) {
assert(curvb.nCount >= 2);
VertexGPU* TriFanVert = curvb.pBufferData + gs.nTriFanVert;
p[0] = TriFanVert[0];
p[1] = p[-1];
} else {
Set_Vertex<true>(&p[0], gs.gsTriFanVertex);
Set_Vertex<true>(&p[1], gs.gsvertex[gs.primPrev(1)]);
ValidPrevPrim = true;
// Remenber the base for future processing
gs.nTriFanVert = curvb.nCount;
}
Set_Vertex<true>(&p[2], gs.gsvertex[gs.primIndex]);
curvb.nCount += 3; curvb.nCount += 3;
break; break;
case PRIM_SPRITE: case PRIM_SPRITE:
assert(gs.primC >= 2);
prev = gs.primPrev(); prev = gs.primPrev();
last = gs.primIndex; last = gs.primIndex;
@ -206,17 +234,20 @@ void Kick::DrawPrim(u32 prim_type)
default: break; default: break;
} }
// Print DEBUG info // Print DEBUG info and code assertion
switch(prim_type) { switch(prim_type) {
case PRIM_TRIANGLE: case PRIM_TRIANGLE:
case PRIM_TRIANGLE_STRIP: case PRIM_TRIANGLE_STRIP:
case PRIM_TRIANGLE_FAN: case PRIM_TRIANGLE_FAN:
assert(gs.primC >= 3);
Output_Vertex(p[2],2); Output_Vertex(p[2],2);
case PRIM_LINE: case PRIM_LINE:
case PRIM_LINE_STRIP: case PRIM_LINE_STRIP:
case PRIM_SPRITE: case PRIM_SPRITE:
assert(gs.primC >= 2);
Output_Vertex(p[1],1); Output_Vertex(p[1],1);
case PRIM_POINT: case PRIM_POINT:
assert(gs.primC >= 1);
Output_Vertex(p[0],0); Output_Vertex(p[0],0);
default: break; default: break;
} }

View File

@ -42,12 +42,17 @@ class Kick
// template<bool DO_Z_FOG> void Set_Vertex(VertexGPU *p, int i); // template<bool DO_Z_FOG> void Set_Vertex(VertexGPU *p, int i);
template<bool DO_Z_FOG> void Set_Vertex(VertexGPU *p, Vertex &gsvertex); template<bool DO_Z_FOG> void Set_Vertex(VertexGPU *p, Vertex &gsvertex);
void Output_Vertex(VertexGPU vert, u32 id); void Output_Vertex(VertexGPU vert, u32 id);
bool ValidPrevPrim;
public: public:
Kick() { } Kick() { }
~Kick() { } ~Kick() { }
void KickVertex(bool adc); void KickVertex(bool adc);
void DrawPrim(u32 i); void DrawPrim(u32 i);
inline void DirtyValidPrevPrim() {
ValidPrevPrim = 0;
}
}; };
extern Kick* ZZKick; extern Kick* ZZKick;

View File

@ -151,7 +151,7 @@ class CMemoryTarget
int ref; int ref;
}; };
inline CMemoryTarget() : ptex(NULL), starty(0), height(0), realy(0), realheight(0), usedstamp(0), psm(0), cpsm(0), channels(0), clearminy(0), clearmaxy(0), validatecount(0), clutsize(0), clut(NULL) {} inline CMemoryTarget() : ptex(NULL), starty(0), height(0), realy(0), realheight(0), usedstamp(0), psm(0), cpsm(0), channels(0), clearminy(0), clearmaxy(0), validatecount(0), clut(NULL), clutsize(0) {}
inline CMemoryTarget(const CMemoryTarget& r) inline CMemoryTarget(const CMemoryTarget& r)
{ {