mirror of https://github.com/PCSX2/pcsx2.git
vif: improve block compilation management
Safety: * check remaining space before compilation * clear hash if recompiler is reset Perf: * don't research the hash after a miss * reduce branching in Unpack/ExecuteUnpack Note: a potential speed optimization for dVifsetVUptr Precompute the length and store in the cache. However it need 2B on the nVifBlock struct. Maybe we can compact cl/wl. Or merge aligned with upkType (if some bits are useless)
This commit is contained in:
parent
b0b5c27fec
commit
3dc7dc0cdc
|
@ -22,6 +22,14 @@
|
||||||
#include "MTVU.h"
|
#include "MTVU.h"
|
||||||
#include "Utilities/Perf.h"
|
#include "Utilities/Perf.h"
|
||||||
|
|
||||||
|
static void recReset(int idx) {
|
||||||
|
nVif[idx].vifBlocks->clear();
|
||||||
|
|
||||||
|
nVif[idx].recReserve->Reset();
|
||||||
|
|
||||||
|
nVif[idx].recWritePtr = nVif[idx].recReserve->GetPtr();
|
||||||
|
}
|
||||||
|
|
||||||
void dVifReserve(int idx) {
|
void dVifReserve(int idx) {
|
||||||
if(!nVif[idx].recReserve)
|
if(!nVif[idx].recReserve)
|
||||||
nVif[idx].recReserve = new RecompiledCodeReserve(pxsFmt(L"VIF%u Unpack Recompiler Cache", idx), _8mb);
|
nVif[idx].recReserve = new RecompiledCodeReserve(pxsFmt(L"VIF%u Unpack Recompiler Cache", idx), _8mb);
|
||||||
|
@ -34,12 +42,8 @@ void dVifReset(int idx) {
|
||||||
|
|
||||||
if(!nVif[idx].vifBlocks)
|
if(!nVif[idx].vifBlocks)
|
||||||
nVif[idx].vifBlocks = new HashBucket<_tParams>();
|
nVif[idx].vifBlocks = new HashBucket<_tParams>();
|
||||||
else
|
|
||||||
nVif[idx].vifBlocks->clear();
|
|
||||||
|
|
||||||
nVif[idx].recReserve->Reset();
|
recReset(idx);
|
||||||
|
|
||||||
nVif[idx].recWritePtr = nVif[idx].recReserve->GetPtr();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void dVifClose(int idx) {
|
void dVifClose(int idx) {
|
||||||
|
@ -198,6 +202,7 @@ void VifUnpackSSE_Dynarec::ModUnpack( int upknum, bool PostOp )
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VifUnpackSSE_Dynarec::CompileRoutine() {
|
void VifUnpackSSE_Dynarec::CompileRoutine() {
|
||||||
const int upkNum = vB.upkType & 0xf;
|
const int upkNum = vB.upkType & 0xf;
|
||||||
const u8& vift = nVifT[upkNum];
|
const u8& vift = nVifT[upkNum];
|
||||||
|
@ -283,35 +288,47 @@ _vifT static __fi u8* dVifsetVUptr(uint cl, uint wl, bool isFill) {
|
||||||
return NULL; // Fall Back to Interpreters which have wrap-around logic
|
return NULL; // Fall Back to Interpreters which have wrap-around logic
|
||||||
}
|
}
|
||||||
|
|
||||||
// [TODO] : Finish implementing support for VIF's growable recBlocks buffer. Currently
|
_vifT static __ri void dVifExecuteUnpack(const u8* data, uptr x86, bool isFill)
|
||||||
// it clears the buffer only.
|
{
|
||||||
static __fi void dVifRecLimit(int idx) {
|
VIFregisters& vifRegs = MTVU_VifXRegs;
|
||||||
if (nVif[idx].recWritePtr > (nVif[idx].recReserve->GetPtrEnd() - _256kb)) {
|
|
||||||
DevCon.WriteLn(L"nVif Recompiler Cache Reset! [%ls > %ls]",
|
if (u8* dest = dVifsetVUptr<idx>(vifRegs.cycle.cl, vifRegs.cycle.wl, isFill)) {
|
||||||
pxsPtr(nVif[idx].recWritePtr), pxsPtr(nVif[idx].recReserve->GetPtrEnd())
|
//DevCon.WriteLn("Running Recompiled Block!");
|
||||||
);
|
((nVifrecCall)x86)((uptr)dest, (uptr)data);
|
||||||
nVif[idx].recReserve->Reset();
|
} else {
|
||||||
nVif[idx].recWritePtr = nVif[idx].recReserve->GetPtr();
|
VIF_LOG("Running Interpreter Block");
|
||||||
|
_nVifUnpack(idx, data, vifRegs.mode, isFill);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_vifT static __ri bool dVifExecuteUnpack(const u8* data, bool isFill)
|
_vifT __fi uptr dVifCompile(nVifBlock& key) {
|
||||||
{
|
nVifStruct& v = nVif[idx];
|
||||||
nVifStruct& v = nVif[idx];
|
nVifBlock* block = v.vifBlocks->find(&key);
|
||||||
VIFregisters& vifRegs = MTVU_VifXRegs;
|
|
||||||
|
|
||||||
if (nVifBlock* b = v.vifBlocks->find(&v.block)) {
|
// Cache hit
|
||||||
if (u8* dest = dVifsetVUptr<idx>(vifRegs.cycle.cl, vifRegs.cycle.wl, isFill)) {
|
if (likely(block != nullptr))
|
||||||
//DevCon.WriteLn("Running Recompiled Block!");
|
return block->startPtr;
|
||||||
((nVifrecCall)b->startPtr)((uptr)dest, (uptr)data);
|
|
||||||
}
|
// Check size before the compilation
|
||||||
else {
|
if (v.recWritePtr > (v.recReserve->GetPtrEnd() - _256kb)) {
|
||||||
VIF_LOG("Running Interpreter Block");
|
DevCon.WriteLn(L"nVif Recompiler Cache Reset! [%ls > %ls]",
|
||||||
_nVifUnpack(idx, data, vifRegs.mode, isFill);
|
pxsPtr(v.recWritePtr), pxsPtr(v.recReserve->GetPtrEnd())
|
||||||
}
|
);
|
||||||
return true;
|
recReset(idx);
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
|
// Compile the block now
|
||||||
|
xSetPtr(v.recWritePtr);
|
||||||
|
|
||||||
|
key.startPtr = (uptr)xGetAlignedCallTarget();
|
||||||
|
v.vifBlocks->add(key);
|
||||||
|
|
||||||
|
VifUnpackSSE_Dynarec(v, key).CompileRoutine();
|
||||||
|
|
||||||
|
Perf::vif.map((uptr)v.recWritePtr, xGetPtr() - v.recWritePtr, v.block.upkType /* FIXME ideally a key*/);
|
||||||
|
v.recWritePtr = xGetPtr();
|
||||||
|
|
||||||
|
return key.startPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
_vifT __fi void dVifUnpack(const u8* data, bool isFill) {
|
_vifT __fi void dVifUnpack(const u8* data, bool isFill) {
|
||||||
|
@ -344,21 +361,9 @@ _vifT __fi void dVifUnpack(const u8* data, bool isFill) {
|
||||||
// doMask >> 4, doMask ? wxsFormat( L"0x%08x", v.Block.mask ).c_str() : L"ignored"
|
// doMask >> 4, doMask ? wxsFormat( L"0x%08x", v.Block.mask ).c_str() : L"ignored"
|
||||||
//);
|
//);
|
||||||
|
|
||||||
if (dVifExecuteUnpack<idx>(data, isFill)) return;
|
uptr x86 = dVifCompile<idx>(v.block);
|
||||||
|
|
||||||
xSetPtr(v.recWritePtr);
|
dVifExecuteUnpack<idx>(data, x86, isFill);
|
||||||
v.block.startPtr = (uptr)xGetAlignedCallTarget();
|
|
||||||
v.vifBlocks->add(v.block);
|
|
||||||
VifUnpackSSE_Dynarec(v, v.block).CompileRoutine();
|
|
||||||
|
|
||||||
Perf::vif.map((uptr)v.recWritePtr, xGetPtr() - v.recWritePtr, v.block.upkType /* FIXME ideally a key*/);
|
|
||||||
nVif[idx].recWritePtr = xGetPtr();
|
|
||||||
|
|
||||||
dVifRecLimit(idx);
|
|
||||||
|
|
||||||
// Run the block we just compiled. Various conditions may force us to still use
|
|
||||||
// the interpreter unpacker though, so a recursive call is the safest way here...
|
|
||||||
dVifExecuteUnpack<idx>(data, isFill);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template void dVifUnpack<0>(const u8* data, bool isFill);
|
template void dVifUnpack<0>(const u8* data, bool isFill);
|
||||||
|
|
Loading…
Reference in New Issue