Skip to content

Commit 9791faa

Browse files
committed
GS: Refactor GSVertexTrace.
1 parent 0e6f790 commit 9791faa

File tree

3 files changed

+137
-193
lines changed

3 files changed

+137
-193
lines changed

pcsx2/GS/Renderers/Common/GSVertexTrace.cpp

Lines changed: 55 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -18,57 +18,95 @@ void GSVertexTrace::Update(const void* vertex, const u16* index, int v_count, in
1818
if (i_count == 0)
1919
return;
2020

21+
const GSDrawingContext* context = m_state->m_context;
22+
2123
m_primclass = primclass;
2224

25+
// Setup selector parameters for FindMinMax()
2326
const u32 iip = m_state->PRIM->IIP;
2427
const u32 tme = m_state->PRIM->TME;
2528
const u32 fst = m_state->PRIM->FST;
26-
const u32 color = !(m_state->PRIM->TME && m_state->m_context->TEX0.TFX == TFX_DECAL && m_state->m_context->TEX0.TCC);
29+
const u32 color = !(m_state->PRIM->TME && context->TEX0.TFX == TFX_DECAL && context->TEX0.TCC);
2730

28-
m_fmm[color][fst][tme][iip][primclass](*this, vertex, index, i_count);
31+
// Select correct FindMinMax() function to calculaute raw min/max values
32+
GSVector4 tmin, tmax;
33+
GSVector4i cmin, cmax, pmin, pmax;
34+
m_fmm[color][fst][tme][iip][primclass](vertex, index, i_count, tmin, tmax, cmin, cmax, pmin, pmax);
2935

30-
// Potential float overflow detected. Better uses the slower division instead
31-
// Note: If Q is too big, 1/Q will end up as 0. 1e30 is a random number
32-
// that feel big enough.
33-
if (!fst && !m_accurate_stq && m_min.t.z > 1e30)
36+
// Set m_min and m_max values based on the raw min/max values
37+
const GSVector4 offset(m_state->m_context->XYOFFSET);
38+
const GSVector4 pscale(1.0f / 16, 1.0f / 16, 0.0f, 1.0f);
39+
40+
m_min.p = (GSVector4(pmin) - offset) * pscale;
41+
m_max.p = (GSVector4(pmax) - offset) * pscale;
42+
43+
// Do Z separately, requires unsigned int conversion
44+
m_min.p.z = static_cast<float>(static_cast<u32>(pmin.z));
45+
m_max.p.z = static_cast<float>(static_cast<u32>(pmax.z));
46+
47+
m_min.t = GSVector4::zero();
48+
m_max.t = GSVector4::zero();
49+
m_min.c = GSVector4i::zero();
50+
m_max.c = GSVector4i::zero();
51+
52+
if (tme)
3453
{
35-
Console.Warning("Vertex Trace: float overflow detected ! min %e max %e", m_min.t.z, m_max.t.z);
36-
m_accurate_stq = true;
54+
GSVector4 tscale;
55+
if (fst)
56+
tscale = GSVector4(1.0f / 16, 1.0f / 16, 1.0f, 1.0f);
57+
else
58+
tscale = GSVector4(static_cast<float>(1 << context->TEX0.TW), static_cast<float>(1 << context->TEX0.TH), 1.0f, 1.0f);
59+
m_min.t = tmin * tscale;
60+
m_max.t = tmax * tscale;
61+
}
62+
63+
if (color)
64+
{
65+
m_min.c = cmin.u8to32();
66+
m_max.c = cmax.u8to32();
3767
}
3868

3969
// AA1: Set alpha min max to coverage 128 when there is no alpha blending.
40-
if (!m_state->PRIM->ABE && m_state->PRIM->AA1 && (m_primclass == GS_LINE_CLASS || m_primclass == GS_TRIANGLE_CLASS))
70+
if (!m_state->PRIM->ABE && m_state->PRIM->AA1 && (primclass == GS_LINE_CLASS || primclass == GS_TRIANGLE_CLASS))
4171
{
4272
m_min.c.a = 128;
4373
m_max.c.a = 128;
4474
}
4575

46-
m_eq.value = (m_min.c == m_max.c).mask() | ((m_min.p == m_max.p).mask() << 16) | ((m_min.t == m_max.t).mask() << 20);
47-
4876
m_alpha.valid = false;
4977

50-
// I'm not sure of the cost. In doubt let's do it only when depth is enabled
51-
if (m_state->m_context->TEST.ZTE == 1 && m_state->m_context->TEST.ZTST > ZTST_ALWAYS)
78+
// Set m_eq flags for when vertex values are constant.
79+
const u32 t_eq = (m_min.t == m_max.t).mask(); // GSVector4, 4 bit mask.
80+
const u32 p_eq = GSVector4::cast(pmin == pmax).mask(); // Cast to GSVector4() for 4 bit mask.
81+
const u32 c_eq = (m_min.c == m_max.c).mask(); // GSVector4i, 16 bit mask.
82+
m_eq.value = c_eq | (p_eq << 16) | (t_eq << 20);
83+
84+
// Potential float overflow detected. Better uses the slower division instead
85+
// Note: If Q is too big, 1/Q will end up as 0. 1e30 is a random number
86+
// that feel big enough.
87+
if (!fst && !m_accurate_stq && m_min.t.z > 1e30)
5288
{
53-
CorrectDepthTrace(vertex, v_count);
89+
Console.Warning("Vertex Trace: float overflow detected ! min %e max %e", m_min.t.z, m_max.t.z);
90+
m_accurate_stq = true;
5491
}
5592

93+
// Determine mipmapping LOD and whether linear filter is used.
5694
if (tme)
5795
{
5896
const GIFRegTEX1& TEX1 = m_state->m_context->TEX1;
5997

6098
m_filter.mmag = TEX1.IsMagLinear();
6199
m_filter.mmin = TEX1.IsMinLinear();
62100

63-
if (TEX1.MXL == 0) // MXL == 0 => MMIN ignored, tested it on ps2
101+
if (TEX1.MXL == 0) // MXL == 0 => MMIN ignored, tested it on ps2.
64102
{
65103
m_filter.linear = m_filter.mmag;
66104
}
67105
else
68106
{
69107
const float K = static_cast<float>(TEX1.K) / 16;
70108

71-
if (TEX1.LCM == 0 && m_state->PRIM->FST == 0) // FST == 1 => Q is not interpolated
109+
if (TEX1.LCM == 0 && m_state->PRIM->FST == 0) // FST == 1 => Q is not interpolated.
72110
{
73111
// LOD = log2(1/|Q|) * (1 << L) + K
74112

@@ -108,7 +146,7 @@ void GSVertexTrace::Update(const void* vertex, const u16* index, int v_count, in
108146
break;
109147

110148
case BiFiltering::Forced_But_Sprite:
111-
// Special case to reduce the number of glitch when upscaling is enabled
149+
// Special case to reduce the number of glitch when upscaling is enabled.
112150
m_filter.opt_linear = (m_primclass == GS_SPRITE_CLASS) ? m_filter.linear : 1;
113151
break;
114152

@@ -123,50 +161,3 @@ void GSVertexTrace::Update(const void* vertex, const u16* index, int v_count, in
123161
}
124162
}
125163
}
126-
127-
void GSVertexTrace::CorrectDepthTrace(const void* vertex, int count)
128-
{
129-
if (m_eq.z == 0)
130-
return;
131-
132-
// FindMinMax isn't accurate for the depth value. Lsb bit is always 0.
133-
// The code below will check that depth value is really constant
134-
// and will update m_min/m_max/m_eq accordingly
135-
//
136-
// Really impact Xenosaga3
137-
//
138-
// Hopefully function is barely called so AVX/SSE will be useless here
139-
140-
141-
const GSVertex* RESTRICT v = (GSVertex*)vertex;
142-
143-
const int sprite_step = (m_primclass == GS_SPRITE_CLASS) ? 1 : 0;
144-
145-
u32 z = v[sprite_step].XYZ.Z;
146-
147-
if (z & 1)
148-
{
149-
// Check that first bit is always 1
150-
for (int i = sprite_step; i < count; i += (sprite_step + 1))
151-
{
152-
z &= v[i].XYZ.Z;
153-
}
154-
}
155-
else
156-
{
157-
// Check that first bit is always 0
158-
for (int i = sprite_step; i < count; i += (sprite_step + 1))
159-
{
160-
z |= v[i].XYZ.Z;
161-
}
162-
}
163-
164-
if (z == v[sprite_step].XYZ.Z)
165-
{
166-
m_eq.z = 1;
167-
}
168-
else
169-
{
170-
m_eq.z = 0;
171-
}
172-
}

pcsx2/GS/Renderers/Common/GSVertexTrace.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@ class alignas(32) GSVertexTrace final : public GSAlignedClass<32>
3737
protected:
3838
const GSState* m_state;
3939

40-
typedef void (*FindMinMaxPtr)(GSVertexTrace& vt, const void* vertex, const u16* index, int count);
40+
typedef void (*FindMinMaxPtr)(const void* vertex, const u16* index, int count,
41+
GSVector4& tmin_out, GSVector4& tmax_out, GSVector4i& cmin_out, GSVector4i& cmax_out,
42+
GSVector4i& pmin_out, GSVector4i& pmax_out);
4143

4244
FindMinMaxPtr m_fmm[2][2][2][2][4];
4345

0 commit comments

Comments
 (0)