tests: roll out igt_fixture
[platform/upstream/intel-gpu-tools.git] / tests / gem_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  *    Chris Wilson <chris@chris-wilson.co.uk>
25  *
26  */
27
28 #include <unistd.h>
29 #include <stdlib.h>
30 #include <stdint.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <fcntl.h>
34 #include <inttypes.h>
35 #include <errno.h>
36 #include <sys/stat.h>
37 #include <sys/ioctl.h>
38 #include <sys/mman.h>
39 #include <sys/time.h>
40 #include "drm.h"
41 #include "i915_drm.h"
42 #include "drmtest.h"
43 #include "intel_bufmgr.h"
44 #include "intel_batchbuffer.h"
45 #include "intel_gpu_tools.h"
46
47 #define OBJECT_SIZE 16384
48
49 #define COPY_BLT_CMD            (2<<29|0x53<<22|0x6)
50 #define BLT_WRITE_ALPHA         (1<<21)
51 #define BLT_WRITE_RGB           (1<<20)
52 #define BLT_SRC_TILED           (1<<15)
53 #define BLT_DST_TILED           (1<<11)
54
55 static void copy(int fd, uint32_t src, uint32_t dst, void *buf, int len, int loops)
56 {
57         struct drm_i915_gem_relocation_entry reloc[] = {
58                 { dst, 0, 4*sizeof(uint32_t), 0, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER },
59                 { src, 0, 7*sizeof(uint32_t), 0, I915_GEM_DOMAIN_RENDER, 0 },
60         };
61         struct drm_i915_gem_exec_object2 exec[] = {
62                 { src },
63                 { dst },
64                 { gem_create(fd, 4096), 2, (uintptr_t)reloc }
65         };
66         uint32_t batch[] = {
67                 COPY_BLT_CMD | BLT_WRITE_ALPHA | BLT_WRITE_RGB,
68                 0xcc << 16 | 1 << 25 | 1 << 24 | len,
69                 0,
70                 1 << 16 | (len / 4),
71                 0, /* dst */
72                 0,
73                 len,
74                 0, /* src */
75                 MI_BATCH_BUFFER_END,
76                 0
77         };
78         struct drm_i915_gem_execbuffer2 execbuf = {
79                 (uintptr_t)exec, 3,
80                 0, sizeof(batch),
81                 0, 0, 0, 0,
82                 HAS_BLT_RING(intel_get_drm_devid(fd)) ? I915_EXEC_BLT : 0,
83         };
84         gem_write(fd, exec[2].handle, 0, batch, sizeof(batch));
85
86         while (loops--) {
87                 gem_write(fd, src, 0, buf, len);
88                 do_or_die(drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf));
89                 gem_read(fd, dst, 0, buf, len);
90         }
91
92         gem_close(fd, exec[2].handle);
93 }
94
95 static void as_gtt_mmap(int fd, uint32_t src, uint32_t dst, void *buf, int len, int loops)
96 {
97         struct drm_i915_gem_relocation_entry reloc[] = {
98                 { dst, 0, 4*sizeof(uint32_t), 0, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER },
99                 { src, 0, 7*sizeof(uint32_t), 0, I915_GEM_DOMAIN_RENDER, 0 },
100         };
101         struct drm_i915_gem_exec_object2 exec[] = {
102                 { src },
103                 { dst },
104                 { gem_create(fd, 4096), 2, (uintptr_t)reloc }
105         };
106         uint32_t batch[] = {
107                 COPY_BLT_CMD | BLT_WRITE_ALPHA | BLT_WRITE_RGB,
108                 0xcc << 16 | 1 << 25 | 1 << 24 | len,
109                 0,
110                 1 << 16 | (len / 4),
111                 0, /* dst */
112                 0,
113                 len,
114                 0, /* src */
115                 MI_BATCH_BUFFER_END,
116                 0
117         };
118         struct drm_i915_gem_execbuffer2 execbuf = {
119                 (uintptr_t)exec, 3,
120                 0, sizeof(batch),
121                 0, 0, 0, 0,
122                 HAS_BLT_RING(intel_get_drm_devid(fd)) ? I915_EXEC_BLT : 0,
123         };
124         uint32_t *src_ptr, *dst_ptr;
125
126         gem_write(fd, exec[2].handle, 0, batch, sizeof(batch));
127
128         src_ptr = gem_mmap__gtt(fd, src, OBJECT_SIZE, PROT_WRITE);
129         dst_ptr = gem_mmap__gtt(fd, dst, OBJECT_SIZE, PROT_READ);
130
131         while (loops--) {
132                 gem_set_domain(fd, src,
133                                I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
134                 memcpy(src_ptr, buf, len);
135
136                 do_or_die(drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf));
137                 gem_set_domain(fd, dst,
138                                I915_GEM_DOMAIN_GTT, 0);
139                 memcpy(buf, dst_ptr, len);
140         }
141
142         munmap(dst_ptr, len);
143         munmap(src_ptr, len);
144         gem_close(fd, exec[2].handle);
145 }
146
147
148 static void as_cpu_mmap(int fd, uint32_t src, uint32_t dst, void *buf, int len, int loops)
149 {
150         struct drm_i915_gem_relocation_entry reloc[] = {
151                 { dst, 0, 4*sizeof(uint32_t), 0, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER },
152                 { src, 0, 7*sizeof(uint32_t), 0, I915_GEM_DOMAIN_RENDER, 0 },
153         };
154         struct drm_i915_gem_exec_object2 exec[] = {
155                 { src },
156                 { dst },
157                 { gem_create(fd, 4096), 2, (uintptr_t)reloc }
158         };
159         uint32_t batch[] = {
160                 COPY_BLT_CMD | BLT_WRITE_ALPHA | BLT_WRITE_RGB,
161                 0xcc << 16 | 1 << 25 | 1 << 24 | len,
162                 0,
163                 1 << 16 | (len / 4),
164                 0, /* dst */
165                 0,
166                 len,
167                 0, /* src */
168                 MI_BATCH_BUFFER_END,
169                 0
170         };
171         struct drm_i915_gem_execbuffer2 execbuf = {
172                 (uintptr_t)exec, 3,
173                 0, sizeof(batch),
174                 0, 0, 0, 0,
175                 HAS_BLT_RING(intel_get_drm_devid(fd)) ? I915_EXEC_BLT : 0,
176         };
177         uint32_t *src_ptr, *dst_ptr;
178
179         gem_write(fd, exec[2].handle, 0, batch, sizeof(batch));
180
181         src_ptr = gem_mmap__cpu(fd, src, OBJECT_SIZE, PROT_WRITE);
182         dst_ptr = gem_mmap__cpu(fd, dst, OBJECT_SIZE, PROT_READ);
183
184         while (loops--) {
185                 gem_set_domain(fd, src,
186                                I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
187                 memcpy(src_ptr, buf, len);
188
189                 do_or_die(drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf));
190                 gem_set_domain(fd, dst,
191                                I915_GEM_DOMAIN_CPU, 0);
192                 memcpy(buf, dst_ptr, len);
193         }
194
195         munmap(dst_ptr, len);
196         munmap(src_ptr, len);
197         gem_close(fd, exec[2].handle);
198 }
199
200 static void test_copy(int fd, uint32_t src, uint32_t dst, uint32_t *buf, int len)
201 {
202         struct drm_i915_gem_relocation_entry reloc[] = {
203                 { dst, 0, 4*sizeof(uint32_t), 0, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER },
204                 { src, 0, 7*sizeof(uint32_t), 0, I915_GEM_DOMAIN_RENDER, 0 },
205         };
206         struct drm_i915_gem_exec_object2 exec[] = {
207                 { src },
208                 { dst },
209                 { gem_create(fd, 4096), 2, (uintptr_t)reloc }
210         };
211         uint32_t batch[] = {
212                 COPY_BLT_CMD | BLT_WRITE_ALPHA | BLT_WRITE_RGB,
213                 0xcc << 16 | 1 << 25 | 1 << 24 | len,
214                 0,
215                 1 << 16 | (len / 4),
216                 0, /* dst */
217                 0,
218                 len,
219                 0, /* src */
220                 MI_BATCH_BUFFER_END,
221                 0
222         };
223         struct drm_i915_gem_execbuffer2 execbuf = {
224                 (uintptr_t)exec, 3,
225                 0, sizeof(batch),
226                 0, 0, 0, 0,
227                 HAS_BLT_RING(intel_get_drm_devid(fd)) ? I915_EXEC_BLT : 0,
228         };
229         int i;
230
231         gem_write(fd, exec[2].handle, 0, batch, sizeof(batch));
232
233         for (i = 0; i < len/4; i++)
234                 buf[i] = i;
235
236         gem_write(fd, src, 0, buf, len);
237         memset(buf, 0, len);
238
239         do_or_die(drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf));
240         gem_read(fd, dst, 0, buf, len);
241
242         gem_close(fd, exec[2].handle);
243
244         for (i = 0; i < len/4; i++)
245                 igt_assert(buf[i] == i);
246 }
247
248 static void test_as_gtt_mmap(int fd, uint32_t src, uint32_t dst, int len)
249 {
250         struct drm_i915_gem_relocation_entry reloc[] = {
251                 { dst, 0, 4*sizeof(uint32_t), 0, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER },
252                 { src, 0, 7*sizeof(uint32_t), 0, I915_GEM_DOMAIN_RENDER, 0 },
253         };
254         struct drm_i915_gem_exec_object2 exec[] = {
255                 { src },
256                 { dst },
257                 { gem_create(fd, 4096), 2, (uintptr_t)reloc }
258         };
259         uint32_t batch[] = {
260                 COPY_BLT_CMD | BLT_WRITE_ALPHA | BLT_WRITE_RGB,
261                 0xcc << 16 | 1 << 25 | 1 << 24 | len,
262                 0,
263                 1 << 16 | (len / 4),
264                 0, /* dst */
265                 0,
266                 len,
267                 0, /* src */
268                 MI_BATCH_BUFFER_END,
269                 0
270         };
271         struct drm_i915_gem_execbuffer2 execbuf = {
272                 (uintptr_t)exec, 3,
273                 0, sizeof(batch),
274                 0, 0, 0, 0,
275                 HAS_BLT_RING(intel_get_drm_devid(fd)) ? I915_EXEC_BLT : 0,
276         };
277         uint32_t *src_ptr, *dst_ptr;
278         int i;
279
280         gem_write(fd, exec[2].handle, 0, batch, sizeof(batch));
281
282         src_ptr = gem_mmap__gtt(fd, src, OBJECT_SIZE, PROT_WRITE);
283         dst_ptr = gem_mmap__gtt(fd, dst, OBJECT_SIZE, PROT_READ);
284
285         gem_set_domain(fd, src, I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
286         for (i = 0; i < len/4; i++)
287                 src_ptr[i] = i;
288
289         do_or_die(drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf));
290         gem_close(fd, exec[2].handle);
291
292         gem_set_domain(fd, dst, I915_GEM_DOMAIN_GTT, 0);
293         for (i = 0; i < len/4; i++)
294                 igt_assert(dst_ptr[i] == i);
295
296         munmap(dst_ptr, len);
297         munmap(src_ptr, len);
298 }
299
300 static void test_as_cpu_mmap(int fd, uint32_t src, uint32_t dst, int len)
301 {
302         struct drm_i915_gem_relocation_entry reloc[] = {
303                 { dst, 0, 4*sizeof(uint32_t), 0, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER },
304                 { src, 0, 7*sizeof(uint32_t), 0, I915_GEM_DOMAIN_RENDER, 0 },
305         };
306         struct drm_i915_gem_exec_object2 exec[] = {
307                 { src },
308                 { dst },
309                 { gem_create(fd, 4096), 2, (uintptr_t)reloc }
310         };
311         uint32_t batch[] = {
312                 COPY_BLT_CMD | BLT_WRITE_ALPHA | BLT_WRITE_RGB,
313                 0xcc << 16 | 1 << 25 | 1 << 24 | len,
314                 0,
315                 1 << 16 | (len / 4),
316                 0, /* dst */
317                 0,
318                 len,
319                 0, /* src */
320                 MI_BATCH_BUFFER_END,
321                 0
322         };
323         struct drm_i915_gem_execbuffer2 execbuf = {
324                 (uintptr_t)exec, 3,
325                 0, sizeof(batch),
326                 0, 0, 0, 0,
327                 HAS_BLT_RING(intel_get_drm_devid(fd)) ? I915_EXEC_BLT : 0,
328         };
329         uint32_t *src_ptr, *dst_ptr;
330         int i;
331
332         gem_write(fd, exec[2].handle, 0, batch, sizeof(batch));
333
334         src_ptr = gem_mmap__cpu(fd, src, OBJECT_SIZE, PROT_WRITE);
335         dst_ptr = gem_mmap__cpu(fd, dst, OBJECT_SIZE, PROT_READ);
336
337         gem_set_domain(fd, src, I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
338         for (i = 0; i < len/4; i++)
339                 src_ptr[i] = i;
340
341         do_or_die(drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf));
342         gem_close(fd, exec[2].handle);
343
344         gem_set_domain(fd, dst, I915_GEM_DOMAIN_CPU, 0);
345         for (i = 0; i < len/4; i++)
346                 igt_assert(dst_ptr[i] == i);
347
348         munmap(dst_ptr, len);
349         munmap(src_ptr, len);
350 }
351
352 static double elapsed(const struct timeval *start,
353                       const struct timeval *end,
354                       int loop)
355 {
356         return (1e6*(end->tv_sec - start->tv_sec) + (end->tv_usec - start->tv_usec))/loop;
357 }
358
359 static const char *bytes_per_sec(char *buf, double v)
360 {
361         const char *order[] = {
362                 "",
363                 "KiB",
364                 "MiB",
365                 "GiB",
366                 "TiB",
367                 NULL,
368         }, **o = order;
369
370         while (v > 1000 && o[1]) {
371                 v /= 1000;
372                 o++;
373         }
374         sprintf(buf, "%.1f%s/s", v, *o);
375         return buf;
376 }
377
378 uint32_t *tmp, src, dst;
379 int fd;
380
381 int main(int argc, char **argv)
382 {
383         int object_size = 0;
384         uint32_t buf[20];
385         int count;
386
387         igt_subtest_init(argc, argv);
388         igt_skip_on_simulation();
389
390         if (argc > 1)
391                 object_size = atoi(argv[1]);
392         if (object_size == 0)
393                 object_size = OBJECT_SIZE;
394         object_size = (object_size + 3) & -4;
395
396         igt_fixture {
397                 fd = drm_open_any();
398
399                 dst = gem_create(fd, object_size);
400                 src = gem_create(fd, object_size);
401                 tmp = malloc(object_size);
402
403                 gem_set_caching(fd, src, 0);
404                 gem_set_caching(fd, dst, 0);
405         }
406
407         igt_subtest("uncached-copy-correctness")
408                 test_copy(fd, src, dst, tmp, object_size);
409         igt_subtest("uncached-copy-performance") {
410                 for (count = 1; count <= 1<<17; count <<= 1) {
411                         struct timeval start, end;
412
413                         gettimeofday(&start, NULL);
414                         copy(fd, src, dst, tmp, object_size, count);
415                         gettimeofday(&end, NULL);
416                         printf("Time to uncached copy %d bytes x %6d:   %7.3fµs, %s\n",
417                                object_size, count,
418                                elapsed(&start, &end, count),
419                                bytes_per_sec((char *)buf, object_size/elapsed(&start, &end, count)*1e6));
420                         fflush(stdout);
421                 }
422         }
423
424         igt_subtest("uncached-pwrite-blt-gtt_mmap-correctness")
425                 test_as_gtt_mmap(fd, src, dst, object_size);
426         igt_subtest("uncached-pwrite-blt-gtt_mmap-performance") {
427                 for (count = 1; count <= 1<<17; count <<= 1) {
428                         struct timeval start, end;
429
430                         gettimeofday(&start, NULL);
431                         as_gtt_mmap(fd, src, dst, tmp, object_size, count);
432                         gettimeofday(&end, NULL);
433                         printf("** mmap uncached copy %d bytes x %6d:   %7.3fµs, %s\n",
434                                object_size, count,
435                                elapsed(&start, &end, count),
436                                bytes_per_sec((char *)buf, object_size/elapsed(&start, &end, count)*1e6));
437                         fflush(stdout);
438                 }
439         }
440
441         igt_fixture {
442                 gem_set_caching(fd, src, 1);
443                 gem_set_caching(fd, dst, 1);
444         }
445
446         igt_subtest("snooped-copy-correctness")
447                 test_copy(fd, src, dst, tmp, object_size);
448         igt_subtest("snooped-copy-performance") {
449                 for (count = 1; count <= 1<<17; count <<= 1) {
450                         struct timeval start, end;
451
452                         gettimeofday(&start, NULL);
453                         copy(fd, src, dst, tmp, object_size, count);
454                         gettimeofday(&end, NULL);
455                         printf("Time to snooped copy %d bytes x %6d:    %7.3fµs, %s\n",
456                                object_size, count,
457                                elapsed(&start, &end, count),
458                                bytes_per_sec((char *)buf, object_size/elapsed(&start, &end, count)*1e6));
459                         fflush(stdout);
460                 }
461         }
462
463         igt_subtest("snooped-pwrite-blt-cpu_mmap-correctness")
464                 test_as_cpu_mmap(fd, src, dst, object_size);
465         igt_subtest("snooped-pwrite-blt-cpu_mmap-performance") {
466                 for (count = 1; count <= 1<<17; count <<= 1) {
467                         struct timeval start, end;
468
469                         gettimeofday(&start, NULL);
470                         as_cpu_mmap(fd, src, dst, tmp, object_size, count);
471                         gettimeofday(&end, NULL);
472                         printf("** mmap snooped copy %d bytes x %6d:    %7.3fµs, %s\n",
473                                object_size, count,
474                                elapsed(&start, &end, count),
475                                bytes_per_sec((char *)buf, object_size/elapsed(&start, &end, count)*1e6));
476                         fflush(stdout);
477                 }
478         }
479
480         igt_fixture {
481                 gem_set_caching(fd, src, 2);
482                 gem_set_caching(fd, dst, 2);
483         }
484
485         igt_subtest("display-copy-correctness")
486                 test_copy(fd, src, dst, tmp, object_size);
487         igt_subtest("display-copy-performance") {
488                 for (count = 1; count <= 1<<17; count <<= 1) {
489                         struct timeval start, end;
490
491                         gettimeofday(&start, NULL);
492                         copy(fd, src, dst, tmp, object_size, count);
493                         gettimeofday(&end, NULL);
494                         printf("Time to display copy %d bytes x %6d:    %7.3fµs, %s\n",
495                                object_size, count,
496                                elapsed(&start, &end, count),
497                                bytes_per_sec((char *)buf, object_size/elapsed(&start, &end, count)*1e6));
498                         fflush(stdout);
499                 }
500         }
501
502         igt_subtest("display-pwrite-blt-gtt_mmap-correctness")
503                 test_as_gtt_mmap(fd, src, dst, object_size);
504         igt_subtest("display-pwrite-blt-gtt_mmap-performance") {
505                 for (count = 1; count <= 1<<17; count <<= 1) {
506                         struct timeval start, end;
507
508                         gettimeofday(&start, NULL);
509                         as_gtt_mmap(fd, src, dst, tmp, object_size, count);
510                         gettimeofday(&end, NULL);
511                         printf("** mmap display copy %d bytes x %6d:    %7.3fµs, %s\n",
512                                object_size, count,
513                                elapsed(&start, &end, count),
514                                bytes_per_sec((char *)buf, object_size/elapsed(&start, &end, count)*1e6));
515                         fflush(stdout);
516                 }
517         }
518
519         igt_fixture {
520                 free(tmp);
521                 gem_close(fd, src);
522                 gem_close(fd, dst);
523
524                 close(fd);
525         }
526
527         igt_exit();
528 }