GS/HW: Improve draw rect accuracy

This commit is contained in:
Stenzek 2023-06-13 00:21:40 +10:00 committed by Connor McLaughlin
parent 7c9c8e197c
commit fbd837eadb
2 changed files with 19 additions and 4 deletions

View File

@ -737,7 +737,7 @@ bool GSHwHack::OI_PointListPalette(GSRendererHW& r, GSTexture* rt, GSTexture* ds
{
const u32 FBP = r.m_cached_ctx.FRAME.Block();
const u32 FBW = r.m_cached_ctx.FRAME.FBW;
GL_INS("PointListPalette - m_r = <%d, %d => %d, %d>, n_vertices = %zu, FBP = 0x%x, FBW = %u", r.m_r.x, r.m_r.y, r.m_r.z, r.m_r.w, n_vertices, FBP, FBW);
GL_INS("PointListPalette - m_r = <%d, %d => %d, %d>, n_vertices = %u, FBP = 0x%x, FBW = %u", r.m_r.x, r.m_r.y, r.m_r.z, r.m_r.w, n_vertices, FBP, FBW);
const GSVertex* RESTRICT v = r.m_vertex.buff;
const int ox(r.m_context->XYOFFSET.OFX);
const int oy(r.m_context->XYOFFSET.OFY);

View File

@ -1670,9 +1670,24 @@ void GSRendererHW::Draw()
return;
}
// The rectangle of the draw rounded up.
const GSVector4 rect = m_vt.m_min.p.upld(m_vt.m_max.p + GSVector4::cxpr(0.5f));
m_r = GSVector4i(rect).rintersect(context->scissor.in);
// GS doesn't fill the right or bottom edges of sprites/triangles, and for a pixel to be shaded, the vertex
// must cross the center. In other words, the range is equal to the floor of coordinates +0.5. Except for
// the case where the minimum equals the maximum, because at least one pixel is filled per line.
// Test cases for the math:
// --------------------------------------
// | Position range | Draw Range | Size |
// | -0.5,0.0 | 0-0 | 1 |
// | -0.5,0.5 | 0-0 | 1 |
// | 0,1 | 0-0 | 1 |
// | 0,1.5 | 0-1 | 2 |
// | 0.5,1.5 | 1-1 | 1 |
// | 0.5,1.75 | 1-1 | 1 |
// | 0.5,2.25 | 1-1 | 1 |
// | 0.5,2.5 | 1-2 | 2 |
// --------------------------------------
m_r = GSVector4i(m_vt.m_min.p.upld(m_vt.m_max.p) + GSVector4::cxpr(0.5f));
m_r = m_r.blend8(m_r + GSVector4i::cxpr(0, 0, 1, 1), (m_r.xyxy() == m_r.zwzw()));
m_r = m_r.rintersect(context->scissor.in);
const bool process_texture = PRIM->TME && !(PRIM->ABE && m_context->ALPHA.IsBlack() && !m_cached_ctx.TEX0.TCC);
const u32 frame_end_bp = GSLocalMemory::GetEndBlockAddress(m_cached_ctx.FRAME.Block(), m_cached_ctx.FRAME.FBW, m_cached_ctx.FRAME.PSM, m_r);