mirror of https://github.com/PCSX2/pcsx2.git
GS: Split out sprite gap check for downscale gap checking
This commit is contained in:
parent
ae57878b27
commit
839a6daa63
|
@ -2998,6 +2998,62 @@ GSState::PRIM_OVERLAP GSState::PrimitiveOverlap()
|
|||
return overlap;
|
||||
}
|
||||
|
||||
bool GSState::SpriteDrawWithoutGaps()
|
||||
{
|
||||
// Check that the height matches. Xenosaga 3 draws a letterbox around
|
||||
// the FMV with a sprite at the top and bottom of the framebuffer.
|
||||
const GSVertex* v = &m_vertex.buff[0];
|
||||
const int first_dpY = v[1].XYZ.Y - v[0].XYZ.Y;
|
||||
const int first_dpX = v[1].XYZ.X - v[0].XYZ.X;
|
||||
|
||||
// Horizontal Match.
|
||||
if (((first_dpX + 8) >> 4) == m_r_no_scissor.z)
|
||||
{
|
||||
// Borrowed from MergeSprite() modified to calculate heights.
|
||||
for (u32 i = 2; i < m_vertex.next; i += 2)
|
||||
{
|
||||
const int last_pY = v[i - 1].XYZ.Y;
|
||||
const int dpY = v[i + 1].XYZ.Y - v[i].XYZ.Y;
|
||||
|
||||
if (std::abs(dpY - first_dpY) >= 16 || std::abs(static_cast<int>(v[i].XYZ.Y) - last_pY) >= 16)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Vertical Match.
|
||||
if (((first_dpY + 8) >> 4) == m_r_no_scissor.w)
|
||||
{
|
||||
// Borrowed from MergeSprite().
|
||||
const int offset_X = m_context->XYOFFSET.OFX;
|
||||
for (u32 i = 2; i < m_vertex.next; i += 2)
|
||||
{
|
||||
const int last_pX = v[i - 1].XYZ.X;
|
||||
const int this_start_X = v[i].XYZ.X;
|
||||
const int last_start_X = v[i - 2].XYZ.X;
|
||||
|
||||
const int dpX = v[i + 1].XYZ.X - v[i].XYZ.X;
|
||||
|
||||
if (this_start_X < last_start_X)
|
||||
{
|
||||
const int prev_X = last_start_X - offset_X;
|
||||
if (std::abs(dpX - prev_X) >= 16 || std::abs(this_start_X - offset_X) >= 16)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((std::abs(dpX - first_dpX) >= 16 && (i + 2) < m_vertex.next) || std::abs(this_start_X - last_pX) >= 16)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GSState::PrimitiveCoversWithoutGaps()
|
||||
{
|
||||
if (m_primitive_covers_without_gaps.has_value())
|
||||
|
@ -3033,69 +3089,10 @@ bool GSState::PrimitiveCoversWithoutGaps()
|
|||
return true;
|
||||
}
|
||||
|
||||
// Check that the height matches. Xenosaga 3 draws a letterbox around
|
||||
// the FMV with a sprite at the top and bottom of the framebuffer.
|
||||
const GSVertex* v = &m_vertex.buff[0];
|
||||
const int first_dpY = v[1].XYZ.Y - v[0].XYZ.Y;
|
||||
const int first_dpX = v[1].XYZ.X - v[0].XYZ.X;
|
||||
const bool result = SpriteDrawWithoutGaps();
|
||||
m_primitive_covers_without_gaps = result;
|
||||
|
||||
// Horizontal Match.
|
||||
if (((first_dpX + 8) >> 4) == m_r_no_scissor.z)
|
||||
{
|
||||
// Borrowed from MergeSprite() modified to calculate heights.
|
||||
for (u32 i = 2; i < m_vertex.next; i += 2)
|
||||
{
|
||||
const int last_pY = v[i - 1].XYZ.Y;
|
||||
const int dpY = v[i + 1].XYZ.Y - v[i].XYZ.Y;
|
||||
if (std::abs(dpY - first_dpY) >= 16 || std::abs(static_cast<int>(v[i].XYZ.Y) - last_pY) >= 16)
|
||||
{
|
||||
m_primitive_covers_without_gaps = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
m_primitive_covers_without_gaps = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Vertical Match.
|
||||
if (((first_dpY + 8) >> 4) == m_r_no_scissor.w)
|
||||
{
|
||||
// Borrowed from MergeSprite().
|
||||
const int offset_X = m_context->XYOFFSET.OFX;
|
||||
for (u32 i = 2; i < m_vertex.next; i += 2)
|
||||
{
|
||||
const int last_pX = v[i - 1].XYZ.X;
|
||||
const int this_start_X = v[i].XYZ.X;
|
||||
const int last_start_X = v[i - 2].XYZ.X;
|
||||
|
||||
const int dpX = v[i + 1].XYZ.X - v[i].XYZ.X;
|
||||
|
||||
if (this_start_X < last_start_X)
|
||||
{
|
||||
const int prev_X = last_start_X - offset_X;
|
||||
if (std::abs(dpX - prev_X) >= 16 || std::abs(this_start_X - offset_X) >= 16)
|
||||
{
|
||||
m_primitive_covers_without_gaps = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((std::abs(dpX - first_dpX) >= 16 && (i + 2) < m_vertex.next) || std::abs(this_start_X - last_pX) >= 16)
|
||||
{
|
||||
m_primitive_covers_without_gaps = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_primitive_covers_without_gaps = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
m_primitive_covers_without_gaps = false;
|
||||
return false;
|
||||
return result;
|
||||
}
|
||||
|
||||
__forceinline bool GSState::IsAutoFlushDraw(u32 prim)
|
||||
|
|
|
@ -410,6 +410,7 @@ public:
|
|||
|
||||
bool TrianglesAreQuads(bool shuffle_check = false) const;
|
||||
PRIM_OVERLAP PrimitiveOverlap();
|
||||
bool SpriteDrawWithoutGaps();
|
||||
bool PrimitiveCoversWithoutGaps();
|
||||
GIFRegTEX0 GetTex0Layer(u32 lod);
|
||||
};
|
||||
|
|
|
@ -2619,9 +2619,13 @@ void GSRendererHW::Draw()
|
|||
{
|
||||
// 1 == Downscale, so we need to reduce the size of the target also.
|
||||
// 2 == Upscale, so likely putting it over the top of the render target.
|
||||
if(scale_draw == 1)
|
||||
if (scale_draw == 1)
|
||||
{
|
||||
target_scale = 1.0f;
|
||||
m_downscale_source = src->m_from_target->GetScale() > 1.0f;
|
||||
m_downscale_source = src->m_from_target->GetScale() > 1.0f;
|
||||
}
|
||||
else
|
||||
m_downscale_source = false; //src->m_from_target->GetScale() > 1.0f; // Bad for GTA + Full Spectrum Warrior, good for Sacred Blaze + Parappa.
|
||||
}
|
||||
else
|
||||
m_downscale_source = false;
|
||||
|
@ -5213,7 +5217,7 @@ __ri void GSRendererHW::HandleTextureHazards(const GSTextureCache::Target* rt, c
|
|||
src_copy.reset(src_target->m_texture->IsDepthStencil() ?
|
||||
g_gs_device->CreateDepthStencil(
|
||||
scaled_copy_size.x, scaled_copy_size.y, src_target->m_texture->GetFormat(), false) :
|
||||
(m_downscale_source ? g_gs_device->CreateRenderTarget(scaled_copy_size.x, scaled_copy_size.y, src_target->m_texture->GetFormat(), true,
|
||||
(m_downscale_source ? g_gs_device->CreateRenderTarget(scaled_copy_size.x, scaled_copy_size.y, src_target->m_texture->GetFormat(), true,
|
||||
true) :
|
||||
g_gs_device->CreateTexture(
|
||||
scaled_copy_size.x, scaled_copy_size.y, 1, src_target->m_texture->GetFormat(), true)));
|
||||
|
@ -5226,10 +5230,9 @@ __ri void GSRendererHW::HandleTextureHazards(const GSTextureCache::Target* rt, c
|
|||
}
|
||||
if (m_downscale_source)
|
||||
{
|
||||
GL_INS("Rescaling %f -> %f", src_scale, scale);
|
||||
const GSVector4 dst_rect = GSVector4(0, 0, src_unscaled_size.x, src_unscaled_size.y);
|
||||
const GSVector4 src_rect = GSVector4(scaled_copy_range) / GSVector4(src_unscaled_size * src_scale).xyxy();
|
||||
g_gs_device->StretchRect(src_target->m_texture, GSVector4::cxpr(0.0f,0.0f,1.0f,1.0f), src_copy.get(), dst_rect, src_target->m_texture->IsDepthStencil() ? ShaderConvert::DEPTH_COPY : ShaderConvert::COPY, false);
|
||||
g_gs_device->StretchRect(src_target->m_texture, GSVector4::cxpr(0.0f, 0.0f, 1.0f, 1.0f), src_copy.get(), dst_rect, src_target->m_texture->IsDepthStencil() ? ShaderConvert::DEPTH_COPY : ShaderConvert::COPY, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -7210,14 +7213,18 @@ int GSRendererHW::IsScalingDraw(GSTextureCache::Source* src, bool no_gaps)
|
|||
if (is_downscale && draw_size.x >= PCRTCDisplays.GetResolution().x)
|
||||
return 0;
|
||||
|
||||
// Check if we're already downscaled and drawing in current size, try not to rescale it.
|
||||
if (src && src->m_from_target && src->m_from_target->m_downscaled && std::abs(draw_size.x - tex_size.x) <= 1 && std::abs(draw_size.y - tex_size.y) <= 1)
|
||||
return 1;
|
||||
|
||||
const bool is_upscale = (draw_size.x / 2.0f) >= tex_size.x && (draw_size.y / 2.0f) >= tex_size.y;
|
||||
|
||||
const bool target_scale = is_downscale ? true : false;
|
||||
// DMC does a blit in strips with the scissor to keep it inside page boundaries, so that's not technically full coverage
|
||||
// but good enough for what we want.
|
||||
const bool no_gaps_or_single_sprite = (no_gaps || (m_vt.m_primclass == GS_SPRITE_CLASS && m_index.tail == 2));
|
||||
if (no_gaps_or_single_sprite && m_vt.m_primclass >= GS_TRIANGLE_CLASS && GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].trbpp > 8 && m_cached_ctx.FRAME.Block() != m_cached_ctx.TEX0.TBP0 && !IsMipMapDraw() &&
|
||||
((is_upscale && !IsDiscardingDstColor()) || (IsDiscardingDstColor() && is_downscale)) &&
|
||||
src && src->m_from_target && !src->m_from_target->m_downscaled && m_context->TEX1.MMAG == 1)
|
||||
const bool no_gaps_or_single_sprite = (no_gaps || (m_vt.m_primclass == GS_SPRITE_CLASS && SpriteDrawWithoutGaps()));
|
||||
if (no_gaps_or_single_sprite && m_vt.m_primclass >= GS_TRIANGLE_CLASS && m_context->TEX1.MMAG == 1 && src && src->m_from_target &&
|
||||
GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].trbpp > 8 && m_cached_ctx.FRAME.Block() != m_cached_ctx.TEX0.TBP0 && !IsMipMapDraw() &&
|
||||
((is_upscale && !IsDiscardingDstColor()) || (IsDiscardingDstColor() && is_downscale)))
|
||||
{
|
||||
GL_INS("%s draw detected - from %dx%d to %dx%d", is_downscale ? "Downscale" : "Upscale", tex_size.x, tex_size.y, draw_size.x, draw_size.y);
|
||||
return is_upscale ? 2 : 1;
|
||||
|
|
|
@ -2398,7 +2398,6 @@ GSTextureCache::Target* GSTextureCache::CreateTarget(GIFRegTEX0 TEX0, const GSVe
|
|||
dst->readbacks_since_draw = 0;
|
||||
|
||||
dst->m_last_draw = GSState::s_n;
|
||||
dst->m_downscaled = scale != GSRendererHW::GetInstance()->GetTextureScaleFactor();
|
||||
|
||||
if (dst->m_dirty.empty() && GSLocalMemory::m_psm[TEX0.PSM].depth == 0 && (GSUtil::GetChannelMask(TEX0.PSM) & 0x8))
|
||||
dst->m_rt_alpha_scale = true;
|
||||
|
|
Loading…
Reference in New Issue