mirror of https://github.com/PCSX2/pcsx2.git
GS/HW: Allow 1:1 quads to be optimized for textures. Fixes for shuffles
This commit is contained in:
parent
1ac2d9fba3
commit
fd53ce2ec6
|
@ -3871,7 +3871,8 @@ GSState::TextureMinMaxResult GSState::GetTextureMinMax(GIFRegTEX0 TEX0, GIFRegCL
|
||||||
const GSVector2 grad(uv_range / pos_range);
|
const GSVector2 grad(uv_range / pos_range);
|
||||||
// Adjust texture range when sprites get scissor clipped. Since we linearly interpolate, this
|
// Adjust texture range when sprites get scissor clipped. Since we linearly interpolate, this
|
||||||
// optimization doesn't work when perspective correction is enabled.
|
// optimization doesn't work when perspective correction is enabled.
|
||||||
if (m_vt.m_primclass == GS_SPRITE_CLASS && PRIM->FST == 1 && m_primitive_covers_without_gaps != NoGapsType::GapsFound)
|
// Allowing for quads when the gradiant is 1. It's not guaranteed (would need to check the grandient on each vector), but should be close enough.
|
||||||
|
if ((m_vt.m_primclass == GS_SPRITE_CLASS || (m_vt.m_primclass == GS_TRIANGLE_CLASS && TrianglesAreQuads(false) && grad.x == 1.0f && grad.y == 1.0f)) && m_primitive_covers_without_gaps != NoGapsType::GapsFound)
|
||||||
{
|
{
|
||||||
// When coordinates are fractional, GS appears to draw to the right/bottom (effectively
|
// When coordinates are fractional, GS appears to draw to the right/bottom (effectively
|
||||||
// taking the ceiling), not to the top/left (taking the floor).
|
// taking the ceiling), not to the top/left (taking the floor).
|
||||||
|
@ -3882,11 +3883,24 @@ GSState::TextureMinMaxResult GSState::GetTextureMinMax(GIFRegTEX0 TEX0, GIFRegCL
|
||||||
|
|
||||||
const GSVertex* vert_first = &m_vertex.buff[m_index.buff[0]];
|
const GSVertex* vert_first = &m_vertex.buff[m_index.buff[0]];
|
||||||
const GSVertex* vert_second = &m_vertex.buff[m_index.buff[1]];
|
const GSVertex* vert_second = &m_vertex.buff[m_index.buff[1]];
|
||||||
|
const GSVertex* vert_third = &m_vertex.buff[m_index.buff[2]];
|
||||||
|
|
||||||
GSVector4 new_st = st;
|
GSVector4 new_st = st;
|
||||||
|
bool u_forward_check = false;
|
||||||
|
bool x_forward_check = false;
|
||||||
|
if (m_vt.m_primclass == GS_TRIANGLE_CLASS)
|
||||||
|
{
|
||||||
|
u_forward_check = PRIM->FST ? ((vert_first->U < vert_second->U) || (vert_first->U < vert_third->U)) : (((vert_first->ST.S / vert_first->RGBAQ.Q) < (vert_second->ST.S / vert_second->RGBAQ.Q)) || ((vert_first->ST.S / vert_first->RGBAQ.Q) < (vert_third->ST.S / vert_third->RGBAQ.Q)));
|
||||||
|
x_forward_check = (vert_first->XYZ.X < vert_second->XYZ.X) || (vert_first->XYZ.X < vert_third->XYZ.X);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u_forward_check = PRIM->FST ? (vert_first->U < vert_second->U) : ((vert_first->ST.T / vert_first->RGBAQ.Q) < (vert_second->ST.T / vert_first->RGBAQ.Q));
|
||||||
|
x_forward_check = vert_first->XYZ.Y < vert_second->XYZ.Y;
|
||||||
|
}
|
||||||
// Check if the UV coords are going in a different direction to the verts, if they match direction, no need to swap
|
// Check if the UV coords are going in a different direction to the verts, if they match direction, no need to swap
|
||||||
const bool u_forward = vert_first->U < vert_second->U;
|
const bool u_forward = u_forward_check;
|
||||||
const bool x_forward = vert_first->XYZ.X < vert_second->XYZ.X;
|
const bool x_forward = x_forward_check;
|
||||||
const bool swap_x = u_forward != x_forward;
|
const bool swap_x = u_forward != x_forward;
|
||||||
|
|
||||||
if (int_rc.left < scissored_rc.left)
|
if (int_rc.left < scissored_rc.left)
|
||||||
|
@ -3909,9 +3923,20 @@ GSState::TextureMinMaxResult GSState::GetTextureMinMax(GIFRegTEX0 TEX0, GIFRegCL
|
||||||
st.x = new_st.x;
|
st.x = new_st.x;
|
||||||
st.z = new_st.z;
|
st.z = new_st.z;
|
||||||
}
|
}
|
||||||
|
bool v_forward_check = false;
|
||||||
const bool v_forward = vert_first->V < vert_second->V;
|
bool y_forward_check = false;
|
||||||
const bool y_forward = vert_first->XYZ.Y < vert_second->XYZ.Y;
|
if (m_vt.m_primclass == GS_TRIANGLE_CLASS)
|
||||||
|
{
|
||||||
|
v_forward_check = PRIM->FST ? ((vert_first->V < vert_second->V) || (vert_first->V < vert_third->V)) : (((vert_first->ST.T / vert_first->RGBAQ.Q) < (vert_second->ST.T / vert_second->RGBAQ.Q)) || ((vert_first->ST.T / vert_first->RGBAQ.Q) < (vert_third->ST.T / vert_third->RGBAQ.Q)));
|
||||||
|
y_forward_check = (vert_first->XYZ.Y < vert_second->XYZ.Y) || (vert_first->XYZ.Y < vert_third->XYZ.Y);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
v_forward_check = PRIM->FST ? (vert_first->V < vert_second->V) : ((vert_first->ST.T / vert_first->RGBAQ.Q) < (vert_second->ST.T / vert_first->RGBAQ.Q));
|
||||||
|
y_forward_check = vert_first->XYZ.Y < vert_second->XYZ.Y;
|
||||||
|
}
|
||||||
|
const bool v_forward = v_forward_check;
|
||||||
|
const bool y_forward = y_forward_check;
|
||||||
const bool swap_y = v_forward != y_forward;
|
const bool swap_y = v_forward != y_forward;
|
||||||
|
|
||||||
if (int_rc.top < scissored_rc.top)
|
if (int_rc.top < scissored_rc.top)
|
||||||
|
|
|
@ -1081,7 +1081,7 @@ bool GSHwHack::OI_SonicUnleashed(GSRendererHW& r, GSTexture* rt, GSTexture* ds,
|
||||||
|
|
||||||
const GSVector4 sRect(0.0f, 0.0f, static_cast<float>(copy_size.x) / static_cast<float>(src_size.x), static_cast<float>(copy_size.y) / static_cast<float>(src_size.y));
|
const GSVector4 sRect(0.0f, 0.0f, static_cast<float>(copy_size.x) / static_cast<float>(src_size.x), static_cast<float>(copy_size.y) / static_cast<float>(src_size.y));
|
||||||
// This is kind of a bodge because the game confuses everything since the source is really 16bit and it assumes it's really drawing 16bit on the copy back, resizing the target.
|
// This is kind of a bodge because the game confuses everything since the source is really 16bit and it assumes it's really drawing 16bit on the copy back, resizing the target.
|
||||||
const GSVector4 dRect(0, 0, copy_size.x, copy_size.y * (src->m_32_bits_fmt ? 1 : 2));
|
const GSVector4 dRect(0, 0, copy_size.x, copy_size.y);
|
||||||
|
|
||||||
g_gs_device->StretchRect(src->m_texture, sRect, rt, dRect, true, true, true, false);
|
g_gs_device->StretchRect(src->m_texture, sRect, rt, dRect, true, true, true, false);
|
||||||
|
|
||||||
|
|
|
@ -2584,7 +2584,7 @@ void GSRendererHW::Draw()
|
||||||
GIFRegTEX0 FRAME_TEX0;
|
GIFRegTEX0 FRAME_TEX0;
|
||||||
bool shuffle_target = false;
|
bool shuffle_target = false;
|
||||||
if (!no_rt && GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].bpp == 16 && GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].bpp >= 16 &&
|
if (!no_rt && GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].bpp == 16 && GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].bpp >= 16 &&
|
||||||
(m_vt.m_primclass == GS_SPRITE_CLASS || (m_vt.m_primclass == GS_TRIANGLE_CLASS && (m_index.tail % 6) == 0 && TrianglesAreQuads(true))))
|
(m_vt.m_primclass == GS_SPRITE_CLASS || (m_vt.m_primclass == GS_TRIANGLE_CLASS && (m_index.tail % 6) == 0 && TrianglesAreQuads(true) && m_index.tail > 6)))
|
||||||
{
|
{
|
||||||
if (!shuffle_target && GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].bpp == 16)
|
if (!shuffle_target && GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].bpp == 16)
|
||||||
{
|
{
|
||||||
|
@ -2653,7 +2653,7 @@ void GSRendererHW::Draw()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
possible_shuffle &= src && (src->m_from_target != nullptr && (src->m_from_target->m_32_bits_fmt) || (m_skip && possible_shuffle));
|
possible_shuffle &= src && (src->m_from_target != nullptr || (m_skip && possible_shuffle));
|
||||||
// We don't know the alpha range of direct sources when we first tried to optimize the alpha test.
|
// We don't know the alpha range of direct sources when we first tried to optimize the alpha test.
|
||||||
// Moving the texture lookup before the ATST optimization complicates things a lot, so instead,
|
// Moving the texture lookup before the ATST optimization complicates things a lot, so instead,
|
||||||
// recompute it, and everything derived from it again if it changes.
|
// recompute it, and everything derived from it again if it changes.
|
||||||
|
@ -4429,7 +4429,7 @@ __ri bool GSRendererHW::EmulateChannelShuffle(GSTextureCache::Target* src, bool
|
||||||
// Performance GPU note: it could be wise to reduce the size to
|
// Performance GPU note: it could be wise to reduce the size to
|
||||||
// the rendered size of the framebuffer
|
// the rendered size of the framebuffer
|
||||||
|
|
||||||
if (GSConfig.UserHacks_TextureInsideRt == GSTextureInRtMode::Disabled || (!m_in_target_draw && IsPageCopy()))
|
if (GSConfig.UserHacks_TextureInsideRt == GSTextureInRtMode::Disabled || (!m_in_target_draw && IsPageCopy()) || m_conf.ps.urban_chaos_hle || m_conf.ps.tales_of_abyss_hle)
|
||||||
{
|
{
|
||||||
GSVertex* s = &m_vertex.buff[0];
|
GSVertex* s = &m_vertex.buff[0];
|
||||||
s[0].XYZ.X = static_cast<u16>(m_context->XYOFFSET.OFX + 0);
|
s[0].XYZ.X = static_cast<u16>(m_context->XYOFFSET.OFX + 0);
|
||||||
|
@ -5703,7 +5703,7 @@ __ri void GSRendererHW::HandleTextureHazards(const GSTextureCache::Target* rt, c
|
||||||
target_region = false;
|
target_region = false;
|
||||||
source_region.bits = 0;
|
source_region.bits = 0;
|
||||||
//copied_rt = tex->m_from_target != nullptr;
|
//copied_rt = tex->m_from_target != nullptr;
|
||||||
if (m_in_target_draw)
|
if (page_offset && m_in_target_draw)
|
||||||
{
|
{
|
||||||
copy_size.x = m_r.width();
|
copy_size.x = m_r.width();
|
||||||
copy_size.y = m_r.height();
|
copy_size.y = m_r.height();
|
||||||
|
|
Loading…
Reference in New Issue