Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GS/HW: Multiple fixes #10093

Merged
merged 4 commits into from
Oct 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions bin/resources/GameIndex.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32786,6 +32786,8 @@ SLPM-65080:
name: "Tokimeki Memorial 3"
region: "NTSC-J"
compat: 5
gsHWFixes:
textureInsideRT: 1 # Fixes character portraits.
SLPM-65081:
name: "Grandia II"
region: "NTSC-J"
Expand Down
22 changes: 8 additions & 14 deletions pcsx2/GS/Renderers/HW/GSRendererHW.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4210,10 +4210,10 @@ __ri void GSRendererHW::EmulateTextureSampler(const GSTextureCache::Target* rt,
m_conf.ps.wms = (wms & 2 || target_region) ? wms : 0;
m_conf.ps.wmt = (wmt & 2 || target_region) ? wmt : 0;

// Depth + bilinear filtering isn't done yet (And I'm not sure we need it anyway but a game will prove me wrong)
// So of course, GTA set the linear mode, but sampling is done at texel center so it is equivalent to nearest sampling
// Depth + bilinear filtering isn't done yet. But if the game has just set a Z24 swizzle on a colour texture, we can
// just pretend it's not a depth format, since in the texture cache, it's not.
// Other games worth testing: Area 51, Burnout
if (psm.depth && m_vt.IsLinear())
if (psm.depth && m_vt.IsLinear() && tex->GetTexture()->IsDepthStencil())
GL_INS("WARNING: Depth + bilinear filtering not supported");

// Performance note:
Expand Down Expand Up @@ -4293,22 +4293,14 @@ __ri void GSRendererHW::EmulateTextureSampler(const GSTextureCache::Target* rt,
}

// Depth format
if (tex->m_texture->GetType() == GSTexture::Type::DepthStencil)
if (tex->m_texture->IsDepthStencil())
{
// Require a float conversion if the texure is a depth format
m_conf.ps.depth_fmt = (psm.bpp == 16) ? 2 : 1;

// Don't force interpolation on depth format
bilinear &= m_vt.IsLinear();
}
else if (psm.depth)
{
// Use Integral scaling
m_conf.ps.depth_fmt = 3;

// Don't force interpolation on depth format
bilinear &= m_vt.IsLinear();
}

const GSVector4 half_pixel = RealignTargetTextureCoordinate(tex);
m_conf.cb_vs.texture_offset = GSVector2(half_pixel.x, half_pixel.y);
Expand Down Expand Up @@ -4384,9 +4376,11 @@ __ri void GSRendererHW::EmulateTextureSampler(const GSTextureCache::Target* rt,
m_conf.cb_ps.HalfTexel = GSVector4(-0.5f, 0.5f).xxyy() / WH.zwzw();
if (complex_wms_wmt)
{
// Add 0.5 to the coordinates because the region clamp is inclusive, size is exclusive. We use 0.5 because we want to clamp
// to the last texel in the image, not halfway between it and wrapping around.
const GSVector4i clamp(m_cached_ctx.CLAMP.MINU, m_cached_ctx.CLAMP.MINV, m_cached_ctx.CLAMP.MAXU, m_cached_ctx.CLAMP.MAXV);
const GSVector4 region_repeat(GSVector4::cast(clamp));
const GSVector4 region_clamp(GSVector4(clamp) / WH.xyxy());
const GSVector4 region_repeat = GSVector4::cast(clamp);
const GSVector4 region_clamp = (GSVector4(clamp) + GSVector4::cxpr(0.0f, 0.0f, 0.5f, 0.5f)) / WH.xyxy();
if (wms >= CLAMP_REGION_CLAMP)
{
m_conf.cb_ps.MinMax.x = (wms == CLAMP_REGION_CLAMP && !m_conf.ps.depth_fmt) ? region_clamp.x : region_repeat.x;
Expand Down
37 changes: 29 additions & 8 deletions pcsx2/GS/Renderers/HW/GSTextureCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1864,8 +1864,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
}
else if (!is_frame && !GSConfig.UserHacks_DisableDepthSupport)
{

int rev_type = (type == DepthStencil) ? RenderTarget : DepthStencil;
const int rev_type = (type == DepthStencil) ? RenderTarget : DepthStencil;

// Depth stencil/RT can be an older RT/DS but only check recent RT/DS to avoid to pick
// some bad data.
Expand All @@ -1878,13 +1877,35 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
if (bp != t->m_TEX0.TBP0 || !t->m_valid_rgb)
continue;

// Probably an old target, get rid of it.
if (possible_clear && GSLocalMemory::m_psm[t->m_TEX0.PSM].bpp != GSLocalMemory::m_psm[TEX0.PSM].bpp)
const GSLocalMemory::psm_t& t_psm_s = GSLocalMemory::m_psm[t->m_TEX0.PSM];
if (t_psm_s.bpp != psm_s.bpp)
{
InvalidateSourcesFromTarget(t);
i = rev_list.erase(i);
delete t;
continue;
bool remove_target = possible_clear;

// If we have a BW change, and it's not a multiple of 2 (for a shuffle), the game's going to get a jigsaw
// puzzle of pages and can't be expecting to have legitimate data. Tokimeki Memorial 3 reuses a BW 17
// buffer as BW 10, and if we don't discard the BW 17 buffer, the BW 10 buffer ends up twice the size.
const u32 shuffle_bw = (psm_s.bpp > t_psm_s.bpp) ? (TEX0.TBW / 2u) : (TEX0.TBW * 2u);
if (t->m_TEX0.TBW != TEX0.TBW && t->m_TEX0.TBW != shuffle_bw)
{
// But we'll make sure the whole existing target's actually being drawn over to be safe.
const u32 end_block = GSLocalMemory::GetUnwrappedEndBlockAddress(TEX0.TBP0, TEX0.TBW, TEX0.PSM, draw_rect);
if (end_block >= t->UnwrappedEndBlock())
{
GL_CACHE("Not converting %s at %x TBW %u with end block of %x when we're drawing through %x",
to_string(rev_type), t->m_TEX0.TBP0, t->m_TEX0.TBW, t->UnwrappedEndBlock(), end_block);
remove_target = true;
}
}

// Probably an old target, get rid of it.
if (remove_target)
{
InvalidateSourcesFromTarget(t);
i = rev_list.erase(i);
delete t;
continue;
}
}

if (t->m_age == 0)
Expand Down