mirror of https://github.com/PCSX2/pcsx2.git
GS-HW: Improve clear detection and avoid making bad render targets
This commit is contained in:
parent
6013d7172a
commit
264086e0aa
|
@ -756,7 +756,7 @@ GSVector2i GSRendererHW::GetTargetSize(GSVector2i* unscaled_size)
|
|||
}
|
||||
}
|
||||
|
||||
u32 width = m_context->FRAME.FBW * 64u;
|
||||
u32 width = std::min(m_context->FRAME.FBW * 64u, static_cast<u32>(m_context->scissor.in.z));
|
||||
|
||||
// If it's a channel shuffle, it'll likely be just a single page, so assume full screen.
|
||||
if (m_channel_shuffle)
|
||||
|
@ -1573,7 +1573,17 @@ void GSRendererHW::Draw()
|
|||
|
||||
GSTextureCache::Target* rt = nullptr;
|
||||
if (!no_rt)
|
||||
rt = m_tc->LookupTarget(TEX0, t_size, GSTextureCache::RenderTarget, true, fm, false, unscaled_target_size.x, unscaled_target_size.y, force_preload);
|
||||
{
|
||||
const bool is_square = (unscaled_target_size.y == unscaled_target_size.x) && m_r.w >= 1024 && m_vertex.next;
|
||||
rt = m_tc->LookupTarget(TEX0, t_size, GSTextureCache::RenderTarget, true, fm, false, unscaled_target_size.x, unscaled_target_size.y, force_preload, IsConstantDirectWriteMemClear(false) && is_square);
|
||||
|
||||
// Draw skipped because it was a clear and there was no target.
|
||||
if (!rt)
|
||||
{
|
||||
OI_GsMemClear();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
TEX0.TBP0 = context->ZBUF.Block();
|
||||
TEX0.TBW = context->FRAME.FBW;
|
||||
|
@ -1581,7 +1591,9 @@ void GSRendererHW::Draw()
|
|||
|
||||
GSTextureCache::Target* ds = nullptr;
|
||||
if (!no_ds)
|
||||
{
|
||||
ds = m_tc->LookupTarget(TEX0, t_size, GSTextureCache::DepthStencil, context->DepthWrite(), 0, false, unscaled_target_size.x, unscaled_target_size.y, force_preload);
|
||||
}
|
||||
|
||||
if (process_texture)
|
||||
{
|
||||
|
@ -1739,6 +1751,7 @@ void GSRendererHW::Draw()
|
|||
|
||||
const bool is_mem_clear = IsConstantDirectWriteMemClear(false);
|
||||
const bool can_update_size = !is_mem_clear && !m_texture_shuffle && !m_channel_shuffle;
|
||||
const GSVector2i resolution = PCRTCDisplays.GetResolution();
|
||||
{
|
||||
// We still need to make sure the dimensions of the targets match.
|
||||
const GSVector2 up_s(GetTextureScaleFactor());
|
||||
|
@ -1753,23 +1766,20 @@ void GSRendererHW::Draw()
|
|||
|
||||
pxAssert(rt->m_texture->GetScale() == up_s);
|
||||
rt->ResizeTexture(new_w, new_h, up_s);
|
||||
const GSVector2i tex_size = rt->m_texture->GetSize();
|
||||
|
||||
// Avoid temporary format changes, as this will change the end block and could break things.
|
||||
if ((old_height != tex_size.y) && can_update_size)
|
||||
if (!m_texture_shuffle && !m_channel_shuffle)
|
||||
{
|
||||
const GSVector2 tex_scale = rt->m_texture->GetScale();
|
||||
const GSVector4i new_valid = GSVector4i(0, 0, tex_size.x / tex_scale.x, tex_size.y / tex_scale.y);
|
||||
const GSVector2i tex_size = rt->m_texture->GetSize();
|
||||
const GSVector4i new_valid = GSVector4i(0, 0, tex_size.x / up_s.x, tex_size.y / up_s.y);
|
||||
rt->ResizeValidity(new_valid);
|
||||
}
|
||||
GSVector2i resolution = PCRTCDisplays.GetResolution();
|
||||
// Limit to 2x the vertical height of the resolution (for double buffering)
|
||||
rt->UpdateValidity(m_r, can_update_size || m_r.w <= (resolution.y * 2));
|
||||
|
||||
// Probably changing to double buffering, so invalidate any old target that was next to it.
|
||||
// This resolves an issue where the PCRTC will find the old target in FMV's causing flashing.
|
||||
// Grandia Xtreme, Onimusha Warlord.
|
||||
if (new_height && old_end_block != rt->m_end_block)
|
||||
if (old_end_block != rt->m_TEX0.TBP0 && new_height && old_end_block != rt->m_end_block)
|
||||
{
|
||||
GSTextureCache::Target* old_rt = nullptr;
|
||||
old_rt = m_tc->FindTargetOverlap(old_end_block, rt->m_end_block, GSTextureCache::RenderTarget, context->FRAME.PSM);
|
||||
|
@ -1794,20 +1804,17 @@ void GSRendererHW::Draw()
|
|||
|
||||
pxAssert(ds->m_texture->GetScale() == up_s);
|
||||
ds->ResizeTexture(new_w, new_h, up_s);
|
||||
const GSVector2i tex_size = ds->m_texture->GetSize();
|
||||
|
||||
if ((old_height != tex_size.y) && can_update_size)
|
||||
if (!m_texture_shuffle && !m_channel_shuffle)
|
||||
{
|
||||
const GSVector2 tex_scale = ds->m_texture->GetScale();
|
||||
const GSVector4i new_valid = GSVector4i(0, 0, tex_size.x / tex_scale.x, tex_size.y / tex_scale.y);
|
||||
const GSVector2i tex_size = ds->m_texture->GetSize();
|
||||
const GSVector4i new_valid = GSVector4i(0, 0, tex_size.x / up_s.x, tex_size.y / up_s.y);
|
||||
ds->ResizeValidity(new_valid);
|
||||
}
|
||||
|
||||
GSVector2i resolution = PCRTCDisplays.GetResolution();
|
||||
// Limit to 2x the vertical height of the resolution (for double buffering)
|
||||
ds->UpdateValidity(m_r, can_update_size || m_r.w <= (resolution.y * 2));
|
||||
|
||||
if (new_height && old_end_block != ds->m_end_block)
|
||||
if (old_end_block != ds->m_TEX0.TBP0 && new_height && old_end_block != ds->m_end_block)
|
||||
{
|
||||
GSTextureCache::Target* old_ds = nullptr;
|
||||
old_ds = m_tc->FindTargetOverlap(old_end_block, ds->m_end_block, GSTextureCache::DepthStencil, context->ZBUF.PSM);
|
||||
|
@ -1955,13 +1962,13 @@ void GSRendererHW::Draw()
|
|||
// Temporary source *must* be invalidated before normal, because otherwise it'll be double freed.
|
||||
m_tc->InvalidateTemporarySource();
|
||||
|
||||
// If it's a mem clear or shuffle we don't want to resize the texture, it can cause textures to take up the entire
|
||||
// video memory, and that is not good.
|
||||
//
|
||||
|
||||
if ((fm & fm_mask) != fm_mask && rt)
|
||||
{
|
||||
//rt->m_valid = rt->m_valid.runion(r);
|
||||
if(can_update_size)
|
||||
rt->UpdateValidity(m_r);
|
||||
// Limit to 2x the vertical height of the resolution (for double buffering)
|
||||
rt->UpdateValidity(m_r, can_update_size || m_r.w <= (resolution.y * 2));
|
||||
|
||||
rt->UpdateValidBits(~fm & fm_mask);
|
||||
|
||||
|
@ -1973,9 +1980,8 @@ void GSRendererHW::Draw()
|
|||
if (zm != 0xffffffff && ds)
|
||||
{
|
||||
//ds->m_valid = ds->m_valid.runion(r);
|
||||
// Shouldn't be a problem as Z will be masked.
|
||||
if (can_update_size)
|
||||
ds->UpdateValidity(m_r);
|
||||
// Limit to 2x the vertical height of the resolution (for double buffering)
|
||||
ds->UpdateValidity(m_r, can_update_size || m_r.w <= (resolution.y * 2));
|
||||
|
||||
ds->UpdateValidBits(GSLocalMemory::m_psm[context->ZBUF.PSM].fmsk);
|
||||
|
||||
|
|
|
@ -599,7 +599,7 @@ GSTextureCache::Target* GSTextureCache::FindTargetOverlap(u32 bp, u32 end_block,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
GSTextureCache::Target* GSTextureCache::LookupTarget(const GIFRegTEX0& TEX0, const GSVector2i& size, int type, bool used, u32 fbmask, const bool is_frame, const int real_w, const int real_h, bool preload)
|
||||
GSTextureCache::Target* GSTextureCache::LookupTarget(const GIFRegTEX0& TEX0, const GSVector2i& size, int type, bool used, u32 fbmask, const bool is_frame, const int real_w, const int real_h, bool preload, bool is_clear)
|
||||
{
|
||||
const GSLocalMemory::psm_t& psm_s = GSLocalMemory::m_psm[TEX0.PSM];
|
||||
const GSVector2& new_s = static_cast<GSRendererHW*>(g_gs_renderer.get())->GetTextureScaleFactor();
|
||||
|
@ -806,6 +806,13 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(const GIFRegTEX0& TEX0, con
|
|||
|
||||
if (!dst)
|
||||
{
|
||||
// Skip full screen clears from making massive targets.
|
||||
if (is_clear)
|
||||
{
|
||||
GL_CACHE("TC: Create RT skipped on clear draw");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GL_CACHE("TC: Lookup %s(%s) %dx%d, miss (0x%x, %s)", is_frame ? "Frame" : "Target", to_string(type), size.x, size.y, bp, psm_str(TEX0.PSM));
|
||||
|
||||
dst = CreateTarget(TEX0, size.x, size.y, type, true);
|
||||
|
@ -3317,8 +3324,8 @@ void GSTextureCache::Target::ResizeValidity(const GSVector4i& rect)
|
|||
}
|
||||
else
|
||||
{
|
||||
m_valid = rect;
|
||||
m_drawn_since_read = rect;
|
||||
// No valid size, so need to resize down.
|
||||
return;
|
||||
}
|
||||
// Block of the bottom right texel of the validity rectangle, last valid block of the texture
|
||||
// TODO: This is not correct when the PSM changes. e.g. a 512x448 target being shuffled will become 512x896 temporarily, and
|
||||
|
|
|
@ -416,7 +416,7 @@ public:
|
|||
Source* LookupDepthSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GIFRegCLAMP& CLAMP, const GSVector4i& r, bool palette = false);
|
||||
|
||||
Target* FindTargetOverlap(u32 bp, u32 end_block, int type, int psm);
|
||||
Target* LookupTarget(const GIFRegTEX0& TEX0, const GSVector2i& size, int type, bool used, u32 fbmask = 0, const bool is_frame = false, const int real_w = 0, const int real_h = 0, bool preload = GSConfig.PreloadFrameWithGSData);
|
||||
Target* LookupTarget(const GIFRegTEX0& TEX0, const GSVector2i& size, int type, bool used, u32 fbmask = 0, const bool is_frame = false, const int real_w = 0, const int real_h = 0, bool preload = GSConfig.PreloadFrameWithGSData, bool is_clear = false);
|
||||
Target* LookupDisplayTarget(const GIFRegTEX0& TEX0, const GSVector2i& size, const int real_w, const int real_h);
|
||||
|
||||
/// Looks up a target in the cache, and only returns it if the BP/BW/PSM match exactly.
|
||||
|
|
Loading…
Reference in New Issue