blob: b6d316d12f7743f96a47a3514603ab20df107730 [file] [log] [blame]
Daniel Vetter3dba47e2013-08-06 22:27:37 +02001/*
2 * Copyright © 2009,2012,2013 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 <eric@anholt.net>
25 * Chris Wilson <chris@chris-wilson.co.uk>
26 * Daniel Vetter <daniel.vetter@ffwll.ch>
27 *
28 */
29
Daniel Vetter43779e32013-08-14 14:50:50 +020030/** @file gem_concurrent_blit.c
Daniel Vetter3dba47e2013-08-06 22:27:37 +020031 *
32 * This is a test of pread/pwrite behavior when writing to active
33 * buffers.
34 *
35 * Based on gem_gtt_concurrent_blt.
36 */
37
38#include <stdlib.h>
39#include <stdio.h>
40#include <string.h>
Daniel Vetter3dba47e2013-08-06 22:27:37 +020041#include <fcntl.h>
42#include <inttypes.h>
43#include <errno.h>
44#include <sys/stat.h>
45#include <sys/time.h>
Chris Wilson99431a42013-08-14 11:03:34 +010046#include <sys/wait.h>
Daniel Vetter3dba47e2013-08-06 22:27:37 +020047#include "drm.h"
48#include "i915_drm.h"
49#include "drmtest.h"
50#include "intel_bufmgr.h"
51#include "intel_batchbuffer.h"
52#include "intel_gpu_tools.h"
53
54static void
Daniel Vetter43779e32013-08-14 14:50:50 +020055prw_set_bo(drm_intel_bo *bo, uint32_t val, int width, int height)
Daniel Vetter3dba47e2013-08-06 22:27:37 +020056{
57 int size = width * height;
58 uint32_t *vaddr, *tmp;
59
60 vaddr = tmp = malloc(size*4);
61 while (size--)
62 *vaddr++ = val;
63 drm_intel_bo_subdata(bo, 0, width*height*4, tmp);
64 free(tmp);
65}
66
67static void
Daniel Vetter43779e32013-08-14 14:50:50 +020068prw_cmp_bo(drm_intel_bo *bo, uint32_t val, int width, int height)
Daniel Vetter3dba47e2013-08-06 22:27:37 +020069{
70 int size = width * height;
71 uint32_t *vaddr, *tmp;
72
73 vaddr = tmp = malloc(size*4);
74 drm_intel_bo_get_subdata(bo, 0, size*4, tmp);
75 while (size--)
Daniel Vetter83440952013-08-13 12:35:58 +020076 igt_assert(*vaddr++ == val);
Daniel Vetter3dba47e2013-08-06 22:27:37 +020077 free(tmp);
78}
79
80static drm_intel_bo *
Daniel Vetter43779e32013-08-14 14:50:50 +020081unmapped_create_bo(drm_intel_bufmgr *bufmgr, uint32_t val, int width, int height)
Daniel Vetter3dba47e2013-08-06 22:27:37 +020082{
83 drm_intel_bo *bo;
84
85 bo = drm_intel_bo_alloc(bufmgr, "bo", 4*width*height, 0);
Daniel Vetter83440952013-08-13 12:35:58 +020086 igt_assert(bo);
Daniel Vetter3dba47e2013-08-06 22:27:37 +020087
88 return bo;
89}
90
Daniel Vetter43779e32013-08-14 14:50:50 +020091static void
92gtt_set_bo(drm_intel_bo *bo, uint32_t val, int width, int height)
Daniel Vetter3dba47e2013-08-06 22:27:37 +020093{
Daniel Vetter43779e32013-08-14 14:50:50 +020094 int size = width * height;
95 uint32_t *vaddr;
96
97 drm_intel_gem_bo_start_gtt_access(bo, true);
98 vaddr = bo->virtual;
99 while (size--)
100 *vaddr++ = val;
101}
102
103static void
104gtt_cmp_bo(drm_intel_bo *bo, uint32_t val, int width, int height)
105{
106 int size = width * height;
107 uint32_t *vaddr;
108
109 drm_intel_gem_bo_start_gtt_access(bo, false);
110 vaddr = bo->virtual;
111 while (size--)
112 igt_assert(*vaddr++ == val);
113}
114
115static drm_intel_bo *
116gtt_create_bo(drm_intel_bufmgr *bufmgr, uint32_t val, int width, int height)
117{
118 drm_intel_bo *bo;
119
120 bo = drm_intel_bo_alloc(bufmgr, "bo", 4*width*height, 0);
121 igt_assert(bo);
122
123 /* gtt map doesn't have a write parameter, so just keep the mapping
124 * around (to avoid the set_domain with the gtt write domain set) and
125 * manually tell the kernel when we start access the gtt. */
126 do_or_die(drm_intel_gem_bo_map_gtt(bo));
127
128 return bo;
129}
130
131static void
132cpu_set_bo(drm_intel_bo *bo, uint32_t val, int width, int height)
133{
134 int size = width * height;
135 uint32_t *vaddr;
136
137 do_or_die(drm_intel_bo_map(bo, true));
138 vaddr = bo->virtual;
139 while (size--)
140 *vaddr++ = val;
141 drm_intel_bo_unmap(bo);
142}
143
144static void
145cpu_cmp_bo(drm_intel_bo *bo, uint32_t val, int width, int height)
146{
147 int size = width * height;
148 uint32_t *vaddr;
149
150 do_or_die(drm_intel_bo_map(bo, false));
151 vaddr = bo->virtual;
152 while (size--)
153 igt_assert(*vaddr++ == val);
154 drm_intel_bo_unmap(bo);
155}
156
157struct access_mode {
158 void (*set_bo)(drm_intel_bo *bo, uint32_t val, int w, int h);
159 void (*cmp_bo)(drm_intel_bo *bo, uint32_t val, int w, int h);
160 drm_intel_bo *(*create_bo)(drm_intel_bufmgr *bufmgr,
161 uint32_t val, int width, int height);
162 const char *name;
163};
164
165struct access_mode access_modes[] = {
166 { .set_bo = prw_set_bo, .cmp_bo = prw_cmp_bo,
167 .create_bo = unmapped_create_bo, .name = "prw" },
168 { .set_bo = cpu_set_bo, .cmp_bo = cpu_cmp_bo,
169 .create_bo = unmapped_create_bo, .name = "cpu" },
170 { .set_bo = gtt_set_bo, .cmp_bo = gtt_cmp_bo,
171 .create_bo = gtt_create_bo, .name = "gtt" },
172};
173
Chris Wilson1ca607b2013-08-16 09:44:13 +0100174#define MAX_NUM_BUFFERS 1024
175int num_buffers = MAX_NUM_BUFFERS, fd;
Daniel Vetter43779e32013-08-14 14:50:50 +0200176drm_intel_bufmgr *bufmgr;
177struct intel_batchbuffer *batch;
Daniel Vetter5a598c92013-08-14 15:08:05 +0200178int width = 512, height = 512;
179
180static void do_overwrite_source(struct access_mode *mode,
181 drm_intel_bo **src, drm_intel_bo **dst,
182 drm_intel_bo *dummy)
183{
184 int i;
185
186 gem_quiescent_gpu(fd);
187 for (i = 0; i < num_buffers; i++) {
188 mode->set_bo(src[i], i, width, height);
189 mode->set_bo(dst[i], i, width, height);
190 }
191 for (i = 0; i < num_buffers; i++)
192 intel_copy_bo(batch, dst[i], src[i], width, height);
193 for (i = num_buffers; i--; )
194 mode->set_bo(src[i], 0xdeadbeef, width, height);
195 for (i = 0; i < num_buffers; i++)
196 mode->cmp_bo(dst[i], i, width, height);
197}
198
199static void do_early_read(struct access_mode *mode,
200 drm_intel_bo **src, drm_intel_bo **dst,
201 drm_intel_bo *dummy)
202{
203 int i;
204
205 gem_quiescent_gpu(fd);
206 for (i = num_buffers; i--; )
207 mode->set_bo(src[i], 0xdeadbeef, width, height);
208 for (i = 0; i < num_buffers; i++)
209 intel_copy_bo(batch, dst[i], src[i], width, height);
210 for (i = num_buffers; i--; )
211 mode->cmp_bo(dst[i], 0xdeadbeef, width, height);
212}
213
214static void do_gpu_read_after_write(struct access_mode *mode,
215 drm_intel_bo **src, drm_intel_bo **dst,
216 drm_intel_bo *dummy)
217{
218 int i;
219
220 gem_quiescent_gpu(fd);
221 for (i = num_buffers; i--; )
222 mode->set_bo(src[i], 0xabcdabcd, width, height);
223 for (i = 0; i < num_buffers; i++)
224 intel_copy_bo(batch, dst[i], src[i], width, height);
225 for (i = num_buffers; i--; )
226 intel_copy_bo(batch, dummy, dst[i], width, height);
227 for (i = num_buffers; i--; )
228 mode->cmp_bo(dst[i], 0xabcdabcd, width, height);
229}
230
Daniel Vetterec283d62013-08-14 15:18:37 +0200231typedef void (*do_test)(struct access_mode *mode,
232 drm_intel_bo **src, drm_intel_bo **dst,
233 drm_intel_bo *dummy);
234
235typedef void (*run_wrap)(struct access_mode *mode,
236 drm_intel_bo **src, drm_intel_bo **dst,
237 drm_intel_bo *dummy,
238 do_test do_test_func);
239
240static void run_single(struct access_mode *mode,
241 drm_intel_bo **src, drm_intel_bo **dst,
242 drm_intel_bo *dummy,
243 do_test do_test_func)
244{
245 do_test_func(mode, src, dst, dummy);
246}
247
248
Chris Wilson1ca607b2013-08-16 09:44:13 +0100249static void run_interruptible(struct access_mode *mode,
250 drm_intel_bo **src, drm_intel_bo **dst,
251 drm_intel_bo *dummy,
252 do_test do_test_func)
Daniel Vetterec283d62013-08-14 15:18:37 +0200253{
254 int loop;
255
Chris Wilson1ca607b2013-08-16 09:44:13 +0100256 igt_fork_signal_helper();
257
Daniel Vetterec283d62013-08-14 15:18:37 +0200258 for (loop = 0; loop < 10; loop++)
259 do_test_func(mode, src, dst, dummy);
Chris Wilson1ca607b2013-08-16 09:44:13 +0100260
261 igt_stop_signal_helper();
Daniel Vetterec283d62013-08-14 15:18:37 +0200262}
263
264static void run_forked(struct access_mode *mode,
265 drm_intel_bo **src, drm_intel_bo **dst,
266 drm_intel_bo *dummy,
267 do_test do_test_func)
268{
Chris Wilson1ca607b2013-08-16 09:44:13 +0100269 const int old_num_buffers = num_buffers;
Daniel Vetterec283d62013-08-14 15:18:37 +0200270
Daniel Vettercd1f2202013-08-29 10:06:51 +0200271 num_buffers /= 16;
Chris Wilson1ca607b2013-08-16 09:44:13 +0100272 num_buffers += 2;
273
274 igt_fork_signal_helper();
275
Daniel Vettercd1f2202013-08-29 10:06:51 +0200276 igt_fork(child, 16) {
277 igt_fail(6);
278
279 /* recreate process local variables */
280 bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
281 drm_intel_bufmgr_gem_enable_reuse(bufmgr);
282 batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd));
283 for (int i = 0; i < num_buffers; i++) {
284 src[i] = mode->create_bo(bufmgr, i, width, height);
285 dst[i] = mode->create_bo(bufmgr, ~i, width, height);
Daniel Vetterec283d62013-08-14 15:18:37 +0200286 }
Daniel Vettercd1f2202013-08-29 10:06:51 +0200287 dummy = mode->create_bo(bufmgr, 0, width, height);
288 for (int loop = 0; loop < 10; loop++)
289 do_test_func(mode, src, dst, dummy);
290 /* as we borrow the fd, we need to reap our bo */
291 for (int i = 0; i < num_buffers; i++) {
292 drm_intel_bo_unreference(src[i]);
293 drm_intel_bo_unreference(dst[i]);
294 }
295 drm_intel_bo_unreference(dummy);
296 intel_batchbuffer_free(batch);
297 drm_intel_bufmgr_destroy(bufmgr);
Daniel Vetterec283d62013-08-14 15:18:37 +0200298 }
Daniel Vettercd1f2202013-08-29 10:06:51 +0200299
300 igt_waitchildren();
Chris Wilson1ca607b2013-08-16 09:44:13 +0100301
302 igt_stop_signal_helper();
303
304 num_buffers = old_num_buffers;
Daniel Vetterec283d62013-08-14 15:18:37 +0200305}
Daniel Vetter5a598c92013-08-14 15:08:05 +0200306
307static void
308run_basic_modes(struct access_mode *mode,
309 drm_intel_bo **src, drm_intel_bo **dst,
Daniel Vetterec283d62013-08-14 15:18:37 +0200310 drm_intel_bo *dummy, const char *suffix,
311 run_wrap run_wrap_func)
Daniel Vetter5a598c92013-08-14 15:08:05 +0200312{
Daniel Vetter5a598c92013-08-14 15:08:05 +0200313 /* try to overwrite the source values */
Daniel Vetterec283d62013-08-14 15:18:37 +0200314 igt_subtest_f("%s-overwrite-source%s", mode->name, suffix)
315 run_wrap_func(mode, src, dst, dummy, do_overwrite_source);
Daniel Vetter5a598c92013-08-14 15:08:05 +0200316
317 /* try to read the results before the copy completes */
Daniel Vetterec283d62013-08-14 15:18:37 +0200318 igt_subtest_f("%s-early-read%s", mode->name, suffix)
319 run_wrap_func(mode, src, dst, dummy, do_early_read);
Daniel Vetter5a598c92013-08-14 15:08:05 +0200320
321 /* and finally try to trick the kernel into loosing the pending write */
Daniel Vetterec283d62013-08-14 15:18:37 +0200322 igt_subtest_f("%s-gpu-read-after-write%s", mode->name, suffix)
323 run_wrap_func(mode, src, dst, dummy, do_gpu_read_after_write);
Daniel Vetter5a598c92013-08-14 15:08:05 +0200324}
Daniel Vetter43779e32013-08-14 14:50:50 +0200325
326static void
327run_modes(struct access_mode *mode)
328{
Daniel Vetterad0f0812013-08-26 20:41:00 +0200329 drm_intel_bo *src[MAX_NUM_BUFFERS], *dst[MAX_NUM_BUFFERS], *dummy = NULL;
330
Daniel Vetter2dbd9982013-08-14 15:48:54 +0200331 igt_fixture {
Chris Wilson0d320fd2013-08-16 12:07:56 +0100332 bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
333 drm_intel_bufmgr_gem_enable_reuse(bufmgr);
334 batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd));
335
Chris Wilson1ca607b2013-08-16 09:44:13 +0100336 for (int i = 0; i < num_buffers; i++) {
Daniel Vetter43779e32013-08-14 14:50:50 +0200337 src[i] = mode->create_bo(bufmgr, i, width, height);
338 dst[i] = mode->create_bo(bufmgr, ~i, width, height);
Daniel Vetter3dba47e2013-08-06 22:27:37 +0200339 }
Daniel Vetter43779e32013-08-14 14:50:50 +0200340 dummy = mode->create_bo(bufmgr, 0, width, height);
Daniel Vetter3dba47e2013-08-06 22:27:37 +0200341 }
342
Daniel Vetterec283d62013-08-14 15:18:37 +0200343 run_basic_modes(mode, src, dst, dummy, "", run_single);
Chris Wilson1ca607b2013-08-16 09:44:13 +0100344 run_basic_modes(mode, src, dst, dummy, "-interruptible", run_interruptible);
Daniel Vetter3dba47e2013-08-06 22:27:37 +0200345
Daniel Vetter2dbd9982013-08-14 15:48:54 +0200346 igt_fixture {
Chris Wilson1ca607b2013-08-16 09:44:13 +0100347 for (int i = 0; i < num_buffers; i++) {
Daniel Vetter43779e32013-08-14 14:50:50 +0200348 drm_intel_bo_unreference(src[i]);
349 drm_intel_bo_unreference(dst[i]);
350 }
351 drm_intel_bo_unreference(dummy);
Chris Wilson0d320fd2013-08-16 12:07:56 +0100352 intel_batchbuffer_free(batch);
353 drm_intel_bufmgr_destroy(bufmgr);
Daniel Vetter43779e32013-08-14 14:50:50 +0200354 }
Chris Wilson1ca607b2013-08-16 09:44:13 +0100355
356 run_basic_modes(mode, src, dst, dummy, "-forked", run_forked);
Daniel Vetter43779e32013-08-14 14:50:50 +0200357}
358
359int
360main(int argc, char **argv)
361{
362 int max, i;
363
364 igt_subtest_init(argc, argv);
365 igt_skip_on_simulation();
366
Daniel Vetter2dbd9982013-08-14 15:48:54 +0200367 igt_fixture {
368 fd = drm_open_any();
Daniel Vetter43779e32013-08-14 14:50:50 +0200369
Daniel Vetter2dbd9982013-08-14 15:48:54 +0200370 max = gem_aperture_size (fd) / (1024 * 1024) / 2;
371 if (num_buffers > max)
372 num_buffers = max;
Daniel Vetter2dbd9982013-08-14 15:48:54 +0200373 }
Daniel Vetter43779e32013-08-14 14:50:50 +0200374
375 for (i = 0; i < ARRAY_SIZE(access_modes); i++)
376 run_modes(&access_modes[i]);
377
Daniel Vettera1ca8ef2013-08-14 16:02:24 +0200378 igt_exit();
Daniel Vetter3dba47e2013-08-06 22:27:37 +0200379}