Skip to content

Commit

Permalink
GS/HW: Further RT in RT changes to improve compatibility
Browse files Browse the repository at this point in the history
  • Loading branch information
refractionpcsx2 committed Jan 10, 2025
1 parent db020cc commit ffb4045
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 85 deletions.
164 changes: 86 additions & 78 deletions pcsx2/GS/Renderers/HW/GSRendererHW.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2730,6 +2730,75 @@ void GSRendererHW::Draw()
m_in_target_draw = false;
m_target_offset = 0;

GSTextureCache::Target* ds = nullptr;
GIFRegTEX0 ZBUF_TEX0;
if (!no_ds)
{
ZBUF_TEX0.U64 = 0;
ZBUF_TEX0.TBP0 = m_cached_ctx.ZBUF.Block();
ZBUF_TEX0.TBW = m_cached_ctx.FRAME.FBW;
ZBUF_TEX0.PSM = m_cached_ctx.ZBUF.PSM;

ds = g_texture_cache->LookupTarget(ZBUF_TEX0, t_size, target_scale, GSTextureCache::DepthStencil,
m_cached_ctx.DepthWrite(), 0, false, force_preload, preserve_depth, preserve_depth, unclamped_draw_rect, IsPossibleChannelShuffle(), is_possible_mem_clear && ZBUF_TEX0.TBP0 != m_cached_ctx.FRAME.Block(), false,
src, -1);

ZBUF_TEX0.TBW = m_channel_shuffle ? src->m_from_target_TEX0.TBW : m_cached_ctx.FRAME.FBW;

if (!ds)
{
ds = g_texture_cache->CreateTarget(ZBUF_TEX0, t_size, GetValidSize(src), target_scale, GSTextureCache::DepthStencil,
true, 0, false, force_preload, preserve_depth, m_r, src);
if (!ds) [[unlikely]]
{
GL_INS("ERROR: Failed to create ZBUF target, skipping.");
CleanupDraw(true);
return;
}
}
else
{
// If it failed to check depth test earlier, we can now check the top bits from the alpha to get a bit more accurate picture.
if (((zm && m_cached_ctx.TEST.ZTST > ZTST_ALWAYS) || (m_vt.m_eq.z && m_cached_ctx.TEST.ZTST == ZTST_GEQUAL)) && GSLocalMemory::m_psm[m_cached_ctx.ZBUF.PSM].trbpp == 32)
{
if (ds->m_alpha_max != 0)
{
const u32 max_z = (static_cast<u64>(ds->m_alpha_max + 1) << 24) - 1;

switch (m_cached_ctx.TEST.ZTST)
{
case ZTST_GEQUAL:
// Every Z value will pass
if (max_z <= m_vt.m_min.p.z)
{
m_cached_ctx.TEST.ZTST = ZTST_ALWAYS;
if (zm)
{
ds = nullptr;
no_ds = true;
}
}
break;
case ZTST_GREATER:
// Every Z value will pass
if (max_z < m_vt.m_min.p.z)
{
m_cached_ctx.TEST.ZTST = ZTST_ALWAYS;
if (zm)
{
ds = nullptr;
no_ds = true;
}
}
break;
default:
break;
}
}
}
}
}

