Skip to content

Commit 7728729

Browse files
committed
GS: Refactor GSState::GetTextureMinMax() and GSDrawingContext::GetSizeFixedTex0().
1 parent d20b897 commit 7728729

7 files changed

Lines changed: 449 additions & 398 deletions

File tree

pcsx2/GS/GSDrawingContext.cpp

Lines changed: 52 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -5,66 +5,24 @@
55
#include "GS/GSGL.h"
66
#include "GS/GS.h"
77
#include "GS/GSUtil.h"
8+
#include "GS/GSState.h"
89

9-
static int findmax(int tl, int br, int limit, int wm, int minuv, int maxuv)
10+
// SIZE: TW or TW
11+
// WM, MIN, MAX : Correspondng field of TEX0
12+
// min, max: Range that U or V coordintes take on.
13+
static int GetMaxUV(int SIZE, int WM, int MIN, int MAX, int min, int max)
1014
{
11-
// return max possible texcoord.
12-
int uv = br;
15+
// Confirmed on hardware if SIZE > 10 (or pixel size > 1024),
16+
// it basically gets masked so you end up with a 1x1 pixel (Except Region Clamp).
17+
if (SIZE > 10 && (WM != CLAMP_REGION_CLAMP))
18+
return 0;
1319

14-
// Confirmed on hardware if the size exceeds 1024, it basically gets masked so you end up with a 1x1 pixel (Except Region Clamp).
15-
if (limit > 1024)
16-
limit = 0;
20+
int min_out, max_out; // ignore min_out
21+
bool min_boundary, max_boundary; // ignore both
22+
23+
GSState::GetClampWrapMinMaxUV(SIZE, WM, MIN, MAX, min, max, &min_out, &max_out, &min_boundary, &max_boundary);
1724

18-
if (wm == CLAMP_CLAMP)
19-
{
20-
if (uv > limit)
21-
uv = limit;
22-
}
23-
else if (wm == CLAMP_REPEAT)
24-
{
25-
if (tl < 0)
26-
uv = limit; // wrap around
27-
else if (uv > limit)
28-
uv = limit;
29-
}
30-
else if (wm == CLAMP_REGION_CLAMP)
31-
{
32-
if (uv < minuv)
33-
uv = minuv;
34-
if (uv > maxuv)
35-
uv = maxuv;
36-
}
37-
else if (wm == CLAMP_REGION_REPEAT)
38-
{
39-
// REGION_REPEAT adhears to the original texture size, even if offset outside the texture (with MAXUV).
40-
minuv &= limit;
41-
if (tl < 0)
42-
uv = minuv | maxuv; // wrap around, just use (any & mask) | fix.
43-
else
44-
uv = std::min(uv, minuv) | maxuv; // (any & mask) cannot be larger than mask, select br if that is smaller (not br & mask because there might be a larger value between tl and br when &'ed with the mask).
45-
}
46-
47-
return uv;
48-
}
49-
50-
static int reduce(int uv, int size)
51-
{
52-
while (size > 3 && (1 << (size - 1)) >= uv)
53-
{
54-
size--;
55-
}
56-
57-
return size;
58-
}
59-
60-
static int extend(int uv, int size)
61-
{
62-
while (size < 10 && (1 << size) < uv)
63-
{
64-
size++;
65-
}
66-
67-
return size;
25+
return max_out;
6826
}
6927

7028
void GSDrawingContext::Reset()
@@ -98,65 +56,69 @@ void GSDrawingContext::UpdateScissor()
9856
scissor.xyof = GSVector4i::loadl(&XYOFFSET.U64).xyxy().sub32(GSVector4i::cxpr(0, 0, 15, 15));
9957
}
10058

