wxgui: maintenance sync with trunk.

git-svn-id: http://pcsx2.googlecode.com/svn/branches/wxgui@1604 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine 2009-08-04 13:34:52 +00:00
commit 3544bcd118
72 changed files with 1367 additions and 1247 deletions

View File

@ -118,6 +118,10 @@ extern SessionOverrideFlags g_Session;
#define EE_CONST_PROP // rec2 - enables constant propagation (faster)
// These are broken, so don't enable.
//#define PCSX2_CACHE_EMU_MEM
//#define ENABLECACHE
// Memory Card configuration, per slot.
struct McdConfig
{

View File

@ -1363,6 +1363,7 @@ extern void SSE4_PMINSD_M128_to_XMM(x86SSERegType to, uptr from);
extern void SSE4_PMAXUD_M128_to_XMM(x86SSERegType to, uptr from);
extern void SSE4_PMINUD_M128_to_XMM(x86SSERegType to, uptr from);
extern void SSE4_PMULDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from);
extern void SSE4_PTEST_XMM_to_XMM(x86SSERegType to, x86SSERegType from);
//*********************
// 3DNOW instructions *

View File

@ -334,8 +334,6 @@ emitterT void SSE2_PSHUFLW_M128_to_XMM( x86SSERegType to, uptr from, u8 imm8 )
emitterT void SSE2_PSHUFHW_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ) { xPSHUF.HW( xRegisterSSE(to), xRegisterSSE(from), imm8 ); }
emitterT void SSE2_PSHUFHW_M128_to_XMM( x86SSERegType to, uptr from, u8 imm8 ) { xPSHUF.HW( xRegisterSSE(to), (void*)from, imm8 ); }
emitterT void SSE4_PMULDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { xPMUL.DQ( xRegisterSSE(to), xRegisterSSE(from) ); }
emitterT void SSE_UNPCKLPS_M128_to_XMM( x86SSERegType to, uptr from ) { xUNPCK.LPS( xRegisterSSE(to), (void*)from ); }
emitterT void SSE_UNPCKLPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { xUNPCK.LPS( xRegisterSSE(to), xRegisterSSE(from) ); }
emitterT void SSE_UNPCKHPS_M128_to_XMM( x86SSERegType to, uptr from ) { xUNPCK.HPS( xRegisterSSE(to), (void*)from ); }
@ -360,7 +358,7 @@ emitterT void SSE2_PMADDWD_XMM_to_XMM(x86SSERegType to, x86SSERegType from) {
emitterT void SSE3_HADDPS_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { xHADD.PS( xRegisterSSE(to), xRegisterSSE(from) ); }
emitterT void SSE3_HADDPS_M128_to_XMM(x86SSERegType to, uptr from) { xHADD.PS( xRegisterSSE(to), (void*)from ); }
emitterT void SSE4_PINSRD_R32_to_XMM(x86SSERegType to, x86IntRegType from, u8 imm8) { xPINSR.D( xRegisterSSE(to), xRegister32(from), imm8 ); }
emitterT void SSE4_PINSRD_R32_to_XMM(x86SSERegType to, x86IntRegType from, u8 imm8) { xPINSR.D( xRegisterSSE(to), xRegister32(from), imm8 ); }
emitterT void SSE4_INSERTPS_XMM_to_XMM(x86SSERegType to, x86SSERegType from, u8 imm8) { xINSERTPS( xRegisterSSE(to), xRegisterSSE(from), imm8 ); }
emitterT void SSE4_EXTRACTPS_XMM_to_R32(x86IntRegType to, x86SSERegType from, u8 imm8) { xEXTRACTPS( xRegister32(to), xRegisterSSE(from), imm8 ); }
@ -374,6 +372,8 @@ emitterT void SSE4_BLENDVPS_XMM_to_XMM(x86SSERegType to, x86SSERegType from) {
emitterT void SSE4_BLENDVPS_M128_to_XMM(x86SSERegType to, uptr from) { xBLEND.VPS( xRegisterSSE(to), (void*)from ); }
emitterT void SSE4_PMOVSXDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { xPMOVSX.DQ( xRegisterSSE(to), xRegisterSSE(from) ); }
emitterT void SSE4_PMULDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { xPMUL.DQ( xRegisterSSE(to), xRegisterSSE(from) ); }
emitterT void SSE4_PTEST_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { xPTEST(xRegisterSSE(to), xRegisterSSE(from)); }
emitterT void SSE_LDMXCSR( uptr from ) { xLDMXCSR( (u32*)from ); }

View File

@ -114,7 +114,7 @@ const SimdImpl_DestRegEither<0x66,0xef> xPXOR;
// [SSE-4.1] Performs a bitwise AND of dest against src, and sets the ZF flag
// only if all bits in the result are 0. PTEST also sets the CF flag according
// to the following condition: (xmm2/m128 AND NOT xmm1) == 0;
extern const Internal::SimdImpl_DestRegSSE<0x66,0x1738> xPTEST;
const SimdImpl_DestRegSSE<0x66,0x1738> xPTEST;
const SimdImpl_Compare<SSE2_Equal> xCMPEQ;
const SimdImpl_Compare<SSE2_Less> xCMPLT;

View File

@ -43,7 +43,8 @@ void CALLBACK ISOclose()
s32 CALLBACK ISOopen(const char* pTitle)
{
//if (pTitle != NULL) strcpy(isoFileName, pTitle);
if ((pTitle != NULL) && (strlen(pTitle) > 0))
strcpy(isoFileName, pTitle);
ISOclose(); // just in case

View File

@ -26,9 +26,8 @@ _cacheS pCache[64];
namespace R5900{
namespace Interpreter
{
// fixme - this code no longer compiles if PCSX2_CACHE_EMU_MEM is defined - do we need it any more?
#ifdef PCSX2_CACHE_EMU_MEM
int getFreeCache(u32 mem, int mode, int * way) {
u8 * out;
u32 paddr;
@ -37,15 +36,16 @@ int getFreeCache(u32 mem, int mode, int * way) {
int number;
int i = (mem >> 6) & 0x3F;
paddr = memLUTR[mem >> 12];
taddr[0] = memLUTW[pCache[i].tag[0]>>12];
taddr[1] = memLUTW[pCache[i].tag[1]>>12];
paddr = getMemR(mem);
taddr[0] = getMemW(pCache[i].tag[0]);
taddr[1] = getMemW(pCache[i].tag[1]);
if (taddr[0] == paddr && (pCache[i].tag[0] & 0x20))
{
*way = 0;
return i;
}else if(taddr[1] == paddr && (pCache[i].tag[1] & 0x20))
}
else if(taddr[1] == paddr && (pCache[i].tag[1] & 0x20))
{
*way = 1;
return i;
@ -67,8 +67,6 @@ int getFreeCache(u32 mem, int mode, int * way) {
((u64*)out)[7] = ((u64*)pCache[i].data[number][3].b8._8)[1];
}
if(mode == 1)
{
pCache[i].tag[number] |= 0x40; // Set Dirty Bit if mode == write
@ -89,8 +87,10 @@ int getFreeCache(u32 mem, int mode, int * way) {
((u64*)pCache[i].data[number][3].b8._8)[0] = ((u64*)out)[6];
((u64*)pCache[i].data[number][3].b8._8)[1] = ((u64*)out)[7];
if(pCache[i].tag[number] & 0x10) pCache[i].tag[number] &= ~(0x10);
else pCache[i].tag[number] |= 0x10;
if(pCache[i].tag[number] & 0x10)
pCache[i].tag[number] &= ~(0x10);
else
pCache[i].tag[number] |= 0x10;
pCache[i].tag[number] |= 0x20;
*way = number;
@ -163,9 +163,9 @@ void CACHE() {
int index = (addr >> 6) & 0x3F;
u32 paddr[2];
int way;
u32 taddr = memLUTR[addr >> 12];
paddr[0] = memLUTW[pCache[index].tag[0] >> 12];
paddr[1] = memLUTW[pCache[index].tag[1] >> 12];
u32 taddr = getMemR(addr);
paddr[0] = getMemW(pCache[index].tag[0]);
paddr[1] = getMemW(pCache[index].tag[1]);
if(paddr[0] == taddr && (pCache[index].tag[0] & 0x20))
{
@ -199,9 +199,9 @@ void CACHE() {
int index = (addr >> 6) & 0x3F;
u32 paddr[2];
int way;
u32 taddr = memLUTW[addr >> 12];
paddr[0] = memLUTW[pCache[index].tag[0] >> 12];
paddr[1] = memLUTW[pCache[index].tag[1] >> 12];
u32 taddr = getMemW(addr);
paddr[0] = getMemW(pCache[index].tag[0]);
paddr[1] = getMemW(pCache[index].tag[1]);
if(paddr[0] == taddr && (pCache[index].tag[0] & 0x20))
{
@ -250,9 +250,9 @@ void CACHE() {
int index = (addr >> 6) & 0x3F;
u32 paddr[2];
int way;
u32 taddr = memLUTW[addr >> 12];
paddr[0] = memLUTW[pCache[index].tag[0] >> 12];
paddr[1] = memLUTW[pCache[index].tag[1] >> 12];
u32 taddr = getMemW(addr);
paddr[0] = getMemW(pCache[index].tag[0]);
paddr[1] = getMemW(pCache[index].tag[1]);
if(paddr[0] == taddr && (pCache[index].tag[0] & 0x20))
{
@ -360,7 +360,7 @@ void CACHE() {
if(pCache[index].tag[way] & 0x60) // Dirty
{
u32 paddr = memLUTW[pCache[index].tag[way] >> 12];
u32 paddr = getMemW(pCache[index].tag[way]);
char * t = (char *)(paddr);
out = (u8*)(t + (addr & 0xFC0));
((u64*)out)[0] = ((u64*)pCache[index].data[way][0].b8._8)[0];

View File

@ -45,4 +45,15 @@ void writeCache64(u32 mem, u64 value);
void writeCache128(u32 mem, u64 *value);
u8 *readCache(u32 mem);
// Fixme - these two functions do nothing, and the cache code relies on these two functions.
static __forceinline u32 getMemR(s32 mem)
{
return 0;//memLUTR[mem >> 12];
}
static __forceinline u32 getMemW(s32 mem)
{
return 0;//memLUTW[mem>>12];
}
#endif /* __CACHE_H__ */

View File

@ -41,7 +41,7 @@ enum gifstate_t
// Should be a gifstate_t rather then int, but I don't feel like possibly interfering with savestates right now.
static int gifstate = GIF_STATE_READY;
static u64 s_gstag = 0; // used for querying the last tag
//static u64 s_gstag = 0; // used for querying the last tag
// This should be a bool, as should the return value of hwDmacSrcChainWithStack.
// Next time I feel like breaking the save state, it will be. --arcum42

View File

@ -23,10 +23,15 @@
enum StartupMode
{
BootMode_Bios,
BootMode_Quick,
BootMode_Elf,
BootMode_Normal
BootMode_Normal = 0,
BootMode_Elf = 1, // not compatible with bios flag, probably
BootMode_Iso = 2,
BootMode_NoDisc = 3, // nodisc implies bios.
BootMode_Quick = 0,
BootMode_Bios = 0x10000,
BootMode_ModeMask = 0xFFFF,
};
class StartupParams

View File

@ -667,7 +667,7 @@ void psxHwWrite8(u32 add, u8 value) {
case 0x1f80380c:
{
bool flush = false;
//bool flush = false;
// Terminate lines on CR or full buffers, and ignore \n's if the string contents
// are empty (otherwise terminate on \n too!)

View File

@ -595,8 +595,8 @@ void memClearPageAddr(u32 vaddr)
vtlb_VMapUnmap(vaddr,0x1000); // -> whut ?
#ifdef FULLTLB
memLUTRK[vaddr >> 12] = 0;
memLUTWK[vaddr >> 12] = 0;
// memLUTRK[vaddr >> 12] = 0;
// memLUTWK[vaddr >> 12] = 0;
#endif
}

View File

@ -1430,6 +1430,10 @@ int OpenPlugins(const char* pTitleFilename)
{
if (!plugins_initialized)
{
// prevent a crash
if(CDVD.init == NULL)
CDVD = ISO; // CDVD_plugin;
if( InitPlugins() == -1 ) return -1;
}

View File

@ -99,7 +99,7 @@ int _getFreeXMMreg()
for (i=0; i<iREGCNT_XMM; i++) {
if (xmmregs[i].needed) continue;
if (xmmregs[i].type == XMMTYPE_GPRREG ) {
if( !(g_pCurInstInfo->regs[xmmregs[i].reg] & (EEINST_LIVE0|EEINST_LIVE1|EEINST_LIVE2)) ) {
if (!(EEINST_ISLIVEXMM(xmmregs[i].reg))) {
_freeXMMreg(i);
return i;
}
@ -144,12 +144,10 @@ int _getFreeXMMreg()
}
int _allocTempXMMreg(XMMSSEType type, int xmmreg) {
if (xmmreg == -1) {
if (xmmreg == -1)
xmmreg = _getFreeXMMreg();
}
else {
else
_freeXMMreg(xmmreg);
}
xmmregs[xmmreg].inuse = 1;
xmmregs[xmmreg].type = XMMTYPE_TEMP;

View File

@ -102,7 +102,11 @@
#define X86TYPE_VU1 0x80
#define X86_ISVI(type) ((type&~X86TYPE_VU1) == X86TYPE_VI)
//#define X86_ISVI(type) ((type&~X86TYPE_VU1) == X86TYPE_VI)
static __forceinline int X86_ISVI(int type)
{
return ((type&~X86TYPE_VU1) == X86TYPE_VI);
}
struct _x86regs {
u8 inuse;
@ -199,25 +203,37 @@ int _signExtendXMMtoM(u32 to, x86SSERegType from, int candestroy); // returns tr
// only valid during writes. If write128, then upper 64bits are in an mmxreg
// (mmreg&0xf). Constant is used from gprreg ((mmreg>>16)&0x1f)
#define MEM_EECONSTTAG 0x0100 // argument is a GPR and comes from g_cpuConstRegs
#define MEM_PSXCONSTTAG 0x0200
#define MEM_MEMORYTAG 0x0400
#define MEM_MMXTAG 0x0800 // mmreg is mmxreg
#define MEM_XMMTAG 0x8000 // mmreg is xmmreg
#define MEM_X86TAG 0x4000 // ignored most of the time
#define MEM_GPRTAG 0x2000 // argument is a GPR reg
#define MEM_CONSTTAG 0x1000 // argument is a const
enum memtag
{
MEM_EECONSTTAG = 0x0100, // argument is a GPR and comes from g_cpuConstRegs
MEM_PSXCONSTTAG = 0x0200,
MEM_MEMORYTAG = 0x0400,
MEM_MMXTAG = 0x0800, // mmreg is mmxreg
MEM_XMMTAG = 0x8000, // mmreg is xmmreg
MEM_X86TAG = 0x4000, // ignored most of the time
MEM_GPRTAG = 0x2000, // argument is a GPR reg
MEM_CONSTTAG = 0x1000 // argument is a const
};
#define IS_EECONSTREG(reg) (reg>=0&&((reg)&MEM_EECONSTTAG))
#define IS_PSXCONSTREG(reg) (reg>=0&&((reg)&MEM_PSXCONSTTAG))
#define IS_MMXREG(reg) (reg>=0&&((reg)&MEM_MMXTAG))
#define IS_XMMREG(reg) (reg>=0&&((reg)&MEM_XMMTAG))
template<memtag tag> static __forceinline bool IS_REG(s32 reg)
{
return ((reg >= 0) && (reg & tag));
}
// fixme - these 4 are only called for u32 registers; should the reg>=0 really be there?
#define IS_X86REG(reg) (reg>=0&&((reg)&MEM_X86TAG))
#define IS_GPRREG(reg) (reg>=0&&((reg)&MEM_GPRTAG))
#define IS_CONSTREG(reg) (reg>=0&&((reg)&MEM_CONSTTAG))
#define IS_MEMORYREG(reg) (reg>=0&&((reg)&MEM_MEMORYTAG))
template<memtag tag> static __forceinline bool IS_REG(u32 reg)
{
return !!(reg & tag);
}
#define IS_EECONSTREG(reg) IS_REG<MEM_EECONSTTAG>(reg)
#define IS_PSXCONSTREG(reg) IS_REG<MEM_PSXCONSTTAG>(reg)
#define IS_MMXREG(reg) IS_REG<MEM_MMXTAG>(reg)
#define IS_XMMREG(reg) IS_REG<MEM_XMMTAG>(reg)
#define IS_X86REG(reg) IS_REG<MEM_X86TAG>(reg)
#define IS_GPRREG(reg) IS_REG<MEM_GPRTAG>(reg)
#define IS_CONSTREG(reg) IS_REG<MEM_CONSTTAG>(reg)
#define IS_MEMORYREG(reg) IS_REG<MEM_MEMORYTAG>(reg)
//////////////////////
// Instruction Info //
@ -265,13 +281,13 @@ extern u32 _recIsRegWritten(EEINST* pinst, int size, u8 xmmtype, u8 reg);
extern u32 _recIsRegUsed(EEINST* pinst, int size, u8 xmmtype, u8 reg);
extern void _recFillRegister(EEINST& pinst, int type, int reg, int write);
#define EEINST_ISLIVE64(reg) (g_pCurInstInfo->regs[reg] & (EEINST_LIVE0|EEINST_LIVE1))
#define EEINST_ISLIVEXMM(reg) (g_pCurInstInfo->regs[reg] & (EEINST_LIVE0|EEINST_LIVE1|EEINST_LIVE2))
#define EEINST_ISLIVE1(reg) (g_pCurInstInfo->regs[reg] & EEINST_LIVE1)
#define EEINST_ISLIVE2(reg) (g_pCurInstInfo->regs[reg] & EEINST_LIVE2)
static __forceinline bool EEINST_ISLIVE64(u32 reg) { return !!(g_pCurInstInfo->regs[reg] & (EEINST_LIVE0|EEINST_LIVE1)); }
static __forceinline bool EEINST_ISLIVEXMM(u32 reg) { return !!(g_pCurInstInfo->regs[reg] & (EEINST_LIVE0|EEINST_LIVE1|EEINST_LIVE2)); }
static __forceinline bool EEINST_ISLIVE1(u32 reg) { return !!(g_pCurInstInfo->regs[reg] & EEINST_LIVE1); }
static __forceinline bool EEINST_ISLIVE2(u32 reg) { return !!(g_pCurInstInfo->regs[reg] & EEINST_LIVE2); }
#define FPUINST_ISLIVE(reg) (g_pCurInstInfo->fpuregs[reg] & EEINST_LIVE0)
#define FPUINST_LASTUSE(reg) (g_pCurInstInfo->fpuregs[reg] & EEINST_LASTUSE)
static __forceinline bool FPUINST_ISLIVE(u32 reg) { return !!(g_pCurInstInfo->fpuregs[reg] & EEINST_LIVE0); }
static __forceinline bool FPUINST_LASTUSE(u32 reg) { return !!(g_pCurInstInfo->fpuregs[reg] & EEINST_LASTUSE); }
// if set, then the variable at this inst really has its upper 32 bits valid
// The difference between EEINST_LIVE1 is that the latter is used in back propagation
@ -309,8 +325,8 @@ void SetMMXstate();
void SetFPUstate();
// max is 0x7f, when 0x80 is set, need to flush reg
#define MMX_GET_CACHE(ptr, index) ((u8*)ptr)[index]
#define MMX_SET_CACHE(ptr, ind3, ind2, ind1, ind0) ((u32*)ptr)[0] = (ind3<<24)|(ind2<<16)|(ind1<<8)|ind0;
//#define MMX_GET_CACHE(ptr, index) ((u8*)ptr)[index]
//#define MMX_SET_CACHE(ptr, ind3, ind2, ind1, ind0) ((u32*)ptr)[0] = (ind3<<24)|(ind2<<16)|(ind1<<8)|ind0;
#define MMX_GPR 0
#define MMX_HI XMMGPR_HI
#define MMX_LO XMMGPR_LO
@ -319,9 +335,20 @@ void SetFPUstate();
#define MMX_COP0 96
#define MMX_TEMP 0x7f
#define MMX_IS32BITS(x) (((x)>=MMX_FPU&&(x)<MMX_COP0+32)||(x)==MMX_FPUACC)
// If x is unsigned, the first part of this is always true, and it usually is.
#define MMX_ISGPR(x) ((x) >= MMX_GPR && (x) < MMX_GPR+34)
static __forceinline bool MMX_IS32BITS(s32 x)
{
return (((x >= MMX_FPU) && (x < MMX_COP0 + 32)) || (x == MMX_FPUACC));
}
static __forceinline bool MMX_ISGPR(s32 x)
{
return ((x >= MMX_GPR) && (x < MMX_GPR + 34));
}
static __forceinline bool MMX_ISGPR(u32 x)
{
return (x < MMX_GPR + 34);
}
struct _mmxregs {
u8 inuse;

View File

@ -32,12 +32,11 @@ using namespace std;
// landmass of shared code. (air)
extern u32 g_psxConstRegs[32];
u16 x86FpuState;
u16 g_mmxAllocCounter = 0;
static u16 g_mmxAllocCounter = 0;
// X86 caching
int g_x86checknext;
static int g_x86checknext;
// use special x86 register allocation for ia32
@ -49,38 +48,83 @@ void _initX86regs() {
u32 _x86GetAddr(int type, int reg)
{
switch(type&~X86TYPE_VU1) {
case X86TYPE_GPR: return (u32)&cpuRegs.GPR.r[reg];
case X86TYPE_VI: {
//assert( reg < 16 || reg == REG_R );
return (type&X86TYPE_VU1)?(u32)&VU1.VI[reg]:(u32)&VU0.VI[reg];
}
case X86TYPE_MEMOFFSET: return 0;
case X86TYPE_VIMEMOFFSET: return 0;
case X86TYPE_VUQREAD: return (type&X86TYPE_VU1)?(u32)&VU1.VI[REG_Q]:(u32)&VU0.VI[REG_Q];
case X86TYPE_VUPREAD: return (type&X86TYPE_VU1)?(u32)&VU1.VI[REG_P]:(u32)&VU0.VI[REG_P];
case X86TYPE_VUQWRITE: return (type&X86TYPE_VU1)?(u32)&VU1.q:(u32)&VU0.q;
case X86TYPE_VUPWRITE: return (type&X86TYPE_VU1)?(u32)&VU1.p:(u32)&VU0.p;
case X86TYPE_PSX: return (u32)&psxRegs.GPR.r[reg];
u32 ret = 0;
switch(type&~X86TYPE_VU1)
{
case X86TYPE_GPR:
ret = (u32)&cpuRegs.GPR.r[reg];
break;
case X86TYPE_VI:
if (type & X86TYPE_VU1)
ret = (u32)&VU1.VI[reg];
else
ret = (u32)&VU0.VI[reg];
break;
case X86TYPE_MEMOFFSET:
ret = 0;
break;
case X86TYPE_VIMEMOFFSET:
ret = 0;
break;
case X86TYPE_VUQREAD:
if (type & X86TYPE_VU1)
ret = (u32)&VU1.VI[REG_Q];
else
ret = (u32)&VU0.VI[REG_Q];
break;
case X86TYPE_VUPREAD:
if (type & X86TYPE_VU1)
ret = (u32)&VU1.VI[REG_P];
else
ret = (u32)&VU0.VI[REG_P];
break;
case X86TYPE_VUQWRITE:
if (type & X86TYPE_VU1)
ret = (u32)&VU1.q;
else
ret = (u32)&VU0.q;
break;
case X86TYPE_VUPWRITE:
if (type & X86TYPE_VU1)
ret = (u32)&VU1.p;
else
ret = (u32)&VU0.p;
break;
case X86TYPE_PSX:
ret = (u32)&psxRegs.GPR.r[reg];
break;
case X86TYPE_PCWRITEBACK:
return (u32)&g_recWriteback;
ret = (u32)&g_recWriteback;
break;
case X86TYPE_VUJUMP:
return (u32)&g_recWriteback;
ret = (u32)&g_recWriteback;
break;
jNO_DEFAULT;
}
return 0;
return ret;
}
int _getFreeX86reg(int mode)
{
int i, tempi;
int tempi = -1;
u32 bestcount = 0x10000;
int maxreg = (mode&MODE_8BITREG)?4:iREGCNT_GPR;
for (i=0; i<iREGCNT_GPR; i++) {
for (int i=0; i<iREGCNT_GPR; i++) {
int reg = (g_x86checknext+i)%iREGCNT_GPR;
if( reg == 0 || reg == ESP ) continue;
if( reg >= maxreg ) continue;
@ -92,8 +136,7 @@ int _getFreeX86reg(int mode)
}
}
tempi = -1;
for (i=1; i<maxreg; i++) {
for (int i=1; i<maxreg; i++) {
if( i == ESP ) continue;
if( (mode&MODE_NOFRAME) && i==EBP ) continue;
@ -139,7 +182,6 @@ void _flushConstReg(int reg)
void _flushConstRegs()
{
s32 i, j;
s32 zero_cnt = 0, minusone_cnt = 0;
s32 eaxval = 1; // 0, -1
u32 done[4] = {0, 0, 0, 0};
@ -149,13 +191,12 @@ void _flushConstRegs()
// flush 0 and -1 first
// ignore r0
for (i = 1, j = 0; i < 32; j++ && ++i, j %= 2) {
if (!GPR_IS_CONST1(i) || g_cpuFlushedConstReg & (1<<i))
continue;
if (g_cpuConstRegs[i].SL[j] != 0)
continue;
if (eaxval != 0)
XOR32RtoR(EAX, EAX), eaxval = 0;
for (int i = 1, j = 0; i < 32; j++ && ++i, j %= 2) {
if (!GPR_IS_CONST1(i) || g_cpuFlushedConstReg & (1<<i)) continue;
if (g_cpuConstRegs[i].SL[j] != 0) continue;
if (eaxval != 0) XOR32RtoR(EAX, EAX), eaxval = 0;
MOV32RtoM((uptr)&cpuRegs.GPR.r[i].SL[j], EAX);
done[j] |= 1<<i;
zero_cnt++;
@ -163,11 +204,9 @@ void _flushConstRegs()
rewindPtr = x86Ptr;
for (i = 1, j = 0; i < 32; j++ && ++i, j %= 2) {
if (!GPR_IS_CONST1(i) || g_cpuFlushedConstReg & (1<<i))
continue;
if (g_cpuConstRegs[i].SL[j] != -1)
continue;
for (int i = 1, j = 0; i < 32; j++ && ++i, j %= 2) {
if (!GPR_IS_CONST1(i) || g_cpuFlushedConstReg & (1<<i)) continue;
if (g_cpuConstRegs[i].SL[j] != -1) continue;
if (eaxval > 0) XOR32RtoR(EAX, EAX), eaxval = 0;
if (eaxval == 0) NOT32R(EAX), eaxval = -1;
@ -184,17 +223,17 @@ void _flushConstRegs()
done[1] |= done[3];
}
for (i = 1; i < 32; ++i) {
for (int i = 1; i < 32; ++i) {
if (GPR_IS_CONST1(i)) {
if (!(g_cpuFlushedConstReg&(1<<i))) {
if (!(done[0] & (1<<i)))
MOV32ItoM((uptr)&cpuRegs.GPR.r[i].UL[0], g_cpuConstRegs[i].UL[0]);
if (!(done[1] & (1<<i)))
MOV32ItoM((uptr)&cpuRegs.GPR.r[i].UL[1], g_cpuConstRegs[i].UL[1]);
g_cpuFlushedConstReg |= 1<<i;
}
if (g_cpuHasConstReg == g_cpuFlushedConstReg)
break;
if (g_cpuHasConstReg == g_cpuFlushedConstReg) break;
}
}
}
@ -206,14 +245,13 @@ int _allocX86reg(int x86reg, int type, int reg, int mode)
// don't alloc EAX and ESP,EBP if MODE_NOFRAME
int oldmode = mode;
int noframe = mode&MODE_NOFRAME;
int maxreg = (mode&MODE_8BITREG)?4:iREGCNT_GPR;
int noframe = mode & MODE_NOFRAME;
int maxreg = (mode & MODE_8BITREG) ? 4 : iREGCNT_GPR;
mode &= ~(MODE_NOFRAME|MODE_8BITREG);
int readfromreg = -1;
if( type != X86TYPE_TEMP ) {
if( maxreg < iREGCNT_GPR ) {
if ( type != X86TYPE_TEMP ) {
if ( maxreg < iREGCNT_GPR ) {
// make sure reg isn't in the higher regs
for(i = maxreg; i < iREGCNT_GPR; ++i) {
@ -232,8 +270,7 @@ int _allocX86reg(int x86reg, int type, int reg, int mode)
}
for (i=1; i<maxreg; i++) {
if( i == ESP ) continue;
if ( i == ESP ) continue;
if (!x86regs[i].inuse || x86regs[i].type != type || x86regs[i].reg != reg) continue;
if( (noframe && i == EBP) || (i >= maxreg) ) {
@ -272,12 +309,10 @@ int _allocX86reg(int x86reg, int type, int reg, int mode)
}
}
if (x86reg == -1) {
if (x86reg == -1)
x86reg = _getFreeX86reg(oldmode);
}
else {
else
_freeX86reg(x86reg);
}
x86regs[x86reg].type = type;
x86regs[x86reg].reg = reg;
@ -378,6 +413,7 @@ void _deleteX86reg(int type, int reg, int flush)
case 0:
_freeX86reg(i);
break;
case 1:
if( x86regs[i].mode & MODE_WRITE) {
@ -391,6 +427,7 @@ void _deleteX86reg(int type, int reg, int flush)
x86regs[i].mode |= MODE_READ;
}
return;
case 2:
x86regs[i].inuse = 0;
break;
@ -470,7 +507,7 @@ int _getFreeMMXreg()
// check for dead regs
for (i=0; i<iREGCNT_MMX; i++) {
if (mmxregs[i].needed) continue;
if (mmxregs[i].reg >= MMX_GPR && mmxregs[i].reg < MMX_GPR+34 ) { // mmxregs[i] is unsigned, and MMX_GPR == 0, so the first part is always true.
if (MMX_ISGPR(mmxregs[i].reg)) {
if( !(g_pCurInstInfo->regs[mmxregs[i].reg-MMX_GPR] & (EEINST_LIVE0|EEINST_LIVE1)) ) {
_freeMMXreg(i);
return i;
@ -485,7 +522,7 @@ int _getFreeMMXreg()
// check for future xmm usage
for (i=0; i<iREGCNT_MMX; i++) {
if (mmxregs[i].needed) continue;
if (mmxregs[i].reg >= MMX_GPR && mmxregs[i].reg < MMX_GPR+34 ) {
if (MMX_ISGPR(mmxregs[i].reg)) {
if( !(g_pCurInstInfo->regs[mmxregs[i].reg] & EEINST_MMX) ) {
_freeMMXreg(i);
return i;
@ -612,7 +649,7 @@ int _checkMMXreg(int reg, int mode)
PXORRtoR(i, i);
}
else {
if( MMX_ISGPR(reg) && (mode&(MODE_READHALF|MODE_READ)) ) _flushConstReg(reg-MMX_GPR);
if (MMX_ISGPR(reg) && (mode&(MODE_READHALF|MODE_READ))) _flushConstReg(reg-MMX_GPR);
if( (mode & MODE_READHALF) || (MMX_IS32BITS(reg)&&(mode&MODE_READ)) )
MOVDMtoMMX(i, (u32)_MMXGetAddr(reg));
else
@ -713,7 +750,7 @@ u8 _hasFreeMMXreg()
// check for dead regs
for (i=0; i<iREGCNT_MMX; i++) {
if (mmxregs[i].needed) continue;
if (mmxregs[i].reg >= MMX_GPR && mmxregs[i].reg < MMX_GPR+34 ) {
if (MMX_ISGPR(mmxregs[i].reg)) {
if( !EEINST_ISLIVE64(mmxregs[i].reg-MMX_GPR) ) {
return 1;
}
@ -723,7 +760,7 @@ u8 _hasFreeMMXreg()
// check for dead regs
for (i=0; i<iREGCNT_MMX; i++) {
if (mmxregs[i].needed) continue;
if (mmxregs[i].reg >= MMX_GPR && mmxregs[i].reg < MMX_GPR+34 ) {
if (MMX_ISGPR(mmxregs[i].reg)) {
if( !(g_pCurInstInfo->regs[mmxregs[i].reg-MMX_GPR]&EEINST_USED) ) {
return 1;
}
@ -739,8 +776,8 @@ void _freeMMXreg(int mmxreg)
if (!mmxregs[mmxreg].inuse) return;
if (mmxregs[mmxreg].mode & MODE_WRITE ) {
if( mmxregs[mmxreg].reg >= MMX_GPR && mmxregs[mmxreg].reg < MMX_GPR+32 )
// Not sure if this line is accurate, since if the 32 was 34, it would be MMX_ISGPR.
if ( /*mmxregs[mmxreg].reg >= MMX_GPR &&*/ mmxregs[mmxreg].reg < MMX_GPR+32 ) // Checking if a u32 is >=0 is pointless.
assert( !(g_cpuHasConstReg & (1<<(mmxregs[mmxreg].reg-MMX_GPR))) );
assert( mmxregs[mmxreg].reg != MMX_GPR );

View File

@ -477,8 +477,6 @@ void recResetEE( void )
__asm__("emms");
#endif
#define GET_HWADDR(mem)
for (int i = 0; i < 0x10000; i++)
recLUT_SetPage(recLUT, 0, 0, 0, i, 0);

View File

@ -26,17 +26,17 @@
// Flag Allocators
//------------------------------------------------------------------
#define getFlagReg(regX, fInst) { \
switch (fInst) { \
case 0: regX = gprF0; break; \
case 1: regX = gprF1; break; \
case 2: regX = gprF2; break; \
case 3: regX = gprF3; break; \
default: \
Console::Error("microVU: Flag Instance Error (fInst = %d)", params fInst); \
regX = gprF0; \
break; \
} \
#define getFlagReg(regX, fInst) { \
switch (fInst) { \
case 0: regX = gprF0; break; \
case 1: regX = gprF1; break; \
case 2: regX = gprF2; break; \
case 3: regX = gprF3; break; \
default: \
Console::Error("microVU Error: fInst = %d", params fInst); \
regX = gprF0; \
break; \
} \
}
#define setBitSFLAG(bitTest, bitSet) { \
@ -114,31 +114,33 @@ microVUt(void) mVUallocVIb(mV, int GPRreg, int _reg_) {
}
//------------------------------------------------------------------
// I/Q/P Reg Allocators
// I/P/Q Reg Allocators
//------------------------------------------------------------------
#define getIreg(reg, modXYZW) { \
SSE_MOVSS_M32_to_XMM(reg, (uptr)&mVU->regs->VI[REG_I].UL); \
if (CHECK_VU_EXTRA_OVERFLOW) mVUclamp2(reg, -1, 8); \
if (!((_XYZW_SS && modXYZW) || (_X_Y_Z_W == 8))) { mVUunpack_xyzw(reg, reg, 0); } \
microVUt(void) getIreg(mV, int reg, bool modXYZW) {
SSE_MOVSS_M32_to_XMM(reg, (uptr)&mVU->regs->VI[REG_I].UL);
if (CHECK_VU_EXTRA_OVERFLOW) mVUclamp2(reg, -1, 8);
if (!((_XYZW_SS && modXYZW) || (_X_Y_Z_W == 8))) { mVUunpack_xyzw(reg, reg, 0); }
}
#define getQreg(reg) { \
mVUunpack_xyzw(reg, xmmPQ, mVUinfo.readQ); \
/*if (CHECK_VU_EXTRA_OVERFLOW) mVUclamp2<vuIndex>(reg, xmmT1, 15);*/ \
microVUt(void) getPreg(mV, int reg) {
mVUunpack_xyzw(reg, xmmPQ, (2 + mVUinfo.readP));
/*if (CHECK_VU_EXTRA_OVERFLOW) mVUclamp2(reg, xmmT1, 15);*/
}
#define getPreg(reg) { \
mVUunpack_xyzw(reg, xmmPQ, (2 + mVUinfo.readP)); \
/*if (CHECK_VU_EXTRA_OVERFLOW) mVUclamp2(reg, xmmT1, 15);*/ \
microVUt(void) getQreg(int reg, int qInstance) {
mVUunpack_xyzw(reg, xmmPQ, qInstance);
/*if (CHECK_VU_EXTRA_OVERFLOW) mVUclamp2<vuIndex>(reg, xmmT1, 15);*/
}
//------------------------------------------------------------------
// Lower Instruction Allocator Helpers
//------------------------------------------------------------------
// VF to GPR
#define getReg8(GPRreg, _reg_, _fxf_) { \
if (!_reg_ && (_fxf_ < 3)) { XOR32RtoR(GPRreg, GPRreg); } \
else { MOV32MtoR(GPRreg, (uptr)&mVU->regs->VF[_reg_].UL[0]); } \
microVUt(void) writeQreg(int reg, int qInstance) {
if (qInstance) {
if (!x86caps.hasStreamingSIMD4Extensions) {
SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, 0xe1);
SSE_MOVSS_XMM_to_XMM(xmmPQ, reg);
SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, 0xe1);
}
else SSE4_INSERTPS_XMM_to_XMM(xmmPQ, reg, _MM_MK_INSERTPS_NDX(0, 1, 0));
}
else SSE_MOVSS_XMM_to_XMM(xmmPQ, reg);
}

View File

@ -275,13 +275,18 @@ microVUt(void) mVUanalyzeR2(mV, int Ft, bool canBeNOP) {
//------------------------------------------------------------------
// Sflag - Status Flag Opcodes
//------------------------------------------------------------------
#define flagSet(xFLAG) { \
int curPC = iPC; \
for (int i = mVUcount, j = 0; i > 0; i--, j++) { \
incPC2(-2); \
if (sFLAG.doFlag) { xFLAG = 1; if (j >= 3) { break; } } \
} \
iPC = curPC; \
microVUt(void) flagSet(mV, bool setMacFlag) {
int curPC = iPC;
for (int i = mVUcount, j = 0; i > 0; i--, j++) {
j += mVUstall;
incPC2(-2);
if (sFLAG.doFlag && (j >= 3)) {
if (setMacFlag) { mFLAG.doFlag = 1; }
else { sFLAG.doNonSticky = 1; }
break;
}
}
iPC = curPC;
}
microVUt(void) mVUanalyzeSflag(mV, int It) {
@ -289,14 +294,10 @@ microVUt(void) mVUanalyzeSflag(mV, int It) {
analyzeVIreg2(It, mVUlow.VI_write, 1);
if (!It) { mVUlow.isNOP = 1; }
else {
mVUinfo.swapOps = 1;
mVUsFlagHack = 0; // Don't Optimize Out Status Flags for this block
flagSet(sFLAG.doNonSticky);
if (mVUcount < 4) { mVUpBlock->pState.needExactMatch |= 0xf; }
if (mVUcount >= 1) { incPC2(-2); mVUlow.useSflag = 1; incPC2(2); }
// Note: useSflag is used for status flag optimizations when a FSSET instruction is called.
// Do to stalls, it can only be set one instruction prior to the status flag read instruction
// if we were guaranteed no-stalls were to happen, it could be set 4 instruction prior.
mVUinfo.swapOps = 1;
flagSet(mVU, 0);
if (mVUcount < 4) { mVUpBlock->pState.needExactMatch |= 0xf; }
}
}
@ -316,8 +317,8 @@ microVUt(void) mVUanalyzeMflag(mV, int Is, int It) {
if (!It) { mVUlow.isNOP = 1; }
else { // Need set _doMac for 4 previous Ops (need to do all 4 because stalls could change the result needed)
mVUinfo.swapOps = 1;
flagSet(mVU, 1);
if (mVUcount < 4) { mVUpBlock->pState.needExactMatch |= 0xf << 4; }
flagSet(mFLAG.doFlag);
}
}

View File

@ -31,10 +31,12 @@
} \
}
#define startLoop() { \
mVUdebug1(); \
memset(&mVUinfo, 0, sizeof(mVUinfo)); \
memset(&mVUregsTemp, 0, sizeof(mVUregsTemp)); \
#define startLoop() { \
if (curI & _Mbit_) { Console::Status("microVU%d: M-bit set!", params getIndex); } \
if (curI & _Dbit_) { DevCon::Status ("microVU%d: D-bit set!", params getIndex); } \
if (curI & _Tbit_) { DevCon::Status ("microVU%d: T-bit set!", params getIndex); } \
memset(&mVUinfo, 0, sizeof(mVUinfo)); \
memset(&mVUregsTemp, 0, sizeof(mVUregsTemp)); \
}
#define calcCycles(reg, x) { reg = ((reg > x) ? (reg - x) : 0); }
@ -44,7 +46,6 @@
#define incQ() { mVU->q = (mVU->q+1) & 1; }
#define doUpperOp() { mVUopU(mVU, 1); mVUdivSet(mVU); }
#define doLowerOp() { incPC(-1); mVUopL(mVU, 1); incPC(1); }
#define doIbit() { if (mVUup.iBit) { incPC(-1); MOV32ItoM((uptr)&mVU->regs->VI[REG_I].UL, curI); incPC(1); } }
#define blockCreate(addr) { if (!mVUblocks[addr]) mVUblocks[addr] = new microBlockManager(); }
//------------------------------------------------------------------
@ -74,6 +75,19 @@ microVUt(void) doSwapOp(mV) {
else { mVUopL(mVU, 1); incPC(1); doUpperOp(); }
}
microVUt(void) doIbit(mV) {
if (mVUup.iBit) {
incPC(-1);
if (CHECK_VU_OVERFLOW && ((curI & 0x7fffffff) >= 0x7f800000)) {
Console::Status("microVU%d: Clamping I Reg", params mVU->index);
int tempI = (0x80000000 & curI) | 0x7f7fffff; // Clamp I Reg
MOV32ItoM((uptr)&mVU->regs->VI[REG_I].UL, tempI);
}
else MOV32ItoM((uptr)&mVU->regs->VI[REG_I].UL, curI);
incPC(1);
}
}
// Used by mVUsetupRange
microVUt(void) mVUcheckIsSame(mV) {
@ -371,7 +385,6 @@ microVUr(void*) mVUcompile(microVU* mVU, u32 startPC, uptr pState) {
mVUsetupRange(mVU, startPC, 1);
// Reset regAlloc
mVU->regAlloc->flushAll();
mVU->regAlloc->reset();
// First Pass
@ -433,7 +446,7 @@ microVUr(void*) mVUcompile(microVU* mVU, u32 startPC, uptr pState) {
for (x = 0; x < endCount; x++) {
if (mVUinfo.isEOB) { x = 0xffff; }
if (mVUup.mBit) { OR32ItoM((uptr)&mVU->regs->flags, VUFLAG_MFLAGSET); }
if (mVUlow.isNOP) { incPC(1); doUpperOp(); doIbit(); }
if (mVUlow.isNOP) { incPC(1); doUpperOp(); doIbit(mVU); }
else if (!mVUinfo.swapOps) { incPC(1); doUpperOp(); doLowerOp(); }
else { doSwapOp(mVU); }
if (mVUinfo.doXGKICK) { mVU_XGKICK_DELAY(mVU, 1); }

View File

@ -34,18 +34,18 @@ microVUt(void) mVUstatusFlagOp(mV) {
int curPC = iPC;
int i = mVUcount;
bool runLoop = 1;
if (sFLAG.doFlag) { mVUlow.useSflag = 1; }
if (sFLAG.doFlag) { sFLAG.doNonSticky = 1; }
else {
for (; i > 0; i--) {
incPC2(-2);
if (mVUlow.useSflag) { runLoop = 0; break; }
if (sFLAG.doFlag) { mVUlow.useSflag = 1; break; }
if (sFLAG.doNonSticky) { runLoop = 0; break; }
else if (sFLAG.doFlag) { sFLAG.doNonSticky = 1; break; }
}
}
if (runLoop) {
for (; i > 0; i--) {
incPC2(-2);
if (mVUlow.useSflag) break;
if (sFLAG.doNonSticky) break;
sFLAG.doFlag = 0;
}
}

View File

@ -107,7 +107,6 @@ struct microLowerOp {
u32 branch; // Branch Type (0 = Not a Branch, 1 = B. 2 = BAL, 3~8 = Conditional Branches, 9 = JALR, 10 = JR)
bool isNOP; // This instruction is a NOP
bool isFSSET; // This instruction is a FSSET
bool useSflag; // This instruction uses/reads Sflag
bool noWriteVF; // Don't write back the result of a lower op to VF reg if upper op writes to same reg (or if VF = 0)
bool backupVI; // Backup VI reg to memory if modified before branch (branch uses old VI value unless opcode is ILW or ILWR)
bool memReadIs; // Read Is (VI reg) from memory (used by branches)
@ -245,6 +244,7 @@ public:
clearReg(reg); // Clear Reg
}
void clearNeeded(int reg) {
if ((reg < 0) || (reg >= xmmTotal)) return;
xmmReg[reg].isNeeded = 0;
if (xmmReg[reg].xyzw) { // Reg was modified
if (xmmReg[reg].reg > 0) {

View File

@ -26,28 +26,35 @@
// DIV/SQRT/RSQRT
//------------------------------------------------------------------
#define testZero(xmmReg, xmmTemp, gprTemp) { \
SSE_XORPS_XMM_to_XMM(xmmTemp, xmmTemp); /* Clear xmmTemp (make it 0) */ \
SSE_CMPEQPS_XMM_to_XMM(xmmTemp, xmmReg); /* Set all F's if zero */ \
SSE_MOVMSKPS_XMM_to_R32(gprTemp, xmmTemp); /* Move the sign bits */ \
TEST32ItoR(gprTemp, 1); /* Test "Is Zero" bit */ \
// Test if Vector is +/- Zero
#define testZero(xmmReg, xmmTemp, gprTemp) { \
SSE_XORPS_XMM_to_XMM(xmmTemp, xmmTemp); \
SSE_CMPEQSS_XMM_to_XMM(xmmTemp, xmmReg); \
if (!x86caps.hasStreamingSIMD4Extensions) { \
SSE_MOVMSKPS_XMM_to_R32(gprTemp, xmmTemp); \
TEST32ItoR(gprTemp, 1); \
} \
else SSE4_PTEST_XMM_to_XMM(xmmTemp, xmmTemp); \
}
#define testNeg(xmmReg, gprTemp, aJump) { \
SSE_MOVMSKPS_XMM_to_R32(gprTemp, xmmReg); \
TEST32ItoR(gprTemp, 1); /* Check sign bit */ \
aJump = JZ8(0); /* Skip if positive */ \
MOV32ItoM((uptr)&mVU->divFlag, divI); /* Set Invalid Flags */ \
SSE_ANDPS_M128_to_XMM(xmmReg, (uptr)mVU_absclip); /* Abs(xmmReg) */ \
x86SetJ8(aJump); \
// Test if Vector is Negative (Set Flags and Makes Positive)
#define testNeg(xmmReg, gprTemp, aJump) { \
SSE_MOVMSKPS_XMM_to_R32(gprTemp, xmmReg); \
TEST32ItoR(gprTemp, 1); \
aJump = JZ8(0); \
MOV32ItoM((uptr)&mVU->divFlag, divI); \
SSE_ANDPS_M128_to_XMM(xmmReg, (uptr)mVU_absclip); \
x86SetJ8(aJump); \
}
mVUop(mVU_DIV) {
pass1 { mVUanalyzeFDIV(mVU, _Fs_, _Fsf_, _Ft_, _Ftf_, 7); }
pass2 {
u8 *ajmp, *bjmp, *cjmp, *djmp;
int Ft;
if (_Ftf_) Ft = mVU->regAlloc->allocReg(_Ft_, 0, (1 << (3 - _Ftf_)));
else Ft = mVU->regAlloc->allocReg(_Ft_);
int Fs = mVU->regAlloc->allocReg(_Fs_, 0, (1 << (3 - _Fsf_)));
int Ft = mVU->regAlloc->allocReg(_Ft_, 0, (1 << (3 - _Ftf_)));
int t1 = mVU->regAlloc->allocReg();
testZero(Ft, t1, gprT1); // Test if Ft is zero
@ -72,9 +79,7 @@ mVUop(mVU_DIV) {
mVUclamp1(Fs, t1, 8);
x86SetJ8(djmp);
if (mVUinfo.writeQ) SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, 0xe1);
SSE_MOVSS_XMM_to_XMM(xmmPQ, Fs);
if (mVUinfo.writeQ) SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, 0xe1);
writeQreg(Fs, mVUinfo.writeQ);
mVU->regAlloc->clearNeeded(Fs);
mVU->regAlloc->clearNeeded(Ft);
@ -94,9 +99,7 @@ mVUop(mVU_SQRT) {
if (CHECK_VU_OVERFLOW) SSE_MINSS_M32_to_XMM(Ft, (uptr)mVU_maxvals); // Clamp infinities (only need to do positive clamp since xmmFt is positive)
SSE_SQRTSS_XMM_to_XMM(Ft, Ft);
if (mVUinfo.writeQ) SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, 0xe1);
SSE_MOVSS_XMM_to_XMM(xmmPQ, Ft);
if (mVUinfo.writeQ) SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, 0xe1);
writeQreg(Ft, mVUinfo.writeQ);
mVU->regAlloc->clearNeeded(Ft);
}
@ -135,9 +138,7 @@ mVUop(mVU_RSQRT) {
mVUclamp1(Fs, t1, 8);
x86SetJ8(djmp);
if (mVUinfo.writeQ) SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, 0xe1);
SSE_MOVSS_XMM_to_XMM(xmmPQ, Fs);
if (mVUinfo.writeQ) SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, 0xe1);
writeQreg(Fs, mVUinfo.writeQ);
mVU->regAlloc->clearNeeded(Fs);
mVU->regAlloc->clearNeeded(Ft);
@ -354,6 +355,7 @@ mVUop(mVU_ERSQRT) {
pass2 {
int Fs = mVU->regAlloc->allocReg(_Fs_, 0, (1 << (3 - _Fsf_)));
SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance
SSE_ANDPS_M128_to_XMM (Fs, (uptr)mVU_absclip);
SSE_SQRTSS_XMM_to_XMM (xmmPQ, Fs);
SSE_MOVSS_M32_to_XMM (Fs, (uptr)mVU_one);
SSE_DIVSS_XMM_to_XMM (Fs, xmmPQ);
@ -416,6 +418,7 @@ mVUop(mVU_ESQRT) {
pass2 {
int Fs = mVU->regAlloc->allocReg(_Fs_, 0, (1 << (3 - _Fsf_)));
SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance
SSE_ANDPS_M128_to_XMM (Fs, (uptr)mVU_absclip);
SSE_SQRTSS_XMM_to_XMM (xmmPQ, Fs);
SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip back
mVU->regAlloc->clearNeeded(Fs);
@ -736,7 +739,7 @@ mVUop(mVU_MFP) {
pass1 { mVUanalyzeMFP(mVU, _Ft_); }
pass2 {
int Ft = mVU->regAlloc->allocReg(-1, _Ft_, _X_Y_Z_W);
getPreg(Ft);
getPreg(mVU, Ft);
mVU->regAlloc->clearNeeded(Ft);
}
pass3 { mVUlog("MFP.%s vf%02d, P", _XYZW_String, _Ft_); }
@ -754,7 +757,7 @@ mVUop(mVU_MOVE) {
mVUop(mVU_MR32) {
pass1 { mVUanalyzeMR32(mVU, _Fs_, _Ft_); }
pass2 {
int Fs = mVU->regAlloc->allocReg(_Fs_, 0, 0xf);
int Fs = mVU->regAlloc->allocReg(_Fs_);
int Ft = mVU->regAlloc->allocReg(-1, _Ft_, _X_Y_Z_W);
if (_XYZW_SS) mVUunpack_xyzw(Ft, Fs, (_X ? 1 : (_Y ? 2 : (_Z ? 3 : 0))));
else SSE2_PSHUFD_XMM_to_XMM(Ft, Fs, 0x39);

View File

@ -80,9 +80,10 @@ declareAllVariables
#define _Z ((mVU->code>>22) & 0x1)
#define _W ((mVU->code>>21) & 0x1)
#define _X_Y_Z_W (((mVU->code >> 21 ) & 0xF ))
#define _X_Y_Z_W (((mVU->code >> 21 ) & 0xF))
#define _XYZW_SS (_X+_Y+_Z+_W==1)
#define _XYZW_SS2 (_XYZW_SS && (_X_Y_Z_W != 8))
#define _XYZW_PS (_X_Y_Z_W == 0xf)
#define _bc_ (mVU->code & 0x3)
#define _bc_x ((mVU->code & 0x3) == 0)
@ -242,20 +243,8 @@ typedef u32 (__fastcall *mVUCall)(void*, void*);
// Debug Stuff...
#ifdef mVUdebug
#define mVUprint Console::Status
#define mVUdebug1() { \
if (curI & _Ibit_) { SysPrintf("microVU: I-bit set!\n"); } \
if (curI & _Ebit_) { SysPrintf("microVU: E-bit set!\n"); } \
if (curI & _Mbit_) { SysPrintf("microVU: M-bit set!\n"); } \
if (curI & _Dbit_) { SysPrintf("microVU: D-bit set!\n"); } \
if (curI & _Tbit_) { SysPrintf("microVU: T-bit set!\n"); } \
}
#else
#define mVUprint 0&&
#define mVUdebug1() { \
if (curI & _Mbit_) { Console::Status("microVU%d: M-bit set!", params getIndex); } \
if (curI & _Dbit_) { DevCon::Status ("microVU%d: D-bit set!", params getIndex); } \
if (curI & _Tbit_) { DevCon::Status ("microVU%d: T-bit set!", params getIndex); } \
}
#endif
// Program Logging...

View File

@ -34,7 +34,7 @@ microVUt(void) mVUupdateFlags(mV, int reg, int regT1 = -1, int regT2 = -1, bool
//SysPrintf("Status = %d; Mac = %d\n", sFLAG.doFlag, mFLAG.doFlag);
if (mVUsFlagHack) { sFLAG.doFlag = 0; }
if (!sFLAG.doFlag && !mFLAG.doFlag) { return; }
if (!(!mFLAG.doFlag || (_XYZW_SS && modXYZW))) {
if ((mFLAG.doFlag && !(_XYZW_SS && modXYZW))) {
if (regT2 < 0) { regT2 = mVU->regAlloc->allocReg(); regT2b = 1; }
SSE2_PSHUFD_XMM_to_XMM(regT2, reg, 0x1B); // Flip wzyx to xyzw
}
@ -119,27 +119,31 @@ void setupPass1(microVU* mVU, int opCase, bool isACC, bool noFlagUpdate) {
}
// Sets Up Ft Reg for Normal, BC, I, and Q Cases
void setupFtReg(microVU* mVU, int& Ft, int opCase) {
void setupFtReg(microVU* mVU, int& Ft, int& tempFt, int opCase) {
opCase1 {
if (_XYZW_SS2) Ft = mVU->regAlloc->allocReg(_Ft_, 0, _X_Y_Z_W);
else Ft = mVU->regAlloc->allocReg(_Ft_);
if (_XYZW_SS2) { Ft = mVU->regAlloc->allocReg(_Ft_, 0, _X_Y_Z_W); tempFt = Ft; }
else { Ft = mVU->regAlloc->allocReg(_Ft_); tempFt = -1; }
}
opCase2 {
int tempFt = mVU->regAlloc->allocReg(_Ft_);
tempFt = mVU->regAlloc->allocReg(_Ft_);
Ft = mVU->regAlloc->allocReg();
mVUunpack_xyzw(Ft, tempFt, _bc_);
mVU->regAlloc->clearNeeded(tempFt);
tempFt = Ft;
}
opCase3 { Ft = mVU->regAlloc->allocReg(); tempFt = Ft; getIreg(mVU, Ft, 1); }
opCase4 {
if (_XYZW_SS && !mVUinfo.readQ) { Ft = xmmPQ; tempFt = -1; }
else { Ft = mVU->regAlloc->allocReg(); tempFt = Ft; getQreg(Ft, mVUinfo.readQ); }
}
opCase3 { Ft = mVU->regAlloc->allocReg(); getIreg(Ft, 1); }
opCase4 { Ft = mVU->regAlloc->allocReg(); getQreg(Ft); }
}
// Normal FMAC Opcodes
void mVU_FMACa(microVU* mVU, int recPass, int opCase, int opType, bool isACC, const char* opName) {
pass1 { setupPass1(mVU, opCase, isACC, ((opType == 3) || (opType == 4))); }
pass2 {
int Fs, Ft, ACC;
setupFtReg(mVU, Ft, opCase);
int Fs, Ft, ACC, tempFt;
setupFtReg(mVU, Ft, tempFt, opCase);
if (isACC) {
Fs = mVU->regAlloc->allocReg(_Fs_, 0, _X_Y_Z_W);
@ -148,7 +152,9 @@ void mVU_FMACa(microVU* mVU, int recPass, int opCase, int opType, bool isACC, co
}
else { Fs = mVU->regAlloc->allocReg(_Fs_, _Fd_, _X_Y_Z_W); }
opCase2 { if (opType == 2) { mVUclamp1(Fs, -1, _X_Y_Z_W); } } // Clamp Needed for alot of games (TOTA, DoM, etc...)
opCase1 { if((opType == 2) && _XYZW_PS) { mVUclamp1(Ft, -1, _X_Y_Z_W); } } // Clamp Needed for Ice Age 3 (VU0)
opCase1 { if((opType == 2) && _XYZW_PS) { mVUclamp1(Fs, -1, _X_Y_Z_W); } } // Clamp Needed for Ice Age 3 (VU0)
opCase2 { if (opType == 2) { mVUclamp1(Fs, -1, _X_Y_Z_W); } } // Clamp Needed for alot of games (TOTA, DoM, etc...)
if (_XYZW_SS) SSE_SS[opType](mVU, Fs, Ft, -1, -1);
else SSE_PS[opType](mVU, Fs, Ft, -1, -1);
@ -156,11 +162,11 @@ void mVU_FMACa(microVU* mVU, int recPass, int opCase, int opType, bool isACC, co
if (isACC) {
if (_XYZW_SS) SSE_MOVSS_XMM_to_XMM(ACC, Fs);
else mVUmergeRegs(ACC, Fs, _X_Y_Z_W);
mVUupdateFlags(mVU, ACC, Fs, ((opCase==2) ? Ft : (((opCase==1) && _XYZW_SS2) ? Ft : -1)));
mVUupdateFlags(mVU, ACC, Fs, tempFt);
if (_XYZW_SS2) SSE2_PSHUFD_XMM_to_XMM(ACC, ACC, shuffleSS(_X_Y_Z_W));
mVU->regAlloc->clearNeeded(ACC);
}
else mVUupdateFlags(mVU, Fs, ((opCase==2) ? Ft : -1), (((opCase==1) && _XYZW_SS2) ? Ft : -1));
else mVUupdateFlags(mVU, Fs, tempFt);
mVU->regAlloc->clearNeeded(Fs); // Always Clear Written Reg First
mVU->regAlloc->clearNeeded(Ft);
@ -172,8 +178,8 @@ void mVU_FMACa(microVU* mVU, int recPass, int opCase, int opType, bool isACC, co
void mVU_FMACb(microVU* mVU, int recPass, int opCase, int opType, const char* opName) {
pass1 { setupPass1(mVU, opCase, 1, 0); }
pass2 {
int Fs, Ft, ACC;
setupFtReg(mVU, Ft, opCase);
int Fs, Ft, ACC, tempFt;
setupFtReg(mVU, Ft, tempFt, opCase);
Fs = mVU->regAlloc->allocReg(_Fs_, 0, _X_Y_Z_W);
ACC = mVU->regAlloc->allocReg(32, 32, 0xf, 0);
@ -185,16 +191,17 @@ void mVU_FMACb(microVU* mVU, int recPass, int opCase, int opType, const char* op
else SSE_PS[2](mVU, Fs, Ft, -1, -1);
if (_XYZW_SS || _X_Y_Z_W == 0xf) {
if (_XYZW_SS) SSE_SS[opType](mVU, ACC, Fs, -1, -1);
else SSE_PS[opType](mVU, ACC, Fs, -1, -1);
mVUupdateFlags(mVU, ACC, Fs, ((opCase==2) ? Ft : (((opCase==1) && _XYZW_SS2) ? Ft : -1)));
if (_XYZW_SS) SSE_SS[opType](mVU, ACC, Fs, tempFt, -1);
else SSE_PS[opType](mVU, ACC, Fs, tempFt, -1);
mVUupdateFlags(mVU, ACC, Fs, tempFt);
if (_XYZW_SS && _X_Y_Z_W != 8) SSE2_PSHUFD_XMM_to_XMM(ACC, ACC, shuffleSS(_X_Y_Z_W));
}
else {
int tempACC = mVU->regAlloc->allocReg();
SSE_MOVAPS_XMM_to_XMM(tempACC, ACC);
SSE_PS[opType](mVU, tempACC, Fs, -1, -1);
SSE_PS[opType](mVU, tempACC, Fs, tempFt, -1);
mVUmergeRegs(ACC, tempACC, _X_Y_Z_W);
mVUupdateFlags(mVU, ACC, Fs, tempFt);
mVU->regAlloc->clearNeeded(tempACC);
}
@ -209,8 +216,8 @@ void mVU_FMACb(microVU* mVU, int recPass, int opCase, int opType, const char* op
void mVU_FMACc(microVU* mVU, int recPass, int opCase, const char* opName) {
pass1 { setupPass1(mVU, opCase, 0, 0); }
pass2 {
int Fs, Ft, ACC;
setupFtReg(mVU, Ft, opCase);
int Fs, Ft, ACC, tempFt;
setupFtReg(mVU, Ft, tempFt, opCase);
ACC = mVU->regAlloc->allocReg(32);
Fs = mVU->regAlloc->allocReg(_Fs_, _Fd_, _X_Y_Z_W);
@ -218,12 +225,12 @@ void mVU_FMACc(microVU* mVU, int recPass, int opCase, const char* opName) {
if (_XYZW_SS2) { SSE2_PSHUFD_XMM_to_XMM(ACC, ACC, shuffleSS(_X_Y_Z_W)); }
opCase2 { mVUclamp1(Fs, -1, _X_Y_Z_W); } // Clamp Needed for alot of games (TOTA, DoM, etc...)
if (_XYZW_SS) { SSE_SS[2](mVU, Fs, Ft, -1, -1); SSE_SS[0](mVU, Fs, ACC, -1, -1); }
else { SSE_PS[2](mVU, Fs, Ft, -1, -1); SSE_PS[0](mVU, Fs, ACC, -1, -1); }
if (_XYZW_SS) { SSE_SS[2](mVU, Fs, Ft, -1, -1); SSE_SS[0](mVU, Fs, ACC, tempFt, -1); }
else { SSE_PS[2](mVU, Fs, Ft, -1, -1); SSE_PS[0](mVU, Fs, ACC, tempFt, -1); }
if (_XYZW_SS2) { SSE2_PSHUFD_XMM_to_XMM(ACC, ACC, shuffleSS(_X_Y_Z_W)); }
mVUupdateFlags(mVU, Fs, ((opCase==2) ? Ft : -1), (((opCase==1) && _XYZW_SS2) ? Ft : -1));
mVUupdateFlags(mVU, Fs, tempFt);
mVU->regAlloc->clearNeeded(Fs); // Always Clear Written Reg First
mVU->regAlloc->clearNeeded(Ft);
@ -236,16 +243,16 @@ void mVU_FMACc(microVU* mVU, int recPass, int opCase, const char* opName) {
void mVU_FMACd(microVU* mVU, int recPass, int opCase, const char* opName) {
pass1 { setupPass1(mVU, opCase, 0, 0); }
pass2 {
int Fs, Ft, Fd;
setupFtReg(mVU, Ft, opCase);
int Fs, Ft, Fd, tempFt;
setupFtReg(mVU, Ft, tempFt, opCase);
Fs = mVU->regAlloc->allocReg(_Fs_, 0, _X_Y_Z_W);
Fs = mVU->regAlloc->allocReg(_Fs_, 0, _X_Y_Z_W);
Fd = mVU->regAlloc->allocReg(32, _Fd_, _X_Y_Z_W);
if (_XYZW_SS) { SSE_SS[2](mVU, Fs, Ft, -1, -1); SSE_SS[1](mVU, Fd, Fs, -1, -1); }
else { SSE_PS[2](mVU, Fs, Ft, -1, -1); SSE_PS[1](mVU, Fd, Fs, -1, -1); }
if (_XYZW_SS) { SSE_SS[2](mVU, Fs, Ft, -1, -1); SSE_SS[1](mVU, Fd, Fs, tempFt, -1); }
else { SSE_PS[2](mVU, Fs, Ft, -1, -1); SSE_PS[1](mVU, Fd, Fs, tempFt, -1); }
mVUupdateFlags(mVU, Fd, Fs, ((opCase==2) ? Ft : (((opCase==1) && _XYZW_SS2) ? Ft : -1)));
mVUupdateFlags(mVU, Fd, Fs, tempFt);
mVU->regAlloc->clearNeeded(Fd); // Always Clear Written Reg First
mVU->regAlloc->clearNeeded(Ft);

View File

@ -377,15 +377,28 @@ REG64_(GSReg, IMR)
REG_END
REG64_(GSReg, PMODE)
uint32 EN1:1;
uint32 EN2:1;
uint32 CRTMD:3;
uint32 MMOD:1;
uint32 AMOD:1;
uint32 SLBG:1;
uint32 ALP:8;
uint32 _PAD:16;
uint32 _PAD1:32;
union
{
struct
{
uint32 EN1:1;
uint32 EN2:1;
uint32 CRTMD:3;
uint32 MMOD:1;
uint32 AMOD:1;
uint32 SLBG:1;
uint32 ALP:8;
uint32 _PAD:16;
uint32 _PAD1:32;
};
struct
{
uint32 EN:2;
uint32 _PAD2:30;
uint32 _PAD3:32;
};
};
REG_END
REG64_(GSReg, SIGLBLID)

View File

@ -71,7 +71,7 @@ __declspec(align(16)) class GSClut : public GSAlignedClass<16>
template<int n> void WriteCLUT16_CSM2(const GIFRegTEX0& TEX0, const GIFRegTEXCLUT& TEXCLUT);
template<int n> void WriteCLUT16S_CSM2(const GIFRegTEX0& TEX0, const GIFRegTEXCLUT& TEXCLUT);
void WriteCLUT_NULL(const GIFRegTEX0& TEX0, const GIFRegTEXCLUT& TEXCLUT) {ASSERT(0);} // xenosaga 3
void WriteCLUT_NULL(const GIFRegTEX0& TEX0, const GIFRegTEXCLUT& TEXCLUT) {} // xenosaga 3, bios
static void WriteCLUT_T32_I8_CSM1(const uint32* RESTRICT src, uint16* RESTRICT clut);
static void WriteCLUT_T32_I4_CSM1(const uint32* RESTRICT src, uint16* RESTRICT clut);

View File

@ -20,6 +20,7 @@
*/
#include "StdAfx.h"
#include "GSdx.h"
#include "GSDevice.h"
GSDevice::GSDevice()
@ -31,6 +32,12 @@ GSDevice::GSDevice()
, m_blend(NULL)
, m_1x1(NULL)
{
memset(&m_vertices, 0, sizeof(m_vertices));
m_msaa = theApp.GetConfig("msaa", 0);
m_msaa_desc.Count = 1;
m_msaa_desc.Quality = 0;
}
GSDevice::~GSDevice()
@ -82,7 +89,7 @@ void GSDevice::Present(const GSVector4i& r, int shader, bool limit)
int w = std::max<int>(cr.width(), 1);
int h = std::max<int>(cr.height(), 1);
if(!m_backbuffer || m_backbuffer->m_size.x != w || m_backbuffer->m_size.y != h)
if(!m_backbuffer || m_backbuffer->GetWidth() != w || m_backbuffer->GetHeight() != h)
{
if(!Reset(w, h, DontCare))
{
@ -102,15 +109,20 @@ void GSDevice::Present(const GSVector4i& r, int shader, bool limit)
Flip(limit);
}
GSTexture* GSDevice::Fetch(int type, int w, int h, int format)
GSTexture* GSDevice::Fetch(int type, int w, int h, bool msaa, int format)
{
if(m_msaa < 2)
{
msaa = false;
}
GSVector2i size(w, h);
for(list<GSTexture*>::iterator i = m_pool.begin(); i != m_pool.end(); i++)
{
GSTexture* t = *i;
if(t->GetType() == type && t->GetFormat() == format && t->GetSize() == size)
if(t->GetType() == type && t->GetFormat() == format && t->GetSize() == size && t->IsMSAA() == msaa)
{
m_pool.erase(i);
@ -118,7 +130,13 @@ GSTexture* GSDevice::Fetch(int type, int w, int h, int format)
}
}
return Create(type, w, h, format);
return Create(type, w, h, msaa, format);
}
void GSDevice::EndScene()
{
m_vertices.start += m_vertices.count;
m_vertices.count = 0;
}
void GSDevice::Recycle(GSTexture* t)
@ -127,7 +145,7 @@ void GSDevice::Recycle(GSTexture* t)
{
m_pool.push_front(t);
while(m_pool.size() > 200)
while(m_pool.size() > 600)
{
delete m_pool.back();
@ -136,24 +154,24 @@ void GSDevice::Recycle(GSTexture* t)
}
}
GSTexture* GSDevice::CreateRenderTarget(int w, int h, int format)
GSTexture* GSDevice::CreateRenderTarget(int w, int h, bool msaa, int format)
{
return Fetch(GSTexture::RenderTarget, w, h, format);
return Fetch(GSTexture::RenderTarget, w, h, msaa, format);
}
GSTexture* GSDevice::CreateDepthStencil(int w, int h, int format)
GSTexture* GSDevice::CreateDepthStencil(int w, int h, bool msaa, int format)
{
return Fetch(GSTexture::DepthStencil, w, h, format);
return Fetch(GSTexture::DepthStencil, w, h, msaa, format);
}
GSTexture* GSDevice::CreateTexture(int w, int h, int format)
{
return Fetch(GSTexture::Texture, w, h, format);
return Fetch(GSTexture::Texture, w, h, false, format);
}
GSTexture* GSDevice::CreateOffscreen(int w, int h, int format)
{
return Fetch(GSTexture::Offscreen, w, h, format);
return Fetch(GSTexture::Offscreen, w, h, false, format);
}
void GSDevice::StretchRect(GSTexture* st, GSTexture* dt, const GSVector4& dr, int shader, bool linear)
@ -170,7 +188,7 @@ void GSDevice::Merge(GSTexture* st[2], GSVector4* sr, GSVector4* dr, const GSVec
{
if(!m_merge || !(m_merge->GetSize() == fs))
{
m_merge = CreateRenderTarget(fs.x, fs.y);
m_merge = CreateRenderTarget(fs.x, fs.y, false);
}
// TODO: m_1x1
@ -181,7 +199,25 @@ void GSDevice::Merge(GSTexture* st[2], GSVector4* sr, GSVector4* dr, const GSVec
if(m_merge)
{
DoMerge(st, sr, dr, m_merge, slbg, mmod, c);
GSTexture* tex[2] = {NULL, NULL};
for(int i = 0; i < countof(tex); i++)
{
if(st[i] != NULL)
{
tex[i] = st[i]->IsMSAA() ? Resolve(st[i]) : st[i];
}
}
DoMerge(tex, sr, dr, m_merge, slbg, mmod, c);
for(int i = 0; i < countof(tex); i++)
{
if(tex[i] != st[i])
{
Recycle(tex[i]);
}
}
}
else
{
@ -195,7 +231,7 @@ void GSDevice::Interlace(const GSVector2i& ds, int field, int mode, float yoffse
{
if(!m_weavebob || !(m_weavebob->GetSize() == ds))
{
m_weavebob = CreateRenderTarget(ds.x, ds.y);
m_weavebob = CreateRenderTarget(ds.x, ds.y, false);
}
if(mode == 0 || mode == 2) // weave or blend
@ -210,7 +246,7 @@ void GSDevice::Interlace(const GSVector2i& ds, int field, int mode, float yoffse
if(!m_blend || !(m_blend->GetSize() == ds))
{
m_blend = CreateRenderTarget(ds.x, ds.y);
m_blend = CreateRenderTarget(ds.x, ds.y, false);
}
DoInterlace(m_weavebob, m_blend, 2, false, 0);
@ -240,7 +276,7 @@ bool GSDevice::ResizeTexture(GSTexture** t, int w, int h)
GSTexture* t2 = *t;
if(t2 == NULL || t2->m_size.x != w || t2->m_size.y != h)
if(t2 == NULL || t2->GetWidth() != w || t2->GetHeight() != h)
{
delete t2;

View File

@ -50,7 +50,7 @@ class GSDevice : public GSAlignedClass<16>
{
list<GSTexture*> m_pool;
GSTexture* Fetch(int type, int w, int h, int format);
GSTexture* Fetch(int type, int w, int h, bool msaa, int format);
protected:
GSWnd* m_wnd;
@ -63,8 +63,11 @@ protected:
GSTexture* m_1x1;
GSTexture* m_current;
struct {D3D_FEATURE_LEVEL level; string model, vs, gs, ps;} m_shader;
struct {size_t stride, start, count, limit;} m_vertices;
uint32 m_msaa;
DXGI_SAMPLE_DESC m_msaa_desc;
virtual GSTexture* Create(int type, int w, int h, int format) = 0;
virtual GSTexture* Create(int type, int w, int h, bool msaa, int format) = 0;
virtual void DoMerge(GSTexture* st[2], GSVector4* sr, GSVector4* dr, GSTexture* dt, bool slbg, bool mmod, const GSVector4& c) = 0;
virtual void DoInterlace(GSTexture* st, GSTexture* dt, int shader, bool linear, float yoffset) = 0;
@ -85,18 +88,20 @@ public:
virtual void BeginScene() {}
virtual void DrawPrimitive() {};
virtual void EndScene() {}
virtual void EndScene();
virtual void ClearRenderTarget(GSTexture* t, const GSVector4& c) {}
virtual void ClearRenderTarget(GSTexture* t, uint32 c) {}
virtual void ClearDepth(GSTexture* t, float c) {}
virtual void ClearStencil(GSTexture* t, uint8 c) {}
virtual GSTexture* CreateRenderTarget(int w, int h, int format = 0);
virtual GSTexture* CreateDepthStencil(int w, int h, int format = 0);
virtual GSTexture* CreateRenderTarget(int w, int h, bool msaa, int format = 0);
virtual GSTexture* CreateDepthStencil(int w, int h, bool msaa, int format = 0);
virtual GSTexture* CreateTexture(int w, int h, int format = 0);
virtual GSTexture* CreateOffscreen(int w, int h, int format = 0);
virtual GSTexture* Resolve(GSTexture* t) {return NULL;}
virtual GSTexture* CopyOffscreen(GSTexture* src, const GSVector4& sr, int w, int h, int format = 0) {return NULL;}
virtual void CopyRect(GSTexture* st, GSTexture* dt, const GSVector4i& r) {}

View File

@ -25,31 +25,11 @@
#include "resource.h"
GSDevice10::GSDevice10()
: m_vb(NULL)
, m_vb_stride(0)
, m_layout(NULL)
, m_topology(D3D10_PRIMITIVE_TOPOLOGY_UNDEFINED)
, m_vs(NULL)
, m_vs_cb(NULL)
, m_gs(NULL)
, m_ps(NULL)
, m_ps_cb(NULL)
, m_scissor(0, 0, 0, 0)
, m_viewport(0, 0)
, m_dss(NULL)
, m_sref(0)
, m_bs(NULL)
, m_bf(-1)
, m_rtv(NULL)
, m_dsv(NULL)
{
memset(m_ps_srv, 0, sizeof(m_ps_srv));
memset(m_ps_ss, 0, sizeof(m_ps_ss));
memset(&m_state, 0, sizeof(m_state));
m_vertices.stride = 0;
m_vertices.start = 0;
m_vertices.count = 0;
m_vertices.limit = 0;
m_state.topology = D3D10_PRIMITIVE_TOPOLOGY_UNDEFINED;
m_state.bf = -1;
}
GSDevice10::~GSDevice10()
@ -63,7 +43,7 @@ bool GSDevice10::Create(GSWnd* wnd, bool vsync)
return false;
}
HRESULT hr;
HRESULT hr = E_FAIL;
DXGI_SWAP_CHAIN_DESC scd;
D3D10_BUFFER_DESC bd;
@ -86,7 +66,7 @@ bool GSDevice10::Create(GSWnd* wnd, bool vsync)
scd.SampleDesc.Quality = 0;
scd.Windowed = TRUE;
uint32 flags = D3D10_CREATE_DEVICE_SINGLETHREADED; //disables thread safety, should be fine (speedup)
uint32 flags = D3D10_CREATE_DEVICE_SINGLETHREADED;
#ifdef DEBUG
flags |= D3D10_CREATE_DEVICE_DEBUG;
@ -115,6 +95,22 @@ bool GSDevice10::Create(GSWnd* wnd, bool vsync)
if(FAILED(hr)) return false;
// msaa
for(uint32 i = 2; i <= D3D10_MAX_MULTISAMPLE_SAMPLE_COUNT; i++)
{
uint32 quality[2] = {0, 0};
if(SUCCEEDED(m_dev->CheckMultisampleQualityLevels(DXGI_FORMAT_R8G8B8A8_UNORM, i, &quality[0])) && quality[0] > 0
&& SUCCEEDED(m_dev->CheckMultisampleQualityLevels(DXGI_FORMAT_D32_FLOAT_S8X24_UINT, i, &quality[1])) && quality[1] > 0)
{
m_msaa_desc.Count = i;
m_msaa_desc.Quality = std::min<uint32>(quality[0] - 1, quality[1] - 1);
if(i >= m_msaa) break;
}
}
// convert
D3D10_INPUT_ELEMENT_DESC il_convert[] =
@ -199,7 +195,7 @@ bool GSDevice10::Create(GSWnd* wnd, bool vsync)
rd.SlopeScaledDepthBias = 0;
rd.DepthClipEnable = false; // ???
rd.ScissorEnable = true;
rd.MultisampleEnable = false;
rd.MultisampleEnable = true;
rd.AntialiasedLineEnable = false;
hr = m_dev->CreateRasterizerState(&rd, &m_rs);
@ -258,27 +254,11 @@ void GSDevice10::Flip(bool limit)
m_swapchain->Present(m_vsync && limit ? 1 : 0, 0);
}
void GSDevice10::BeginScene()
{
}
void GSDevice10::DrawPrimitive()
{
m_dev->Draw(m_vertices.count, m_vertices.start);
}
void GSDevice10::EndScene()
{
PSSetShaderResources(NULL, NULL);
// not clearing the rt/ds gives a little fps boost in complex games (5-10%)
// OMSetRenderTargets(NULL, NULL);
m_vertices.start += m_vertices.count;
m_vertices.count = 0;
}
void GSDevice10::ClearRenderTarget(GSTexture* t, const GSVector4& c)
{
m_dev->ClearRenderTargetView(*(GSTexture10*)t, c.v);
@ -301,7 +281,7 @@ void GSDevice10::ClearStencil(GSTexture* t, uint8 c)
m_dev->ClearDepthStencilView(*(GSTexture10*)t, D3D10_CLEAR_STENCIL, 0, c);
}
GSTexture* GSDevice10::Create(int type, int w, int h, int format)
GSTexture* GSDevice10::Create(int type, int w, int h, bool msaa, int format)
{
HRESULT hr;
@ -318,6 +298,11 @@ GSTexture* GSDevice10::Create(int type, int w, int h, int format)
desc.SampleDesc.Quality = 0;
desc.Usage = D3D10_USAGE_DEFAULT;
if(msaa)
{
desc.SampleDesc = m_msaa_desc;
}
switch(type)
{
case GSTexture::RenderTarget:
@ -359,14 +344,14 @@ GSTexture* GSDevice10::Create(int type, int w, int h, int format)
return t;
}
GSTexture* GSDevice10::CreateRenderTarget(int w, int h, int format)
GSTexture* GSDevice10::CreateRenderTarget(int w, int h, bool msaa, int format)
{
return __super::CreateRenderTarget(w, h, format ? format : DXGI_FORMAT_R8G8B8A8_UNORM);
return __super::CreateRenderTarget(w, h, msaa, format ? format : DXGI_FORMAT_R8G8B8A8_UNORM);
}
GSTexture* GSDevice10::CreateDepthStencil(int w, int h, int format)
GSTexture* GSDevice10::CreateDepthStencil(int w, int h, bool msaa, int format)
{
return __super::CreateDepthStencil(w, h, format ? format : DXGI_FORMAT_D32_FLOAT_S8X24_UINT); // DXGI_FORMAT_R32G8X24_TYPELESS
return __super::CreateDepthStencil(w, h, msaa, format ? format : DXGI_FORMAT_D32_FLOAT_S8X24_UINT); // DXGI_FORMAT_R32G8X24_TYPELESS
}
GSTexture* GSDevice10::CreateTexture(int w, int h, int format)
@ -379,6 +364,22 @@ GSTexture* GSDevice10::CreateOffscreen(int w, int h, int format)
return __super::CreateOffscreen(w, h, format ? format : DXGI_FORMAT_R8G8B8A8_UNORM);
}
GSTexture* GSDevice10::Resolve(GSTexture* t)
{
ASSERT(t != NULL && t->IsMSAA());
if(GSTexture* dst = CreateRenderTarget(t->GetWidth(), t->GetHeight(), false, t->GetFormat()))
{
dst->SetScale(t->GetScale());
m_dev->ResolveSubresource(*(GSTexture10*)dst, 0, *(GSTexture10*)t, 0, (DXGI_FORMAT)t->GetFormat());
return dst;
}
return NULL;
}
GSTexture* GSDevice10::CopyOffscreen(GSTexture* src, const GSVector4& sr, int w, int h, int format)
{
GSTexture* dst = NULL;
@ -395,11 +396,16 @@ GSTexture* GSDevice10::CopyOffscreen(GSTexture* src, const GSVector4& sr, int w,
return false;
}
if(GSTexture* rt = CreateRenderTarget(w, h, format))
if(GSTexture* rt = CreateRenderTarget(w, h, false, format))
{
GSVector4 dr(0, 0, w, h);
StretchRect(src, sr, rt, dr, m_convert.ps[format == DXGI_FORMAT_R16_UINT ? 1 : 0], NULL);
if(GSTexture* src2 = src->IsMSAA() ? Resolve(src) : src)
{
StretchRect(src2, sr, rt, dr, m_convert.ps[format == DXGI_FORMAT_R16_UINT ? 1 : 0], NULL);
if(src2 != src) Recycle(src2);
}
dst = CreateOffscreen(w, h, format);
@ -483,6 +489,8 @@ void GSDevice10::StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt,
//
EndScene();
PSSetShaderResources(NULL, NULL);
}
void GSDevice10::DoMerge(GSTexture* st[2], GSVector4* sr, GSVector4* dr, GSTexture* dt, bool slbg, bool mmod, const GSVector4& c)
@ -525,14 +533,15 @@ void GSDevice10::IASetVertexBuffer(const void* vertices, size_t stride, size_t c
if(count * stride > m_vertices.limit * m_vertices.stride)
{
m_vertices.vb_old = m_vertices.vb;
m_vertices.vb = NULL;
m_vb_old = m_vb;
m_vb = NULL;
m_vertices.start = 0;
m_vertices.count = 0;
m_vertices.limit = std::max<int>(count * 3 / 2, 10000);
}
if(m_vertices.vb == NULL)
if(m_vb == NULL)
{
D3D10_BUFFER_DESC bd;
@ -545,7 +554,7 @@ void GSDevice10::IASetVertexBuffer(const void* vertices, size_t stride, size_t c
HRESULT hr;
hr = m_dev->CreateBuffer(&bd, NULL, &m_vertices.vb);
hr = m_dev->CreateBuffer(&bd, NULL, &m_vb);
if(FAILED(hr)) return;
}
@ -561,25 +570,25 @@ void GSDevice10::IASetVertexBuffer(const void* vertices, size_t stride, size_t c
void* v = NULL;
if(SUCCEEDED(m_vertices.vb->Map(type, 0, &v)))
if(SUCCEEDED(m_vb->Map(type, 0, &v)))
{
GSVector4i::storent((uint8*)v + m_vertices.start * stride, vertices, count * stride);
m_vertices.vb->Unmap();
m_vb->Unmap();
}
m_vertices.count = count;
m_vertices.stride = stride;
IASetVertexBuffer(m_vertices.vb, stride);
IASetVertexBuffer(m_vb, stride);
}
void GSDevice10::IASetVertexBuffer(ID3D10Buffer* vb, size_t stride)
{
if(m_vb != vb || m_vb_stride != stride)
if(m_state.vb != vb || m_state.vb_stride != stride)
{
m_vb = vb;
m_vb_stride = stride;
m_state.vb = vb;
m_state.vb_stride = stride;
uint32 offset = 0;
@ -589,9 +598,9 @@ void GSDevice10::IASetVertexBuffer(ID3D10Buffer* vb, size_t stride)
void GSDevice10::IASetInputLayout(ID3D10InputLayout* layout)
{
if(m_layout != layout)
if(m_state.layout != layout)
{
m_layout = layout;
m_state.layout = layout;
m_dev->IASetInputLayout(layout);
}
@ -599,9 +608,9 @@ void GSDevice10::IASetInputLayout(ID3D10InputLayout* layout)
void GSDevice10::IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY topology)
{
if(m_topology != topology)
if(m_state.topology != topology)
{
m_topology = topology;
m_state.topology = topology;
m_dev->IASetPrimitiveTopology(topology);
}
@ -609,16 +618,16 @@ void GSDevice10::IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY topology)
void GSDevice10::VSSetShader(ID3D10VertexShader* vs, ID3D10Buffer* vs_cb)
{
if(m_vs != vs)
if(m_state.vs != vs)
{
m_vs = vs;
m_state.vs = vs;
m_dev->VSSetShader(vs);
}
if(m_vs_cb != vs_cb)
if(m_state.vs_cb != vs_cb)
{
m_vs_cb = vs_cb;
m_state.vs_cb = vs_cb;
m_dev->VSSetConstantBuffers(0, 1, &vs_cb);
}
@ -626,9 +635,9 @@ void GSDevice10::VSSetShader(ID3D10VertexShader* vs, ID3D10Buffer* vs_cb)
void GSDevice10::GSSetShader(ID3D10GeometryShader* gs)
{
if(m_gs != gs)
if(m_state.gs != gs)
{
m_gs = gs;
m_state.gs = gs;
m_dev->GSSetShader(gs);
}
@ -642,10 +651,10 @@ void GSDevice10::PSSetShaderResources(GSTexture* sr0, GSTexture* sr1)
if(sr0) srv0 = *(GSTexture10*)sr0;
if(sr1) srv1 = *(GSTexture10*)sr1;
if(m_ps_srv[0] != srv0 || m_ps_srv[1] != srv1)
if(m_state.ps_srv[0] != srv0 || m_state.ps_srv[1] != srv1)
{
m_ps_srv[0] = srv0;
m_ps_srv[1] = srv1;
m_state.ps_srv[0] = srv0;
m_state.ps_srv[1] = srv1;
ID3D10ShaderResourceView* srvs[] = {srv0, srv1};
@ -655,16 +664,16 @@ void GSDevice10::PSSetShaderResources(GSTexture* sr0, GSTexture* sr1)
void GSDevice10::PSSetShader(ID3D10PixelShader* ps, ID3D10Buffer* ps_cb)
{
if(m_ps != ps)
if(m_state.ps != ps)
{
m_ps = ps;
m_state.ps = ps;
m_dev->PSSetShader(ps);
}
if(m_ps_cb != ps_cb)
if(m_state.ps_cb != ps_cb)
{
m_ps_cb = ps_cb;
m_state.ps_cb = ps_cb;
m_dev->PSSetConstantBuffers(0, 1, &ps_cb);
}
@ -672,10 +681,10 @@ void GSDevice10::PSSetShader(ID3D10PixelShader* ps, ID3D10Buffer* ps_cb)
void GSDevice10::PSSetSamplerState(ID3D10SamplerState* ss0, ID3D10SamplerState* ss1)
{
if(m_ps_ss[0] != ss0 || m_ps_ss[1] != ss1)
if(m_state.ps_ss[0] != ss0 || m_state.ps_ss[1] != ss1)
{
m_ps_ss[0] = ss0;
m_ps_ss[1] = ss1;
m_state.ps_ss[0] = ss0;
m_state.ps_ss[1] = ss1;
ID3D10SamplerState* sss[] = {ss0, ss1};
@ -685,10 +694,10 @@ void GSDevice10::PSSetSamplerState(ID3D10SamplerState* ss0, ID3D10SamplerState*
void GSDevice10::OMSetDepthStencilState(ID3D10DepthStencilState* dss, uint8 sref)
{
if(m_dss != dss || m_sref != sref)
if(m_state.dss != dss || m_state.sref != sref)
{
m_dss = dss;
m_sref = sref;
m_state.dss = dss;
m_state.sref = sref;
m_dev->OMSetDepthStencilState(dss, sref);
}
@ -696,10 +705,10 @@ void GSDevice10::OMSetDepthStencilState(ID3D10DepthStencilState* dss, uint8 sref
void GSDevice10::OMSetBlendState(ID3D10BlendState* bs, float bf)
{
if(m_bs != bs || m_bf != bf)
if(m_state.bs != bs || m_state.bf != bf)
{
m_bs = bs;
m_bf = bf;
m_state.bs = bs;
m_state.bf = bf;
float BlendFactor[] = {bf, bf, bf, 0};
@ -715,17 +724,17 @@ void GSDevice10::OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVector
if(rt) rtv = *(GSTexture10*)rt;
if(ds) dsv = *(GSTexture10*)ds;
if(m_rtv != rtv || m_dsv != dsv)
if(m_state.rtv != rtv || m_state.dsv != dsv)
{
m_rtv = rtv;
m_dsv = dsv;
m_state.rtv = rtv;
m_state.dsv = dsv;
m_dev->OMSetRenderTargets(1, &rtv, dsv);
}
if(m_viewport != rt->m_size)
if(m_state.viewport != rt->GetSize())
{
m_viewport = rt->m_size;
m_state.viewport = rt->GetSize();
D3D10_VIEWPORT vp;
@ -733,19 +742,19 @@ void GSDevice10::OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVector
vp.TopLeftX = 0;
vp.TopLeftY = 0;
vp.Width = rt->m_size.x;
vp.Height = rt->m_size.y;
vp.Width = rt->GetWidth();
vp.Height = rt->GetHeight();
vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f;
m_dev->RSSetViewports(1, &vp);
}
GSVector4i r = scissor ? *scissor : GSVector4i(rt->m_size).zwxy();
GSVector4i r = scissor ? *scissor : GSVector4i(rt->GetSize()).zwxy();
if(!m_scissor.eq(r))
if(!m_state.scissor.eq(r))
{
m_scissor = r;
m_state.scissor = r;
m_dev->RSSetScissorRects(1, r);
}

View File

@ -26,29 +26,7 @@
class GSDevice10 : public GSDevice
{
ID3D10Buffer* m_vb;
size_t m_vb_stride;
ID3D10InputLayout* m_layout;
D3D10_PRIMITIVE_TOPOLOGY m_topology;
ID3D10VertexShader* m_vs;
ID3D10Buffer* m_vs_cb;
ID3D10GeometryShader* m_gs;
ID3D10ShaderResourceView* m_ps_srv[2];
ID3D10PixelShader* m_ps;
ID3D10Buffer* m_ps_cb;
ID3D10SamplerState* m_ps_ss[2];
GSVector2i m_viewport;
GSVector4i m_scissor;
ID3D10DepthStencilState* m_dss;
uint8 m_sref;
ID3D10BlendState* m_bs;
float m_bf;
ID3D10RenderTargetView* m_rtv;
ID3D10DepthStencilView* m_dsv;
//
GSTexture* Create(int type, int w, int h, int format);
GSTexture* Create(int type, int w, int h, bool msaa, int format);
void DoMerge(GSTexture* st[2], GSVector4* sr, GSVector4* dr, GSTexture* dt, bool slbg, bool mmod, const GSVector4& c);
void DoInterlace(GSTexture* st, GSTexture* dt, int shader, bool linear, float yoffset = 0);
@ -57,12 +35,31 @@ class GSDevice10 : public GSDevice
CComPtr<ID3D10Device1> m_dev;
CComPtr<IDXGISwapChain> m_swapchain;
CComPtr<ID3D10Buffer> m_vb;
CComPtr<ID3D10Buffer> m_vb_old;
struct
{
CComPtr<ID3D10Buffer> vb, vb_old;
size_t stride, start, count, limit;
} m_vertices;
ID3D10Buffer* vb;
size_t vb_stride;
ID3D10InputLayout* layout;
D3D10_PRIMITIVE_TOPOLOGY topology;
ID3D10VertexShader* vs;
ID3D10Buffer* vs_cb;
ID3D10GeometryShader* gs;
ID3D10ShaderResourceView* ps_srv[2];
ID3D10PixelShader* ps;
ID3D10Buffer* ps_cb;
ID3D10SamplerState* ps_ss[2];
GSVector2i viewport;
GSVector4i scissor;
ID3D10DepthStencilState* dss;
uint8 sref;
ID3D10BlendState* bs;
float bf;
ID3D10RenderTargetView* rtv;
ID3D10DepthStencilView* dsv;
} m_state;
public: // TODO
CComPtr<ID3D10RasterizerState> m_rs;
@ -99,20 +96,20 @@ public:
bool Reset(int w, int h, int mode);
void Flip(bool limit);
void BeginScene();
void DrawPrimitive();
void EndScene();
void ClearRenderTarget(GSTexture* t, const GSVector4& c);
void ClearRenderTarget(GSTexture* t, uint32 c);
void ClearDepth(GSTexture* t, float c);
void ClearStencil(GSTexture* t, uint8 c);
GSTexture* CreateRenderTarget(int w, int h, int format = 0);
GSTexture* CreateDepthStencil(int w, int h, int format = 0);
GSTexture* CreateRenderTarget(int w, int h, bool msaa, int format = 0);
GSTexture* CreateDepthStencil(int w, int h, bool msaa, int format = 0);
GSTexture* CreateTexture(int w, int h, int format = 0);
GSTexture* CreateOffscreen(int w, int h, int format = 0);
GSTexture* Resolve(GSTexture* t);
GSTexture* CopyOffscreen(GSTexture* src, const GSVector4& sr, int w, int h, int format = 0);
void CopyRect(GSTexture* st, GSTexture* dt, const GSVector4i& r);

View File

@ -25,31 +25,11 @@
#include "resource.h"
GSDevice11::GSDevice11()
: m_vb(NULL)
, m_vb_stride(0)
, m_layout(NULL)
, m_topology(D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED)
, m_vs(NULL)
, m_vs_cb(NULL)
, m_gs(NULL)
, m_ps(NULL)
, m_ps_cb(NULL)
, m_scissor(0, 0, 0, 0)
, m_viewport(0, 0)
, m_dss(NULL)
, m_sref(0)
, m_bs(NULL)
, m_bf(-1)
, m_rtv(NULL)
, m_dsv(NULL)
{
memset(m_ps_srv, 0, sizeof(m_ps_srv));
memset(m_ps_ss, 0, sizeof(m_ps_ss));
memset(&m_state, 0, sizeof(m_state));
m_vertices.stride = 0;
m_vertices.start = 0;
m_vertices.count = 0;
m_vertices.limit = 0;
m_state.topology = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED;
m_state.bf = -1;
}
GSDevice11::~GSDevice11()
@ -63,7 +43,7 @@ bool GSDevice11::Create(GSWnd* wnd, bool vsync)
return false;
}
HRESULT hr;
HRESULT hr = E_FAIL;
DXGI_SWAP_CHAIN_DESC scd;
D3D11_BUFFER_DESC bd;
@ -86,7 +66,7 @@ bool GSDevice11::Create(GSWnd* wnd, bool vsync)
scd.SampleDesc.Quality = 0;
scd.Windowed = TRUE;
uint32 flags = D3D11_CREATE_DEVICE_SINGLETHREADED; //disables thread safety, should be fine (speedup)
uint32 flags = D3D11_CREATE_DEVICE_SINGLETHREADED;
#ifdef DEBUG
flags |= D3D11_CREATE_DEVICE_DEBUG;
@ -115,6 +95,22 @@ bool GSDevice11::Create(GSWnd* wnd, bool vsync)
hr = m_dev->CheckFeatureSupport(D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, &options, sizeof(D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS));
// msaa
for(uint32 i = 2; i <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; i++)
{
uint32 quality[2] = {0, 0};
if(SUCCEEDED(m_dev->CheckMultisampleQualityLevels(DXGI_FORMAT_R8G8B8A8_UNORM, i, &quality[0])) && quality[0] > 0
&& SUCCEEDED(m_dev->CheckMultisampleQualityLevels(DXGI_FORMAT_D32_FLOAT_S8X24_UINT, i, &quality[1])) && quality[1] > 0)
{
m_msaa_desc.Count = i;
m_msaa_desc.Quality = std::min<uint32>(quality[0] - 1, quality[1] - 1);
if(i >= m_msaa) break;
}
}
// convert
D3D11_INPUT_ELEMENT_DESC il_convert[] =
@ -198,7 +194,7 @@ bool GSDevice11::Create(GSWnd* wnd, bool vsync)
rd.SlopeScaledDepthBias = 0;
rd.DepthClipEnable = false; // ???
rd.ScissorEnable = true;
rd.MultisampleEnable = false;
rd.MultisampleEnable = true;
rd.AntialiasedLineEnable = false;
hr = m_dev->CreateRasterizerState(&rd, &m_rs);
@ -257,27 +253,11 @@ void GSDevice11::Flip(bool limit)
m_swapchain->Present(m_vsync && limit ? 1 : 0, 0);
}
void GSDevice11::BeginScene()
{
}
void GSDevice11::DrawPrimitive()
{
m_ctx->Draw(m_vertices.count, m_vertices.start);
}
void GSDevice11::EndScene()
{
PSSetShaderResources(NULL, NULL);
// not clearing the rt/ds gives a little fps boost in complex games (5-10%)
// OMSetRenderTargets(NULL, NULL);
m_vertices.start += m_vertices.count;
m_vertices.count = 0;
}
void GSDevice11::ClearRenderTarget(GSTexture* t, const GSVector4& c)
{
m_ctx->ClearRenderTargetView(*(GSTexture11*)t, c.v);
@ -300,7 +280,7 @@ void GSDevice11::ClearStencil(GSTexture* t, uint8 c)
m_ctx->ClearDepthStencilView(*(GSTexture11*)t, D3D11_CLEAR_STENCIL, 0, c);
}
GSTexture* GSDevice11::Create(int type, int w, int h, int format)
GSTexture* GSDevice11::Create(int type, int w, int h, bool msaa, int format)
{
HRESULT hr;
@ -317,6 +297,11 @@ GSTexture* GSDevice11::Create(int type, int w, int h, int format)
desc.SampleDesc.Quality = 0;
desc.Usage = D3D11_USAGE_DEFAULT;
if(msaa)
{
desc.SampleDesc = m_msaa_desc;
}
switch(type)
{
case GSTexture::RenderTarget:
@ -358,14 +343,14 @@ GSTexture* GSDevice11::Create(int type, int w, int h, int format)
return t;
}
GSTexture* GSDevice11::CreateRenderTarget(int w, int h, int format)
GSTexture* GSDevice11::CreateRenderTarget(int w, int h, bool msaa, int format)
{
return __super::CreateRenderTarget(w, h, format ? format : DXGI_FORMAT_R8G8B8A8_UNORM);
return __super::CreateRenderTarget(w, h, msaa, format ? format : DXGI_FORMAT_R8G8B8A8_UNORM);
}
GSTexture* GSDevice11::CreateDepthStencil(int w, int h, int format)
GSTexture* GSDevice11::CreateDepthStencil(int w, int h, bool msaa, int format)
{
return __super::CreateDepthStencil(w, h, format ? format : DXGI_FORMAT_D32_FLOAT_S8X24_UINT);
return __super::CreateDepthStencil(w, h, msaa, format ? format : DXGI_FORMAT_D32_FLOAT_S8X24_UINT);
}
GSTexture* GSDevice11::CreateTexture(int w, int h, int format)
@ -378,6 +363,22 @@ GSTexture* GSDevice11::CreateOffscreen(int w, int h, int format)
return __super::CreateOffscreen(w, h, format ? format : DXGI_FORMAT_R8G8B8A8_UNORM);
}
GSTexture* GSDevice11::Resolve(GSTexture* t)
{
ASSERT(t != NULL && t->IsMSAA());
if(GSTexture* dst = CreateRenderTarget(t->GetWidth(), t->GetHeight(), false, t->GetFormat()))
{
dst->SetScale(t->GetScale());
m_ctx->ResolveSubresource(*(GSTexture11*)dst, 0, *(GSTexture11*)t, 0, (DXGI_FORMAT)t->GetFormat());
return dst;
}
return NULL;
}
GSTexture* GSDevice11::CopyOffscreen(GSTexture* src, const GSVector4& sr, int w, int h, int format)
{
GSTexture* dst = NULL;
@ -394,11 +395,16 @@ GSTexture* GSDevice11::CopyOffscreen(GSTexture* src, const GSVector4& sr, int w,
return false;
}
if(GSTexture* rt = CreateRenderTarget(w, h, format))
if(GSTexture* rt = CreateRenderTarget(w, h, false, format))
{
GSVector4 dr(0, 0, w, h);
StretchRect(src, sr, rt, dr, m_convert.ps[format == DXGI_FORMAT_R16_UINT ? 1 : 0], NULL);
if(GSTexture* src2 = src->IsMSAA() ? Resolve(src) : src)
{
StretchRect(src2, sr, rt, dr, m_convert.ps[format == DXGI_FORMAT_R16_UINT ? 1 : 0], NULL);
if(src2 != src) Recycle(src2);
}
dst = CreateOffscreen(w, h, format);
@ -482,6 +488,8 @@ void GSDevice11::StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt,
//
EndScene();
PSSetShaderResources(NULL, NULL);
}
void GSDevice11::DoMerge(GSTexture* st[2], GSVector4* sr, GSVector4* dr, GSTexture* dt, bool slbg, bool mmod, const GSVector4& c)
@ -524,14 +532,15 @@ void GSDevice11::IASetVertexBuffer(const void* vertices, size_t stride, size_t c
if(count * stride > m_vertices.limit * m_vertices.stride)
{
m_vertices.vb_old = m_vertices.vb;
m_vertices.vb = NULL;
m_vb_old = m_vb;
m_vb = NULL;
m_vertices.start = 0;
m_vertices.count = 0;
m_vertices.limit = std::max<int>(count * 3 / 2, 10000);
}
if(m_vertices.vb == NULL)
if(m_vb == NULL)
{
D3D11_BUFFER_DESC bd;
@ -544,7 +553,7 @@ void GSDevice11::IASetVertexBuffer(const void* vertices, size_t stride, size_t c
HRESULT hr;
hr = m_dev->CreateBuffer(&bd, NULL, &m_vertices.vb);
hr = m_dev->CreateBuffer(&bd, NULL, &m_vb);
if(FAILED(hr)) return;
}
@ -560,25 +569,25 @@ void GSDevice11::IASetVertexBuffer(const void* vertices, size_t stride, size_t c
D3D11_MAPPED_SUBRESOURCE m;
if(SUCCEEDED(m_ctx->Map(m_vertices.vb, 0, type, 0, &m)))
if(SUCCEEDED(m_ctx->Map(m_vb, 0, type, 0, &m)))
{
GSVector4i::storent((uint8*)m.pData + m_vertices.start * stride, vertices, count * stride);
m_ctx->Unmap(m_vertices.vb, 0);
m_ctx->Unmap(m_vb, 0);
}
m_vertices.count = count;
m_vertices.stride = stride;
IASetVertexBuffer(m_vertices.vb, stride);
IASetVertexBuffer(m_vb, stride);
}
void GSDevice11::IASetVertexBuffer(ID3D11Buffer* vb, size_t stride)
{
if(m_vb != vb || m_vb_stride != stride)
if(m_state.vb != vb || m_state.vb_stride != stride)
{
m_vb = vb;
m_vb_stride = stride;
m_state.vb = vb;
m_state.vb_stride = stride;
uint32 offset = 0;
@ -588,9 +597,9 @@ void GSDevice11::IASetVertexBuffer(ID3D11Buffer* vb, size_t stride)
void GSDevice11::IASetInputLayout(ID3D11InputLayout* layout)
{
if(m_layout != layout)
if(m_state.layout != layout)
{
m_layout = layout;
m_state.layout = layout;
m_ctx->IASetInputLayout(layout);
}
@ -598,9 +607,9 @@ void GSDevice11::IASetInputLayout(ID3D11InputLayout* layout)
void GSDevice11::IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY topology)
{
if(m_topology != topology)
if(m_state.topology != topology)
{
m_topology = topology;
m_state.topology = topology;
m_ctx->IASetPrimitiveTopology(topology);
}
@ -608,16 +617,16 @@ void GSDevice11::IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY topology)
void GSDevice11::VSSetShader(ID3D11VertexShader* vs, ID3D11Buffer* vs_cb)
{
if(m_vs != vs)
if(m_state.vs != vs)
{
m_vs = vs;
m_state.vs = vs;
m_ctx->VSSetShader(vs, NULL, 0);
}
if(m_vs_cb != vs_cb)
if(m_state.vs_cb != vs_cb)
{
m_vs_cb = vs_cb;
m_state.vs_cb = vs_cb;
m_ctx->VSSetConstantBuffers(0, 1, &vs_cb);
}
@ -625,11 +634,11 @@ void GSDevice11::VSSetShader(ID3D11VertexShader* vs, ID3D11Buffer* vs_cb)
void GSDevice11::GSSetShader(ID3D11GeometryShader* gs)
{
if(m_gs != gs)
if(m_state.gs != gs)
{
m_ctx->GSSetShader(gs, NULL, 0);
m_state.gs = gs;
m_gs = gs;
m_ctx->GSSetShader(gs, NULL, 0);
}
}
@ -641,10 +650,10 @@ void GSDevice11::PSSetShaderResources(GSTexture* sr0, GSTexture* sr1)
if(sr0) srv0 = *(GSTexture11*)sr0;
if(sr1) srv1 = *(GSTexture11*)sr1;
if(m_ps_srv[0] != srv0 || m_ps_srv[1] != srv1)
if(m_state.ps_srv[0] != srv0 || m_state.ps_srv[1] != srv1)
{
m_ps_srv[0] = srv0;
m_ps_srv[1] = srv1;
m_state.ps_srv[0] = srv0;
m_state.ps_srv[1] = srv1;
ID3D11ShaderResourceView* srvs[] = {srv0, srv1};
@ -654,16 +663,16 @@ void GSDevice11::PSSetShaderResources(GSTexture* sr0, GSTexture* sr1)
void GSDevice11::PSSetShader(ID3D11PixelShader* ps, ID3D11Buffer* ps_cb)
{
if(m_ps != ps)
if(m_state.ps != ps)
{
m_ps = ps;
m_state.ps = ps;
m_ctx->PSSetShader(ps, NULL, 0);
}
if(m_ps_cb != ps_cb)
if(m_state.ps_cb != ps_cb)
{
m_ps_cb = ps_cb;
m_state.ps_cb = ps_cb;
m_ctx->PSSetConstantBuffers(0, 1, &ps_cb);
}
@ -671,10 +680,10 @@ void GSDevice11::PSSetShader(ID3D11PixelShader* ps, ID3D11Buffer* ps_cb)
void GSDevice11::PSSetSamplerState(ID3D11SamplerState* ss0, ID3D11SamplerState* ss1)
{
if(m_ps_ss[0] != ss0 || m_ps_ss[1] != ss1)
if(m_state.ps_ss[0] != ss0 || m_state.ps_ss[1] != ss1)
{
m_ps_ss[0] = ss0;
m_ps_ss[1] = ss1;
m_state.ps_ss[0] = ss0;
m_state.ps_ss[1] = ss1;
ID3D11SamplerState* sss[] = {ss0, ss1};
@ -684,25 +693,25 @@ void GSDevice11::PSSetSamplerState(ID3D11SamplerState* ss0, ID3D11SamplerState*
void GSDevice11::OMSetDepthStencilState(ID3D11DepthStencilState* dss, uint8 sref)
{
if(m_dss != dss || m_sref != sref)
if(m_state.dss != dss || m_state.sref != sref)
{
m_ctx->OMSetDepthStencilState(dss, sref);
m_state.dss = dss;
m_state.sref = sref;
m_dss = dss;
m_sref = sref;
m_ctx->OMSetDepthStencilState(dss, sref);
}
}
void GSDevice11::OMSetBlendState(ID3D11BlendState* bs, float bf)
{
if(m_bs != bs || m_bf != bf)
if(m_state.bs != bs || m_state.bf != bf)
{
m_state.bs = bs;
m_state.bf = bf;
float BlendFactor[] = {bf, bf, bf, 0};
m_ctx->OMSetBlendState(bs, BlendFactor, 0xffffffff);
m_bs = bs;
m_bf = bf;
}
}
@ -714,17 +723,17 @@ void GSDevice11::OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVector
if(rt) rtv = *(GSTexture11*)rt;
if(ds) dsv = *(GSTexture11*)ds;
if(m_rtv != rtv || m_dsv != dsv)
if(m_state.rtv != rtv || m_state.dsv != dsv)
{
m_rtv = rtv;
m_dsv = dsv;
m_state.rtv = rtv;
m_state.dsv = dsv;
m_ctx->OMSetRenderTargets(1, &rtv, dsv);
}
if(m_viewport != rt->m_size)
if(m_state.viewport != rt->GetSize())
{
m_viewport = rt->m_size;
m_state.viewport = rt->GetSize();
D3D11_VIEWPORT vp;
@ -732,19 +741,19 @@ void GSDevice11::OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVector
vp.TopLeftX = 0;
vp.TopLeftY = 0;
vp.Width = rt->m_size.x;
vp.Height = rt->m_size.y;
vp.Width = rt->GetWidth();
vp.Height = rt->GetHeight();
vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f;
m_ctx->RSSetViewports(1, &vp);
}
GSVector4i r = scissor ? *scissor : GSVector4i(rt->m_size).zwxy();
GSVector4i r = scissor ? *scissor : GSVector4i(rt->GetSize()).zwxy();
if(!m_scissor.eq(r))
if(!m_state.scissor.eq(r))
{
m_scissor = r;
m_state.scissor = r;
m_ctx->RSSetScissorRects(1, r);
}

View File

@ -26,29 +26,7 @@
class GSDevice11 : public GSDevice
{
ID3D11Buffer* m_vb;
size_t m_vb_stride;
ID3D11InputLayout* m_layout;
D3D11_PRIMITIVE_TOPOLOGY m_topology;
ID3D11VertexShader* m_vs;
ID3D11Buffer* m_vs_cb;
ID3D11GeometryShader* m_gs;
ID3D11ShaderResourceView* m_ps_srv[2];
ID3D11PixelShader* m_ps;
ID3D11Buffer* m_ps_cb;
ID3D11SamplerState* m_ps_ss[2];
GSVector2i m_viewport;
GSVector4i m_scissor;
ID3D11DepthStencilState* m_dss;
uint8 m_sref;
ID3D11BlendState* m_bs;
float m_bf;
ID3D11RenderTargetView* m_rtv;
ID3D11DepthStencilView* m_dsv;
//
GSTexture* Create(int type, int w, int h, int format);
GSTexture* Create(int type, int w, int h, bool msaa, int format);
void DoMerge(GSTexture* st[2], GSVector4* sr, GSVector4* dr, GSTexture* dt, bool slbg, bool mmod, const GSVector4& c);
void DoInterlace(GSTexture* st, GSTexture* dt, int shader, bool linear, float yoffset = 0);
@ -58,12 +36,31 @@ class GSDevice11 : public GSDevice
CComPtr<ID3D11Device> m_dev;
CComPtr<ID3D11DeviceContext> m_ctx;
CComPtr<IDXGISwapChain> m_swapchain;
CComPtr<ID3D11Buffer> m_vb;
CComPtr<ID3D11Buffer> m_vb_old;
struct
{
CComPtr<ID3D11Buffer> vb, vb_old;
size_t stride, start, count, limit;
} m_vertices;
ID3D11Buffer* vb;
size_t vb_stride;
ID3D11InputLayout* layout;
D3D11_PRIMITIVE_TOPOLOGY topology;
ID3D11VertexShader* vs;
ID3D11Buffer* vs_cb;
ID3D11GeometryShader* gs;
ID3D11ShaderResourceView* ps_srv[2];
ID3D11PixelShader* ps;
ID3D11Buffer* ps_cb;
ID3D11SamplerState* ps_ss[2];
GSVector2i viewport;
GSVector4i scissor;
ID3D11DepthStencilState* dss;
uint8 sref;
ID3D11BlendState* bs;
float bf;
ID3D11RenderTargetView* rtv;
ID3D11DepthStencilView* dsv;
} m_state;
public: // TODO
CComPtr<ID3D11RasterizerState> m_rs;
@ -100,20 +97,20 @@ public:
bool Reset(int w, int h, int mode);
void Flip(bool limit);
void BeginScene();
void DrawPrimitive();
void EndScene();
void ClearRenderTarget(GSTexture* t, const GSVector4& c);
void ClearRenderTarget(GSTexture* t, uint32 c);
void ClearDepth(GSTexture* t, float c);
void ClearStencil(GSTexture* t, uint8 c);
GSTexture* CreateRenderTarget(int w, int h, int format = 0);
GSTexture* CreateDepthStencil(int w, int h, int format = 0);
GSTexture* CreateRenderTarget(int w, int h, bool msaa, int format = 0);
GSTexture* CreateDepthStencil(int w, int h, bool msaa, int format = 0);
GSTexture* CreateTexture(int w, int h, int format = 0);
GSTexture* CreateOffscreen(int w, int h, int format = 0);
GSTexture* Resolve(GSTexture* t);
GSTexture* CopyOffscreen(GSTexture* src, const GSVector4& sr, int w, int h, int format = 0);
void CopyRect(GSTexture* st, GSTexture* dt, const GSVector4i& r);

View File

@ -145,7 +145,7 @@ void GSDevice7::Present(const GSVector4i& r, int shader, bool limit)
int w = std::max<int>(cr.width(), 1);
int h = std::max<int>(cr.height(), 1);
if(!m_backbuffer || m_backbuffer->m_size.x != w || m_backbuffer->m_size.y != h)
if(!m_backbuffer || m_backbuffer->GetWidth() != w || m_backbuffer->GetHeight() != h)
{
if(!Reset(w, h, DontCare))
{
@ -198,7 +198,7 @@ void GSDevice7::Present(const GSVector4i& r, int shader, bool limit)
}
}
GSTexture* GSDevice7::Create(int type, int w, int h, int format)
GSTexture* GSDevice7::Create(int type, int w, int h, bool msaa, int format)
{
HRESULT hr;

View File

@ -31,7 +31,7 @@ private:
CComPtr<IDirectDrawSurface7> m_primary;
bool m_lost;
GSTexture* Create(int type, int w, int h, int format);
GSTexture* Create(int type, int w, int h, bool msaa, int format);
void DoMerge(GSTexture* st[2], GSVector4* sr, GSVector4* dr, GSTexture* dt, bool slbg, bool mmod, const GSVector4& c);
void DoInterlace(GSTexture* st, GSTexture* dt, int shader, bool linear, float yoffset = 0);

View File

@ -25,42 +25,23 @@
#include "resource.h"
GSDevice9::GSDevice9()
: m_vb(NULL)
, m_vb_stride(0)
, m_layout(NULL)
, m_topology((D3DPRIMITIVETYPE)0)
, m_vs(NULL)
, m_vs_cb(NULL)
, m_vs_cb_len(0)
, m_ps(NULL)
, m_ps_cb(NULL)
, m_ps_cb_len(0)
, m_ps_ss(NULL)
, m_scissor(0, 0, 0, 0)
, m_dss(NULL)
, m_bs(NULL)
, m_bf(0xffffffff)
, m_rtv(NULL)
, m_dsv(NULL)
, m_lost(false)
: m_lost(false)
{
m_rbswapped = true;
memset(&m_pp, 0, sizeof(m_pp));
memset(&m_ddcaps, 0, sizeof(m_ddcaps));
memset(&m_d3dcaps, 0, sizeof(m_d3dcaps));
memset(m_ps_srvs, 0, sizeof(m_ps_srvs));
m_vertices.stride = 0;
m_vertices.start = 0;
m_vertices.count = 0;
m_vertices.limit = 0;
memset(&m_state, 0, sizeof(m_state));
m_state.bf = 0xffffffff;
}
GSDevice9::~GSDevice9()
{
if(m_vs_cb) _aligned_free(m_vs_cb);
if(m_ps_cb) _aligned_free(m_ps_cb);
if(m_state.vs_cb) _aligned_free(m_state.vs_cb);
if(m_state.ps_cb) _aligned_free(m_state.ps_cb);
}
bool GSDevice9::Create(GSWnd* wnd, bool vsync)
@ -112,9 +93,14 @@ bool GSDevice9::Create(GSWnd* wnd, bool vsync)
if(m_d3dcaps.VertexShaderVersion < (m_d3dcaps.PixelShaderVersion & ~0x10000))
{
ASSERT(0);
if(m_d3dcaps.VertexShaderVersion > D3DVS_VERSION(0, 0))
{
ASSERT(0);
return false;
return false;
}
// else vertex shader should be emulated in software (gma950)
}
m_d3dcaps.VertexShaderVersion = m_d3dcaps.PixelShaderVersion & ~0x10000;
@ -138,6 +124,22 @@ bool GSDevice9::Create(GSWnd* wnd, bool vsync)
return false;
}
// msaa
for(uint32 i = 2; i <= 16; i++)
{
DWORD quality[2] = {0, 0};
if(SUCCEEDED(m_d3d->CheckDeviceMultiSampleType(m_d3dcaps.AdapterOrdinal, m_d3dcaps.DeviceType, D3DFMT_A8R8G8B8, TRUE, (D3DMULTISAMPLE_TYPE)i, &quality[0])) && quality[0] > 0
&& SUCCEEDED(m_d3d->CheckDeviceMultiSampleType(m_d3dcaps.AdapterOrdinal, m_d3dcaps.DeviceType, D3DFMT_D24S8, TRUE, (D3DMULTISAMPLE_TYPE)i, &quality[1])) && quality[1] > 0)
{
m_msaa_desc.Count = i;
m_msaa_desc.Quality = std::min<DWORD>(quality[0] - 1, quality[1] - 1);
if(i >= m_msaa) break;
}
}
//
if(!Reset(1, 1, theApp.GetConfig("windowed", 1) ? Windowed : Fullscreen))
@ -246,30 +248,18 @@ bool GSDevice9::Reset(int w, int h, int mode)
m_swapchain = NULL;
m_vertices.vb = NULL;
m_vertices.vb_old = NULL;
m_vb = NULL;
m_vb_old = NULL;
m_vertices.start = 0;
m_vertices.count = 0;
if(m_vs_cb) _aligned_free(m_vs_cb);
if(m_ps_cb) _aligned_free(m_ps_cb);
if(m_state.vs_cb) _aligned_free(m_state.vs_cb);
if(m_state.ps_cb) _aligned_free(m_state.ps_cb);
m_vb = NULL;
m_vb_stride = 0;
m_layout = NULL;
m_vs = NULL;
m_vs_cb = NULL;
m_vs_cb_len = 0;
m_ps = NULL;
m_ps_cb = NULL;
m_ps_cb_len = 0;
m_ps_ss = NULL;
m_scissor = GSVector4i::zero();
m_dss = NULL;
m_bs = NULL;
m_bf = 0xffffffff;
m_rtv = NULL;
m_dsv = NULL;
memset(&m_state, 0, sizeof(m_state));
m_state.bf = 0xffffffff;
memset(&m_pp, 0, sizeof(m_pp));
@ -304,9 +294,13 @@ bool GSDevice9::Reset(int w, int h, int mode)
if(!m_dev)
{
//D3DCREATE_MULTITHREADED flag shouldn't be needed
uint32 flags = m_d3dcaps.VertexProcessingCaps ? D3DCREATE_HARDWARE_VERTEXPROCESSING : D3DCREATE_SOFTWARE_VERTEXPROCESSING;
if(flags & D3DCREATE_HARDWARE_VERTEXPROCESSING)
{
flags |= D3DCREATE_PUREDEVICE;
}
hr = m_d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, (HWND)m_wnd->GetHandle(), flags, &m_pp, &m_dev);
if(FAILED(hr)) return false;
@ -403,7 +397,7 @@ void GSDevice9::DrawPrimitive()
{
int prims = 0;
switch(m_topology)
switch(m_state.topology)
{
case D3DPT_TRIANGLELIST:
prims = m_vertices.count / 3;
@ -423,15 +417,14 @@ void GSDevice9::DrawPrimitive()
break;
}
m_dev->DrawPrimitive(m_topology, m_vertices.start, prims);
m_dev->DrawPrimitive(m_state.topology, m_vertices.start, prims);
}
void GSDevice9::EndScene()
{
// m_dev->EndScene();
m_vertices.start += m_vertices.count;
m_vertices.count = 0;
__super::EndScene();
}
void GSDevice9::ClearRenderTarget(GSTexture* t, const GSVector4& c)
@ -450,7 +443,7 @@ void GSDevice9::ClearRenderTarget(GSTexture* rt, uint32 c)
void GSDevice9::ClearDepth(GSTexture* t, float c)
{
GSTexture* rt = CreateRenderTarget(t->m_size.x, t->m_size.y);
GSTexture* rt = CreateRenderTarget(t->GetWidth(), t->GetHeight(), t->IsMSAA());
CComPtr<IDirect3DSurface9> rtsurface;
CComPtr<IDirect3DSurface9> dssurface;
@ -471,7 +464,7 @@ void GSDevice9::ClearDepth(GSTexture* t, float c)
void GSDevice9::ClearStencil(GSTexture* t, uint8 c)
{
GSTexture* rt = CreateRenderTarget(t->m_size.x, t->m_size.y);
GSTexture* rt = CreateRenderTarget(t->GetWidth(), t->GetHeight(), t->IsMSAA());
CComPtr<IDirect3DSurface9> rtsurface;
CComPtr<IDirect3DSurface9> dssurface;
@ -490,7 +483,7 @@ void GSDevice9::ClearStencil(GSTexture* t, uint8 c)
Recycle(rt);
}
GSTexture* GSDevice9::Create(int type, int w, int h, int format)
GSTexture* GSDevice9::Create(int type, int w, int h, bool msaa, int format)
{
HRESULT hr;
@ -500,10 +493,12 @@ GSTexture* GSDevice9::Create(int type, int w, int h, int format)
switch(type)
{
case GSTexture::RenderTarget:
hr = m_dev->CreateTexture(w, h, 1, D3DUSAGE_RENDERTARGET, (D3DFORMAT)format, D3DPOOL_DEFAULT, &texture, NULL);
if(msaa) hr = m_dev->CreateRenderTarget(w, h, (D3DFORMAT)format, (D3DMULTISAMPLE_TYPE)m_msaa_desc.Count, m_msaa_desc.Quality, FALSE, &surface, NULL);
else hr = m_dev->CreateTexture(w, h, 1, D3DUSAGE_RENDERTARGET, (D3DFORMAT)format, D3DPOOL_DEFAULT, &texture, NULL);
break;
case GSTexture::DepthStencil:
hr = m_dev->CreateDepthStencilSurface(w, h, (D3DFORMAT)format, D3DMULTISAMPLE_NONE, 0, FALSE, &surface, NULL);
if(msaa) hr = m_dev->CreateDepthStencilSurface(w, h, (D3DFORMAT)format, (D3DMULTISAMPLE_TYPE)m_msaa_desc.Count, m_msaa_desc.Quality, FALSE, &surface, NULL);
else hr = m_dev->CreateDepthStencilSurface(w, h, (D3DFORMAT)format, D3DMULTISAMPLE_NONE, 0, FALSE, &surface, NULL);
break;
case GSTexture::Texture:
hr = m_dev->CreateTexture(w, h, 1, 0, (D3DFORMAT)format, D3DPOOL_MANAGED, &texture, NULL);
@ -541,14 +536,14 @@ GSTexture* GSDevice9::Create(int type, int w, int h, int format)
return t;
}
GSTexture* GSDevice9::CreateRenderTarget(int w, int h, int format)
GSTexture* GSDevice9::CreateRenderTarget(int w, int h, bool msaa, int format)
{
return __super::CreateRenderTarget(w, h, format ? format : D3DFMT_A8R8G8B8);
return __super::CreateRenderTarget(w, h, msaa, format ? format : D3DFMT_A8R8G8B8);
}
GSTexture* GSDevice9::CreateDepthStencil(int w, int h, int format)
GSTexture* GSDevice9::CreateDepthStencil(int w, int h, bool msaa, int format)
{
return __super::CreateDepthStencil(w, h, format ? format : D3DFMT_D24S8);
return __super::CreateDepthStencil(w, h, msaa, format ? format : D3DFMT_D24S8);
}
GSTexture* GSDevice9::CreateTexture(int w, int h, int format)
@ -561,6 +556,22 @@ GSTexture* GSDevice9::CreateOffscreen(int w, int h, int format)
return __super::CreateOffscreen(w, h, format ? format : D3DFMT_A8R8G8B8);
}
GSTexture* GSDevice9::Resolve(GSTexture* t)
{
ASSERT(t != NULL && t->IsMSAA());
if(GSTexture* dst = CreateRenderTarget(t->GetWidth(), t->GetHeight(), false, t->GetFormat()))
{
dst->SetScale(t->GetScale());
m_dev->StretchRect(*(GSTexture9*)t, NULL, *(GSTexture9*)dst, NULL, D3DTEXF_POINT);
return dst;
}
return NULL;
}
GSTexture* GSDevice9::CopyOffscreen(GSTexture* src, const GSVector4& sr, int w, int h, int format)
{
GSTexture* dst = NULL;
@ -577,11 +588,16 @@ GSTexture* GSDevice9::CopyOffscreen(GSTexture* src, const GSVector4& sr, int w,
return false;
}
if(GSTexture* rt = CreateRenderTarget(w, h, format))
if(GSTexture* rt = CreateRenderTarget(w, h, false, format))
{
GSVector4 dr(0, 0, w, h);
StretchRect(src, sr, rt, dr, m_convert.ps[1], NULL, 0);
if(GSTexture* src2 = src->IsMSAA() ? Resolve(src) : src)
{
StretchRect(src2, sr, rt, dr, m_convert.ps[1], NULL, 0);
if(src2 != src) Recycle(src2);
}
dst = CreateOffscreen(w, h, format);
@ -707,18 +723,19 @@ void GSDevice9::IASetVertexBuffer(const void* vertices, size_t stride, size_t co
if(count * stride > m_vertices.limit * m_vertices.stride)
{
m_vertices.vb_old = m_vertices.vb;
m_vertices.vb = NULL;
m_vb_old = m_vb;
m_vb = NULL;
m_vertices.start = 0;
m_vertices.count = 0;
m_vertices.limit = std::max<int>(count * 3 / 2, 10000);
}
if(m_vertices.vb == NULL)
if(m_vb == NULL)
{
HRESULT hr;
hr = m_dev->CreateVertexBuffer(m_vertices.limit * stride, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &m_vertices.vb, NULL);
hr = m_dev->CreateVertexBuffer(m_vertices.limit * stride, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &m_vb, NULL);
if(FAILED(hr)) return;
}
@ -734,25 +751,25 @@ void GSDevice9::IASetVertexBuffer(const void* vertices, size_t stride, size_t co
void* v = NULL;
if(SUCCEEDED(m_vertices.vb->Lock(m_vertices.start * stride, count * stride, &v, flags)))
if(SUCCEEDED(m_vb->Lock(m_vertices.start * stride, count * stride, &v, flags)))
{
GSVector4i::storent(v, vertices, count * stride);
m_vertices.vb->Unlock();
m_vb->Unlock();
}
m_vertices.count = count;
m_vertices.stride = stride;
IASetVertexBuffer(m_vertices.vb, stride);
IASetVertexBuffer(m_vb, stride);
}
void GSDevice9::IASetVertexBuffer(IDirect3DVertexBuffer9* vb, size_t stride)
{
if(m_vb != vb || m_vb_stride != stride)
if(m_state.vb != vb || m_state.vb_stride != stride)
{
m_vb = vb;
m_vb_stride = stride;
m_state.vb = vb;
m_state.vb_stride = stride;
m_dev->SetStreamSource(0, vb, 0, stride);
}
@ -760,9 +777,9 @@ void GSDevice9::IASetVertexBuffer(IDirect3DVertexBuffer9* vb, size_t stride)
void GSDevice9::IASetInputLayout(IDirect3DVertexDeclaration9* layout)
{
if(m_layout != layout)
if(m_state.layout != layout)
{
m_layout = layout;
m_state.layout = layout;
m_dev->SetVertexDeclaration(layout);
}
@ -770,14 +787,14 @@ void GSDevice9::IASetInputLayout(IDirect3DVertexDeclaration9* layout)
void GSDevice9::IASetPrimitiveTopology(D3DPRIMITIVETYPE topology)
{
m_topology = topology;
m_state.topology = topology;
}
void GSDevice9::VSSetShader(IDirect3DVertexShader9* vs, const float* vs_cb, int vs_cb_len)
{
if(m_vs != vs)
if(m_state.vs != vs)
{
m_vs = vs;
m_state.vs = vs;
m_dev->SetVertexShader(vs);
}
@ -786,18 +803,18 @@ void GSDevice9::VSSetShader(IDirect3DVertexShader9* vs, const float* vs_cb, int
{
int size = vs_cb_len * sizeof(float) * 4;
if(m_vs_cb_len != vs_cb_len || m_vs_cb == NULL || memcmp(m_vs_cb, vs_cb, size))
if(m_state.vs_cb_len != vs_cb_len || m_state.vs_cb == NULL || memcmp(m_state.vs_cb, vs_cb, size))
{
if(m_vs_cb == NULL || m_vs_cb_len < vs_cb_len)
if(m_state.vs_cb == NULL || m_state.vs_cb_len < vs_cb_len)
{
if(m_vs_cb) _aligned_free(m_vs_cb);
if(m_state.vs_cb) _aligned_free(m_state.vs_cb);
m_vs_cb = (float*)_aligned_malloc(size, 16);
m_state.vs_cb = (float*)_aligned_malloc(size, 16);
}
m_vs_cb_len = vs_cb_len;
m_state.vs_cb_len = vs_cb_len;
memcpy(m_vs_cb, vs_cb, size);
memcpy(m_state.vs_cb, vs_cb, size);
m_dev->SetVertexShaderConstantF(0, vs_cb, vs_cb_len);
}
@ -812,16 +829,16 @@ void GSDevice9::PSSetShaderResources(GSTexture* sr0, GSTexture* sr1)
if(sr0) srv0 = *(GSTexture9*)sr0;
if(sr1) srv1 = *(GSTexture9*)sr1;
if(m_ps_srvs[0] != srv0)
if(m_state.ps_srvs[0] != srv0)
{
m_ps_srvs[0] = srv0;
m_state.ps_srvs[0] = srv0;
m_dev->SetTexture(0, srv0);
}
if(m_ps_srvs[1] != srv1)
if(m_state.ps_srvs[1] != srv1)
{
m_ps_srvs[1] = srv1;
m_state.ps_srvs[1] = srv1;
m_dev->SetTexture(1, srv1);
}
@ -829,9 +846,9 @@ void GSDevice9::PSSetShaderResources(GSTexture* sr0, GSTexture* sr1)
void GSDevice9::PSSetShader(IDirect3DPixelShader9* ps, const float* ps_cb, int ps_cb_len)
{
if(m_ps != ps)
if(m_state.ps != ps)
{
m_ps = ps;
m_state.ps = ps;
m_dev->SetPixelShader(ps);
}
@ -840,18 +857,18 @@ void GSDevice9::PSSetShader(IDirect3DPixelShader9* ps, const float* ps_cb, int p
{
int size = ps_cb_len * sizeof(float) * 4;
if(m_ps_cb_len != ps_cb_len || m_ps_cb == NULL || memcmp(m_ps_cb, ps_cb, size))
if(m_state.ps_cb_len != ps_cb_len || m_state.ps_cb == NULL || memcmp(m_state.ps_cb, ps_cb, size))
{
if(m_ps_cb == NULL || m_ps_cb_len < ps_cb_len)
if(m_state.ps_cb == NULL || m_state.ps_cb_len < ps_cb_len)
{
if(m_ps_cb) _aligned_free(m_ps_cb);
if(m_state.ps_cb) _aligned_free(m_state.ps_cb);
m_ps_cb = (float*)_aligned_malloc(size, 16);
m_state.ps_cb = (float*)_aligned_malloc(size, 16);
}
m_ps_cb_len = ps_cb_len;
m_state.ps_cb_len = ps_cb_len;
memcpy(m_ps_cb, ps_cb, size);
memcpy(m_state.ps_cb, ps_cb, size);
m_dev->SetPixelShaderConstantF(0, ps_cb, ps_cb_len);
}
@ -860,9 +877,9 @@ void GSDevice9::PSSetShader(IDirect3DPixelShader9* ps, const float* ps_cb, int p
void GSDevice9::PSSetSamplerState(Direct3DSamplerState9* ss)
{
if(ss && m_ps_ss != ss)
if(ss && m_state.ps_ss != ss)
{
m_ps_ss = ss;
m_state.ps_ss = ss;
m_dev->SetSamplerState(0, D3DSAMP_ADDRESSU, ss->AddressU);
m_dev->SetSamplerState(0, D3DSAMP_ADDRESSV, ss->AddressV);
@ -885,9 +902,9 @@ void GSDevice9::PSSetSamplerState(Direct3DSamplerState9* ss)
void GSDevice9::OMSetDepthStencilState(Direct3DDepthStencilState9* dss)
{
if(m_dss != dss)
if(m_state.dss != dss)
{
m_dss = dss;
m_state.dss = dss;
m_dev->SetRenderState(D3DRS_ZENABLE, dss->DepthEnable);
m_dev->SetRenderState(D3DRS_ZWRITEENABLE, dss->DepthWriteMask);
@ -914,10 +931,10 @@ void GSDevice9::OMSetDepthStencilState(Direct3DDepthStencilState9* dss)
void GSDevice9::OMSetBlendState(Direct3DBlendState9* bs, uint32 bf)
{
if(m_bs != bs || m_bf != bf)
if(m_state.bs != bs || m_state.bf != bf)
{
m_bs = bs;
m_bf = bf;
m_state.bs = bs;
m_state.bf = bf;
m_dev->SetRenderState(D3DRS_ALPHABLENDENABLE, bs->BlendEnable);
@ -945,25 +962,25 @@ void GSDevice9::OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVector4
if(rt) rtv = *(GSTexture9*)rt;
if(ds) dsv = *(GSTexture9*)ds;
if(m_rtv != rtv)
if(m_state.rtv != rtv)
{
m_rtv = rtv;
m_state.rtv = rtv;
m_dev->SetRenderTarget(0, rtv);
}
if(m_dsv != dsv)
if(m_state.dsv != dsv)
{
m_dsv = dsv;
m_state.dsv = dsv;
m_dev->SetDepthStencilSurface(dsv);
}
GSVector4i r = scissor ? *scissor : GSVector4i(rt->m_size).zwxy();
GSVector4i r = scissor ? *scissor : GSVector4i(rt->GetSize()).zwxy();
if(!m_scissor.eq(r))
if(!m_state.scissor.eq(r))
{
m_scissor = r;
m_state.scissor = r;
m_dev->SetScissorRect(r);
}

View File

@ -61,29 +61,7 @@ struct Direct3DBlendState9
class GSDevice9 : public GSDevice
{
private:
IDirect3DVertexBuffer9* m_vb;
size_t m_vb_stride;
IDirect3DVertexDeclaration9* m_layout;
D3DPRIMITIVETYPE m_topology;
IDirect3DVertexShader9* m_vs;
float* m_vs_cb;
int m_vs_cb_len;
IDirect3DTexture9* m_ps_srvs[2];
IDirect3DPixelShader9* m_ps;
float* m_ps_cb;
int m_ps_cb_len;
Direct3DSamplerState9* m_ps_ss;
GSVector4i m_scissor;
Direct3DDepthStencilState9* m_dss;
Direct3DBlendState9* m_bs;
uint32 m_bf;
IDirect3DSurface9* m_rtv;
IDirect3DSurface9* m_dsv;
//
GSTexture* Create(int type, int w, int h, int format);
GSTexture* Create(int type, int w, int h, bool msaa, int format);
void DoMerge(GSTexture* st[2], GSVector4* sr, GSVector4* dr, GSTexture* dt, bool slbg, bool mmod, const GSVector4& c);
void DoInterlace(GSTexture* st, GSTexture* dt, int shader, bool linear, float yoffset = 0);
@ -96,13 +74,31 @@ private:
CComPtr<IDirect3D9> m_d3d;
CComPtr<IDirect3DDevice9> m_dev;
CComPtr<IDirect3DSwapChain9> m_swapchain;
CComPtr<IDirect3DVertexBuffer9> m_vb;
CComPtr<IDirect3DVertexBuffer9> m_vb_old;
bool m_lost;
struct
{
CComPtr<IDirect3DVertexBuffer9> vb, vb_old;
size_t stride, start, count, limit;
} m_vertices;
IDirect3DVertexBuffer9* vb;
size_t vb_stride;
IDirect3DVertexDeclaration9* layout;
D3DPRIMITIVETYPE topology;
IDirect3DVertexShader9* vs;
float* vs_cb;
int vs_cb_len;
IDirect3DTexture9* ps_srvs[2];
IDirect3DPixelShader9* ps;
float* ps_cb;
int ps_cb_len;
Direct3DSamplerState9* ps_ss;
GSVector4i scissor;
Direct3DDepthStencilState9* dss;
Direct3DBlendState9* bs;
uint32 bf;
IDirect3DSurface9* rtv;
IDirect3DSurface9* dsv;
} m_state;
public: // TODO
@ -146,11 +142,13 @@ public:
void ClearDepth(GSTexture* t, float c);
void ClearStencil(GSTexture* t, uint8 c);
GSTexture* CreateRenderTarget(int w, int h, int format = 0);
GSTexture* CreateDepthStencil(int w, int h, int format = 0);
GSTexture* CreateRenderTarget(int w, int h, bool msaa, int format = 0);
GSTexture* CreateDepthStencil(int w, int h, bool msaa, int format = 0);
GSTexture* CreateTexture(int w, int h, int format = 0);
GSTexture* CreateOffscreen(int w, int h, int format = 0);
GSTexture* Resolve(GSTexture* t);
GSTexture* CopyOffscreen(GSTexture* src, const GSVector4& sr, int w, int h, int format = 0);
void CopyRect(GSTexture* st, GSTexture* dt, const GSVector4i& r);

View File

@ -42,7 +42,7 @@ bool GSDeviceNull::Reset(int w, int h, int mode)
return true;
}
GSTexture* GSDeviceNull::Create(int type, int w, int h, int format)
GSTexture* GSDeviceNull::Create(int type, int w, int h, bool msaa, int format)
{
return new GSTextureNull(type, w, h, format);
}

View File

@ -27,7 +27,7 @@
class GSDeviceNull : public GSDevice
{
private:
GSTexture* Create(int type, int w, int h, int format);
GSTexture* Create(int type, int w, int h, bool msaa, int format);
void DoMerge(GSTexture* st[2], GSVector4* sr, GSVector4* dr, GSTexture* dt, bool slbg, bool mmod, const GSVector4& c) {}
void DoInterlace(GSTexture* st, GSTexture* dt, int shader, bool linear, float yoffset = 0) {}

View File

@ -203,21 +203,11 @@ void GSDeviceOGL::Flip(bool limit)
#endif
}
void GSDeviceOGL::BeginScene()
{
}
void GSDeviceOGL::DrawPrimitive()
{
glDrawArrays(m_topology, m_vertices.count, m_vertices.start); CheckError();
}
void GSDeviceOGL::EndScene()
{
m_vertices.start += m_vertices.count;
m_vertices.count = 0;
}
void GSDeviceOGL::ClearRenderTarget(GSTexture* t, const GSVector4& c)
{
GLuint texture = *(GSTextureOGL*)t;
@ -262,7 +252,7 @@ void GSDeviceOGL::ClearStencil(GSTexture* t, uint8 c)
glClear(GL_STENCIL_BUFFER_BIT); CheckError();
}
GSTexture* GSDeviceOGL::Create(int type, int w, int h, int format)
GSTexture* GSDeviceOGL::Create(int type, int w, int h, bool msaa, int format)
{
GLuint texture = 0;
@ -306,14 +296,14 @@ GSTexture* GSDeviceOGL::Create(int type, int w, int h, int format)
return t;
}
GSTexture* GSDeviceOGL::CreateRenderTarget(int w, int h, int format)
GSTexture* GSDeviceOGL::CreateRenderTarget(int w, int h, bool msaa, int format)
{
return __super::CreateRenderTarget(w, h, format ? format : GL_RGBA8);
return __super::CreateRenderTarget(w, h, msaa, format ? format : GL_RGBA8);
}
GSTexture* GSDeviceOGL::CreateDepthStencil(int w, int h, int format)
GSTexture* GSDeviceOGL::CreateDepthStencil(int w, int h, bool msaa, int format)
{
return __super::CreateDepthStencil(w, h, format ? format : GL_DEPTH32F_STENCIL8); // TODO: GL_DEPTH24_STENCIL8_EXT, GL_DEPTH24_STENCIL8
return __super::CreateDepthStencil(w, h, msaa, format ? format : GL_DEPTH32F_STENCIL8); // TODO: GL_DEPTH24_STENCIL8_EXT, GL_DEPTH24_STENCIL8
}
GSTexture* GSDeviceOGL::CreateTexture(int w, int h, int format)
@ -519,14 +509,14 @@ void GSDeviceOGL::OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVecto
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT, dsi); CheckError();
}
if(m_viewport != rt->m_size)
if(m_viewport != rt->GetSize())
{
m_viewport = rt->m_size;
m_viewport = rt->GetSize();
glViewport(0, 0, rt->m_size.x, rt->m_size.y); CheckError();
glViewport(0, 0, rt->GetWidth(), rt->GetHeight()); CheckError();
}
GSVector4i r = scissor ? *scissor : GSVector4i(rt->m_size).zwxy();
GSVector4i r = scissor ? *scissor : GSVector4i(rt->GetSize()).zwxy();
if(!m_scissor.eq(r))
{

View File

@ -100,7 +100,7 @@ class GSDeviceOGL : public GSDevice
//
GSTexture* Create(int type, int w, int h, int format);
GSTexture* Create(int type, int w, int h, bool msaa, int format);
void DoMerge(GSTexture* st[2], GSVector4* sr, GSVector4* dr, GSTexture* dt, bool slbg, bool mmod, const GSVector4& c);
void DoInterlace(GSTexture* st, GSTexture* dt, int shader, bool linear, float yoffset = 0);
@ -114,17 +114,15 @@ public:
void Present(const GSVector4i& r, int shader, bool limit);
void Flip(bool limit);
void BeginScene();
void DrawPrimitive();
void EndScene();
void ClearRenderTarget(GSTexture* t, const GSVector4& c);
void ClearRenderTarget(GSTexture* t, uint32 c);
void ClearDepth(GSTexture* t, float c);
void ClearStencil(GSTexture* t, uint8 c);
GSTexture* CreateRenderTarget(int w, int h, int format = 0);
GSTexture* CreateDepthStencil(int w, int h, int format = 0);
GSTexture* CreateRenderTarget(int w, int h, bool msaa, int format = 0);
GSTexture* CreateDepthStencil(int w, int h, bool msaa, int format = 0);
GSTexture* CreateTexture(int w, int h, int format = 0);
GSTexture* CreateOffscreen(int w, int h, int format = 0);

View File

@ -208,7 +208,7 @@ bool GSRenderer::Merge(int field)
r += GSVector4i(0, 1).xyxy();
}
GSVector4 scale = GSVector4(tex[i]->m_scale).xyxy();
GSVector4 scale = GSVector4(tex[i]->GetScale()).xyxy();
src[i] = GSVector4(r) * scale / GSVector4(tex[i]->GetSize()).xyxy();
@ -216,7 +216,7 @@ bool GSRenderer::Merge(int field)
if(dr[i].top - baseline >= 4) // 2?
{
o.y = tex[i]->m_scale.y * (dr[i].top - baseline);
o.y = tex[i]->GetScale().y * (dr[i].top - baseline);
if(m_regs->SMODE2.INT && m_regs->SMODE2.FFMD)
{
@ -251,7 +251,7 @@ bool GSRenderer::Merge(int field)
int field2 = 1 - ((m_interlace - 1) & 1);
int mode = (m_interlace - 1) >> 1;
m_dev->Interlace(ds, field ^ field2, mode, tex[1] ? tex[1]->m_scale.y : tex[0]->m_scale.y);
m_dev->Interlace(ds, field ^ field2, mode, tex[1] ? tex[1]->GetScale().y : tex[0]->GetScale().y);
}
}

View File

@ -80,7 +80,7 @@ public:
virtual bool CanUpscale()
{
return !m_nativeres;
return !m_nativeres && m_regs->PMODE.EN != 0; // upscale ratio depends on the display size, with no output it may not be set correctly (ps2 logo to game transition)
}
};

View File

@ -163,12 +163,12 @@ public:
GSTextureFX::VSConstantBuffer vs_cb;
float sx = 2.0f * rt->m_scale.x / (rt->m_size.x << 4);
float sy = 2.0f * rt->m_scale.y / (rt->m_size.y << 4);
float sx = 2.0f * rt->GetScale().x / (rt->GetWidth() << 4);
float sy = 2.0f * rt->GetScale().y / (rt->GetHeight() << 4);
float ox = (float)(int)context->XYOFFSET.OFX;
float oy = (float)(int)context->XYOFFSET.OFY;
float ox2 = 2.0f * m_pixelcenter.x / rt->m_size.x;
float oy2 = 2.0f * m_pixelcenter.y / rt->m_size.y;
float ox2 = 2.0f * m_pixelcenter.x / rt->GetWidth();
float oy2 = 2.0f * m_pixelcenter.y / rt->GetHeight();
vs_cb.VertexScale = GSVector4(sx, -sy, 1.0f / UINT_MAX, 0.0f);
vs_cb.VertexOffset = GSVector4(ox * sx + ox2 + 1, -(oy * sy + oy2 + 1), 0.0f, -1.0f);
@ -230,8 +230,8 @@ public:
ps_sel.ltf = m_filter == 2 ? IsLinear() : m_filter;
ps_sel.rt = tex->m_target;
int w = tex->m_texture->m_size.x;
int h = tex->m_texture->m_size.y;
int w = tex->m_texture->GetWidth();
int h = tex->m_texture->GetHeight();
int tw = (int)(1 << context->TEX0.TW);
int th = (int)(1 << context->TEX0.TH);
@ -266,7 +266,7 @@ public:
// rs
GSVector4i scissor = GSVector4i(GSVector4(rt->m_scale).xyxy() * context->scissor.in).rintersect(GSVector4i(rt->GetSize()).zwxy());
GSVector4i scissor = GSVector4i(GSVector4(rt->GetScale()).xyxy() * context->scissor.in).rintersect(GSVector4i(rt->GetSize()).zwxy());
m_dev->OMSetRenderTargets(rt, ds, &scissor);
m_dev->PSSetShaderResources(tex ? tex->m_texture : NULL, tex ? tex->m_palette : NULL);

View File

@ -199,9 +199,9 @@ void GSRendererDX10::SetupDATE(GSTexture* rt, GSTexture* ds)
GSDevice10* dev = (GSDevice10*)m_dev;
const GSVector2i& size = rt->m_size;
const GSVector2i& size = rt->GetSize();
if(GSTexture* t = dev->CreateRenderTarget(size.x, size.y))
if(GSTexture* t = dev->CreateRenderTarget(size.x, size.y, rt->IsMSAA()))
{
// sfex3 (after the capcom logo), vf4 (first menu fading in), ffxii shadows, rumble roses shadows, persona4 shadows
@ -217,7 +217,7 @@ void GSRendererDX10::SetupDATE(GSTexture* rt, GSTexture* ds)
// ia
GSVector4 s = GSVector4(rt->m_scale.x / size.x, rt->m_scale.y / size.y);
GSVector4 s = GSVector4(rt->GetScale().x / size.x, rt->GetScale().y / size.y);
GSVector4 o = GSVector4(-1.0f, 1.0f);
GSVector4 src = ((m_vt.m_min.p.xyxy(m_vt.m_max.p) + o.xxyy()) * s.xyxy()).sat(o.zzyy());
@ -245,7 +245,9 @@ void GSRendererDX10::SetupDATE(GSTexture* rt, GSTexture* ds)
// ps
dev->PSSetShaderResources(rt, NULL);
GSTexture* rt2 = rt->IsMSAA() ? dev->Resolve(rt) : rt;
dev->PSSetShaderResources(rt2, NULL);
dev->PSSetShader(dev->m_convert.ps[m_context->TEST.DATM ? 2 : 3], NULL);
dev->PSSetSamplerState(dev->m_convert.pt, NULL);
@ -258,5 +260,7 @@ void GSRendererDX10::SetupDATE(GSTexture* rt, GSTexture* ds)
dev->EndScene();
dev->Recycle(t);
if(rt2 != rt) dev->Recycle(rt2);
}
}

View File

@ -199,9 +199,9 @@ void GSRendererDX11::SetupDATE(GSTexture* rt, GSTexture* ds)
GSDevice11* dev = (GSDevice11*)m_dev;
const GSVector2i& size = rt->m_size;
const GSVector2i& size = rt->GetSize();
if(GSTexture* t = dev->CreateRenderTarget(size.x, size.y))
if(GSTexture* t = dev->CreateRenderTarget(size.x, size.y, rt->IsMSAA()))
{
// sfex3 (after the capcom logo), vf4 (first menu fading in), ffxii shadows, rumble roses shadows, persona4 shadows
@ -217,7 +217,7 @@ void GSRendererDX11::SetupDATE(GSTexture* rt, GSTexture* ds)
// ia
GSVector4 s = GSVector4(rt->m_scale.x / size.x, rt->m_scale.y / size.y);
GSVector4 s = GSVector4(rt->GetScale().x / size.x, rt->GetScale().y / size.y);
GSVector4 o = GSVector4(-1.0f, 1.0f);
GSVector4 src = ((m_vt.m_min.p.xyxy(m_vt.m_max.p) + o.xxyy()) * s.xyxy()).sat(o.zzyy());
@ -245,7 +245,9 @@ void GSRendererDX11::SetupDATE(GSTexture* rt, GSTexture* ds)
// ps
dev->PSSetShaderResources(rt, NULL);
GSTexture* rt2 = rt->IsMSAA() ? dev->Resolve(rt) : rt;
dev->PSSetShaderResources(rt2, NULL);
dev->PSSetShader(dev->m_convert.ps[m_context->TEST.DATM ? 2 : 3], NULL);
dev->PSSetSamplerState(dev->m_convert.pt, NULL);
@ -258,5 +260,7 @@ void GSRendererDX11::SetupDATE(GSTexture* rt, GSTexture* ds)
dev->EndScene();
dev->Recycle(t);
if(rt2 != rt) dev->Recycle(rt2);
}
}

View File

@ -216,9 +216,9 @@ void GSRendererDX9::SetupDATE(GSTexture* rt, GSTexture* ds)
GSDevice9* dev = (GSDevice9*)m_dev;
const GSVector2i& size = rt->m_size;
const GSVector2i& size = rt->GetSize();
if(GSTexture* t = dev->CreateRenderTarget(size.x, size.y))
if(GSTexture* t = dev->CreateRenderTarget(size.x, size.y, rt->IsMSAA()))
{
// sfex3 (after the capcom logo), vf4 (first menu fading in), ffxii shadows, rumble roses shadows, persona4 shadows
@ -234,7 +234,7 @@ void GSRendererDX9::SetupDATE(GSTexture* rt, GSTexture* ds)
// ia
GSVector4 s = GSVector4(rt->m_scale.x / size.x, rt->m_scale.y / size.y);
GSVector4 s = GSVector4(rt->GetScale().x / size.x, rt->GetScale().y / size.y);
GSVector4 o = GSVector4(-1.0f, 1.0f);
GSVector4 src = ((m_vt.m_min.p.xyxy(m_vt.m_max.p) + o.xxyy()) * s.xyxy()).sat(o.zzyy());
@ -258,7 +258,9 @@ void GSRendererDX9::SetupDATE(GSTexture* rt, GSTexture* ds)
// ps
dev->PSSetShaderResources(rt, NULL);
GSTexture* rt2 = rt->IsMSAA() ? dev->Resolve(rt) : rt;
dev->PSSetShaderResources(rt2, NULL);
dev->PSSetShader(dev->m_convert.ps[m_context->TEST.DATM ? 2 : 3], NULL, 0);
dev->PSSetSamplerState(&dev->m_convert.pt);
@ -271,6 +273,8 @@ void GSRendererDX9::SetupDATE(GSTexture* rt, GSTexture* ds)
dev->EndScene();
dev->Recycle(t);
if(rt2 != rt) dev->Recycle(rt2);
}
}
@ -287,7 +291,7 @@ void GSRendererDX9::UpdateFBA(GSTexture* rt)
// ia
GSVector4 s = GSVector4(rt->m_scale.x / rt->m_size.x, rt->m_scale.y / rt->m_size.y);
GSVector4 s = GSVector4(rt->GetScale().x / rt->GetWidth(), rt->GetScale().y / rt->GetHeight());
GSVector4 o = GSVector4(-1.0f, 1.0f);
GSVector4 src = ((m_vt.m_min.p.xyxy(m_vt.m_max.p) + o.xxyy()) * s.xyxy()).sat(o.zzyy());

View File

@ -495,7 +495,7 @@ protected:
GSTexture* t = NULL;
if(GSTextureCache::Target* rt = m_tc->LookupTarget(TEX0, m_width, m_height, GSTextureCache::RenderTarget, true, true))
if(GSTextureCache::Target* rt = m_tc->LookupTarget(TEX0, m_width, m_height))
{
t = rt->m_texture;

View File

@ -21,3 +21,11 @@
#include "StdAfx.h"
#include "GSTexture.h"
GSTexture::GSTexture()
: m_scale(1, 1)
, m_size(0, 0)
, m_type(None)
, m_msaa(false)
{
}

View File

@ -25,30 +25,38 @@
class GSTexture
{
public:
protected:
GSVector2 m_scale;
GSVector2i m_size;
int m_type;
int m_format;
bool m_msaa;
public:
struct GSMap {uint8* bits; int pitch;};
enum {None, RenderTarget, DepthStencil, Texture, Offscreen};
public:
GSTexture() : m_scale(1, 1), m_size(0, 0) {}
GSTexture();
virtual ~GSTexture() {}
virtual operator bool() {ASSERT(0); return false;}
virtual int GetType() const = 0;
virtual int GetFormat() const = 0;
virtual bool Update(const GSVector4i& r, const void* data, int pitch) = 0;
virtual bool Map(GSMap& m, const GSVector4i* r = NULL) = 0;
virtual void Unmap() = 0;
virtual bool Save(const string& fn, bool dds = false) = 0;
GSVector2 GetScale() const {return m_scale;}
void SetScale(const GSVector2& scale) {m_scale = scale;}
int GetWidth() const {return m_size.x;}
int GetHeight() const {return m_size.y;}
GSVector2i GetSize() const {return m_size;}
int GetType() const {return m_type;}
int GetFormat() const {return m_format;}
bool IsMSAA() const {return m_msaa;}
};

View File

@ -32,20 +32,15 @@ GSTexture10::GSTexture10(ID3D10Texture2D* texture)
m_size.x = (int)m_desc.Width;
m_size.y = (int)m_desc.Height;
}
int GSTexture10::GetType() const
{
if(m_desc.BindFlags & D3D10_BIND_RENDER_TARGET) return GSTexture::RenderTarget;
if(m_desc.BindFlags & D3D10_BIND_DEPTH_STENCIL) return GSTexture::DepthStencil;
if(m_desc.BindFlags & D3D10_BIND_SHADER_RESOURCE) return GSTexture::Texture;
if(m_desc.Usage == D3D10_USAGE_STAGING) return GSTexture::Offscreen;
return GSTexture::None;
}
if(m_desc.BindFlags & D3D10_BIND_RENDER_TARGET) m_type = RenderTarget;
else if(m_desc.BindFlags & D3D10_BIND_DEPTH_STENCIL) m_type = DepthStencil;
else if(m_desc.BindFlags & D3D10_BIND_SHADER_RESOURCE) m_type = Texture;
else if(m_desc.Usage == D3D10_USAGE_STAGING) m_type = Offscreen;
int GSTexture10::GetFormat() const
{
return m_desc.Format;
m_format = (int)m_desc.Format;
m_msaa = m_desc.SampleDesc.Count > 1;
}
bool GSTexture10::Update(const GSVector4i& r, const void* data, int pitch)
@ -162,6 +157,8 @@ GSTexture10::operator ID3D10ShaderResourceView*()
{
if(!m_srv && m_dev && m_texture)
{
ASSERT(!m_msaa);
D3D10_SHADER_RESOURCE_VIEW_DESC* desc = NULL;
if(m_desc.Format == DXGI_FORMAT_R32G8X24_TYPELESS)

View File

@ -35,9 +35,6 @@ class GSTexture10 : public GSTexture
public:
explicit GSTexture10(ID3D10Texture2D* texture);
int GetType() const;
int GetFormat() const;
bool Update(const GSVector4i& r, const void* data, int pitch);
bool Map(GSMap& m, const GSVector4i* r);
void Unmap();

View File

@ -34,20 +34,15 @@ GSTexture11::GSTexture11(ID3D11Texture2D* texture)
m_size.x = (int)m_desc.Width;
m_size.y = (int)m_desc.Height;
}
int GSTexture11::GetType() const
{
if(m_desc.BindFlags & D3D11_BIND_RENDER_TARGET) return GSTexture::RenderTarget;
if(m_desc.BindFlags & D3D11_BIND_DEPTH_STENCIL) return GSTexture::DepthStencil;
if(m_desc.BindFlags & D3D11_BIND_SHADER_RESOURCE) return GSTexture::Texture;
if(m_desc.Usage == D3D11_USAGE_STAGING) return GSTexture::Offscreen;
return GSTexture::None;
}
if(m_desc.BindFlags & D3D11_BIND_RENDER_TARGET) m_type = RenderTarget;
else if(m_desc.BindFlags & D3D11_BIND_DEPTH_STENCIL) m_type = DepthStencil;
else if(m_desc.BindFlags & D3D11_BIND_SHADER_RESOURCE) m_type = Texture;
else if(m_desc.Usage == D3D11_USAGE_STAGING) m_type = Offscreen;
int GSTexture11::GetFormat() const
{
return m_desc.Format;
m_format = (int)m_desc.Format;
m_msaa = m_desc.SampleDesc.Count > 1;
}
bool GSTexture11::Update(const GSVector4i& r, const void* data, int pitch)
@ -164,6 +159,8 @@ GSTexture11::operator ID3D11ShaderResourceView*()
{
if(!m_srv && m_dev && m_texture)
{
ASSERT(!m_msaa);
m_dev->CreateShaderResourceView(m_texture, NULL, &m_srv);
}

View File

@ -36,9 +36,6 @@ class GSTexture11 : public GSTexture
public:
explicit GSTexture11(ID3D11Texture2D* texture);
int GetType() const;
int GetFormat() const;
bool Update(const GSVector4i& r, const void* data, int pitch);
bool Map(GSMap& m, const GSVector4i* r);
void Unmap();

View File

@ -23,8 +23,7 @@
#include "GSTexture7.h"
GSTexture7::GSTexture7(int type, IDirectDrawSurface7* system)
: m_type(type)
, m_system(system)
: m_system(system)
{
memset(&m_desc, 0, sizeof(m_desc));
@ -34,11 +33,14 @@ GSTexture7::GSTexture7(int type, IDirectDrawSurface7* system)
m_size.x = (int)m_desc.dwWidth;
m_size.y = (int)m_desc.dwHeight;
m_type = type;
m_format = (int)m_desc.ddpfPixelFormat.dwFourCC;
}
GSTexture7::GSTexture7(int type, IDirectDrawSurface7* system, IDirectDrawSurface7* video)
: m_type(type)
, m_system(system)
: m_system(system)
, m_video(video)
{
memset(&m_desc, 0, sizeof(m_desc));
@ -49,16 +51,10 @@ GSTexture7::GSTexture7(int type, IDirectDrawSurface7* system, IDirectDrawSurface
m_size.x = (int)m_desc.dwWidth;
m_size.y = (int)m_desc.dwHeight;
}
int GSTexture7::GetType() const
{
return m_type;
}
m_type = type;
int GSTexture7::GetFormat() const
{
return (int)m_desc.ddpfPixelFormat.dwFourCC;
m_format = (int)m_desc.ddpfPixelFormat.dwFourCC;
}
bool GSTexture7::Update(const GSVector4i& r, const void* data, int pitch)

View File

@ -26,7 +26,6 @@
class GSTexture7 : public GSTexture
{
int m_type;
CComPtr<IDirectDrawSurface7> m_system;
CComPtr<IDirectDrawSurface7> m_video;
DDSURFACEDESC2 m_desc;
@ -35,9 +34,6 @@ public:
GSTexture7(int type, IDirectDrawSurface7* system);
GSTexture7(int type, IDirectDrawSurface7* system, IDirectDrawSurface7* video);
int GetType() const;
int GetFormat() const;
bool Update(const GSVector4i& r, const void* data, int pitch);
bool Map(GSMap& m, const GSVector4i* r);
void Unmap();

View File

@ -38,6 +38,15 @@ GSTexture9::GSTexture9(IDirect3DSurface9* surface)
m_size.x = (int)m_desc.Width;
m_size.y = (int)m_desc.Height;
if(m_desc.Usage & D3DUSAGE_RENDERTARGET) m_type = RenderTarget;
else if(m_desc.Usage & D3DUSAGE_DEPTHSTENCIL) m_type = DepthStencil;
else if(m_desc.Pool == D3DPOOL_MANAGED) m_type = Texture;
else if(m_desc.Pool == D3DPOOL_SYSTEMMEM) m_type = Offscreen;
m_format = (int)m_desc.Format;
m_msaa = m_desc.MultiSampleType != D3DMULTISAMPLE_NONE;
}
GSTexture9::GSTexture9(IDirect3DTexture9* texture)
@ -52,26 +61,21 @@ GSTexture9::GSTexture9(IDirect3DTexture9* texture)
m_size.x = (int)m_desc.Width;
m_size.y = (int)m_desc.Height;
if(m_desc.Usage & D3DUSAGE_RENDERTARGET) m_type = RenderTarget;
else if(m_desc.Usage & D3DUSAGE_DEPTHSTENCIL) m_type = DepthStencil;
else if(m_desc.Pool == D3DPOOL_MANAGED) m_type = Texture;
else if(m_desc.Pool == D3DPOOL_SYSTEMMEM) m_type = Offscreen;
m_format = (int)m_desc.Format;
m_msaa = m_desc.MultiSampleType > 1;
}
GSTexture9::~GSTexture9()
{
}
int GSTexture9::GetType() const
{
if(m_desc.Usage & D3DUSAGE_RENDERTARGET) return GSTexture::RenderTarget;
if(m_desc.Usage & D3DUSAGE_DEPTHSTENCIL) return GSTexture::DepthStencil;
if(m_desc.Pool == D3DPOOL_MANAGED) return GSTexture::Texture;
if(m_desc.Pool == D3DPOOL_SYSTEMMEM) return GSTexture::Offscreen;
return GSTexture::None;
}
int GSTexture9::GetFormat() const
{
return m_desc.Format;
}
bool GSTexture9::Update(const GSVector4i& r, const void* data, int pitch)
{
if(m_surface)

View File

@ -35,9 +35,6 @@ public:
explicit GSTexture9(IDirect3DTexture9* texture);
virtual ~GSTexture9();
int GetType() const;
int GetFormat() const;
bool Update(const GSVector4i& r, const void* data, int pitch);
bool Map(GSMap& m, const GSVector4i* r);
void Unmap();

View File

@ -106,21 +106,12 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con
if(src == NULL)
{
src = CreateSource();
src = CreateSource(TEX0, TEXA, dst);
if(!(dst ? src->Create(dst) : src->Create(m_paltex)))
if(src == NULL)
{
delete src;
return NULL;
}
if(psm.pal > 0)
{
memcpy(src->m_clut, clut, psm.pal * sizeof(clut[0]));
}
m_src.Add(src, TEX0, m_renderer->m_context->offset.tex);
}
if(psm.pal > 0)
@ -144,7 +135,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con
return src;
}
GSTextureCache::Target* GSTextureCache::LookupTarget(const GIFRegTEX0& TEX0, int w, int h, int type, bool used, bool fb)
GSTextureCache::Target* GSTextureCache::LookupTarget(const GIFRegTEX0& TEX0, int w, int h, int type, bool used)
{
uint32 bp = TEX0.TBP0;
@ -160,41 +151,20 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(const GIFRegTEX0& TEX0, int
dst = t;
if(!fb) dst->m_TEX0 = TEX0;
dst->m_TEX0 = TEX0;
break;
}
}
if(dst == NULL && fb)
{
// HACK: try to find something close to the base pointer
for(list<Target*>::iterator i = m_dst[type].begin(); i != m_dst[type].end(); i++)
{
Target* t = *i;
if(t->m_TEX0.TBP0 <= bp && bp < t->m_TEX0.TBP0 + 0x700 && (!dst || t->m_TEX0.TBP0 >= dst->m_TEX0.TBP0))
{
dst = t;
}
}
}
if(dst == NULL)
{
dst = CreateTarget();
dst = CreateTarget(TEX0, w, h, type);
dst->m_TEX0 = TEX0;
if(!dst->Create(w, h, type))
if(dst == NULL)
{
delete dst;
return NULL;
}
m_dst[type].push_front(dst);
}
else
{
@ -212,16 +182,15 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(const GIFRegTEX0& TEX0, int
{
hh *= 2;
}
/*
if(hh < 512)
if(hh < 512 && m_renderer->m_context->SCISSOR.SCAY1 == 511) // vp2
{
hh = 512;
}
*/
if(ww > 0 && hh > 0)
{
dst->m_texture->m_scale.x = (float)w / ww;
dst->m_texture->m_scale.y = (float)h / hh;
dst->m_texture->SetScale(GSVector2((float)w / ww, (float)h / hh));
}
}
@ -233,6 +202,52 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(const GIFRegTEX0& TEX0, int
return dst;
}
GSTextureCache::Target* GSTextureCache::LookupTarget(const GIFRegTEX0& TEX0, int w, int h)
{
uint32 bp = TEX0.TBP0;
Target* dst = NULL;
for(list<Target*>::iterator i = m_dst[RenderTarget].begin(); i != m_dst[RenderTarget].end(); i++)
{
Target* t = *i;
if(bp == t->m_TEX0.TBP0)
{
dst = t;
break;
}
else
{
// HACK: try to find something close to the base pointer
if(t->m_TEX0.TBP0 <= bp && bp < t->m_TEX0.TBP0 + 0x700 && (!dst || t->m_TEX0.TBP0 >= dst->m_TEX0.TBP0))
{
dst = t;
}
}
}
if(dst == NULL)
{
dst = CreateTarget(TEX0, w, h, RenderTarget);
if(dst == NULL)
{
return NULL;
}
}
else
{
dst->Update();
}
dst->m_used = true;
return dst;
}
void GSTextureCache::InvalidateVideoMem(const GSOffset* o, const GSVector4i& rect, bool target)
{
uint32 bp = o->bp;
@ -368,12 +383,7 @@ void GSTextureCache::InvalidateLocalMem(const GSOffset* o, const GSVector4i& r)
{
if(GSUtil::HasCompatibleBits(psm, t->m_TEX0.PSM))
{
GSVector4i r2 = r.rintersect(t->m_valid);
if(!r2.rempty())
{
t->Read(r2);
}
Read(t, r.rintersect(t->m_valid));
return;
}
@ -381,12 +391,7 @@ void GSTextureCache::InvalidateLocalMem(const GSOffset* o, const GSVector4i& r)
{
// ffx-2 riku changing to her default (shoots some reflecting glass at the end), 16-bit rt read as 32-bit
GSVector4i r2 = GSVector4i(r.left, r.top, r.right, r.top + (r.bottom - r.top) * 2).rintersect(t->m_valid);
if(!r2.rempty())
{
t->Read(r2);
}
Read(t, GSVector4i(r.left, r.top, r.right, r.top + (r.bottom - r.top) * 2).rintersect(t->m_valid));
return;
}
@ -477,6 +482,257 @@ void GSTextureCache::IncAge()
}
}
GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, Target* dst)
{
Source* src = new Source(m_renderer);
src->m_TEX0 = TEX0;
src->m_TEXA = TEXA;
int tw = 1 << TEX0.TW;
int th = 1 << TEX0.TH;
int tp = (int)TEX0.TW << 6;
if(dst == NULL)
{
if(m_paltex && GSLocalMemory::m_psm[TEX0.PSM].pal > 0)
{
src->m_fmt = GSTextureFX::FMT_8;
src->m_texture = m_renderer->m_dev->CreateTexture(tw, th, Get8bitFormat());
src->m_palette = m_renderer->m_dev->CreateTexture(256, 1);
}
else
{
src->m_fmt = GSTextureFX::FMT_32;
src->m_texture = m_renderer->m_dev->CreateTexture(tw, th);
}
}
else
{
// TODO: clean up this mess
src->m_target = true;
if(dst->m_type != RenderTarget)
{
// TODO
delete src;
return NULL;
}
dst->Update();
GSTexture* tmp = NULL;
if(dst->m_texture->IsMSAA())
{
tmp = dst->m_texture;
dst->m_texture = m_renderer->m_dev->Resolve(dst->m_texture);
}
// do not round here!!! if edge becomes a black pixel and addressing mode is clamp => everything outside the clamped area turns into black (kh2 shadows)
int w = (int)(dst->m_texture->GetScale().x * tw);
int h = (int)(dst->m_texture->GetScale().y * th);
GSVector2i dstsize = dst->m_texture->GetSize();
// pitch conversion
if(dst->m_TEX0.TBW != TEX0.TBW) // && dst->m_TEX0.PSM == TEX0.PSM
{
// sfex3 uses this trick (bw: 10 -> 5, wraps the right side below the left)
// ASSERT(dst->m_TEX0.TBW > TEX0.TBW); // otherwise scale.x need to be reduced to make the larger texture fit (TODO)
src->m_texture = m_renderer->m_dev->CreateRenderTarget(dstsize.x, dstsize.y, false);
GSVector4 size = GSVector4(dstsize).xyxy();
GSVector4 scale = GSVector4(dst->m_texture->GetScale()).xyxy();
int bw = 64;
int bh = TEX0.PSM == PSM_PSMCT32 || TEX0.PSM == PSM_PSMCT24 ? 32 : 64;
GSVector4i br(0, 0, bw, bh);
int sw = (int)dst->m_TEX0.TBW << 6;
int dw = (int)TEX0.TBW << 6;
int dh = 1 << TEX0.TH;
if(sw != 0)
for(int dy = 0; dy < dh; dy += bh)
{
for(int dx = 0; dx < dw; dx += bw)
{
int o = dy * dw / bh + dx;
int sx = o % sw;
int sy = o / sw;
GSVector4 sr = GSVector4(GSVector4i(sx, sy).xyxy() + br) * scale / size;
GSVector4 dr = GSVector4(GSVector4i(dx, dy).xyxy() + br) * scale;
m_renderer->m_dev->StretchRect(dst->m_texture, sr, src->m_texture, dr);
// TODO: this is quite a lot of StretchRect, do it with one Draw
}
}
}
else if(tw < tp)
{
// FIXME: timesplitters blurs the render target by blending itself over a couple of times
if(tw == 256 && th == 128 && tp == 512 && (TEX0.TBP0 == 0 || TEX0.TBP0 == 0x00e00))
{
return false;
}
}
// width/height conversion
GSVector2 scale = dst->m_texture->GetScale();
GSVector4 dr(0, 0, w, h);
if(w > dstsize.x)
{
scale.x = (float)dstsize.x / tw;
dr.z = (float)dstsize.x * scale.x / dst->m_texture->GetScale().x;
w = dstsize.x;
}
if(h > dstsize.y)
{
scale.y = (float)dstsize.y / th;
dr.w = (float)dstsize.y * scale.y / dst->m_texture->GetScale().y;
h = dstsize.y;
}
GSVector4 sr(0, 0, w, h);
GSTexture* st = src->m_texture ? src->m_texture : dst->m_texture;
GSTexture* dt = m_renderer->m_dev->CreateRenderTarget(w, h, false);
if(!src->m_texture)
{
src->m_texture = dt;
}
if((sr == dr).alltrue())
{
m_renderer->m_dev->CopyRect(st, dt, GSVector4i(0, 0, w, h));
}
else
{
sr.z /= st->GetWidth();
sr.w /= st->GetHeight();
m_renderer->m_dev->StretchRect(st, sr, dt, dr);
}
if(dt != src->m_texture)
{
m_renderer->m_dev->Recycle(src->m_texture);
src->m_texture = dt;
}
src->m_texture->SetScale(scale);
switch(TEX0.PSM)
{
default:
ASSERT(0);
case PSM_PSMCT32:
src->m_fmt = GSTextureFX::FMT_32;
break;
case PSM_PSMCT24:
src->m_fmt = GSTextureFX::FMT_24;
break;
case PSM_PSMCT16:
case PSM_PSMCT16S:
src->m_fmt = GSTextureFX::FMT_16;
break;
case PSM_PSMT8H:
src->m_fmt = GSTextureFX::FMT_8H;
src->m_palette = m_renderer->m_dev->CreateTexture(256, 1);
break;
case PSM_PSMT4HL:
src->m_fmt = GSTextureFX::FMT_4HL;
src->m_palette = m_renderer->m_dev->CreateTexture(256, 1);
break;
case PSM_PSMT4HH:
src->m_fmt = GSTextureFX::FMT_4HH;
src->m_palette = m_renderer->m_dev->CreateTexture(256, 1);
break;
}
if(tmp != NULL)
{
m_renderer->m_dev->Recycle(dst->m_texture);
dst->m_texture = tmp;
}
}
if(src->m_texture == NULL)
{
ASSERT(0);
return NULL;
}
const GSLocalMemory::psm_t& psm = GSLocalMemory::m_psm[TEX0.PSM];
if(psm.pal > 0)
{
memcpy(src->m_clut, (const uint32*)m_renderer->m_mem.m_clut, psm.pal * sizeof(uint32));
}
m_src.Add(src, TEX0, m_renderer->m_context->offset.tex);
return src;
}
GSTextureCache::Target* GSTextureCache::CreateTarget(const GIFRegTEX0& TEX0, int w, int h, int type)
{
Target* t = new Target(m_renderer);
t->m_TEX0 = TEX0;
// FIXME: initial data should be unswizzled from local mem in Update() if dirty
t->m_type = type;
if(type == RenderTarget)
{
t->m_texture = m_renderer->m_dev->CreateRenderTarget(w, h, true);
t->m_used = true; // FIXME
}
else if(type == DepthStencil)
{
t->m_texture = m_renderer->m_dev->CreateDepthStencil(w, h, true);
}
if(t->m_texture == NULL)
{
ASSERT(0);
return NULL;
}
m_dst[type].push_front(t);
return t;
}
// GSTextureCache::Surface
GSTextureCache::Surface::Surface(GSRenderer* r)
@ -526,197 +782,6 @@ GSTextureCache::Source::~Source()
_aligned_free(m_write.rect);
}
bool GSTextureCache::Source::Create(bool paltex)
{
m_TEX0 = m_renderer->m_context->TEX0;
m_TEXA = m_renderer->m_env.TEXA;
ASSERT(m_texture == NULL);
if(paltex && GSLocalMemory::m_psm[m_TEX0.PSM].pal > 0)
{
m_fmt = GSTextureFX::FMT_8;
m_texture = m_renderer->m_dev->CreateTexture(1 << m_TEX0.TW, 1 << m_TEX0.TH, Get8bitFormat());
m_palette = m_renderer->m_dev->CreateTexture(256, 1);
}
else
{
m_fmt = GSTextureFX::FMT_32;
m_texture = m_renderer->m_dev->CreateTexture(1 << m_TEX0.TW, 1 << m_TEX0.TH);
}
return m_texture != NULL;
}
bool GSTextureCache::Source::Create(Target* dst)
{
m_target = true;
if(dst->m_type != RenderTarget)
{
// TODO
return false;
}
// TODO: clean up this mess
dst->Update();
// m_renderer->m_perfmon.Put(GSPerfMon::ConvertRT2T, 1);
m_TEX0 = m_renderer->m_context->TEX0;
m_TEXA = m_renderer->m_env.TEXA;
int tw = 1 << m_TEX0.TW;
int th = 1 << m_TEX0.TH;
int tp = (int)m_TEX0.TW << 6;
// do not round here!!! if edge becomes a black pixel and addressing mode is clamp => everything outside the clamped area turns into black (kh2 shadows)
int w = (int)(dst->m_texture->m_scale.x * tw);
int h = (int)(dst->m_texture->m_scale.y * th);
GSVector2i dstsize = dst->m_texture->GetSize();
// pitch conversion
if(dst->m_TEX0.TBW != m_TEX0.TBW) // && dst->m_TEX0.PSM == m_TEX0.PSM
{
// sfex3 uses this trick (bw: 10 -> 5, wraps the right side below the left)
// ASSERT(dst->m_TEX0.TBW > m_TEX0.TBW); // otherwise scale.x need to be reduced to make the larger texture fit (TODO)
ASSERT(m_texture == NULL);
m_texture = m_renderer->m_dev->CreateRenderTarget(dstsize.x, dstsize.y);
GSVector4 size = GSVector4(dstsize).xyxy();
GSVector4 scale = GSVector4(dst->m_texture->m_scale).xyxy();
int bw = 64;
int bh = m_TEX0.PSM == PSM_PSMCT32 || m_TEX0.PSM == PSM_PSMCT24 ? 32 : 64;
GSVector4i br(0, 0, bw, bh);
int sw = (int)dst->m_TEX0.TBW << 6;
int dw = (int)m_TEX0.TBW << 6;
int dh = 1 << m_TEX0.TH;
if(sw != 0)
for(int dy = 0; dy < dh; dy += bh)
{
for(int dx = 0; dx < dw; dx += bw)
{
int o = dy * dw / bh + dx;
int sx = o % sw;
int sy = o / sw;
GSVector4 sr = GSVector4(GSVector4i(sx, sy).xyxy() + br) * scale / size;
GSVector4 dr = GSVector4(GSVector4i(dx, dy).xyxy() + br) * scale;
m_renderer->m_dev->StretchRect(dst->m_texture, sr, m_texture, dr);
// TODO: this is quite a lot of StretchRect, do it with one Draw
}
}
}
else if(tw < tp)
{
// FIXME: timesplitters blurs the render target by blending itself over a couple of times
if(tw == 256 && th == 128 && tp == 512 && (m_TEX0.TBP0 == 0 || m_TEX0.TBP0 == 0x00e00))
{
return false;
}
}
// width/height conversion
GSVector2 scale = dst->m_texture->m_scale;
GSVector4 dr(0, 0, w, h);
if(w > dstsize.x)
{
scale.x = (float)dstsize.x / tw;
dr.z = (float)dstsize.x * scale.x / dst->m_texture->m_scale.x;
w = dstsize.x;
}
if(h > dstsize.y)
{
scale.y = (float)dstsize.y / th;
dr.w = (float)dstsize.y * scale.y / dst->m_texture->m_scale.y;
h = dstsize.y;
}
GSVector4 sr(0, 0, w, h);
GSTexture* st = m_texture ? m_texture : dst->m_texture;
GSTexture* dt = m_renderer->m_dev->CreateRenderTarget(w, h);
if(!m_texture)
{
m_texture = dt;
}
if((sr == dr).alltrue())
{
m_renderer->m_dev->CopyRect(st, dt, GSVector4i(0, 0, w, h));
}
else
{
sr.z /= st->m_size.x;
sr.w /= st->m_size.y;
m_renderer->m_dev->StretchRect(st, sr, dt, dr);
}
if(dt != m_texture)
{
m_renderer->m_dev->Recycle(m_texture);
m_texture = dt;
}
m_texture->m_scale = scale;
switch(m_TEX0.PSM)
{
default:
ASSERT(0);
case PSM_PSMCT32:
m_fmt = GSTextureFX::FMT_32;
break;
case PSM_PSMCT24:
m_fmt = GSTextureFX::FMT_24;
break;
case PSM_PSMCT16:
case PSM_PSMCT16S:
m_fmt = GSTextureFX::FMT_16;
break;
case PSM_PSMT8H:
m_fmt = GSTextureFX::FMT_8H;
m_palette = m_renderer->m_dev->CreateTexture(256, 1);
break;
case PSM_PSMT4HL:
m_fmt = GSTextureFX::FMT_4HL;
m_palette = m_renderer->m_dev->CreateTexture(256, 1);
break;
case PSM_PSMT4HH:
m_fmt = GSTextureFX::FMT_4HH;
m_palette = m_renderer->m_dev->CreateTexture(256, 1);
break;
}
return true;
}
void GSTextureCache::Source::Update(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GSVector4i& rect)
{
__super::Update();
@ -912,28 +977,6 @@ GSTextureCache::Target::Target(GSRenderer* r)
m_valid = GSVector4i::zero();
}
bool GSTextureCache::Target::Create(int w, int h, int type)
{
ASSERT(m_texture == NULL);
// FIXME: initial data should be unswizzled from local mem in Update() if dirty
m_type = type;
if(type == RenderTarget)
{
m_texture = m_renderer->m_dev->CreateRenderTarget(w, h);
m_used = true;
}
else if(type == DepthStencil)
{
m_texture = m_renderer->m_dev->CreateDepthStencil(w, h);
}
return m_texture != NULL;
}
void GSTextureCache::Target::Update()
{
__super::Update();
@ -980,7 +1023,7 @@ void GSTextureCache::Target::Update()
// m_renderer->m_perfmon.Put(GSPerfMon::Unswizzle, w * h * 4);
m_renderer->m_dev->StretchRect(t, m_texture, GSVector4(r) * GSVector4(m_texture->m_scale).xyxy());
m_renderer->m_dev->StretchRect(t, m_texture, GSVector4(r) * GSVector4(m_texture->GetScale()).xyxy());
m_renderer->m_dev->Recycle(t);
}

View File

@ -46,8 +46,6 @@ public:
virtual void Update();
};
class Target;
class Source : public Surface
{
struct {GSVector4i* rect; uint32 count;} m_write;
@ -55,9 +53,6 @@ public:
void Write(const GSVector4i& r);
void Flush(uint32 count);
protected:
virtual int Get8bitFormat() = 0;
public:
GSTexture* m_palette;
bool m_initpalette;
@ -68,11 +63,9 @@ public:
bool m_complete;
public:
explicit Source(GSRenderer* renderer);
explicit Source(GSRenderer* r);
virtual ~Source();
virtual bool Create(bool paltex);
virtual bool Create(Target* dst);
virtual void Update(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GSVector4i& rect);
};
@ -87,9 +80,7 @@ public:
public:
explicit Target(GSRenderer* r);
virtual bool Create(int w, int h, int type);
virtual void Update();
virtual void Read(const GSVector4i& r) = 0;
};
protected:
@ -113,8 +104,14 @@ protected:
list<Target*> m_dst[2];
virtual Source* CreateSource() = 0;
virtual Target* CreateTarget() = 0;
virtual Source* CreateSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, Target* t = NULL);
virtual Target* CreateTarget(const GIFRegTEX0& TEX0, int w, int h, int type);
virtual int Get8bitFormat() = 0;
// TODO: virtual void Write(Source* s, const GSVector4i& r) = 0;
// TODO: virtual void Write(Target* t, const GSVector4i& r) = 0;
virtual void Read(Target* t, const GSVector4i& r) = 0;
public:
GSTextureCache(GSRenderer* r);
@ -123,7 +120,8 @@ public:
void RemoveAll();
Source* LookupSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GSVector4i& r);
Target* LookupTarget(const GIFRegTEX0& TEX0, int w, int h, int type, bool used, bool fb = false);
Target* LookupTarget(const GIFRegTEX0& TEX0, int w, int h, int type, bool used);
Target* LookupTarget(const GIFRegTEX0& TEX0, int w, int h);
void InvalidateVideoMem(const GSOffset* o, const GSVector4i& r, bool target = true);
void InvalidateLocalMem(const GSOffset* o, const GSVector4i& r);

View File

@ -29,46 +29,42 @@ GSTextureCache10::GSTextureCache10(GSRenderer* r)
{
}
// Source10
// Target10
void GSTextureCache10::Target10::Read(const GSVector4i& r)
void GSTextureCache10::Read(Target* t, const GSVector4i& r)
{
if(m_type != RenderTarget)
if(t->m_type != RenderTarget)
{
// TODO
return;
}
if(m_TEX0.PSM != PSM_PSMCT32
&& m_TEX0.PSM != PSM_PSMCT24
&& m_TEX0.PSM != PSM_PSMCT16
&& m_TEX0.PSM != PSM_PSMCT16S)
const GIFRegTEX0& TEX0 = t->m_TEX0;
if(TEX0.PSM != PSM_PSMCT32
&& TEX0.PSM != PSM_PSMCT24
&& TEX0.PSM != PSM_PSMCT16
&& TEX0.PSM != PSM_PSMCT16S)
{
//ASSERT(0);
return;
}
if(!m_dirty.empty())
if(!t->m_dirty.empty())
{
return;
}
// printf("GSRenderTarget::Read %d,%d - %d,%d (%08x)\n", r.left, r.top, r.right, r.bottom, m_TEX0.TBP0);
// m_renderer->m_perfmon.Put(GSPerfMon::ReadRT, 1);
// printf("GSRenderTarget::Read %d,%d - %d,%d (%08x)\n", r.left, r.top, r.right, r.bottom, TEX0.TBP0);
int w = r.width();
int h = r.height();
GSVector4 src = GSVector4(r) * GSVector4(m_texture->m_scale).xyxy() / GSVector4(m_texture->GetSize()).xyxy();
GSVector4 src = GSVector4(r) * GSVector4(t->m_texture->GetScale()).xyxy() / GSVector4(t->m_texture->GetSize()).xyxy();
DXGI_FORMAT format = m_TEX0.PSM == PSM_PSMCT16 || m_TEX0.PSM == PSM_PSMCT16S ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R8G8B8A8_UNORM;
DXGI_FORMAT format = TEX0.PSM == PSM_PSMCT16 || TEX0.PSM == PSM_PSMCT16S ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R8G8B8A8_UNORM;
if(GSTexture* offscreen = m_renderer->m_dev->CopyOffscreen(m_texture, src, w, h, format))
if(GSTexture* offscreen = m_renderer->m_dev->CopyOffscreen(t->m_texture, src, w, h, format))
{
GSTexture::GSMap m;
@ -76,9 +72,9 @@ void GSTextureCache10::Target10::Read(const GSVector4i& r)
{
// TODO: block level write
GSOffset* o = m_renderer->m_mem.GetOffset(m_TEX0.TBP0, m_TEX0.TBW, m_TEX0.PSM);
GSOffset* o = m_renderer->m_mem.GetOffset(TEX0.TBP0, TEX0.TBW, TEX0.PSM);
switch(m_TEX0.PSM)
switch(TEX0.PSM)
{
case PSM_PSMCT32:
m_renderer->m_mem.WritePixel32(m.bits, m.pitch, o, r);

View File

@ -26,26 +26,10 @@
class GSTextureCache10 : public GSTextureCache
{
class Source10 : public Source
{
protected:
int Get8bitFormat() {return DXGI_FORMAT_A8_UNORM;}
public:
explicit Source10(GSRenderer* r) : Source(r) {}
};
class Target10 : public Target
{
public:
explicit Target10(GSRenderer* r) : Target(r) {}
void Read(const GSVector4i& r);
};
protected:
Source* CreateSource() {return new Source10(m_renderer);}
Target* CreateTarget() {return new Target10(m_renderer);}
int Get8bitFormat() {return DXGI_FORMAT_A8_UNORM;}
void Read(Target* t, const GSVector4i& r);
public:
GSTextureCache10(GSRenderer* r);

View File

@ -29,46 +29,42 @@ GSTextureCache11::GSTextureCache11(GSRenderer* r)
{
}
// Source11
// Target11
void GSTextureCache11::Target11::Read(const GSVector4i& r)
void GSTextureCache11::Read(Target* t, const GSVector4i& r)
{
if(m_type != RenderTarget)
if(t->m_type != RenderTarget)
{
// TODO
return;
}
if(m_TEX0.PSM != PSM_PSMCT32
&& m_TEX0.PSM != PSM_PSMCT24
&& m_TEX0.PSM != PSM_PSMCT16
&& m_TEX0.PSM != PSM_PSMCT16S)
const GIFRegTEX0& TEX0 = t->m_TEX0;
if(TEX0.PSM != PSM_PSMCT32
&& TEX0.PSM != PSM_PSMCT24
&& TEX0.PSM != PSM_PSMCT16
&& TEX0.PSM != PSM_PSMCT16S)
{
//ASSERT(0);
return;
}
if(!m_dirty.empty())
if(!t->m_dirty.empty())
{
return;
}
// printf("GSRenderTarget::Read %d,%d - %d,%d (%08x)\n", r.left, r.top, r.right, r.bottom, m_TEX0.TBP0);
// m_renderer->m_perfmon.Put(GSPerfMon::ReadRT, 1);
// printf("GSRenderTarget::Read %d,%d - %d,%d (%08x)\n", r.left, r.top, r.right, r.bottom, TEX0.TBP0);
int w = r.width();
int h = r.height();
GSVector4 src = GSVector4(r) * GSVector4(m_texture->m_scale).xyxy() / GSVector4(m_texture->GetSize()).xyxy();
GSVector4 src = GSVector4(r) * GSVector4(t->m_texture->GetScale()).xyxy() / GSVector4(t->m_texture->GetSize()).xyxy();
DXGI_FORMAT format = m_TEX0.PSM == PSM_PSMCT16 || m_TEX0.PSM == PSM_PSMCT16S ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R8G8B8A8_UNORM;
DXGI_FORMAT format = TEX0.PSM == PSM_PSMCT16 || TEX0.PSM == PSM_PSMCT16S ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R8G8B8A8_UNORM;
if(GSTexture* offscreen = m_renderer->m_dev->CopyOffscreen(m_texture, src, w, h, format))
if(GSTexture* offscreen = m_renderer->m_dev->CopyOffscreen(t->m_texture, src, w, h, format))
{
GSTexture::GSMap m;
@ -76,9 +72,9 @@ void GSTextureCache11::Target11::Read(const GSVector4i& r)
{
// TODO: block level write
GSOffset* o = m_renderer->m_mem.GetOffset(m_TEX0.TBP0, m_TEX0.TBW, m_TEX0.PSM);
GSOffset* o = m_renderer->m_mem.GetOffset(TEX0.TBP0, TEX0.TBW, TEX0.PSM);
switch(m_TEX0.PSM)
switch(TEX0.PSM)
{
case PSM_PSMCT32:
m_renderer->m_mem.WritePixel32(m.bits, m.pitch, o, r);

View File

@ -26,26 +26,10 @@
class GSTextureCache11 : public GSTextureCache
{
class Source11 : public Source
{
protected:
int Get8bitFormat() {return DXGI_FORMAT_A8_UNORM;}
public:
explicit Source11(GSRenderer* r) : Source(r) {}
};
class Target11 : public Target
{
public:
explicit Target11(GSRenderer* r) : Target(r) {}
void Read(const GSVector4i& r);
};
protected:
Source* CreateSource() {return new Source11(m_renderer);}
Target* CreateTarget() {return new Target11(m_renderer);}
int Get8bitFormat() {return DXGI_FORMAT_A8_UNORM;}
void Read(Target* t, const GSVector4i& r);
public:
GSTextureCache11(GSRenderer* r);

View File

@ -29,44 +29,40 @@ GSTextureCache9::GSTextureCache9(GSRenderer* r)
{
}
// Source9
// Target9
void GSTextureCache9::Target9::Read(const GSVector4i& r)
void GSTextureCache9::Read(Target* t, const GSVector4i& r)
{
if(m_type != RenderTarget)
if(t->m_type != RenderTarget)
{
// TODO
return;
}
if(m_TEX0.PSM != PSM_PSMCT32
&& m_TEX0.PSM != PSM_PSMCT24
&& m_TEX0.PSM != PSM_PSMCT16
&& m_TEX0.PSM != PSM_PSMCT16S)
const GIFRegTEX0& TEX0 = t->m_TEX0;
if(TEX0.PSM != PSM_PSMCT32
&& TEX0.PSM != PSM_PSMCT24
&& TEX0.PSM != PSM_PSMCT16
&& TEX0.PSM != PSM_PSMCT16S)
{
//ASSERT(0);
return;
}
if(!m_dirty.empty())
if(!t->m_dirty.empty())
{
return;
}
// printf("GSRenderTarget::Read %d,%d - %d,%d (%08x)\n", r.left, r.top, r.right, r.bottom, m_TEX0.TBP0);
// m_renderer->m_perfmon.Put(GSPerfMon::ReadRT, 1);
// printf("GSRenderTarget::Read %d,%d - %d,%d (%08x)\n", r.left, r.top, r.right, r.bottom, TEX0.TBP0);
int w = r.width();
int h = r.height();
GSVector4 src = GSVector4(r) * GSVector4(m_texture->m_scale).xyxy() / GSVector4(m_texture->GetSize()).xyxy();
GSVector4 src = GSVector4(r) * GSVector4(t->m_texture->GetScale()).xyxy() / GSVector4(t->m_texture->GetSize()).xyxy();
if(GSTexture* offscreen = m_renderer->m_dev->CopyOffscreen(m_texture, src, w, h))
if(GSTexture* offscreen = m_renderer->m_dev->CopyOffscreen(t->m_texture, src, w, h))
{
GSTexture::GSMap m;
@ -74,9 +70,9 @@ void GSTextureCache9::Target9::Read(const GSVector4i& r)
{
// TODO: block level write
GSOffset* o = m_renderer->m_mem.GetOffset(m_TEX0.TBP0, m_TEX0.TBW, m_TEX0.PSM);
GSOffset* o = m_renderer->m_mem.GetOffset(TEX0.TBP0, TEX0.TBW, TEX0.PSM);
switch(m_TEX0.PSM)
switch(TEX0.PSM)
{
case PSM_PSMCT32:
m_renderer->m_mem.WritePixel32(m.bits, m.pitch, o, r);

View File

@ -26,26 +26,10 @@
class GSTextureCache9 : public GSTextureCache
{
class Source9 : public Source
{
protected:
int Get8bitFormat() {return D3DFMT_A8;}
public:
explicit Source9(GSRenderer* r) : Source(r) {}
};
class Target9 : public Target
{
public:
explicit Target9(GSRenderer* r) : Target(r) {}
void Read(const GSVector4i& r);
};
protected:
Source* CreateSource() {return new Source9(m_renderer);}
Target* CreateTarget() {return new Target9(m_renderer);}
int Get8bitFormat() {return D3DFMT_A8;}
void Read(Target* t, const GSVector4i& r);
public:
GSTextureCache9(GSRenderer* r);

View File

@ -28,12 +28,3 @@ GSTextureCacheOGL::GSTextureCacheOGL(GSRenderer* r)
: GSTextureCache(r)
{
}
// SourceOGL
// TargetOGL
void GSTextureCacheOGL::TargetOGL::Read(const GSVector4i& r)
{
// TODO
}

View File

@ -26,26 +26,10 @@
class GSTextureCacheOGL : public GSTextureCache
{
class SourceOGL : public Source
{
protected:
int Get8bitFormat() {return 0;} // TODO
public:
explicit SourceOGL(GSRenderer* r) : Source(r) {}
};
class TargetOGL : public Target
{
public:
explicit TargetOGL(GSRenderer* r) : Target(r) {}
void Read(const GSVector4i& r);
};
protected:
Source* CreateSource() {return new SourceOGL(m_renderer);}
Target* CreateTarget() {return new TargetOGL(m_renderer);}
int Get8bitFormat() {return 0;} // TODO
void Read(Target* t, const GSVector4i& r) {} // TODO
public:
GSTextureCacheOGL(GSRenderer* r);

View File

@ -25,8 +25,6 @@
GSTextureOGL::GSTextureOGL(GLuint texture, int type, int width, int height, int format)
: m_texture(texture)
, m_type(type)
, m_format(format)
{
m_size.x = width;
m_size.y = height;
@ -34,6 +32,10 @@ GSTextureOGL::GSTextureOGL(GLuint texture, int type, int width, int height, int
// TODO: offscreen type should be just a memory array, also returned in Map
glGenBuffers(1, &m_pbo); GSDeviceOGL::CheckError();
m_type = type;
m_format = format;
}
GSTextureOGL::~GSTextureOGL()
@ -57,16 +59,6 @@ GSTextureOGL::~GSTextureOGL()
}
}
int GSTextureOGL::GetType() const
{
return m_type;
}
int GSTextureOGL::GetFormat() const
{
return m_format;
}
bool GSTextureOGL::Update(const GSVector4i& r, const void* data, int pitch)
{
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pbo); GSDeviceOGL::CheckError();

View File

@ -35,9 +35,6 @@ public:
GSTextureOGL(GLuint texture, int type, int width, int height, int format = 0);
virtual ~GSTextureOGL();
int GetType() const;
int GetFormat() const;
bool Update(const GSVector4i& r, const void* data, int pitch);
bool Map(GSMap& m, const GSVector4i* r);
void Unmap();

View File

@ -138,12 +138,10 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
@ -160,7 +158,6 @@
</PropertyGroup>
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug SSE2|Win32'">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug SSE2|X64'">
@ -171,7 +168,6 @@
</PropertyGroup>
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release SSE2|Win32'">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
@ -183,7 +179,6 @@
</PropertyGroup>
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release SSSE3|Win32'">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
@ -195,7 +190,6 @@
</PropertyGroup>
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug SSSE3|Win32'">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug SSSE3|X64'">
@ -205,7 +199,6 @@
</PropertyGroup>
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug SSE4|Win32'">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug SSE4|X64'">
@ -215,7 +208,6 @@
</PropertyGroup>
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release SSE4|Win32'">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>

View File

@ -1,7 +1,7 @@
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<_PropertySheetDisplayName>common</_PropertySheetDisplayName>
<OutDir>$(SolutionDir)\bin\$(PcsxSubsection)\</OutDir>
<OutDir>$(SolutionDir)bin\$(PcsxSubsection)\</OutDir>
<IntDir>$(PlatformName)\$(Configuration)\</IntDir>
<TargetName>$(ProjectName)-$(SSEtype)</TargetName>
</PropertyGroup>

View File

@ -31,16 +31,20 @@
return -1;
}
#ifdef _WINDOWS_
WORD toCharTemp;
#endif
char* KeysymToChar(int keysym)
{
#ifdef __LINUX__
#ifdef __LINUX__
return XKeysymToString(keysym);
#else
LPWORD temp;
ToAscii((UINT) keysym, NULL, NULL, temp, NULL);
return (char*)temp;
#endif
// fixed this to return *valid* results, and not some pointer
// to the fourth oblivion-- air
ToAscii((UINT) keysym, NULL, NULL, &toCharTemp, NULL);
return (char*)(&toCharTemp);
#endif
}
void PollForKeyboardInput(int pad)