mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-11-14 18:20:36 +01:00
GS/HW: Detect double buffers when Z not offset during RT in RT
This commit is contained in:
1 parent
f7c0d6af73
commit
56fe0b32e6
3 files changed
+30
-4
No files matched your search
@@ -3358,6 +3358,15 @@ void GSRendererHW::Draw()
|
||||
|
||||
if (ds->m_TEX0.TBP0 != z_address_info.ZBP || z_address_info.offset != static_cast<u32>(vertical_offset - z_vertical_offset))
|
||||
g_texture_cache->InvalidateTemporaryZ();
|
||||
else if (!m_r.rintersect(z_address_info.rect_since + GSVector4i(0, z_address_info.offset, 0, z_address_info.offset)).rempty() && m_cached_ctx.TEST.ZTST > ZTST_ALWAYS)
|
||||
{
|
||||
GL_CACHE("RT in RT Updating Z copy on draw %d z_offset %d", s_n, z_address_info.offset);
|
||||
GSVector4i dRect = GSVector4i(z_address_info.rect_since.x * ds->m_scale, (z_address_info.offset + z_address_info.rect_since.y) * ds->m_scale, (z_address_info.rect_since.z + (1.0f / ds->m_scale)) * ds->m_scale, (z_address_info.offset + z_address_info.rect_since.w + (1.0f / ds->m_scale)) * ds->m_scale);
|
||||
g_gs_device->StretchRect(ds->m_texture, GSVector4(z_address_info.rect_since.x / static_cast<float>(ds->m_unscaled_size.x), z_address_info.rect_since.y / static_cast<float>(ds->m_unscaled_size.y), (z_address_info.rect_since.z + (1.0f / ds->m_scale)) / static_cast<float>(ds->m_unscaled_size.x), (z_address_info.rect_since.w + (1.0f / ds->m_scale)) / static_cast<float>(ds->m_unscaled_size.y)), g_texture_cache->GetTemporaryZ(), GSVector4(dRect), ShaderConvert::DEPTH_COPY, false);
|
||||
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
|
||||
z_address_info.rect_since = GSVector4i::zero();
|
||||
g_texture_cache->SetTemporaryZInfo(z_address_info);
|
||||
}
|
||||
}
|
||||
|
||||
if (g_texture_cache->GetTemporaryZ() == nullptr)
|
||||
@@ -4267,10 +4276,11 @@ void GSRendererHW::Draw()
|
||||
GSTextureCache::TempZAddress z_address_info = g_texture_cache->GetTemporaryZInfo();
|
||||
if (ds->m_TEX0.TBP0 == z_address_info.ZBP)
|
||||
{
|
||||
GL_CACHE("RT in RT Updating Z copy on draw %d z_offset %d", s_n, z_address_info.offset);
|
||||
GSVector4i dRect = GSVector4i(real_rect.x * ds->m_scale, (z_address_info.offset + real_rect.y) * ds->m_scale, (real_rect.z + (1.0f / ds->m_scale)) * ds->m_scale, (z_address_info.offset + real_rect.w + (1.0f / ds->m_scale)) * ds->m_scale);
|
||||
g_gs_device->StretchRect(ds->m_texture, GSVector4(real_rect.x / static_cast<float>(ds->m_unscaled_size.x), real_rect.y / static_cast<float>(ds->m_unscaled_size.y), (real_rect.z + (1.0f / ds->m_scale)) / static_cast<float>(ds->m_unscaled_size.x), (real_rect.w + (1.0f / ds->m_scale)) / static_cast<float>(ds->m_unscaled_size.y)), g_texture_cache->GetTemporaryZ(), GSVector4(dRect), ShaderConvert::DEPTH_COPY, false);
|
||||
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
|
||||
if (z_address_info.rect_since.rempty())
|
||||
z_address_info.rect_since = real_rect;
|
||||
else
|
||||
z_address_info.rect_since = z_address_info.rect_since.runion(real_rect);
|
||||
g_texture_cache->SetTemporaryZInfo(z_address_info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2259,6 +2259,15 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
|
||||
{
|
||||
const GSLocalMemory::psm_t& s_psm = GSLocalMemory::m_psm[TEX0.PSM];
|
||||
|
||||
// If it overlaps but the target is huge and the Z isn't offset, we need to split the buffer, so let's shrink this one down.
|
||||
// 896 is just 448 * 2,just gives the buffer chance to be larger than normal, in case they do something like 640x640, or something ridiculous.
|
||||
if (!is_shuffle && (ds && offset == 0 && (t->m_valid.w >= 896) && ((((t->m_end_block + 1) - t->m_TEX0.TBP0) >> 1) + t->m_TEX0.TBP0) <= bp))
|
||||
{
|
||||
t->m_valid.w /= 2;
|
||||
t->m_end_block = ((((t->m_end_block + 1) - t->m_TEX0.TBP0) >> 1) + t->m_TEX0.TBP0) - 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
// I know what you're thinking, and I hate the guy who wrote it too (me). Project Snowblind, Tomb Raider etc decide to offset where they're drawing using a channel shuffle, and this gets messy, so best just to kill the old target.
|
||||
if (is_shuffle && src && src->m_TEX0.PSM == PSMT8 && GSRendererHW::GetInstance()->m_context->FRAME.FBW == 1 && t->m_last_draw != (GSState::s_n - 1) && src->m_from_target && (src->m_from_target->m_TEX0.TBP0 == src->m_TEX0.TBP0 || (((src->m_TEX0.TBP0 - src->m_from_target->m_TEX0.TBP0) >> 5) % std::max(src->m_from_target->m_TEX0.TBW, 1U) == 0)) && widthpage_offset && src->m_from_target != t)
|
||||
{
|
||||
@@ -7759,6 +7768,11 @@ void GSTextureCache::SetTemporaryZInfo(u32 address, u32 offset)
|
||||
{
|
||||
m_temporary_z_info.ZBP = address;
|
||||
m_temporary_z_info.offset = offset;
|
||||
m_temporary_z_info.rect_since = GSVector4i::zero();
|
||||
}
|
||||
void GSTextureCache::SetTemporaryZInfo(TempZAddress address_info)
|
||||
{
|
||||
m_temporary_z_info = address_info;
|
||||
}
|
||||
|
||||
void GSTextureCache::SetTemporaryZ(GSTexture* temp_z)
|
||||
|
||||
@@ -210,6 +210,7 @@ public:
|
||||
{
|
||||
u32 ZBP;
|
||||
u32 offset;
|
||||
GSVector4i rect_since;
|
||||
};
|
||||
|
||||
class Target : public Surface
|
||||
@@ -564,6 +565,7 @@ public:
|
||||
GSTexture* GetTemporaryZ();
|
||||
TempZAddress GetTemporaryZInfo();
|
||||
void SetTemporaryZInfo(u32 address, u32 offset);
|
||||
void SetTemporaryZInfo(TempZAddress address_info);
|
||||
/// Invalidates a temporary Z, a partial copy only created from the current DS for the current draw when Z is not offset but RT is.
|
||||
void InvalidateTemporaryZ();
|
||||
|
||||
|
||||
Reference in new issue
Block a user