if (!no_rt)
{
const bool possible_shuffle = draw_sprite_tex && (((src && src->m_target && src->m_from_target && src->m_from_target->m_32_bits_fmt) &&
Expand Down Expand Up @@ -2759,7 +2828,7 @@ void GSRendererHW::Draw()

rt = g_texture_cache->LookupTarget(FRAME_TEX0, t_size, ((src && src->m_scale != 1) && GSConfig.UserHacks_NativeScaling == GSNativeScaling::Normal && !possible_shuffle) ? GetTextureScaleFactor() : target_scale, GSTextureCache::RenderTarget, true,
fm, false, force_preload, preserve_rt_rgb, preserve_rt_alpha, unclamped_draw_rect, possible_shuffle, is_possible_mem_clear && FRAME_TEX0.TBP0 != m_cached_ctx.ZBUF.Block(),
GSConfig.UserHacks_NativeScaling != GSNativeScaling::Off && preserve_downscale_draw && is_possible_mem_clear != ClearType::NormalClear, src);
GSConfig.UserHacks_NativeScaling != GSNativeScaling::Off && preserve_downscale_draw && is_possible_mem_clear != ClearType::NormalClear, src, no_ds ? -1 : (m_cached_ctx.ZBUF.Block() - ds->m_TEX0.TBP0));

// Draw skipped because it was a clear and there was no target.
if (!rt)
Expand Down Expand Up @@ -2794,7 +2863,7 @@ void GSRendererHW::Draw()
return;
}
}
else if (rt->m_TEX0.TBP0 != m_cached_ctx.FRAME.Block()) // Must have done rt in rt
else if (rt->m_TEX0.TBP0 != m_cached_ctx.FRAME.Block())
{
GSVertex* v = &m_vertex.buff[0];
int vertical_offset = ((std::abs(static_cast<int>(m_cached_ctx.FRAME.Block() - rt->m_TEX0.TBP0)) >> 5) / std::max(rt->m_TEX0.TBW, 1U)) * frame_psm.pgs.y; // I know I could just not shift it..
Expand Down Expand Up @@ -2822,17 +2891,24 @@ void GSRendererHW::Draw()
m_vt.m_max.p.x += horizontal_offset;
m_vt.m_min.p.y += vertical_offset;
m_vt.m_max.p.y += vertical_offset;

t_size.x = rt->m_unscaled_size.x - horizontal_offset;
t_size.y = rt->m_unscaled_size.y - vertical_offset;

if (t_size.y <= 0)
// Don't resize if the BPP don't match.
if (frame_psm.bpp == GSLocalMemory::m_psm[rt->m_TEX0.PSM].bpp)
{
u32 new_height = m_r.w;

//DevCon.Warning("Resizing texture %d x %d draw %d", rt->m_unscaled_size.x, new_height, s_n);
rt->ResizeTexture(rt->m_unscaled_size.x, new_height);
rt->UpdateValidity(m_r, true);
rt->UpdateDrawn(m_r, true);
if (t_size.y <= 0)
{
u32 new_height = m_r.w;

if (possible_shuffle && std::abs(static_cast<s16>(GSLocalMemory::m_psm[rt->m_TEX0.PSM].bpp - GSLocalMemory::m_psm[TEX0.PSM].bpp)) == 16)
new_height /= 2;
//DevCon.Warning("Resizing texture %d x %d draw %d", rt->m_unscaled_size.x, new_height, s_n);
rt->ResizeTexture(rt->m_unscaled_size.x, new_height);
rt->UpdateValidity(m_r, true);
rt->UpdateDrawn(m_r, true);
}
}
}

Expand Down Expand Up @@ -2860,74 +2936,6 @@ void GSRendererHW::Draw()
m_last_channel_shuffle_end_block = 0xFFFF;
}

GSTextureCache::Target* ds = nullptr;
GIFRegTEX0 ZBUF_TEX0;
if (!no_ds)
{
ZBUF_TEX0.U64 = 0;
ZBUF_TEX0.TBP0 = m_cached_ctx.ZBUF.Block();
ZBUF_TEX0.TBW = m_cached_ctx.FRAME.FBW;
ZBUF_TEX0.PSM = m_cached_ctx.ZBUF.PSM;

ds = g_texture_cache->LookupTarget(ZBUF_TEX0, t_size, target_scale, GSTextureCache::DepthStencil,
m_cached_ctx.DepthWrite(), 0, false, force_preload, preserve_depth, preserve_depth, unclamped_draw_rect, IsPossibleChannelShuffle(), is_possible_mem_clear && ZBUF_TEX0.TBP0 != m_cached_ctx.FRAME.Block());

ZBUF_TEX0.TBW = m_channel_shuffle ? src->m_from_target_TEX0.TBW : m_cached_ctx.FRAME.FBW;

if (!ds)
{
ds = g_texture_cache->CreateTarget(ZBUF_TEX0, t_size, GetValidSize(src), target_scale, GSTextureCache::DepthStencil,
true, 0, false, force_preload, preserve_depth, m_r, src);
if (!ds) [[unlikely]]
{
GL_INS("ERROR: Failed to create ZBUF target, skipping.");
CleanupDraw(true);
return;
}
}
else
{
// If it failed to check depth test earlier, we can now check the top bits from the alpha to get a bit more accurate picture.
if (((zm && m_cached_ctx.TEST.ZTST > ZTST_ALWAYS) || (m_vt.m_eq.z && m_cached_ctx.TEST.ZTST == ZTST_GEQUAL)) && GSLocalMemory::m_psm[m_cached_ctx.ZBUF.PSM].trbpp == 32)
{
if (ds->m_alpha_max != 0)
{
const u32 max_z = (static_cast<u64>(ds->m_alpha_max + 1) << 24) - 1;

switch (m_cached_ctx.TEST.ZTST)
{
case ZTST_GEQUAL:
// Every Z value will pass
if (max_z <= m_vt.m_min.p.z)
{
m_cached_ctx.TEST.ZTST = ZTST_ALWAYS;
if (zm)
{
ds = nullptr;
no_ds = true;
}
}
break;
case ZTST_GREATER:
// Every Z value will pass
if (max_z < m_vt.m_min.p.z)
{
m_cached_ctx.TEST.ZTST = ZTST_ALWAYS;
if (zm)
{
ds = nullptr;
no_ds = true;
}
}
break;
default:
break;
}
}
}
}
}

