mirror of https://github.com/PCSX2/pcsx2.git
GS/HW: Make Haunting Ground render fix invalidate depth as well
Fixes depth leaking into the image.
This commit is contained in:
parent
9d1c60239e
commit
85b41e23f0
|
@ -196,6 +196,16 @@ u32 GSUtil::GetChannelMask(u32 spsm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 GSUtil::GetChannelMask(u32 spsm, u32 fbmsk)
|
||||||
|
{
|
||||||
|
u32 mask = GetChannelMask(spsm);
|
||||||
|
mask &= (fbmsk & 0xFF) ? (~0x1 & 0xf) : 0xf;
|
||||||
|
mask &= (fbmsk & 0xFF00) ? (~0x2 & 0xf) : 0xf;
|
||||||
|
mask &= (fbmsk & 0xFF0000) ? (~0x4 & 0xf) : 0xf;
|
||||||
|
mask &= (fbmsk & 0xFF000000) ? (~0x8 & 0xf) : 0xf;
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
|
||||||
GSRendererType GSUtil::GetPreferredRenderer()
|
GSRendererType GSUtil::GetPreferredRenderer()
|
||||||
{
|
{
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
|
|
|
@ -34,6 +34,7 @@ public:
|
||||||
static bool HasCompatibleBits(u32 spsm, u32 dpsm);
|
static bool HasCompatibleBits(u32 spsm, u32 dpsm);
|
||||||
static bool HasSameSwizzleBits(u32 spsm, u32 dpsm);
|
static bool HasSameSwizzleBits(u32 spsm, u32 dpsm);
|
||||||
static u32 GetChannelMask(u32 spsm);
|
static u32 GetChannelMask(u32 spsm);
|
||||||
|
static u32 GetChannelMask(u32 spsm, u32 fbmsk);
|
||||||
|
|
||||||
static GSRendererType GetPreferredRenderer();
|
static GSRendererType GetPreferredRenderer();
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
union RGBAMask
|
union RGBAMask
|
||||||
{
|
{
|
||||||
|
u32 _u32;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
u32 r : 1;
|
u32 r : 1;
|
||||||
|
@ -26,7 +27,6 @@ union RGBAMask
|
||||||
u32 b : 1;
|
u32 b : 1;
|
||||||
u32 a : 1;
|
u32 a : 1;
|
||||||
} c;
|
} c;
|
||||||
u32 _u32;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class GSDirtyRect
|
class GSDirtyRect
|
||||||
|
|
|
@ -971,12 +971,67 @@ bool GSHwHack::OI_Battlefield2(GSRendererHW& r, GSTexture* rt, GSTexture* ds, GS
|
||||||
|
|
||||||
bool GSHwHack::OI_HauntingGround(GSRendererHW& r, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t)
|
bool GSHwHack::OI_HauntingGround(GSRendererHW& r, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t)
|
||||||
{
|
{
|
||||||
// Haunting Ground clears two targets by doing a 256x448 direct colour write at 0x3000, covering a target at 0x3380.
|
// Haunting Ground clears two targets by doing a direct colour write at 0x3000, covering a target at 0x3380.
|
||||||
// This currently isn't handled in our HLE clears, so we need to manually remove the other target.
|
// To make matters worse, it's masked. This currently isn't handled in our HLE clears, so we need to manually
|
||||||
|
// remove the other target.
|
||||||
if (rt && !ds && !t && r.IsConstantDirectWriteMemClear())
|
if (rt && !ds && !t && r.IsConstantDirectWriteMemClear())
|
||||||
{
|
{
|
||||||
GL_CACHE("GSHwHack::OI_HauntingGround()");
|
GL_CACHE("GSHwHack::OI_HauntingGround()");
|
||||||
g_texture_cache->InvalidateVideoMemTargets(GSTextureCache::RenderTarget, RFRAME.Block(), RFRAME.FBW, RFRAME.PSM, r.m_r);
|
|
||||||
|
const u32 bp = RFBP;
|
||||||
|
const u32 bw = RFBW;
|
||||||
|
const u32 psm = RFPSM;
|
||||||
|
const u32 fbmsk = RFBMSK;
|
||||||
|
const GSVector4i rc = r.m_r;
|
||||||
|
|
||||||
|
for (int type = 0; type < 2; type++)
|
||||||
|
{
|
||||||
|
auto& list = g_texture_cache->m_dst[type];
|
||||||
|
|
||||||
|
for (auto i = list.begin(); i != list.end();)
|
||||||
|
{
|
||||||
|
GSTextureCache::Target* t = *i;
|
||||||
|
auto ei = i++;
|
||||||
|
|
||||||
|
// There's two cases we hit here - when we clear 3380 via 3000, and when we overlap 3000 by writing to 3380.
|
||||||
|
// The latter is actually only 256x224, which ends at 337F, but because the game's a pain in the ass, it
|
||||||
|
// shuffles 512x512, causing the target to expand. It'd actually be shuffling junk and wasting draw cycles,
|
||||||
|
// but when did that stop anyone? So, we can get away with just saying "if it's before, ignore".
|
||||||
|
if (t->m_TEX0.TBP0 <= bp)
|
||||||
|
{
|
||||||
|
// don't remove ourself..
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Has to intersect.
|
||||||
|
if (!t->Overlaps(bp, bw, psm, rc))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Another annoying case. Sometimes it clears with RGB masked, only writing to A. We don't want to kill the
|
||||||
|
// target in this case, so we'll dirty A instead.
|
||||||
|
if (fbmsk != 0)
|
||||||
|
{
|
||||||
|
GL_CACHE("OI_HauntingGround(%x, %u, %s, %d,%d => %d,%d): Dirty target at %x %u %s %08X", bp, bw,
|
||||||
|
psm_str(psm), rc.x, rc.y, rc.z, rc.w, t->m_TEX0.TBP0, t->m_TEX0.TBW, psm_str(t->m_TEX0.PSM),
|
||||||
|
fbmsk);
|
||||||
|
|
||||||
|
g_texture_cache->AddDirtyRectTarget(t, rc, psm, bw, RGBAMask{GSUtil::GetChannelMask(psm, fbmsk)});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GL_CACHE("OI_HauntingGround(%x, %u, %s, %d,%d => %d,%d): Removing target at %x %u %s", bp, bw,
|
||||||
|
psm_str(psm), rc.x, rc.y, rc.z, rc.w, t->m_TEX0.TBP0, t->m_TEX0.TBW, psm_str(t->m_TEX0.PSM));
|
||||||
|
|
||||||
|
// Need to also remove any sources which reference this target.
|
||||||
|
g_texture_cache->InvalidateSourcesFromTarget(t);
|
||||||
|
|
||||||
|
list.erase(ei);
|
||||||
|
delete t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_texture_cache->InvalidateVideoMemType(GSTextureCache::DepthStencil, bp);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not skipping anything. This is just an invalidation hack.
|
// Not skipping anything. This is just an invalidation hack.
|
||||||
|
|
|
@ -2924,29 +2924,6 @@ void GSTextureCache::InvalidateVideoMemSubTarget(GSTextureCache::Target* rt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GSTextureCache::InvalidateVideoMemTargets(int type, u32 bp, u32 bw, u32 psm, const GSVector4i& r)
|
|
||||||
{
|
|
||||||
auto& list = m_dst[type];
|
|
||||||
|
|
||||||
for (auto i = list.begin(); i != list.end();)
|
|
||||||
{
|
|
||||||
GSTextureCache::Target* t = *i;
|
|
||||||
auto ei = i++;
|
|
||||||
|
|
||||||
if (t->m_TEX0.TBP0 != bp && t->Overlaps(bp, bw, psm, r))
|
|
||||||
{
|
|
||||||
GL_CACHE("InvalidateVideoMemTargets(%x, %u, %s, %d,%d => %d,%d): Removing target at %x %u %s", bp, bw,
|
|
||||||
psm_str(psm), r.x, r.y, r.z, r.w, t->m_TEX0.TBP0, t->m_TEX0.TBW, psm_str(t->m_TEX0.PSM));
|
|
||||||
|
|
||||||
// Need to also remove any sources which reference this target.
|
|
||||||
InvalidateSourcesFromTarget(t);
|
|
||||||
|
|
||||||
list.erase(ei);
|
|
||||||
delete t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GSTextureCache::InvalidateSourcesFromTarget(const Target* t)
|
void GSTextureCache::InvalidateSourcesFromTarget(const Target* t)
|
||||||
{
|
{
|
||||||
for (auto it = m_src.m_surfaces.begin(); it != m_src.m_surfaces.end();)
|
for (auto it = m_src.m_surfaces.begin(); it != m_src.m_surfaces.end();)
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
#include "GS/Renderers/Common/GSDirtyRect.h"
|
#include "GS/Renderers/Common/GSDirtyRect.h"
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
|
class GSHwHack;
|
||||||
|
|
||||||
// Only for debugging. Reads back every target to local memory after drawing, effectively
|
// Only for debugging. Reads back every target to local memory after drawing, effectively
|
||||||
// disabling caching between draws.
|
// disabling caching between draws.
|
||||||
//#define DISABLE_HW_TEXTURE_CACHE
|
//#define DISABLE_HW_TEXTURE_CACHE
|
||||||
|
@ -29,6 +31,8 @@
|
||||||
class GSTextureCache
|
class GSTextureCache
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
friend GSHwHack;
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
RenderTarget,
|
RenderTarget,
|
||||||
|
@ -467,9 +471,6 @@ public:
|
||||||
void InvalidateVideoMem(const GSOffset& off, const GSVector4i& r, bool eewrite = false, bool target = true);
|
void InvalidateVideoMem(const GSOffset& off, const GSVector4i& r, bool eewrite = false, bool target = true);
|
||||||
void InvalidateLocalMem(const GSOffset& off, const GSVector4i& r, bool full_flush = false);
|
void InvalidateLocalMem(const GSOffset& off, const GSVector4i& r, bool full_flush = false);
|
||||||
|
|
||||||
/// Removes any targets overlapping the specified BP and rectangle.
|
|
||||||
void InvalidateVideoMemTargets(int type, u32 bp, u32 bw, u32 psm, const GSVector4i& r);
|
|
||||||
|
|
||||||
/// Removes any sources which point to the specified target.
|
/// Removes any sources which point to the specified target.
|
||||||
void InvalidateSourcesFromTarget(const Target* t);
|
void InvalidateSourcesFromTarget(const Target* t);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue