• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2021 Intel Corporation
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 <gtest/gtest.h>
25 #include <inttypes.h>
26 
27 #include "util/u_math.h"
28 #include "isl/isl.h"
29 #include "isl/isl_priv.h"
30 
31 #define LIN_OFF(y, tw, x) ((y * tw) + x)
32 #define IMAGE_FORMAT ISL_FORMAT_R32G32B32_UINT
33 #define TILEW_IMAGE_FORMAT ISL_FORMAT_R8_UINT
34 
35 enum TILE_CONV {LIN_TO_TILE, TILE_TO_LIN};
36 
37 typedef uint8_t *(*swizzle_func_t)(const uint8_t *base_addr, uint32_t pitch, uint32_t x_B, uint32_t y_px);
38 
39 #define TILE_COORDINATES                 \
40                  /* x1,  x2, y1, y2 */   \
41    std::make_tuple(  0,   1,  0,  1),    \
42    std::make_tuple(  0,   2,  0,  1),    \
43    std::make_tuple(  0,   4,  0,  1),    \
44    std::make_tuple(  0,   8,  0,  8),    \
45    std::make_tuple(  0, 128,  0, 32),    \
46    std::make_tuple( 19,  20, 25, 32),    \
47    std::make_tuple( 59,  83, 13, 32),    \
48    std::make_tuple( 10,  12,  5,  8),    \
49    std::make_tuple( 64,  65, 16, 17),    \
50    std::make_tuple(128, 129,  0, 32),    \
51    std::make_tuple(245, 521,  5,  8)
52 
53 #define FULL_TILEX_COORDINATES \
54    std::make_tuple(  0,  32,  0,  8),    \
55    std::make_tuple(  0,  64,  0, 16),    \
56    std::make_tuple(  0,  64,  0, 32)
57 
58 #define FULL_TILEY_COORDINATES \
59    std::make_tuple(  0,   8,  0, 32),    \
60    std::make_tuple(  0,  16,  0, 32),    \
61    std::make_tuple(  0,  16,  0, 64)
62 
63 #define FULL_TILEW_COORDINATES \
64    std::make_tuple(  0,  64,  0, 64),    \
65    std::make_tuple(  0, 128,  0, 64),    \
66    std::make_tuple(  0, 128,  0,128)
67 
68 struct tile_swizzle_ops {
69    enum isl_tiling tiling;
70    swizzle_func_t linear_to_tile_swizzle;
71 };
72 
swizzle_bitops(uint32_t num,uint8_t field,uint8_t curr_ind,uint8_t swizzle_ind)73 uint32_t swizzle_bitops(uint32_t num, uint8_t field, uint8_t curr_ind, uint8_t swizzle_ind)
74 {
75    uint32_t bitmask = (1 << field) - 1;
76    uint32_t maskednum = num & (bitmask << curr_ind);
77    uint32_t bits = maskednum >> curr_ind;
78    return bits << swizzle_ind;
79 }
80 
linear_to_tileY_swizzle(const uint8_t * base_addr,uint32_t pitch,uint32_t x_B,uint32_t y_px)81 uint8_t *linear_to_tileY_swizzle(const uint8_t *base_addr, uint32_t pitch, uint32_t x_B, uint32_t y_px)
82 {
83    const uint32_t cu = 7, cv = 5;
84    const uint32_t tile_id = (y_px >> cv) * (pitch >> cu) + (x_B >> cu);
85 
86    /* The table below represents the mapping from coordinate (x_B, y_px) to
87     * byte offset in a 128x32px 1Bpp image:
88     *
89     *    Bit ind : 11 10  9  8  7  6  5  4  3  2  1  0
90     *     Tile-Y : u6 u5 u4 v4 v3 v2 v1 v0 u3 u2 u1 u0
91     */
92    uint32_t tiled_off;
93 
94    tiled_off = tile_id * 4096 |
95                swizzle_bitops(x_B, 4, 0, 0) |
96                swizzle_bitops(y_px, 5, 0, 4) |
97                swizzle_bitops(x_B, 3, 4, 9);
98 
99    return (uint8_t *)(base_addr + tiled_off);
100 }
101 
linear_to_tile4_swizzle(const uint8_t * base_addr,uint32_t pitch,uint32_t x_B,uint32_t y_px)102 uint8_t *linear_to_tile4_swizzle(const uint8_t * base_addr, uint32_t pitch, uint32_t x_B, uint32_t y_px)
103 {
104    const uint32_t cu = 7, cv = 5;
105    const uint32_t tile_id = (y_px >> cv) * (pitch >> cu) + (x_B >> cu);
106 
107    /* The table below represents the mapping from coordinate (x_B, y_px) to
108     * byte offset in a 128x32px 1Bpp image:
109     *
110     *    Bit ind : 11 10  9  8  7  6  5  4  3  2  1  0
111     *     Tile-Y : v4 v3 u6 v2 u5 u4 v1 v0 u3 u2 u1 u0
112     */
113    uint32_t tiled_off;
114 
115    tiled_off = tile_id * 4096 |
116                swizzle_bitops(x_B, 4, 0, 0) |
117                swizzle_bitops(y_px, 2, 0, 4) |
118                swizzle_bitops(x_B, 2, 4, 6) |
119                swizzle_bitops(y_px, 1, 2, 8) |
120                swizzle_bitops(x_B, 1, 6, 9) |
121 	       swizzle_bitops(y_px, 2, 3, 10);
122 
123    return (uint8_t *) (base_addr + tiled_off);
124 }
125 
linear_to_tileX_swizzle(const uint8_t * base_addr,uint32_t pitch,uint32_t x_B,uint32_t y_px)126 uint8_t *linear_to_tileX_swizzle(const uint8_t * base_addr, uint32_t pitch, uint32_t x_B, uint32_t y_px)
127 {
128    const uint32_t cu = 9, cv = 3;
129    const uint32_t tile_id = (y_px >> cv) * (pitch >> cu) + (x_B >> cu);
130 
131    /* The table below represents the mapping from coordinate (x_B, y_px) to
132     * byte offset in a 512x8px 1Bpp image:
133     *
134     *    Bit ind : 11 10  9  8  7  6  5  4  3  2  1  0
135     *     Tile-X : v2 v1 v0 u8 u7 u6 u5 u4 u3 u2 u1 u0
136     */
137    uint32_t tiled_off;
138 
139    tiled_off = tile_id * 4096 |
140                swizzle_bitops(x_B,  9, 0, 0) |
141                swizzle_bitops(y_px, 3, 0, 9);
142 
143    return (uint8_t *) (base_addr + tiled_off);
144 }
145 
linear_to_tileW_swizzle(const uint8_t * base_addr,uint32_t pitch,uint32_t x_B,uint32_t y_px)146 uint8_t *linear_to_tileW_swizzle(const uint8_t *base_addr, uint32_t pitch, uint32_t x_B, uint32_t y_px)
147 {
148    /* TileW is a special case with doubled physical tile width due to HW
149     * programming requirements (see isl_tiling_get_info() in
150     * src/intel/isl/isl.c)
151     */
152    pitch /= 2;
153 
154    const uint32_t cu = 6, cv = 6;
155    const uint32_t tile_id = (y_px >> cv) * (pitch >> cu) + (x_B >> cu);
156 
157    /* The table below represents the mapping from coordinate (x_B, y_px) to
158     * byte offset in a 64x64px 1Bpp image:
159     *
160     *    Bit ind : 11 10  9  8  7  6  5  4  3  2  1  0
161     *     Tile-W : u5 u4 u3 v5 v4 v3 v2 u2 v1 u1 v0 u0
162     */
163    uint32_t tiled_off;
164 
165    tiled_off = tile_id * 4096 |
166                swizzle_bitops(x_B,  1, 0, 0) |
167                swizzle_bitops(y_px, 1, 0, 1) |
168                swizzle_bitops(x_B,  1, 1, 2) |
169                swizzle_bitops(y_px, 1, 1, 3) |
170                swizzle_bitops(x_B,  1, 2, 4) |
171                swizzle_bitops(y_px, 4, 2, 5) |
172                swizzle_bitops(x_B,  3, 3, 9);
173 
174    return (uint8_t *) (base_addr + tiled_off);
175 }
176 
177 struct tile_swizzle_ops swizzle_opers[] = {
178    {ISL_TILING_Y0, linear_to_tileY_swizzle},
179    {ISL_TILING_4, linear_to_tile4_swizzle},
180    {ISL_TILING_X, linear_to_tileX_swizzle},
181    {ISL_TILING_W, linear_to_tileW_swizzle},
182 };
183 
184 class tileTFixture: public ::testing::Test {
185 
186 protected:
187    uint32_t x_max_el;
188    uint32_t y_max_el;
189 
190    uint8_t *buf_dst;
191    uint8_t *buf_src;
192    uint32_t buf_dst_size_B;
193    uint32_t buf_src_size_B;
194 
195    uint32_t tiled_pitch_B, tiled_height;
196    uint32_t tiled_size_B;
197    uint32_t linear_pitch_B;
198    uint32_t linear_sz;
199    uint32_t fmt_bs; /* format bytes per block */
200    TILE_CONV conv;
201    struct tile_swizzle_ops ops;
202    bool print_results;
203    struct isl_tile_info tile_info;
204 
205 public:
206    void test_setup(TILE_CONV convert, enum isl_tiling tiling_fmt,
207               enum isl_format format,
208               uint32_t max_width, uint32_t max_height);
209    void TearDown();
210    uint32_t swizzle_bitops(uint32_t num, uint8_t field,
211                            uint8_t curr_ind, uint8_t swizzle_ind);
212    void bounded_byte_fill(uint32_t x1, uint32_t x2, uint32_t y1, uint32_t y2);
213    void hex_oword_print(const uint8_t *buf, uint32_t size);
214    void convert_texture(uint32_t x1, uint32_t x2, uint32_t y1, uint32_t y2);
215    void compare_conv_result(uint32_t x1, uint32_t x2, uint32_t y1, uint32_t y2);
216    void run_test(uint32_t x1, uint32_t x2, uint32_t y1, uint32_t y2);
217 };
218 
219 class tileYFixture : public tileTFixture,
220                      public ::testing::WithParamInterface<std::tuple<int, int,
221                                                                      int, int>>
222 {};
223 
224 class tile4Fixture : public tileTFixture,
225                      public ::testing::WithParamInterface<std::tuple<int, int,
226                                                                      int, int>>
227 {};
228 
229 class tileXFixture : public tileTFixture,
230                      public ::testing::WithParamInterface<std::tuple<int, int,
231                                                                      int, int>>
232 {};
233 
234 class tileWFixture : public tileTFixture,
235                      public ::testing::WithParamInterface<std::tuple<int, int,
236                                                                      int, int>>
237 {};
238 
test_setup(TILE_CONV convert,enum isl_tiling tiling_fmt,enum isl_format format,uint32_t max_width,uint32_t max_height)239 void tileTFixture::test_setup(TILE_CONV convert,
240                          enum isl_tiling tiling_fmt,
241                          enum isl_format format,
242                          uint32_t max_width,
243                          uint32_t max_height)
244 {
245    print_results = debug_get_bool_option("ISL_TEST_DEBUG", false);
246 
247    const struct isl_format_layout *fmtl = isl_format_get_layout(format);
248    conv = convert;
249    fmt_bs = fmtl->bpb / 8;
250    ops.tiling = tiling_fmt;
251 
252    isl_tiling_get_info(tiling_fmt, ISL_SURF_DIM_2D, ISL_MSAA_LAYOUT_NONE,
253 		       fmtl->bpb, 1 , &tile_info);
254 
255    x_max_el = align(max_width, tile_info.logical_extent_el.w);
256    y_max_el = align(max_height, tile_info.logical_extent_el.h);
257 
258    tiled_pitch_B = (x_max_el * (fmt_bs / (tile_info.format_bpb / 8)) /
259                     tile_info.logical_extent_el.w) *
260                    tile_info.phys_extent_B.w;
261    tiled_height = y_max_el / tile_info.logical_extent_el.h *
262                   tile_info.phys_extent_B.h;
263    tiled_size_B = tiled_pitch_B * tiled_height;
264 
265    linear_pitch_B = x_max_el * fmt_bs;
266    linear_sz = linear_pitch_B * y_max_el;
267 
268    buf_dst_size_B = convert == LIN_TO_TILE ? tiled_size_B : linear_sz;
269    buf_src_size_B = convert == LIN_TO_TILE ? linear_sz : tiled_size_B;
270 
271    buf_src = (uint8_t *) calloc(buf_src_size_B, sizeof(uint8_t));
272    ASSERT_TRUE(buf_src != nullptr);
273 
274    buf_dst = (uint8_t *) calloc(buf_dst_size_B, sizeof(uint8_t));
275    ASSERT_TRUE(buf_src != nullptr);
276 
277    for (uint8_t i = 0; i < ARRAY_SIZE(swizzle_opers); i++)
278       if (ops.tiling == swizzle_opers[i].tiling)
279          ops.linear_to_tile_swizzle = swizzle_opers[i].linear_to_tile_swizzle;
280 
281    memset(buf_src, 0xcc, buf_src_size_B);
282    memset(buf_dst, 0xcc, buf_dst_size_B);
283 }
284 
TearDown()285 void tileTFixture::TearDown()
286 {
287    free(buf_src);
288    buf_src = nullptr;
289 
290    free(buf_dst);
291    buf_dst = nullptr;
292 }
293 
bounded_byte_fill(uint32_t x1_el,uint32_t x2_el,uint32_t y1_el,uint32_t y2_el)294 void tileTFixture::bounded_byte_fill(uint32_t x1_el, uint32_t x2_el,
295                                      uint32_t y1_el, uint32_t y2_el)
296 {
297    for(auto y_el = y1_el; y_el < y2_el; y_el++)
298       for (auto x_b = x1_el * fmt_bs; x_b < x2_el * fmt_bs; x_b++)
299          if (conv == LIN_TO_TILE) {
300             *(buf_src + LIN_OFF(y_el, linear_pitch_B, x_b)) = LIN_OFF(y_el, linear_pitch_B, x_b)%16;
301          } else {
302             *(ops.linear_to_tile_swizzle(buf_src, tiled_pitch_B, x_b, y_el)) =
303                LIN_OFF(y_el, linear_pitch_B, x_b)%16;
304          }
305 }
306 
hex_oword_print(const uint8_t * buf,uint32_t size)307 void tileTFixture::hex_oword_print(const uint8_t *buf, uint32_t size)
308 {
309    uint64_t *itr;
310    uint32_t i;
311 
312    for (itr = (uint64_t *)buf, i=0; itr < (uint64_t *)(buf + size); i++) {
313       fprintf(stdout, "%.16" PRIx64 "%.16" PRIx64, util_bswap64(*(itr)), util_bswap64(*(itr+1)));
314 
315       itr = itr+2;
316 
317       if((i+1) % 8 == 0 && i > 0)
318          printf("\n");
319       else
320          printf("  ");
321    }
322 }
323 
convert_texture(uint32_t x1_el,uint32_t x2_el,uint32_t y1_el,uint32_t y2_el)324 void tileTFixture::convert_texture(uint32_t x1_el, uint32_t x2_el, uint32_t y1_el, uint32_t y2_el)
325 {
326    if (print_results) {
327       printf("/************** Printing src ***************/\n");
328       hex_oword_print((const uint8_t *)buf_src, buf_src_size_B);
329    }
330 
331    uint32_t linear_offset_B = LIN_OFF(y1_el, linear_pitch_B, x1_el * fmt_bs);
332 
333    if (conv == LIN_TO_TILE)
334       isl_memcpy_linear_to_tiled(x1_el * fmt_bs, x2_el * fmt_bs, y1_el, y2_el,
335                                  (char *)buf_dst,
336                                  (const char *)buf_src + linear_offset_B,
337                                  tiled_pitch_B, linear_pitch_B,
338                                  0, ops.tiling, ISL_MEMCPY);
339    else
340       isl_memcpy_tiled_to_linear(x1_el * fmt_bs, x2_el * fmt_bs, y1_el, y2_el,
341                                  (char *)buf_dst + linear_offset_B,
342                                  (const char *)buf_src,
343                                  linear_pitch_B, tiled_pitch_B,
344                                  0, ops.tiling, ISL_MEMCPY);
345 
346    if (print_results) {
347       printf("/************** Printing dest **************/\n");
348       hex_oword_print((const uint8_t *) buf_dst, buf_dst_size_B);
349    }
350 }
351 
compare_conv_result(uint32_t x1_el,uint32_t x2_el,uint32_t y1_el,uint32_t y2_el)352 void tileTFixture::compare_conv_result(uint32_t x1_el, uint32_t x2_el,
353                                        uint32_t y1_el, uint32_t y2_el)
354 {
355    for (uint32_t y_el = 0; y_el < y_max_el; y_el++) {
356       for (uint32_t x_el = 0; x_el < x_max_el; x_el++) {
357          for (uint32_t b = 0; b < fmt_bs; b++) {
358             uint32_t x_b = x_el * fmt_bs + b;
359 
360             if (x_el < x1_el || x_el >= x2_el || y_el < y1_el || y_el >= y2_el) {
361                if (conv == LIN_TO_TILE) {
362                   EXPECT_EQ(*(buf_src + LIN_OFF(y_el, linear_pitch_B, x_b)), 0xcc)
363                      << "Not matching for x:" << x_el << " and y:" << y_el << std::endl;
364                } else {
365                   EXPECT_EQ(*(buf_dst + LIN_OFF(y_el, linear_pitch_B, x_b)), 0xcc)
366                      << "Not matching for x:" << x_el << " and y:" << y_el << std::endl;
367                }
368             } else {
369                if (conv == LIN_TO_TILE) {
370                   EXPECT_EQ(*(buf_src + LIN_OFF(y_el, linear_pitch_B, x_b)),
371                             *(ops.linear_to_tile_swizzle(buf_dst, tiled_pitch_B, x_b, y_el)))
372                      << "Not matching for x:" << x_el << " and y:" << y_el << std::endl;
373                } else {
374                   EXPECT_EQ(*(buf_dst + LIN_OFF(y_el, linear_pitch_B, x_b)),
375                             *(ops.linear_to_tile_swizzle(buf_src, tiled_pitch_B, x_b, y_el)))
376                      << "Not matching for x:" << x_el << " and y:" << y_el << std::endl;
377                }
378             }
379          }
380       }
381    }
382 }
383 
run_test(uint32_t x1,uint32_t x2,uint32_t y1,uint32_t y2)384 void tileTFixture::run_test(uint32_t x1, uint32_t x2,
385                             uint32_t y1, uint32_t y2)
386 {
387     bounded_byte_fill(x1, x2, y1, y2);
388     convert_texture(x1, x2, y1, y2);
389     compare_conv_result(x1, x2, y1, y2);
390 }
391 
TEST_P(tileYFixture,lintotile)392 TEST_P(tileYFixture, lintotile)
393 {
394     auto [x1, x2, y1, y2] = GetParam();
395     test_setup(LIN_TO_TILE, ISL_TILING_Y0, IMAGE_FORMAT, x2, y2);
396     if (print_results)
397        printf("Coordinates: x1=%d x2=%d y1=%d y2=%d \n", x1, x2, y1, y2);
398     run_test(x1, x2, y1, y2);
399 }
400 
TEST_P(tileYFixture,tiletolin)401 TEST_P(tileYFixture, tiletolin)
402 {
403     auto [x1, x2, y1, y2] = GetParam();
404     test_setup(TILE_TO_LIN, ISL_TILING_Y0, IMAGE_FORMAT, x2, y2);
405     if (print_results)
406        printf("Coordinates: x1=%d x2=%d y1=%d y2=%d \n", x1, x2, y1, y2);
407     run_test(x1, x2, y1, y2);
408 }
409 
TEST_P(tile4Fixture,lintotile)410 TEST_P(tile4Fixture, lintotile)
411 {
412     auto [x1, x2, y1, y2] = GetParam();
413     test_setup(LIN_TO_TILE, ISL_TILING_4, IMAGE_FORMAT, x2, y2);
414     if (print_results)
415        printf("Coordinates: x1=%d x2=%d y1=%d y2=%d \n", x1, x2, y1, y2);
416     run_test(x1, x2, y1, y2);
417 }
418 
TEST_P(tile4Fixture,tiletolin)419 TEST_P(tile4Fixture, tiletolin)
420 {
421     auto [x1, x2, y1, y2] = GetParam();
422     test_setup(TILE_TO_LIN, ISL_TILING_4, IMAGE_FORMAT, x2, y2);
423     if (print_results)
424        printf("Coordinates: x1=%d x2=%d y1=%d y2=%d \n", x1, x2, y1, y2);
425     run_test(x1, x2, y1, y2);
426 }
427 
TEST_P(tileXFixture,lintotile)428 TEST_P(tileXFixture, lintotile)
429 {
430     auto [x1, x2, y1, y2] = GetParam();
431     test_setup(LIN_TO_TILE, ISL_TILING_X, IMAGE_FORMAT, x2, y2);
432     if (print_results)
433        printf("Coordinates: x1=%d x2=%d y1=%d y2=%d \n", x1, x2, y1, y2);
434     run_test(x1, x2, y1, y2);
435 }
436 
TEST_P(tileXFixture,tiletolin)437 TEST_P(tileXFixture, tiletolin)
438 {
439     auto [x1, x2, y1, y2] = GetParam();
440     test_setup(TILE_TO_LIN, ISL_TILING_X, IMAGE_FORMAT, x2, y2);
441     if (print_results)
442        printf("Coordinates: x1=%d x2=%d y1=%d y2=%d \n", x1, x2, y1, y2);
443     run_test(x1, x2, y1, y2);
444 }
445 
TEST_P(tileWFixture,lintotile)446 TEST_P(tileWFixture, lintotile)
447 {
448     auto [x1, x2, y1, y2] = GetParam();
449     test_setup(LIN_TO_TILE, ISL_TILING_W, TILEW_IMAGE_FORMAT, x2, y2);
450     if (print_results)
451        printf("Coordinates: x1=%d x2=%d y1=%d y2=%d \n", x1, x2, y1, y2);
452     run_test(x1, x2, y1, y2);
453 }
454 
TEST_P(tileWFixture,tiletolin)455 TEST_P(tileWFixture, tiletolin)
456 {
457     auto [x1, x2, y1, y2] = GetParam();
458     test_setup(TILE_TO_LIN, ISL_TILING_W, TILEW_IMAGE_FORMAT, x2, y2);
459     if (print_results)
460        printf("Coordinates: x1=%d x2=%d y1=%d y2=%d \n", x1, x2, y1, y2);
461     run_test(x1, x2, y1, y2);
462 }
463 
464 
465 INSTANTIATE_TEST_SUITE_P(tileY, tileYFixture, testing::Values(TILE_COORDINATES,
466                                                               FULL_TILEY_COORDINATES));
467 INSTANTIATE_TEST_SUITE_P(tile4, tile4Fixture, testing::Values(TILE_COORDINATES,
468                                                               FULL_TILEY_COORDINATES));
469 INSTANTIATE_TEST_SUITE_P(tileX, tileXFixture, testing::Values(TILE_COORDINATES,
470                                                               FULL_TILEX_COORDINATES));
471 INSTANTIATE_TEST_SUITE_P(tileW, tileWFixture, testing::Values(TILE_COORDINATES,
472                                                               FULL_TILEW_COORDINATES));
473