xref: /aosp_15_r20/external/mesa3d/src/intel/isl/tests/isl_tilememcpy_tiled_unittest.cpp (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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 
34 enum TILE_CONV {LIN_TO_TILE, TILE_TO_LIN};
35 
36 typedef uint8_t *(*swizzle_func_t)(const uint8_t *base_addr, uint32_t x_B, uint32_t y_px);
37 
38 #define TILE_COORDINATES  std::make_tuple(0, 128, 0, 32), \
39                           std::make_tuple(19, 20, 25, 32), \
40                           std::make_tuple(59, 83, 13, 32), \
41                           std::make_tuple(10, 12, 5, 8), \
42                           std::make_tuple(245, 521, 5, 8)
43 
44 struct tile_swizzle_ops {
45    enum isl_tiling tiling;
46    swizzle_func_t linear_to_tile_swizzle;
47 };
48 
swizzle_bitops(uint32_t num,uint8_t field,uint8_t curr_ind,uint8_t swizzle_ind)49 uint32_t swizzle_bitops(uint32_t num, uint8_t field, uint8_t curr_ind, uint8_t swizzle_ind)
50 {
51    uint32_t bitmask = (1 << field) - 1;
52    uint32_t maskednum = num & (bitmask << curr_ind);
53    uint32_t bits = maskednum >> curr_ind;
54    return bits << swizzle_ind;
55 }
56 
linear_to_Ytile_swizzle(const uint8_t * base_addr,uint32_t x_B,uint32_t y_px)57 uint8_t *linear_to_Ytile_swizzle(const uint8_t *base_addr, uint32_t x_B, uint32_t y_px)
58 {
59    /* The table below represents the mapping from coordinate (x_B, y_px) to
60     * byte offset in a 128x32px 1Bpp image:
61     *
62     *    Bit ind : 11 10  9  8  7  6  5  4  3  2  1  0
63     *     Tile-Y : u6 u5 u4 v4 v3 v2 v1 v0 u3 u2 u1 u0
64     */
65    uint32_t tiled_off;
66 
67    tiled_off = swizzle_bitops(x_B, 4, 0, 0) |
68                swizzle_bitops(y_px, 5, 0, 4) |
69                swizzle_bitops(x_B, 3, 4, 9);
70 
71    return (uint8_t *)(base_addr + tiled_off);
72 }
73 
linear_to_tile4_swizzle(const uint8_t * base_addr,uint32_t x_B,uint32_t y_px)74 uint8_t *linear_to_tile4_swizzle(const uint8_t * base_addr, uint32_t x_B, uint32_t y_px)
75 {
76    /* The table below represents the mapping from coordinate (x_B, y_px) to
77     * byte offset in a 128x32px 1Bpp image:
78     *
79     *    Bit ind : 11 10  9  8  7  6  5  4  3  2  1  0
80     *     Tile-Y : v4 v3 u6 v2 u5 u4 v1 v0 u3 u2 u1 u0
81     */
82    uint32_t tiled_off;
83 
84    tiled_off = swizzle_bitops(x_B, 4, 0, 0) |
85                swizzle_bitops(y_px, 2, 0, 4) |
86                swizzle_bitops(x_B, 2, 4, 6) |
87                swizzle_bitops(y_px, 1, 2, 8) |
88                swizzle_bitops(x_B, 1, 6, 9) |
89 	       swizzle_bitops(y_px, 2, 3, 10);
90 
91    return (uint8_t *) (base_addr + tiled_off);
92 }
93 
94 struct tile_swizzle_ops swizzle_opers[] = {
95    {ISL_TILING_Y0, linear_to_Ytile_swizzle},
96    {ISL_TILING_4, linear_to_tile4_swizzle},
97 };
98 
99 class tileTFixture: public ::testing::Test {
100 
101 protected:
102    uint8_t *buf_dst;
103    uint8_t *buf_src;
104    uint32_t tile_width, tile_height;
105    uint32_t tile_sz;
106    TILE_CONV conv;
107    struct tile_swizzle_ops ops;
108    bool print_results;
109    struct isl_tile_info tile_info;
110 
111 public:
112    void test_setup(TILE_CONV convert, enum isl_tiling tiling_fmt,
113               enum isl_format format,
114               uint32_t max_width, uint32_t max_height);
115    void TearDown();
116    uint32_t swizzle_bitops(uint32_t num, uint8_t field,
117                            uint8_t curr_ind, uint8_t swizzle_ind);
118    void bounded_byte_fill(uint8_t x1, uint8_t x2, uint8_t y1, uint8_t y2);
119    void hex_oword_print(const uint8_t *buf, uint32_t size);
120    void convert_texture(uint8_t x1, uint8_t x2, uint8_t y1, uint8_t y2);
121    void compare_conv_result(uint8_t x1, uint8_t x2, uint8_t y1, uint8_t y2);
122    void run_test(uint8_t x1, uint8_t x2, uint8_t y1, uint8_t y2);
123 };
124 
125 class tileYFixture : public tileTFixture,
126                      public ::testing::WithParamInterface<std::tuple<int, int,
127                                                                      int, int>>
128 {};
129 
130 class tile4Fixture : public tileTFixture,
131                      public ::testing::WithParamInterface<std::tuple<int, int,
132                                                                      int, int>>
133 {};
134 
test_setup(TILE_CONV convert,enum isl_tiling tiling_fmt,enum isl_format format,uint32_t max_width,uint32_t max_height)135 void tileTFixture::test_setup(TILE_CONV convert,
136                          enum isl_tiling tiling_fmt,
137                          enum isl_format format,
138                          uint32_t max_width,
139                          uint32_t max_height)
140 {
141    print_results = debug_get_bool_option("ISL_TEST_DEBUG", false);
142 
143    const struct isl_format_layout *fmtl = isl_format_get_layout(format);
144    conv = convert;
145    ops.tiling = tiling_fmt;
146 
147    isl_tiling_get_info(tiling_fmt, ISL_SURF_DIM_2D, ISL_MSAA_LAYOUT_NONE,
148 		       fmtl->bpb, 1 , &tile_info);
149 
150    tile_width = DIV_ROUND_UP(max_width, tile_info.logical_extent_el.w) *
151                 tile_info.phys_extent_B.w;
152    tile_height = DIV_ROUND_UP(max_height, tile_info.logical_extent_el.h) *
153                  tile_info.phys_extent_B.h;
154    tile_sz = tile_width * tile_height;
155 
156    buf_src = (uint8_t *) calloc(tile_sz, sizeof(uint8_t));
157    ASSERT_TRUE(buf_src != nullptr);
158 
159    buf_dst = (uint8_t *) calloc(tile_sz, sizeof(uint8_t));
160    ASSERT_TRUE(buf_src != nullptr);
161 
162    for (uint8_t i = 0; i < ARRAY_SIZE(swizzle_opers); i++)
163       if (ops.tiling == swizzle_opers[i].tiling)
164          ops.linear_to_tile_swizzle = swizzle_opers[i].linear_to_tile_swizzle;
165 
166    memset(buf_src, 0xcc, tile_sz);
167    memset(buf_dst, 0xcc, tile_sz);
168 }
169 
TearDown()170 void tileTFixture::TearDown()
171 {
172    free(buf_src);
173    buf_src = nullptr;
174 
175    free(buf_dst);
176    buf_dst = nullptr;
177 }
178 
bounded_byte_fill(uint8_t x1,uint8_t x2,uint8_t y1,uint8_t y2)179 void tileTFixture::bounded_byte_fill(uint8_t x1, uint8_t x2, uint8_t y1, uint8_t y2)
180 {
181    uint8_t *itr = (uint8_t *) buf_src;
182 
183    for(auto y = y1; y < y2; y++)
184       for (auto x = x1; x < x2; x++)
185          if (conv == LIN_TO_TILE)
186             *(itr + LIN_OFF(y, tile_width, x)) = LIN_OFF(y, tile_width, x)/16;
187          else
188             *(ops.linear_to_tile_swizzle(buf_src, x, y)) = LIN_OFF(y, tile_width, x)/16;
189 }
190 
hex_oword_print(const uint8_t * buf,uint32_t size)191 void tileTFixture::hex_oword_print(const uint8_t *buf, uint32_t size)
192 {
193    uint64_t *itr;
194    uint32_t i;
195 
196    for (itr = (uint64_t *)buf, i=0; itr < (uint64_t *)(buf + size); i++) {
197       fprintf(stdout, "%.16" PRIx64 "%.16" PRIx64, util_bswap64(*(itr)), util_bswap64(*(itr+1)));
198 
199       itr = itr+2;
200 
201       if((i+1) % 8 == 0 && i > 0)
202          printf("\n");
203       else
204          printf("  ");
205    }
206 }
207 
convert_texture(uint8_t x1,uint8_t x2,uint8_t y1,uint8_t y2)208 void tileTFixture::convert_texture(uint8_t x1, uint8_t x2, uint8_t y1, uint8_t y2)
209 {
210    if (print_results) {
211       printf("/************** Printing src ***************/\n");
212       hex_oword_print((const uint8_t *)buf_src, tile_sz);
213    }
214 
215    if (conv == LIN_TO_TILE)
216       isl_memcpy_linear_to_tiled(x1, x2, y1, y2,
217                                  (char *)buf_dst,
218                                  (const char *)buf_src + LIN_OFF(y1, tile_width, x1),
219                                  tile_width, tile_width,
220                                  0, ops.tiling, ISL_MEMCPY);
221    else
222       isl_memcpy_tiled_to_linear(x1, x2, y1, y2,
223                                  (char *)buf_dst + LIN_OFF(y1, tile_width, x1),
224                                  (const char *)buf_src,
225                                  tile_width, tile_width,
226                                  0, ops.tiling, ISL_MEMCPY);
227 
228    if (print_results) {
229       printf("/************** Printing dest **************/\n");
230       hex_oword_print((const uint8_t *) buf_dst, tile_sz);
231    }
232 }
233 
compare_conv_result(uint8_t x1,uint8_t x2,uint8_t y1,uint8_t y2)234 void tileTFixture::compare_conv_result(uint8_t x1, uint8_t x2,
235                                        uint8_t y1, uint8_t y2)
236 {
237    uint32_t x_max = (uint32_t) align(x2, tile_info.logical_extent_el.w);
238    uint32_t y_max = (uint32_t) align(y2, tile_info.logical_extent_el.h);
239 
240    for(uint32_t y = 0; y < y_max; y++) {
241       for (uint32_t x = 0; x < x_max; x++) {
242 
243          if (x < x1 || x > x2 || y < y1 || y > y2) {
244             if (conv == LIN_TO_TILE) {
245                EXPECT_EQ(*(buf_src + LIN_OFF(y, tile_width, x)), 0xcc)
246                   << "Not matching for x:" << x << "and y:" << y << std::endl;
247             } else {
248                EXPECT_EQ(*(buf_dst + LIN_OFF(y, tile_width, x)), 0xcc)
249                   << "Not matching for x:" << x << "and y:" << y << std::endl;
250             }
251          } else {
252             if (conv == LIN_TO_TILE) {
253                EXPECT_EQ(*(buf_src + LIN_OFF(y, tile_width, x)),
254                          *(ops.linear_to_tile_swizzle(buf_dst, x, y)))
255                   << "Not matching for x:" << x << "and y:" << y << std::endl;
256             } else {
257                EXPECT_EQ(*(buf_dst + LIN_OFF(y, tile_width, x)),
258                          *(ops.linear_to_tile_swizzle(buf_src, x, y)))
259                   << "Not matching for x:" << x << "and y:" << y << std::endl;
260             }
261          }
262       }
263    }
264 }
265 
run_test(uint8_t x1,uint8_t x2,uint8_t y1,uint8_t y2)266 void tileTFixture::run_test(uint8_t x1, uint8_t x2,
267                             uint8_t y1, uint8_t y2)
268 {
269     bounded_byte_fill(x1, x2, y1, y2);
270     convert_texture(x1, x2, y1, y2);
271     compare_conv_result(x1, x2, y1, y2);
272 }
273 
TEST_P(tileYFixture,lintotile)274 TEST_P(tileYFixture, lintotile)
275 {
276     auto [x1, x2, y1, y2] = GetParam();
277     test_setup(LIN_TO_TILE, ISL_TILING_Y0, IMAGE_FORMAT, x2, y2);
278     if (print_results)
279        printf("Coordinates: x1=%d x2=%d y1=%d y2=%d \n", x1, x2, y1, y2);
280     run_test(x1, x2, y1, y2);
281 }
282 
TEST_P(tileYFixture,tiletolin)283 TEST_P(tileYFixture, tiletolin)
284 {
285     auto [x1, x2, y1, y2] = GetParam();
286     test_setup(TILE_TO_LIN, ISL_TILING_Y0, IMAGE_FORMAT, x2, y2);
287     if (print_results)
288        printf("Coordinates: x1=%d x2=%d y1=%d y2=%d \n", x1, x2, y1, y2);
289     run_test(x1, x2, y1, y2);
290 }
291 
TEST_P(tile4Fixture,lintotile)292 TEST_P(tile4Fixture, lintotile)
293 {
294     auto [x1, x2, y1, y2] = GetParam();
295     test_setup(LIN_TO_TILE, ISL_TILING_4, IMAGE_FORMAT, x2, y2);
296     if (print_results)
297        printf("Coordinates: x1=%d x2=%d y1=%d y2=%d \n", x1, x2, y1, y2);
298     run_test(x1, x2, y1, y2);
299 }
300 
TEST_P(tile4Fixture,tiletolin)301 TEST_P(tile4Fixture, tiletolin)
302 {
303     auto [x1, x2, y1, y2] = GetParam();
304     test_setup(TILE_TO_LIN, ISL_TILING_4, IMAGE_FORMAT, x2, y2);
305     if (print_results)
306        printf("Coordinates: x1=%d x2=%d y1=%d y2=%d \n", x1, x2, y1, y2);
307     run_test(x1, x2, y1, y2);
308 }
309 
310 
311 INSTANTIATE_TEST_SUITE_P(Ytile, tileYFixture, testing::Values(TILE_COORDINATES));
312 INSTANTIATE_TEST_SUITE_P(tile4, tile4Fixture, testing::Values(TILE_COORDINATES));
313