• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2024 Collabora, Ltd.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  */
23 
24 #include "nir_test.h"
25 #include "nir_format_convert.h"
26 
27 #include "util/macros.h"
28 #include "util/format/u_formats.h"
29 #include "util/format_srgb.h"
30 #include "util/half_float.h"
31 #include "util/u_endian.h"
32 #include "util/u_math.h"
33 
34 /* These tests and the NIR code currently assume little endian */
35 #if UTIL_ARCH_LITTLE_ENDIAN
36 
37 #define NUM_COLORS 32
38 
39 class nir_format_convert_test
40    : public nir_test
41    , public testing::WithParamInterface<pipe_format>
42 {
43 protected:
nir_format_convert_test()44    nir_format_convert_test()
45       : nir_test::nir_test("nir_format_convert_test")
46    { }
47 };
48 
49 /* Repeatable random number generator */
50 static uint16_t
rand_u16(void)51 rand_u16(void)
52 {
53    static const uint16_t data[] = {
54    /* Important numbers we want to hit, twice for good measure */
55       0, 0, 128, 128, 255, 255, 256, 256, 32768, 32768, 65535, 65535,
56 
57    /* 100 random 16-bit numbers from random.org */
58       31401 , 17066 , 65230 , 954   , 12680 ,
59       3631  , 45135 , 1477  , 40861 , 62785 ,
60       35775 , 3171  , 24120 , 6774  , 24488 ,
61       12377 , 29039 , 22146 , 27893 , 62104 ,
62       15854 , 36623 , 23545 , 47719 , 31666 ,
63       23657 , 43795 , 64813 , 18846 , 32886 ,
64       48464 , 28934 , 48575 , 9247  , 32525 ,
65       82    , 15366 , 24299 , 13694 , 48017 ,
66       48449 , 13739 , 47257 , 52684 , 52094 ,
67       61776 , 42874 , 1031  , 11529 , 15276 ,
68       26020 , 494   , 47804 , 50461 , 55816 ,
69       44489 , 22592 , 44167 , 64247 , 60796 ,
70       49925 , 23000 , 12849 , 20699 , 62204 ,
71       5888  , 3813  , 27129 , 29019 , 7790  ,
72       65437 , 64541 , 41808 , 28539 , 29315 ,
73       50120 , 24765 , 7507  , 9653  , 62136 ,
74       32915 , 15143 , 39313 , 50201 , 29143 ,
75       14190 , 10041 , 31015 , 20616 , 42076 ,
76       23404 , 61917 , 10701 , 40230 , 38904 ,
77       30589 , 47499 , 63444 , 49431 , 40875 ,
78    };
79 
80    static int count = 0;
81 
82    int i = count;
83    count = (i + 1) % ARRAY_SIZE(data);
84 
85    return data[i];
86 }
87 
88 static uint32_t
rand_uint(unsigned bits)89 rand_uint(unsigned bits)
90 {
91    uint32_t data = rand_u16();
92    if (bits > 16)
93       data |= rand_u16() << 16;
94    assert(bits <= 32);
95 
96    return data & BITFIELD_MASK(bits);
97 }
98 
99 static int32_t
rand_int(unsigned bits)100 rand_int(unsigned bits)
101 {
102    uint32_t data = rand_u16();
103    if (bits > 16)
104       data |= rand_u16() << 16;
105    assert(bits <= 32);
106 
107    return util_mask_sign_extend(data, bits);
108 }
109 
110 static uint32_t
rand_color(util_format_colorspace colorspace,util_format_type type,bool normalized,bool pure_integer,unsigned bits)111 rand_color(util_format_colorspace colorspace,
112            util_format_type type,
113            bool normalized,
114            bool pure_integer,
115            unsigned bits)
116 {
117    switch (type) {
118    case UTIL_FORMAT_TYPE_VOID:
119       return 0;
120 
121    case UTIL_FORMAT_TYPE_UNSIGNED:
122       if (pure_integer) {
123          assert(colorspace == UTIL_FORMAT_COLORSPACE_RGB);
124          return rand_uint(bits);
125       } else if (normalized) {
126          switch (colorspace) {
127          case UTIL_FORMAT_COLORSPACE_RGB:
128             /* By starting with an integer, we ensure we don't get funny
129              * rounding.
130              */
131             return fui(rand_uint(bits) / (float)u_uintN_max(bits));
132 
133          case UTIL_FORMAT_COLORSPACE_SRGB:
134             /* By starting with an integer, we ensure we don't get funny
135              * rounding.
136              */
137             assert(bits == 8);
138             return util_format_srgb_8unorm_to_linear_float(rand_uint(8));
139 
140          default:
141             unreachable("Unknown colorspace");
142          }
143       } else {
144          assert(colorspace == UTIL_FORMAT_COLORSPACE_RGB);
145          return fui((float)rand_uint(bits));
146       }
147 
148    case UTIL_FORMAT_TYPE_SIGNED:
149       assert(colorspace == UTIL_FORMAT_COLORSPACE_RGB);
150       if (pure_integer) {
151          return rand_int(bits);
152       } else if (normalized) {
153          /* By starting with an integer, we ensure we don't get funny
154           * rounding.
155           */
156          return fui(rand_int(bits) / (float)u_intN_max(bits));
157       } else {
158          return fui((float)rand_int(bits));
159       }
160 
161    case UTIL_FORMAT_TYPE_FIXED:
162       assert(colorspace == UTIL_FORMAT_COLORSPACE_RGB);
163       return rand_uint(bits);
164 
165    case UTIL_FORMAT_TYPE_FLOAT:
166       assert(colorspace == UTIL_FORMAT_COLORSPACE_RGB);
167       if (bits <= 16) {
168          uint16_t val = rand_u16();
169          /* Let's keep it to numbers, shall we? */
170          if ((val & 0x7c00) == 0x7c00)
171             val &= 0xfc00;
172 
173          /* Make sure the mantissa fits so we don't round funny */
174          if (bits < 16)
175             val &= ~BITFIELD_MASK(16 - bits);
176 
177          return fui(_mesa_half_to_float(val));
178       } else if (bits == 32) {
179          uint32_t val = rand_uint(32);
180          /* Let's keep it to numbers, shall we? */
181          if ((val & 0x7f800000) == 0x7f800000)
182             val &= 0xff800000;
183          return val;
184       }
185 
186    default:
187       unreachable("Invalid format type");
188    }
189 }
190 
191 class rgba : public nir_format_convert_test { };
192 
TEST_P(rgba,pack)193 TEST_P(rgba, pack)
194 {
195    pipe_format format = GetParam();
196    auto desc = util_format_description(format);
197 
198    struct {
199       uint32_t u32[4];
200    } colors[NUM_COLORS];
201    for (unsigned i = 0; i < NUM_COLORS; i++) {
202       for (unsigned c = 0; c < 4; c++) {
203          pipe_swizzle s = (pipe_swizzle)desc->swizzle[c];
204          if (s < PIPE_SWIZZLE_X || s > PIPE_SWIZZLE_W) {
205             colors[i].u32[c] = 0;
206          } else {
207             auto chan = &desc->channel[s - PIPE_SWIZZLE_X];
208             assert(chan->type != (unsigned)UTIL_FORMAT_TYPE_VOID);
209             colors[i].u32[c] = rand_color(desc->colorspace,
210                                           (util_format_type)chan->type,
211                                           chan->normalized,
212                                           chan->pure_integer,
213                                           chan->size);
214          }
215       }
216    }
217 
218    nir_intrinsic_instr *uses[NUM_COLORS];
219    for (unsigned i = 0; i < NUM_COLORS; i++) {
220       nir_def *rgba = nir_imm_ivec4(b, colors[i].u32[0],
221                                        colors[i].u32[1],
222                                        colors[i].u32[2],
223                                        colors[i].u32[3]);
224       nir_def *packed = nir_format_pack_rgba(b, format, rgba);
225       uses[i] = nir_use(b, packed);
226    }
227 
228    nir_lower_undef_to_zero(b->shader);
229    ASSERT_TRUE(nir_opt_constant_folding(b->shader));
230    ASSERT_TRUE(nir_opt_dce(b->shader));
231 
232    for (unsigned i = 0; i < NUM_COLORS; i++) {
233       char expected[16] = { 0, };
234       util_format_pack_rgba(format, expected, colors[i].u32, 1);
235 
236       nir_def *packed_ssa = uses[i]->src[0].ssa;
237       const nir_const_value *packed =
238          nir_instr_as_load_const(packed_ssa->parent_instr)->value;
239       if (packed_ssa->num_components == 1) {
240          switch (packed_ssa->bit_size) {
241          case 8:
242             EXPECT_EQ(*(uint8_t *)expected, packed[0].u8);
243             break;
244          case 16:
245             EXPECT_EQ(*(uint16_t *)expected, packed[0].u16);
246             break;
247          case 32:
248             EXPECT_EQ(*(uint32_t *)expected, packed[0].u32);
249             break;
250          default:
251             unreachable("Unsupported packed data bit size");
252          }
253       } else {
254          assert(packed_ssa->bit_size == 32);
255          uint32_t *exp_u32 = (uint32_t *)expected;
256          for (unsigned c = 0; c < packed_ssa->num_components; c++)
257             EXPECT_EQ(exp_u32[c], packed[c].u32);
258       }
259    }
260 }
261 
TEST_P(rgba,unpack)262 TEST_P(rgba, unpack)
263 {
264    pipe_format format = GetParam();
265    auto desc = util_format_description(format);
266    const unsigned dwords = DIV_ROUND_UP(desc->block.bits, 32);
267 
268    struct {
269       uint32_t u32[4];
270    } colors[NUM_COLORS];
271    memset(colors, 0, sizeof(colors));
272 
273    for (unsigned i = 0; i < NUM_COLORS; i++) {
274       for (unsigned dw = 0; dw < dwords; dw++) {
275          unsigned bits = MIN2(32, desc->block.bits - dw * 32);
276          colors[i].u32[dw] = rand_uint(bits);
277       }
278    }
279 
280    nir_intrinsic_instr *uses[NUM_COLORS];
281    for (unsigned i = 0; i < NUM_COLORS; i++) {
282       nir_def *packed_comps[4];
283       for (unsigned dw = 0; dw < dwords; dw++)
284          packed_comps[dw] = nir_imm_int(b, colors[i].u32[dw]);
285       nir_def *packed = nir_vec(b, packed_comps, dwords);
286       nir_def *rgba = nir_format_unpack_rgba(b, packed, format);
287       uses[i] = nir_use(b, rgba);
288    }
289 
290    nir_lower_undef_to_zero(b->shader);
291    ASSERT_TRUE(nir_opt_constant_folding(b->shader));
292    ASSERT_TRUE(nir_opt_dce(b->shader));
293 
294    for (unsigned i = 0; i < NUM_COLORS; i++) {
295       char expected[16] = { 0, };
296       util_format_unpack_rgba(format, expected, colors[i].u32, 1);
297 
298       nir_def *rgba_ssa = uses[i]->src[0].ssa;
299       assert(rgba_ssa->bit_size == 32);
300       assert(rgba_ssa->num_components == 4);
301 
302       const nir_const_value *rgba =
303          nir_instr_as_load_const(rgba_ssa->parent_instr)->value;
304 
305       if (util_format_is_pure_integer(format)) {
306          uint32_t *exp_u32 = (uint32_t *)expected;
307          for (uint32_t c = 0; c < 4; c++)
308             EXPECT_EQ(exp_u32[c], rgba[c].u32);
309       } else {
310          float *exp_f32 = (float *)expected;
311          for (uint32_t c = 0; c < 4; c++) {
312             EXPECT_EQ(isnan(exp_f32[c]), isnan(uif(rgba[c].u32)));
313             if (!isnan(exp_f32[c]) && !isnan(uif(rgba[c].u32))) {
314                EXPECT_FLOAT_EQ(exp_f32[c], uif(rgba[c].u32));
315             }
316          }
317       }
318    }
319 }
320 
321 INSTANTIATE_TEST_SUITE_P(nir_format_convert_test, rgba, testing::Values(
322 // There's no way to get bit-for-bit identical with the CPU for these
323 //
324 // PIPE_FORMAT_R32_UNORM,
325 // PIPE_FORMAT_R32G32_UNORM,
326 // PIPE_FORMAT_R32G32B32_UNORM,
327 // PIPE_FORMAT_R32G32B32A32_UNORM,
328 // PIPE_FORMAT_R32_USCALED,
329 // PIPE_FORMAT_R32G32_USCALED,
330 // PIPE_FORMAT_R32G32B32_USCALED,
331 // PIPE_FORMAT_R32G32B32A32_USCALED,
332 // PIPE_FORMAT_R32_SNORM,
333 // PIPE_FORMAT_R32G32_SNORM,
334 // PIPE_FORMAT_R32G32B32_SNORM,
335 // PIPE_FORMAT_R32G32B32A32_SNORM,
336 // PIPE_FORMAT_R32_SSCALED,
337 // PIPE_FORMAT_R32G32_SSCALED,
338 // PIPE_FORMAT_R32G32B32_SSCALED,
339 // PIPE_FORMAT_R32G32B32A32_SSCALED,
340 
341    PIPE_FORMAT_R16_UNORM,
342    PIPE_FORMAT_R16G16_UNORM,
343    PIPE_FORMAT_R16G16B16_UNORM,
344    PIPE_FORMAT_R16G16B16A16_UNORM,
345    PIPE_FORMAT_R16_USCALED,
346    PIPE_FORMAT_R16G16_USCALED,
347    PIPE_FORMAT_R16G16B16_USCALED,
348    PIPE_FORMAT_R16G16B16A16_USCALED,
349    PIPE_FORMAT_R16_SNORM,
350    PIPE_FORMAT_R16G16_SNORM,
351    PIPE_FORMAT_R16G16B16_SNORM,
352    PIPE_FORMAT_R16G16B16A16_SNORM,
353    PIPE_FORMAT_R16_SSCALED,
354    PIPE_FORMAT_R16G16_SSCALED,
355    PIPE_FORMAT_R16G16B16_SSCALED,
356    PIPE_FORMAT_R16G16B16A16_SSCALED,
357    PIPE_FORMAT_R8_UNORM,
358    PIPE_FORMAT_R8G8_UNORM,
359    PIPE_FORMAT_R8G8B8_UNORM,
360    PIPE_FORMAT_B8G8R8_UNORM,
361    PIPE_FORMAT_R8G8B8A8_UNORM,
362    PIPE_FORMAT_B8G8R8A8_UNORM,
363    PIPE_FORMAT_R8_USCALED,
364    PIPE_FORMAT_R8G8_USCALED,
365    PIPE_FORMAT_R8G8B8_USCALED,
366    PIPE_FORMAT_B8G8R8_USCALED,
367    PIPE_FORMAT_R8G8B8A8_USCALED,
368    PIPE_FORMAT_B8G8R8A8_USCALED,
369    PIPE_FORMAT_A8B8G8R8_USCALED,
370    PIPE_FORMAT_R8_SNORM,
371    PIPE_FORMAT_R8G8_SNORM,
372    PIPE_FORMAT_R8G8B8_SNORM,
373    PIPE_FORMAT_B8G8R8_SNORM,
374    PIPE_FORMAT_R8G8B8A8_SNORM,
375    PIPE_FORMAT_B8G8R8A8_SNORM,
376    PIPE_FORMAT_R8_SSCALED,
377    PIPE_FORMAT_R8G8_SSCALED,
378    PIPE_FORMAT_R8G8B8_SSCALED,
379    PIPE_FORMAT_B8G8R8_SSCALED,
380    PIPE_FORMAT_R8G8B8A8_SSCALED,
381    PIPE_FORMAT_B8G8R8A8_SSCALED,
382    PIPE_FORMAT_A8B8G8R8_SSCALED,
383    PIPE_FORMAT_A8R8G8B8_UNORM,
384 
385 // nir_format_[un]pack() don't handle the legacy GL fixed formats
386 //
387 // PIPE_FORMAT_R32_FIXED,
388 // PIPE_FORMAT_R32G32_FIXED,
389 // PIPE_FORMAT_R32G32B32_FIXED,
390 // PIPE_FORMAT_R32G32B32A32_FIXED,
391 
392    PIPE_FORMAT_R16_FLOAT,
393    PIPE_FORMAT_R16G16_FLOAT,
394    PIPE_FORMAT_R16G16B16_FLOAT,
395    PIPE_FORMAT_R16G16B16A16_FLOAT,
396    PIPE_FORMAT_R8_UINT,
397    PIPE_FORMAT_R8G8_UINT,
398    PIPE_FORMAT_R8G8B8_UINT,
399    PIPE_FORMAT_B8G8R8_UINT,
400    PIPE_FORMAT_R8G8B8A8_UINT,
401    PIPE_FORMAT_B8G8R8A8_UINT,
402    PIPE_FORMAT_R8_SINT,
403    PIPE_FORMAT_R8G8_SINT,
404    PIPE_FORMAT_R8G8B8_SINT,
405    PIPE_FORMAT_B8G8R8_SINT,
406    PIPE_FORMAT_R8G8B8A8_SINT,
407    PIPE_FORMAT_B8G8R8A8_SINT,
408    PIPE_FORMAT_R16_UINT,
409    PIPE_FORMAT_R16G16_UINT,
410    PIPE_FORMAT_R16G16B16_UINT,
411    PIPE_FORMAT_R16G16B16A16_UINT,
412    PIPE_FORMAT_R16_SINT,
413    PIPE_FORMAT_R16G16_SINT,
414    PIPE_FORMAT_R16G16B16_SINT,
415    PIPE_FORMAT_R16G16B16A16_SINT,
416    PIPE_FORMAT_R32_UINT,
417    PIPE_FORMAT_R32G32_UINT,
418    PIPE_FORMAT_R32G32B32_UINT,
419    PIPE_FORMAT_R32G32B32A32_UINT,
420    PIPE_FORMAT_R32_SINT,
421    PIPE_FORMAT_R32G32_SINT,
422    PIPE_FORMAT_R32G32B32_SINT,
423    PIPE_FORMAT_R32G32B32A32_SINT,
424 
425    PIPE_FORMAT_R10G10B10A2_UNORM,
426    PIPE_FORMAT_R10G10B10A2_SNORM,
427    PIPE_FORMAT_R10G10B10A2_USCALED,
428    PIPE_FORMAT_R10G10B10A2_SSCALED,
429 
430    PIPE_FORMAT_B10G10R10A2_UNORM,
431    PIPE_FORMAT_B10G10R10A2_SNORM,
432    PIPE_FORMAT_B10G10R10A2_USCALED,
433    PIPE_FORMAT_B10G10R10A2_SSCALED,
434 
435    PIPE_FORMAT_R11G11B10_FLOAT,
436 
437    PIPE_FORMAT_R10G10B10A2_UINT,
438    PIPE_FORMAT_R10G10B10A2_SINT,
439 
440    PIPE_FORMAT_B10G10R10A2_UINT,
441    PIPE_FORMAT_B10G10R10A2_SINT,
442 
443    PIPE_FORMAT_B8G8R8X8_UNORM,
444    PIPE_FORMAT_X8B8G8R8_UNORM,
445    PIPE_FORMAT_X8R8G8B8_UNORM,
446    PIPE_FORMAT_B5G5R5A1_UNORM,
447    PIPE_FORMAT_R4G4B4A4_UNORM,
448    PIPE_FORMAT_B4G4R4A4_UNORM,
449    PIPE_FORMAT_R5G6B5_UNORM,
450    PIPE_FORMAT_B5G6R5_UNORM,
451 
452    PIPE_FORMAT_R8G8_SRGB,
453    PIPE_FORMAT_R8G8B8_SRGB,
454    PIPE_FORMAT_B8G8R8_SRGB,
455    PIPE_FORMAT_A8B8G8R8_SRGB,
456    PIPE_FORMAT_X8B8G8R8_SRGB,
457    PIPE_FORMAT_B8G8R8A8_SRGB,
458    PIPE_FORMAT_B8G8R8X8_SRGB,
459    PIPE_FORMAT_A8R8G8B8_SRGB,
460    PIPE_FORMAT_X8R8G8B8_SRGB,
461    PIPE_FORMAT_R8G8B8A8_SRGB
462 ));
463 
464 #endif /* UTIL_ARCH_LITTLE_ENDIAN */
465