mirror of https://github.com/PCSX2/pcsx2.git
GS: Improve autoflush rect checks
This commit is contained in:
parent
d01ee3163d
commit
283c7fa88c
|
@ -2642,10 +2642,6 @@ __forceinline void GSState::HandleAutoFlush()
|
||||||
// So we need to calculate if a page boundary is being crossed for the format it is in and if the same part of the texture being written and read inside the draw.
|
// So we need to calculate if a page boundary is being crossed for the format it is in and if the same part of the texture being written and read inside the draw.
|
||||||
if (PRIM->TME && (frame_hit || zbuf_hit) && GSUtil::HasSharedBits(frame_z_bp, frame_z_psm, m_context->TEX0.TBP0, m_context->TEX0.PSM))
|
if (PRIM->TME && (frame_hit || zbuf_hit) && GSUtil::HasSharedBits(frame_z_bp, frame_z_psm, m_context->TEX0.TBP0, m_context->TEX0.PSM))
|
||||||
{
|
{
|
||||||
const int page_mask_x = ~(GSLocalMemory::m_psm[m_context->TEX0.PSM].pgs.x - 1);
|
|
||||||
const int page_mask_y = ~(GSLocalMemory::m_psm[m_context->TEX0.PSM].pgs.y - 1);
|
|
||||||
const GSVector4i page_mask = { page_mask_x, page_mask_y, page_mask_x, page_mask_y };
|
|
||||||
|
|
||||||
size_t n = 1;
|
size_t n = 1;
|
||||||
|
|
||||||
switch (GSUtil::GetPrimClass(PRIM->PRIM))
|
switch (GSUtil::GetPrimClass(PRIM->PRIM))
|
||||||
|
@ -2662,6 +2658,19 @@ __forceinline void GSState::HandleAutoFlush()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const int current_tex_end = (int)(m_vertex.tail - (m_vertex.tail % n)) - 1;
|
||||||
|
|
||||||
|
// Make sure including the new vert we have the whole rect to be drawn
|
||||||
|
// Example being a sprite which is 2 verts
|
||||||
|
// Tail = 3 (aka we have one sprite and 1 vert already saved, plus the incoming one)
|
||||||
|
// current_tex_end will be 1 ((3 - (3 % 2 == 1) == 2) - 1), meaning 3-1 = 2, so we have enough data for the full rect.
|
||||||
|
if (((m_vertex.tail - current_tex_end) < n) && PRIM->PRIM != GS_POINTLIST)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const int page_mask_x = ~(GSLocalMemory::m_psm[m_context->TEX0.PSM].pgs.x - 1);
|
||||||
|
const int page_mask_y = ~(GSLocalMemory::m_psm[m_context->TEX0.PSM].pgs.y - 1);
|
||||||
|
const GSVector4i page_mask = { page_mask_x, page_mask_y, page_mask_x, page_mask_y };
|
||||||
|
|
||||||
GSVector4i tex_coord;
|
GSVector4i tex_coord;
|
||||||
// Prepare the currently processed vertex.
|
// Prepare the currently processed vertex.
|
||||||
if (PRIM->FST)
|
if (PRIM->FST)
|
||||||
|
@ -2676,14 +2685,11 @@ __forceinline void GSState::HandleAutoFlush()
|
||||||
}
|
}
|
||||||
|
|
||||||
GSVector4i tex_rect = tex_coord.xyxy();
|
GSVector4i tex_rect = tex_coord.xyxy();
|
||||||
GSVector4i next_rect = tex_rect;
|
|
||||||
const int current_tex_end = (int)(m_index.tail - (m_index.tail % n)) - 1;
|
|
||||||
bool page_crossed = false;
|
|
||||||
|
|
||||||
// Check previous texture co-ordindates to see if we have changed page
|
// Get the rest of the rect.
|
||||||
for (int i = m_index.tail - 1; i >= current_tex_end; i--)
|
for (int i = m_vertex.tail - 1; i > current_tex_end; i--)
|
||||||
{
|
{
|
||||||
const GSVertex* v = &m_vertex.buff[m_index.buff[i]];
|
const GSVertex* v = &m_vertex.buff[i];
|
||||||
|
|
||||||
if (PRIM->FST)
|
if (PRIM->FST)
|
||||||
{
|
{
|
||||||
|
@ -2696,24 +2702,34 @@ __forceinline void GSState::HandleAutoFlush()
|
||||||
tex_coord.y = (int)((1 << m_context->TEX0.TH) * (v->ST.T / v->RGBAQ.Q));
|
tex_coord.y = (int)((1 << m_context->TEX0.TH) * (v->ST.T / v->RGBAQ.Q));
|
||||||
}
|
}
|
||||||
|
|
||||||
next_rect.x = std::min(next_rect.x, tex_coord.x);
|
tex_rect.x = std::min(tex_rect.x, tex_coord.x);
|
||||||
next_rect.z = std::max(next_rect.z, tex_coord.x);
|
tex_rect.z = std::max(tex_rect.z, tex_coord.x);
|
||||||
next_rect.y = std::min(next_rect.y, tex_coord.y);
|
tex_rect.y = std::min(tex_rect.y, tex_coord.y);
|
||||||
next_rect.w = std::max(next_rect.w, tex_coord.y);
|
tex_rect.w = std::max(tex_rect.w, tex_coord.y);
|
||||||
|
|
||||||
const GSVector4i pages = next_rect & page_mask;
|
|
||||||
|
|
||||||
// We have changed page, so ignore the old textures co-ordinates.
|
|
||||||
if (!pages.xyxy().eq(pages.zwzw()))
|
|
||||||
{
|
|
||||||
page_crossed = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
tex_rect = next_rect;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tex_rect += GSVector4i(0, 0, 1, 1); // Intersect goes on space inside the rect
|
// Get the last texture position from the last draw.
|
||||||
|
const GSVertex* v = &m_vertex.buff[m_index.buff[m_index.tail - 1]];
|
||||||
|
|
||||||
|
if (PRIM->FST)
|
||||||
|
{
|
||||||
|
tex_coord.x = v->U >> 4;
|
||||||
|
tex_coord.y = v->V >> 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tex_coord.x = (int)((1 << m_context->TEX0.TW) * (v->ST.S / v->RGBAQ.Q));
|
||||||
|
tex_coord.y = (int)((1 << m_context->TEX0.TH) * (v->ST.T / v->RGBAQ.Q));
|
||||||
|
}
|
||||||
|
|
||||||
|
const GSVector4i pages = tex_rect & page_mask;
|
||||||
|
|
||||||
|
tex_coord = tex_coord & page_mask;
|
||||||
|
|
||||||
|
bool page_crossed = false;
|
||||||
|
|
||||||
|
if (!pages.xyzw().eq(tex_coord.xyxy()))
|
||||||
|
page_crossed = true;
|
||||||
|
|
||||||
if(page_crossed)
|
if(page_crossed)
|
||||||
{
|
{
|
||||||
|
@ -2721,11 +2737,10 @@ __forceinline void GSState::HandleAutoFlush()
|
||||||
if (GSUtil::HasCompatibleBits(m_context->TEX0.PSM, frame_z_psm) && (m_context->FRAME.FBW == m_context->TEX0.TBW))
|
if (GSUtil::HasCompatibleBits(m_context->TEX0.PSM, frame_z_psm) && (m_context->FRAME.FBW == m_context->TEX0.TBW))
|
||||||
{
|
{
|
||||||
// Update the vertex trace, scissor it (important for Jak 3!) and intersect with the current texture.
|
// Update the vertex trace, scissor it (important for Jak 3!) and intersect with the current texture.
|
||||||
if ((m_index.tail - 1) == current_tex_end)
|
m_vt.Update(m_vertex.buff, m_index.buff, m_vertex.tail - m_vertex.head, m_index.tail, GSUtil::GetPrimClass(PRIM->PRIM));
|
||||||
m_vt.Update(m_vertex.buff, m_index.buff, m_vertex.tail - m_vertex.head, m_index.tail, GSUtil::GetPrimClass(PRIM->PRIM));
|
|
||||||
|
|
||||||
// Intersect goes on space inside the rect
|
// Intersect goes on space inside the rect
|
||||||
GSVector4i area_out = GSVector4i(m_vt.m_min.p.xyxy(m_vt.m_max.p)) + GSVector4i(0, 0, 1, 1);
|
GSVector4i area_out = GSVector4i(m_vt.m_min.p.xyxy(m_vt.m_max.p));
|
||||||
// Scissor output
|
// Scissor output
|
||||||
area_out = area_out.rintersect(GSVector4i(m_context->scissor.in));
|
area_out = area_out.rintersect(GSVector4i(m_context->scissor.in));
|
||||||
// Intersect with texture
|
// Intersect with texture
|
||||||
|
@ -2734,7 +2749,6 @@ __forceinline void GSState::HandleAutoFlush()
|
||||||
}
|
}
|
||||||
else // Storage of the TEX and FRAME/Z is different, so uhh, just fall back to flushing each page. It's slower, sorry.
|
else // Storage of the TEX and FRAME/Z is different, so uhh, just fall back to flushing each page. It's slower, sorry.
|
||||||
{
|
{
|
||||||
|
|
||||||
if (m_context->FRAME.FBW == m_context->TEX0.TBW)
|
if (m_context->FRAME.FBW == m_context->TEX0.TBW)
|
||||||
{
|
{
|
||||||
//We know we've changed page, so let's set the dimension to cover the page they're in (for different pixel orders)
|
//We know we've changed page, so let's set the dimension to cover the page they're in (for different pixel orders)
|
||||||
|
@ -2743,8 +2757,7 @@ __forceinline void GSState::HandleAutoFlush()
|
||||||
tex_rect.z += GSLocalMemory::m_psm[m_context->TEX0.PSM].pgs.x;
|
tex_rect.z += GSLocalMemory::m_psm[m_context->TEX0.PSM].pgs.x;
|
||||||
tex_rect.w += GSLocalMemory::m_psm[m_context->TEX0.PSM].pgs.y;
|
tex_rect.w += GSLocalMemory::m_psm[m_context->TEX0.PSM].pgs.y;
|
||||||
|
|
||||||
if ((m_index.tail - 1) == current_tex_end)
|
m_vt.Update(m_vertex.buff, m_index.buff, m_vertex.tail - m_vertex.head, m_index.tail, GSUtil::GetPrimClass(PRIM->PRIM));
|
||||||
m_vt.Update(m_vertex.buff, m_index.buff, m_vertex.tail - m_vertex.head, m_index.tail, GSUtil::GetPrimClass(PRIM->PRIM));
|
|
||||||
|
|
||||||
GSVector4i area_out = GSVector4i(m_vt.m_min.p.xyxy(m_vt.m_max.p)).rintersect(GSVector4i(m_context->scissor.in));
|
GSVector4i area_out = GSVector4i(m_vt.m_min.p.xyxy(m_vt.m_max.p)).rintersect(GSVector4i(m_context->scissor.in));
|
||||||
area_out = area_out & page_mask;
|
area_out = area_out & page_mask;
|
||||||
|
@ -2785,11 +2798,13 @@ __forceinline void GSState::VertexKick(u32 skip)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto_flush && m_index.tail >= n)
|
|
||||||
HandleAutoFlush();
|
|
||||||
|
|
||||||
ASSERT(m_vertex.tail < m_vertex.maxcount + 3);
|
ASSERT(m_vertex.tail < m_vertex.maxcount + 3);
|
||||||
|
|
||||||
|
if (auto_flush && m_index.tail >= n && !skip)
|
||||||
|
{
|
||||||
|
HandleAutoFlush();
|
||||||
|
}
|
||||||
|
|
||||||
size_t head = m_vertex.head;
|
size_t head = m_vertex.head;
|
||||||
size_t tail = m_vertex.tail;
|
size_t tail = m_vertex.tail;
|
||||||
size_t next = m_vertex.next;
|
size_t next = m_vertex.next;
|
||||||
|
@ -2812,7 +2827,6 @@ __forceinline void GSState::VertexKick(u32 skip)
|
||||||
m_vertex.tail = ++tail;
|
m_vertex.tail = ++tail;
|
||||||
m_vertex.xy_tail = ++xy_tail;
|
m_vertex.xy_tail = ++xy_tail;
|
||||||
|
|
||||||
|
|
||||||
size_t m = tail - head;
|
size_t m = tail - head;
|
||||||
|
|
||||||
if (m < n)
|
if (m < n)
|
||||||
|
|
Loading…
Reference in New Issue