blob: d20eb0bd67dd738116ca7335fd009fe93d87f34a [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
30/** @file gem_prw_concurrent_blit.c
31 *
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
55set_bo(drm_intel_bo *bo, uint32_t val, int width, int height)
56{
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
68cmp_bo(drm_intel_bo *bo, uint32_t val, int width, int height)
69{
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 *
81create_bo(drm_intel_bufmgr *bufmgr, uint32_t val, int width, int height)
82{
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
91int
92main(int argc, char **argv)
93{
94 drm_intel_bufmgr *bufmgr;
95 struct intel_batchbuffer *batch;
96 int num_buffers = 128, max;
97 drm_intel_bo *src[128], *dst[128], *dummy = NULL;
98 int width = 512, height = 512;
Chris Wilson99431a42013-08-14 11:03:34 +010099 int fd, loop, i, nc;
100 pid_t children[16];
Daniel Vetter3dba47e2013-08-06 22:27:37 +0200101
Daniel Vetter1caaf0a2013-08-12 12:17:35 +0200102 igt_subtest_init(argc, argv);
103 igt_skip_on_simulation();
Daniel Vetter3dba47e2013-08-06 22:27:37 +0200104
105 fd = drm_open_any();
106
107 max = gem_aperture_size (fd) / (1024 * 1024) / 2;
108 if (num_buffers > max)
109 num_buffers = max;
110
111 bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
112 drm_intel_bufmgr_gem_enable_reuse(bufmgr);
113 batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd));
114
Daniel Vetter1caaf0a2013-08-12 12:17:35 +0200115 if (!igt_only_list_subtests()) {
Daniel Vetter3dba47e2013-08-06 22:27:37 +0200116 for (i = 0; i < num_buffers; i++) {
117 src[i] = create_bo(bufmgr, i, width, height);
118 dst[i] = create_bo(bufmgr, ~i, width, height);
119 }
120 dummy = create_bo(bufmgr, 0, width, height);
121 }
122
123 /* try to overwrite the source values */
Daniel Vetter1caaf0a2013-08-12 12:17:35 +0200124 igt_subtest("overwrite-source") {
Daniel Vetter3dba47e2013-08-06 22:27:37 +0200125 for (i = 0; i < num_buffers; i++) {
126 set_bo(src[i], i, width, height);
127 set_bo(dst[i], i, width, height);
128 }
129 for (i = 0; i < num_buffers; i++)
130 intel_copy_bo(batch, dst[i], src[i], width, height);
131 for (i = num_buffers; i--; )
132 set_bo(src[i], 0xdeadbeef, width, height);
133 for (i = 0; i < num_buffers; i++)
134 cmp_bo(dst[i], i, width, height);
135 }
136
137 /* try to read the results before the copy completes */
Daniel Vetter1caaf0a2013-08-12 12:17:35 +0200138 igt_subtest("early-read") {
Daniel Vetter3dba47e2013-08-06 22:27:37 +0200139 for (i = num_buffers; i--; )
140 set_bo(src[i], 0xdeadbeef, width, height);
141 for (i = 0; i < num_buffers; i++)
142 intel_copy_bo(batch, dst[i], src[i], width, height);
143 for (i = num_buffers; i--; )
144 cmp_bo(dst[i], 0xdeadbeef, width, height);
145 }
146
147 /* and finally try to trick the kernel into loosing the pending write */
Daniel Vetter1caaf0a2013-08-12 12:17:35 +0200148 igt_subtest("gpu-read-after-write") {
Daniel Vetter3dba47e2013-08-06 22:27:37 +0200149 for (i = num_buffers; i--; )
150 set_bo(src[i], 0xabcdabcd, width, height);
151 for (i = 0; i < num_buffers; i++)
152 intel_copy_bo(batch, dst[i], src[i], width, height);
153 for (i = num_buffers; i--; )
154 intel_copy_bo(batch, dummy, dst[i], width, height);
155 for (i = num_buffers; i--; )
156 cmp_bo(dst[i], 0xabcdabcd, width, height);
157 }
158
Daniel Vetter1caaf0a2013-08-12 12:17:35 +0200159 igt_fork_signal_helper();
Daniel Vetter3dba47e2013-08-06 22:27:37 +0200160
161 /* try to read the results before the copy completes */
Daniel Vetter1caaf0a2013-08-12 12:17:35 +0200162 igt_subtest("overwrite-source-interruptible") {
Daniel Vetter3dba47e2013-08-06 22:27:37 +0200163 for (loop = 0; loop < 10; loop++) {
164 gem_quiescent_gpu(fd);
165 for (i = 0; i < num_buffers; i++) {
166 set_bo(src[i], i, width, height);
167 set_bo(dst[i], i, width, height);
168 }
169 for (i = 0; i < num_buffers; i++)
170 intel_copy_bo(batch, dst[i], src[i], width, height);
171 for (i = num_buffers; i--; )
172 set_bo(src[i], 0xdeadbeef, width, height);
173 for (i = 0; i < num_buffers; i++)
174 cmp_bo(dst[i], i, width, height);
175 }
176 }
177
178 /* try to read the results before the copy completes */
Daniel Vetter1caaf0a2013-08-12 12:17:35 +0200179 igt_subtest("early-read-interruptible") {
Daniel Vetter3dba47e2013-08-06 22:27:37 +0200180 for (loop = 0; loop < 10; loop++) {
181 gem_quiescent_gpu(fd);
182 for (i = num_buffers; i--; )
183 set_bo(src[i], 0xdeadbeef, width, height);
184 for (i = 0; i < num_buffers; i++)
185 intel_copy_bo(batch, dst[i], src[i], width, height);
186 for (i = num_buffers; i--; )
187 cmp_bo(dst[i], 0xdeadbeef, width, height);
188 }
189 }
190
191 /* and finally try to trick the kernel into loosing the pending write */
Daniel Vetter1caaf0a2013-08-12 12:17:35 +0200192 igt_subtest("gpu-read-after-write-interruptible") {
Daniel Vetter3dba47e2013-08-06 22:27:37 +0200193 for (loop = 0; loop < 10; loop++) {
194 gem_quiescent_gpu(fd);
195 for (i = num_buffers; i--; )
196 set_bo(src[i], 0xabcdabcd, width, height);
197 for (i = 0; i < num_buffers; i++)
198 intel_copy_bo(batch, dst[i], src[i], width, height);
199 for (i = num_buffers; i--; )
200 intel_copy_bo(batch, dummy, dst[i], width, height);
201 for (i = num_buffers; i--; )
202 cmp_bo(dst[i], 0xabcdabcd, width, height);
203 }
204 }
205
Chris Wilson99431a42013-08-14 11:03:34 +0100206 /* try to read the results before the copy completes */
207 igt_subtest("overwrite-source-forked") {
208 for (nc = 0; nc < ARRAY_SIZE(children); nc++) {
209 switch ((children[nc] = fork())) {
210 case -1: igt_assert(0);
211 default: break;
212 case 0:
213 /* recreate process local variables */
214 bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
215 drm_intel_bufmgr_gem_enable_reuse(bufmgr);
216 batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd));
217 for (i = 0; i < num_buffers; i++) {
218 src[i] = create_bo(bufmgr, i, width, height);
219 dst[i] = create_bo(bufmgr, ~i, width, height);
220 }
221 for (loop = 0; loop < 10; loop++) {
222 gem_quiescent_gpu(fd);
223 for (i = 0; i < num_buffers; i++) {
224 set_bo(src[i], i, width, height);
225 set_bo(dst[i], i, width, height);
226 }
227 for (i = 0; i < num_buffers; i++)
228 intel_copy_bo(batch, dst[i], src[i], width, height);
229 for (i = num_buffers; i--; )
230 set_bo(src[i], 0xdeadbeef, width, height);
231 for (i = 0; i < num_buffers; i++)
232 cmp_bo(dst[i], i, width, height);
233 }
234 exit(0);
235 }
236 }
237 for (nc = 0; nc < ARRAY_SIZE(children); nc++) {
238 int status = -1;
239 while (waitpid(children[nc], &status, 0) == -1 &&
240 errno == -EINTR)
241 ;
242 igt_assert(status == 0);
243 }
244 }
245
246 /* try to read the results before the copy completes */
247 igt_subtest("early-read-forked") {
248 for (nc = 0; nc < ARRAY_SIZE(children); nc++) {
249 switch ((children[nc] = fork())) {
250 case -1: igt_assert(0);
251 default: break;
252 case 0:
253 /* recreate process local variables */
254 bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
255 drm_intel_bufmgr_gem_enable_reuse(bufmgr);
256 batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd));
257 for (i = 0; i < num_buffers; i++) {
258 src[i] = create_bo(bufmgr, i, width, height);
259 dst[i] = create_bo(bufmgr, ~i, width, height);
260 }
261 for (loop = 0; loop < 10; loop++) {
262 gem_quiescent_gpu(fd);
263 for (i = num_buffers; i--; )
264 set_bo(src[i], 0xdeadbeef, width, height);
265 for (i = 0; i < num_buffers; i++)
266 intel_copy_bo(batch, dst[i], src[i], width, height);
267 for (i = num_buffers; i--; )
268 cmp_bo(dst[i], 0xdeadbeef, width, height);
269 }
270 exit(0);
271 }
272 }
273 for (nc = 0; nc < ARRAY_SIZE(children); nc++) {
274 int status = -1;
275 while (waitpid(children[nc], &status, 0) == -1 &&
276 errno == -EINTR)
277 ;
278 igt_assert(status == 0);
279 }
280 }
281
282 /* and finally try to trick the kernel into loosing the pending write */
283 igt_subtest("gpu-read-after-write-forked") {
284 for (nc = 0; nc < ARRAY_SIZE(children); nc++) {
285 switch ((children[nc] = fork())) {
286 case -1: igt_assert(0);
287 default: break;
288 case 0:
289 /* recreate process local variables */
290 bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
291 drm_intel_bufmgr_gem_enable_reuse(bufmgr);
292 batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd));
293 for (i = 0; i < num_buffers; i++) {
294 src[i] = create_bo(bufmgr, i, width, height);
295 dst[i] = create_bo(bufmgr, ~i, width, height);
296 }
297 dummy = create_bo(bufmgr, 0, width, height);
298 for (loop = 0; loop < 10; loop++) {
299 gem_quiescent_gpu(fd);
300 for (i = num_buffers; i--; )
301 set_bo(src[i], 0xabcdabcd, width, height);
302 for (i = 0; i < num_buffers; i++)
303 intel_copy_bo(batch, dst[i], src[i], width, height);
304 for (i = num_buffers; i--; )
305 intel_copy_bo(batch, dummy, dst[i], width, height);
306 for (i = num_buffers; i--; )
307 cmp_bo(dst[i], 0xabcdabcd, width, height);
308 }
309 exit(0);
310 }
311 }
312 for (nc = 0; nc < ARRAY_SIZE(children); nc++) {
313 int status = -1;
314 while (waitpid(children[nc], &status, 0) == -1 &&
315 errno == -EINTR)
316 ;
317 igt_assert(status == 0);
318 }
319 }
320
Daniel Vetter1caaf0a2013-08-12 12:17:35 +0200321 igt_stop_signal_helper();
Daniel Vetter3dba47e2013-08-06 22:27:37 +0200322
323 return 0;
324}