lib: extract igt_aux.[hc]
[platform/upstream/intel-gpu-tools.git] / tests / gem_tiled_partial_pwrite_pread.c
1 /*
2  * Copyright © 2011 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  *    Daniel Vetter <daniel.vetter@ffwll.ch>
25  *
26  */
27
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <fcntl.h>
32 #include <inttypes.h>
33 #include <errno.h>
34 #include <sys/stat.h>
35 #include <sys/time.h>
36
37 #include <drm.h>
38
39 #include "ioctl_wrappers.h"
40 #include "drmtest.h"
41 #include "intel_chipset.h"
42 #include "intel_io.h"
43 #include "igt_aux.h"
44
45 /*
46  * Testcase: pwrite/pread consistency when touching partial cachelines
47  *
48  * Some fancy new pwrite/pread optimizations clflush in-line while
49  * reading/writing. Check whether all required clflushes happen.
50  *
51  * Unfortunately really old mesa used unaligned pread/pwrite for s/w fallback
52  * rendering, so we need to check whether this works on tiled buffers, too.
53  *
54  */
55
56 static drm_intel_bufmgr *bufmgr;
57 struct intel_batchbuffer *batch;
58
59 drm_intel_bo *scratch_bo;
60 drm_intel_bo *staging_bo;
61 drm_intel_bo *tiled_staging_bo;
62 unsigned long scratch_pitch;
63 #define BO_SIZE (32*4096)
64 uint32_t devid;
65 uint64_t mappable_gtt_limit;
66 int fd;
67
68 static void
69 copy_bo(drm_intel_bo *src, int src_tiled,
70         drm_intel_bo *dst, int dst_tiled)
71 {
72         unsigned long dst_pitch = scratch_pitch;
73         unsigned long src_pitch = scratch_pitch;
74         uint32_t cmd_bits = 0;
75
76         /* dst is tiled ... */
77         if (intel_gen(devid) >= 4 && dst_tiled) {
78                 dst_pitch /= 4;
79                 cmd_bits |= XY_SRC_COPY_BLT_DST_TILED;
80         }
81
82         if (intel_gen(devid) >= 4 && dst_tiled) {
83                 src_pitch /= 4;
84                 cmd_bits |= XY_SRC_COPY_BLT_SRC_TILED;
85         }
86
87         BLIT_COPY_BATCH_START(devid, cmd_bits);
88         OUT_BATCH((3 << 24) | /* 32 bits */
89                   (0xcc << 16) | /* copy ROP */
90                   dst_pitch);
91         OUT_BATCH(0 << 16 | 0);
92         OUT_BATCH(BO_SIZE/scratch_pitch << 16 | 1024);
93         OUT_RELOC_FENCED(dst, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
94         BLIT_RELOC_UDW(devid);
95         OUT_BATCH(0 << 16 | 0);
96         OUT_BATCH(src_pitch);
97         OUT_RELOC_FENCED(src, I915_GEM_DOMAIN_RENDER, 0, 0);
98         BLIT_RELOC_UDW(devid);
99         ADVANCE_BATCH();
100
101         intel_batchbuffer_flush(batch);
102 }
103
104 static void
105 blt_bo_fill(drm_intel_bo *tmp_bo, drm_intel_bo *bo, int val)
106 {
107         uint8_t *gtt_ptr;
108         int i;
109
110         drm_intel_gem_bo_map_gtt(tmp_bo);
111         gtt_ptr = tmp_bo->virtual;
112
113         for (i = 0; i < BO_SIZE; i++)
114                 gtt_ptr[i] = val;
115
116         drm_intel_gem_bo_unmap_gtt(tmp_bo);
117
118         if (bo->offset < mappable_gtt_limit &&
119             (IS_G33(devid) || intel_gen(devid) >= 4))
120                 igt_trash_aperture();
121
122         copy_bo(tmp_bo, 0, bo, 1);
123 }
124
125 #define MAX_BLT_SIZE 128
126 #define ROUNDS 200
127 uint8_t tmp[BO_SIZE];
128 uint8_t compare_tmp[BO_SIZE];
129
130 static void test_partial_reads(void)
131 {
132         int i, j;
133
134         printf("checking partial reads\n");
135         for (i = 0; i < ROUNDS; i++) {
136                 int start, len;
137                 int val = i % 256;
138
139                 blt_bo_fill(staging_bo, scratch_bo, i);
140
141                 start = random() % BO_SIZE;
142                 len = random() % (BO_SIZE-start) + 1;
143
144                 drm_intel_bo_get_subdata(scratch_bo, start, len, tmp);
145                 for (j = 0; j < len; j++) {
146                         igt_assert_f(tmp[j] == val,
147                                      "mismatch at %i, got: %i, expected: %i\n",
148                                      start + j, tmp[j], val);
149                 }
150
151                 igt_progress("partial reads test: ", i, ROUNDS);
152         }
153 }
154
155 static void test_partial_writes(void)
156 {
157         int i, j;
158
159         printf("checking partial writes\n");
160         for (i = 0; i < ROUNDS; i++) {
161                 int start, len;
162                 int val = i % 256;
163
164                 blt_bo_fill(staging_bo, scratch_bo, i);
165
166                 start = random() % BO_SIZE;
167                 len = random() % (BO_SIZE-start) + 1;
168
169                 memset(tmp, i + 63, BO_SIZE);
170
171                 drm_intel_bo_subdata(scratch_bo, start, len, tmp);
172
173                 copy_bo(scratch_bo, 1, tiled_staging_bo, 1);
174                 drm_intel_bo_get_subdata(tiled_staging_bo, 0, BO_SIZE,
175                                          compare_tmp);
176
177                 for (j = 0; j < start; j++) {
178                         igt_assert_f(compare_tmp[j] == val,
179                                      "mismatch at %i, got: %i, expected: %i\n",
180                                      j, tmp[j], val);
181                 }
182                 for (; j < start + len; j++) {
183                         igt_assert_f(compare_tmp[j] == tmp[0],
184                                      "mismatch at %i, got: %i, expected: %i\n",
185                                      j, tmp[j], i);
186                 }
187                 for (; j < BO_SIZE; j++) {
188                         igt_assert_f(compare_tmp[j] == val,
189                                      "mismatch at %i, got: %i, expected: %i\n",
190                                      j, tmp[j], val);
191                 }
192                 drm_intel_gem_bo_unmap_gtt(staging_bo);
193
194                 igt_progress("partial writes test: ", i, ROUNDS);
195         }
196 }
197
198 static void test_partial_read_writes(void)
199 {
200         int i, j;
201
202         printf("checking partial writes after partial reads\n");
203         for (i = 0; i < ROUNDS; i++) {
204                 int start, len;
205                 int val = i % 256;
206
207                 blt_bo_fill(staging_bo, scratch_bo, i);
208
209                 /* partial read */
210                 start = random() % BO_SIZE;
211                 len = random() % (BO_SIZE-start) + 1;
212
213                 drm_intel_bo_get_subdata(scratch_bo, start, len, tmp);
214                 for (j = 0; j < len; j++) {
215                         igt_assert_f(tmp[j] == val,
216                                      "mismatch in read at %i, got: %i, expected: %i\n",
217                                      start + j, tmp[j], val);
218                 }
219
220                 /* Change contents through gtt to make the pread cachelines
221                  * stale. */
222                 val = (i + 17) % 256;
223                 blt_bo_fill(staging_bo, scratch_bo, val);
224
225                 /* partial write */
226                 start = random() % BO_SIZE;
227                 len = random() % (BO_SIZE-start) + 1;
228
229                 memset(tmp, i + 63, BO_SIZE);
230
231                 drm_intel_bo_subdata(scratch_bo, start, len, tmp);
232
233                 copy_bo(scratch_bo, 1, tiled_staging_bo, 1);
234                 drm_intel_bo_get_subdata(tiled_staging_bo, 0, BO_SIZE,
235                                          compare_tmp);
236
237                 for (j = 0; j < start; j++) {
238                         igt_assert_f(compare_tmp[j] == val,
239                                      "mismatch at %i, got: %i, expected: %i\n",
240                                      j, tmp[j], val);
241                 }
242                 for (; j < start + len; j++) {
243                         igt_assert_f(compare_tmp[j] == tmp[0],
244                                      "mismatch at %i, got: %i, expected: %i\n",
245                                      j, tmp[j], tmp[0]);
246                 }
247                 for (; j < BO_SIZE; j++) {
248                         igt_assert_f(compare_tmp[j] == val,
249                                      "mismatch at %i, got: %i, expected: %i\n",
250                                      j, tmp[j], val);
251                 }
252                 drm_intel_gem_bo_unmap_gtt(staging_bo);
253
254                 igt_progress("partial read/writes test: ", i, ROUNDS);
255         }
256 }
257
258 igt_main
259 {
260         uint32_t tiling_mode = I915_TILING_X;
261
262         igt_skip_on_simulation();
263
264         srandom(0xdeadbeef);
265
266         igt_fixture {
267                 fd = drm_open_any();
268
269                 bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
270                 //drm_intel_bufmgr_gem_enable_reuse(bufmgr);
271                 devid = intel_get_drm_devid(fd);
272                 batch = intel_batchbuffer_alloc(bufmgr, devid);
273
274                 /* overallocate the buffers we're actually using because */
275                 scratch_bo = drm_intel_bo_alloc_tiled(bufmgr, "scratch bo", 1024,
276                                                       BO_SIZE/4096, 4,
277                                                       &tiling_mode, &scratch_pitch, 0);
278                 igt_assert(tiling_mode == I915_TILING_X);
279                 igt_assert(scratch_pitch == 4096);
280                 staging_bo = drm_intel_bo_alloc(bufmgr, "staging bo", BO_SIZE, 4096);
281                 tiled_staging_bo = drm_intel_bo_alloc_tiled(bufmgr, "scratch bo", 1024,
282                                                             BO_SIZE/4096, 4,
283                                                             &tiling_mode,
284                                                             &scratch_pitch, 0);
285
286                 igt_init_aperture_trashers(bufmgr);
287                 mappable_gtt_limit = gem_mappable_aperture_size();
288         }
289
290         igt_subtest("reads")
291                 test_partial_reads();
292
293         igt_subtest("writes")
294                 test_partial_writes();
295
296         igt_subtest("writes-after-reads")
297                 test_partial_read_writes();
298
299         igt_fixture {
300                 igt_cleanup_aperture_trashers();
301                 drm_intel_bufmgr_destroy(bufmgr);
302
303                 close(fd);
304         }
305 }