mirror of https://github.com/PCSX2/pcsx2.git
GS/HW: Improve Round Sprite upscaling fix to cause less problems
This commit is contained in:
parent
671255c684
commit
5f4d2b3905
|
@ -1859,42 +1859,136 @@ void GSRendererHW::RoundSpriteOffset()
|
|||
for (u32 i = 0; i < count; i += 2)
|
||||
{
|
||||
// Performance note: if it had any impact on perf, someone would port it to SSE (AKA GSVector)
|
||||
|
||||
// Compute the coordinate of first and last texels (in native with a linear filtering)
|
||||
// if the draw is page aligned, then don't round it.
|
||||
const int tex_width = std::max(1, (v[i + 1].U - v[i].U) >> 4);
|
||||
const int ox = m_context->XYOFFSET.OFX;
|
||||
const int X0 = v[i].XYZ.X - ox;
|
||||
const int X1 = v[i + 1].XYZ.X - ox;
|
||||
const int Lx = (v[i + 1].XYZ.X - v[i].XYZ.X);
|
||||
const float ax0 = alpha0(Lx, X0, X1);
|
||||
const float ax1 = alpha1(Lx, X0, X1);
|
||||
const u16 tx0 = Interpolate_UV(ax0, v[i].U, v[i + 1].U);
|
||||
const u16 tx1 = Interpolate_UV(ax1, v[i].U, v[i + 1].U);
|
||||
|
||||
if ((((Lx - ox) >> 4) % tex_width) != 0)
|
||||
{
|
||||
// Compute the coordinate of first and last texels (in native with a linear filtering)
|
||||
const int X0 = v[i].XYZ.X - ox;
|
||||
const int X1 = v[i + 1].XYZ.X - ox;
|
||||
const float ax0 = alpha0(Lx, X0, X1);
|
||||
const float ax1 = alpha1(Lx, X0, X1);
|
||||
const u16 tx0 = Interpolate_UV(ax0, v[i].U, v[i + 1].U);
|
||||
const u16 tx1 = Interpolate_UV(ax1, v[i].U, v[i + 1].U);
|
||||
//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);
|
||||
#ifdef DEBUG_U
|
||||
if (debug)
|
||||
{
|
||||
fprintf(stderr, "u0:%d and u1:%d\n", v[i].U, v[i + 1].U);
|
||||
fprintf(stderr, "a0:%f and a1:%f\n", ax0, ax1);
|
||||
fprintf(stderr, "t0:%d and t1:%d\n", tx0, tx1);
|
||||
}
|
||||
if (debug)
|
||||
{
|
||||
fprintf(stderr, "u0:%d and u1:%d\n", v[i].U, v[i + 1].U);
|
||||
fprintf(stderr, "a0:%f and a1:%f\n", ax0, ax1);
|
||||
fprintf(stderr, "t0:%d and t1:%d\n", tx0, tx1);
|
||||
}
|
||||
#endif
|
||||
#if 1
|
||||
// Use rounded value of the newly computed texture coordinate. It ensures
|
||||
// that sampling will remains inside texture boundary
|
||||
//
|
||||
// Note for bilinear: by definition it will never work correctly! A sligh modification
|
||||
// of interpolation migth trigger a discard (with alpha testing)
|
||||
// Let's use something simple that correct really bad case (for a couple of 2D games).
|
||||
// I hope it won't create too much glitches.
|
||||
if (linear)
|
||||
{
|
||||
const int Lu = v[i + 1].U - v[i].U;
|
||||
// Note 32 is based on taisho-mononoke
|
||||
if ((Lu > 0) && (Lu <= (Lx + 32)))
|
||||
{
|
||||
v[i + 1].U -= 8;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tx0 <= tx1)
|
||||
{
|
||||
v[i].U = tx0;
|
||||
v[i + 1].U = tx1 + 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
v[i].U = tx0 + 15;
|
||||
v[i + 1].U = tx1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
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)
|
||||
{
|
||||
v[i].U &= ~0xf;
|
||||
v[i + 1].U -= 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
v[i].U &= ~0xf;
|
||||
v[i + 1].U &= ~0xf;
|
||||
v[i].U |= (v[i].XYZ.X - ox) & 0xf;
|
||||
v[i + 1].U |= (v[i + 1].XYZ.X - ox) & 0xf;
|
||||
}
|
||||
}
|
||||
|
||||
const int tex_height = std::max(1, (v[i + 1].V - v[i].V) >> 4);
|
||||
const int oy = m_context->XYOFFSET.OFY;
|
||||
const int Y0 = v[i].XYZ.Y - oy;
|
||||
const int Y1 = v[i + 1].XYZ.Y - oy;
|
||||
const int Ly = (v[i + 1].XYZ.Y - v[i].XYZ.Y);
|
||||
const float ay0 = alpha0(Ly, Y0, Y1);
|
||||
const float ay1 = alpha1(Ly, Y0, Y1);
|
||||
const u16 ty0 = Interpolate_UV(ay0, v[i].V, v[i + 1].V);
|
||||
const u16 ty1 = Interpolate_UV(ay1, v[i].V, v[i + 1].V);
|
||||
#ifdef DEBUG_V
|
||||
if (debug)
|
||||
{
|
||||
fprintf(stderr, "v0:%d and v1:%d\n", v[i].V, v[i + 1].V);
|
||||
fprintf(stderr, "a0:%f and a1:%f\n", ay0, ay1);
|
||||
fprintf(stderr, "t0:%d and t1:%d\n", ty0, ty1);
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((((Ly - oy) >> 4) % tex_height) != 0)
|
||||
{
|
||||
const int Y0 = v[i].XYZ.Y - oy;
|
||||
const int Y1 = v[i + 1].XYZ.Y - oy;
|
||||
const float ay0 = alpha0(Ly, Y0, Y1);
|
||||
const float ay1 = alpha1(Ly, Y0, Y1);
|
||||
const u16 ty0 = Interpolate_UV(ay0, v[i].V, v[i + 1].V);
|
||||
const u16 ty1 = Interpolate_UV(ay1, v[i].V, v[i + 1].V);
|
||||
#ifdef DEBUG_V
|
||||
if (debug)
|
||||
{
|
||||
fprintf(stderr, "v0:%d and v1:%d\n", v[i].V, v[i + 1].V);
|
||||
fprintf(stderr, "a0:%f and a1:%f\n", ay0, ay1);
|
||||
fprintf(stderr, "t0:%d and t1:%d\n", ty0, ty1);
|
||||
}
|
||||
#endif
|
||||
#if 1
|
||||
if (linear)
|
||||
{
|
||||
const int Lv = v[i + 1].V - v[i].V;
|
||||
if ((Lv > 0) && (Lv <= (Ly + 32)))
|
||||
{
|
||||
v[i + 1].V -= 8;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ty0 <= ty1)
|
||||
{
|
||||
v[i].V = ty0;
|
||||
v[i + 1].V = ty1 + 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
v[i].V = ty0 + 15;
|
||||
v[i + 1].V = ty1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
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)
|
||||
{
|
||||
v[i].V &= ~0xf;
|
||||
v[i + 1].V -= 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
v[i].V &= ~0xf;
|
||||
v[i + 1].V &= ~0xf;
|
||||
v[i].V |= (v[i].XYZ.Y - oy) & 0xf;
|
||||
v[i + 1].V |= (v[i + 1].XYZ.Y - oy) & 0xf;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG_U
|
||||
if (debug)
|
||||
fprintf(stderr, "GREP_BEFORE %d => %d\n", v[i].U, v[i + 1].U);
|
||||
|
@ -1904,60 +1998,6 @@ void GSRendererHW::RoundSpriteOffset()
|
|||
fprintf(stderr, "GREP_BEFORE %d => %d\n", v[i].V, v[i + 1].V);
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
// Use rounded value of the newly computed texture coordinate. It ensures
|
||||
// that sampling will remains inside texture boundary
|
||||
//
|
||||
// Note for bilinear: by definition it will never work correctly! A sligh modification
|
||||
// of interpolation migth trigger a discard (with alpha testing)
|
||||
// Let's use something simple that correct really bad case (for a couple of 2D games).
|
||||
// I hope it won't create too much glitches.
|
||||
if (linear)
|
||||
{
|
||||
const int Lu = v[i + 1].U - v[i].U;
|
||||
// Note 32 is based on taisho-mononoke
|
||||
if ((Lu > 0) && (Lu <= (Lx + 32)))
|
||||
{
|
||||
v[i + 1].U -= 8;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tx0 <= tx1)
|
||||
{
|
||||
v[i].U = tx0;
|
||||
v[i + 1].U = tx1 + 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
v[i].U = tx0 + 15;
|
||||
v[i + 1].U = tx1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if 1
|
||||
if (linear)
|
||||
{
|
||||
const int Lv = v[i + 1].V - v[i].V;
|
||||
if ((Lv > 0) && (Lv <= (Ly + 32)))
|
||||
{
|
||||
v[i + 1].V -= 8;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ty0 <= ty1)
|
||||
{
|
||||
v[i].V = ty0;
|
||||
v[i + 1].V = ty1 + 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
v[i].V = ty0 + 15;
|
||||
v[i + 1].V = ty1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_U
|
||||
if (debug)
|
||||
|
|
Loading…
Reference in New Issue