summaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
authoriCatButler <i.am.catbutler@gmail.com>2016-05-15 16:26:39 +0100
committeriCatButler <i.am.catbutler@gmail.com>2016-05-15 16:26:39 +0100
commit2a24b74c12c6d248409dc93b35edbc373d03b29c (patch)
tree94bf6d4022a5209c7713fe4b8107342839b193f7 /plugins
parentfed51208575d3b67789ded126a38c7da3b23cef0 (diff)
Implement vertex caching
- Try using Blade_Arma's vertex cache to find untracked vertices - Fix GTE_LOG - Add more logging spew - Update debug mode to track cached vertices
Diffstat (limited to 'plugins')
-rw-r--r--plugins/peopsxgl/pgxp_gpu.c164
1 files changed, 153 insertions, 11 deletions
diff --git a/plugins/peopsxgl/pgxp_gpu.c b/plugins/peopsxgl/pgxp_gpu.c
index ece50795..5cb5d5b3 100644
--- a/plugins/peopsxgl/pgxp_gpu.c
+++ b/plugins/peopsxgl/pgxp_gpu.c
@@ -41,6 +41,113 @@ typedef struct
unsigned int value;
} PGXP_vertex;
+/////////////////////////////////
+//// Blade_Arma's Vertex Cache (CatBlade?)
+/////////////////////////////////
+const unsigned int mode_init = 0;
+const unsigned int mode_write = 1;
+const unsigned int mode_read = 2;
+
+PGXP_vertex vertexCache[0x800 * 2][0x800 * 2];
+
+unsigned int baseID = 0;
+unsigned int lastID = 0;
+unsigned int cacheMode = 0;
+
+unsigned int IsSessionID(unsigned int vertID)
+{
+ // No wrapping
+ if (lastID >= baseID)
+ return (vertID >= baseID);
+
+ // If vertID is >= baseID it is pre-wrap and in session
+ if (vertID >= baseID)
+ return 1;
+
+ // vertID is < baseID, If it is <= lastID it is post-wrap and in session
+ if (vertID <= lastID)
+ return 1;
+
+ return 0;
+}
+
+void CALLBACK GPUpgxpCacheVertex(short sx, short sy, const unsigned char* _pVertex)
+{
+ const PGXP_vertex* pNewVertex = (const PGXP_vertex*)_pVertex;
+ PGXP_vertex* pOldVertex = NULL;
+
+ if (!pNewVertex)
+ return;
+
+ //if (bGteAccuracy)
+ {
+ if (cacheMode != mode_write)
+ {
+ // Initialise cache on first use
+ if (cacheMode == mode_init)
+ memset(vertexCache, 0x00, sizeof(vertexCache));
+
+ // First vertex of write session (frame?)
+ cacheMode = mode_write;
+ baseID = pNewVertex->count;
+ }
+
+ lastID = pNewVertex->count;
+
+ if (sx >= -0x800 && sx <= 0x7ff &&
+ sy >= -0x800 && sy <= 0x7ff)
+ {
+ pOldVertex = &vertexCache[sy + 0x800][sx + 0x800];
+
+ // To avoid ambiguity there can only be one valid entry per-session
+ if (IsSessionID(pOldVertex->count) && (pOldVertex->value == pNewVertex->value))
+ {
+ // check to ensure this isn't identical
+ if ((fabsf(pOldVertex->x - pNewVertex->x) > 0.1f) ||
+ (fabsf(pOldVertex->y - pNewVertex->y) > 0.1f) ||
+ (fabsf(pOldVertex->z - pNewVertex->z) > 0.1f))
+ {
+ pOldVertex->valid = 5;
+ return;
+ }
+ }
+
+ // Write vertex into cache
+ *pOldVertex = *pNewVertex;
+ }
+ }
+}
+
+PGXP_vertex* PGXP_GetCachedVertex(short sx, short sy)
+{
+ //if (bGteAccuracy)
+ {
+ if (cacheMode != mode_read)
+ {
+ // Initialise cache on first use
+ if (cacheMode == mode_init)
+ memset(vertexCache, 0x00, sizeof(vertexCache));
+
+ // First vertex of read session (frame?)
+ cacheMode = mode_read;
+ }
+
+ if (sx >= -0x800 && sx <= 0x7ff &&
+ sy >= -0x800 && sy <= 0x7ff)
+ {
+ // Return pointer to cache entry
+ return &vertexCache[sy + 0x800][sx + 0x800];
+ }
+ }
+
+ return NULL;
+}
+
+
+/////////////////////////////////
+//// PGXP Implementation
+/////////////////////////////////
+
const unsigned int primStrideTable[] = { 1, 2, 1, 2, 2, 3, 2, 3, 0 };
const unsigned int primCountTable[] = { 3, 3, 4, 4, 3, 3, 4, 4, 0 };
@@ -137,7 +244,9 @@ int PGXP_GetVertices(unsigned int* addr, void* pOutput, int xOffs, int yOffs)
unsigned int count = primCountTable[primIdx]; // number of vertices
PGXP_vertex* primStart = NULL; // pointer to first vertex
char invalidVert = 0; // Number of vertices without valid PGXP values
- float w = 0; // W coordinate of transformed vertex
+
+ short* pPrimData = (short*)addr; // primitive data for cache lookups
+ PGXP_vertex* pCacheVert = NULL;
if (PGXP_Mem == NULL)
return 0;
@@ -148,6 +257,7 @@ int PGXP_GetVertices(unsigned int* addr, void* pOutput, int xOffs, int yOffs)
// Offset to start of primitive
primStart = &PGXP_Mem[currentAddr + 1];
+ pPrimData += 2;
// Find any invalid vertices
for (unsigned i = 0; i < count; ++i)
@@ -158,24 +268,48 @@ int PGXP_GetVertices(unsigned int* addr, void* pOutput, int xOffs, int yOffs)
for (unsigned i = 0; i < count; ++i)
{
- w = primStart[stride * i].z;
- // If there are any invalid vertices set all w values to 1
- // iCB: Could use plane equation to find w for single invalid vertex in a quad
- if (invalidVert > 0)
- w = 1;
-
if (primStart[stride * i].valid)
{
pVertex[i].x = (primStart[stride * i].x + xOffs);
pVertex[i].y = (primStart[stride * i].y + yOffs);
pVertex[i].z = 0.95f;
- pVertex[i].w = w;
+ pVertex[i].w = primStart[stride * i].z;
pVertex[i].PGXP_flag = 1;
}
else
+ {
+ // Default to low precision vertex data
pVertex[i].PGXP_flag = 2;
+
+ // Look in cache for valid vertex
+ pCacheVert = PGXP_GetCachedVertex(pPrimData[stride * i * 2], pPrimData[(stride * i * 2) + 1]);
+ if (pCacheVert)
+ {
+ if (IsSessionID(pCacheVert->count))
+ {
+ if (pCacheVert->valid == 1)
+ {
+ pVertex[i].x = (pCacheVert->x + xOffs);
+ pVertex[i].y = (pCacheVert->y + yOffs);
+ pVertex[i].z = 0.95f;
+ pVertex[i].w = pCacheVert->z;
+ pVertex[i].PGXP_flag = 3;
+ // reduce number of invalid vertices
+ invalidVert--;
+ }
+ else if(pCacheVert->valid > 1)
+ pVertex[i].PGXP_flag = 4;
+ }
+ }
+ }
}
+ // If there are any invalid vertices set all w values to 1
+ // iCB: Could use plane equation to find w for single invalid vertex in a quad
+ if (invalidVert > 0)
+ for (unsigned i = 0; i < count; ++i)
+ pVertex[i].w = 1;
+
return 1;
}
@@ -184,10 +318,14 @@ int PGXP_GetVertices(unsigned int* addr, void* pOutput, int xOffs, int yOffs)
/////////////////////////////////
unsigned int PGXP_vDebug = 0;
-const char blue[4] = { 0, 0, 255, 255 };
-const char red[4] = { 255, 0, 0, 255 };
-const char black[4] = { 0, 0, 0, 255 };
+const char red[4] = { 255, 0, 0, 255 };
+const char blue[4] = { 0, 0, 255, 255 };
+const char green[4] = { 0, 255, 0, 255 };
+
const char yellow[4] = { 255, 255, 0, 255 };
+const char magenta[4] = { 255, 0, 255, 255 };
+const char black[4] = { 0, 0, 0, 255 };
+
void CALLBACK GPUtoggleDebug(void)
{
@@ -207,6 +345,10 @@ const char* PGXP_colour(unsigned int flag)
return blue;
case 2:
return red;
+ case 3:
+ return green;
+ case 4:
+ return magenta;
default:
return black;
}