PGXP: Allocate large storage dynamically

This causes performance issues on ARM otherwise.
This commit is contained in:
Connor McLaughlin 2020-09-02 22:44:52 +10:00
parent 1b47e6e8cd
commit a2eaaf0e89
5 changed files with 83 additions and 45 deletions

View File

@ -61,6 +61,7 @@ void Initialize()
void Shutdown()
{
// GTE::Shutdown();
PGXP::Shutdown();
}
void Reset()
@ -128,6 +129,7 @@ bool DoState(StateWrapper& sw)
if (sw.IsReading())
{
ClearICache();
if (g_settings.gpu_pgxp_enable)
PGXP::Initialize();
}

View File

@ -561,6 +561,9 @@ void HostInterface::CheckForSettingsChanges(const Settings& old_settings)
CPU::CodeCache::Flush();
}
if (old_settings.gpu_pgxp_enable)
PGXP::Shutdown();
if (g_settings.gpu_pgxp_enable)
PGXP::Initialize();
}

View File

@ -20,8 +20,8 @@
#include "pgxp.h"
#include "settings.h"
#include <cmath>
#include <climits>
#include <cmath>
namespace PGXP {
// pgxp_types.h
@ -134,6 +134,26 @@ static void WriteMem(PGXP_value* value, u32 addr);
static void WriteMem16(PGXP_value* src, u32 addr);
// pgxp_gpu.h
enum : u32
{
VERTEX_CACHE_WIDTH = 0x800 * 2,
VERTEX_CACHE_HEIGHT = 0x800 * 2,
VERTEX_CACHE_SIZE = VERTEX_CACHE_WIDTH * VERTEX_CACHE_HEIGHT,
PGXP_MEM_SIZE = 3 * 2048 * 1024 / 4 // mirror 2MB in 32-bit words * 3
};
static PGXP_value* Mem = nullptr;
const unsigned int mode_init = 0;
const unsigned int mode_write = 1;
const unsigned int mode_read = 2;
const unsigned int mode_fail = 3;
unsigned int baseID = 0;
unsigned int lastID = 0;
unsigned int cacheMode = 0;
static PGXP_value* vertexCache = nullptr;
void PGXP_CacheVertex(short sx, short sy, const PGXP_value* _pVertex);
// pgxp_gte.h
@ -195,7 +215,6 @@ double f16Overflow(double in)
// pgxp_mem.c
static void PGXP_InitMem();
static PGXP_value Mem[3 * 2048 * 1024 / 4]; // mirror 2MB in 32-bit words * 3
static const u32 UserMemOffset = 0;
static const u32 ScratchOffset = 2048 * 1024 / 4;
static const u32 RegisterOffset = 2 * 2048 * 1024 / 4;
@ -203,7 +222,19 @@ static const u32 InvalidAddress = 3 * 2048 * 1024 / 4;
void PGXP_InitMem()
{
memset(Mem, 0, sizeof(Mem));
if (!Mem)
{
Mem = static_cast<PGXP_value*>(std::calloc(PGXP_MEM_SIZE, sizeof(PGXP_value)));
if (!Mem)
{
std::fprintf(stderr, "Failed to allocate PGXP memory\n");
std::abort();
}
}
else
{
std::memset(Mem, 0, sizeof(PGXP_value) * PGXP_MEM_SIZE);
}
}
u32 PGXP_ConvertAddress(u32 addr)
@ -366,8 +397,6 @@ void WriteMem16(PGXP_value* src, u32 addr)
}
// pgxp_main.c
u32 static gMode = 0;
void Initialize()
{
PGXP_InitMem();
@ -375,24 +404,19 @@ void Initialize()
PGXP_InitGTE();
}
void PGXP_SetModes(u32 modes)
void Shutdown()
{
gMode = modes;
}
u32 PGXP_GetModes()
{
return gMode;
}
void PGXP_EnableModes(u32 modes)
{
gMode |= modes;
}
void PGXP_DisableModes(u32 modes)
{
gMode = gMode & ~modes;
cacheMode = mode_init;
if (vertexCache)
{
std::free(vertexCache);
vertexCache = nullptr;
}
if (Mem)
{
std::free(Mem);
Mem = nullptr;
}
}
// pgxp_gte.c
@ -584,17 +608,6 @@ void CPU_SWC2(u32 instr, u32 rtVal, u32 addr)
/////////////////////////////////
//// Blade_Arma's Vertex Cache (CatBlade?)
/////////////////////////////////
const unsigned int mode_init = 0;
const unsigned int mode_write = 1;
const unsigned int mode_read = 2;
const unsigned int mode_fail = 3;
PGXP_value 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
@ -612,6 +625,23 @@ unsigned int IsSessionID(unsigned int vertID)
return 0;
}
static void InitPGXPVertexCache()
{
if (!vertexCache)
{
vertexCache = static_cast<PGXP_value*>(std::calloc(VERTEX_CACHE_SIZE, sizeof(PGXP_value)));
if (!vertexCache)
{
std::fprintf(stderr, "Failed to allocate PGXP vertex cache memory\n");
std::abort();
}
}
else
{
memset(vertexCache, 0x00, VERTEX_CACHE_SIZE * sizeof(PGXP_value));
}
}
void PGXP_CacheVertex(short sx, short sy, const PGXP_value* _pVertex)
{
const PGXP_value* pNewVertex = (const PGXP_value*)_pVertex;
@ -623,14 +653,14 @@ void PGXP_CacheVertex(short sx, short sy, const PGXP_value* _pVertex)
return;
}
// Initialise cache on first use
if (!vertexCache)
InitPGXPVertexCache();
// 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;
@ -640,7 +670,7 @@ void PGXP_CacheVertex(short sx, short sy, const PGXP_value* _pVertex)
if (sx >= -0x800 && sx <= 0x7ff && sy >= -0x800 && sy <= 0x7ff)
{
pOldVertex = &vertexCache[sy + 0x800][sx + 0x800];
pOldVertex = &vertexCache[(sy + 0x800) * VERTEX_CACHE_WIDTH + (sx + 0x800)];
// To avoid ambiguity there can only be one valid entry per-session
if (0) //(IsSessionID(pOldVertex->count) && (pOldVertex->value == pNewVertex->value))
@ -664,25 +694,25 @@ void PGXP_CacheVertex(short sx, short sy, const PGXP_value* _pVertex)
PGXP_value* PGXP_GetCachedVertex(short sx, short sy)
{
// if (bGteAccuracy)
if (g_settings.gpu_pgxp_vertex_cache)
{
if (cacheMode != mode_read)
{
if (cacheMode == mode_fail)
return NULL;
// Initialise cache on first use
if (cacheMode == mode_init)
memset(vertexCache, 0x00, sizeof(vertexCache));
// First vertex of read session (frame?)
cacheMode = mode_read;
}
// Initialise cache on first use
if (!vertexCache)
InitPGXPVertexCache();
if (sx >= -0x800 && sx <= 0x7ff && sy >= -0x800 && sy <= 0x7ff)
{
// Return pointer to cache entry
return &vertexCache[sy + 0x800][sx + 0x800];
return &vertexCache[(sy + 0x800) * VERTEX_CACHE_WIDTH + (sx + 0x800)];
}
}

View File

@ -24,6 +24,7 @@
namespace PGXP {
void Initialize();
void Shutdown();
// -- GTE functions
// Transforms

View File

@ -1411,6 +1411,8 @@ void CommonHostInterface::RegisterGraphicsHotkeys()
if (g_settings.gpu_pgxp_enable)
PGXP::Initialize();
else
PGXP::Shutdown();
// we need to recompile all blocks if pgxp is toggled on/off
if (g_settings.IsUsingCodeCache())