xref: /aosp_15_r20/external/igt-gpu-tools/tests/i915/gem_tiled_pread_basic.c (revision d83cc019efdc2edc6c4b16e9034a3ceb8d35d77c)
1 /*
2  * Copyright © 2009 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 DEALINGS
21  * IN THE SOFTWARE.
22  *
23  * Authors:
24  *    Eric Anholt <[email protected]>
25  *
26  */
27 
28 /** @file gem_tiled_pread.c
29  *
30  * This is a test of pread's behavior on tiled objects with respect to the
31  * reported swizzling value.
32  *
33  * The goal is to exercise the slow_bit17_copy path for reading on bit17
34  * machines, but will also be useful for catching swizzling value bugs on
35  * other systems.
36  */
37 
38 #include "igt.h"
39 #include <stdlib.h>
40 #include <stdio.h>
41 #include <string.h>
42 #include <fcntl.h>
43 #include <inttypes.h>
44 #include <errno.h>
45 #include <sys/stat.h>
46 #include <sys/time.h>
47 #include <sys/ioctl.h>
48 #include "drm.h"
49 
50 
51 IGT_TEST_DESCRIPTION("Test pread behavior on tiled objects with respect to the"
52 		     " reported swizzling value.");
53 
54 #define WIDTH 512
55 #define HEIGHT 512
56 static uint32_t linear[WIDTH * HEIGHT];
57 
58 #define PAGE_SIZE 4096
59 
60 static int tile_width;
61 static int tile_height;
62 static int tile_size;
63 
64 static uint32_t
create_bo(int fd)65 create_bo(int fd)
66 {
67 	uint32_t handle;
68 	uint32_t *data;
69 	int i;
70 
71 	handle = gem_create(fd, sizeof(linear));
72 	gem_set_tiling(fd, handle, I915_TILING_X, WIDTH * sizeof(uint32_t));
73 
74 	/* Fill the BO with dwords starting at start_val */
75 	data = gem_mmap__gtt(fd, handle, sizeof(linear),
76 			     PROT_READ | PROT_WRITE);
77 	gem_set_domain(fd, handle, I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
78 	for (i = 0; i < WIDTH*HEIGHT; i++)
79 		data[i] = i;
80 	munmap(data, sizeof(linear));
81 
82 	return handle;
83 }
84 
85 static int
swizzle_bit(int bit,int offset)86 swizzle_bit(int bit, int offset)
87 {
88 	return (offset & (1 << bit)) >> (bit - 6);
89 }
90 
91 struct offset {
92 	int base_x, base_y;
93 	int tile_x, tile_y;
94 };
95 
96 /* Translate from a swizzled offset in the tiled buffer to the corresponding
97  * value from the original linear buffer.
98  */
99 static uint32_t
calculate_expected(int offset,struct offset * dbg)100 calculate_expected(int offset, struct offset *dbg)
101 {
102 	int tile_off = offset & (tile_size - 1);
103 	int tile_base = offset & -tile_size;
104 	int tile_index = tile_base / tile_size;
105 	int tiles_per_row = 4*WIDTH / tile_width;
106 
107 	/* base x,y values from the tile (page) index. */
108 	dbg->base_y = tile_index / tiles_per_row * tile_height;
109 	dbg->base_x = tile_index % tiles_per_row * (tile_width/4);
110 
111 	/* x, y offsets within the tile */
112 	dbg->tile_y = tile_off / tile_width;
113 	dbg->tile_x = (tile_off % tile_width) / 4;
114 
115 	return (dbg->base_y + dbg->tile_y) * WIDTH + dbg->base_x + dbg->tile_x;
116 }
117 
118 igt_simple_main
119 {
120 	int fd;
121 	int i, iter = 100;
122 	uint32_t tiling, swizzle;
123 	uint32_t handle;
124 	uint32_t devid;
125 
126 	fd = drm_open_driver(DRIVER_INTEL);
127 
128 	handle = create_bo(fd);
129 	igt_require(gem_get_tiling(fd, handle, &tiling, &swizzle));
130 
131 	devid = intel_get_drm_devid(fd);
132 
133 	if (IS_GEN2(devid)) {
134 		tile_height = 16;
135 		tile_width = 128;
136 		tile_size = 2048;
137 	} else {
138 		tile_height = 8;
139 		tile_width = 512;
140 		tile_size = PAGE_SIZE;
141 	}
142 
143 	/* Read a bunch of random subsets of the data and check that they come
144 	 * out right.
145 	 */
146 	for (i = 0; i < iter; i++) {
147 		int size = WIDTH * HEIGHT * 4;
148 		int offset = (random() % size) & ~3;
149 		int len = (random() % size) & ~3;
150 		int j;
151 
152 		if (len == 0)
153 			len = 4;
154 
155 		if (offset + len > size)
156 			len = size - offset;
157 
158 		if (i == 0) {
159 			offset = 0;
160 			len = size;
161 		}
162 
163 		gem_read(fd, handle, offset, linear, len);
164 
165 		/* Translate from offsets in the read buffer to the swizzled
166 		 * address that it corresponds to.  This is the opposite of
167 		 * what Mesa does (calculate offset to be read given the linear
168 		 * offset it's looking for).
169 		 */
170 		for (j = offset; j < offset + len; j += 4) {
171 			struct offset dbg;
172 			uint32_t expected, found;
173 			int swizzled_offset;
174 			const char *swizzle_str;
175 
176 			switch (swizzle) {
177 			case I915_BIT_6_SWIZZLE_NONE:
178 				swizzled_offset = j;
179 				swizzle_str = "none";
180 				break;
181 			case I915_BIT_6_SWIZZLE_9:
182 				swizzled_offset = j ^
183 					swizzle_bit(9, j);
184 				swizzle_str = "bit9";
185 				break;
186 			case I915_BIT_6_SWIZZLE_9_10:
187 				swizzled_offset = j ^
188 					swizzle_bit(9, j) ^
189 					swizzle_bit(10, j);
190 				swizzle_str = "bit9^10";
191 				break;
192 			case I915_BIT_6_SWIZZLE_9_11:
193 				swizzled_offset = j ^
194 					swizzle_bit(9, j) ^
195 					swizzle_bit(11, j);
196 				swizzle_str = "bit9^11";
197 				break;
198 			case I915_BIT_6_SWIZZLE_9_10_11:
199 				swizzled_offset = j ^
200 					swizzle_bit(9, j) ^
201 					swizzle_bit(10, j) ^
202 					swizzle_bit(11, j);
203 				swizzle_str = "bit9^10^11";
204 				break;
205 			default:
206 				igt_assert_f(0, "Bad swizzle bits; %d\n",
207 					     swizzle);
208 			}
209 			expected = calculate_expected(swizzled_offset, &dbg);
210 			found = linear[(j - offset) / 4];
211 			igt_assert_f(expected == found,
212 				     "Bad read [%d]: %d instead of %d at 0x%08x "
213 				     "[tile (%d, %d) subtile (%d, %d)] "
214 				     "for read from 0x%08x to 0x%08x, swizzle=%s\n",
215 				     i, found, expected, j,
216 				     dbg.base_x, dbg.base_y,
217 				     dbg.tile_x, dbg.tile_y,
218 				     offset, offset + len,
219 				     swizzle_str);
220 		}
221 	}
222 
223 	close(fd);
224 }
225