mirror of https://github.com/PCSX2/pcsx2.git
gsdx: new generic OI hack
To clear a (W, H) RT/Depth, GS can only send a (W , H/2) primitive with a Z (or RT) pointer in the middle of the buffer Top-half will be cleared by the color (or the depth). Bottom-half will be cleared by the depth (or the color). Code isn't enabled yet but it was tested with success on GoW2.
This commit is contained in:
parent
42e911c78f
commit
33c9e9da0a
|
@ -345,6 +345,7 @@ void GSRendererHW::Draw()
|
||||||
TEX0.PSM = context->FRAME.PSM;
|
TEX0.PSM = context->FRAME.PSM;
|
||||||
|
|
||||||
GSTextureCache::Target* rt = no_rt ? NULL : m_tc->LookupTarget(TEX0, m_width, m_height, GSTextureCache::RenderTarget, true);
|
GSTextureCache::Target* rt = no_rt ? NULL : m_tc->LookupTarget(TEX0, m_width, m_height, GSTextureCache::RenderTarget, true);
|
||||||
|
GSTexture* rt_tex = rt ? rt->m_texture : NULL;
|
||||||
|
|
||||||
TEX0.TBP0 = context->ZBUF.Block();
|
TEX0.TBP0 = context->ZBUF.Block();
|
||||||
TEX0.TBW = context->FRAME.FBW;
|
TEX0.TBW = context->FRAME.FBW;
|
||||||
|
@ -453,7 +454,7 @@ void GSRendererHW::Draw()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_hacks.m_oi && !(this->*m_hacks.m_oi)(NULL, ds->m_texture, tex))
|
if(m_hacks.m_oi && !(this->*m_hacks.m_oi)(rt_tex, ds->m_texture, tex))
|
||||||
{
|
{
|
||||||
s_n += 1; // keep counter sync
|
s_n += 1; // keep counter sync
|
||||||
GL_POP();
|
GL_POP();
|
||||||
|
@ -520,7 +521,7 @@ void GSRendererHW::Draw()
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
DrawPrims(rt ? rt->m_texture : NULL, ds->m_texture, tex);
|
DrawPrims(rt_tex, ds->m_texture, tex);
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
|
@ -644,12 +645,67 @@ void GSRendererHW::Hacks::SetGameCRC(const CRC::Game& game)
|
||||||
m_oo = m_oo_map[hash];
|
m_oo = m_oo_map[hash];
|
||||||
m_cu = m_cu_map[hash];
|
m_cu = m_cu_map[hash];
|
||||||
|
|
||||||
if(game.flags & CRC::PointListPalette)
|
if (game.flags & CRC::PointListPalette) {
|
||||||
{
|
|
||||||
ASSERT(m_oi == NULL);
|
ASSERT(m_oi == NULL);
|
||||||
|
|
||||||
m_oi = &GSRendererHW::OI_PointListPalette;
|
m_oi = &GSRendererHW::OI_PointListPalette;
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
|
// FIXME: Enable this code in the future. I think it could replace
|
||||||
|
// most of the "old" OI hack. So far code was tested on GoW2 & SimpsonsGame with
|
||||||
|
// success
|
||||||
|
if (m_oi == NULL) {
|
||||||
|
m_oi = &GSRendererHW::OI_DoubleHalfClear;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GSRendererHW::OI_DoubleHalfClear(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t)
|
||||||
|
{
|
||||||
|
if (m_vt.m_primclass == GS_SPRITE_CLASS && !PRIM->TME && !m_context->ZBUF.ZMSK && (m_context->FRAME.FBW >= 7)) {
|
||||||
|
GSVertex* v = &m_vertex.buff[0];
|
||||||
|
|
||||||
|
//GL_INS("OI_DoubleHalfClear: psm:%x. Z:%d R:%d G:%d B:%d A:%d", m_context->FRAME.PSM,
|
||||||
|
// v[1].XYZ.Z, v[1].RGBAQ.R, v[1].RGBAQ.G, v[1].RGBAQ.B, v[1].RGBAQ.A);
|
||||||
|
|
||||||
|
// Check it is a clear on the first primitive only
|
||||||
|
if (v[1].XYZ.Z || v[1].RGBAQ.R || v[1].RGBAQ.G || v[1].RGBAQ.B || v[1].RGBAQ.A) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Only 32 bits format is supported otherwise it is complicated
|
||||||
|
if (m_context->FRAME.PSM & 2)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// FIXME might need some rounding
|
||||||
|
// In 32 bits pages are 64x32 pixels. In theory, it must be somethings
|
||||||
|
// like FBW * 64 pixels * ratio / 32 pixels / 2 = FBW * ratio
|
||||||
|
// It is hard to predict the ratio, so I round it to 1. And I use
|
||||||
|
// <= comparison below.
|
||||||
|
uint32 h_pages = m_context->FRAME.FBW;
|
||||||
|
|
||||||
|
uint32 base;
|
||||||
|
uint32 half;
|
||||||
|
if (m_context->FRAME.FBP > m_context->ZBUF.ZBP) {
|
||||||
|
base = m_context->ZBUF.ZBP;
|
||||||
|
half = m_context->FRAME.FBP;
|
||||||
|
} else {
|
||||||
|
base = m_context->FRAME.FBP;
|
||||||
|
half = m_context->ZBUF.ZBP;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (half <= (base + h_pages * m_context->FRAME.FBW)) {
|
||||||
|
//GL_INS("OI_DoubleHalfClear: base %x half %x. h_pages %d fbw %d", base, half, h_pages, m_context->FRAME.FBW);
|
||||||
|
if (m_context->FRAME.FBP > m_context->ZBUF.ZBP) {
|
||||||
|
m_dev->ClearDepth(ds, 0);
|
||||||
|
} else {
|
||||||
|
m_dev->ClearRenderTarget(rt, 0);
|
||||||
|
}
|
||||||
|
// Don't return false, it will break the rendering. I guess that it misses texture
|
||||||
|
// invalidation
|
||||||
|
//return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// OI (others input?/implementation?) hacks replace current draw call
|
// OI (others input?/implementation?) hacks replace current draw call
|
||||||
|
|
|
@ -46,6 +46,7 @@ private:
|
||||||
typedef void (GSRendererHW::*OO_Ptr)();
|
typedef void (GSRendererHW::*OO_Ptr)();
|
||||||
typedef bool (GSRendererHW::*CU_Ptr)();
|
typedef bool (GSRendererHW::*CU_Ptr)();
|
||||||
|
|
||||||
|
bool OI_DoubleHalfClear(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t);
|
||||||
bool OI_FFXII(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t);
|
bool OI_FFXII(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t);
|
||||||
bool OI_FFX(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t);
|
bool OI_FFX(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t);
|
||||||
bool OI_MetalSlug6(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t);
|
bool OI_MetalSlug6(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t);
|
||||||
|
|
Loading…
Reference in New Issue