101-
GIFRegTEX0 GSDrawingContext::GetSizeFixedTEX0(const GSVector4& st, bool linear, bool mipmap) const
59+
// Find the optimal value for TW/TH by analyzing vertex trace and clamping values,
60+
// extending only for region modes where uv may be outside.
61+
// uv_rect has rectangle bounding effecive UV coordinate (u0, v0, u1, v1) (u1 v1 endpoints exclusive)
62+
GIFRegTEX0 GSDrawingContext::GetSizeFixedTEX0(GSVector4i uv_rect, bool linear, bool mipmap) const
10263
{
10364
if (mipmap)
10465
return TEX0; // no mipmaping allowed
10566

106-
// find the optimal value for TW/TH by analyzing vertex trace and clamping values, extending only for region modes where uv may be outside
107-
108-
int tw = TEX0.TW;
109-
int th = TEX0.TH;
67+
const int WMS = (int)CLAMP.WMS;
68+
const int WMT = (int)CLAMP.WMT;
11069

111-
int wms = (int)CLAMP.WMS;
112-
int wmt = (int)CLAMP.WMT;
70+
const int MINU = (int)CLAMP.MINU;
71+
const int MINV = (int)CLAMP.MINV;
72+
const int MAXU = (int)CLAMP.MAXU;
73+
const int MAXV = (int)CLAMP.MAXV;
11374

114-
int minu = (int)CLAMP.MINU;
115-
int minv = (int)CLAMP.MINV;
116-
int maxu = (int)CLAMP.MAXU;
117-
int maxv = (int)CLAMP.MAXV;
75+
int TW = TEX0.TW;
76+
int TH = TEX0.TH;
11877

119-
GSVector4 uvf = st;
120-
121-
if (linear)
122-
{
123-
uvf += GSVector4(-0.5f, 0.5f).xxyy();
124-
}
78+
const int min_width = uv_rect.right;
79+
const int min_height = uv_rect.bottom;
12580

126-
GSVector4i uv = GSVector4i(uvf.floor().xyzw(uvf.ceil()));
81+
auto ExtendLog2Size = [](int min_size, int log2_size) {
82+
while (log2_size < 10 && (1 << log2_size) < min_size)
83+
log2_size++;
84+
return log2_size;
85+
};
12786

128-
uv.x = findmax(uv.x, uv.z, (1 << tw) - 1, wms, minu, maxu);
129-
uv.y = findmax(uv.y, uv.w, (1 << th) - 1, wmt, minv, maxv);
87+
auto ReduceLog2Size = [](int min_size, int log2_size) {
88+
while (log2_size > 3 && (1 << (log2_size - 1)) >= min_size)
89+
log2_size--;
90+
return log2_size;
91+
};
13092

131-
if (tw + th >= 19) // smaller sizes aren't worth, they just create multiple entries in the textue cache and the saved memory is less
93+
if (TW + TH >= 19) // smaller sizes aren't worth, they just create multiple entries in the textue cache and the saved memory is less
13294
{
133-
tw = reduce(uv.x, tw);
134-
th = reduce(uv.y, th);
95+
TW = ReduceLog2Size(min_width, TW);
96+
TH = ReduceLog2Size(min_height, TH);
13597
}
13698

137-
if (wms == CLAMP_REGION_CLAMP || wms == CLAMP_REGION_REPEAT)
99+
if (WMS == CLAMP_REGION_CLAMP || WMS == CLAMP_REGION_REPEAT)
138100
{
139-
tw = extend(uv.x, tw);
101+
TW = ExtendLog2Size(min_width, TW);
140102
}
141103

142-
if (wmt == CLAMP_REGION_CLAMP || wmt == CLAMP_REGION_REPEAT)
104+
if (WMT == CLAMP_REGION_CLAMP || WMT == CLAMP_REGION_REPEAT)
143105
{
144-
th = extend(uv.y, th);
106+
TH = ExtendLog2Size(min_height, TH);
145107
}
146108

147109
GIFRegTEX0 res = TEX0;
148110

149-
res.TW = tw > 10 ? 0 : tw;
150-
res.TH = th > 10 ? 0 : th;
111+
res.TW = TW > 10 ? 0 : TW;
112+
res.TH = TH > 10 ? 0 : TH;
151113

152114
if (TEX0.TW != res.TW || TEX0.TH != res.TH)
153115
{
154-
GL_DBG("FixedTEX0 %05x %d %d tw %d=>%d th %d=>%d st (%.0f,%.0f,%.0f,%.0f) uvmax %d,%d wm %d,%d (%d,%d,%d,%d)",
116+
GL_DBG("FixedTEX0 %05x %d %d tw %d=>%d th %d=>%d uv (%d,%d,%d,%d) uvmax %d,%d wm %d,%d (%d,%d,%d,%d)",
155117
(int)TEX0.TBP0, (int)TEX0.TBW, (int)TEX0.PSM,
156-
(int)TEX0.TW, tw, (int)TEX0.TH, th,
157-
uvf.x, uvf.y, uvf.z, uvf.w,
158-
uv.x, uv.y,
159-
wms, wmt, minu, maxu, minv, maxv);
118+
(int)TEX0.TW, TW, (int)TEX0.TH, TH,
119+
uv_rect.left, uv_rect.top, uv_rect.right, uv_rect.bottom,
120+
min_width - 1, min_height - 1,
121+
WMS, WMT, MINU, MAXU, MINV, MAXV);
160122
}
161123

162124
return res;

pcsx2/GS/GSDrawingContext.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class alignas(32) GSDrawingContext
4444

4545
void UpdateScissor();
4646

47-
GIFRegTEX0 GetSizeFixedTEX0(const GSVector4& st, bool linear, bool mipmap = false) const;
47+
GIFRegTEX0 GetSizeFixedTEX0(GSVector4i uv_rect, bool linear, bool mipmap = false) const;
4848

4949
void Dump(const std::string& filename);
5050
};

0 commit comments

Comments
 (0)