if (m_process_texture)
{
GIFRegCLAMP MIP_CLAMP = m_cached_ctx.CLAMP;
Expand Down Expand Up @@ -4157,7 +4165,7 @@ __ri bool GSRendererHW::EmulateChannelShuffle(GSTextureCache::Target* src, bool
// Performance GPU note: it could be wise to reduce the size to
// the rendered size of the framebuffer

if (!m_in_target_draw && (GSConfig.UserHacks_TextureInsideRt == GSTextureInRtMode::Disabled || NextDrawMatchesShuffle()))
if (GSConfig.UserHacks_TextureInsideRt == GSTextureInRtMode::Disabled || (!m_in_target_draw && NextDrawMatchesShuffle()))
{
GSVertex* s = &m_vertex.buff[0];
s[0].XYZ.X = static_cast<u16>(m_context->XYOFFSET.OFX + 0);
Expand Down
29 changes: 23 additions & 6 deletions pcsx2/GS/Renderers/HW/GSTextureCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1800,7 +1800,8 @@ GSVector2i GSTextureCache::ScaleRenderTargetSize(const GSVector2i& sz, float sca
}

GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVector2i& size, float scale, int type,
bool used, u32 fbmask, bool is_frame, bool preload, bool preserve_rgb, bool preserve_alpha, const GSVector4i draw_rect, bool is_shuffle, bool possible_clear, bool preserve_scale, GSTextureCache::Source* src)
bool used, u32 fbmask, bool is_frame, bool preload, bool preserve_rgb, bool preserve_alpha, const GSVector4i draw_rect,
bool is_shuffle, bool possible_clear, bool preserve_scale, GSTextureCache::Source* src, int offset)
{
const GSLocalMemory::psm_t& psm_s = GSLocalMemory::m_psm[TEX0.PSM];
const u32 bp = TEX0.TBP0;
Expand Down Expand Up @@ -1898,8 +1899,11 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
}
}
// Probably pointing to half way through the target
else if(GSConfig.UserHacks_TextureInsideRt >= GSTextureInRtMode::InsideTargets)
else if (GSConfig.UserHacks_TextureInsideRt >= GSTextureInRtMode::InsideTargets)
{
if (offset != -1 && (bp - t->m_TEX0.TBP0) != offset)
continue;

const u32 widthpage_offset = (std::abs(static_cast<int>(bp - t->m_TEX0.TBP0)) >> 5) % std::max(t->m_TEX0.TBW, 1U);
const bool is_aligned_ok = widthpage_offset == 0 || ((widthpage_offset + TEX0.TBW) <= t->m_TEX0.TBW) || min_rect.width() <= 64 || (widthpage_offset == (t->m_TEX0.TBW >> 1) && (static_cast<u32>(min_rect.width()) <= (widthpage_offset * 64)));
if ((!dst || ((GSState::s_n - dst->m_last_draw) < (GSState::s_n - t->m_last_draw))) && is_aligned_ok && (t->m_TEX0.TBW == TEX0.TBW || (TEX0.TBW == 1 && t->m_TEX0.TBW > 1)) && t->Inside(bp, TEX0.TBW, TEX0.PSM, min_rect))
Expand Down Expand Up @@ -2083,6 +2087,8 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
}
else if (!is_shuffle && std::abs(static_cast<s16>(GSLocalMemory::m_psm[dst->m_TEX0.PSM].bpp - GSLocalMemory::m_psm[TEX0.PSM].bpp)) == 16)
{
dst->Update(false);

const bool scale_down = GSLocalMemory::m_psm[dst->m_TEX0.PSM].bpp > GSLocalMemory::m_psm[TEX0.PSM].bpp;
new_size = dst->m_unscaled_size;
new_scaled_size = ScaleRenderTargetSize(dst->m_unscaled_size, scale);
Expand Down Expand Up @@ -2340,6 +2346,8 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
dst->m_valid_alpha_high = dst_match->m_valid_alpha_high; //&& psm_s.trbpp != 24;
dst->m_valid_rgb = dst_match->m_valid_rgb;
dst->m_was_dst_matched = true;
dst_match->m_was_dst_matched = true;
dst_match->m_valid_rgb = false;

if (GSLocalMemory::m_psm[dst->m_TEX0.PSM].bpp == 16 && GSLocalMemory::m_psm[dst_match->m_TEX0.PSM].bpp > 16)
dst->m_TEX0.TBW = dst_match->m_TEX0.TBW; // Be careful of shuffles of the depth as C16, but using a buffer width of 16 (Mercenaries).
Expand Down Expand Up @@ -3167,6 +3175,17 @@ void GSTextureCache::InvalidateContainedTargets(u32 start_bp, u32 end_bp, u32 wr
continue;
}

// Not covering the whole target, and a different format, so just dirty it.
if (start_bp == t->m_TEX0.TBP0 && (t->UnwrappedEndBlock() > end_bp) && write_psm != t->m_TEX0.PSM)
{
const GSLocalMemory::psm_t& target_psm = GSLocalMemory::m_psm[write_psm];
u32 total_pages = (end_bp - t->m_TEX0.TBP0) >> 5;
GSVector4i dirty_area = GSVector4i(0, 0, t->m_valid.z, (total_pages / t->m_TEX0.TBW) * target_psm.pgs.y);
InvalidateVideoMem(g_gs_renderer->m_mem.GetOffset(t->m_TEX0.TBP0, t->m_TEX0.TBW, write_psm), dirty_area, true);
++i;
continue;
}

InvalidateSourcesFromTarget(t);

t->m_valid_alpha_low &= preserve_alpha;
Expand Down Expand Up @@ -4565,9 +4584,9 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
}

