Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/src/common-tests/gsvector_tests.cpp
4214 views
1
// SPDX-FileCopyrightText: 2019-2025 Connor McLaughlin <[email protected]>
2
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
3
4
#include "common/gsvector.h"
5
6
#include "gtest/gtest.h"
7
8
static constexpr s8 s8t(int v)
9
{
10
return static_cast<s8>(static_cast<s32>(v));
11
}
12
13
static constexpr s16 s16t(int v)
14
{
15
return static_cast<s16>(static_cast<s32>(v));
16
}
17
18
// GSVector2i Tests
19
TEST(GSVector2iTest, Construction)
20
{
21
// Default constructor
22
[[maybe_unused]] GSVector2i v1;
23
// Values are uninitialized, so we don't test them
24
25
// Single value constructor
26
GSVector2i v2(42);
27
EXPECT_EQ(v2.x, 42);
28
EXPECT_EQ(v2.y, 42);
29
30
// Two value constructor
31
GSVector2i v3(10, 20);
32
EXPECT_EQ(v3.x, 10);
33
EXPECT_EQ(v3.y, 20);
34
35
// 16-bit constructor
36
GSVector2i v4(s16(1), s16(2), s16(3), s16(4));
37
EXPECT_EQ(v4.S16[0], 1);
38
EXPECT_EQ(v4.S16[1], 2);
39
EXPECT_EQ(v4.S16[2], 3);
40
EXPECT_EQ(v4.S16[3], 4);
41
42
// 8-bit constructor
43
GSVector2i v5(s8t(1), s8t(2), s8t(3), s8t(4), s8t(5), s8t(6), s8t(7), s8t(8));
44
for (int i = 0; i < 8; i++)
45
{
46
EXPECT_EQ(v5.S8[i], i + 1);
47
}
48
49
// Copy constructor
50
GSVector2i v6(v3);
51
EXPECT_EQ(v6.x, 10);
52
EXPECT_EQ(v6.y, 20);
53
}
54
55
TEST(GSVector2iTest, ConstexprCreation)
56
{
57
constexpr auto v1 = GSVector2i::cxpr(5, 10);
58
EXPECT_EQ(v1.x, 5);
59
EXPECT_EQ(v1.y, 10);
60
61
constexpr auto v2 = GSVector2i::cxpr(7);
62
EXPECT_EQ(v2.x, 7);
63
EXPECT_EQ(v2.y, 7);
64
65
constexpr auto v3 = GSVector2i::cxpr16(s16(255));
66
for (int i = 0; i < 4; i++)
67
{
68
EXPECT_EQ(v3.S16[i], 255);
69
}
70
}
71
72
TEST(GSVector2iTest, SaturationOperations)
73
{
74
GSVector2i v1(100, 200);
75
GSVector2i min_val(-50, -100);
76
GSVector2i max_val(150, 250);
77
78
auto sat_result = v1.sat_s32(min_val, max_val);
79
EXPECT_EQ(sat_result.x, 100); // Within range
80
EXPECT_EQ(sat_result.y, 200); // Within range
81
82
GSVector2i v2(300, -150);
83
auto sat_result2 = v2.sat_s32(min_val, max_val);
84
EXPECT_EQ(sat_result2.x, 150); // Clamped to max
85
EXPECT_EQ(sat_result2.y, -100); // Clamped to min
86
}
87
88
TEST(GSVector2iTest, MinMaxVertical)
89
{
90
GSVector2i v1(10, 20);
91
92
EXPECT_EQ(v1.minv_s32(), 10);
93
EXPECT_EQ(v1.maxv_s32(), 20);
94
EXPECT_EQ(v1.addv_s32(), 30);
95
96
GSVector2i v2(s8t(0x50), s8t(0x40), s8t(0x30), s8t(0x20), s8t(0x80), s8t(0x70), s8t(0x60), s8t(0x10)); // 8-bit values
97
EXPECT_EQ(v2.minv_u8(), 0x10u);
98
EXPECT_EQ(v2.maxv_u8(), 0x80u);
99
100
GSVector2i v3(s16t(0x1000), s16t(0x2000), s16t(0x3000), s16t(0x4000)); // 16-bit values
101
EXPECT_EQ(v3.minv_u16(), 0x1000u);
102
EXPECT_EQ(v3.maxv_u16(), 0x4000u);
103
}
104
105
TEST(GSVector2iTest, ClampOperations)
106
{
107
// Test clamp8 which does pu16().upl8()
108
GSVector2i v1(300, 400, -100, 500); // Values that exceed 8-bit range
109
auto clamped = v1.clamp8();
110
// This should pack to 16-bit unsigned with saturation, then unpack low 8-bit
111
for (int i = 0; i < 8; i++)
112
{
113
EXPECT_GE(clamped.U8[i], 0);
114
EXPECT_LE(clamped.U8[i], 255);
115
}
116
}
117
118
TEST(GSVector2iTest, BlendOperations)
119
{
120
GSVector2i v1(s8t(0x11), s8t(0x22), s8t(0x33), s8t(0x44), s8t(0x55), s8t(0x66), s8t(0x77), s8t(0x88));
121
GSVector2i v2(s8t(0xAA), s8t(0xBB), s8t(0xCC), s8t(0xDD), s8t(0xEE), s8t(0xFF), s8t(0x00), s8t(0x11));
122
GSVector2i mask(s8t(0x80), s8t(0x00), s8t(0x80), s8t(0x00), s8t(0x80), s8t(0x00), s8t(0x80),
123
s8t(0x00)); // Alternate selection
124
125
auto blend_result = v1.blend8(v2, mask);
126
EXPECT_EQ(blend_result.U8[0], 0xAAu); // mask bit set, select from v2
127
EXPECT_EQ(blend_result.U8[1], 0x22u); // mask bit clear, select from v1
128
EXPECT_EQ(blend_result.U8[2], 0xCCu); // mask bit set, select from v2
129
EXPECT_EQ(blend_result.U8[3], 0x44u); // mask bit clear, select from v1
130
}
131
132
TEST(GSVector2iTest, BlendTemplated)
133
{
134
GSVector2i v1(s16t(0x1111), s16t(0x2222), s16t(0x3333), s16t(0x4444));
135
GSVector2i v2(s16t(0xAAAA), s16t(0xBBBB), s16t(0xCCCC), s16t(0xDDDD));
136
137
// Test blend16 with mask 0x5 (binary 0101) - select elements 0 and 2 from v2
138
auto blend16_result = v1.blend16<0x5>(v2);
139
EXPECT_EQ(blend16_result.U16[0], 0xAAAAu); // bit 0 set, select from v2
140
EXPECT_EQ(blend16_result.U16[1], 0x2222u); // bit 1 clear, select from v1
141
EXPECT_EQ(blend16_result.U16[2], 0xCCCCu); // bit 2 set, select from v2
142
EXPECT_EQ(blend16_result.U16[3], 0x4444u); // bit 3 clear, select from v1
143
144
// Test blend32 with mask 0x1 - select element 0 from v2
145
auto blend32_result = v1.blend32<0x1>(v2);
146
EXPECT_EQ(blend32_result.U32[0], 0xBBBBAAAAu); // bit 0 set, select from v2
147
EXPECT_EQ(blend32_result.U32[1], 0x44443333u); // bit 1 clear, select from v1
148
}
149
150
TEST(GSVector2iTest, ShuffleOperations)
151
{
152
GSVector2i v1(s8t(0x10), s8t(0x20), s8t(0x30), s8t(0x40), s8t(0x50), s8t(0x60), s8t(0x70), s8t(0x80));
153
GSVector2i shuffle_mask(s8t(0x00), s8t(0x02), s8t(0x04), s8t(0x06), s8t(0x80), s8t(0x81), s8t(0x82),
154
s8t(0x83)); // Mix indices and zero
155
156
auto shuffled = v1.shuffle8(shuffle_mask);
157
EXPECT_EQ(shuffled.S8[0], s8t(0x10)); // Index 0
158
EXPECT_EQ(shuffled.S8[1], s8t(0x30)); // Index 2
159
EXPECT_EQ(shuffled.S8[2], s8t(0x50)); // Index 4
160
EXPECT_EQ(shuffled.S8[3], s8t(0x70)); // Index 6
161
EXPECT_EQ(shuffled.S8[4], s8t(0)); // High bit set, zero
162
EXPECT_EQ(shuffled.S8[5], s8t(0)); // High bit set, zero
163
}
164
165
TEST(GSVector2iTest, PackingOperations)
166
{
167
// Test ps16 - pack signed 16-bit to signed 8-bit with saturation
168
GSVector2i v1(300, -200, 100, 400); // 16-bit values, some out of 8-bit range
169
auto packed_s = v1.ps16();
170
EXPECT_EQ(packed_s.S8[0], 127); // 300 saturated to max s8
171
EXPECT_EQ(packed_s.S8[1], -128); // -200 saturated to min s8
172
EXPECT_EQ(packed_s.S8[2], 100); // 100 within range
173
EXPECT_EQ(packed_s.S8[3], 127); // 400 saturated to max s8
174
175
// Test pu16 - pack unsigned 16-bit to unsigned 8-bit with saturation
176
GSVector2i v2(100, 300, 50, 400);
177
auto packed_u = v2.pu16();
178
EXPECT_EQ(packed_u.U8[0], 100); // 100 within range
179
EXPECT_EQ(packed_u.U8[1], 255); // 300 saturated to max u8
180
EXPECT_EQ(packed_u.U8[2], 50); // 50 within range
181
EXPECT_EQ(packed_u.U8[3], 255); // 400 saturated to max u8
182
}
183
184
TEST(GSVector2iTest, UnpackOperations)
185
{
186
GSVector2i v1(0x12, 0x34, 0x56, 0x78);
187
188
auto upl8_result = v1.upl8();
189
EXPECT_EQ(upl8_result.U8[0], 0x12);
190
EXPECT_EQ(upl8_result.U8[1], 0);
191
EXPECT_EQ(upl8_result.U8[2], 0);
192
EXPECT_EQ(upl8_result.U8[3], 0);
193
EXPECT_EQ(upl8_result.U8[4], 0x34);
194
EXPECT_EQ(upl8_result.U8[5], 0);
195
EXPECT_EQ(upl8_result.U8[6], 0);
196
EXPECT_EQ(upl8_result.U8[7], 0);
197
EXPECT_EQ(upl8_result.U8[8], 0x56);
198
EXPECT_EQ(upl8_result.U8[9], 0);
199
EXPECT_EQ(upl8_result.U8[10], 0);
200
EXPECT_EQ(upl8_result.U8[11], 0);
201
EXPECT_EQ(upl8_result.U8[12], 0x78);
202
EXPECT_EQ(upl8_result.U8[13], 0);
203
EXPECT_EQ(upl8_result.U8[14], 0);
204
EXPECT_EQ(upl8_result.U8[15], 0);
205
206
auto upl16_result = v1.upl16();
207
EXPECT_EQ(upl16_result.U16[0], 0x12);
208
EXPECT_EQ(upl16_result.U16[1], 0);
209
EXPECT_EQ(upl16_result.U16[2], 0x34);
210
EXPECT_EQ(upl16_result.U16[3], 0);
211
EXPECT_EQ(upl16_result.U16[4], 0x56);
212
EXPECT_EQ(upl16_result.U16[5], 0);
213
EXPECT_EQ(upl16_result.U16[6], 0x78);
214
EXPECT_EQ(upl16_result.U16[7], 0);
215
}
216
217
TEST(GSVector2iTest, TypeConversions)
218
{
219
GSVector2i v1(0x12, 0x34, 0x56, 0x78);
220
221
// Test u8to16
222
auto s8to16_result = v1.u8to16();
223
EXPECT_EQ(s8to16_result.S16[0], 0x12);
224
EXPECT_EQ(s8to16_result.S16[1], 0);
225
EXPECT_EQ(s8to16_result.S16[2], 0x34);
226
EXPECT_EQ(s8to16_result.S16[3], 0);
227
228
// Test u8to32
229
auto u8to32_result = v1.u8to32();
230
EXPECT_EQ(u8to32_result.U32[0], 0x12u);
231
EXPECT_EQ(u8to32_result.U32[1], 0u);
232
}
233
234
TEST(GSVector2iTest, ByteShifts)
235
{
236
GSVector2i v1(s8t(0x12), s8t(0x34), s8t(0x56), s8t(0x78), s8t(0x9A), s8t(0xBC), s8t(0xDE), s8t(0xF0));
237
238
// Test srl<2> - shift right logical by 2 bytes
239
auto srl_result = v1.srl<2>();
240
EXPECT_EQ(srl_result.U8[0], 0x56u);
241
EXPECT_EQ(srl_result.U8[1], 0x78u);
242
EXPECT_EQ(srl_result.U8[2], 0x9Au);
243
EXPECT_EQ(srl_result.U8[3], 0xBCu);
244
EXPECT_EQ(srl_result.U8[4], 0xDEu);
245
EXPECT_EQ(srl_result.U8[5], 0xF0u);
246
EXPECT_EQ(srl_result.U8[6], 0u);
247
EXPECT_EQ(srl_result.U8[7], 0u);
248
249
// Test sll<3> - shift left logical by 3 bytes
250
auto sll_result = v1.sll<3>();
251
EXPECT_EQ(sll_result.U8[0], 0u);
252
EXPECT_EQ(sll_result.U8[1], 0u);
253
EXPECT_EQ(sll_result.U8[2], 0u);
254
EXPECT_EQ(sll_result.U8[3], 0x12u);
255
EXPECT_EQ(sll_result.U8[4], 0x34u);
256
EXPECT_EQ(sll_result.U8[5], 0x56u);
257
EXPECT_EQ(sll_result.U8[6], 0x78u);
258
EXPECT_EQ(sll_result.U8[7], 0x9Au);
259
}
260
261
TEST(GSVector2iTest, ArithmeticWith16BitElements)
262
{
263
GSVector2i v1(100, 200, 300, 400);
264
GSVector2i v2(50, 60, 70, 80);
265
266
auto add16_result = v1.add16(v2);
267
EXPECT_EQ(add16_result.S16[0], 150);
268
EXPECT_EQ(add16_result.S16[1], 260);
269
EXPECT_EQ(add16_result.S16[2], 370);
270
EXPECT_EQ(add16_result.S16[3], 480);
271
272
auto sub16_result = v1.sub16(v2);
273
EXPECT_EQ(sub16_result.S16[0], 50);
274
EXPECT_EQ(sub16_result.S16[1], 140);
275
EXPECT_EQ(sub16_result.S16[2], 230);
276
EXPECT_EQ(sub16_result.S16[3], 320);
277
278
auto mul16_result = v1.mul16l(v2);
279
EXPECT_EQ(mul16_result.S16[0], 5000);
280
EXPECT_EQ(mul16_result.S16[1], 12000);
281
EXPECT_EQ(mul16_result.S16[2], 21000);
282
EXPECT_EQ(mul16_result.S16[3], 32000);
283
}
284
285
TEST(GSVector2iTest, ArithmeticWith8BitElements)
286
{
287
GSVector2i v1(10, 20, 30, 40, 50, 60, 70, 80);
288
GSVector2i v2(5, 8, 12, 16, 20, 24, 28, 32);
289
290
auto add8_result = v1.add8(v2);
291
for (int i = 0; i < 8; i++)
292
{
293
EXPECT_EQ(add8_result.S8[i], v1.S8[i] + v2.S8[i]);
294
}
295
296
auto sub8_result = v1.sub8(v2);
297
for (int i = 0; i < 8; i++)
298
{
299
EXPECT_EQ(sub8_result.S8[i], v1.S8[i] - v2.S8[i]);
300
}
301
}
302
303
TEST(GSVector2iTest, SaturatedArithmetic)
304
{
305
// Test signed saturation
306
GSVector2i v1(120, -120, 100, -100, 0, 0, 0, 0);
307
GSVector2i v2(50, -50, 60, -60, 0, 0, 0, 0);
308
309
auto adds8_result = v1.adds8(v2);
310
EXPECT_EQ(adds8_result.S8[0], 127); // 120 + 50 = 170, saturated to 127
311
EXPECT_EQ(adds8_result.S8[1], -128); // -120 + (-50) = -170, saturated to -128
312
EXPECT_EQ(adds8_result.S8[2], 127); // 100 + 60 = 160, saturated to 127
313
EXPECT_EQ(adds8_result.S8[3], -128); // -100 + (-60) = -160, saturated to -128
314
315
auto subs8_result = v1.subs8(v2);
316
EXPECT_EQ(subs8_result.S8[0], 70); // 120 - 50 = 70
317
EXPECT_EQ(subs8_result.S8[1], -70); // -120 - (-50) = -70
318
EXPECT_EQ(subs8_result.S8[2], 40); // 100 - 60 = 40
319
EXPECT_EQ(subs8_result.S8[3], -40); // -100 - (-60) = -40
320
}
321
322
TEST(GSVector2iTest, UnsignedSaturatedArithmetic)
323
{
324
GSVector2i v1(s8t(200), s8t(100), s8t(150), s8t(50), s8t(0), s8t(0), s8t(0), s8t(0));
325
GSVector2i v2(s8t(80), s8t(120), s8t(30), s8t(70), s8t(0), s8t(0), s8t(0), s8t(0));
326
327
auto addus8_result = v1.addus8(v2);
328
EXPECT_EQ(addus8_result.U8[0], 255); // 200 + 80 = 280, saturated to 255
329
EXPECT_EQ(addus8_result.U8[1], 220); // 100 + 120 = 220
330
EXPECT_EQ(addus8_result.U8[2], 180); // 150 + 30 = 180
331
EXPECT_EQ(addus8_result.U8[3], 120); // 50 + 70 = 120
332
333
auto subus8_result = v1.subus8(v2);
334
EXPECT_EQ(subus8_result.U8[0], 120); // 200 - 80 = 120
335
EXPECT_EQ(subus8_result.U8[1], 0); // 100 - 120 = -20, saturated to 0
336
EXPECT_EQ(subus8_result.U8[2], 120); // 150 - 30 = 120
337
EXPECT_EQ(subus8_result.U8[3], 0); // 50 - 70 = -20, saturated to 0
338
}
339
340
TEST(GSVector2iTest, AverageOperations)
341
{
342
GSVector2i v1(s8t(100), s8t(200), s8t(50), s8t(150), s8t(0), s8t(0), s8t(0), s8t(0));
343
GSVector2i v2(s8t(80), s8t(180), s8t(70), s8t(130), s8t(0), s8t(0), s8t(0), s8t(0));
344
345
auto avg8_result = v1.avg8(v2);
346
EXPECT_EQ(avg8_result.U8[0], 90); // (100 + 80) / 2 = 90
347
EXPECT_EQ(avg8_result.U8[1], 190); // (200 + 180) / 2 = 190
348
EXPECT_EQ(avg8_result.U8[2], 60); // (50 + 70) / 2 = 60
349
EXPECT_EQ(avg8_result.U8[3], 140); // (150 + 130) / 2 = 140
350
351
auto avg16_result = v1.avg16(v2);
352
EXPECT_EQ(avg16_result.U16[0], (51300 + 46160) / 2); // Average of packed 16-bit values
353
EXPECT_EQ(avg16_result.U16[1], (38450 + 33350) / 2);
354
}
355
356
TEST(GSVector2iTest, ComparisonOperations)
357
{
358
GSVector2i v1(10, 20, 30, 40, 50, 60, 70, 80);
359
GSVector2i v2(5, 25, 30, 45, 55, 55, 75, 75);
360
361
// Test eq8
362
auto eq8_result = v1.eq8(v2);
363
EXPECT_EQ(eq8_result.S8[0], 0); // 10 != 5
364
EXPECT_EQ(eq8_result.S8[1], 0); // 20 != 25
365
EXPECT_EQ(eq8_result.S8[2], -1); // 30 == 30
366
EXPECT_EQ(eq8_result.S8[3], 0); // 40 != 45
367
368
// Test neq8
369
auto neq8_result = v1.neq8(v2);
370
EXPECT_EQ(neq8_result.S8[0], -1); // 10 != 5
371
EXPECT_EQ(neq8_result.S8[1], -1); // 20 != 25
372
EXPECT_EQ(neq8_result.S8[2], 0); // 30 == 30
373
EXPECT_EQ(neq8_result.S8[3], -1); // 40 != 45
374
375
// Test gt8
376
auto gt8_result = v1.gt8(v2);
377
EXPECT_EQ(gt8_result.S8[0], -1); // 10 > 5
378
EXPECT_EQ(gt8_result.S8[1], 0); // 20 < 25
379
EXPECT_EQ(gt8_result.S8[2], 0); // 30 == 30
380
EXPECT_EQ(gt8_result.S8[3], 0); // 40 < 45
381
382
// Test ge8
383
auto ge8_result = v1.ge8(v2);
384
EXPECT_EQ(ge8_result.S8[0], -1); // 10 >= 5
385
EXPECT_EQ(ge8_result.S8[1], 0); // 20 < 25
386
EXPECT_EQ(ge8_result.S8[2], -1); // 30 >= 30
387
EXPECT_EQ(ge8_result.S8[3], 0); // 40 < 45
388
389
// Test lt8
390
auto lt8_result = v1.lt8(v2);
391
EXPECT_EQ(lt8_result.S8[0], 0); // 10 > 5
392
EXPECT_EQ(lt8_result.S8[1], -1); // 20 < 25
393
EXPECT_EQ(lt8_result.S8[2], 0); // 30 == 30
394
EXPECT_EQ(lt8_result.S8[3], -1); // 40 < 45
395
396
// Test le8
397
auto le8_result = v1.le8(v2);
398
EXPECT_EQ(le8_result.S8[0], 0); // 10 > 5
399
EXPECT_EQ(le8_result.S8[1], -1); // 20 <= 25
400
EXPECT_EQ(le8_result.S8[2], -1); // 30 <= 30
401
EXPECT_EQ(le8_result.S8[3], -1); // 40 <= 45
402
}
403
404
TEST(GSVector2iTest, MaskAndBooleanOperations)
405
{
406
GSVector2i v1(s8t(0x80), s8t(0x40), s8t(0x80), s8t(0x00), s8t(0x80), s8t(0x80), s8t(0x00), s8t(0x80));
407
408
s32 mask_result = v1.mask();
409
// Mask should be formed from high bits of each byte
410
s32 expected_mask = 0x01 | 0x04 | 0x10 | 0x20 | 0x80; // Bits 0, 2, 4, 5, 7
411
EXPECT_EQ(mask_result & 0xB5, expected_mask & 0xB5); // Check set bits
412
413
// Test alltrue and allfalse
414
GSVector2i all_ones;
415
all_ones.U64[0] = 0xFFFFFFFFFFFFFFFFULL;
416
EXPECT_TRUE(all_ones.alltrue());
417
EXPECT_FALSE(all_ones.allfalse());
418
419
GSVector2i all_zeros;
420
all_zeros.U64[0] = 0;
421
EXPECT_FALSE(all_zeros.alltrue());
422
EXPECT_TRUE(all_zeros.allfalse());
423
}
424
425
TEST(GSVector2iTest, InsertExtractOperations)
426
{
427
GSVector2i v1(0x12345678, 0x9ABCDEF0);
428
429
// Test insert/extract 8-bit
430
auto v_insert8 = v1.insert8<0>(0x55);
431
EXPECT_EQ(v_insert8.extract8<0>(), 0x55);
432
EXPECT_EQ(v1.extract8<1>(), s8t(0x56));
433
434
// Test insert/extract 16-bit
435
auto v_insert16 = v1.insert16<1>(0x1234);
436
EXPECT_EQ(v_insert16.extract16<1>(), 0x1234);
437
EXPECT_EQ(v1.extract16<0>(), static_cast<s16>(0x5678));
438
439
// Test insert/extract 32-bit
440
auto v_insert32 = v1.insert32<0>(0xAABBCCDD);
441
EXPECT_EQ(v_insert32.extract32<0>(), static_cast<s32>(0xAABBCCDD));
442
EXPECT_EQ(v1.extract32<1>(), static_cast<s32>(0x9ABCDEF0));
443
}
444
445
TEST(GSVector2iTest, LoadStoreOperations)
446
{
447
// Test load32
448
s32 value = 0x12345678;
449
auto loaded32 = GSVector2i::load32(&value);
450
EXPECT_EQ(loaded32.x, 0x12345678);
451
EXPECT_EQ(loaded32.y, 0);
452
453
// Test set32
454
auto set32_result = GSVector2i::set32(0xAABBCCDD);
455
EXPECT_EQ(set32_result.x, static_cast<s32>(0xAABBCCDD));
456
EXPECT_EQ(set32_result.y, 0);
457
458
// Test store32
459
s32 output_value;
460
GSVector2i::store32(&output_value, loaded32);
461
EXPECT_EQ(output_value, 0x12345678);
462
463
// Test full load/store
464
s32 data[2] = {0x11111111, 0x22222222};
465
auto loaded = GSVector2i::load<true>(data);
466
EXPECT_EQ(loaded.S32[0], 0x11111111);
467
EXPECT_EQ(loaded.S32[1], 0x22222222);
468
469
s32 output[2];
470
GSVector2i::store<true>(output, loaded);
471
EXPECT_EQ(output[0], 0x11111111);
472
EXPECT_EQ(output[1], 0x22222222);
473
}
474
475
TEST(GSVector2iTest, BitwiseAssignmentOperations)
476
{
477
GSVector2i v1(0xF0F0F0F0, 0x0F0F0F0F);
478
GSVector2i v2(0xAAAAAAAA, 0x55555555);
479
480
// Test &=
481
GSVector2i v_and = v1;
482
v_and &= v2;
483
EXPECT_EQ(v_and.U32[0], 0xA0A0A0A0u);
484
EXPECT_EQ(v_and.U32[1], 0x05050505u);
485
486
// Test |=
487
GSVector2i v_or = v1;
488
v_or |= v2;
489
EXPECT_EQ(v_or.U32[0], 0xFAFAFAFAu);
490
EXPECT_EQ(v_or.U32[1], 0x5F5F5F5Fu);
491
492
// Test ^=
493
GSVector2i v_xor = v1;
494
v_xor ^= v2;
495
EXPECT_EQ(v_xor.U32[0], 0x5A5A5A5Au);
496
EXPECT_EQ(v_xor.U32[1], 0x5A5A5A5Au);
497
}
498
499
TEST(GSVector2iTest, BitwiseScalarOperations)
500
{
501
GSVector2i v1(0xF0F0F0F0, 0x0F0F0F0F);
502
s32 scalar = 0xAAAAAAAA;
503
504
auto and_result = v1 & scalar;
505
EXPECT_EQ(and_result.U32[0], 0xA0A0A0A0u);
506
EXPECT_EQ(and_result.U32[1], 0x0A0A0A0Au);
507
508
auto or_result = v1 | scalar;
509
EXPECT_EQ(or_result.U32[0], 0xFAFAFAFAu);
510
EXPECT_EQ(or_result.U32[1], 0xAFAFAFAFu);
511
512
auto xor_result = v1 ^ scalar;
513
EXPECT_EQ(xor_result.U32[0], 0x5A5A5A5Au);
514
EXPECT_EQ(xor_result.U32[1], 0xA5A5A5A5u);
515
}
516
517
TEST(GSVector2iTest, NotOperation)
518
{
519
GSVector2i v1(0xF0F0F0F0, 0x0F0F0F0F);
520
auto not_result = ~v1;
521
EXPECT_EQ(not_result.U32[0], 0x0F0F0F0Fu);
522
EXPECT_EQ(not_result.U32[1], 0xF0F0F0F0u);
523
}
524
525
// GSVector2 Tests
526
TEST(GSVector2Test, Construction)
527
{
528
// Single value constructor
529
GSVector2 v1(3.14f);
530
EXPECT_FLOAT_EQ(v1.x, 3.14f);
531
EXPECT_FLOAT_EQ(v1.y, 3.14f);
532
533
// Two value constructor (float)
534
GSVector2 v2(1.5f, 2.5f);
535
EXPECT_FLOAT_EQ(v2.x, 1.5f);
536
EXPECT_FLOAT_EQ(v2.y, 2.5f);
537
538
// Two value constructor (int)
539
GSVector2 v3(10, 20);
540
EXPECT_FLOAT_EQ(v3.x, 10.0f);
541
EXPECT_FLOAT_EQ(v3.y, 20.0f);
542
543
// Single int constructor
544
GSVector2 v4(42);
545
EXPECT_FLOAT_EQ(v4.x, 42.0f);
546
EXPECT_FLOAT_EQ(v4.y, 42.0f);
547
}
548
549
TEST(GSVector2Test, BlendOperations)
550
{
551
GSVector2 v1(1.0f, 2.0f);
552
GSVector2 v2(3.0f, 4.0f);
553
554
// Test templated blend32
555
auto blend_result = v1.blend32<1>(v2); // mask = 1, select x from v1, y from v2
556
EXPECT_FLOAT_EQ(blend_result.x, 3.0f); // From v2
557
EXPECT_FLOAT_EQ(blend_result.y, 2.0f); // From v1
558
559
// Test mask-based blend32
560
GSVector2 mask;
561
mask.U32[0] = 0x80000000u; // High bit set
562
mask.U32[1] = 0x00000000u; // High bit clear
563
auto mask_blend_result = v1.blend32(v2, mask);
564
EXPECT_FLOAT_EQ(mask_blend_result.x, 3.0f); // From v2 (mask high bit set)
565
EXPECT_FLOAT_EQ(mask_blend_result.y, 2.0f); // From v1 (mask high bit clear)
566
}
567
568
TEST(GSVector2Test, MaskOperations)
569
{
570
GSVector2 v1;
571
v1.U32[0] = 0x80000000u; // High bit set
572
v1.U32[1] = 0x40000000u; // Second bit set
573
574
int mask_result = v1.mask();
575
EXPECT_EQ(mask_result, 0x1); // One bit should be set in result
576
}
577
578
TEST(GSVector2Test, ReplaceNaN)
579
{
580
GSVector2 v1(1.0f, std::numeric_limits<float>::quiet_NaN());
581
GSVector2 replacement(99.0f, 88.0f);
582
583
auto result = v1.replace_nan(replacement);
584
EXPECT_FLOAT_EQ(result.x, 1.0f); // Not NaN, keep original
585
EXPECT_FLOAT_EQ(result.y, 88.0f); // Was NaN, use replacement
586
}
587
588
TEST(GSVector2Test, InsertExtract)
589
{
590
GSVector2 v1(1.0f, 2.0f);
591
GSVector2 v2(3.0f, 4.0f);
592
593
// Test insert32
594
auto insert_result = v1.insert32<1, 0>(v2); // Insert v2[1] into v1[0]
595
EXPECT_FLOAT_EQ(insert_result.x, 4.0f); // v2[1]
596
EXPECT_FLOAT_EQ(insert_result.y, 2.0f); // Original v1[1]
597
598
// Test extract32
599
GSVector2 v3;
600
v3.I32[0] = 0x12345678;
601
v3.I32[1] = 0x9ABCDEF0;
602
EXPECT_EQ(v3.extract32<0>(), 0x12345678);
603
EXPECT_EQ(v3.extract32<1>(), static_cast<s32>(0x9ABCDEF0));
604
}
605
606
TEST(GSVector2Test, ComparisonOperators)
607
{
608
GSVector2 v1(1.0f, 2.0f);
609
GSVector2 v2(1.0f, 3.0f);
610
611
auto eq_result = v1 == v2;
612
EXPECT_EQ(eq_result.I32[0], -1); // 1.0 == 1.0
613
EXPECT_EQ(eq_result.I32[1], 0); // 2.0 != 3.0
614
615
auto neq_result = v1 != v2;
616
EXPECT_EQ(neq_result.I32[0], 0); // 1.0 == 1.0
617
EXPECT_EQ(neq_result.I32[1], -1); // 2.0 != 3.0
618
619
auto gt_result = v1 > v2;
620
EXPECT_EQ(gt_result.I32[0], 0); // 1.0 == 1.0
621
EXPECT_EQ(gt_result.I32[1], 0); // 2.0 < 3.0
622
623
auto lt_result = v1 < v2;
624
EXPECT_EQ(lt_result.I32[0], 0); // 1.0 == 1.0
625
EXPECT_EQ(lt_result.I32[1], -1); // 2.0 < 3.0
626
627
auto ge_result = v1 >= v2;
628
EXPECT_EQ(ge_result.I32[0], -1); // 1.0 >= 1.0
629
EXPECT_EQ(ge_result.I32[1], 0); // 2.0 < 3.0
630
631
auto le_result = v1 <= v2;
632
EXPECT_EQ(le_result.I32[0], -1); // 1.0 <= 1.0
633
EXPECT_EQ(le_result.I32[1], -1); // 2.0 <= 3.0
634
}
635
636
TEST(GSVector2Test, XfffffffffConstant)
637
{
638
const auto all_ones = GSVector2::xffffffff();
639
EXPECT_EQ(all_ones.U64[0], 0xFFFFFFFFFFFFFFFFULL);
640
}
641
642
// GSVector4i Tests
643
TEST(GSVector4iTest, ConstexprCreation8Bit)
644
{
645
constexpr auto v1 = GSVector4i::cxpr8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
646
for (int i = 0; i < 16; i++)
647
{
648
EXPECT_EQ(v1.S8[i], i + 1);
649
}
650
}
651
652
TEST(GSVector4iTest, MaddOperations)
653
{
654
GSVector4i v1(1, 2, 3, 4, 5, 6, 7, 8); // 16-bit values
655
GSVector4i v2(2, 3, 4, 5, 6, 7, 8, 9);
656
657
auto madd_result = v1.madd_s16(v2);
658
EXPECT_EQ(madd_result.S32[0], 1 * 2 + 2 * 3); // 2 + 6 = 8
659
EXPECT_EQ(madd_result.S32[1], 3 * 4 + 4 * 5); // 12 + 20 = 32
660
EXPECT_EQ(madd_result.S32[2], 5 * 6 + 6 * 7); // 30 + 42 = 72
661
EXPECT_EQ(madd_result.S32[3], 7 * 8 + 8 * 9); // 56 + 72 = 128
662
}
663
664
TEST(GSVector4iTest, HorizontalAdd)
665
{
666
GSVector4i v1(10, 20, 30, 40);
667
668
auto addp_result = v1.addp_s32();
669
EXPECT_EQ(addp_result.x, 30); // 10 + 20
670
EXPECT_EQ(addp_result.y, 70); // 30 + 40
671
EXPECT_EQ(addp_result.z, 30);
672
EXPECT_EQ(addp_result.w, 70);
673
}
674
675
TEST(GSVector4iTest, VerticalMinMaxU8)
676
{
677
GSVector4i v1(s8t(10), s8t(50), s8t(30), s8t(200), s8t(15), s8t(100), s8t(5), s8t(250), s8t(80), s8t(20), s8t(60),
678
s8t(40), s8t(90), s8t(70), s8t(180), s8t(1));
679
680
EXPECT_EQ(v1.minv_u8(), 1u);
681
EXPECT_EQ(v1.maxv_u8(), 250u);
682
}
683
684
TEST(GSVector4iTest, VerticalMinMaxU16)
685
{
686
GSVector4i v1(1000, 2000, 500, 3000, 1500, 800, 2500, 100);
687
688
EXPECT_EQ(v1.minv_u16(), 100u);
689
EXPECT_EQ(v1.maxv_u16(), 3000u);
690
}
691
692
TEST(GSVector4iTest, HaddS16)
693
{
694
GSVector4i v1(10, 20, 30, 40, 50, 60, 70, 80);
695
GSVector4i v2(1, 2, 3, 4, 5, 6, 7, 8);
696
697
auto hadds_result = v1.hadds16(v2);
698
// First vector: pairs (10,20), (30,40), (50,60), (70,80)
699
// Second vector: pairs (1,2), (3,4), (5,6), (7,8)
700
EXPECT_EQ(hadds_result.S16[0], 30); // 10 + 20
701
EXPECT_EQ(hadds_result.S16[1], 70); // 30 + 40
702
EXPECT_EQ(hadds_result.S16[2], 110); // 50 + 60
703
EXPECT_EQ(hadds_result.S16[3], 150); // 70 + 80
704
EXPECT_EQ(hadds_result.S16[4], 3); // 1 + 2
705
EXPECT_EQ(hadds_result.S16[5], 7); // 3 + 4
706
EXPECT_EQ(hadds_result.S16[6], 11); // 5 + 6
707
EXPECT_EQ(hadds_result.S16[7], 15); // 7 + 8
708
}
709
710
TEST(GSVector4iTest, BlendOperationsAdvanced)
711
{
712
GSVector4i v1(s8t(0x11), s8t(0x22), s8t(0x33), s8t(0x44), s8t(0x55), s8t(0x66), s8t(0x77), s8t(0x88), s8t(0x99),
713
s8t(0xAA), s8t(0xBB), s8t(0xCC), s8t(0xDD), s8t(0xEE), s8t(0xFF), s8t(0x00));
714
GSVector4i v2(s8t(0xA1), s8t(0xB2), s8t(0xC3), s8t(0xD4), s8t(0xE5), s8t(0xF6), s8t(0x07), s8t(0x18), s8t(0x29),
715
s8t(0x3A), s8t(0x4B), s8t(0x5C), s8t(0x6D), s8t(0x7E), s8t(0x8F), s8t(0x90));
716
GSVector4i mask_blend(s8t(0xFF), s8t(0x00), s8t(0xFF), s8t(0x00), s8t(0xFF), s8t(0x00), s8t(0xFF), s8t(0x00),
717
s8t(0xFF), s8t(0x00), s8t(0xFF), s8t(0x00), s8t(0xFF), s8t(0x00), s8t(0xFF), s8t(0x00));
718
719
auto blend_result = v1.blend(v2, mask_blend);
720
// The blend operation should mix bits based on the mask
721
// Where mask bit is 1, select from v2; where 0, select from v1
722
for (int i = 0; i < 2; i++)
723
{
724
u64 expected = (v2.U64[i] & mask_blend.U64[i]) | (v1.U64[i] & ~mask_blend.U64[i]);
725
EXPECT_EQ(blend_result.U64[i], expected);
726
}
727
}
728
729
TEST(GSVector4iTest, AdvancedPackingWithTwoVectors)
730
{
731
GSVector4i v1(100, 200, 300, 400); // 32-bit signed values
732
GSVector4i v2(500, 600, 700, 800);
733
734
auto ps32_result = v1.ps32(v2);
735
// Should pack both vectors' 32-bit values to 16-bit with saturation
736
EXPECT_EQ(ps32_result.S16[0], 100);
737
EXPECT_EQ(ps32_result.S16[1], 200);
738
EXPECT_EQ(ps32_result.S16[2], 300);
739
EXPECT_EQ(ps32_result.S16[3], 400);
740
EXPECT_EQ(ps32_result.S16[4], 500);
741
EXPECT_EQ(ps32_result.S16[5], 600);
742
EXPECT_EQ(ps32_result.S16[6], 700);
743
EXPECT_EQ(ps32_result.S16[7], 800);
744
}
745
746
TEST(GSVector4iTest, AdvancedUnpackingWithTwoVectors)
747
{
748
GSVector4i v1(s8t(0x11), s8t(0x22), s8t(0x33), s8t(0x44), s8t(0x55), s8t(0x66), s8t(0x77), s8t(0x88), s8t(0x99),
749
s8t(0xAA), s8t(0xBB), s8t(0xCC), s8t(0xDD), s8t(0xEE), s8t(0xFF), s8t(0x00));
750
GSVector4i v2(s8t(0xA1), s8t(0xB2), s8t(0xC3), s8t(0xD4), s8t(0xE5), s8t(0xF6), s8t(0x07), s8t(0x18), s8t(0x29),
751
s8t(0x3A), s8t(0x4B), s8t(0x5C), s8t(0x6D), s8t(0x7E), s8t(0x8F), s8t(0x90));
752
753
auto upl8_result = v1.upl8(v2);
754
// Should interleave low 8 bytes from both vectors
755
EXPECT_EQ(upl8_result.S8[0], s8t(0x11)); // v1[0]
756
EXPECT_EQ(upl8_result.S8[1], s8t(0xA1)); // v2[0]
757
EXPECT_EQ(upl8_result.S8[2], s8t(0x22)); // v1[1]
758
EXPECT_EQ(upl8_result.S8[3], s8t(0xB2)); // v2[1]
759
760
auto uph8_result = v1.uph8(v2);
761
// Should interleave high 8 bytes from both vectors
762
EXPECT_EQ(uph8_result.S8[0], s8t(0x99)); // v1[8]
763
EXPECT_EQ(uph8_result.S8[1], s8t(0x29)); // v2[8]
764
EXPECT_EQ(uph8_result.S8[2], s8t(0xAA)); // v1[9]
765
EXPECT_EQ(uph8_result.S8[3], s8t(0x3A)); // v2[9]
766
}
767
768
TEST(GSVector4iTest, Type64BitConversions)
769
{
770
GSVector4i v1(s8t(0x12), s8t(0x34), s8t(0x56), s8t(0x78), s8t(0x9A), s8t(0xBC), s8t(0xDE), s8t(0xF0), s8t(0x11),
771
s8t(0x22), s8t(0x33), s8t(0x44), s8t(0x55), s8t(0x66), s8t(0x77), s8t(0x88));
772
773
// Test s8to64
774
auto s8to64_result = v1.s8to64();
775
EXPECT_EQ(s8to64_result.S64[0], 0x12);
776
EXPECT_EQ(s8to64_result.S64[1], 0x34);
777
778
// Test u16to64
779
auto u16to64_result = v1.u16to64();
780
EXPECT_EQ(u16to64_result.U64[0], 0x3412u); // Little endian 16-bit
781
EXPECT_EQ(u16to64_result.U64[1], 0x7856u);
782
783
// Test s32to64
784
auto s32to64_result = v1.s32to64();
785
EXPECT_EQ(s32to64_result.S64[0], static_cast<s64>(0x0000000078563412LL));
786
EXPECT_EQ(s32to64_result.S64[1], static_cast<s64>(0xFFFFFFFFF0DEBC9ALL));
787
}
788
789
TEST(GSVector4iTest, Shift64BitOperations)
790
{
791
GSVector4i v1;
792
v1.U64[0] = 0x123456789ABCDEF0ULL;
793
v1.U64[1] = 0xFEDCBA0987654321ULL;
794
795
// Test sll64
796
auto sll64_result = v1.sll64<4>();
797
EXPECT_EQ(sll64_result.U64[0], 0x23456789ABCDEF00ULL);
798
EXPECT_EQ(sll64_result.U64[1], 0xEDCBA09876543210ULL);
799
800
// Test srl64
801
auto srl64_result = v1.srl64<4>();
802
EXPECT_EQ(srl64_result.U64[0], 0x0123456789ABCDEFULL);
803
EXPECT_EQ(srl64_result.U64[1], 0x0FEDCBA098765432ULL);
804
}
805
806
#ifdef GSVECTOR_HAS_SRLV
807
TEST(GSVector4iTest, VariableShifts)
808
{
809
GSVector4i v1(0x1000, 0x2000, 0x4000, 0x8000);
810
GSVector4i shift_amounts(1, 2, 3, 4);
811
812
auto sllv16_result = v1.sllv16(shift_amounts);
813
EXPECT_EQ(sllv16_result.U16[0], 0x2000); // 0x1000 << 1
814
EXPECT_EQ(sllv16_result.U16[1], 0x8000); // 0x2000 << 2
815
EXPECT_EQ(sllv16_result.U16[2], 0x0000); // 0x4000 << 3 (overflow)
816
EXPECT_EQ(sllv16_result.U16[3], 0x0000); // 0x8000 << 4 (overflow)
817
818
auto srlv16_result = v1.srlv16(shift_amounts);
819
EXPECT_EQ(srlv16_result.U16[0], 0x0800); // 0x1000 >> 1
820
EXPECT_EQ(srlv16_result.U16[1], 0x0800); // 0x2000 >> 2
821
EXPECT_EQ(srlv16_result.U16[2], 0x0800); // 0x4000 >> 3
822
EXPECT_EQ(srlv16_result.U16[3], 0x0800); // 0x8000 >> 4
823
}
824
#endif
825
826
TEST(GSVector4iTest, MultiplicationOperations)
827
{
828
GSVector4i v1(10, 20, 30, 40, 50, 60, 70, 80);
829
GSVector4i v2(2, 3, 4, 5, 6, 7, 8, 9);
830
831
// Test mul16hs - high 16 bits of 16-bit multiplication
832
auto mul16hs_result = v1.mul16hs(v2);
833
// For 16-bit values, this should mostly be 0 unless we have large values
834
for (int i = 0; i < 8; i++)
835
{
836
s32 expected = (v1.S16[i] * v2.S16[i]) >> 16;
837
EXPECT_EQ(mul16hs_result.S16[i], expected);
838
}
839
840
// Test mul16hrs - rounded high 16 bits
841
auto mul16hrs_result = v1.mul16hrs(v2);
842
for (int i = 0; i < 8; i++)
843
{
844
const s16 expected = static_cast<s16>((((v1.S16[i] * v2.S16[i]) >> 14) + 1) >> 1);
845
EXPECT_EQ(mul16hrs_result.S16[i], expected);
846
}
847
}
848
849
TEST(GSVector4iTest, Eq64Operations)
850
{
851
GSVector4i v1;
852
GSVector4i v2;
853
v1.S64[0] = 0x123456789ABCDEF0LL;
854
v1.S64[1] = 0xFEDCBA0987654321LL;
855
v2.S64[0] = 0x123456789ABCDEF0LL; // Same as v1[0]
856
v2.S64[1] = 0x1111111111111111LL; // Different from v1[1]
857
858
auto eq64_result = v1.eq64(v2);
859
EXPECT_EQ(eq64_result.S64[0], -1); // Equal
860
EXPECT_EQ(eq64_result.S64[1], 0); // Not equal
861
}
862
863
TEST(GSVector4iTest, InsertExtract64Bit)
864
{
865
GSVector4i v1(0x12345678, 0x9ABCDEF0, 0x11111111, 0x22222222);
866
867
// Test insert64
868
auto v_insert64 = v1.insert64<0>(static_cast<s64>(0x9999888877776666ULL));
869
EXPECT_EQ(v_insert64.extract64<0>(), static_cast<s64>(0x9999888877776666ULL));
870
EXPECT_EQ(v_insert64.extract64<1>(), v1.extract64<1>());
871
872
// Test extract64
873
EXPECT_EQ(v1.extract64<0>(), static_cast<s64>(0x9ABCDEF012345678ULL)); // Little endian combination
874
EXPECT_EQ(v1.extract64<1>(), static_cast<s64>(0x2222222211111111ULL));
875
}
876
877
TEST(GSVector4iTest, LoadStoreSpecialOperations)
878
{
879
// Test loadnt (non-temporal load)
880
alignas(VECTOR_ALIGNMENT) static constexpr const s32 data[4] = {0x11111111, 0x22222222, 0x33333333, 0x44444444};
881
auto loaded_nt = GSVector4i::loadnt(data);
882
for (int i = 0; i < 4; i++)
883
{
884
EXPECT_EQ(loaded_nt.S32[i], data[i]);
885
}
886
887
// Test storent (non-temporal store)
888
alignas(VECTOR_ALIGNMENT) s32 output_nt[4];
889
GSVector4i::storent(output_nt, loaded_nt);
890
for (int i = 0; i < 4; i++)
891
{
892
EXPECT_EQ(output_nt[i], data[i]);
893
}
894
895
// Test zext32
896
auto zext_result = GSVector4i::zext32(0x12345678);
897
EXPECT_EQ(zext_result.x, 0x12345678);
898
EXPECT_EQ(zext_result.y, 0);
899
EXPECT_EQ(zext_result.z, 0);
900
EXPECT_EQ(zext_result.w, 0);
901
}
902
903
TEST(GSVector4iTest, LoadStoreHalfOperations)
904
{
905
// Test loadl and loadh
906
u64 data[2] = {0x123456789ABCDEF0ULL, 0xFEDCBA0987654321ULL};
907
908
auto loaded_low = GSVector4i::loadl<true>(data);
909
EXPECT_EQ(loaded_low.U64[0], data[0]);
910
EXPECT_EQ(loaded_low.U64[1], 0u);
911
912
auto loaded_high = GSVector4i::loadh<true>(data);
913
EXPECT_EQ(loaded_high.U64[0], 0u);
914
EXPECT_EQ(loaded_high.U64[1], data[0]);
915
916
// Test storel and storeh
917
GSVector4i test_vec;
918
test_vec.U64[0] = 0xAAAABBBBCCCCDDDDULL;
919
test_vec.U64[1] = 0xEEEEFFFF00001111ULL;
920
921
s32 output_low[2];
922
GSVector4i::storel<true>(output_low, test_vec);
923
EXPECT_EQ(reinterpret_cast<u64*>(output_low)[0], test_vec.U64[0]);
924
925
s32 output_high[2];
926
GSVector4i::storeh<true>(output_high, test_vec);
927
EXPECT_EQ(reinterpret_cast<u64*>(output_high)[0], test_vec.U64[1]);
928
}
929
930
TEST(GSVector4iTest, BroadcastOperations)
931
{
932
GSVector4i v1(10, 20, 30, 40);
933
934
auto broadcast_result = GSVector4i::broadcast128(v1);
935
// In no-SIMD implementation, this just returns the same vector
936
EXPECT_EQ(broadcast_result.x, v1.x);
937
EXPECT_EQ(broadcast_result.y, v1.y);
938
EXPECT_EQ(broadcast_result.z, v1.z);
939
EXPECT_EQ(broadcast_result.w, v1.w);
940
}
941
942
TEST(GSVector4iTest, StaticHelperFunctions)
943
{
944
GSVector2i xy(10, 20);
945
GSVector2i zw(30, 40);
946
947
auto xyxy_result1 = GSVector4i::xyxy(xy, zw);
948
EXPECT_EQ(xyxy_result1.x, 10);
949
EXPECT_EQ(xyxy_result1.y, 20);
950
EXPECT_EQ(xyxy_result1.z, 30);
951
EXPECT_EQ(xyxy_result1.w, 40);
952
953
auto xyxy_result2 = GSVector4i::xyxy(xy);
954
EXPECT_EQ(xyxy_result2.x, 10);
955
EXPECT_EQ(xyxy_result2.y, 20);
956
EXPECT_EQ(xyxy_result2.z, 10);
957
EXPECT_EQ(xyxy_result2.w, 20);
958
}
959
960
// GSVector4 Tests
961
TEST(GSVector4Test, DoubleOperations)
962
{
963
// Test all 64-bit double operations
964
GSVector4 v1 = GSVector4::f64(3.14159, 2.71828);
965
GSVector4 v2 = GSVector4::f64(1.41421, 1.73205);
966
967
auto add64_result = v1.add64(v2);
968
EXPECT_DOUBLE_EQ(add64_result.F64[0], 3.14159 + 1.41421);
969
EXPECT_DOUBLE_EQ(add64_result.F64[1], 2.71828 + 1.73205);
970
971
auto sub64_result = v1.sub64(v2);
972
EXPECT_DOUBLE_EQ(sub64_result.F64[0], 3.14159 - 1.41421);
973
EXPECT_DOUBLE_EQ(sub64_result.F64[1], 2.71828 - 1.73205);
974
975
auto mul64_result = v1.mul64(v2);
976
EXPECT_DOUBLE_EQ(mul64_result.F64[0], 3.14159 * 1.41421);
977
EXPECT_DOUBLE_EQ(mul64_result.F64[1], 2.71828 * 1.73205);
978
979
auto div64_result = v1.div64(v2);
980
EXPECT_DOUBLE_EQ(div64_result.F64[0], 3.14159 / 1.41421);
981
EXPECT_DOUBLE_EQ(div64_result.F64[1], 2.71828 / 1.73205);
982
}
983
984
TEST(GSVector4Test, BasicOps)
985
{
986
GSVector4 v(1.0f, -2.0f, 3.5f, -4.5f);
987
988
EXPECT_FLOAT_EQ(v.addv(), (1.0f - 2.0f + 3.5f - 4.5f));
989
EXPECT_FLOAT_EQ(v.minv(), -4.5f);
990
EXPECT_FLOAT_EQ(v.maxv(), 3.5f);
991
992
auto av = v.abs();
993
EXPECT_FLOAT_EQ(av.x, 1.0f);
994
EXPECT_FLOAT_EQ(av.y, 2.0f);
995
EXPECT_FLOAT_EQ(av.z, 3.5f);
996
EXPECT_FLOAT_EQ(av.w, 4.5f);
997
998
auto nv = v.neg();
999
EXPECT_FLOAT_EQ(nv.x, -1.0f);
1000
EXPECT_FLOAT_EQ(nv.y, 2.0f);
1001
EXPECT_FLOAT_EQ(nv.z, -3.5f);
1002
EXPECT_FLOAT_EQ(nv.w, 4.5f);
1003
1004
auto fl = GSVector4(1.9f, -1.2f, 3.01f, -3.99f).floor();
1005
EXPECT_FLOAT_EQ(fl.x, 1.0f);
1006
EXPECT_FLOAT_EQ(fl.y, -2.0f);
1007
EXPECT_FLOAT_EQ(fl.z, 3.0f);
1008
EXPECT_FLOAT_EQ(fl.w, -4.0f);
1009
1010
auto cl = GSVector4(1.1f, -1.2f, 3.01f, -3.99f).ceil();
1011
EXPECT_FLOAT_EQ(cl.x, 2.0f);
1012
EXPECT_FLOAT_EQ(cl.y, -1.0f);
1013
EXPECT_FLOAT_EQ(cl.z, 4.0f);
1014
EXPECT_FLOAT_EQ(cl.w, -3.0f);
1015
1016
// sat(scale)
1017
auto sat_scaled = GSVector4(-5.0f, 10.0f, 500.0f, 260.0f).sat(255.0f);
1018
EXPECT_FLOAT_EQ(sat_scaled.x, 0.0f);
1019
EXPECT_FLOAT_EQ(sat_scaled.y, 10.0f);
1020
EXPECT_FLOAT_EQ(sat_scaled.z, 255.0f);
1021
EXPECT_FLOAT_EQ(sat_scaled.w, 255.0f);
1022
1023
// sat(minmax vector) : x/z clamped to [min.x, min.z], y/w to [min.y, min.w]
1024
GSVector4 range(0.0f, -1.0f, 2.0f, 1.0f);
1025
auto sat_pair = v.sat(range);
1026
EXPECT_FLOAT_EQ(sat_pair.x, 1.0f); // within [0,2]
1027
EXPECT_FLOAT_EQ(sat_pair.y, -1.0f); // clamped to -1
1028
EXPECT_FLOAT_EQ(sat_pair.z, 2.0f); // clamped to 2
1029
EXPECT_FLOAT_EQ(sat_pair.w, -1.0f); // clamped to -1
1030
}
1031
1032
TEST(GSVector4Test, BlendAndMask)
1033
{
1034
GSVector4 a(1, 2, 3, 4);
1035
GSVector4 b(5, 6, 7, 8);
1036
1037
// Template blend32<mask> (selects only lanes 0/1 from the 'v' argument per bit)
1038
auto tb = a.blend32<0b1010>(b);
1039
EXPECT_FLOAT_EQ(tb.x, 1.0f); // bit0 = 0 -> v[0]
1040
EXPECT_FLOAT_EQ(tb.y, 6.0f); // bit1 = 1 -> v[1]
1041
EXPECT_FLOAT_EQ(tb.z, 3.0f); // bit2 = 0 -> v[0]
1042
EXPECT_FLOAT_EQ(tb.w, 8.0f); // bit3 = 1 -> v[1]
1043
1044
// Masked blend: high bit set -> take from second vector argument (b); else from 'a'
1045
GSVector4 mask;
1046
mask.U32[0] = 0x00000000u;
1047
mask.U32[1] = 0x80000000u;
1048
mask.U32[2] = 0x00000000u;
1049
mask.U32[3] = 0x80000000u;
1050
auto mb = a.blend32(b, mask);
1051
EXPECT_FLOAT_EQ(mb.x, a.x);
1052
EXPECT_FLOAT_EQ(mb.y, b.y);
1053
EXPECT_FLOAT_EQ(mb.z, a.z);
1054
EXPECT_FLOAT_EQ(mb.w, b.w);
1055
1056
// mask() bit packing (bits 31,23,15,7)
1057
GSVector4 m;
1058
m.U32[0] = 0x80000000u; // sets bit 0
1059
m.U32[1] = 0x40000000u; // sets bit 1
1060
m.U32[2] = 0x20000000u; // sets bit 2
1061
m.U32[3] = 0x10000000u; // sets bit 3
1062
EXPECT_EQ(m.mask(), 0x1);
1063
}
1064
1065
TEST(GSVector4Test, HorizontalAndInterleave)
1066
{
1067
GSVector4 v(1, 2, 10, 20);
1068
auto hadd0 = v.hadd();
1069
EXPECT_FLOAT_EQ(hadd0.x, 3);
1070
EXPECT_FLOAT_EQ(hadd0.y, 30);
1071
EXPECT_FLOAT_EQ(hadd0.z, 3);
1072
EXPECT_FLOAT_EQ(hadd0.w, 30);
1073
1074
auto hsub0 = v.hsub();
1075
EXPECT_FLOAT_EQ(hsub0.x, -1);
1076
EXPECT_FLOAT_EQ(hsub0.y, -10);
1077
EXPECT_FLOAT_EQ(hsub0.z, -1);
1078
EXPECT_FLOAT_EQ(hsub0.w, -10);
1079
1080
GSVector4 v2(3, 4, 5, 6);
1081
auto hadd1 = v.hadd(v2);
1082
EXPECT_FLOAT_EQ(hadd1.x, 3);
1083
EXPECT_FLOAT_EQ(hadd1.y, 30);
1084
EXPECT_FLOAT_EQ(hadd1.z, 7);
1085
EXPECT_FLOAT_EQ(hadd1.w, 11);
1086
1087
auto hsub1 = v.hsub(v2);
1088
EXPECT_FLOAT_EQ(hsub1.x, -1);
1089
EXPECT_FLOAT_EQ(hsub1.y, -10);
1090
EXPECT_FLOAT_EQ(hsub1.z, -1);
1091
EXPECT_FLOAT_EQ(hsub1.w, -1);
1092
1093
// Interleave / low-high helpers
1094
GSVector4 a(1, 2, 3, 4);
1095
GSVector4 b(5, 6, 7, 8);
1096
auto upl = a.upl(b);
1097
EXPECT_FLOAT_EQ(upl.x, 1);
1098
EXPECT_FLOAT_EQ(upl.y, 5);
1099
EXPECT_FLOAT_EQ(upl.z, 2);
1100
EXPECT_FLOAT_EQ(upl.w, 6);
1101
auto uph = a.uph(b);
1102
EXPECT_FLOAT_EQ(uph.x, 3);
1103
EXPECT_FLOAT_EQ(uph.y, 7);
1104
EXPECT_FLOAT_EQ(uph.z, 4);
1105
EXPECT_FLOAT_EQ(uph.w, 8);
1106
auto l2h = a.l2h(b);
1107
EXPECT_FLOAT_EQ(l2h.x, 1);
1108
EXPECT_FLOAT_EQ(l2h.y, 2);
1109
EXPECT_FLOAT_EQ(l2h.z, 5);
1110
EXPECT_FLOAT_EQ(l2h.w, 6);
1111
auto h2l = a.h2l(b);
1112
EXPECT_FLOAT_EQ(h2l.x, 7);
1113
EXPECT_FLOAT_EQ(h2l.y, 8);
1114
EXPECT_FLOAT_EQ(h2l.z, 3);
1115
EXPECT_FLOAT_EQ(h2l.w, 4);
1116
}
1117
1118
TEST(GSVector4Test, BroadcastAndInsertExtract)
1119
{
1120
GSVector4 v(9, 2, 3, 4);
1121
auto bc_self = v.broadcast32();
1122
EXPECT_FLOAT_EQ(bc_self.x, 9);
1123
EXPECT_FLOAT_EQ(bc_self.y, 9);
1124
EXPECT_FLOAT_EQ(bc_self.z, 9);
1125
EXPECT_FLOAT_EQ(bc_self.w, 9);
1126
1127
auto bc_static = GSVector4::broadcast32(v);
1128
EXPECT_FLOAT_EQ(bc_static.z, 9);
1129
1130
GSVector4 a(1, 2, 3, 4);
1131
GSVector4 b(5, 6, 7, 8);
1132
auto ins_from_other = a.insert32<2, 0>(b); // copy b.z into a.x
1133
EXPECT_FLOAT_EQ(ins_from_other.x, 7);
1134
EXPECT_FLOAT_EQ(ins_from_other.y, 2);
1135
EXPECT_FLOAT_EQ(ins_from_other.z, 3);
1136
EXPECT_FLOAT_EQ(ins_from_other.w, 4);
1137
1138
auto ins_scalar = a.insert32<1>(42.0f);
1139
EXPECT_FLOAT_EQ(ins_scalar.x, 1);
1140
EXPECT_FLOAT_EQ(ins_scalar.y, 42.0f);
1141
EXPECT_FLOAT_EQ(ins_scalar.z, 3);
1142
EXPECT_FLOAT_EQ(ins_scalar.w, 4);
1143
1144
EXPECT_FLOAT_EQ(a.extract32<0>(), 1.0f);
1145
EXPECT_FLOAT_EQ(a.extract32<3>(), 4.0f);
1146
}
1147
1148
TEST(GSVector4Test, BitwiseAndAndNot)
1149
{
1150
GSVector4 a;
1151
a.U32[0] = 0xFFFFFFFFu;
1152
a.U32[1] = 0x00FF00FFu;
1153
a.U32[2] = 0x12345678u;
1154
a.U32[3] = 0xAAAAAAAAu;
1155
1156
GSVector4 b;
1157
b.U32[0] = 0x0F0F0F0Fu;
1158
b.U32[1] = 0xFF00FF00u;
1159
b.U32[2] = 0xFFFFFFFFu;
1160
b.U32[3] = 0x55555555u;
1161
1162
auto vand = a & b;
1163
EXPECT_EQ(vand.U32[0], 0x0F0F0F0Fu);
1164
EXPECT_EQ(vand.U32[1], 0x00000000u);
1165
EXPECT_EQ(vand.U32[2], 0x12345678u);
1166
EXPECT_EQ(vand.U32[3], 0x00000000u);
1167
1168
auto vor = a | b;
1169
EXPECT_EQ(vor.U32[0], 0xFFFFFFFFu);
1170
EXPECT_EQ(vor.U32[1], 0xFFFFFFFFu);
1171
EXPECT_EQ(vor.U32[2], 0xFFFFFFFFu);
1172
EXPECT_EQ(vor.U32[3], 0xFFFFFFFFu);
1173
1174
auto vxor = a ^ b;
1175
EXPECT_EQ(vxor.U32[0], 0xF0F0F0F0u);
1176
EXPECT_EQ(vxor.U32[1], 0xFFFFFFFFu);
1177
EXPECT_EQ(vxor.U32[2], 0xEDCBA987u);
1178
EXPECT_EQ(vxor.U32[3], 0xFFFFFFFFu);
1179
1180
auto an = a.andnot(b); // (~b) & a
1181
EXPECT_EQ(an.U32[0], (~b.U32[0]) & a.U32[0]);
1182
EXPECT_EQ(an.U32[1], (~b.U32[1]) & a.U32[1]);
1183
EXPECT_EQ(an.U32[2], (~b.U32[2]) & a.U32[2]);
1184
EXPECT_EQ(an.U32[3], (~b.U32[3]) & a.U32[3]);
1185
}
1186
1187
TEST(GSVector4Test, ReplaceNaN)
1188
{
1189
GSVector4 v(1.0f, std::numeric_limits<float>::quiet_NaN(), -5.0f, std::numeric_limits<float>::quiet_NaN());
1190
GSVector4 repl(10.0f, 20.0f, 30.0f, 40.0f);
1191
auto r = v.replace_nan(repl);
1192
EXPECT_FLOAT_EQ(r.x, 1.0f); // kept
1193
EXPECT_FLOAT_EQ(r.y, 20.0f); // replaced
1194
EXPECT_FLOAT_EQ(r.z, -5.0f); // kept
1195
EXPECT_FLOAT_EQ(r.w, 40.0f); // replaced
1196
}
1197
1198
TEST(GSVector4Test, DoubleExtendedOps)
1199
{
1200
GSVector4 d = GSVector4::f64(-4.0, 9.0);
1201
auto sq = d.sqr64();
1202
EXPECT_DOUBLE_EQ(sq.F64[0], 16.0);
1203
EXPECT_DOUBLE_EQ(sq.F64[1], 81.0);
1204
1205
auto rt = GSVector4::f64(4.0, 9.0).sqrt64();
1206
EXPECT_DOUBLE_EQ(rt.F64[0], 2.0);
1207
EXPECT_DOUBLE_EQ(rt.F64[1], 3.0);
1208
1209
auto ab = d.abs64();
1210
EXPECT_DOUBLE_EQ(ab.F64[0], 4.0);
1211
EXPECT_DOUBLE_EQ(ab.F64[1], 9.0);
1212
1213
auto ng = d.neg64();
1214
EXPECT_DOUBLE_EQ(ng.F64[0], 4.0);
1215
EXPECT_DOUBLE_EQ(ng.F64[1], -9.0);
1216
1217
GSVector4 d2 = GSVector4::f64(-2.0, 10.0);
1218
EXPECT_DOUBLE_EQ(d.min64(d2).F64[0], -4.0);
1219
EXPECT_DOUBLE_EQ(d.min64(d2).F64[1], 9.0);
1220
EXPECT_DOUBLE_EQ(d.max64(d2).F64[0], -2.0);
1221
EXPECT_DOUBLE_EQ(d.max64(d2).F64[1], 10.0);
1222
1223
auto gt = d.gt64(d2);
1224
EXPECT_EQ(gt.U64[0], 0ULL); // -4 > -2 ? no
1225
EXPECT_EQ(gt.U64[1], 0ULL); // 9 > 10 ? no
1226
auto lt = d.lt64(d2);
1227
EXPECT_NE(lt.U64[0], 0ULL); // -4 < -2
1228
EXPECT_NE(lt.U64[1], 0ULL); // 9 < 10
1229
auto ge = d.ge64(d2);
1230
EXPECT_EQ(ge.U64[0], 0ULL); // -4 >= -2 ? no
1231
EXPECT_EQ(ge.U64[1], 0ULL); // 9 >= 10 ? no
1232
auto le = d.le64(d2);
1233
EXPECT_NE(le.U64[0], 0ULL);
1234
EXPECT_NE(le.U64[1], 0ULL);
1235
auto eq = d.eq64(d);
1236
EXPECT_EQ(eq.U64[0], 0xFFFFFFFFFFFFFFFFULL);
1237
EXPECT_EQ(eq.U64[1], 0xFFFFFFFFFFFFFFFFULL);
1238
}
1239
1240
TEST(GSVector4Test, FloatToDoubleConversions)
1241
{
1242
GSVector4 vf(1.25f, 2.75f, 3.0f, 4.0f);
1243
auto fd = GSVector4::f32to64(vf);
1244
EXPECT_DOUBLE_EQ(fd.F64[0], 1.25);
1245
EXPECT_DOUBLE_EQ(fd.F64[1], 2.75);
1246
1247
GSVector4 vd = GSVector4::f64(5.9, -2.1);
1248
auto i32 = vd.f64toi32();
1249
EXPECT_EQ(i32.S32[0], 5);
1250
EXPECT_EQ(i32.S32[1], -2);
1251
}
1252
1253
// Cross-class conversion tests
1254
TEST(GSVectorTest, ConversionsGSVector2iGSVector2)
1255
{
1256
GSVector2i vi(42, 84);
1257
GSVector2 vf(vi);
1258
EXPECT_FLOAT_EQ(vf.x, 42.0f);
1259
EXPECT_FLOAT_EQ(vf.y, 84.0f);
1260
1261
GSVector2 vf2(3.14f, 2.71f);
1262
GSVector2i vi2(vf2);
1263
EXPECT_EQ(vi2.x, 3);
1264
EXPECT_EQ(vi2.y, 2);
1265
1266
// Test cast operations
1267
auto cast_result = GSVector2::cast(vi);
1268
// Cast preserves bit pattern, so we can't directly compare float values
1269
EXPECT_EQ(cast_result.I32[0], 42);
1270
EXPECT_EQ(cast_result.I32[1], 84);
1271
1272
auto cast_result2 = GSVector2i::cast(vf2);
1273
// Cast preserves bit pattern
1274
EXPECT_EQ(cast_result2.U32[0], vf2.U32[0]);
1275
EXPECT_EQ(cast_result2.U32[1], vf2.U32[1]);
1276
}
1277
1278