GSdx: changed a lot of things, expect new bugs :P

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1439 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
gabest11 2009-06-27 03:32:33 +00:00
parent 6e5d4a5d15
commit 7bb9a3cc25
52 changed files with 3004 additions and 3437 deletions

View File

@ -185,7 +185,7 @@ LRESULT CALLBACK GPURenderer::WndProc(HWND hWnd, UINT message, WPARAM wParam, LP
if(i != m_wnd2gpu.end())
{
return (*i).second->OnMessage(message, wParam, lParam);
return i->second->OnMessage(message, wParam, lParam);
}
ASSERT(0);

View File

@ -21,9 +21,9 @@
#include "stdafx.h"
#include "GSUtil.h"
#include "GSRendererHW9.h"
#include "GSRendererHW10.h"
#include "GSRendererHW11.h"
#include "GSRendererDX9.h"
#include "GSRendererDX10.h"
#include "GSRendererDX11.h"
#include "GSRendererOGL.h"
#include "GSRendererSW.h"
#include "GSRendererNull.h"
@ -121,13 +121,13 @@ static INT32 GSopen(void* dsp, char* title, int mt, int renderer)
switch(renderer)
{
default:
case 0: s_gs = new GSRendererHW9(s_basemem, !!mt, s_irq); break;
case 0: s_gs = new GSRendererDX9(s_basemem, !!mt, s_irq); break;
case 1: s_gs = new GSRendererSW(s_basemem, !!mt, s_irq, new GSDevice9()); break;
case 2: s_gs = new GSRendererNull(s_basemem, !!mt, s_irq, new GSDevice9()); break;
case 3: s_gs = new GSRendererHW10(s_basemem, !!mt, s_irq); break;
case 3: s_gs = new GSRendererDX10(s_basemem, !!mt, s_irq); break;
case 4: s_gs = new GSRendererSW(s_basemem, !!mt, s_irq, new GSDevice10()); break;
case 5: s_gs = new GSRendererNull(s_basemem, !!mt, s_irq, new GSDevice10()); break;
case 6: s_gs = new GSRendererHW11(s_basemem, !!mt, s_irq); break;
case 6: s_gs = new GSRendererDX11(s_basemem, !!mt, s_irq); break;
case 7: s_gs = new GSRendererSW(s_basemem, !!mt, s_irq, new GSDevice11()); break;
case 8: s_gs = new GSRendererNull(s_basemem, !!mt, s_irq, new GSDevice11()); break;
#if 0

View File

@ -28,6 +28,9 @@
#define PLUGIN_VERSION 15
#define MAX_PAGES 512
#define MAX_BLOCKS 16384
#include "GSVector.h"
#pragma pack(push, 1)
@ -813,13 +816,39 @@ REG64_(GIFReg, TEX1)
uint32 K:12;
uint32 _PAD4:20;
REG_END2
bool IsMinLinear() const {return (MMIN == 1) || (MMIN & 4);}
bool IsMagLinear() const {return MMAG;}
bool IsLinear() const
{
bool mmag = (MMAG & 1);
bool mmin = (MMIN == 1) || (MMIN & 4);
bool mmin = IsMinLinear();
bool mmag = IsMagLinear();
return !LCM ? mmag || mmin : K <= 0 ? mmag : mmin;
}
bool IsLinear(float qmin, float qmax) const
{
bool mmin = IsMinLinear();
bool mmag = IsMagLinear();
if(mmag == mmin) return mmag;
float LODmin = K;
float LODmax = K;
if(!LCM)
{
float f = (float)(1 << L) / log(2.0f);
LODmin += log(1.0f / abs(qmax)) * f;
LODmax += log(1.0f / abs(qmin)) * f;
}
return LODmax <= 0 ? mmag : LODmin > 0 ? mmin : mmag || mmin;
}
REG_END2
REG64_(GIFReg, TEX2)

View File

@ -31,6 +31,7 @@ CRC::Game CRC::m_games[] =
{0xA6167B59, Lamune, JP, PointListPalette},
{0xDDB59F46, KyuuketsuKitanMoonties, JP, PointListPalette},
{0xC8EE2562, PiaCarroteYoukosoGPGakuenPrincess, JP, PointListPalette},
{0x6CF94A43, KazokuKeikakuKokoroNoKizuna, JP, PointListPalette},
{0xa39517ab, FFX, EU, 0},
{0xa39517ae, FFX, FR, 0},
{0x941bb7d9, FFX, DE, 0},
@ -156,7 +157,7 @@ CRC::Game CRC::Lookup(uint32 crc)
if(i != m_map.end())
{
return *(*i).second;
return *i->second;
}
return m_games[0];

View File

@ -33,6 +33,7 @@ public:
Lamune,
KyuuketsuKitanMoonties,
PiaCarroteYoukosoGPGakuenPrincess,
KazokuKeikakuKokoroNoKizuna,
FFX,
FFX2,
FFXII,

View File

@ -89,7 +89,7 @@ public:
(int)SCISSOR.SCAX1 + 1,
(int)SCISSOR.SCAY1 + 1);
scissor.ex = GSVector4i(
scissor.ex = GSVector4(
(int)SCISSOR.SCAX0,
(int)SCISSOR.SCAY0,
(int)SCISSOR.SCAX1,

View File

@ -68,7 +68,7 @@ public:
{
for(hash_map<KEY, ActivePtr*>::iterator i = m_map_active.begin(); i != m_map_active.end(); i++)
{
delete (*i).second;
delete i->second;
}
}
@ -80,7 +80,7 @@ public:
if(i != m_map_active.end())
{
m_active = (*i).second;
m_active = i->second;
}
else
{
@ -92,7 +92,7 @@ public:
p->frame = (uint64)-1;
p->f = i != m_map.end() ? (*i).second : GetDefaultFunction(key);
p->f = i != m_map.end() ? i->second : GetDefaultFunction(key);
m_map_active[key] = p;
@ -123,7 +123,7 @@ public:
for(hash_map<KEY, ActivePtr*>::iterator i = m_map_active.begin(); i != m_map_active.end(); i++)
{
ActivePtr* p = (*i).second;
ActivePtr* p = i->second;
if(p->frames)
{
@ -133,8 +133,8 @@ public:
for(hash_map<KEY, ActivePtr*>::iterator i = m_map_active.begin(); i != m_map_active.end(); i++)
{
KEY key = (*i).first;
ActivePtr* p = (*i).second;
KEY key = i->first;
ActivePtr* p = i->second;
if(p->frames > 0)
{
@ -179,7 +179,7 @@ public:
{
for(hash_map<uint64, CG*>::iterator i = m_cgmap.begin(); i != m_cgmap.end(); i++)
{
delete (*i).second;
delete i->second;
}
}
@ -191,7 +191,7 @@ public:
if(i != m_cgmap.end())
{
cg = (*i).second;
cg = i->second;
}
else
{

View File

@ -30,14 +30,17 @@
#define ASSERT_BLOCK(r, w, h) \
ASSERT((r).width() >= w && (r).height() >= h && !((r).left&(w-1)) && !((r).top&(h-1)) && !((r).right&(w-1)) && !((r).bottom&(h-1))); \
#define FOREACH_BLOCK_START(w, h, bpp) \
#define FOREACH_BLOCK_START(w, h, bpp, format) \
const GSLocalMemory::psm_t& psm = GSLocalMemory::m_psm[format]; \
uint32 bp = TEX0.TBP0; \
uint32 bw = TEX0.TBW; \
int offset = dstpitch * h - r.width() * bpp / 8; \
for(int y = r.top, ye = r.bottom; y < ye; y += h, dst += offset) \
{ ASSERT_BLOCK(r, w, h); \
uint32 base = psm.bn(0, y, bp, bw); \
for(int x = r.left, xe = r.right; x < xe; x += w, dst += w * bpp / 8) \
{ \
const uint8* src = BlockPtr(base + psm.blockOffset[x >> 3]); \
#define FOREACH_BLOCK_END }}
@ -462,7 +465,7 @@ GSLocalMemory::~GSLocalMemory()
for(hash_map<uint32, Offset*>::iterator i = m_omap.begin(); i != m_omap.end(); i++)
{
Offset* o = (*i).second;
Offset* o = i->second;
_aligned_free(o->col[0]);
@ -471,7 +474,7 @@ GSLocalMemory::~GSLocalMemory()
for(hash_map<uint32, Offset4*>::iterator i = m_o4map.begin(); i != m_o4map.end(); i++)
{
_aligned_free((*i).second);
_aligned_free(i->second);
}
}
@ -487,7 +490,7 @@ GSLocalMemory::Offset* GSLocalMemory::GetOffset(uint32 bp, uint32 bw, uint32 psm
if(i != m_omap.end())
{
return (*i).second;
return i->second;
}
Offset* o = (Offset*)_aligned_malloc(sizeof(Offset), 16);
@ -536,7 +539,7 @@ GSLocalMemory::Offset4* GSLocalMemory::GetOffset4(const GIFRegFRAME& FRAME, cons
if(i != m_o4map.end())
{
return (*i).second;
return i->second;
}
Offset4* o = (Offset4*)_aligned_malloc(sizeof(Offset4), 16);
@ -1435,9 +1438,9 @@ void GSLocalMemory::ReadImageX(int& tx, int& ty, uint8* dst, int len, GIFRegBITB
void GSLocalMemory::ReadTexture32(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const
{
FOREACH_BLOCK_START(8, 8, 32)
FOREACH_BLOCK_START(8, 8, 32, PSM_PSMCT32)
{
ReadBlock32<true>(BlockPtr32(x, y, bp, bw), dst, dstpitch);
ReadBlock32<true>(src, dst, dstpitch);
}
FOREACH_BLOCK_END
}
@ -1446,17 +1449,17 @@ void GSLocalMemory::ReadTexture24(const GSVector4i& r, uint8* dst, int dstpitch,
{
if(TEXA.AEM)
{
FOREACH_BLOCK_START(8, 8, 32)
FOREACH_BLOCK_START(8, 8, 32, PSM_PSMCT24)
{
ReadAndExpandBlock24<true>(BlockPtr32(x, y, bp, bw), dst, dstpitch, TEXA);
ReadAndExpandBlock24<true>(src, dst, dstpitch, TEXA);
}
FOREACH_BLOCK_END
}
else
{
FOREACH_BLOCK_START(8, 8, 32)
FOREACH_BLOCK_START(8, 8, 32, PSM_PSMCT24)
{
ReadAndExpandBlock24<false>(BlockPtr32(x, y, bp, bw), dst, dstpitch, TEXA);
ReadAndExpandBlock24<false>(src, dst, dstpitch, TEXA);
}
FOREACH_BLOCK_END
}
@ -1466,9 +1469,9 @@ void GSLocalMemory::ReadTexture16(const GSVector4i& r, uint8* dst, int dstpitch,
{
__declspec(align(16)) uint16 block[16 * 8];
FOREACH_BLOCK_START(16, 8, 32)
FOREACH_BLOCK_START(16, 8, 32, PSM_PSMCT16)
{
ReadBlock16<true>(BlockPtr16(x, y, bp, bw), (uint8*)block, sizeof(block) / 8);
ReadBlock16<true>(src, (uint8*)block, sizeof(block) / 8);
ExpandBlock16(block, dst, dstpitch, TEXA);
}
@ -1479,9 +1482,9 @@ void GSLocalMemory::ReadTexture16S(const GSVector4i& r, uint8* dst, int dstpitch
{
__declspec(align(16)) uint16 block[16 * 8];
FOREACH_BLOCK_START(16, 8, 32)
FOREACH_BLOCK_START(16, 8, 32, PSM_PSMCT16S)
{
ReadBlock16<true>(BlockPtr16S(x, y, bp, bw), (uint8*)block, sizeof(block) / 8);
ReadBlock16<true>(src, (uint8*)block, sizeof(block) / 8);
ExpandBlock16(block, dst, dstpitch, TEXA);
}
@ -1492,9 +1495,9 @@ void GSLocalMemory::ReadTexture8(const GSVector4i& r, uint8* dst, int dstpitch,
{
const uint32* pal = m_clut;
FOREACH_BLOCK_START(16, 16, 32)
FOREACH_BLOCK_START(16, 16, 32, PSM_PSMT8)
{
ReadAndExpandBlock8_32(BlockPtr8(x, y, bp, bw), dst, dstpitch, pal);
ReadAndExpandBlock8_32(src, dst, dstpitch, pal);
}
FOREACH_BLOCK_END
}
@ -1503,9 +1506,9 @@ void GSLocalMemory::ReadTexture4(const GSVector4i& r, uint8* dst, int dstpitch,
{
const uint64* pal = m_clut;
FOREACH_BLOCK_START(32, 16, 32)
FOREACH_BLOCK_START(32, 16, 32, PSM_PSMT4)
{
ReadAndExpandBlock4_32(BlockPtr4(x, y, bp, bw), dst, dstpitch, pal);
ReadAndExpandBlock4_32(src, dst, dstpitch, pal);
}
FOREACH_BLOCK_END
}
@ -1514,9 +1517,9 @@ void GSLocalMemory::ReadTexture8H(const GSVector4i& r, uint8* dst, int dstpitch,
{
const uint32* pal = m_clut;
FOREACH_BLOCK_START(8, 8, 32)
FOREACH_BLOCK_START(8, 8, 32, PSM_PSMT8H)
{
ReadAndExpandBlock8H_32(BlockPtr32(x, y, bp, bw), dst, dstpitch, pal);
ReadAndExpandBlock8H_32(src, dst, dstpitch, pal);
}
FOREACH_BLOCK_END
}
@ -1525,9 +1528,9 @@ void GSLocalMemory::ReadTexture4HL(const GSVector4i& r, uint8* dst, int dstpitch
{
const uint32* pal = m_clut;
FOREACH_BLOCK_START(8, 8, 32)
FOREACH_BLOCK_START(8, 8, 32, PSM_PSMT4HL)
{
ReadAndExpandBlock4HL_32(BlockPtr32(x, y, bp, bw), dst, dstpitch, pal);
ReadAndExpandBlock4HL_32(src, dst, dstpitch, pal);
}
FOREACH_BLOCK_END
}
@ -1536,18 +1539,18 @@ void GSLocalMemory::ReadTexture4HH(const GSVector4i& r, uint8* dst, int dstpitch
{
const uint32* pal = m_clut;
FOREACH_BLOCK_START(8, 8, 32)
FOREACH_BLOCK_START(8, 8, 32, PSM_PSMT4HH)
{
ReadAndExpandBlock4HH_32(BlockPtr32(x, y, bp, bw), dst, dstpitch, pal);
ReadAndExpandBlock4HH_32(src, dst, dstpitch, pal);
}
FOREACH_BLOCK_END
}
void GSLocalMemory::ReadTexture32Z(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const
{
FOREACH_BLOCK_START(8, 8, 32)
FOREACH_BLOCK_START(8, 8, 32, PSM_PSMZ32)
{
ReadBlock32<true>(BlockPtr32Z(x, y, bp, bw), dst, dstpitch);
ReadBlock32<true>(src, dst, dstpitch);
}
FOREACH_BLOCK_END
}
@ -1556,17 +1559,17 @@ void GSLocalMemory::ReadTexture24Z(const GSVector4i& r, uint8* dst, int dstpitch
{
if(TEXA.AEM)
{
FOREACH_BLOCK_START(8, 8, 32)
FOREACH_BLOCK_START(8, 8, 32, PSM_PSMZ24)
{
ReadAndExpandBlock24<true>(BlockPtr32Z(x, y, bp, bw), dst, dstpitch, TEXA);
ReadAndExpandBlock24<true>(src, dst, dstpitch, TEXA);
}
FOREACH_BLOCK_END
}
else
{
FOREACH_BLOCK_START(8, 8, 32)
FOREACH_BLOCK_START(8, 8, 32, PSM_PSMZ24)
{
ReadAndExpandBlock24<false>(BlockPtr32Z(x, y, bp, bw), dst, dstpitch, TEXA);
ReadAndExpandBlock24<false>(src, dst, dstpitch, TEXA);
}
FOREACH_BLOCK_END
}
@ -1576,9 +1579,9 @@ void GSLocalMemory::ReadTexture16Z(const GSVector4i& r, uint8* dst, int dstpitch
{
__declspec(align(16)) uint16 block[16 * 8];
FOREACH_BLOCK_START(16, 8, 32)
FOREACH_BLOCK_START(16, 8, 32, PSM_PSMZ16)
{
ReadBlock16<true>(BlockPtr16Z(x, y, bp, bw), (uint8*)block, sizeof(block) / 8);
ReadBlock16<true>(src, (uint8*)block, sizeof(block) / 8);
ExpandBlock16(block, dst, dstpitch, TEXA);
}
@ -1589,9 +1592,9 @@ void GSLocalMemory::ReadTexture16SZ(const GSVector4i& r, uint8* dst, int dstpitc
{
__declspec(align(16)) uint16 block[16 * 8];
FOREACH_BLOCK_START(16, 8, 32)
FOREACH_BLOCK_START(16, 8, 32, PSM_PSMZ16S)
{
ReadBlock16<true>(BlockPtr16SZ(x, y, bp, bw), (uint8*)block, sizeof(block) / 8);
ReadBlock16<true>(src, (uint8*)block, sizeof(block) / 8);
ExpandBlock16(block, dst, dstpitch, TEXA);
}
@ -1736,18 +1739,18 @@ void GSLocalMemory::ReadTexture(const GSVector4i& r, uint8* dst, int dstpitch, c
void GSLocalMemory::ReadTexture16NP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const
{
FOREACH_BLOCK_START(16, 8, 16)
FOREACH_BLOCK_START(16, 8, 16, PSM_PSMCT16)
{
ReadBlock16<true>(BlockPtr16(x, y, bp, bw), dst, dstpitch);
ReadBlock16<true>(src, dst, dstpitch);
}
FOREACH_BLOCK_END
}
void GSLocalMemory::ReadTexture16SNP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const
{
FOREACH_BLOCK_START(16, 8, 16)
FOREACH_BLOCK_START(16, 8, 16, PSM_PSMCT16S)
{
ReadBlock16<true>(BlockPtr16S(x, y, bp, bw), dst, dstpitch);
ReadBlock16<true>(src, dst, dstpitch);
}
FOREACH_BLOCK_END
}
@ -1758,9 +1761,9 @@ void GSLocalMemory::ReadTexture8NP(const GSVector4i& r, uint8* dst, int dstpitch
if(TEX0.CPSM == PSM_PSMCT32 || TEX0.CPSM == PSM_PSMCT24)
{
FOREACH_BLOCK_START(16, 16, 32)
FOREACH_BLOCK_START(16, 16, 32, PSM_PSMT8)
{
ReadAndExpandBlock8_32(BlockPtr8(x, y, bp, bw), dst, dstpitch, pal);
ReadAndExpandBlock8_32(src, dst, dstpitch, pal);
}
FOREACH_BLOCK_END
}
@ -1770,9 +1773,9 @@ void GSLocalMemory::ReadTexture8NP(const GSVector4i& r, uint8* dst, int dstpitch
__declspec(align(16)) uint8 block[16 * 16];
FOREACH_BLOCK_START(16, 16, 16)
FOREACH_BLOCK_START(16, 16, 16, PSM_PSMT8)
{
ReadBlock8<true>(BlockPtr8(x, y, bp, bw), (uint8*)block, sizeof(block) / 16);
ReadBlock8<true>(src, (uint8*)block, sizeof(block) / 16);
ExpandBlock8_16(block, dst, dstpitch, pal);
}
@ -1786,9 +1789,9 @@ void GSLocalMemory::ReadTexture4NP(const GSVector4i& r, uint8* dst, int dstpitch
if(TEX0.CPSM == PSM_PSMCT32 || TEX0.CPSM == PSM_PSMCT24)
{
FOREACH_BLOCK_START(32, 16, 32)
FOREACH_BLOCK_START(32, 16, 32, PSM_PSMT4)
{
ReadAndExpandBlock4_32(BlockPtr4(x, y, bp, bw), dst, dstpitch, pal);
ReadAndExpandBlock4_32(src, dst, dstpitch, pal);
}
FOREACH_BLOCK_END
}
@ -1798,9 +1801,9 @@ void GSLocalMemory::ReadTexture4NP(const GSVector4i& r, uint8* dst, int dstpitch
__declspec(align(16)) uint8 block[(32 / 2) * 16];
FOREACH_BLOCK_START(32, 16, 16)
FOREACH_BLOCK_START(32, 16, 16, PSM_PSMT4)
{
ReadBlock4<true>(BlockPtr4(x, y, bp, bw), (uint8*)block, sizeof(block) / 16);
ReadBlock4<true>(src, (uint8*)block, sizeof(block) / 16);
ExpandBlock4_16(block, dst, dstpitch, pal);
}
@ -1814,9 +1817,9 @@ void GSLocalMemory::ReadTexture8HNP(const GSVector4i& r, uint8* dst, int dstpitc
if(TEX0.CPSM == PSM_PSMCT32 || TEX0.CPSM == PSM_PSMCT24)
{
FOREACH_BLOCK_START(8, 8, 32)
FOREACH_BLOCK_START(8, 8, 32, PSM_PSMT8H)
{
ReadAndExpandBlock8H_32(BlockPtr32(x, y, bp, bw), dst, dstpitch, pal);
ReadAndExpandBlock8H_32(src, dst, dstpitch, pal);
}
FOREACH_BLOCK_END
}
@ -1826,9 +1829,9 @@ void GSLocalMemory::ReadTexture8HNP(const GSVector4i& r, uint8* dst, int dstpitc
__declspec(align(16)) uint32 block[8 * 8];
FOREACH_BLOCK_START(8, 8, 16)
FOREACH_BLOCK_START(8, 8, 16, PSM_PSMT8H)
{
ReadBlock32<true>(BlockPtr32(x, y, bp, bw), (uint8*)block, sizeof(block) / 8);
ReadBlock32<true>(src, (uint8*)block, sizeof(block) / 8);
ExpandBlock8H_16(block, dst, dstpitch, pal);
}
@ -1842,9 +1845,9 @@ void GSLocalMemory::ReadTexture4HLNP(const GSVector4i& r, uint8* dst, int dstpit
if(TEX0.CPSM == PSM_PSMCT32 || TEX0.CPSM == PSM_PSMCT24)
{
FOREACH_BLOCK_START(8, 8, 32)
FOREACH_BLOCK_START(8, 8, 32, PSM_PSMT4HL)
{
ReadAndExpandBlock4HL_32(BlockPtr32(x, y, bp, bw), dst, dstpitch, pal);
ReadAndExpandBlock4HL_32(src, dst, dstpitch, pal);
}
FOREACH_BLOCK_END
}
@ -1854,9 +1857,9 @@ void GSLocalMemory::ReadTexture4HLNP(const GSVector4i& r, uint8* dst, int dstpit
__declspec(align(16)) uint32 block[8 * 8];
FOREACH_BLOCK_START(8, 8, 16)
FOREACH_BLOCK_START(8, 8, 16, PSM_PSMT4HL)
{
ReadBlock32<true>(BlockPtr32(x, y, bp, bw), (uint8*)block, sizeof(block) / 8);
ReadBlock32<true>(src, (uint8*)block, sizeof(block) / 8);
ExpandBlock4HL_16(block, dst, dstpitch, pal);
}
@ -1870,9 +1873,9 @@ void GSLocalMemory::ReadTexture4HHNP(const GSVector4i& r, uint8* dst, int dstpit
if(TEX0.CPSM == PSM_PSMCT32 || TEX0.CPSM == PSM_PSMCT24)
{
FOREACH_BLOCK_START(8, 8, 32)
FOREACH_BLOCK_START(8, 8, 32, PSM_PSMT4HH)
{
ReadAndExpandBlock4HH_32(BlockPtr32(x, y, bp, bw), dst, dstpitch, pal);
ReadAndExpandBlock4HH_32(src, dst, dstpitch, pal);
}
FOREACH_BLOCK_END
}
@ -1882,9 +1885,9 @@ void GSLocalMemory::ReadTexture4HHNP(const GSVector4i& r, uint8* dst, int dstpit
__declspec(align(16)) uint32 block[8 * 8];
FOREACH_BLOCK_START(8, 8, 16)
FOREACH_BLOCK_START(8, 8, 16, PSM_PSMT4HH)
{
ReadBlock32<true>(BlockPtr32(x, y, bp, bw), (uint8*)block, sizeof(block) / 8);
ReadBlock32<true>(src, (uint8*)block, sizeof(block) / 8);
ExpandBlock4HH_16(block, dst, dstpitch, pal);
}
@ -1894,18 +1897,18 @@ void GSLocalMemory::ReadTexture4HHNP(const GSVector4i& r, uint8* dst, int dstpit
void GSLocalMemory::ReadTexture16ZNP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const
{
FOREACH_BLOCK_START(16, 8, 16)
FOREACH_BLOCK_START(16, 8, 16, PSM_PSMZ16)
{
ReadBlock16<true>(BlockPtr16Z(x, y, bp, bw), dst, dstpitch);
ReadBlock16<true>(src, dst, dstpitch);
}
FOREACH_BLOCK_END
}
void GSLocalMemory::ReadTexture16SZNP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const
{
FOREACH_BLOCK_START(16, 8, 16)
FOREACH_BLOCK_START(16, 8, 16, PSM_PSMZ16S)
{
ReadBlock16<true>(BlockPtr16SZ(x, y, bp, bw), dst, dstpitch);
ReadBlock16<true>(src, dst, dstpitch);
}
FOREACH_BLOCK_END
}
@ -1958,45 +1961,45 @@ void GSLocalMemory::ReadTextureNP(const GSVector4i& r, uint8* dst, int dstpitch,
void GSLocalMemory::ReadTexture8P(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const
{
FOREACH_BLOCK_START(16, 16, 8)
FOREACH_BLOCK_START(16, 16, 8, PSM_PSMT8)
{
ReadBlock8<true>(BlockPtr8(x, y, bp, bw), dst, dstpitch);
ReadBlock8<true>(src, dst, dstpitch);
}
FOREACH_BLOCK_END
}
void GSLocalMemory::ReadTexture4P(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const
{
FOREACH_BLOCK_START(32, 16, 8)
FOREACH_BLOCK_START(32, 16, 8, PSM_PSMT4)
{
ReadBlock4P(BlockPtr4(x, y, bp, bw), dst, dstpitch);
ReadBlock4P(src, dst, dstpitch);
}
FOREACH_BLOCK_END
}
void GSLocalMemory::ReadTexture8HP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const
{
FOREACH_BLOCK_START(8, 8, 8)
FOREACH_BLOCK_START(8, 8, 8, PSM_PSMT8H)
{
ReadBlock8HP(BlockPtr32(x, y, bp, bw), dst, dstpitch);
ReadBlock8HP(src, dst, dstpitch);
}
FOREACH_BLOCK_END
}
void GSLocalMemory::ReadTexture4HLP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const
{
FOREACH_BLOCK_START(8, 8, 8)
FOREACH_BLOCK_START(8, 8, 8, PSM_PSMT4HL)
{
ReadBlock4HLP(BlockPtr32(x, y, bp, bw), dst, dstpitch);
ReadBlock4HLP(src, dst, dstpitch);
}
FOREACH_BLOCK_END
}
void GSLocalMemory::ReadTexture4HHP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const
{
FOREACH_BLOCK_START(8, 8, 8)
FOREACH_BLOCK_START(8, 8, 8, PSM_PSMT4HH)
{
ReadBlock4HHP(BlockPtr32(x, y, bp, bw), dst, dstpitch);
ReadBlock4HHP(src, dst, dstpitch);
}
FOREACH_BLOCK_END
}

View File

@ -426,7 +426,7 @@ void GSRenderer::KeyEvent(GSKeyEventData* e)
}
}
void GSRenderer::GetTextureMinMax(GSVector4i& r)
void GSRenderer::GetTextureMinMax(GSVector4i& r, bool linear)
{
const GSDrawingContext* context = m_context;
@ -488,7 +488,7 @@ void GSRenderer::GetTextureMinMax(GSVector4i& r)
{
GSVector4 st = m_vt.m_min.t.xyxy(m_vt.m_max.t);
if(context->TEX1.IsLinear())
if(linear)
{
st += GSVector4(-0x8000, 0x8000).xxyy();
}
@ -697,6 +697,21 @@ bool GSRenderer::TryAlphaTest(uint32& fm, uint32& zm)
return true;
}
bool GSRenderer::IsLinear()
{
float qmin = m_vt.m_min.t.z;
float qmax = m_vt.m_max.t.z;
if(PRIM->FST)
{
// assume Q = 1.0f => LOD > 0 (should not, but Q is very often bogus, 0 or DEN)
qmin = qmax = 1.0f;
}
return m_context->TEX1.IsLinear(qmin, qmax);
}
bool GSRenderer::IsOpaque()
{
if(PRIM->AA1)

View File

@ -53,9 +53,10 @@ protected:
// following functions need m_vt to be initialized
void GetTextureMinMax(GSVector4i& r);
void GetTextureMinMax(GSVector4i& r, bool linear);
void GetAlphaMinMax();
bool TryAlphaTest(uint32& fm, uint32& zm);
bool IsLinear();
bool IsOpaque();
public:
@ -127,6 +128,8 @@ protected:
// FIXME: berserk fpsm = 27 (8H)
Draw();
m_perfmon.Put(GSPerfMon::Draw, 1);
}
m_count = 0;
@ -222,9 +225,9 @@ protected:
public:
GSRendererT(uint8* base, bool mt, void (*irq)(), GSDevice* dev)
: GSRenderer(base, mt, irq, dev)
, m_vertices(NULL)
, m_count(0)
, m_maxcount(0)
, m_vertices(NULL)
{
}

View File

@ -0,0 +1,23 @@
/*
* Copyright (C) 2007-2009 Gabest
* http://www.gabest.org
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
#include "stdafx.h"
#include "GSRendererDX.h"

338
plugins/GSdx/GSRendererDX.h Normal file
View File

@ -0,0 +1,338 @@
/*
* Copyright (C) 2007-2009 Gabest
* http://www.gabest.org
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
#pragma once
#include "GSRendererHW.h"
#include "GSTextureFX.h"
template<class Vertex>
class GSRendererDX : public GSRendererHW<Vertex>
{
GSTextureFX* m_tfx;
bool m_logz;
bool m_fba;
protected:
int m_topology;
GSVector2 m_pixelcenter;
virtual void SetupDATE(GSTexture* rt, GSTexture* ds) {}
virtual void UpdateFBA(GSTexture* rt) {}
public:
GSRendererDX(uint8* base, bool mt, void (*irq)(), GSDevice* dev, GSTextureCache* tc, GSTextureFX* tfx)
: GSRendererHW<Vertex>(base, mt, irq, dev, tc)
, m_tfx(tfx)
, m_topology(-1)
, m_pixelcenter(0, 0)
{
m_logz = !!theApp.GetConfig("logz", 0);
m_fba = !!theApp.GetConfig("fba", 1);
}
virtual ~GSRendererDX()
{
delete m_tfx;
}
bool Create(const string& title)
{
if(!__super::Create(title))
return false;
if(!m_tfx->Create(m_dev))
return false;
return true;
}
void Draw(GS_PRIM_CLASS primclass, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex)
{
GSDrawingEnvironment& env = m_env;
GSDrawingContext* context = m_context;
//
SetupDATE(rt, ds);
//
m_dev->BeginScene();
// om
GSTextureFX::OMDepthStencilSelector om_dssel;
om_dssel.zte = context->TEST.ZTE;
om_dssel.ztst = context->TEST.ZTST;
om_dssel.zwe = !context->ZBUF.ZMSK;
om_dssel.date = context->FRAME.PSM != PSM_PSMCT24 ? context->TEST.DATE : 0;
om_dssel.fba = m_fba ? context->FBA.FBA : 0;
GSTextureFX::OMBlendSelector om_bsel;
om_bsel.abe = !IsOpaque();
om_bsel.a = context->ALPHA.A;
om_bsel.b = context->ALPHA.B;
om_bsel.c = context->ALPHA.C;
om_bsel.d = context->ALPHA.D;
om_bsel.wr = (context->FRAME.FBMSK & 0x000000ff) != 0x000000ff;
om_bsel.wg = (context->FRAME.FBMSK & 0x0000ff00) != 0x0000ff00;
om_bsel.wb = (context->FRAME.FBMSK & 0x00ff0000) != 0x00ff0000;
om_bsel.wa = (context->FRAME.FBMSK & 0xff000000) != 0xff000000;
// vs
GSTextureFX::VSSelector vs_sel;
vs_sel.bppz = 0;
vs_sel.tme = PRIM->TME;
vs_sel.fst = PRIM->FST;
vs_sel.logz = m_logz ? 1 : 0;
vs_sel.prim = primclass;
if(om_dssel.zte && om_dssel.ztst > 0 && om_dssel.zwe)
{
if(context->ZBUF.PSM == PSM_PSMZ24)
{
if(m_vt.m_max.p.z > 0xffffff)
{
ASSERT(m_vt.m_min.p.z > 0xffffff);
vs_sel.bppz = 1;
om_dssel.ztst = 1;
}
}
else if(context->ZBUF.PSM == PSM_PSMZ16 || context->ZBUF.PSM == PSM_PSMZ16S)
{
if(m_vt.m_max.p.z > 0xffff)
{
ASSERT(m_vt.m_min.p.z > 0xffff); // sfex capcom logo
vs_sel.bppz = 2;
om_dssel.ztst = 1;
}
}
}
GSTextureFX::VSConstantBuffer vs_cb;
float sx = 2.0f * rt->m_scale.x / (rt->GetWidth() * 16);
float sy = 2.0f * rt->m_scale.y / (rt->GetHeight() * 16);
float ox = (float)(int)context->XYOFFSET.OFX;
float oy = (float)(int)context->XYOFFSET.OFY;
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);
if(PRIM->TME)
{
if(PRIM->FST)
{
vs_cb.TextureScale.x = 1.0f / (16 << context->TEX0.TW);
vs_cb.TextureScale.y = 1.0f / (16 << context->TEX0.TH);
}
else
{
vs_cb.TextureScale = GSVector2(1.0f, 1.0f);
}
}
// gs
GSTextureFX::GSSelector gs_sel;
gs_sel.iip = PRIM->IIP;
gs_sel.prim = primclass;
// ps
GSTextureFX::PSSelector ps_sel;
ps_sel.fst = PRIM->FST;
ps_sel.wms = context->CLAMP.WMS;
ps_sel.wmt = context->CLAMP.WMT;
ps_sel.bpp = 0;
ps_sel.aem = env.TEXA.AEM;
ps_sel.tfx = context->TEX0.TFX;
ps_sel.tcc = context->TEX0.TCC;
ps_sel.ate = context->TEST.ATE;
ps_sel.atst = context->TEST.ATST;
ps_sel.fog = PRIM->FGE;
ps_sel.clr1 = om_bsel.abe && om_bsel.a == 1 && om_bsel.b == 2 && om_bsel.d == 1;
ps_sel.fba = context->FBA.FBA;
ps_sel.aout = context->FRAME.PSM == PSM_PSMCT16 || context->FRAME.PSM == PSM_PSMCT16S || (context->FRAME.FBMSK & 0xff000000) == 0x7f000000 ? 1 : 0;
ps_sel.ltf = m_filter == 2 ? IsLinear() : m_filter;
GSTextureFX::PSSamplerSelector ps_ssel;
ps_ssel.tau = 0;
ps_ssel.tav = 0;
ps_ssel.ltf = ps_sel.ltf;
GSTextureFX::PSConstantBuffer ps_cb;
ps_cb.FogColor_AREF = GSVector4((int)env.FOGCOL.FCR, (int)env.FOGCOL.FCG, (int)env.FOGCOL.FCB, (int)context->TEST.AREF) / 255;
if(ps_sel.atst == 2 || ps_sel.atst == 5)
{
ps_cb.FogColor_AREF.a -= 0.9f / 255;
}
else if(ps_sel.atst == 3 || ps_sel.atst == 6)
{
ps_cb.FogColor_AREF.a += 0.9f / 255;
}
if(tex)
{
ps_sel.bpp = tex->m_bpp;
int w = tex->m_texture->GetWidth();
int h = tex->m_texture->GetHeight();
ps_cb.WH = GSVector4((int)(1 << context->TEX0.TW), (int)(1 << context->TEX0.TH), w, h);
ps_cb.HalfTexel = GSVector4(-0.5f, 0.5f).xxyy() / GSVector4(w, h).xyxy();
ps_cb.MinF_TA.z = (float)(int)env.TEXA.TA0 / 255;
ps_cb.MinF_TA.w = (float)(int)env.TEXA.TA1 / 255;
switch(context->CLAMP.WMS)
{
case 0:
ps_ssel.tau = 1;
break;
case 1:
ps_ssel.tau = 0;
break;
case 2:
ps_cb.MinMax.x = ((float)(int)context->CLAMP.MINU) / (1 << context->TEX0.TW);
ps_cb.MinMax.z = ((float)(int)context->CLAMP.MAXU) / (1 << context->TEX0.TW);
ps_cb.MinF_TA.x = ((float)(int)context->CLAMP.MINU + 0.5f) / (1 << context->TEX0.TW);
ps_ssel.tau = 0;
break;
case 3:
ps_cb.MskFix.x = context->CLAMP.MINU;
ps_cb.MskFix.z = context->CLAMP.MAXU;
ps_ssel.tau = 1;
break;
default:
__assume(0);
}
switch(context->CLAMP.WMT)
{
case 0:
ps_ssel.tav = 1;
break;
case 1:
ps_ssel.tav = 0;
break;
case 2:
ps_cb.MinMax.y = ((float)(int)context->CLAMP.MINV) / (1 << context->TEX0.TH);
ps_cb.MinMax.w = ((float)(int)context->CLAMP.MAXV) / (1 << context->TEX0.TH);
ps_cb.MinF_TA.y = ((float)(int)context->CLAMP.MINV + 0.5f) / (1 << context->TEX0.TH);
ps_ssel.tav = 0;
break;
case 3:
ps_cb.MskFix.y = context->CLAMP.MINV;
ps_cb.MskFix.w = context->CLAMP.MAXV;
ps_ssel.tav = 1;
break;
default:
__assume(0);
}
}
else
{
ps_sel.tfx = 4;
}
// rs
int w = rt->GetWidth();
int h = rt->GetHeight();
GSVector4i scissor = GSVector4i(GSVector4(rt->m_scale).xyxy() * context->scissor.in).rintersect(GSVector4i(0, 0, w, h));
//
uint8 afix = context->ALPHA.FIX;
m_tfx->SetupOM(om_dssel, om_bsel, afix, rt, ds);
m_tfx->SetupIA(m_vertices, m_count, m_topology);
m_tfx->SetupVS(vs_sel, &vs_cb);
m_tfx->SetupGS(gs_sel);
m_tfx->SetupPS(ps_sel, &ps_cb, ps_ssel, tex ? tex->m_texture : NULL, tex ? tex->m_palette : NULL);
m_tfx->SetupRS(w, h, scissor);
// draw
if(context->TEST.DoFirstPass())
{
m_dev->DrawPrimitive();
}
if(context->TEST.DoSecondPass())
{
ASSERT(!env.PABE.PABE);
static const uint32 iatst[] = {1, 0, 5, 6, 7, 2, 3, 4};
ps_sel.atst = iatst[ps_sel.atst];
m_tfx->UpdatePS(ps_sel, &ps_cb, ps_ssel);
bool z = om_dssel.zwe;
bool r = om_bsel.wr;
bool g = om_bsel.wg;
bool b = om_bsel.wb;
bool a = om_bsel.wa;
switch(context->TEST.AFAIL)
{
case 0: z = r = g = b = a = false; break; // none
case 1: z = false; break; // rgba
case 2: r = g = b = a = false; break; // z
case 3: z = a = false; break; // rgb
default: __assume(0);
}
if(z || r || g || b || a)
{
om_dssel.zwe = z;
om_bsel.wr = r;
om_bsel.wg = g;
om_bsel.wb = b;
om_bsel.wa = a;
m_tfx->UpdateOM(om_dssel, om_bsel, afix);
m_dev->DrawPrimitive();
}
}
m_dev->EndScene();
if(om_dssel.fba) UpdateFBA(rt);
}
};

View File

@ -0,0 +1,266 @@
/*
* Copyright (C) 2007-2009 Gabest
* http://www.gabest.org
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
#include "stdafx.h"
#include "GSRendererDX10.h"
#include "GSCrc.h"
#include "resource.h"
GSRendererDX10::GSRendererDX10(uint8* base, bool mt, void (*irq)())
: GSRendererDX<GSVertexHW10>(base, mt, irq, new GSDevice10(), new GSTextureCache10(this), new GSTextureFX10())
{
InitVertexKick<GSRendererDX10>();
m_pixelcenter = GSVector2(-0.5f, -0.5f);
}
bool GSRendererDX10::Create(const string& title)
{
if(!__super::Create(title))
return false;
//
D3D10_DEPTH_STENCIL_DESC dsd;
memset(&dsd, 0, sizeof(dsd));
dsd.DepthEnable = false;
dsd.StencilEnable = true;
dsd.StencilReadMask = 1;
dsd.StencilWriteMask = 1;
dsd.FrontFace.StencilFunc = D3D10_COMPARISON_ALWAYS;
dsd.FrontFace.StencilPassOp = D3D10_STENCIL_OP_REPLACE;
dsd.FrontFace.StencilFailOp = D3D10_STENCIL_OP_KEEP;
dsd.FrontFace.StencilDepthFailOp = D3D10_STENCIL_OP_KEEP;
dsd.BackFace.StencilFunc = D3D10_COMPARISON_ALWAYS;
dsd.BackFace.StencilPassOp = D3D10_STENCIL_OP_REPLACE;
dsd.BackFace.StencilFailOp = D3D10_STENCIL_OP_KEEP;
dsd.BackFace.StencilDepthFailOp = D3D10_STENCIL_OP_KEEP;
(*(GSDevice10*)m_dev)->CreateDepthStencilState(&dsd, &m_date.dss);
D3D10_BLEND_DESC bd;
memset(&bd, 0, sizeof(bd));
(*(GSDevice10*)m_dev)->CreateBlendState(&bd, &m_date.bs);
//
return true;
}
template<uint32 prim, uint32 tme, uint32 fst>
void GSRendererDX10::VertexKick(bool skip)
{
GSVertexHW10& dst = m_vl.AddTail();
dst.vi[0] = m_v.vi[0];
dst.vi[1] = m_v.vi[1];
if(tme && fst)
{
GSVector4::storel(&dst.ST, m_v.GetUV());
}
int count = 0;
if(GSVertexHW10* v = DrawingKick<prim>(skip, count))
{
GSVector4i scissor = m_context->scissor.dx10;
#if _M_SSE >= 0x401
GSVector4i pmin, pmax, v0, v1, v2;
switch(prim)
{
case GS_POINTLIST:
v0 = GSVector4i::load((int)v[0].p.xy).upl16();
pmin = v0;
pmax = v0;
break;
case GS_LINELIST:
case GS_LINESTRIP:
case GS_SPRITE:
v0 = GSVector4i::load((int)v[0].p.xy);
v1 = GSVector4i::load((int)v[1].p.xy);
pmin = v0.min_u16(v1).upl16();
pmax = v0.max_u16(v1).upl16();
break;
case GS_TRIANGLELIST:
case GS_TRIANGLESTRIP:
case GS_TRIANGLEFAN:
v0 = GSVector4i::load((int)v[0].p.xy);
v1 = GSVector4i::load((int)v[1].p.xy);
v2 = GSVector4i::load((int)v[2].p.xy);
pmin = v0.min_u16(v1).min_u16(v2).upl16();
pmax = v0.max_u16(v1).max_u16(v2).upl16();
break;
}
GSVector4i test = (pmax < scissor) | (pmin > scissor.zwxy());
if(test.mask() & 0xff)
{
return;
}
#else
switch(prim)
{
case GS_POINTLIST:
if(v[0].p.x < scissor.x
|| v[0].p.x > scissor.z
|| v[0].p.y < scissor.y
|| v[0].p.y > scissor.w)
{
return;
}
break;
case GS_LINELIST:
case GS_LINESTRIP:
case GS_SPRITE:
if(v[0].p.x < scissor.x && v[1].p.x < scissor.x
|| v[0].p.x > scissor.z && v[1].p.x > scissor.z
|| v[0].p.y < scissor.y && v[1].p.y < scissor.y
|| v[0].p.y > scissor.w && v[1].p.y > scissor.w)
{
return;
}
break;
case GS_TRIANGLELIST:
case GS_TRIANGLESTRIP:
case GS_TRIANGLEFAN:
if(v[0].p.x < scissor.x && v[1].p.x < scissor.x && v[2].p.x < scissor.x
|| v[0].p.x > scissor.z && v[1].p.x > scissor.z && v[2].p.x > scissor.z
|| v[0].p.y < scissor.y && v[1].p.y < scissor.y && v[2].p.y < scissor.y
|| v[0].p.y > scissor.w && v[1].p.y > scissor.w && v[2].p.y > scissor.w)
{
return;
}
break;
}
#endif
m_count += count;
}
}
void GSRendererDX10::Draw(GS_PRIM_CLASS primclass, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex)
{
switch(primclass)
{
case GS_POINT_CLASS:
m_topology = D3D10_PRIMITIVE_TOPOLOGY_POINTLIST;
m_perfmon.Put(GSPerfMon::Prim, m_count);
break;
case GS_LINE_CLASS:
case GS_SPRITE_CLASS:
m_topology = D3D10_PRIMITIVE_TOPOLOGY_LINELIST;
m_perfmon.Put(GSPerfMon::Prim, m_count / 2);
break;
case GS_TRIANGLE_CLASS:
m_topology = D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
m_perfmon.Put(GSPerfMon::Prim, m_count / 3);
break;
default:
__assume(0);
}
__super::Draw(primclass, rt, ds, tex);
}
void GSRendererDX10::SetupDATE(GSTexture* rt, GSTexture* ds)
{
if(!m_context->TEST.DATE) return; // || (::GetAsyncKeyState(VK_CONTROL) & 0x8000)
GSDevice10* dev = (GSDevice10*)m_dev;
int w = rt->GetWidth();
int h = rt->GetHeight();
if(GSTexture* t = dev->CreateRenderTarget(w, h))
{
// sfex3 (after the capcom logo), vf4 (first menu fading in), ffxii shadows, rumble roses shadows, persona4 shadows
dev->BeginScene();
dev->ClearStencil(ds, 0);
// om
dev->OMSetDepthStencilState(m_date.dss, 1);
dev->OMSetBlendState(m_date.bs, 0);
dev->OMSetRenderTargets(t, ds);
// ia
GSVector4 s = GSVector4(rt->m_scale.x / w, rt->m_scale.y / h);
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());
GSVector4 dst = src * 2.0f + o.xxxx();
GSVertexPT1 vertices[] =
{
{GSVector4(dst.x, -dst.y, 0.5f, 1.0f), GSVector2(src.x, src.y)},
{GSVector4(dst.z, -dst.y, 0.5f, 1.0f), GSVector2(src.z, src.y)},
{GSVector4(dst.x, -dst.w, 0.5f, 1.0f), GSVector2(src.x, src.w)},
{GSVector4(dst.z, -dst.w, 0.5f, 1.0f), GSVector2(src.z, src.w)},
};
dev->IASetVertexBuffer(vertices, sizeof(vertices[0]), countof(vertices));
dev->IASetInputLayout(dev->m_convert.il);
dev->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
// vs
dev->VSSetShader(dev->m_convert.vs, NULL);
// gs
dev->GSSetShader(NULL);
// ps
dev->PSSetShaderResources(rt, NULL);
dev->PSSetShader(dev->m_convert.ps[m_context->TEST.DATM ? 2 : 3], NULL);
dev->PSSetSamplerState(dev->m_convert.pt, NULL);
// rs
dev->RSSet(w, h);
// set
dev->DrawPrimitive();
//
dev->EndScene();
dev->Recycle(t);
}
}

View File

@ -21,28 +21,25 @@
#pragma once
#include "GSRendererHW.h"
#include "GSRendererDX.h"
#include "GSVertexHW.h"
#include "GSTextureCache10.h"
#include "GSTextureFX10.h"
class GSRendererHW10 : public GSRendererHW<GSVertexHW10>
class GSRendererDX10 : public GSRendererDX<GSVertexHW10>
{
protected:
GSTextureFX10 m_tfx;
void Draw(GS_PRIM_CLASS primclass, GSTexture* rt, GSTexture* ds, GSTextureCache::GSCachedTexture* tex);
struct
{
CComPtr<ID3D10DepthStencilState> dss;
CComPtr<ID3D10BlendState> bs;
} m_date;
void Draw(GS_PRIM_CLASS primclass, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex);
void SetupDATE(GSTexture* rt, GSTexture* ds);
public:
GSRendererHW10(uint8* base, bool mt, void (*irq)());
GSRendererDX10(uint8* base, bool mt, void (*irq)());
bool Create(const string& title);

View File

@ -0,0 +1,266 @@
/*
* Copyright (C) 2007-2009 Gabest
* http://www.gabest.org
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
#include "stdafx.h"
#include "GSRendererDX11.h"
#include "GSCrc.h"
#include "resource.h"
GSRendererDX11::GSRendererDX11(uint8* base, bool mt, void (*irq)())
: GSRendererDX<GSVertexHW11>(base, mt, irq, new GSDevice11(), new GSTextureCache11(this), new GSTextureFX11())
{
InitVertexKick<GSRendererDX11>();
m_pixelcenter = GSVector2(-0.5f, -0.5f);
}
bool GSRendererDX11::Create(const string& title)
{
if(!__super::Create(title))
return false;
//
D3D11_DEPTH_STENCIL_DESC dsd;
memset(&dsd, 0, sizeof(dsd));
dsd.DepthEnable = false;
dsd.StencilEnable = true;
dsd.StencilReadMask = 1;
dsd.StencilWriteMask = 1;
dsd.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
dsd.FrontFace.StencilPassOp = D3D11_STENCIL_OP_REPLACE;
dsd.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
dsd.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
dsd.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
dsd.BackFace.StencilPassOp = D3D11_STENCIL_OP_REPLACE;
dsd.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
dsd.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
(*(GSDevice11*)m_dev)->CreateDepthStencilState(&dsd, &m_date.dss);
D3D11_BLEND_DESC bd;
memset(&bd, 0, sizeof(bd));
(*(GSDevice11*)m_dev)->CreateBlendState(&bd, &m_date.bs);
//
return true;
}
template<uint32 prim, uint32 tme, uint32 fst>
void GSRendererDX11::VertexKick(bool skip)
{
GSVertexHW11& dst = m_vl.AddTail();
dst.vi[0] = m_v.vi[0];
dst.vi[1] = m_v.vi[1];
if(tme && fst)
{
GSVector4::storel(&dst.ST, m_v.GetUV());
}
int count = 0;
if(GSVertexHW11* v = DrawingKick<prim>(skip, count))
{
GSVector4i scissor = m_context->scissor.dx10;
#if _M_SSE >= 0x401
GSVector4i pmin, pmax, v0, v1, v2;
switch(prim)
{
case GS_POINTLIST:
v0 = GSVector4i::load((int)v[0].p.xy).upl16();
pmin = v0;
pmax = v0;
break;
case GS_LINELIST:
case GS_LINESTRIP:
case GS_SPRITE:
v0 = GSVector4i::load((int)v[0].p.xy);
v1 = GSVector4i::load((int)v[1].p.xy);
pmin = v0.min_u16(v1).upl16();
pmax = v0.max_u16(v1).upl16();
break;
case GS_TRIANGLELIST:
case GS_TRIANGLESTRIP:
case GS_TRIANGLEFAN:
v0 = GSVector4i::load((int)v[0].p.xy);
v1 = GSVector4i::load((int)v[1].p.xy);
v2 = GSVector4i::load((int)v[2].p.xy);
pmin = v0.min_u16(v1).min_u16(v2).upl16();
pmax = v0.max_u16(v1).max_u16(v2).upl16();
break;
}
GSVector4i test = (pmax < scissor) | (pmin > scissor.zwxy());
if(test.mask() & 0xff)
{
return;
}
#else
switch(prim)
{
case GS_POINTLIST:
if(v[0].p.x < scissor.x
|| v[0].p.x > scissor.z
|| v[0].p.y < scissor.y
|| v[0].p.y > scissor.w)
{
return;
}
break;
case GS_LINELIST:
case GS_LINESTRIP:
case GS_SPRITE:
if(v[0].p.x < scissor.x && v[1].p.x < scissor.x
|| v[0].p.x > scissor.z && v[1].p.x > scissor.z
|| v[0].p.y < scissor.y && v[1].p.y < scissor.y
|| v[0].p.y > scissor.w && v[1].p.y > scissor.w)
{
return;
}
break;
case GS_TRIANGLELIST:
case GS_TRIANGLESTRIP:
case GS_TRIANGLEFAN:
if(v[0].p.x < scissor.x && v[1].p.x < scissor.x && v[2].p.x < scissor.x
|| v[0].p.x > scissor.z && v[1].p.x > scissor.z && v[2].p.x > scissor.z
|| v[0].p.y < scissor.y && v[1].p.y < scissor.y && v[2].p.y < scissor.y
|| v[0].p.y > scissor.w && v[1].p.y > scissor.w && v[2].p.y > scissor.w)
{
return;
}
break;
}
#endif
m_count += count;
}
}
void GSRendererDX11::Draw(GS_PRIM_CLASS primclass, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex)
{
switch(primclass)
{
case GS_POINT_CLASS:
m_topology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
m_perfmon.Put(GSPerfMon::Prim, m_count);
break;
case GS_LINE_CLASS:
case GS_SPRITE_CLASS:
m_topology = D3D11_PRIMITIVE_TOPOLOGY_LINELIST;
m_perfmon.Put(GSPerfMon::Prim, m_count / 2);
break;
case GS_TRIANGLE_CLASS:
m_topology = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
m_perfmon.Put(GSPerfMon::Prim, m_count / 3);
break;
default:
__assume(0);
}
__super::Draw(primclass, rt, ds, tex);
}
void GSRendererDX11::SetupDATE(GSTexture* rt, GSTexture* ds)
{
if(!m_context->TEST.DATE) return; // || (::GetAsyncKeyState(VK_CONTROL) & 0x8000)
GSDevice11* dev = (GSDevice11*)m_dev;
int w = rt->GetWidth();
int h = rt->GetHeight();
if(GSTexture* t = dev->CreateRenderTarget(w, h))
{
// sfex3 (after the capcom logo), vf4 (first menu fading in), ffxii shadows, rumble roses shadows, persona4 shadows
dev->BeginScene();
dev->ClearStencil(ds, 0);
// om
dev->OMSetDepthStencilState(m_date.dss, 1);
dev->OMSetBlendState(m_date.bs, 0);
dev->OMSetRenderTargets(t, ds);
// ia
GSVector4 s = GSVector4(rt->m_scale.x / w, rt->m_scale.y / h);
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());
GSVector4 dst = src * 2.0f + o.xxxx();
GSVertexPT1 vertices[] =
{
{GSVector4(dst.x, -dst.y, 0.5f, 1.0f), GSVector2(src.x, src.y)},
{GSVector4(dst.z, -dst.y, 0.5f, 1.0f), GSVector2(src.z, src.y)},
{GSVector4(dst.x, -dst.w, 0.5f, 1.0f), GSVector2(src.x, src.w)},
{GSVector4(dst.z, -dst.w, 0.5f, 1.0f), GSVector2(src.z, src.w)},
};
dev->IASetVertexBuffer(vertices, sizeof(vertices[0]), countof(vertices));
dev->IASetInputLayout(dev->m_convert.il);
dev->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
// vs
dev->VSSetShader(dev->m_convert.vs, NULL);
// gs
dev->GSSetShader(NULL);
// ps
dev->PSSetShaderResources(rt, NULL);
dev->PSSetShader(dev->m_convert.ps[m_context->TEST.DATM ? 2 : 3], NULL);
dev->PSSetSamplerState(dev->m_convert.pt, NULL);
// rs
dev->RSSet(w, h);
// set
dev->DrawPrimitive();
//
dev->EndScene();
dev->Recycle(t);
}
}

View File

@ -21,17 +21,15 @@
#pragma once
#include "GSRendererHW.h"
#include "GSRendererDX.h"
#include "GSVertexHW.h"
#include "GSTextureCache11.h"
#include "GSTextureFX11.h"
class GSRendererHW11 : public GSRendererHW<GSVertexHW11>
class GSRendererDX11 : public GSRendererDX<GSVertexHW11>
{
protected:
GSTextureFX11 m_tfx;
void Draw(GS_PRIM_CLASS primclass, GSTexture* rt, GSTexture* ds, GSTextureCache::GSCachedTexture* tex);
void Draw(GS_PRIM_CLASS primclass, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex);
struct
{
@ -42,7 +40,7 @@ protected:
void SetupDATE(GSTexture* rt, GSTexture* ds);
public:
GSRendererHW11(uint8* base, bool mt, void (*irq)());
GSRendererDX11(uint8* base, bool mt, void (*irq)());
bool Create(const string& title);

View File

@ -0,0 +1,322 @@
/*
* Copyright (C) 2007-2009 Gabest
* http://www.gabest.org
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
#include "stdafx.h"
#include "GSRendererDX9.h"
#include "GSCrc.h"
#include "resource.h"
GSRendererDX9::GSRendererDX9(uint8* base, bool mt, void (*irq)())
: GSRendererDX<GSVertexHW9>(base, mt, irq, new GSDevice9(), new GSTextureCache9(this), new GSTextureFX9())
{
InitVertexKick<GSRendererDX9>();
}
bool GSRendererDX9::Create(const string& title)
{
if(!__super::Create(title))
return false;
//
memset(&m_date.dss, 0, sizeof(m_date.dss));
m_date.dss.StencilEnable = true;
m_date.dss.StencilReadMask = 1;
m_date.dss.StencilWriteMask = 1;
m_date.dss.StencilFunc = D3DCMP_ALWAYS;
m_date.dss.StencilPassOp = D3DSTENCILOP_REPLACE;
m_date.dss.StencilRef = 1;
memset(&m_date.bs, 0, sizeof(m_date.bs));
//
memset(&m_fba.dss, 0, sizeof(m_fba.dss));
m_fba.dss.StencilEnable = true;
m_fba.dss.StencilReadMask = 2;
m_fba.dss.StencilWriteMask = 2;
m_fba.dss.StencilFunc = D3DCMP_EQUAL;
m_fba.dss.StencilPassOp = D3DSTENCILOP_ZERO;
m_fba.dss.StencilFailOp = D3DSTENCILOP_ZERO;
m_fba.dss.StencilDepthFailOp = D3DSTENCILOP_ZERO;
m_fba.dss.StencilRef = 2;
memset(&m_fba.bs, 0, sizeof(m_fba.bs));
m_fba.bs.RenderTargetWriteMask = D3DCOLORWRITEENABLE_ALPHA;
//
return true;
}
template<uint32 prim, uint32 tme, uint32 fst>
void GSRendererDX9::VertexKick(bool skip)
{
GSVertexHW9 v;
v.p = GSVector4(((GSVector4i)m_v.XYZ).upl16());
if(tme && !fst)
{
v.p = v.p.xyxy(GSVector4((float)m_v.XYZ.Z, m_v.RGBAQ.Q));
}
else
{
v.p = v.p.xyxy(GSVector4::load((float)m_v.XYZ.Z));
}
if(tme)
{
if(fst)
{
v.t = m_v.GetUV();
}
else
{
v.t = GSVector4::loadl(&m_v.ST);
}
}
GSVertexHW9& dst = m_vl.AddTail();
dst = v;
dst.c0 = m_v.RGBAQ.u32[0];
dst.c1 = m_v.FOG.u32[1];
int count = 0;
if(GSVertexHW9* v = DrawingKick<prim>(skip, count))
{
GSVector4 scissor = m_context->scissor.dx9;
GSVector4 pmin, pmax;
switch(prim)
{
case GS_POINTLIST:
pmin = v[0].p;
pmax = v[0].p;
break;
case GS_LINELIST:
case GS_LINESTRIP:
case GS_SPRITE:
pmin = v[0].p.minv(v[1].p);
pmax = v[0].p.maxv(v[1].p);
break;
case GS_TRIANGLELIST:
case GS_TRIANGLESTRIP:
case GS_TRIANGLEFAN:
pmin = v[0].p.minv(v[1].p).minv(v[2].p);
pmax = v[0].p.maxv(v[1].p).maxv(v[2].p);
break;
}
GSVector4 test = (pmax < scissor) | (pmin > scissor.zwxy());
if(test.mask() & 3)
{
return;
}
switch(prim)
{
case GS_POINTLIST:
break;
case GS_LINELIST:
case GS_LINESTRIP:
if(PRIM->IIP == 0) {v[0].c0 = v[1].c0;}
break;
case GS_TRIANGLELIST:
case GS_TRIANGLESTRIP:
case GS_TRIANGLEFAN:
if(PRIM->IIP == 0) {v[0].c0 = v[1].c0 = v[2].c0;}
break;
case GS_SPRITE:
if(PRIM->IIP == 0) {v[0].c0 = v[1].c0;}
v[0].p.z = v[1].p.z;
v[0].p.w = v[1].p.w;
v[0].c1 = v[1].c1;
v[2] = v[1];
v[3] = v[1];
v[1].p.y = v[0].p.y;
v[1].t.y = v[0].t.y;
v[2].p.x = v[0].p.x;
v[2].t.x = v[0].t.x;
v[4] = v[1];
v[5] = v[2];
count += 4;
break;
}
m_count += count;
}
}
void GSRendererDX9::Draw(GS_PRIM_CLASS primclass, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex)
{
switch(primclass)
{
case GS_POINT_CLASS:
m_topology = D3DPT_POINTLIST;
m_perfmon.Put(GSPerfMon::Prim, m_count);
break;
case GS_LINE_CLASS:
m_topology = D3DPT_LINELIST;
m_perfmon.Put(GSPerfMon::Prim, m_count / 2);
break;
case GS_TRIANGLE_CLASS:
case GS_SPRITE_CLASS:
m_topology = D3DPT_TRIANGLELIST;
m_perfmon.Put(GSPerfMon::Prim, m_count / 3);
break;
default:
__assume(0);
}
(*(GSDevice9*)m_dev)->SetRenderState(D3DRS_SHADEMODE, PRIM->IIP ? D3DSHADE_GOURAUD : D3DSHADE_FLAT); // TODO
__super::Draw(primclass, rt, ds, tex);
}
void GSRendererDX9::SetupDATE(GSTexture* rt, GSTexture* ds)
{
if(!m_context->TEST.DATE) return; // || (::GetAsyncKeyState(VK_CONTROL) & 0x8000)
GSDevice9* dev = (GSDevice9*)m_dev;
int w = rt->GetWidth();
int h = rt->GetHeight();
if(GSTexture* t = dev->CreateRenderTarget(w, h))
{
// sfex3 (after the capcom logo), vf4 (first menu fading in), ffxii shadows, rumble roses shadows, persona4 shadows
dev->BeginScene();
dev->ClearStencil(ds, 0);
// om
dev->OMSetDepthStencilState(&m_date.dss);
dev->OMSetBlendState(&m_date.bs, 0);
dev->OMSetRenderTargets(t, ds);
// ia
GSVector4 s = GSVector4(rt->m_scale.x / w, rt->m_scale.y / h);
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());
GSVector4 dst = src * 2.0f + o.xxxx();
GSVertexPT1 vertices[] =
{
{GSVector4(dst.x, -dst.y, 0.5f, 1.0f), GSVector2(src.x, src.y)},
{GSVector4(dst.z, -dst.y, 0.5f, 1.0f), GSVector2(src.z, src.y)},
{GSVector4(dst.x, -dst.w, 0.5f, 1.0f), GSVector2(src.x, src.w)},
{GSVector4(dst.z, -dst.w, 0.5f, 1.0f), GSVector2(src.z, src.w)},
};
dev->IASetVertexBuffer(vertices, sizeof(vertices[0]), countof(vertices));
dev->IASetInputLayout(dev->m_convert.il);
dev->IASetPrimitiveTopology(D3DPT_TRIANGLESTRIP);
// vs
dev->VSSetShader(dev->m_convert.vs, NULL, 0);
// ps
dev->PSSetShaderResources(rt, NULL);
dev->PSSetShader(dev->m_convert.ps[m_context->TEST.DATM ? 2 : 3], NULL, 0);
dev->PSSetSamplerState(&dev->m_convert.pt);
// rs
dev->RSSet(w, h);
//
dev->DrawPrimitive();
//
dev->EndScene();
dev->Recycle(t);
}
}
void GSRendererDX9::UpdateFBA(GSTexture* rt)
{
GSDevice9* dev = (GSDevice9*)m_dev;
dev->BeginScene();
// om
dev->OMSetDepthStencilState(&m_fba.dss);
dev->OMSetBlendState(&m_fba.bs, 0);
// ia
GSVector4 s = GSVector4(rt->m_scale.x / rt->GetWidth(), rt->m_scale.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());
GSVector4 dst = src * 2.0f + o.xxxx();
GSVertexPT1 vertices[] =
{
{GSVector4(dst.x, -dst.y, 0.5f, 1.0f), GSVector2(0, 0)},
{GSVector4(dst.z, -dst.y, 0.5f, 1.0f), GSVector2(0, 0)},
{GSVector4(dst.x, -dst.w, 0.5f, 1.0f), GSVector2(0, 0)},
{GSVector4(dst.z, -dst.w, 0.5f, 1.0f), GSVector2(0, 0)},
};
dev->IASetVertexBuffer(vertices, sizeof(vertices[0]), countof(vertices));
dev->IASetInputLayout(dev->m_convert.il);
dev->IASetPrimitiveTopology(D3DPT_TRIANGLESTRIP);
// vs
dev->VSSetShader(dev->m_convert.vs, NULL, 0);
// ps
dev->PSSetShader(dev->m_convert.ps[4], NULL, 0);
// rs
dev->RSSet(rt->GetWidth(), rt->GetHeight());
//
dev->DrawPrimitive();
//
dev->EndScene();
}

View File

@ -21,19 +21,14 @@
#pragma once
#include "GSRendererHW.h"
#include "GSRendererDX.h"
#include "GSVertexHW.h"
#include "GSTextureCache9.h"
#include "GSTextureFX9.h"
class GSRendererHW9 : public GSRendererHW<GSVertexHW9>
class GSRendererDX9 : public GSRendererDX<GSVertexHW9>
{
protected:
GSTextureFX9 m_tfx;
bool m_logz;
void Draw(GS_PRIM_CLASS primclass, GSTexture* rt, GSTexture* ds, GSTextureCache::GSCachedTexture* tex);
struct
{
Direct3DDepthStencilState9 dss;
@ -42,16 +37,16 @@ protected:
struct
{
bool enabled;
Direct3DDepthStencilState9 dss;
Direct3DBlendState9 bs;
} m_fba;
void Draw(GS_PRIM_CLASS primclass, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex);
void SetupDATE(GSTexture* rt, GSTexture* ds);
void UpdateFBA(GSTexture* rt);
public:
GSRendererHW9(uint8* base, bool mt, void (*irq)());
GSRendererDX9(uint8* base, bool mt, void (*irq)());
bool Create(const string& title);

View File

@ -81,7 +81,7 @@ protected:
GSTexture* t = NULL;
if(GSTextureCache::GSRenderTarget* rt = m_tc->GetRenderTarget(TEX0, m_width, m_height, true))
if(GSTextureCache::Target* rt = m_tc->LookupTarget(TEX0, m_width, m_height, GSTextureCache::RenderTarget, true, true))
{
t = rt->m_texture;
@ -128,15 +128,15 @@ protected:
TEX0.TBW = context->FRAME.FBW;
TEX0.PSM = context->FRAME.PSM;
GSTextureCache::GSRenderTarget* rt = m_tc->GetRenderTarget(TEX0, m_width, m_height);
GSTextureCache::Target* rt = m_tc->LookupTarget(TEX0, m_width, m_height, GSTextureCache::RenderTarget, true);
TEX0.TBP0 = context->ZBUF.Block();
TEX0.TBW = context->FRAME.FBW;
TEX0.PSM = context->ZBUF.PSM;
GSTextureCache::GSDepthStencil* ds = m_tc->GetDepthStencil(TEX0, m_width, m_height);
GSTextureCache::Target* ds = m_tc->LookupTarget(TEX0, m_width, m_height, GSTextureCache::DepthStencil, m_context->DepthWrite());
GSTextureCache::GSCachedTexture* tex = NULL;
GSTextureCache::Source* tex = NULL;
if(PRIM->TME)
{
@ -144,9 +144,9 @@ protected:
GSVector4i r;
GetTextureMinMax(r);
GetTextureMinMax(r, IsLinear());
tex = m_tc->GetTexture(r);
tex = m_tc->LookupSource(context->TEX0, env.TEXA, r);
if(!tex) return;
}
@ -157,7 +157,7 @@ protected:
string s;
if(s_save && PRIM->TME)
if(s_save && tex)
{
s = format("c:\\temp2\\_%05d_f%I64d_tex_%05x_%d_%d%d_%02x_%02x_%02x_%02x.dds",
s_n, frame, (int)context->TEX0.TBP0, (int)context->TEX0.PSM,
@ -233,6 +233,30 @@ protected:
//
GSVector4i r = GSVector4i(m_vt.m_min.p.xyxy(m_vt.m_max.p)).rintersect(GSVector4i(m_context->scissor.in));
GIFRegBITBLTBUF BITBLTBUF;
BITBLTBUF.DBW = context->FRAME.FBW;
if(fm != 0xffffffff)
{
BITBLTBUF.DBP = context->FRAME.Block();
BITBLTBUF.DPSM = context->FRAME.PSM;
m_tc->InvalidateVideoMem(BITBLTBUF, r, false);
}
if(zm != 0xffffffff)
{
BITBLTBUF.DBP = context->ZBUF.Block();
BITBLTBUF.DPSM = context->ZBUF.PSM;
m_tc->InvalidateVideoMem(BITBLTBUF, r, false);
}
//
OverrideOutput();
if(s_dump)
@ -257,13 +281,11 @@ protected:
s_n++;
}
m_tc->InvalidateTextures(context->FRAME, context->ZBUF);
}
virtual void Draw(GS_PRIM_CLASS primclass, GSTexture* rt, GSTexture* ds, GSTextureCache::GSCachedTexture* tex) = 0;
virtual void Draw(GS_PRIM_CLASS primclass, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex) = 0;
virtual bool OverrideInput(int& prim, GSTexture* rt, GSTexture* ds, GSTextureCache::GSCachedTexture* t)
virtual bool OverrideInput(int& prim, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t)
{
#pragma region ffxii pal video conversion
@ -424,7 +446,7 @@ protected:
TEX0.TBW = FBW;
TEX0.PSM = FPSM;
if(GSTextureCache::GSDepthStencil* ds = m_tc->GetDepthStencil(TEX0, m_width, m_height))
if(GSTextureCache::Target* ds = m_tc->LookupTarget(TEX0, m_width, m_height, GSTextureCache::DepthStencil, true))
{
m_dev->ClearDepth(ds->m_texture, 0);
}

View File

@ -1,529 +0,0 @@
/*
* Copyright (C) 2007-2009 Gabest
* http://www.gabest.org
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
#include "stdafx.h"
#include "GSRendererHW10.h"
#include "GSCrc.h"
#include "resource.h"
GSRendererHW10::GSRendererHW10(uint8* base, bool mt, void (*irq)())
: GSRendererHW<GSVertexHW10>(base, mt, irq, new GSDevice10(), new GSTextureCache10(this))
{
InitVertexKick<GSRendererHW10>();
}
bool GSRendererHW10::Create(const string& title)
{
if(!__super::Create(title))
return false;
if(!m_tfx.Create((GSDevice10*)m_dev))
return false;
//
D3D10_DEPTH_STENCIL_DESC dsd;
memset(&dsd, 0, sizeof(dsd));
dsd.DepthEnable = false;
dsd.StencilEnable = true;
dsd.StencilReadMask = 1;
dsd.StencilWriteMask = 1;
dsd.FrontFace.StencilFunc = D3D10_COMPARISON_ALWAYS;
dsd.FrontFace.StencilPassOp = D3D10_STENCIL_OP_REPLACE;
dsd.FrontFace.StencilFailOp = D3D10_STENCIL_OP_KEEP;
dsd.FrontFace.StencilDepthFailOp = D3D10_STENCIL_OP_KEEP;
dsd.BackFace.StencilFunc = D3D10_COMPARISON_ALWAYS;
dsd.BackFace.StencilPassOp = D3D10_STENCIL_OP_REPLACE;
dsd.BackFace.StencilFailOp = D3D10_STENCIL_OP_KEEP;
dsd.BackFace.StencilDepthFailOp = D3D10_STENCIL_OP_KEEP;
(*(GSDevice10*)m_dev)->CreateDepthStencilState(&dsd, &m_date.dss);
D3D10_BLEND_DESC bd;
memset(&bd, 0, sizeof(bd));
(*(GSDevice10*)m_dev)->CreateBlendState(&bd, &m_date.bs);
//
return true;
}
template<uint32 prim, uint32 tme, uint32 fst>
void GSRendererHW10::VertexKick(bool skip)
{
GSVertexHW10& dst = m_vl.AddTail();
dst.vi[0] = m_v.vi[0];
dst.vi[1] = m_v.vi[1];
if(tme && fst)
{
GSVector4::storel(&dst.ST, m_v.GetUV());
}
int count = 0;
if(GSVertexHW10* v = DrawingKick<prim>(skip, count))
{
GSVector4i scissor = m_context->scissor.dx10;
#if _M_SSE >= 0x401
GSVector4i pmin, pmax, v0, v1, v2;
switch(prim)
{
case GS_POINTLIST:
v0 = GSVector4i::load((int)v[0].p.xy).upl16();
pmin = v0;
pmax = v0;
break;
case GS_LINELIST:
case GS_LINESTRIP:
case GS_SPRITE:
v0 = GSVector4i::load((int)v[0].p.xy);
v1 = GSVector4i::load((int)v[1].p.xy);
pmin = v0.min_u16(v1).upl16();
pmax = v0.max_u16(v1).upl16();
break;
case GS_TRIANGLELIST:
case GS_TRIANGLESTRIP:
case GS_TRIANGLEFAN:
v0 = GSVector4i::load((int)v[0].p.xy);
v1 = GSVector4i::load((int)v[1].p.xy);
v2 = GSVector4i::load((int)v[2].p.xy);
pmin = v0.min_u16(v1).min_u16(v2).upl16();
pmax = v0.max_u16(v1).max_u16(v2).upl16();
break;
}
GSVector4i test = (pmax < scissor) | (pmin > scissor.zwxy());
if(test.mask() & 0xff)
{
return;
}
#else
switch(prim)
{
case GS_POINTLIST:
if(v[0].p.x < scissor.x
|| v[0].p.x > scissor.z
|| v[0].p.y < scissor.y
|| v[0].p.y > scissor.w)
{
return;
}
break;
case GS_LINELIST:
case GS_LINESTRIP:
case GS_SPRITE:
if(v[0].p.x < scissor.x && v[1].p.x < scissor.x
|| v[0].p.x > scissor.z && v[1].p.x > scissor.z
|| v[0].p.y < scissor.y && v[1].p.y < scissor.y
|| v[0].p.y > scissor.w && v[1].p.y > scissor.w)
{
return;
}
break;
case GS_TRIANGLELIST:
case GS_TRIANGLESTRIP:
case GS_TRIANGLEFAN:
if(v[0].p.x < scissor.x && v[1].p.x < scissor.x && v[2].p.x < scissor.x
|| v[0].p.x > scissor.z && v[1].p.x > scissor.z && v[2].p.x > scissor.z
|| v[0].p.y < scissor.y && v[1].p.y < scissor.y && v[2].p.y < scissor.y
|| v[0].p.y > scissor.w && v[1].p.y > scissor.w && v[2].p.y > scissor.w)
{
return;
}
break;
}
#endif
m_count += count;
}
}
void GSRendererHW10::Draw(GS_PRIM_CLASS primclass, GSTexture* rt, GSTexture* ds, GSTextureCache::GSCachedTexture* tex)
{
GSDrawingEnvironment& env = m_env;
GSDrawingContext* context = m_context;
D3D10_PRIMITIVE_TOPOLOGY topology;
int prims = 0;
switch(primclass)
{
case GS_POINT_CLASS:
topology = D3D10_PRIMITIVE_TOPOLOGY_POINTLIST;
prims = m_count;
break;
case GS_LINE_CLASS:
case GS_SPRITE_CLASS:
topology = D3D10_PRIMITIVE_TOPOLOGY_LINELIST;
prims = m_count / 2;
break;
case GS_TRIANGLE_CLASS:
topology = D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
prims = m_count / 3;
break;
default:
__assume(0);
}
m_perfmon.Put(GSPerfMon::Prim, prims);
m_perfmon.Put(GSPerfMon::Draw, 1);
// date
SetupDATE(rt, ds);
//
m_dev->BeginScene();
// om
GSTextureFX::OMDepthStencilSelector om_dssel;
om_dssel.zte = context->TEST.ZTE;
om_dssel.ztst = context->TEST.ZTST;
om_dssel.zwe = !context->ZBUF.ZMSK;
om_dssel.date = context->FRAME.PSM != PSM_PSMCT24 ? context->TEST.DATE : 0;
GSTextureFX::OMBlendSelector om_bsel;
om_bsel.abe = !IsOpaque();
om_bsel.a = context->ALPHA.A;
om_bsel.b = context->ALPHA.B;
om_bsel.c = context->ALPHA.C;
om_bsel.d = context->ALPHA.D;
om_bsel.wr = (context->FRAME.FBMSK & 0x000000ff) != 0x000000ff;
om_bsel.wg = (context->FRAME.FBMSK & 0x0000ff00) != 0x0000ff00;
om_bsel.wb = (context->FRAME.FBMSK & 0x00ff0000) != 0x00ff0000;
om_bsel.wa = (context->FRAME.FBMSK & 0xff000000) != 0xff000000;
float bf = (float)(int)context->ALPHA.FIX / 0x80;
// vs
GSTextureFX::VSSelector vs_sel;
vs_sel.bppz = 0;
vs_sel.tme = PRIM->TME;
vs_sel.fst = PRIM->FST;
vs_sel.prim = primclass;
if(om_dssel.zte && om_dssel.ztst > 0 && om_dssel.zwe)
{
if(context->ZBUF.PSM == PSM_PSMZ24)
{
if(m_vt.m_max.p.z > 0xffffff)
{
ASSERT(m_vt.m_min.p.z > 0xffffff);
vs_sel.bppz = 1;
om_dssel.ztst = 1;
}
}
else if(context->ZBUF.PSM == PSM_PSMZ16 || context->ZBUF.PSM == PSM_PSMZ16S)
{
if(m_vt.m_max.p.z > 0xffff)
{
ASSERT(m_vt.m_min.p.z > 0xffff);
vs_sel.bppz = 2;
om_dssel.ztst = 1;
}
}
}
GSTextureFX::VSConstantBuffer vs_cb;
float sx = 2.0f * rt->m_scale.x / (rt->GetWidth() * 16);
float sy = 2.0f * rt->m_scale.y / (rt->GetHeight() * 16);
float ox = (float)(int)context->XYOFFSET.OFX;
float oy = (float)(int)context->XYOFFSET.OFY;
float ox2 = 1.0f / rt->GetWidth();
float oy2 = 1.0f / 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);
vs_cb.TextureScale = GSVector2(1.0f, 1.0f);
if(PRIM->TME && PRIM->FST)
{
vs_cb.TextureScale.x = 1.0f / (16 << context->TEX0.TW);
vs_cb.TextureScale.y = 1.0f / (16 << context->TEX0.TH);
}
// gs
GSTextureFX::GSSelector gs_sel;
gs_sel.iip = PRIM->IIP;
gs_sel.prim = primclass;
// ps
GSTextureFX::PSSelector ps_sel;
ps_sel.fst = PRIM->FST;
ps_sel.wms = context->CLAMP.WMS;
ps_sel.wmt = context->CLAMP.WMT;
ps_sel.bpp = 0;
ps_sel.aem = env.TEXA.AEM;
ps_sel.tfx = context->TEX0.TFX;
ps_sel.tcc = context->TEX0.TCC;
ps_sel.ate = context->TEST.ATE;
ps_sel.atst = context->TEST.ATST;
ps_sel.fog = PRIM->FGE;
ps_sel.clr1 = om_bsel.abe && om_bsel.a == 1 && om_bsel.b == 2 && om_bsel.d == 1;
ps_sel.fba = context->FBA.FBA;
ps_sel.aout = context->FRAME.PSM == PSM_PSMCT16 || context->FRAME.PSM == PSM_PSMCT16S || (context->FRAME.FBMSK & 0xff000000) == 0x7f000000 ? 1 : 0;
ps_sel.ltf = m_filter == 2 ? context->TEX1.IsLinear() : m_filter;
GSTextureFX::PSSamplerSelector ps_ssel;
ps_ssel.tau = 0;
ps_ssel.tav = 0;
ps_ssel.ltf = ps_sel.ltf;
GSTextureFX::PSConstantBuffer ps_cb;
ps_cb.FogColor_AREF = GSVector4((int)env.FOGCOL.FCR, (int)env.FOGCOL.FCG, (int)env.FOGCOL.FCB, (int)context->TEST.AREF) / 255;
if(ps_sel.atst == 2 || ps_sel.atst == 5)
{
ps_cb.FogColor_AREF.a -= 0.9f / 255;
}
else if(ps_sel.atst == 3 || ps_sel.atst == 6)
{
ps_cb.FogColor_AREF.a += 0.9f / 255;
}
if(tex)
{
ps_sel.bpp = tex->m_bpp;
int w = tex->m_texture->GetWidth();
int h = tex->m_texture->GetHeight();
ps_cb.WH_TA = GSVector4((int)(1 << context->TEX0.TW), (int)(1 << context->TEX0.TH), env.TEXA.TA0, env.TEXA.TA1) / GSVector4(1, 255).xxyy();
ps_cb.HalfTexel = GSVector4(-0.5f, 0.5f).xxyy() / GSVector4(w, h).xyxy();
switch(context->CLAMP.WMS)
{
case 0:
ps_ssel.tau = 1;
break;
case 1:
ps_ssel.tau = 0;
break;
case 2:
ps_cb.MinMax.x = ((float)(int)context->CLAMP.MINU) / (1 << context->TEX0.TW);
ps_cb.MinMax.z = ((float)(int)context->CLAMP.MAXU) / (1 << context->TEX0.TW);
ps_cb.MinMaxF.x = ((float)(int)context->CLAMP.MINU + 0.5f) / (1 << context->TEX0.TW);
ps_cb.MinMaxF.z = ((float)(int)context->CLAMP.MAXU) / (1 << context->TEX0.TW);
ps_ssel.tau = 0;
break;
case 3:
ps_cb.MskFix.x = context->CLAMP.MINU;
ps_cb.MskFix.z = context->CLAMP.MAXU;
ps_ssel.tau = 1;
break;
default:
__assume(0);
}
switch(context->CLAMP.WMT)
{
case 0:
ps_ssel.tav = 1;
break;
case 1:
ps_ssel.tav = 0;
break;
case 2:
ps_cb.MinMax.y = ((float)(int)context->CLAMP.MINV) / (1 << context->TEX0.TH);
ps_cb.MinMax.w = ((float)(int)context->CLAMP.MAXV) / (1 << context->TEX0.TH);
ps_cb.MinMaxF.y = ((float)(int)context->CLAMP.MINV + 0.5f) / (1 << context->TEX0.TH);
ps_cb.MinMaxF.w = ((float)(int)context->CLAMP.MAXV) / (1 << context->TEX0.TH);
ps_ssel.tav = 0;
break;
case 3:
ps_cb.MskFix.y = context->CLAMP.MINV;
ps_cb.MskFix.w = context->CLAMP.MAXV;
ps_ssel.tav = 1;
break;
default:
__assume(0);
}
}
else
{
ps_sel.tfx = 4;
}
// rs
int w = rt->GetWidth();
int h = rt->GetHeight();
GSVector4i scissor = GSVector4i(GSVector4(rt->m_scale).xyxy() * context->scissor.in).rintersect(GSVector4i(0, 0, w, h));
//
m_tfx.SetupOM(om_dssel, om_bsel, bf, rt, ds);
m_tfx.SetupIA(m_vertices, m_count, topology);
m_tfx.SetupVS(vs_sel, &vs_cb);
m_tfx.SetupGS(gs_sel);
m_tfx.SetupPS(ps_sel, &ps_cb, ps_ssel, tex ? tex->m_texture : NULL, tex ? tex->m_palette : NULL);
m_tfx.SetupRS(w, h, scissor);
// draw
if(context->TEST.DoFirstPass())
{
m_dev->DrawPrimitive();
}
if(context->TEST.DoSecondPass())
{
ASSERT(!env.PABE.PABE);
static const uint32 iatst[] = {1, 0, 5, 6, 7, 2, 3, 4};
ps_sel.atst = iatst[ps_sel.atst];
m_tfx.UpdatePS(ps_sel, &ps_cb, ps_ssel);
bool z = om_dssel.zwe;
bool r = om_bsel.wr;
bool g = om_bsel.wg;
bool b = om_bsel.wb;
bool a = om_bsel.wa;
switch(context->TEST.AFAIL)
{
case 0: z = r = g = b = a = false; break; // none
case 1: z = false; break; // rgba
case 2: r = g = b = a = false; break; // z
case 3: z = a = false; break; // rgb
default: __assume(0);
}
if(z || r || g || b || a)
{
om_dssel.zwe = z;
om_bsel.wr = r;
om_bsel.wg = g;
om_bsel.wb = b;
om_bsel.wa = a;
m_tfx.UpdateOM(om_dssel, om_bsel, bf);
m_dev->DrawPrimitive();
}
}
m_dev->EndScene();
}
void GSRendererHW10::SetupDATE(GSTexture* rt, GSTexture* ds)
{
if(!m_context->TEST.DATE) return; // || (::GetAsyncKeyState(VK_CONTROL) & 0x8000)
GSDevice10* dev = (GSDevice10*)m_dev;
int w = rt->GetWidth();
int h = rt->GetHeight();
if(GSTexture* t = dev->CreateRenderTarget(w, h))
{
// sfex3 (after the capcom logo), vf4 (first menu fading in), ffxii shadows, rumble roses shadows, persona4 shadows
dev->BeginScene();
dev->ClearStencil(ds, 0);
// om
dev->OMSetDepthStencilState(m_date.dss, 1);
dev->OMSetBlendState(m_date.bs, 0);
dev->OMSetRenderTargets(t, ds);
// ia
GSVector4 s = GSVector4(rt->m_scale.x / w, rt->m_scale.y / h);
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());
GSVector4 dst = src * 2.0f + o.xxxx();
GSVertexPT1 vertices[] =
{
{GSVector4(dst.x, -dst.y, 0.5f, 1.0f), GSVector2(src.x, src.y)},
{GSVector4(dst.z, -dst.y, 0.5f, 1.0f), GSVector2(src.z, src.y)},
{GSVector4(dst.x, -dst.w, 0.5f, 1.0f), GSVector2(src.x, src.w)},
{GSVector4(dst.z, -dst.w, 0.5f, 1.0f), GSVector2(src.z, src.w)},
};
dev->IASetVertexBuffer(vertices, sizeof(vertices[0]), countof(vertices));
dev->IASetInputLayout(dev->m_convert.il);
dev->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
// vs
dev->VSSetShader(dev->m_convert.vs, NULL);
// gs
dev->GSSetShader(NULL);
// ps
dev->PSSetShaderResources(rt, NULL);
dev->PSSetShader(dev->m_convert.ps[m_context->TEST.DATM ? 2 : 3], NULL);
dev->PSSetSamplerState(dev->m_convert.pt, NULL);
// rs
dev->RSSet(w, h);
// set
dev->DrawPrimitive();
//
dev->EndScene();
dev->Recycle(t);
}
}

View File

@ -1,529 +0,0 @@
/*
* Copyright (C) 2007-2009 Gabest
* http://www.gabest.org
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
#include "stdafx.h"
#include "GSRendererHW11.h"
#include "GSCrc.h"
#include "resource.h"
GSRendererHW11::GSRendererHW11(uint8* base, bool mt, void (*irq)())
: GSRendererHW<GSVertexHW11>(base, mt, irq, new GSDevice11(), new GSTextureCache11(this))
{
InitVertexKick<GSRendererHW11>();
}
bool GSRendererHW11::Create(const string& title)
{
if(!__super::Create(title))
return false;
if(!m_tfx.Create((GSDevice11*)m_dev))
return false;
//
D3D11_DEPTH_STENCIL_DESC dsd;
memset(&dsd, 0, sizeof(dsd));
dsd.DepthEnable = false;
dsd.StencilEnable = true;
dsd.StencilReadMask = 1;
dsd.StencilWriteMask = 1;
dsd.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
dsd.FrontFace.StencilPassOp = D3D11_STENCIL_OP_REPLACE;
dsd.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
dsd.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
dsd.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
dsd.BackFace.StencilPassOp = D3D11_STENCIL_OP_REPLACE;
dsd.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
dsd.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
(*(GSDevice11*)m_dev)->CreateDepthStencilState(&dsd, &m_date.dss);
D3D11_BLEND_DESC bd;
memset(&bd, 0, sizeof(bd));
(*(GSDevice11*)m_dev)->CreateBlendState(&bd, &m_date.bs);
//
return true;
}
template<uint32 prim, uint32 tme, uint32 fst>
void GSRendererHW11::VertexKick(bool skip)
{
GSVertexHW11& dst = m_vl.AddTail();
dst.vi[0] = m_v.vi[0];
dst.vi[1] = m_v.vi[1];
if(tme && fst)
{
GSVector4::storel(&dst.ST, m_v.GetUV());
}
int count = 0;
if(GSVertexHW11* v = DrawingKick<prim>(skip, count))
{
GSVector4i scissor = m_context->scissor.dx10;
#if _M_SSE >= 0x401
GSVector4i pmin, pmax, v0, v1, v2;
switch(prim)
{
case GS_POINTLIST:
v0 = GSVector4i::load((int)v[0].p.xy).upl16();
pmin = v0;
pmax = v0;
break;
case GS_LINELIST:
case GS_LINESTRIP:
case GS_SPRITE:
v0 = GSVector4i::load((int)v[0].p.xy);
v1 = GSVector4i::load((int)v[1].p.xy);
pmin = v0.min_u16(v1).upl16();
pmax = v0.max_u16(v1).upl16();
break;
case GS_TRIANGLELIST:
case GS_TRIANGLESTRIP:
case GS_TRIANGLEFAN:
v0 = GSVector4i::load((int)v[0].p.xy);
v1 = GSVector4i::load((int)v[1].p.xy);
v2 = GSVector4i::load((int)v[2].p.xy);
pmin = v0.min_u16(v1).min_u16(v2).upl16();
pmax = v0.max_u16(v1).max_u16(v2).upl16();
break;
}
GSVector4i test = (pmax < scissor) | (pmin > scissor.zwxy());
if(test.mask() & 0xff)
{
return;
}
#else
switch(prim)
{
case GS_POINTLIST:
if(v[0].p.x < scissor.x
|| v[0].p.x > scissor.z
|| v[0].p.y < scissor.y
|| v[0].p.y > scissor.w)
{
return;
}
break;
case GS_LINELIST:
case GS_LINESTRIP:
case GS_SPRITE:
if(v[0].p.x < scissor.x && v[1].p.x < scissor.x
|| v[0].p.x > scissor.z && v[1].p.x > scissor.z
|| v[0].p.y < scissor.y && v[1].p.y < scissor.y
|| v[0].p.y > scissor.w && v[1].p.y > scissor.w)
{
return;
}
break;
case GS_TRIANGLELIST:
case GS_TRIANGLESTRIP:
case GS_TRIANGLEFAN:
if(v[0].p.x < scissor.x && v[1].p.x < scissor.x && v[2].p.x < scissor.x
|| v[0].p.x > scissor.z && v[1].p.x > scissor.z && v[2].p.x > scissor.z
|| v[0].p.y < scissor.y && v[1].p.y < scissor.y && v[2].p.y < scissor.y
|| v[0].p.y > scissor.w && v[1].p.y > scissor.w && v[2].p.y > scissor.w)
{
return;
}
break;
}
#endif
m_count += count;
}
}
void GSRendererHW11::Draw(GS_PRIM_CLASS primclass, GSTexture* rt, GSTexture* ds, GSTextureCache::GSCachedTexture* tex)
{
GSDrawingEnvironment& env = m_env;
GSDrawingContext* context = m_context;
D3D11_PRIMITIVE_TOPOLOGY topology;
int prims = 0;
switch(primclass)
{
case GS_POINT_CLASS:
topology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
prims = m_count;
break;
case GS_LINE_CLASS:
case GS_SPRITE_CLASS:
topology = D3D11_PRIMITIVE_TOPOLOGY_LINELIST;
prims = m_count / 2;
break;
case GS_TRIANGLE_CLASS:
topology = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
prims = m_count / 3;
break;
default:
__assume(0);
}
m_perfmon.Put(GSPerfMon::Prim, prims);
m_perfmon.Put(GSPerfMon::Draw, 1);
// date
SetupDATE(rt, ds);
//
m_dev->BeginScene();
// om
GSTextureFX::OMDepthStencilSelector om_dssel;
om_dssel.zte = context->TEST.ZTE;
om_dssel.ztst = context->TEST.ZTST;
om_dssel.zwe = !context->ZBUF.ZMSK;
om_dssel.date = context->FRAME.PSM != PSM_PSMCT24 ? context->TEST.DATE : 0;
GSTextureFX::OMBlendSelector om_bsel;
om_bsel.abe = !IsOpaque();
om_bsel.a = context->ALPHA.A;
om_bsel.b = context->ALPHA.B;
om_bsel.c = context->ALPHA.C;
om_bsel.d = context->ALPHA.D;
om_bsel.wr = (context->FRAME.FBMSK & 0x000000ff) != 0x000000ff;
om_bsel.wg = (context->FRAME.FBMSK & 0x0000ff00) != 0x0000ff00;
om_bsel.wb = (context->FRAME.FBMSK & 0x00ff0000) != 0x00ff0000;
om_bsel.wa = (context->FRAME.FBMSK & 0xff000000) != 0xff000000;
float bf = (float)(int)context->ALPHA.FIX / 0x80;
// vs
GSTextureFX::VSSelector vs_sel;
vs_sel.bppz = 0;
vs_sel.tme = PRIM->TME;
vs_sel.fst = PRIM->FST;
vs_sel.prim = primclass;
if(om_dssel.zte && om_dssel.ztst > 0 && om_dssel.zwe)
{
if(context->ZBUF.PSM == PSM_PSMZ24)
{
if(m_vt.m_max.p.z > 0xffffff)
{
ASSERT(m_vt.m_min.p.z > 0xffffff);
vs_sel.bppz = 1;
om_dssel.ztst = 1;
}
}
else if(context->ZBUF.PSM == PSM_PSMZ16 || context->ZBUF.PSM == PSM_PSMZ16S)
{
if(m_vt.m_max.p.z > 0xffff)
{
ASSERT(m_vt.m_min.p.z > 0xffff);
vs_sel.bppz = 2;
om_dssel.ztst = 1;
}
}
}
GSTextureFX::VSConstantBuffer vs_cb;
float sx = 2.0f * rt->m_scale.x / (rt->GetWidth() * 16);
float sy = 2.0f * rt->m_scale.y / (rt->GetHeight() * 16);
float ox = (float)(int)context->XYOFFSET.OFX;
float oy = (float)(int)context->XYOFFSET.OFY;
float ox2 = 1.0f / rt->GetWidth();
float oy2 = 1.0f / 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);
vs_cb.TextureScale = GSVector2(1.0f, 1.0f);
if(PRIM->TME && PRIM->FST)
{
vs_cb.TextureScale.x = 1.0f / (16 << context->TEX0.TW);
vs_cb.TextureScale.y = 1.0f / (16 << context->TEX0.TH);
}
// gs
GSTextureFX::GSSelector gs_sel;
gs_sel.iip = PRIM->IIP;
gs_sel.prim = primclass;
// ps
GSTextureFX::PSSelector ps_sel;
ps_sel.fst = PRIM->FST;
ps_sel.wms = context->CLAMP.WMS;
ps_sel.wmt = context->CLAMP.WMT;
ps_sel.bpp = 0;
ps_sel.aem = env.TEXA.AEM;
ps_sel.tfx = context->TEX0.TFX;
ps_sel.tcc = context->TEX0.TCC;
ps_sel.ate = context->TEST.ATE;
ps_sel.atst = context->TEST.ATST;
ps_sel.fog = PRIM->FGE;
ps_sel.clr1 = om_bsel.abe && om_bsel.a == 1 && om_bsel.b == 2 && om_bsel.d == 1;
ps_sel.fba = context->FBA.FBA;
ps_sel.aout = context->FRAME.PSM == PSM_PSMCT16 || context->FRAME.PSM == PSM_PSMCT16S || (context->FRAME.FBMSK & 0xff000000) == 0x7f000000 ? 1 : 0;
ps_sel.ltf = m_filter == 2 ? context->TEX1.IsLinear() : m_filter;
GSTextureFX::PSSamplerSelector ps_ssel;
ps_ssel.tau = 0;
ps_ssel.tav = 0;
ps_ssel.ltf = ps_sel.ltf;
GSTextureFX::PSConstantBuffer ps_cb;
ps_cb.FogColor_AREF = GSVector4((int)env.FOGCOL.FCR, (int)env.FOGCOL.FCG, (int)env.FOGCOL.FCB, (int)context->TEST.AREF) / 255;
if(ps_sel.atst == 2 || ps_sel.atst == 5)
{
ps_cb.FogColor_AREF.a -= 0.9f / 255;
}
else if(ps_sel.atst == 3 || ps_sel.atst == 6)
{
ps_cb.FogColor_AREF.a += 0.9f / 255;
}
if(tex)
{
ps_sel.bpp = tex->m_bpp;
int w = tex->m_texture->GetWidth();
int h = tex->m_texture->GetHeight();
ps_cb.WH_TA = GSVector4((int)(1 << context->TEX0.TW), (int)(1 << context->TEX0.TH), env.TEXA.TA0, env.TEXA.TA1) / GSVector4(1, 255).xxyy();
ps_cb.HalfTexel = GSVector4(-0.5f, 0.5f).xxyy() / GSVector4(w, h).xyxy();
switch(context->CLAMP.WMS)
{
case 0:
ps_ssel.tau = 1;
break;
case 1:
ps_ssel.tau = 0;
break;
case 2:
ps_cb.MinMax.x = ((float)(int)context->CLAMP.MINU) / (1 << context->TEX0.TW);
ps_cb.MinMax.z = ((float)(int)context->CLAMP.MAXU) / (1 << context->TEX0.TW);
ps_cb.MinMaxF.x = ((float)(int)context->CLAMP.MINU + 0.5f) / (1 << context->TEX0.TW);
ps_cb.MinMaxF.z = ((float)(int)context->CLAMP.MAXU) / (1 << context->TEX0.TW);
ps_ssel.tau = 0;
break;
case 3:
ps_cb.MskFix.x = context->CLAMP.MINU;
ps_cb.MskFix.z = context->CLAMP.MAXU;
ps_ssel.tau = 1;
break;
default:
__assume(0);
}
switch(context->CLAMP.WMT)
{
case 0:
ps_ssel.tav = 1;
break;
case 1:
ps_ssel.tav = 0;
break;
case 2:
ps_cb.MinMax.y = ((float)(int)context->CLAMP.MINV) / (1 << context->TEX0.TH);
ps_cb.MinMax.w = ((float)(int)context->CLAMP.MAXV) / (1 << context->TEX0.TH);
ps_cb.MinMaxF.y = ((float)(int)context->CLAMP.MINV + 0.5f) / (1 << context->TEX0.TH);
ps_cb.MinMaxF.w = ((float)(int)context->CLAMP.MAXV) / (1 << context->TEX0.TH);
ps_ssel.tav = 0;
break;
case 3:
ps_cb.MskFix.y = context->CLAMP.MINV;
ps_cb.MskFix.w = context->CLAMP.MAXV;
ps_ssel.tav = 1;
break;
default:
__assume(0);
}
}
else
{
ps_sel.tfx = 4;
}
// rs
int w = rt->GetWidth();
int h = rt->GetHeight();
GSVector4i scissor = GSVector4i(GSVector4(rt->m_scale).xyxy() * context->scissor.in).rintersect(GSVector4i(0, 0, w, h));
//
m_tfx.SetupOM(om_dssel, om_bsel, bf, rt, ds);
m_tfx.SetupIA(m_vertices, m_count, topology);
m_tfx.SetupVS(vs_sel, &vs_cb);
m_tfx.SetupGS(gs_sel);
m_tfx.SetupPS(ps_sel, &ps_cb, ps_ssel, tex ? tex->m_texture : NULL, tex ? tex->m_palette : NULL);
m_tfx.SetupRS(w, h, scissor);
// draw
if(context->TEST.DoFirstPass())
{
m_dev->DrawPrimitive();
}
if(context->TEST.DoSecondPass())
{
ASSERT(!env.PABE.PABE);
static const uint32 iatst[] = {1, 0, 5, 6, 7, 2, 3, 4};
ps_sel.atst = iatst[ps_sel.atst];
m_tfx.UpdatePS(ps_sel, &ps_cb, ps_ssel);
bool z = om_dssel.zwe;
bool r = om_bsel.wr;
bool g = om_bsel.wg;
bool b = om_bsel.wb;
bool a = om_bsel.wa;
switch(context->TEST.AFAIL)
{
case 0: z = r = g = b = a = false; break; // none
case 1: z = false; break; // rgba
case 2: r = g = b = a = false; break; // z
case 3: z = a = false; break; // rgb
default: __assume(0);
}
if(z || r || g || b || a)
{
om_dssel.zwe = z;
om_bsel.wr = r;
om_bsel.wg = g;
om_bsel.wb = b;
om_bsel.wa = a;
m_tfx.UpdateOM(om_dssel, om_bsel, bf);
m_dev->DrawPrimitive();
}
}
m_dev->EndScene();
}
void GSRendererHW11::SetupDATE(GSTexture* rt, GSTexture* ds)
{
if(!m_context->TEST.DATE) return; // || (::GetAsyncKeyState(VK_CONTROL) & 0x8000)
GSDevice11* dev = (GSDevice11*)m_dev;
int w = rt->GetWidth();
int h = rt->GetHeight();
if(GSTexture* t = dev->CreateRenderTarget(w, h))
{
// sfex3 (after the capcom logo), vf4 (first menu fading in), ffxii shadows, rumble roses shadows, persona4 shadows
dev->BeginScene();
dev->ClearStencil(ds, 0);
// om
dev->OMSetDepthStencilState(m_date.dss, 1);
dev->OMSetBlendState(m_date.bs, 0);
dev->OMSetRenderTargets(t, ds);
// ia
GSVector4 s = GSVector4(rt->m_scale.x / w, rt->m_scale.y / h);
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());
GSVector4 dst = src * 2.0f + o.xxxx();
GSVertexPT1 vertices[] =
{
{GSVector4(dst.x, -dst.y, 0.5f, 1.0f), GSVector2(src.x, src.y)},
{GSVector4(dst.z, -dst.y, 0.5f, 1.0f), GSVector2(src.z, src.y)},
{GSVector4(dst.x, -dst.w, 0.5f, 1.0f), GSVector2(src.x, src.w)},
{GSVector4(dst.z, -dst.w, 0.5f, 1.0f), GSVector2(src.z, src.w)},
};
dev->IASetVertexBuffer(vertices, sizeof(vertices[0]), countof(vertices));
dev->IASetInputLayout(dev->m_convert.il);
dev->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
// vs
dev->VSSetShader(dev->m_convert.vs, NULL);
// gs
dev->GSSetShader(NULL);
// ps
dev->PSSetShaderResources(rt, NULL);
dev->PSSetShader(dev->m_convert.ps[m_context->TEST.DATM ? 2 : 3], NULL);
dev->PSSetSamplerState(dev->m_convert.pt, NULL);
// rs
dev->RSSet(w, h);
// set
dev->DrawPrimitive();
//
dev->EndScene();
dev->Recycle(t);
}
}

View File

@ -1,573 +0,0 @@
/*
* Copyright (C) 2007-2009 Gabest
* http://www.gabest.org
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
#include "stdafx.h"
#include "GSRendererHW9.h"
#include "GSCrc.h"
#include "resource.h"
GSRendererHW9::GSRendererHW9(uint8* base, bool mt, void (*irq)())
: GSRendererHW<GSVertexHW9>(base, mt, irq, new GSDevice9(), new GSTextureCache9(this))
{
m_fba.enabled = !!theApp.GetConfig("fba", 1);
m_logz = !!theApp.GetConfig("logz", 0);
InitVertexKick<GSRendererHW9>();
}
bool GSRendererHW9::Create(const string& title)
{
if(!__super::Create(title))
return false;
if(!m_tfx.Create((GSDevice9*)m_dev))
return false;
//
memset(&m_date.dss, 0, sizeof(m_date.dss));
m_date.dss.StencilEnable = true;
m_date.dss.StencilReadMask = 1;
m_date.dss.StencilWriteMask = 1;
m_date.dss.StencilFunc = D3DCMP_ALWAYS;
m_date.dss.StencilPassOp = D3DSTENCILOP_REPLACE;
m_date.dss.StencilRef = 1;
memset(&m_date.bs, 0, sizeof(m_date.bs));
//
memset(&m_fba.dss, 0, sizeof(m_fba.dss));
m_fba.dss.StencilEnable = true;
m_fba.dss.StencilReadMask = 2;
m_fba.dss.StencilWriteMask = 2;
m_fba.dss.StencilFunc = D3DCMP_EQUAL;
m_fba.dss.StencilPassOp = D3DSTENCILOP_ZERO;
m_fba.dss.StencilFailOp = D3DSTENCILOP_ZERO;
m_fba.dss.StencilDepthFailOp = D3DSTENCILOP_ZERO;
m_fba.dss.StencilRef = 2;
memset(&m_fba.bs, 0, sizeof(m_fba.bs));
m_fba.bs.RenderTargetWriteMask = D3DCOLORWRITEENABLE_ALPHA;
//
return true;
}
template<uint32 prim, uint32 tme, uint32 fst>
void GSRendererHW9::VertexKick(bool skip)
{
GSVertexHW9& dst = m_vl.AddTail();
dst.p.x = (float)(int)m_v.XYZ.X;
dst.p.y = (float)(int)m_v.XYZ.Y;
dst.p.z = (float)m_v.XYZ.Z;
dst.c0 = m_v.RGBAQ.u32[0];
dst.c1 = m_v.FOG.u32[1];
if(tme)
{
if(fst)
{
GSVector4::storel(&dst.t, m_v.GetUV());
}
else
{
dst.t.x = m_v.ST.S;
dst.t.y = m_v.ST.T;
dst.p.w = m_v.RGBAQ.Q;
}
}
int count = 0;
if(GSVertexHW9* v = DrawingKick<prim>(skip, count))
{
GSVector4 scissor = m_context->scissor.dx9;
GSVector4 pmin, pmax;
switch(prim)
{
case GS_POINTLIST:
pmin = v[0].p;
pmax = v[0].p;
break;
case GS_LINELIST:
case GS_LINESTRIP:
case GS_SPRITE:
pmin = v[0].p.minv(v[1].p);
pmax = v[0].p.maxv(v[1].p);
break;
case GS_TRIANGLELIST:
case GS_TRIANGLESTRIP:
case GS_TRIANGLEFAN:
pmin = v[0].p.minv(v[1].p).minv(v[2].p);
pmax = v[0].p.maxv(v[1].p).maxv(v[2].p);
break;
}
GSVector4 test = (pmax < scissor) | (pmin > scissor.zwxy());
if(test.mask() & 3)
{
return;
}
switch(prim)
{
case GS_POINTLIST:
break;
case GS_LINELIST:
case GS_LINESTRIP:
if(PRIM->IIP == 0) {v[0].c0 = v[1].c0;}
break;
case GS_TRIANGLELIST:
case GS_TRIANGLESTRIP:
case GS_TRIANGLEFAN:
if(PRIM->IIP == 0) {v[0].c0 = v[1].c0 = v[2].c0;}
break;
case GS_SPRITE:
if(PRIM->IIP == 0) {v[0].c0 = v[1].c0;}
v[0].p.z = v[1].p.z;
v[0].p.w = v[1].p.w;
v[0].c1 = v[1].c1;
v[2] = v[1];
v[3] = v[1];
v[1].p.y = v[0].p.y;
v[1].t.y = v[0].t.y;
v[2].p.x = v[0].p.x;
v[2].t.x = v[0].t.x;
v[4] = v[1];
v[5] = v[2];
count += 4;
break;
}
m_count += count;
}
}
void GSRendererHW9::Draw(GS_PRIM_CLASS primclass, GSTexture* rt, GSTexture* ds, GSTextureCache::GSCachedTexture* tex)
{
GSDrawingEnvironment& env = m_env;
GSDrawingContext* context = m_context;
D3DPRIMITIVETYPE topology;
int prims = 0;
switch(primclass)
{
case GS_POINT_CLASS:
topology = D3DPT_POINTLIST;
prims = m_count;
break;
case GS_LINE_CLASS:
topology = D3DPT_LINELIST;
prims = m_count / 2;
break;
case GS_TRIANGLE_CLASS:
case GS_SPRITE_CLASS:
topology = D3DPT_TRIANGLELIST;
prims = m_count / 3;
break;
default:
__assume(0);
}
m_perfmon.Put(GSPerfMon::Prim, prims);
m_perfmon.Put(GSPerfMon::Draw, 1);
// date
SetupDATE(rt, ds);
//
m_dev->BeginScene();
(*(GSDevice9*)m_dev)->SetRenderState(D3DRS_SHADEMODE, PRIM->IIP ? D3DSHADE_GOURAUD : D3DSHADE_FLAT); // TODO
// om
GSTextureFX::OMDepthStencilSelector om_dssel;
om_dssel.zte = context->TEST.ZTE;
om_dssel.ztst = context->TEST.ZTST;
om_dssel.zwe = !context->ZBUF.ZMSK;
om_dssel.date = context->FRAME.PSM != PSM_PSMCT24 ? context->TEST.DATE : 0;
om_dssel.fba = m_fba.enabled ? context->FBA.FBA : 0;
GSTextureFX::OMBlendSelector om_bsel;
om_bsel.abe = !IsOpaque();
om_bsel.a = context->ALPHA.A;
om_bsel.b = context->ALPHA.B;
om_bsel.c = context->ALPHA.C;
om_bsel.d = context->ALPHA.D;
om_bsel.wr = (context->FRAME.FBMSK & 0x000000ff) != 0x000000ff;
om_bsel.wg = (context->FRAME.FBMSK & 0x0000ff00) != 0x0000ff00;
om_bsel.wb = (context->FRAME.FBMSK & 0x00ff0000) != 0x00ff0000;
om_bsel.wa = (context->FRAME.FBMSK & 0xff000000) != 0xff000000;
uint8 bf = context->ALPHA.FIX >= 0x80 ? 0xff : (uint8)(context->ALPHA.FIX * 2);
// vs
GSTextureFX::VSSelector vs_sel;
vs_sel.bppz = 0;
vs_sel.tme = PRIM->TME;
vs_sel.fst = PRIM->FST;
vs_sel.logz = m_logz ? 1 : 0;
if(om_dssel.zte && om_dssel.ztst > 0 && om_dssel.zwe)
{
if(context->ZBUF.PSM == PSM_PSMZ24)
{
if(m_vt.m_max.p.z > 0xffffff)
{
ASSERT(m_vt.m_min.p.z > 0xffffff);
vs_sel.bppz = 1;
om_dssel.ztst = 1;
}
}
else if(context->ZBUF.PSM == PSM_PSMZ16 || context->ZBUF.PSM == PSM_PSMZ16S)
{
if(m_vt.m_max.p.z > 0xffff)
{
ASSERT(m_vt.m_min.p.z > 0xffff);
vs_sel.bppz = 2;
om_dssel.ztst = 1;
}
}
}
GSTextureFX::VSConstantBuffer vs_cb;
float sx = 2.0f * rt->m_scale.x / (rt->GetWidth() * 16);
float sy = 2.0f * rt->m_scale.y / (rt->GetHeight() * 16);
float ox = (float)(int)context->XYOFFSET.OFX;
float oy = (float)(int)context->XYOFFSET.OFY;
vs_cb.VertexScale = GSVector4(sx, -sy, 1.0f / UINT_MAX, 0.0f);
vs_cb.VertexOffset = GSVector4(ox * sx + 1, -(oy * sy + 1), 0.0f, -1.0f);
vs_cb.TextureScale = GSVector2(1.0f, 1.0f);
if(PRIM->TME && PRIM->FST)
{
vs_cb.TextureScale.x = 1.0f / (16 << context->TEX0.TW);
vs_cb.TextureScale.y = 1.0f / (16 << context->TEX0.TH);
}
// ps
GSTextureFX::PSSelector ps_sel;
ps_sel.fst = PRIM->FST;
ps_sel.wms = context->CLAMP.WMS;
ps_sel.wmt = context->CLAMP.WMT;
ps_sel.bpp = 0;
ps_sel.aem = env.TEXA.AEM;
ps_sel.tfx = context->TEX0.TFX;
ps_sel.tcc = context->TEX0.TCC;
ps_sel.ate = context->TEST.ATE;
ps_sel.atst = context->TEST.ATST;
ps_sel.fog = PRIM->FGE;
ps_sel.clr1 = om_bsel.abe && om_bsel.a == 1 && om_bsel.b == 2 && om_bsel.d == 1;
ps_sel.rt = tex && tex->m_rendered;
ps_sel.ltf = m_filter == 2 ? context->TEX1.IsLinear() : m_filter;
GSTextureFX::PSSamplerSelector ps_ssel;
ps_ssel.tau = 0;
ps_ssel.tav = 0;
ps_ssel.ltf = ps_sel.ltf;
GSTextureFX9::PSConstantBuffer ps_cb;
ps_cb.FogColor_AREF = GSVector4((int)env.FOGCOL.FCR, (int)env.FOGCOL.FCG, (int)env.FOGCOL.FCB, (int)context->TEST.AREF) / 255;
if(ps_sel.atst == 2 || ps_sel.atst == 5)
{
ps_cb.FogColor_AREF.a -= 0.9f / 255;
}
else if(ps_sel.atst == 3 || ps_sel.atst == 6)
{
ps_cb.FogColor_AREF.a += 0.9f / 255;
}
if(tex)
{
ps_sel.bpp = tex->m_bpp;
int w = tex->m_texture->GetWidth();
int h = tex->m_texture->GetHeight();
ps_cb.WH_TA = GSVector4(w, h, env.TEXA.TA0, env.TEXA.TA1) / GSVector4(1, 255).xxyy();
ps_cb.HalfTexel = GSVector4(-0.5f, 0.5f).xxyy() / GSVector4(w, h).xyxy();
switch(context->CLAMP.WMS)
{
case 0:
ps_ssel.tau = 1;
break;
case 1:
ps_ssel.tau = 0;
break;
case 2:
ps_cb.MinMax.x = (float)(int)context->CLAMP.MINU / (1 << context->TEX0.TW);
ps_cb.MinMax.z = (float)(int)context->CLAMP.MAXU / (1 << context->TEX0.TW);
ps_cb.MinMaxF.x = ((float)(int)context->CLAMP.MINU + 0.5f) / (1 << context->TEX0.TW);
ps_cb.MinMaxF.z = ((float)(int)context->CLAMP.MAXU) / (1 << context->TEX0.TW);
ps_ssel.tau = 0;
break;
case 3:
ps_cb.MskFix.x = context->CLAMP.MINU;
ps_cb.MskFix.z = context->CLAMP.MAXU;
ps_ssel.tau = 1;
break;
default:
__assume(0);
}
switch(context->CLAMP.WMT)
{
case 0:
ps_ssel.tav = 1;
break;
case 1:
ps_ssel.tav = 0;
break;
case 2:
ps_cb.MinMax.y = (float)(int)context->CLAMP.MINV / (1 << context->TEX0.TH);
ps_cb.MinMax.w = (float)(int)context->CLAMP.MAXV / (1 << context->TEX0.TH);
ps_cb.MinMaxF.y = ((float)(int)context->CLAMP.MINV + 0.5f) / (1 << context->TEX0.TH);
ps_cb.MinMaxF.w = ((float)(int)context->CLAMP.MAXV) / (1 << context->TEX0.TH);
ps_ssel.tav = 0;
break;
case 3:
ps_cb.MskFix.y = context->CLAMP.MINV;
ps_cb.MskFix.w = context->CLAMP.MAXV;
ps_ssel.tav = 1;
break;
default:
__assume(0);
}
}
else
{
ps_sel.tfx = 4;
}
// rs
int w = rt->GetWidth();
int h = rt->GetHeight();
GSVector4i scissor = GSVector4i(GSVector4(rt->m_scale).xyxy() * context->scissor.in).rintersect(GSVector4i(0, 0, w, h));
//
m_tfx.SetupOM(om_dssel, om_bsel, bf, rt, ds);
m_tfx.SetupIA(m_vertices, m_count, topology);
m_tfx.SetupVS(vs_sel, &vs_cb);
m_tfx.SetupPS(ps_sel, &ps_cb, ps_ssel, tex ? tex->m_texture : NULL, tex ? tex->m_palette : NULL);
m_tfx.SetupRS(w, h, scissor);
// draw
if(context->TEST.DoFirstPass())
{
m_dev->DrawPrimitive();
}
if(context->TEST.DoSecondPass())
{
ASSERT(!env.PABE.PABE);
static const uint32 iatst[] = {1, 0, 5, 6, 7, 2, 3, 4};
ps_sel.atst = iatst[ps_sel.atst];
m_tfx.UpdatePS(ps_sel, &ps_cb, ps_ssel);
bool z = om_dssel.zwe;
bool r = om_bsel.wr;
bool g = om_bsel.wg;
bool b = om_bsel.wb;
bool a = om_bsel.wa;
switch(context->TEST.AFAIL)
{
case 0: z = r = g = b = a = false; break; // none
case 1: z = false; break; // rgba
case 2: r = g = b = a = false; break; // z
case 3: z = a = false; break; // rgb
default: __assume(0);
}
if(z || r || g || b || a)
{
om_dssel.zwe = z;
om_bsel.wr = r;
om_bsel.wg = g;
om_bsel.wb = b;
om_bsel.wa = a;
m_tfx.UpdateOM(om_dssel, om_bsel, bf);
m_dev->DrawPrimitive();
}
}
m_dev->EndScene();
if(om_dssel.fba) UpdateFBA(rt);
}
void GSRendererHW9::SetupDATE(GSTexture* rt, GSTexture* ds)
{
if(!m_context->TEST.DATE) return; // || (::GetAsyncKeyState(VK_CONTROL) & 0x8000)
GSDevice9* dev = (GSDevice9*)m_dev;
int w = rt->GetWidth();
int h = rt->GetHeight();
if(GSTexture* t = dev->CreateRenderTarget(w, h))
{
// sfex3 (after the capcom logo), vf4 (first menu fading in), ffxii shadows, rumble roses shadows, persona4 shadows
dev->BeginScene();
dev->ClearStencil(ds, 0);
// om
dev->OMSetDepthStencilState(&m_date.dss);
dev->OMSetBlendState(&m_date.bs, 0);
dev->OMSetRenderTargets(t, ds);
// ia
GSVector4 s = GSVector4(rt->m_scale.x / w, rt->m_scale.y / h);
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());
GSVector4 dst = src * 2.0f + o.xxxx();
GSVertexPT1 vertices[] =
{
{GSVector4(dst.x, -dst.y, 0.5f, 1.0f), GSVector2(src.x, src.y)},
{GSVector4(dst.z, -dst.y, 0.5f, 1.0f), GSVector2(src.z, src.y)},
{GSVector4(dst.x, -dst.w, 0.5f, 1.0f), GSVector2(src.x, src.w)},
{GSVector4(dst.z, -dst.w, 0.5f, 1.0f), GSVector2(src.z, src.w)},
};
dev->IASetVertexBuffer(vertices, sizeof(vertices[0]), countof(vertices));
dev->IASetInputLayout(dev->m_convert.il);
dev->IASetPrimitiveTopology(D3DPT_TRIANGLESTRIP);
// vs
dev->VSSetShader(dev->m_convert.vs, NULL, 0);
// ps
dev->PSSetShaderResources(rt, NULL);
dev->PSSetShader(dev->m_convert.ps[m_context->TEST.DATM ? 2 : 3], NULL, 0);
dev->PSSetSamplerState(&dev->m_convert.pt);
// rs
dev->RSSet(w, h);
//
dev->DrawPrimitive();
//
dev->EndScene();
dev->Recycle(t);
}
}
void GSRendererHW9::UpdateFBA(GSTexture* rt)
{
GSDevice9* dev = (GSDevice9*)m_dev;
dev->BeginScene();
// om
dev->OMSetDepthStencilState(&m_fba.dss);
dev->OMSetBlendState(&m_fba.bs, 0);
// ia
GSVector4 s = GSVector4(rt->m_scale.x / rt->GetWidth(), rt->m_scale.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());
GSVector4 dst = src * 2.0f + o.xxxx();
GSVertexPT1 vertices[] =
{
{GSVector4(dst.x, -dst.y, 0.5f, 1.0f), GSVector2(0, 0)},
{GSVector4(dst.z, -dst.y, 0.5f, 1.0f), GSVector2(0, 0)},
{GSVector4(dst.x, -dst.w, 0.5f, 1.0f), GSVector2(0, 0)},
{GSVector4(dst.z, -dst.w, 0.5f, 1.0f), GSVector2(0, 0)},
};
dev->IASetVertexBuffer(vertices, sizeof(vertices[0]), countof(vertices));
dev->IASetInputLayout(dev->m_convert.il);
dev->IASetPrimitiveTopology(D3DPT_TRIANGLESTRIP);
// vs
dev->VSSetShader(dev->m_convert.vs, NULL, 0);
// ps
dev->PSSetShader(dev->m_convert.ps[4], NULL, 0);
// rs
dev->RSSet(rt->GetWidth(), rt->GetHeight());
//
dev->DrawPrimitive();
//
dev->EndScene();
}

View File

@ -64,13 +64,12 @@ void GSRendererOGL::VertexKick(bool skip)
}
}
void GSRendererOGL::Draw(int prim, GSTexture* rt, GSTexture* ds, GSTextureCache::GSCachedTexture* tex)
void GSRendererOGL::Draw(int prim, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex)
{
GSDrawingEnvironment& env = m_env;
GSDrawingContext* context = m_context;
// m_perfmon.Put(GSPerfMon::Prim, prims);
m_perfmon.Put(GSPerfMon::Draw, 1);
m_dev->BeginScene();

View File

@ -29,7 +29,7 @@
class GSRendererOGL : public GSRendererHW<GSVertexOGL>
{
protected:
void Draw(int prim, GSTexture* rt, GSTexture* ds, GSTextureCache::GSCachedTexture* tex);
void Draw(int prim, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex);
public:
GSRendererOGL(uint8* base, bool mt, void (*irq)());

View File

@ -329,7 +329,7 @@ void GSRendererSW::GetScanlineParam(GSScanlineParam& p, GS_PRIM_CLASS primclass)
p.sel.tfx = context->TEX0.TFX;
p.sel.tcc = context->TEX0.TCC;
p.sel.fst = PRIM->FST;
p.sel.ltf = context->TEX1.IsLinear();
p.sel.ltf = IsLinear();
p.sel.tlu = GSLocalMemory::m_psm[context->TEX0.PSM].pal > 0;
p.sel.wms = context->CLAMP.WMS;
p.sel.wmt = context->CLAMP.WMT;
@ -394,7 +394,7 @@ void GSRendererSW::GetScanlineParam(GSScanlineParam& p, GS_PRIM_CLASS primclass)
GSVector4i r;
GetTextureMinMax(r);
GetTextureMinMax(r, p.sel.ltf);
const GSTextureCacheSW::GSTexture* t = m_tc->Lookup(context->TEX0, env.TEXA, r);

File diff suppressed because it is too large Load Diff

View File

@ -26,101 +26,86 @@
class GSTextureCache
{
public:
class GSSurface : public GSAlignedClass<16>
enum {RenderTarget, DepthStencil};
class Surface : public GSAlignedClass<16>
{
protected:
GSRenderer* m_renderer;
public:
GSTexture* m_texture;
GSTexture* m_palette;
bool m_initpalette;
int m_age;
GSDirtyRectList m_dirty;
GIFRegTEX0 m_TEX0;
GIFRegTEXA m_TEXA;
int m_age;
explicit GSSurface(GSRenderer* r);
virtual ~GSSurface();
public:
explicit Surface(GSRenderer* r);
virtual ~Surface();
virtual void Update();
};
class GSRenderTarget : public GSSurface
class Target;
class Source : public Surface
{
public:
bool m_used;
explicit GSRenderTarget(GSRenderer* r);
void Update();
virtual bool Create(int w, int h);
virtual void Read(const GSVector4i& r) = 0;
};
class GSDepthStencil : public GSSurface
{
public:
bool m_used;
explicit GSDepthStencil(GSRenderer* renderer);
void Update();
virtual bool Create(int w, int h);
};
class GSCachedTexture : public GSSurface
{
protected:
bool GetDirtyRect(GSVector4i& r);
public:
uint32* m_clut; // *
GSVector4i m_valid;
GSTexture* m_palette;
bool m_initpalette;
list<int> m_pages;
uint32 m_valid[MAX_PAGES]; // each uint32 bits map to the 32 blocks of that page
uint32* m_clut;
int m_bpp;
bool m_rendered;
bool m_target;
explicit GSCachedTexture(GSRenderer* renderer);
virtual ~GSCachedTexture();
void Update(const GSVector4i& rect);
public:
explicit Source(GSRenderer* renderer);
virtual ~Source();
virtual bool Create() = 0;
virtual bool Create(GSRenderTarget* rt) = 0;
virtual bool Create(GSDepthStencil* ds) = 0;
virtual bool Create(Target* dst) = 0;
virtual void Update(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GSVector4i& rect);
void Write(const GSVector4i& r, uint8* buff, int pitch);
};
class Target : public Surface
{
public:
int m_type;
bool m_used;
GSDirtyRectList m_dirty;
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:
GSRenderer* m_renderer;
list<GSRenderTarget*> m_rt;
list<GSDepthStencil*> m_ds;
list<GSCachedTexture*> m_tex;
bool m_tex_used;
template<class T> void RecycleByAge(list<T*>& l, int maxage = 60)
struct SourceMap
{
for(list<T*>::iterator i = l.begin(); i != l.end(); )
{
list<T*>::iterator j = i++;
hash_map<Source*, bool> m_surfaces;
hash_map<Source*, bool> m_map[MAX_PAGES];
bool m_used;
T* t = *j;
SourceMap() : m_used(false) {}
if(++t->m_age > maxage)
{
l.erase(j);
void Add(Source* s, const GIFRegTEX0& TEX0);
void RemoveAll();
void RemoveAt(Source* s);
delete t;
}
}
}
} m_src;
virtual GSRenderTarget* CreateRenderTarget() = 0;
virtual GSDepthStencil* CreateDepthStencil() = 0;
virtual GSCachedTexture* CreateTexture() = 0;
list<Target*> m_dst[2];
virtual Source* CreateSource() = 0;
virtual Target* CreateTarget() = 0;
public:
GSTextureCache(GSRenderer* r);
@ -128,12 +113,10 @@ public:
void RemoveAll();
GSRenderTarget* GetRenderTarget(const GIFRegTEX0& TEX0, int w, int h, bool fb = false);
GSDepthStencil* GetDepthStencil(const GIFRegTEX0& TEX0, int w, int h);
GSCachedTexture* GetTexture(const GSVector4i& r);
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);
void InvalidateTextures(const GIFRegFRAME& FRAME, const GIFRegZBUF& ZBUF);
void InvalidateVideoMem(const GIFRegBITBLTBUF& BITBLTBUF, const GSVector4i& r);
void InvalidateVideoMem(const GIFRegBITBLTBUF& BITBLTBUF, const GSVector4i& r, bool target = true);
void InvalidateLocalMem(const GIFRegBITBLTBUF& BITBLTBUF, const GSVector4i& r);
void IncAge();

View File

@ -29,16 +29,207 @@ GSTextureCache10::GSTextureCache10(GSRenderer* r)
{
}
// GSRenderTargetHW10
// Source10
void GSTextureCache10::GSRenderTargetHW10::Read(const GSVector4i& r)
bool GSTextureCache10::Source10::Create()
{
// m_renderer->m_perfmon.Put(GSPerfMon::WriteTexture, 1);
m_TEX0 = m_renderer->m_context->TEX0;
m_TEXA = m_renderer->m_env.TEXA;
m_bpp = 0;
ASSERT(m_texture == NULL);
m_texture = m_renderer->m_dev->CreateTexture(1 << m_TEX0.TW, 1 << m_TEX0.TH);
return m_texture != NULL;
}
bool GSTextureCache10::Source10::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())
{
D3D10_BOX box = {0, 0, 0, w, h, 1};
(*(GSDevice10*)m_renderer->m_dev)->CopySubresourceRegion(*(GSTexture10*)dt, 0, 0, 0, 0, *(GSTexture10*)st, 0, &box);
}
else
{
sr.z /= st->GetWidth();
sr.w /= st->GetHeight();
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)
{
case PSM_PSMCT32:
m_bpp = 0;
break;
case PSM_PSMCT24:
m_bpp = 1;
break;
case PSM_PSMCT16:
case PSM_PSMCT16S:
m_bpp = 2;
break;
case PSM_PSMT8H:
m_bpp = 3;
m_palette = m_renderer->m_dev->CreateTexture(256, 1);
m_initpalette = true;
break;
case PSM_PSMT4HL:
case PSM_PSMT4HH:
ASSERT(0); // TODO
break;
}
return true;
}
// Target10
void GSTextureCache10::Target10::Read(const GSVector4i& r)
{
if(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)
{
//ASSERT(0);
return;
}
@ -121,272 +312,3 @@ void GSTextureCache10::GSRenderTargetHW10::Read(const GSVector4i& r)
m_renderer->m_dev->Recycle(offscreen);
}
}
// GSTextureHW10
bool GSTextureCache10::GSCachedTextureHW10::Create()
{
// m_renderer->m_perfmon.Put(GSPerfMon::WriteTexture, 1);
m_TEX0 = m_renderer->m_context->TEX0;
m_TEXA = m_renderer->m_env.TEXA;
m_bpp = 0;
ASSERT(m_texture == NULL);
m_texture = m_renderer->m_dev->CreateTexture(1 << m_TEX0.TW, 1 << m_TEX0.TH);
return m_texture != NULL;
}
bool GSTextureCache10::GSCachedTextureHW10::Create(GSRenderTarget* rt)
{
m_rendered = true;
// TODO: clean up this mess
rt->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)(rt->m_texture->m_scale.x * tw);
int h = (int)(rt->m_texture->m_scale.y * th);
GSVector2i rtsize = rt->m_texture->GetSize();
// pitch conversion
if(rt->m_TEX0.TBW != m_TEX0.TBW) // && rt->m_TEX0.PSM == m_TEX0.PSM
{
// sfex3 uses this trick (bw: 10 -> 5, wraps the right side below the left)
// ASSERT(rt->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(rtsize.x, rtsize.y);
GSVector4 size = GSVector4(rtsize).xyxy();
GSVector4 scale = GSVector4(rt->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)rt->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 src = GSVector4(GSVector4i(sx, sy).xyxy() + br) * scale / size;
GSVector4 dst = GSVector4(GSVector4i(dx, dy).xyxy() + br) * scale;
m_renderer->m_dev->StretchRect(rt->m_texture, src, m_texture, dst);
// 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 = rt->m_texture->m_scale;
GSVector4 dst(0, 0, w, h);
if(w > rtsize.x)
{
scale.x = (float)rtsize.x / tw;
dst.z = (float)rtsize.x * scale.x / rt->m_texture->m_scale.x;
w = rtsize.x;
}
if(h > rtsize.y)
{
scale.y = (float)rtsize.y / th;
dst.w = (float)rtsize.y * scale.y / rt->m_texture->m_scale.y;
h = rtsize.y;
}
GSVector4 src(0, 0, w, h);
GSTexture* st = m_texture ? m_texture : rt->m_texture;
GSTexture* dt = m_renderer->m_dev->CreateRenderTarget(w, h);
if(!m_texture)
{
m_texture = dt;
}
if(src.x == dst.x && src.y == dst.y && src.z == dst.z && src.w == dst.w)
{
D3D10_BOX box = {0, 0, 0, w, h, 1};
(*(GSDevice10*)m_renderer->m_dev)->CopySubresourceRegion(*(GSTexture10*)dt, 0, 0, 0, 0, *(GSTexture10*)st, 0, &box);
}
else
{
src.z /= st->GetWidth();
src.w /= st->GetHeight();
m_renderer->m_dev->StretchRect(st, src, dt, dst);
}
if(dt != m_texture)
{
m_renderer->m_dev->Recycle(m_texture);
m_texture = dt;
}
m_texture->m_scale = scale;
switch(m_TEX0.PSM)
{
case PSM_PSMCT32:
m_bpp = 0;
break;
case PSM_PSMCT24:
m_bpp = 1;
break;
case PSM_PSMCT16:
case PSM_PSMCT16S:
m_bpp = 2;
break;
case PSM_PSMT8H:
m_bpp = 3;
m_palette = m_renderer->m_dev->CreateTexture(256, 1);
m_initpalette = true;
break;
case PSM_PSMT4HL:
case PSM_PSMT4HH:
ASSERT(0); // TODO
break;
}
return true;
}
bool GSTextureCache10::GSCachedTextureHW10::Create(GSDepthStencil* ds)
{
m_rendered = true;
return false;
/*
// TODO: clean up this mess
ds->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)(ds->m_texture->m_scale.x * tw);
int h = (int)(ds->m_texture->m_scale.y * th);
GSVector2i dssize = ds->m_texture->GetSize();
// pitch conversion
if(ds->m_TEX0.TBW != m_TEX0.TBW) // && rt->m_TEX0.PSM == m_TEX0.PSM
{
ASSERT(0);
}
else if(tw < tp)
{
}
// width/height conversion
GSVector2 scale = ds->m_texture->m_scale;
GSVector4 dst(0, 0, w, h);
if(w > dssize.x)
{
scale.x = (float)dssize.x / tw;
dst.z = (float)dssize.x * scale.x / ds->m_texture->m_scale.x;
w = dssize.x;
}
if(h > dssize.y)
{
scale.y = (float)dssize.y / th;
dst.w = (float)dssize.y * scale.y / ds->m_texture->m_scale.y;
h = dssize.y;
}
m_texture = m_renderer->m_dev->CreateRenderTarget(w, h);
GSVector4 src(0, 0, w, h);
src.z /= ds->m_texture->GetWidth();
src.w /= ds->m_texture->GetHeight();
m_renderer->m_dev->StretchRect(ds->m_texture, src, m_texture, dst, 7);
m_texture->m_scale = scale;
switch(m_TEX0.PSM)
{
case PSM_PSMCT32:
m_bpp = 0;
break;
case PSM_PSMCT24:
m_bpp = 1;
break;
case PSM_PSMCT16:
case PSM_PSMCT16S:
m_bpp = 2;
break;
case PSM_PSMT8H:
m_bpp = 3;
m_palette = m_renderer->m_dev->CreateTexture(256, 1);
m_initpalette = true;
break;
case PSM_PSMT4HL:
case PSM_PSMT4HH:
ASSERT(0); // TODO
break;
}
return true;
*/
}

View File

@ -26,34 +26,26 @@
class GSTextureCache10 : public GSTextureCache
{
class GSRenderTargetHW10 : public GSRenderTarget
class Source10 : public Source
{
public:
explicit GSRenderTargetHW10(GSRenderer* r) : GSRenderTarget(r) {}
explicit Source10(GSRenderer* r) : Source(r) {}
bool Create();
bool Create(Target* dst);
};
class Target10 : public Target
{
public:
explicit Target10(GSRenderer* r) : Target(r) {}
void Read(const GSVector4i& r);
};
class GSDepthStencilHW10 : public GSDepthStencil
{
public:
explicit GSDepthStencilHW10(GSRenderer* r) : GSDepthStencil(r) {}
};
class GSCachedTextureHW10 : public GSCachedTexture
{
public:
explicit GSCachedTextureHW10(GSRenderer* r) : GSCachedTexture(r) {}
bool Create();
bool Create(GSRenderTarget* rt);
bool Create(GSDepthStencil* ds);
};
protected:
GSRenderTarget* CreateRenderTarget() {return new GSRenderTargetHW10(m_renderer);}
GSDepthStencil* CreateDepthStencil() {return new GSDepthStencilHW10(m_renderer);}
GSCachedTexture* CreateTexture() {return new GSCachedTextureHW10(m_renderer);}
Source* CreateSource() {return new Source10(m_renderer);}
Target* CreateTarget() {return new Target10(m_renderer);}
public:
GSTextureCache10(GSRenderer* r);

View File

@ -29,16 +29,208 @@ GSTextureCache11::GSTextureCache11(GSRenderer* r)
{
}
// GSRenderTargetHW10
// Source11
void GSTextureCache11::GSRenderTargetHW11::Read(const GSVector4i& r)
bool GSTextureCache11::Source11::Create()
{
// m_renderer->m_perfmon.Put(GSPerfMon::WriteTexture, 1);
m_TEX0 = m_renderer->m_context->TEX0;
m_TEXA = m_renderer->m_env.TEXA;
m_bpp = 0;
ASSERT(m_texture == NULL);
m_texture = m_renderer->m_dev->CreateTexture(1 << m_TEX0.TW, 1 << m_TEX0.TH);
return m_texture != NULL;
}
bool GSTextureCache11::Source11::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())
{
D3D11_BOX box = {0, 0, 0, w, h, 1};
ID3D11DeviceContext* ctx = *(GSDevice11*)m_renderer->m_dev;
ctx->CopySubresourceRegion(*(GSTexture11*)dt, 0, 0, 0, 0, *(GSTexture11*)st, 0, &box);
}
else
{
sr.z /= st->GetWidth();
sr.w /= st->GetHeight();
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)
{
case PSM_PSMCT32:
m_bpp = 0;
break;
case PSM_PSMCT24:
m_bpp = 1;
break;
case PSM_PSMCT16:
case PSM_PSMCT16S:
m_bpp = 2;
break;
case PSM_PSMT8H:
m_bpp = 3;
m_palette = m_renderer->m_dev->CreateTexture(256, 1);
m_initpalette = true;
break;
case PSM_PSMT4HL:
case PSM_PSMT4HH:
ASSERT(0); // TODO
break;
}
return true;
}
// Target11
void GSTextureCache11::Target11::Read(const GSVector4i& r)
{
if(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)
{
//ASSERT(0);
return;
}
@ -122,188 +314,3 @@ void GSTextureCache11::GSRenderTargetHW11::Read(const GSVector4i& r)
}
}
// GSTextureHW10
bool GSTextureCache11::GSCachedTextureHW11::Create()
{
// m_renderer->m_perfmon.Put(GSPerfMon::WriteTexture, 1);
m_TEX0 = m_renderer->m_context->TEX0;
m_TEXA = m_renderer->m_env.TEXA;
m_bpp = 0;
ASSERT(m_texture == NULL);
m_texture = m_renderer->m_dev->CreateTexture(1 << m_TEX0.TW, 1 << m_TEX0.TH);
return m_texture != NULL;
}
bool GSTextureCache11::GSCachedTextureHW11::Create(GSRenderTarget* rt)
{
// TODO: clean up this mess
rt->Update();
// m_renderer->m_perfmon.Put(GSPerfMon::ConvertRT2T, 1);
m_TEX0 = m_renderer->m_context->TEX0;
m_TEXA = m_renderer->m_env.TEXA;
m_rendered = true;
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)(rt->m_texture->m_scale.x * tw);
int h = (int)(rt->m_texture->m_scale.y * th);
GSVector2i rtsize = rt->m_texture->GetSize();
// pitch conversion
if(rt->m_TEX0.TBW != m_TEX0.TBW) // && rt->m_TEX0.PSM == m_TEX0.PSM
{
// sfex3 uses this trick (bw: 10 -> 5, wraps the right side below the left)
// ASSERT(rt->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(rtsize.x, rtsize.y);
GSVector4 size = GSVector4(rtsize).xyxy();
GSVector4 scale = GSVector4(rt->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)rt->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 src = GSVector4(GSVector4i(sx, sy).xyxy() + br) * scale / size;
GSVector4 dst = GSVector4(GSVector4i(dx, dy).xyxy() + br) * scale;
m_renderer->m_dev->StretchRect(rt->m_texture, src, m_texture, dst);
// 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 = rt->m_texture->m_scale;
GSVector4 dst(0, 0, w, h);
if(w > rtsize.x)
{
scale.x = (float)rtsize.x / tw;
dst.z = (float)rtsize.x * scale.x / rt->m_texture->m_scale.x;
w = rtsize.x;
}
if(h > rtsize.y)
{
scale.y = (float)rtsize.y / th;
dst.w = (float)rtsize.y * scale.y / rt->m_texture->m_scale.y;
h = rtsize.y;
}
GSVector4 src(0, 0, w, h);
GSTexture* st = m_texture ? m_texture : rt->m_texture;
GSTexture* dt = m_renderer->m_dev->CreateRenderTarget(w, h);
if(!m_texture)
{
m_texture = dt;
}
if(src.x == dst.x && src.y == dst.y && src.z == dst.z && src.w == dst.w)
{
D3D11_BOX box = {0, 0, 0, w, h, 1};
ID3D11DeviceContext* ctx = *(GSDevice11*)m_renderer->m_dev;
ctx->CopySubresourceRegion(*(GSTexture11*)dt, 0, 0, 0, 0, *(GSTexture11*)st, 0, &box);
}
else
{
src.z /= st->GetWidth();
src.w /= st->GetHeight();
m_renderer->m_dev->StretchRect(st, src, dt, dst);
}
if(dt != m_texture)
{
m_renderer->m_dev->Recycle(m_texture);
m_texture = dt;
}
m_texture->m_scale = scale;
switch(m_TEX0.PSM)
{
case PSM_PSMCT32:
m_bpp = 0;
break;
case PSM_PSMCT24:
m_bpp = 1;
break;
case PSM_PSMCT16:
case PSM_PSMCT16S:
m_bpp = 2;
break;
case PSM_PSMT8H:
m_bpp = 3;
m_palette = m_renderer->m_dev->CreateTexture(256, 1);
m_initpalette = true;
break;
case PSM_PSMT4HL:
case PSM_PSMT4HH:
ASSERT(0); // TODO
break;
}
return true;
}
bool GSTextureCache11::GSCachedTextureHW11::Create(GSDepthStencil* ds)
{
m_rendered = true;
// TODO
return false;
}

View File

@ -26,34 +26,26 @@
class GSTextureCache11 : public GSTextureCache
{
class GSRenderTargetHW11 : public GSRenderTarget
class Source11 : public Source
{
public:
explicit GSRenderTargetHW11(GSRenderer* r) : GSRenderTarget(r) {}
explicit Source11(GSRenderer* r) : Source(r) {}
bool Create();
bool Create(Target* dst);
};
class Target11 : public Target
{
public:
explicit Target11(GSRenderer* r) : Target(r) {}
void Read(const GSVector4i& r);
};
class GSDepthStencilHW11 : public GSDepthStencil
{
public:
explicit GSDepthStencilHW11(GSRenderer* r) : GSDepthStencil(r) {}
};
class GSCachedTextureHW11 : public GSCachedTexture
{
public:
explicit GSCachedTextureHW11(GSRenderer* r) : GSCachedTexture(r) {}
bool Create();
bool Create(GSRenderTarget* rt);
bool Create(GSDepthStencil* ds);
};
protected:
GSRenderTarget* CreateRenderTarget() {return new GSRenderTargetHW11(m_renderer);}
GSDepthStencil* CreateDepthStencil() {return new GSDepthStencilHW11(m_renderer);}
GSCachedTexture* CreateTexture() {return new GSCachedTextureHW11(m_renderer);}
Source* CreateSource() {return new Source11(m_renderer);}
Target* CreateTarget() {return new Target11(m_renderer);}
public:
GSTextureCache11(GSRenderer* r);

View File

@ -29,16 +29,207 @@ GSTextureCache9::GSTextureCache9(GSRenderer* r)
{
}
// GSRenderTarget9
// Source9
void GSTextureCache9::GSRenderTarget9::Read(const GSVector4i& r)
bool GSTextureCache9::Source9::Create()
{
// m_renderer->m_perfmon.Put(GSPerfMon::WriteTexture, 1);
m_TEX0 = m_renderer->m_context->TEX0;
m_TEXA = m_renderer->m_env.TEXA;
m_bpp = 0;
ASSERT(m_texture == NULL);
m_texture = m_renderer->m_dev->CreateTexture(1 << m_TEX0.TW, 1 << m_TEX0.TH);
return m_texture != NULL;
}
bool GSTextureCache9::Source9::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())
{
GSVector4i r(0, 0, w, h);
(*(GSDevice9*)m_renderer->m_dev)->StretchRect(*(GSTexture9*)st, r, *(GSTexture9*)dt, r, D3DTEXF_POINT);
}
else
{
sr.z /= st->GetWidth();
sr.w /= st->GetHeight();
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)
{
case PSM_PSMCT32:
m_bpp = 0;
break;
case PSM_PSMCT24:
m_bpp = 1;
break;
case PSM_PSMCT16:
case PSM_PSMCT16S:
m_bpp = 2;
break;
case PSM_PSMT8H:
m_bpp = 3;
m_palette = m_renderer->m_dev->CreateTexture(256, 1);
m_initpalette = true;
break;
case PSM_PSMT4HL:
case PSM_PSMT4HH:
ASSERT(0); // TODO
break;
}
return true;
}
// Target9
void GSTextureCache9::Target9::Read(const GSVector4i& r)
{
if(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)
{
//ASSERT(0);
return;
}
@ -120,186 +311,3 @@ void GSTextureCache9::GSRenderTarget9::Read(const GSVector4i& r)
}
}
// GSTexture9
bool GSTextureCache9::GSCachedTexture9::Create()
{
// m_renderer->m_perfmon.Put(GSPerfMon::WriteTexture, 1);
m_TEX0 = m_renderer->m_context->TEX0;
m_TEXA = m_renderer->m_env.TEXA;
m_bpp = 0;
ASSERT(m_texture == NULL);
m_texture = m_renderer->m_dev->CreateTexture(1 << m_TEX0.TW, 1 << m_TEX0.TH);
return m_texture != NULL;
}
bool GSTextureCache9::GSCachedTexture9::Create(GSRenderTarget* rt)
{
// TODO: clean up this mess
rt->Update();
// m_renderer->m_perfmon.Put(GSPerfMon::ConvertRT2T, 1);
m_TEX0 = m_renderer->m_context->TEX0;
m_TEXA = m_renderer->m_env.TEXA;
m_rendered = true;
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)(rt->m_texture->m_scale.x * tw);
int h = (int)(rt->m_texture->m_scale.y * th);
GSVector2i rtsize = rt->m_texture->GetSize();
// pitch conversion
if(rt->m_TEX0.TBW != m_TEX0.TBW) // && rt->m_TEX0.PSM == m_TEX0.PSM
{
// sfex3 uses this trick (bw: 10 -> 5, wraps the right side below the left)
// ASSERT(rt->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(rtsize.x, rtsize.y);
GSVector4 size = GSVector4(rtsize).xyxy();
GSVector4 scale = GSVector4(rt->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)rt->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 src = GSVector4(GSVector4i(sx, sy).xyxy() + br) * scale / size;
GSVector4 dst = GSVector4(GSVector4i(dx, dy).xyxy() + br) * scale;
m_renderer->m_dev->StretchRect(rt->m_texture, src, m_texture, dst);
// 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 = rt->m_texture->m_scale;
GSVector4 dst(0, 0, w, h);
if(w > rtsize.x)
{
scale.x = (float)rtsize.x / tw;
dst.z = (float)rtsize.x * scale.x / rt->m_texture->m_scale.x;
w = rtsize.x;
}
if(h > rtsize.y)
{
scale.y = (float)rtsize.y / th;
dst.w = (float)rtsize.y * scale.y / rt->m_texture->m_scale.y;
h = rtsize.y;
}
GSVector4 src(0, 0, w, h);
GSTexture* st = m_texture ? m_texture : rt->m_texture;
GSTexture* dt = m_renderer->m_dev->CreateRenderTarget(w, h);
if(!m_texture)
{
m_texture = dt;
}
if(src.x == dst.x && src.y == dst.y && src.z == dst.z && src.w == dst.w)
{
GSVector4i r(0, 0, w, h);
(*(GSDevice9*)m_renderer->m_dev)->StretchRect(*(GSTexture9*)st, r, *(GSTexture9*)dt, r, D3DTEXF_POINT);
}
else
{
src.z /= st->GetWidth();
src.w /= st->GetHeight();
m_renderer->m_dev->StretchRect(st, src, dt, dst);
}
if(dt != m_texture)
{
m_renderer->m_dev->Recycle(m_texture);
m_texture = dt;
}
m_texture->m_scale = scale;
switch(m_TEX0.PSM)
{
case PSM_PSMCT32:
m_bpp = 0;
break;
case PSM_PSMCT24:
m_bpp = 1;
break;
case PSM_PSMCT16:
case PSM_PSMCT16S:
m_bpp = 2;
break;
case PSM_PSMT8H:
m_bpp = 3;
m_palette = m_renderer->m_dev->CreateTexture(256, 1);
m_initpalette = true;
break;
case PSM_PSMT4HL:
case PSM_PSMT4HH:
ASSERT(0); // TODO
break;
}
return true;
}
bool GSTextureCache9::GSCachedTexture9::Create(GSDepthStencil* ds)
{
m_rendered = true;
// TODO
return false;
}

View File

@ -26,34 +26,26 @@
class GSTextureCache9 : public GSTextureCache
{
class GSRenderTarget9 : public GSRenderTarget
class Source9 : public Source
{
public:
explicit GSRenderTarget9(GSRenderer* r) : GSRenderTarget(r) {}
explicit Source9(GSRenderer* r) : Source(r) {}
bool Create();
bool Create(Target* dst);
};
class Target9 : public Target
{
public:
explicit Target9(GSRenderer* r) : Target(r) {}
void Read(const GSVector4i& r);
};
class GSDepthStencil9 : public GSDepthStencil
{
public:
explicit GSDepthStencil9(GSRenderer* r) : GSDepthStencil(r) {}
};
class GSCachedTexture9 : public GSCachedTexture
{
public:
explicit GSCachedTexture9(GSRenderer* r) : GSCachedTexture(r) {}
bool Create();
bool Create(GSRenderTarget* rt);
bool Create(GSDepthStencil* ds);
};
protected:
GSRenderTarget* CreateRenderTarget() {return new GSRenderTarget9(m_renderer);}
GSDepthStencil* CreateDepthStencil() {return new GSDepthStencil9(m_renderer);}
GSCachedTexture* CreateTexture() {return new GSCachedTexture9(m_renderer);}
Source* CreateSource() {return new Source9(m_renderer);}
Target* CreateTarget() {return new Target9(m_renderer);}
public:
GSTextureCache9(GSRenderer* r);

View File

@ -29,34 +29,27 @@ GSTextureCacheOGL::GSTextureCacheOGL(GSRenderer* r)
{
}
// GSRenderTargetOGL
// SourceOGL
void GSTextureCacheOGL::GSRenderTargetOGL::Read(const GSVector4i& r)
{
// TODO
}
// GSTextureOGL
bool GSTextureCacheOGL::GSCachedTextureOGL::Create()
bool GSTextureCacheOGL::SourceOGL::Create()
{
// TODO
return true;
}
bool GSTextureCacheOGL::GSCachedTextureOGL::Create(GSRenderTarget* rt)
bool GSTextureCacheOGL::SourceOGL::Create(Target* dst)
{
m_target = true;
// TODO
return true;
}
bool GSTextureCacheOGL::GSCachedTextureOGL::Create(GSDepthStencil* ds)
// TargetOGL
void GSTextureCacheOGL::TargetOGL::Read(const GSVector4i& r)
{
m_rendered = true;
// TODO
return false;
}

View File

@ -26,34 +26,26 @@
class GSTextureCacheOGL : public GSTextureCache
{
class GSRenderTargetOGL : public GSRenderTarget
class SourceOGL : public Source
{
public:
explicit GSRenderTargetOGL(GSRenderer* r) : GSRenderTarget(r) {}
explicit SourceOGL(GSRenderer* r) : Source(r) {}
bool Create();
bool Create(Target* dst);
};
class TargetOGL : public Target
{
public:
explicit TargetOGL(GSRenderer* r) : Target(r) {}
void Read(const GSVector4i& r);
};
class GSDepthStencilOGL : public GSDepthStencil
{
public:
explicit GSDepthStencilOGL(GSRenderer* r) : GSDepthStencil(r) {}
};
class GSCachedTextureOGL : public GSCachedTexture
{
public:
explicit GSCachedTextureOGL(GSRenderer* r) : GSCachedTexture(r) {}
bool Create();
bool Create(GSRenderTarget* rt);
bool Create(GSDepthStencil* ds);
};
protected:
GSRenderTarget* CreateRenderTarget() {return new GSRenderTargetOGL(m_renderer);}
GSDepthStencil* CreateDepthStencil() {return new GSDepthStencilOGL(m_renderer);}
GSCachedTexture* CreateTexture() {return new GSCachedTextureOGL(m_renderer);}
Source* CreateSource() {return new SourceOGL(m_renderer);}
Target* CreateTarget() {return new TargetOGL(m_renderer);}
public:
GSTextureCacheOGL(GSRenderer* r);

View File

@ -34,17 +34,15 @@ GSTextureCacheSW::~GSTextureCacheSW()
const GSTextureCacheSW::GSTexture* GSTextureCacheSW::Lookup(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GSVector4i& r)
{
GSLocalMemory& mem = m_state->m_mem;
const GSLocalMemory::psm_t& psm = GSLocalMemory::m_psm[TEX0.PSM];
const hash_map<GSTexture*, bool>& map = m_map[TEX0.TBP0 >> 5];
GSTexture* t = NULL;
const hash_map<GSTexture*, bool>& map = m_map[TEX0.TBP0 >> 5];
for(hash_map<GSTexture*, bool>::const_iterator i = map.begin(); i != map.end(); i++)
{
GSTexture* t2 = (*i).first;
GSTexture* t2 = i->first;
if(((t2->m_TEX0.u32[0] ^ TEX0.u32[0]) | ((t2->m_TEX0.u32[1] ^ TEX0.u32[1]) & 3)) != 0) // TBP0 TBW PSM TW TH
{
@ -85,12 +83,10 @@ const GSTextureCacheSW::GSTexture* GSTextureCacheSW::Lookup(const GIFRegTEX0& TE
{
uint32 page = (base + psm.blockOffset[x >> 3]) >> 5;
if(page >= MAX_PAGES)
if(page < MAX_PAGES)
{
continue;
m_map[page][t] = true;
}
m_map[page][t] = true;
}
}
}
@ -170,20 +166,21 @@ void GSTextureCacheSW::InvalidateVideoMem(const GIFRegBITBLTBUF& BITBLTBUF, cons
{
uint32 page = (base + psm.blockOffset[x >> 3]) >> 5;
if(page >= MAX_PAGES)
if(page < MAX_PAGES)
{
continue;
}
const hash_map<GSTexture*, bool>& map = m_map[page];
const hash_map<GSTexture*, bool>& map = m_map[page];
for(hash_map<GSTexture*, bool>::const_iterator i = map.begin(); i != map.end(); i++)
{
GSTexture* t = i->first;
for(hash_map<GSTexture*, bool>::const_iterator i = map.begin(); i != map.end(); i++)
{
GSTexture* t = (*i).first;
if(GSUtil::HasSharedBits(BITBLTBUF.DPSM, t->m_TEX0.PSM))
{
t->m_valid[page] = 0;
t->m_valid[page] = 0;
t->m_complete = false;
t->m_complete = false;
}
}
}
}
}
@ -219,13 +216,8 @@ bool GSTextureCacheSW::GSTexture::Update(const GIFRegTEX0& TEX0, const GIFRegTEX
m_TEX0 = TEX0;
m_TEXA = TEXA;
GSLocalMemory& mem = m_state->m_mem;
const GSLocalMemory::psm_t& psm = GSLocalMemory::m_psm[TEX0.PSM];
uint32 bp = TEX0.TBP0;
uint32 bw = TEX0.TBW;
GSVector2i s = psm.bs;
int tw = max(1 << TEX0.TW, s.x);
@ -250,8 +242,13 @@ bool GSTextureCacheSW::GSTexture::Update(const GIFRegTEX0& TEX0, const GIFRegTEX
m_complete = true; // lame, but better than nothing
}
GSLocalMemory& mem = m_state->m_mem;
uint32 bp = TEX0.TBP0;
uint32 bw = TEX0.TBW;
GSLocalMemory::readTextureBlock rtxb = psm.rtxbP;
int bytes = psm.pal > 0 ? 1 : 4;
uint32 pitch = (1 << m_tw) * bytes;

View File

@ -23,9 +23,6 @@
#include "GSRenderer.h"
#define MAX_PAGES 512
#define MAX_BLOCKS 16384
class GSTextureCacheSW
{
public:

View File

@ -21,3 +21,16 @@
#include "stdafx.h"
#include "GSTextureFX.h"
GSTextureFX::GSTextureFX()
: m_dev(NULL)
{
}
bool GSTextureFX::Create(GSDevice* dev)
{
m_dev = dev;
return true;
}

View File

@ -22,8 +22,10 @@
#pragma once
#include "GSVector.h"
#include "GSDevice.h"
#include "GSAlignedClass.h"
class GSTextureFX
class GSTextureFX : public GSAlignedClass<16>
{
public:
#pragma pack(push, 1)
@ -87,9 +89,9 @@ public:
{
GSVector4 FogColor_AREF;
GSVector4 HalfTexel;
GSVector4 WH_TA;
GSVector4 WH;
GSVector4 MinMax;
GSVector4 MinMaxF;
GSVector4 MinF_TA;
GSVector4i MskFix;
struct PSConstantBuffer()
@ -240,4 +242,21 @@ public:
};
#pragma pack(pop)
protected:
GSDevice* m_dev;
public:
GSTextureFX();
virtual bool Create(GSDevice* dev);
virtual void SetupIA(const void* vertices, int count, int prim) = 0;
virtual void SetupVS(VSSelector sel, const VSConstantBuffer* cb) = 0;
virtual void SetupGS(GSSelector sel) = 0;
virtual void SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSelector ssel, GSTexture* tex, GSTexture* pal) = 0;
virtual void UpdatePS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSelector ssel) = 0;
virtual void SetupRS(int w, int h, const GSVector4i& scissor) = 0;
virtual void SetupOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, uint8 afix, GSTexture* rt, GSTexture* ds) = 0;
virtual void UpdateOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, uint8 afix) = 0;
};

View File

@ -24,21 +24,17 @@
#include "resource.h"
GSTextureFX10::GSTextureFX10()
: m_dev(NULL)
{
memset(&m_vs_cb_cache, 0, sizeof(m_vs_cb_cache));
memset(&m_ps_cb_cache, 0, sizeof(m_ps_cb_cache));
}
bool GSTextureFX10::Create(GSDevice10* dev)
bool GSTextureFX10::Create(GSDevice* dev)
{
m_dev = dev;
VSSelector sel;
VSConstantBuffer cb;
SetupVS(sel, &cb); // creates layout
if(!__super::Create(dev))
{
return false;
}
HRESULT hr;
@ -50,7 +46,7 @@ bool GSTextureFX10::Create(GSDevice10* dev)
bd.Usage = D3D10_USAGE_DEFAULT;
bd.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
hr = (*m_dev)->CreateBuffer(&bd, NULL, &m_vs_cb);
hr = (*(GSDevice10*)dev)->CreateBuffer(&bd, NULL, &m_vs_cb);
if(FAILED(hr)) return false;
@ -60,7 +56,7 @@ bool GSTextureFX10::Create(GSDevice10* dev)
bd.Usage = D3D10_USAGE_DEFAULT;
bd.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
hr = (*m_dev)->CreateBuffer(&bd, NULL, &m_ps_cb);
hr = (*(GSDevice10*)dev)->CreateBuffer(&bd, NULL, &m_ps_cb);
if(FAILED(hr)) return false;
@ -76,7 +72,7 @@ bool GSTextureFX10::Create(GSDevice10* dev)
sd.MaxAnisotropy = 16;
sd.ComparisonFunc = D3D10_COMPARISON_NEVER;
hr = (*m_dev)->CreateSamplerState(&sd, &m_palette_ss);
hr = (*(GSDevice10*)dev)->CreateSamplerState(&sd, &m_palette_ss);
if(FAILED(hr)) return false;
@ -85,17 +81,19 @@ bool GSTextureFX10::Create(GSDevice10* dev)
return true;
}
bool GSTextureFX10::SetupIA(const GSVertexHW10* vertices, int count, D3D10_PRIMITIVE_TOPOLOGY prim)
void GSTextureFX10::SetupIA(const void* vertices, int count, int prim)
{
m_dev->IASetVertexBuffer(vertices, sizeof(vertices[0]), count);
m_dev->IASetInputLayout(m_il);
m_dev->IASetPrimitiveTopology(prim);
GSDevice10* dev = (GSDevice10*)m_dev;
return true;
dev->IASetVertexBuffer(vertices, sizeof(GSVertexHW10), count);
dev->IASetInputLayout(m_il);
dev->IASetPrimitiveTopology((D3D10_PRIMITIVE_TOPOLOGY)prim);
}
bool GSTextureFX10::SetupVS(VSSelector sel, const VSConstantBuffer* cb)
void GSTextureFX10::SetupVS(VSSelector sel, const VSConstantBuffer* cb)
{
GSDevice10* dev = (GSDevice10*)m_dev;
hash_map<uint32, CComPtr<ID3D10VertexShader> >::const_iterator i = m_vs.find(sel);
if(i == m_vs.end())
@ -129,7 +127,7 @@ bool GSTextureFX10::SetupVS(VSSelector sel, const VSConstantBuffer* cb)
CComPtr<ID3D10InputLayout> il;
CComPtr<ID3D10VertexShader> vs;
m_dev->CompileShader(IDR_TFX_FX, "vs_main", macro, &vs, layout, countof(layout), &il);
dev->CompileShader(IDR_TFX_FX, "vs_main", macro, &vs, layout, countof(layout), &il);
if(m_il == NULL)
{
@ -143,17 +141,15 @@ bool GSTextureFX10::SetupVS(VSSelector sel, const VSConstantBuffer* cb)
if(m_vs_cb_cache.Update(cb))
{
(*m_dev)->UpdateSubresource(m_vs_cb, 0, NULL, cb, 0, 0);
(*dev)->UpdateSubresource(m_vs_cb, 0, NULL, cb, 0, 0);
}
m_dev->VSSetShader((*i).second, m_vs_cb);
return true;
dev->VSSetShader(i->second, m_vs_cb);
}
bool GSTextureFX10::SetupGS(GSSelector sel)
void GSTextureFX10::SetupGS(GSSelector sel)
{
HRESULT hr;
GSDevice10* dev = (GSDevice10*)m_dev;
ID3D10GeometryShader* gs = NULL;
@ -163,7 +159,7 @@ bool GSTextureFX10::SetupGS(GSSelector sel)
if(i != m_gs.end())
{
gs = (*i).second;
gs = i->second;
}
else
{
@ -179,29 +175,25 @@ bool GSTextureFX10::SetupGS(GSSelector sel)
{NULL, NULL},
};
hr = m_dev->CompileShader(IDR_TFX_FX, "gs_main", macro, &gs);
dev->CompileShader(IDR_TFX_FX, "gs_main", macro, &gs);
m_gs[sel] = gs;
}
}
m_dev->GSSetShader(gs);
return true;
dev->GSSetShader(gs);
}
bool GSTextureFX10::SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSelector ssel, GSTexture* tex, GSTexture* pal)
void GSTextureFX10::SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSelector ssel, GSTexture* tex, GSTexture* pal)
{
m_dev->PSSetShaderResources(tex, pal);
((GSDevice10*)m_dev)->PSSetShaderResources(tex, pal);
UpdatePS(sel, cb, ssel);
return true;
}
void GSTextureFX10::UpdatePS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSelector ssel)
{
HRESULT hr;
GSDevice10* dev = (GSDevice10*)m_dev;
hash_map<uint32, CComPtr<ID3D10PixelShader> >::const_iterator i = m_ps.find(sel);
@ -245,7 +237,7 @@ void GSTextureFX10::UpdatePS(PSSelector sel, const PSConstantBuffer* cb, PSSampl
CComPtr<ID3D10PixelShader> ps;
hr = m_dev->CompileShader(IDR_TFX_FX, "ps_main", macro, &ps);
dev->CompileShader(IDR_TFX_FX, "ps_main", macro, &ps);
m_ps[sel] = ps;
@ -254,10 +246,10 @@ void GSTextureFX10::UpdatePS(PSSelector sel, const PSConstantBuffer* cb, PSSampl
if(m_ps_cb_cache.Update(cb))
{
(*m_dev)->UpdateSubresource(m_ps_cb, 0, NULL, cb, 0, 0);
(*dev)->UpdateSubresource(m_ps_cb, 0, NULL, cb, 0, 0);
}
m_dev->PSSetShader((*i).second, m_ps_cb);
dev->PSSetShader(i->second, m_ps_cb);
ID3D10SamplerState* ss0 = NULL;
ID3D10SamplerState* ss1 = NULL;
@ -291,7 +283,7 @@ void GSTextureFX10::UpdatePS(PSSelector sel, const PSConstantBuffer* cb, PSSampl
sd.MaxAnisotropy = 16;
sd.ComparisonFunc = D3D10_COMPARISON_NEVER;
hr = (*m_dev)->CreateSamplerState(&sd, &ss0);
(*dev)->CreateSamplerState(&sd, &ss0);
m_ps_ss[ssel] = ss0;
}
@ -302,24 +294,24 @@ void GSTextureFX10::UpdatePS(PSSelector sel, const PSConstantBuffer* cb, PSSampl
}
}
m_dev->PSSetSamplerState(ss0, ss1);
dev->PSSetSamplerState(ss0, ss1);
}
void GSTextureFX10::SetupRS(int w, int h, const GSVector4i& scissor)
{
m_dev->RSSet(w, h, &scissor);
((GSDevice10*)m_dev)->RSSet(w, h, &scissor);
}
void GSTextureFX10::SetupOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, float bf, GSTexture* rt, GSTexture* ds)
void GSTextureFX10::SetupOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, uint8 afix, GSTexture* rt, GSTexture* ds)
{
UpdateOM(dssel, bsel, bf);
UpdateOM(dssel, bsel, afix);
m_dev->OMSetRenderTargets(rt, ds);
((GSDevice10*)m_dev)->OMSetRenderTargets(rt, ds);
}
void GSTextureFX10::UpdateOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, float bf)
void GSTextureFX10::UpdateOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, uint8 afix)
{
HRESULT hr;
GSDevice10* dev = (GSDevice10*)m_dev;
hash_map<uint32, CComPtr<ID3D10DepthStencilState> >::const_iterator i = m_om_dss.find(dssel);
@ -361,14 +353,14 @@ void GSTextureFX10::UpdateOM(OMDepthStencilSelector dssel, OMBlendSelector bsel,
CComPtr<ID3D10DepthStencilState> dss;
hr = (*m_dev)->CreateDepthStencilState(&dsd, &dss);
(*dev)->CreateDepthStencilState(&dsd, &dss);
m_om_dss[dssel] = dss;
i = m_om_dss.find(dssel);
}
m_dev->OMSetDepthStencilState((*i).second, 1);
dev->OMSetDepthStencilState((*i).second, 1);
hash_map<uint32, CComPtr<ID3D10BlendState> >::const_iterator j = m_om_bs.find(bsel);
@ -502,12 +494,12 @@ void GSTextureFX10::UpdateOM(OMDepthStencilSelector dssel, OMBlendSelector bsel,
CComPtr<ID3D10BlendState> bs;
hr = (*m_dev)->CreateBlendState(&bd, &bs);
(*dev)->CreateBlendState(&bd, &bs);
m_om_bs[bsel] = bs;
j = m_om_bs.find(bsel);
}
m_dev->OMSetBlendState((*j).second, bf);
dev->OMSetBlendState(j->second, (float)(int)afix / 0x80);
}

View File

@ -26,7 +26,6 @@
class GSTextureFX10 : public GSTextureFX
{
GSDevice10* m_dev;
CComPtr<ID3D10InputLayout> m_il;
hash_map<uint32, CComPtr<ID3D10VertexShader> > m_vs;
CComPtr<ID3D10Buffer> m_vs_cb;
@ -44,14 +43,14 @@ class GSTextureFX10 : public GSTextureFX
public:
GSTextureFX10();
bool Create(GSDevice10* dev);
bool Create(GSDevice* dev);
bool SetupIA(const GSVertexHW10* vertices, int count, D3D10_PRIMITIVE_TOPOLOGY prim);
bool SetupVS(VSSelector sel, const VSConstantBuffer* cb);
bool SetupGS(GSSelector sel);
bool SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSelector ssel, GSTexture* tex, GSTexture* pal);
void SetupIA(const void* vertices, int count, int prim);
void SetupVS(VSSelector sel, const VSConstantBuffer* cb);
void SetupGS(GSSelector sel);
void SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSelector ssel, GSTexture* tex, GSTexture* pal);
void UpdatePS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSelector ssel);
void SetupRS(int w, int h, const GSVector4i& scissor);
void SetupOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, float bf, GSTexture* rt, GSTexture* ds);
void UpdateOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, float bf);
void SetupOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, uint8 afix, GSTexture* rt, GSTexture* ds);
void UpdateOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, uint8 afix);
};

View File

@ -24,21 +24,17 @@
#include "resource.h"
GSTextureFX11::GSTextureFX11()
: m_dev(NULL)
{
memset(&m_vs_cb_cache, 0, sizeof(m_vs_cb_cache));
memset(&m_ps_cb_cache, 0, sizeof(m_ps_cb_cache));
}
bool GSTextureFX11::Create(GSDevice11* dev)
bool GSTextureFX11::Create(GSDevice* dev)
{
m_dev = dev;
VSSelector sel;
VSConstantBuffer cb;
SetupVS(sel, &cb); // creates layout
if(!__super::Create(dev))
{
return false;
}
HRESULT hr;
@ -50,7 +46,7 @@ bool GSTextureFX11::Create(GSDevice11* dev)
bd.Usage = D3D11_USAGE_DEFAULT;
bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
hr = (*m_dev)->CreateBuffer(&bd, NULL, &m_vs_cb);
hr = (*(GSDevice11*)dev)->CreateBuffer(&bd, NULL, &m_vs_cb);
if(FAILED(hr)) return false;
@ -60,7 +56,7 @@ bool GSTextureFX11::Create(GSDevice11* dev)
bd.Usage = D3D11_USAGE_DEFAULT;
bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
hr = (*m_dev)->CreateBuffer(&bd, NULL, &m_ps_cb);
hr = (*(GSDevice11*)dev)->CreateBuffer(&bd, NULL, &m_ps_cb);
if(FAILED(hr)) return false;
@ -76,7 +72,7 @@ bool GSTextureFX11::Create(GSDevice11* dev)
sd.MaxAnisotropy = 16;
sd.ComparisonFunc = D3D11_COMPARISON_NEVER;
hr = (*m_dev)->CreateSamplerState(&sd, &m_palette_ss);
hr = (*(GSDevice11*)dev)->CreateSamplerState(&sd, &m_palette_ss);
if(FAILED(hr)) return false;
@ -85,17 +81,19 @@ bool GSTextureFX11::Create(GSDevice11* dev)
return true;
}
bool GSTextureFX11::SetupIA(const GSVertexHW11* vertices, int count, D3D11_PRIMITIVE_TOPOLOGY prim)
void GSTextureFX11::SetupIA(const void* vertices, int count, int prim)
{
m_dev->IASetVertexBuffer(vertices, sizeof(vertices[0]), count);
m_dev->IASetInputLayout(m_il);
m_dev->IASetPrimitiveTopology(prim);
GSDevice11* dev = (GSDevice11*)m_dev;
return true;
dev->IASetVertexBuffer(vertices, sizeof(GSVertexHW11), count);
dev->IASetInputLayout(m_il);
dev->IASetPrimitiveTopology((D3D11_PRIMITIVE_TOPOLOGY)prim);
}
bool GSTextureFX11::SetupVS(VSSelector sel, const VSConstantBuffer* cb)
void GSTextureFX11::SetupVS(VSSelector sel, const VSConstantBuffer* cb)
{
GSDevice11* dev = (GSDevice11*)m_dev;
hash_map<uint32, CComPtr<ID3D11VertexShader> >::const_iterator i = m_vs.find(sel);
if(i == m_vs.end())
@ -129,7 +127,7 @@ bool GSTextureFX11::SetupVS(VSSelector sel, const VSConstantBuffer* cb)
CComPtr<ID3D11InputLayout> il;
CComPtr<ID3D11VertexShader> vs;
m_dev->CompileShader(IDR_TFX_FX, "vs_main", macro, &vs, layout, countof(layout), &il);
dev->CompileShader(IDR_TFX_FX, "vs_main", macro, &vs, layout, countof(layout), &il);
if(m_il == NULL)
{
@ -143,19 +141,17 @@ bool GSTextureFX11::SetupVS(VSSelector sel, const VSConstantBuffer* cb)
if(m_vs_cb_cache.Update(cb))
{
ID3D11DeviceContext* ctx = *m_dev;
ID3D11DeviceContext* ctx = *dev;
ctx->UpdateSubresource(m_vs_cb, 0, NULL, cb, 0, 0);
}
m_dev->VSSetShader((*i).second, m_vs_cb);
return true;
dev->VSSetShader(i->second, m_vs_cb);
}
bool GSTextureFX11::SetupGS(GSSelector sel)
void GSTextureFX11::SetupGS(GSSelector sel)
{
HRESULT hr;
GSDevice11* dev = (GSDevice11*)m_dev;
ID3D11GeometryShader* gs = NULL;
@ -165,7 +161,7 @@ bool GSTextureFX11::SetupGS(GSSelector sel)
if(i != m_gs.end())
{
gs = (*i).second;
gs = i->second;
}
else
{
@ -181,29 +177,25 @@ bool GSTextureFX11::SetupGS(GSSelector sel)
{NULL, NULL},
};
hr = m_dev->CompileShader(IDR_TFX_FX, "gs_main", macro, &gs);
dev->CompileShader(IDR_TFX_FX, "gs_main", macro, &gs);
m_gs[sel] = gs;
}
}
m_dev->GSSetShader(gs);
return true;
dev->GSSetShader(gs);
}
bool GSTextureFX11::SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSelector ssel, GSTexture* tex, GSTexture* pal)
void GSTextureFX11::SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSelector ssel, GSTexture* tex, GSTexture* pal)
{
m_dev->PSSetShaderResources(tex, pal);
((GSDevice11*)m_dev)->PSSetShaderResources(tex, pal);
UpdatePS(sel, cb, ssel);
return true;
}
void GSTextureFX11::UpdatePS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSelector ssel)
{
HRESULT hr;
GSDevice11* dev = (GSDevice11*)m_dev;
hash_map<uint32, CComPtr<ID3D11PixelShader> >::const_iterator i = m_ps.find(sel);
@ -247,7 +239,7 @@ void GSTextureFX11::UpdatePS(PSSelector sel, const PSConstantBuffer* cb, PSSampl
CComPtr<ID3D11PixelShader> ps;
hr = m_dev->CompileShader(IDR_TFX_FX, "ps_main", macro, &ps);
dev->CompileShader(IDR_TFX_FX, "ps_main", macro, &ps);
m_ps[sel] = ps;
@ -256,12 +248,12 @@ void GSTextureFX11::UpdatePS(PSSelector sel, const PSConstantBuffer* cb, PSSampl
if(m_ps_cb_cache.Update(cb))
{
ID3D11DeviceContext* ctx = *m_dev;
ID3D11DeviceContext* ctx = *dev;
ctx->UpdateSubresource(m_ps_cb, 0, NULL, cb, 0, 0);
}
m_dev->PSSetShader((*i).second, m_ps_cb);
dev->PSSetShader(i->second, m_ps_cb);
ID3D11SamplerState* ss0 = NULL;
ID3D11SamplerState* ss1 = NULL;
@ -277,7 +269,7 @@ void GSTextureFX11::UpdatePS(PSSelector sel, const PSConstantBuffer* cb, PSSampl
if(i != m_ps_ss.end())
{
ss0 = (*i).second;
ss0 = i->second;
}
else
{
@ -295,7 +287,7 @@ void GSTextureFX11::UpdatePS(PSSelector sel, const PSConstantBuffer* cb, PSSampl
sd.MaxAnisotropy = 16;
sd.ComparisonFunc = D3D11_COMPARISON_NEVER;
hr = (*m_dev)->CreateSamplerState(&sd, &ss0);
(*dev)->CreateSamplerState(&sd, &ss0);
m_ps_ss[ssel] = ss0;
}
@ -306,24 +298,24 @@ void GSTextureFX11::UpdatePS(PSSelector sel, const PSConstantBuffer* cb, PSSampl
}
}
m_dev->PSSetSamplerState(ss0, ss1);
dev->PSSetSamplerState(ss0, ss1);
}
void GSTextureFX11::SetupRS(int w, int h, const GSVector4i& scissor)
{
m_dev->RSSet(w, h, &scissor);
((GSDevice11*)m_dev)->RSSet(w, h, &scissor);
}
void GSTextureFX11::SetupOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, float bf, GSTexture* rt, GSTexture* ds)
void GSTextureFX11::SetupOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, uint8 afix, GSTexture* rt, GSTexture* ds)
{
UpdateOM(dssel, bsel, bf);
UpdateOM(dssel, bsel, afix);
m_dev->OMSetRenderTargets(rt, ds);
((GSDevice11*)m_dev)->OMSetRenderTargets(rt, ds);
}
void GSTextureFX11::UpdateOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, float bf)
void GSTextureFX11::UpdateOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, uint8 afix)
{
HRESULT hr;
GSDevice11* dev = (GSDevice11*)m_dev;
hash_map<uint32, CComPtr<ID3D11DepthStencilState> >::const_iterator i = m_om_dss.find(dssel);
@ -365,14 +357,14 @@ void GSTextureFX11::UpdateOM(OMDepthStencilSelector dssel, OMBlendSelector bsel,
CComPtr<ID3D11DepthStencilState> dss;
hr = (*m_dev)->CreateDepthStencilState(&dsd, &dss);
(*dev)->CreateDepthStencilState(&dsd, &dss);
m_om_dss[dssel] = dss;
i = m_om_dss.find(dssel);
}
m_dev->OMSetDepthStencilState((*i).second, 1);
dev->OMSetDepthStencilState(i->second, 1);
hash_map<uint32, CComPtr<ID3D11BlendState> >::const_iterator j = m_om_bs.find(bsel);
@ -506,12 +498,12 @@ void GSTextureFX11::UpdateOM(OMDepthStencilSelector dssel, OMBlendSelector bsel,
CComPtr<ID3D11BlendState> bs;
hr = (*m_dev)->CreateBlendState(&bd, &bs);
(*dev)->CreateBlendState(&bd, &bs);
m_om_bs[bsel] = bs;
j = m_om_bs.find(bsel);
}
m_dev->OMSetBlendState((*j).second, bf);
dev->OMSetBlendState(j->second, (float)(int)afix / 0x80);
}

View File

@ -26,7 +26,6 @@
class GSTextureFX11 : public GSTextureFX
{
GSDevice11* m_dev;
CComPtr<ID3D11InputLayout> m_il;
hash_map<uint32, CComPtr<ID3D11VertexShader> > m_vs;
CComPtr<ID3D11Buffer> m_vs_cb;
@ -44,14 +43,14 @@ class GSTextureFX11 : public GSTextureFX
public:
GSTextureFX11();
bool Create(GSDevice11* dev);
bool Create(GSDevice* dev);
bool SetupIA(const GSVertexHW11* vertices, int count, D3D11_PRIMITIVE_TOPOLOGY prim);
bool SetupVS(VSSelector sel, const VSConstantBuffer* cb);
bool SetupGS(GSSelector sel);
bool SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSelector ssel, GSTexture* tex, GSTexture* pal);
void SetupIA(const void* vertices, int count, int prim);
void SetupVS(VSSelector sel, const VSConstantBuffer* cb);
void SetupGS(GSSelector sel);
void SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSelector ssel, GSTexture* tex, GSTexture* pal);
void UpdatePS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSelector ssel);
void SetupRS(int w, int h, const GSVector4i& scissor);
void SetupOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, float bf, GSTexture* rt, GSTexture* ds);
void UpdateOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, float bf);
void SetupOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, uint8 afix, GSTexture* rt, GSTexture* ds);
void UpdateOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, uint8 afix);
};

View File

@ -24,19 +24,24 @@
#include "resource.h"
GSTextureFX9::GSTextureFX9()
: m_dev(NULL)
{
}
bool GSTextureFX9::Create(GSDevice9* dev)
bool GSTextureFX9::Create(GSDevice* dev)
{
m_dev = dev;
if(!__super::Create(dev))
{
return false;
}
// create layout
VSSelector sel;
VSConstantBuffer cb;
SetupVS(sel, &cb); // creates layout
SetupVS(sel, &cb);
//
return true;
}
@ -51,7 +56,7 @@ GSTexture* GSTextureFX9::CreateMskFix(uint32 size, uint32 msk, uint32 fix)
if(i != m_mskfix.end())
{
t = (*i).second;
t = i->second;
}
else
{
@ -78,17 +83,19 @@ GSTexture* GSTextureFX9::CreateMskFix(uint32 size, uint32 msk, uint32 fix)
return t;
}
bool GSTextureFX9::SetupIA(const GSVertexHW9* vertices, int count, D3DPRIMITIVETYPE prim)
void GSTextureFX9::SetupIA(const void* vertices, int count, int prim)
{
m_dev->IASetVertexBuffer(vertices, sizeof(vertices[0]), count);
m_dev->IASetInputLayout(m_il);
m_dev->IASetPrimitiveTopology(prim);
GSDevice9* dev = (GSDevice9*)m_dev;
return true;
dev->IASetVertexBuffer(vertices, sizeof(GSVertexHW9), count);
dev->IASetInputLayout(m_il);
dev->IASetPrimitiveTopology((D3DPRIMITIVETYPE)prim);
}
bool GSTextureFX9::SetupVS(VSSelector sel, const VSConstantBuffer* cb)
void GSTextureFX9::SetupVS(VSSelector sel, const VSConstantBuffer* cb)
{
GSDevice9* dev = (GSDevice9*)m_dev;
hash_map<uint32, CComPtr<IDirect3DVertexShader9> >::const_iterator i = m_vs.find(sel);
if(i == m_vs.end())
@ -121,7 +128,7 @@ bool GSTextureFX9::SetupVS(VSSelector sel, const VSConstantBuffer* cb)
CComPtr<IDirect3DVertexDeclaration9> il;
CComPtr<IDirect3DVertexShader9> vs;
m_dev->CompileShader(IDR_TFX_FX, "vs_main", macro, &vs, layout, countof(layout), &il);
dev->CompileShader(IDR_TFX_FX, "vs_main", macro, &vs, layout, countof(layout), &il);
if(m_il == NULL)
{
@ -133,14 +140,14 @@ bool GSTextureFX9::SetupVS(VSSelector sel, const VSConstantBuffer* cb)
i = m_vs.find(sel);
}
m_dev->VSSetShader((*i).second, (const float*)cb, sizeof(*cb) / sizeof(GSVector4));
return true;
dev->VSSetShader(i->second, (const float*)cb, sizeof(*cb) / sizeof(GSVector4));
}
bool GSTextureFX9::SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSelector ssel, GSTexture* tex, GSTexture* pal)
void GSTextureFX9::SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSelector ssel, GSTexture* tex, GSTexture* pal)
{
m_dev->PSSetShaderResources(tex, pal);
GSDevice9* dev = (GSDevice9*)m_dev;
dev->PSSetShaderResources(tex, pal);
if(tex && (sel.wms == 3 || sel.wmt == 3))
{
@ -148,7 +155,7 @@ bool GSTextureFX9::SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSampler
{
if(GSTexture* t = CreateMskFix(tex->GetWidth(), cb->MskFix.x, cb->MskFix.z))
{
(*m_dev)->SetTexture(2, *(GSTexture9*)t);
(*dev)->SetTexture(2, *(GSTexture9*)t);
}
}
@ -156,19 +163,17 @@ bool GSTextureFX9::SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSampler
{
if(GSTexture* t = CreateMskFix(tex->GetHeight(), cb->MskFix.y, cb->MskFix.w))
{
(*m_dev)->SetTexture(3, *(GSTexture9*)t);
(*dev)->SetTexture(3, *(GSTexture9*)t);
}
}
}
UpdatePS(sel, cb, ssel);
return true;
}
void GSTextureFX9::UpdatePS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSelector ssel)
{
HRESULT hr;
GSDevice9* dev = (GSDevice9*)m_dev;
hash_map<uint32, CComPtr<IDirect3DPixelShader9> >::const_iterator i = m_ps.find(sel);
@ -210,14 +215,14 @@ void GSTextureFX9::UpdatePS(PSSelector sel, const PSConstantBuffer* cb, PSSample
CComPtr<IDirect3DPixelShader9> ps;
hr = m_dev->CompileShader(IDR_TFX_FX, "ps_main", macro, &ps);
dev->CompileShader(IDR_TFX_FX, "ps_main", macro, &ps);
m_ps[sel] = ps;
i = m_ps.find(sel);
}
m_dev->PSSetShader((*i).second, (const float*)cb, sizeof(*cb) / sizeof(GSVector4));
dev->PSSetShader(i->second, (const float*)cb, sizeof(*cb) / sizeof(GSVector4));
Direct3DSamplerState9* ss = NULL;
@ -232,7 +237,7 @@ void GSTextureFX9::UpdatePS(PSSelector sel, const PSConstantBuffer* cb, PSSample
if(i != m_ps_ss.end())
{
ss = (*i).second;
ss = i->second;
}
else
{
@ -252,23 +257,25 @@ void GSTextureFX9::UpdatePS(PSSelector sel, const PSConstantBuffer* cb, PSSample
}
}
m_dev->PSSetSamplerState(ss);
dev->PSSetSamplerState(ss);
}
void GSTextureFX9::SetupRS(int w, int h, const GSVector4i& scissor)
{
m_dev->RSSet(w, h, &scissor);
((GSDevice9*)m_dev)->RSSet(w, h, &scissor);
}
void GSTextureFX9::SetupOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, uint8 bf, GSTexture* rt, GSTexture* ds)
void GSTextureFX9::SetupOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, uint8 afix, GSTexture* rt, GSTexture* ds)
{
UpdateOM(dssel, bsel, bf);
UpdateOM(dssel, bsel, afix);
m_dev->OMSetRenderTargets(rt, ds);
((GSDevice9*)m_dev)->OMSetRenderTargets(rt, ds);
}
void GSTextureFX9::UpdateOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, uint8 bf)
void GSTextureFX9::UpdateOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, uint8 afix)
{
GSDevice9* dev = (GSDevice9*)m_dev;
Direct3DDepthStencilState9* dss = NULL;
hash_map<uint32, Direct3DDepthStencilState9*>::const_iterator i = m_om_dss.find(dssel);
@ -311,7 +318,7 @@ void GSTextureFX9::UpdateOM(OMDepthStencilSelector dssel, OMBlendSelector bsel,
i = m_om_dss.find(dssel);
}
m_dev->OMSetDepthStencilState((*i).second);
dev->OMSetDepthStencilState(i->second);
hash_map<uint32, Direct3DBlendState9*>::const_iterator j = m_om_bs.find(bsel);
@ -448,5 +455,5 @@ void GSTextureFX9::UpdateOM(OMDepthStencilSelector dssel, OMBlendSelector bsel,
j = m_om_bs.find(bsel);
}
m_dev->OMSetBlendState((*j).second, 0x010101 * bf);
dev->OMSetBlendState(j->second, afix >= 0x80 ? 0xffffff : 0x020202 * afix);
}

View File

@ -26,7 +26,6 @@
class GSTextureFX9 : public GSTextureFX
{
GSDevice9* m_dev;
CComPtr<IDirect3DVertexDeclaration9> m_il;
hash_map<uint32, CComPtr<IDirect3DVertexShader9> > m_vs;
D3DXHANDLE m_vs_params;
@ -41,13 +40,14 @@ class GSTextureFX9 : public GSTextureFX
public:
GSTextureFX9();
bool Create(GSDevice9* dev);
bool Create(GSDevice* dev);
bool SetupIA(const GSVertexHW9* vertices, int count, D3DPRIMITIVETYPE prim);
bool SetupVS(VSSelector sel, const VSConstantBuffer* cb);
bool SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSelector ssel, GSTexture* tex, GSTexture* pal);
void SetupIA(const void* vertices, int count, int prim);
void SetupVS(VSSelector sel, const VSConstantBuffer* cb);
void SetupGS(GSSelector sel) {}
void SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSelector ssel, GSTexture* tex, GSTexture* pal);
void UpdatePS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSelector ssel);
void SetupRS(int w, int h, const GSVector4i& scissor);
void SetupOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, uint8 bf, GSTexture* rt, GSTexture* ds);
void UpdateOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, uint8 bf);
void SetupOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, uint8 afix, GSTexture* rt, GSTexture* ds);
void UpdateOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, uint8 afix);
};

View File

@ -27,16 +27,16 @@ const GSVector4 GSVector4::m_ps4567(4.0f, 5.0f, 6.0f, 7.0f);
const GSVector4 GSVector4::m_x3f800000(_mm_castsi128_ps(_mm_set1_epi32(0x3f800000)));
const GSVector4 GSVector4::m_x4b000000(_mm_castsi128_ps(_mm_set1_epi32(0x4b000000)));
void GSVector4::operator = (const GSVector4i& v)
{
m = _mm_cvtepi32_ps(v);
}
void GSVector4i::operator = (const GSVector4& v)
GSVector4i::GSVector4i(const GSVector4& v)
{
m = _mm_cvttps_epi32(v);
}
GSVector4::GSVector4(const GSVector4i& v)
{
m = _mm_cvtepi32_ps(v);
}
GSVector4i GSVector4i::cast(const GSVector4& v)
{
return GSVector4i(_mm_castps_si128(v.m));

View File

@ -121,18 +121,13 @@ public:
this->m = m;
}
explicit GSVector4i(const GSVector4& v)
{
*this = v;
}
explicit GSVector4i(const GSVector4& v);
void operator = (const GSVector4i& v)
{
m = v.m;
}
void operator = (const GSVector4& v);
void operator = (int i)
{
m = _mm_set1_epi32(i);
@ -1822,6 +1817,11 @@ public:
GSVector4i* s = (GSVector4i*)src;
GSVector4i* d = (GSVector4i*)dst;
if(!d[0].eq(s[0]))
{
return false;
}
GSVector4i v = GSVector4i::xffffffff();
for(int i = 0; i < size; i++)
@ -2312,18 +2312,13 @@ public:
*this = GSVector4(GSVector4i::load((int)u32).u8to32());
}
explicit GSVector4(const GSVector4i& v)
{
*this = v;
}
explicit GSVector4(const GSVector4i& v);
void operator = (const GSVector4& v)
{
m = v.m;
}
void operator = (const GSVector4i& v);
void operator = (float f)
{
m = _mm_set1_ps(f);
@ -2625,10 +2620,10 @@ public:
{
GSVector4i mask = GSVector4i::x000000ff();
a = v & mask;
b = (v >> 8) & mask;
c = (v >> 16) & mask;
d = (v >> 24);
a = GSVector4(v & mask);
b = GSVector4((v >> 8) & mask);
c = GSVector4((v >> 16) & mask);
d = GSVector4((v >> 24));
}
__forceinline static void transpose(GSVector4& a, GSVector4& b, GSVector4& c, GSVector4& d)

View File

@ -30,9 +30,21 @@ __declspec(align(16)) union GSVertexHW9
{
struct
{
GSVector2 t;
union {struct {uint8 r, g, b, a;}; uint32 c0;};
union {struct {uint8 ta0, ta1, res, f;}; uint32 c1;};
union
{
struct
{
GSVector4 t;
};
struct
{
uint32 _pad[2];
union {struct {uint8 r, g, b, a;}; uint32 c0;};
union {struct {uint8 ta0, ta1, res, f;}; uint32 c1;};
};
};
GSVector4 p;
};

View File

@ -1276,54 +1276,58 @@
RelativePath=".\GSRenderer.cpp"
>
</File>
<File
RelativePath=".\GSRendererDX.cpp"
>
</File>
<File
RelativePath=".\GSRendererDX10.cpp"
>
<FileConfiguration
Name="Release SSE2|Win32"
>
<Tool
Name="VCCLCompilerTool"
AssemblerOutput="4"
/>
</FileConfiguration>
<FileConfiguration
Name="Release SSSE3|Win32"
>
<Tool
Name="VCCLCompilerTool"
AssemblerOutput="4"
/>
</FileConfiguration>
</File>
<File
RelativePath=".\GSRendererDX11.cpp"
>
</File>
<File
RelativePath=".\GSRendererDX9.cpp"
>
<FileConfiguration
Name="Release SSE2|Win32"
>
<Tool
Name="VCCLCompilerTool"
AssemblerOutput="4"
/>
</FileConfiguration>
<FileConfiguration
Name="Release SSSE3|Win32"
>
<Tool
Name="VCCLCompilerTool"
AssemblerOutput="4"
/>
</FileConfiguration>
</File>
<File
RelativePath=".\GSRendererHW.cpp"
>
</File>
<File
RelativePath=".\GSRendererHW10.cpp"
>
<FileConfiguration
Name="Release SSE2|Win32"
>
<Tool
Name="VCCLCompilerTool"
AssemblerOutput="4"
/>
</FileConfiguration>
<FileConfiguration
Name="Release SSSE3|Win32"
>
<Tool
Name="VCCLCompilerTool"
AssemblerOutput="4"
/>
</FileConfiguration>
</File>
<File
RelativePath=".\GSRendererHW11.cpp"
>
</File>
<File
RelativePath=".\GSRendererHW9.cpp"
>
<FileConfiguration
Name="Release SSE2|Win32"
>
<Tool
Name="VCCLCompilerTool"
AssemblerOutput="4"
/>
</FileConfiguration>
<FileConfiguration
Name="Release SSSE3|Win32"
>
<Tool
Name="VCCLCompilerTool"
AssemblerOutput="4"
/>
</FileConfiguration>
</File>
<File
RelativePath=".\GSRendererNull.cpp"
>
@ -1790,22 +1794,26 @@
RelativePath=".\GSRenderer.h"
>
</File>
<File
RelativePath=".\GSRendererDX.h"
>
</File>
<File
RelativePath=".\GSRendererDX10.h"
>
</File>
<File
RelativePath=".\GSRendererDX11.h"
>
</File>
<File
RelativePath=".\GSRendererDX9.h"
>
</File>
<File
RelativePath=".\GSRendererHW.h"
>
</File>
<File
RelativePath=".\GSRendererHW10.h"
>
</File>
<File
RelativePath=".\GSRendererHW11.h"
>
</File>
<File
RelativePath=".\GSRendererHW9.h"
>
</File>
<File
RelativePath=".\GSRendererNull.h"
>

View File

@ -1320,9 +1320,9 @@
<ClCompile Include="GSRasterizer.cpp" />
<ClCompile Include="GSRenderer.cpp" />
<ClCompile Include="GSRendererHW.cpp" />
<ClCompile Include="GSRendererHW10.cpp" />
<ClCompile Include="GSRendererHW11.cpp" />
<ClCompile Include="GSRendererHW9.cpp" />
<ClCompile Include="GSRendererDX10.cpp" />
<ClCompile Include="GSRendererDX11.cpp" />
<ClCompile Include="GSRendererDX9.cpp" />
<ClCompile Include="GSRendererNull.cpp" />
<ClCompile Include="GSRendererOGL.cpp" />
<ClCompile Include="GSRendererSW.cpp" />
@ -1445,9 +1445,9 @@
<ClInclude Include="GSRasterizer.h" />
<ClInclude Include="GSRenderer.h" />
<ClInclude Include="GSRendererHW.h" />
<ClInclude Include="GSRendererHW10.h" />
<ClInclude Include="GSRendererHW11.h" />
<ClInclude Include="GSRendererHW9.h" />
<ClInclude Include="GSRendererDX10.h" />
<ClInclude Include="GSRendererDX11.h" />
<ClInclude Include="GSRendererDX9.h" />
<ClInclude Include="GSRendererNull.h" />
<ClInclude Include="GSRendererOGL.h" />
<ClInclude Include="GSRendererSW.h" />

View File

@ -201,13 +201,13 @@
<ClCompile Include="GSRendererHW.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GSRendererHW10.cpp">
<ClCompile Include="GSRendererDX10.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GSRendererHW11.cpp">
<ClCompile Include="GSRendererDX11.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GSRendererHW9.cpp">
<ClCompile Include="GSRendererDX9.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GSRendererNull.cpp">
@ -521,13 +521,13 @@
<ClInclude Include="GSRendererHW.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GSRendererHW10.h">
<ClInclude Include="GSRendererDX10.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GSRendererHW11.h">
<ClInclude Include="GSRendererDX11.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GSRendererHW9.h">
<ClInclude Include="GSRendererDX9.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GSRendererNull.h">

View File

@ -76,10 +76,10 @@ cbuffer cb1
float3 FogColor;
float AREF;
float4 HalfTexel;
float2 WH;
float2 TA;
float4 WH;
float4 MinMax;
float4 MinMaxF;
float2 MinF;
float2 TA;
uint4 MskFix;
};
@ -145,11 +145,11 @@ float4 ps_params[5];
#define FogColor ps_params[0].bgr
#define AREF ps_params[0].a
#define HalfTexel ps_params[1]
#define WH ps_params[2].xy
#define TA0 ps_params[2].z
#define TA1 ps_params[2].w
#define WH ps_params[2]
#define MinMax ps_params[3]
#define MinMaxF ps_params[4]
#define MinF ps_params[4].xy
#define TA0 ps_params[4].z
#define TA1 ps_params[4].w
#endif
@ -198,7 +198,7 @@ float4 wrapuv(float4 uv)
else if(PS_WMS == 3)
{
#if SHADER_MODEL >= 0x400
uv.xz = (float2)(((int2)(uv * WH.xyxy).xz & MskFix.xx) | MskFix.zz) / WH;
uv.xz = (float2)(((int2)(uv * WH.xyxy).xz & MskFix.xx) | MskFix.zz) / WH.xy;
#elif SHADER_MODEL <= 0x300
uv.x = tex1D(UMSKFIX, uv.x);
uv.z = tex1D(UMSKFIX, uv.z);
@ -220,7 +220,7 @@ float4 wrapuv(float4 uv)
else if(PS_WMT == 3)
{
#if SHADER_MODEL >= 0x400
uv.yw = (float2)(((int2)(uv * WH.xyxy).yw & MskFix.yy) | MskFix.ww) / WH;
uv.yw = (float2)(((int2)(uv * WH.xyxy).yw & MskFix.yy) | MskFix.ww) / WH.xy;
#elif SHADER_MODEL <= 0x300
uv.y = tex1D(VMSKFIX, uv.y);
uv.w = tex1D(VMSKFIX, uv.w);
@ -235,15 +235,15 @@ float2 clampuv(float2 uv)
{
if(PS_WMS == 2 && PS_WMT == 2)
{
uv = clamp(uv, MinMaxF.xy, MinMaxF.zw);
uv = clamp(uv, MinF, MinMax.zw);
}
else if(PS_WMS == 2)
{
uv.x = clamp(uv.x, MinMaxF.x, MinMaxF.z);
uv.x = clamp(uv.x, MinF.x, MinMax.z);
}
else if(PS_WMT == 2)
{
uv.y = clamp(uv.y, MinMaxF.y, MinMaxF.w);
uv.y = clamp(uv.y, MinF.y, MinMax.w);
}
return uv;
@ -476,7 +476,7 @@ float4 sample(float2 tc, float w)
Texture.GetDimensions(w, h);
float4 uv2 = tc.xyxy + HalfTexel;
float2 dd = frac(uv2.xy * float2(w, h));
float2 dd = frac(uv2.xy * float2(w, h)); // * WH.zw
float4 uv = wrapuv(uv2);
float4 t00, t01, t10, t11;
@ -637,7 +637,7 @@ float4 sample(float2 tc, float w)
else
{
float4 uv2 = tc.xyxy + HalfTexel;
float2 dd = frac(uv2.xy * WH);
float2 dd = frac(uv2.xy * WH.zw);
float4 uv = wrapuv(uv2);
float4 t00, t01, t10, t11;