bool hack = false;
bool channel_shuffle = false;
bool channel_shuffle = dst && (TEX0.PSM == PSMT8) && (GSRendererHW::GetInstance()->TestChannelShuffle(dst));

if (dst && (x_offset != 0 || y_offset != 0))
if (dst && (x_offset != 0 || y_offset != 0) && (TEX0.PSM != PSMT8 || channel_shuffle))
{
const float scale = dst->m_scale;
const int x = static_cast<int>(scale * x_offset);
Expand Down Expand Up @@ -4630,8 +4649,6 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
src->m_texture = dst->m_texture;
src->m_unscaled_size = dst->m_unscaled_size;
src->m_shared_texture = true;

channel_shuffle = GSRendererHW::GetInstance()->TestChannelShuffle(dst);
}

// Invalidate immediately on recursive draws, because if we don't here, InvalidateVideoMem() will.
Expand Down
2 changes: 1 addition & 1 deletion pcsx2/GS/Renderers/HW/GSTextureCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,7 @@ class GSTextureCache
Target* FindTargetOverlap(Target* target, int type, int psm);
Target* LookupTarget(GIFRegTEX0 TEX0, const GSVector2i& size, float scale, int type, bool used = true, u32 fbmask = 0,
bool is_frame = false, bool preload = GSConfig.PreloadFrameWithGSData, bool preserve_rgb = true, bool preserve_alpha = true,
const GSVector4i draw_rc = GSVector4i::zero(), bool is_shuffle = false, bool possible_clear = false, bool preserve_scale = false, GSTextureCache::Source* src = nullptr);
const GSVector4i draw_rc = GSVector4i::zero(), bool is_shuffle = false, bool possible_clear = false, bool preserve_scale = false, GSTextureCache::Source* src = nullptr, int offset = -1);
Target* CreateTarget(GIFRegTEX0 TEX0, const GSVector2i& size, const GSVector2i& valid_size,float scale, int type, bool used = true, u32 fbmask = 0,
bool is_frame = false, bool preload = GSConfig.PreloadFrameWithGSData, bool preserve_target = true,
const GSVector4i draw_rc = GSVector4i::zero(), GSTextureCache::Source* src = nullptr);
Expand Down

0 comments on commit ffb4045

Please sign in to comment.