Skip to content

Commit 5298e6a

Browse files
GS/HW: Improve Round Sprite upscaling fix to cause less problems
1 parent 3b7ad78 commit 5298e6a

1 file changed

Lines changed: 107 additions & 67 deletions

File tree

pcsx2/GS/Renderers/HW/GSRendererHW.cpp

Lines changed: 107 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1704,106 +1704,146 @@ void GSRendererHW::RoundSpriteOffset()
17041704
for (u32 i = 0; i < count; i += 2)
17051705
{
17061706
// Performance note: if it had any impact on perf, someone would port it to SSE (AKA GSVector)
1707-
1708-
// Compute the coordinate of first and last texels (in native with a linear filtering)
1707+
// if the draw is page aligned, then don't round it.
1708+
const int tex_width = std::max(1, (v[i + 1].U - v[i].U) >> 4);
17091709
const int ox = m_context->XYOFFSET.OFX;
1710-
const int X0 = v[i].XYZ.X - ox;
1711-
const int X1 = v[i + 1].XYZ.X - ox;
17121710
const int Lx = (v[i + 1].XYZ.X - v[i].XYZ.X);
1713-
const float ax0 = alpha0(Lx, X0, X1);
1714-
const float ax1 = alpha1(Lx, X0, X1);
1715-
const u16 tx0 = Interpolate_UV(ax0, v[i].U, v[i + 1].U);
1716-
const u16 tx1 = Interpolate_UV(ax1, v[i].U, v[i + 1].U);
1717-
#ifdef DEBUG_U
1718-
if (debug)
1719-
{
1720-
fprintf(stderr, "u0:%d and u1:%d\n", v[i].U, v[i + 1].U);
1721-
fprintf(stderr, "a0:%f and a1:%f\n", ax0, ax1);
1722-
fprintf(stderr, "t0:%d and t1:%d\n", tx0, tx1);
1723-
}
1724-
#endif
17251711

1726-
const int oy = m_context->XYOFFSET.OFY;
1727-
const int Y0 = v[i].XYZ.Y - oy;
1728-
const int Y1 = v[i + 1].XYZ.Y - oy;
1729-
const int Ly = (v[i + 1].XYZ.Y - v[i].XYZ.Y);
1730-
const float ay0 = alpha0(Ly, Y0, Y1);
1731-
const float ay1 = alpha1(Ly, Y0, Y1);
1732-
const u16 ty0 = Interpolate_UV(ay0, v[i].V, v[i + 1].V);
1733-
const u16 ty1 = Interpolate_UV(ay1, v[i].V, v[i + 1].V);
1734-
#ifdef DEBUG_V
1735-
if (debug)
1712+
if ((((Lx - ox) >> 4) % tex_width) != 0)
17361713
{
1737-
fprintf(stderr, "v0:%d and v1:%d\n", v[i].V, v[i + 1].V);
1738-
fprintf(stderr, "a0:%f and a1:%f\n", ay0, ay1);
1739-
fprintf(stderr, "t0:%d and t1:%d\n", ty0, ty1);
1740-
}
1741-
#endif
1742-
1714+
// Compute the coordinate of first and last texels (in native with a linear filtering)
1715+
const int X0 = v[i].XYZ.X - ox;
1716+
const int X1 = v[i + 1].XYZ.X - ox;
1717+
const float ax0 = alpha0(Lx, X0, X1);
1718+
const float ax1 = alpha1(Lx, X0, X1);
1719+
const u16 tx0 = Interpolate_UV(ax0, v[i].U, v[i + 1].U);
1720+
const u16 tx1 = Interpolate_UV(ax1, v[i].U, v[i + 1].U);
1721+
//DevCon.Warning("Tex width %d draw width %d (X %x -> %x U %x -> %x", tex_width, ((v[i + 1].XYZ.X - v[i].XYZ.X) >> 4), X0, X1, v[i].U, v[i+1].U);
17431722
#ifdef DEBUG_U
1744-
if (debug)
1745-
fprintf(stderr, "GREP_BEFORE %d => %d\n", v[i].U, v[i + 1].U);
1746-
#endif
1747-
#ifdef DEBUG_V
1748-
if (debug)
1749-
fprintf(stderr, "GREP_BEFORE %d => %d\n", v[i].V, v[i + 1].V);
1723+
if (debug)
1724+
{
1725+
fprintf(stderr, "u0:%d and u1:%d\n", v[i].U, v[i + 1].U);
1726+
fprintf(stderr, "a0:%f and a1:%f\n", ax0, ax1);
1727+
fprintf(stderr, "t0:%d and t1:%d\n", tx0, tx1);
1728+
}
17501729
#endif
1751-
17521730
#if 1
1753-
// Use rounded value of the newly computed texture coordinate. It ensures
1754-
// that sampling will remains inside texture boundary
1755-
//
1756-
// Note for bilinear: by definition it will never work correctly! A sligh modification
1757-
// of interpolation migth trigger a discard (with alpha testing)
1758-
// Let's use something simple that correct really bad case (for a couple of 2D games).
1759-
// I hope it won't create too much glitches.
1760-
if (linear)
1761-
{
1762-
const int Lu = v[i + 1].U - v[i].U;
1763-
// Note 32 is based on taisho-mononoke
1764-
if ((Lu > 0) && (Lu <= (Lx + 32)))
1731+
// Use rounded value of the newly computed texture coordinate. It ensures
1732+
// that sampling will remains inside texture boundary
1733+
//
1734+
// Note for bilinear: by definition it will never work correctly! A sligh modification
1735+
// of interpolation migth trigger a discard (with alpha testing)
1736+
// Let's use something simple that correct really bad case (for a couple of 2D games).
1737+
// I hope it won't create too much glitches.
1738+
if (linear)
17651739
{
1766-
v[i + 1].U -= 8;
1740+
const int Lu = v[i + 1].U - v[i].U;
1741+
// Note 32 is based on taisho-mononoke
1742+
if ((Lu > 0) && (Lu <= (Lx + 32)))
1743+
{
1744+
v[i + 1].U -= 8;
1745+
}
17671746
}
1747+
else
1748+
{
1749+
if (tx0 <= tx1)
1750+
{
1751+
v[i].U = tx0;
1752+
v[i + 1].U = tx1 + 16;
1753+
}
1754+
else
1755+
{
1756+
v[i].U = tx0 + 15;
1757+
v[i + 1].U = tx1;
1758+
}
1759+
}
1760+
#endif
17681761
}
17691762
else
17701763
{
1771-
if (tx0 <= tx1)
1764+
if (((v[i + 1].U & 0xf) ^ ((v[i + 1].XYZ.X - ox) & 0xf)) && ((v[i + 1].U - v[i].U) >> 4) == tex_width && (Lx >> 4) / tex_width <= 2)
17721765
{
1773-
v[i].U = tx0;
1774-
v[i + 1].U = tx1 + 16;
1766+
v[i].U &= ~0xf;
1767+
v[i + 1].U -= 8;
17751768
}
17761769
else
17771770
{
1778-
v[i].U = tx0 + 15;
1779-
v[i + 1].U = tx1;
1771+
v[i].U &= ~0xf;
1772+
v[i + 1].U &= ~0xf;
1773+
v[i].U |= (v[i].XYZ.X - ox) & 0xf;
1774+
v[i + 1].U |= (v[i + 1].XYZ.X - ox) & 0xf;
17801775
}
17811776
}
1777+
1778+
const int tex_height = std::max(1, (v[i + 1].V - v[i].V) >> 4);
1779+
const int oy = m_context->XYOFFSET.OFY;
1780+
const int Ly = (v[i + 1].XYZ.Y - v[i].XYZ.Y);
1781+
1782+
if ((((Ly - oy) >> 4) % tex_height) != 0)
1783+
{
1784+
const int Y0 = v[i].XYZ.Y - oy;
1785+
const int Y1 = v[i + 1].XYZ.Y - oy;
1786+
const float ay0 = alpha0(Ly, Y0, Y1);
1787+
const float ay1 = alpha1(Ly, Y0, Y1);
1788+
const u16 ty0 = Interpolate_UV(ay0, v[i].V, v[i + 1].V);
1789+
const u16 ty1 = Interpolate_UV(ay1, v[i].V, v[i + 1].V);
1790+
#ifdef DEBUG_V
1791+
if (debug)
1792+
{
1793+
fprintf(stderr, "v0:%d and v1:%d\n", v[i].V, v[i + 1].V);
1794+
fprintf(stderr, "a0:%f and a1:%f\n", ay0, ay1);
1795+
fprintf(stderr, "t0:%d and t1:%d\n", ty0, ty1);
1796+
}
17821797
#endif
17831798
#if 1
1784-
if (linear)
1785-
{
1786-
const int Lv = v[i + 1].V - v[i].V;
1787-
if ((Lv > 0) && (Lv <= (Ly + 32)))
1799+
if (linear)
17881800
{
1789-
v[i + 1].V -= 8;
1801+
const int Lv = v[i + 1].V - v[i].V;
1802+
if ((Lv > 0) && (Lv <= (Ly + 32)))
1803+
{
1804+
v[i + 1].V -= 8;
1805+
}
1806+
}
1807+
else
1808+
{
1809+
if (ty0 <= ty1)
1810+
{
1811+
v[i].V = ty0;
1812+
v[i + 1].V = ty1 + 16;
1813+
}
1814+
else
1815+
{
1816+
v[i].V = ty0 + 15;
1817+
v[i + 1].V = ty1;
1818+
}
17901819
}
1820+
#endif
17911821
}
17921822
else
17931823
{
1794-
if (ty0 <= ty1)
1824+
if (((v[i + 1].V & 0xf) ^ ((v[i + 1].XYZ.Y - oy) & 0xf)) && ((v[i + 1].V - v[i].V) >> 4) == tex_height && (Ly >> 4) / tex_height <= 2)
17951825
{
1796-
v[i].V = ty0;
1797-
v[i + 1].V = ty1 + 16;
1826+
v[i].V &= ~0xf;
1827+
v[i + 1].V -= 8;
17981828
}
17991829
else
18001830
{
1801-
v[i].V = ty0 + 15;
1802-
v[i + 1].V = ty1;
1831+
v[i].V &= ~0xf;
1832+
v[i + 1].V &= ~0xf;
1833+
v[i].V |= (v[i].XYZ.Y - oy) & 0xf;
1834+
v[i + 1].V |= (v[i + 1].XYZ.Y - oy) & 0xf;
18031835
}
18041836
}
1837+
#ifdef DEBUG_U
1838+
if (debug)
1839+
fprintf(stderr, "GREP_BEFORE %d => %d\n", v[i].U, v[i + 1].U);
1840+
#endif
1841+
#ifdef DEBUG_V
1842+
if (debug)
1843+
fprintf(stderr, "GREP_BEFORE %d => %d\n", v[i].V, v[i + 1].V);
18051844
#endif
18061845

1846+
18071847
#ifdef DEBUG_U
18081848
if (debug)
18091849
fprintf(stderr, "GREP_AFTER %d => %d\n\n", v[i].U, v[i + 1].U);

0 commit comments

Comments
 (0)