tests: s/assert/igt_assert
[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 int main(int argc, char **argv)
379 {
380         int object_size = 0;
381         uint32_t buf[20];
382         uint32_t *tmp, src, dst;
383         int fd, count;
384
385         igt_subtest_init(argc, argv);
386         igt_skip_on_simulation();
387
388         if (argc > 1)
389                 object_size = atoi(argv[1]);
390         if (object_size == 0)
391                 object_size = OBJECT_SIZE;
392         object_size = (object_size + 3) & -4;
393
394         fd = drm_open_any();
395
396         dst = gem_create(fd, object_size);
397         src = gem_create(fd, object_size);
398         tmp = malloc(object_size);
399
400         gem_set_caching(fd, src, 0);
401         gem_set_caching(fd, dst, 0);
402
403         igt_subtest("uncached-copy-correctness")
404                 test_copy(fd, src, dst, tmp, object_size);
405         igt_subtest("uncached-copy-performance") {
406                 for (count = 1; count <= 1<<17; count <<= 1) {
407                         struct timeval start, end;
408
409                         gettimeofday(&start, NULL);
410                         copy(fd, src, dst, tmp, object_size, count);
411                         gettimeofday(&end, NULL);
412                         printf("Time to uncached copy %d bytes x %6d:   %7.3fµs, %s\n",
413                                object_size, count,
414                                elapsed(&start, &end, count),
415                                bytes_per_sec((char *)buf, object_size/elapsed(&start, &end, count)*1e6));
416                         fflush(stdout);
417                 }
418         }
419
420         igt_subtest("uncached-pwrite-blt-gtt_mmap-correctness")
421                 test_as_gtt_mmap(fd, src, dst, object_size);
422         igt_subtest("uncached-pwrite-blt-gtt_mmap-performance") {
423                 for (count = 1; count <= 1<<17; count <<= 1) {
424                         struct timeval start, end;
425
426                         gettimeofday(&start, NULL);
427                         as_gtt_mmap(fd, src, dst, tmp, object_size, count);
428                         gettimeofday(&end, NULL);
429                         printf("** mmap uncached copy %d bytes x %6d:   %7.3fµs, %s\n",
430                                object_size, count,
431                                elapsed(&start, &end, count),
432                                bytes_per_sec((char *)buf, object_size/elapsed(&start, &end, count)*1e6));
433                         fflush(stdout);
434                 }
435         }
436
437         gem_set_caching(fd, src, 1);
438         gem_set_caching(fd, dst, 1);
439
440         igt_subtest("snooped-copy-correctness")
441                 test_copy(fd, src, dst, tmp, object_size);
442         igt_subtest("snooped-copy-performance") {
443                 for (count = 1; count <= 1<<17; count <<= 1) {
444                         struct timeval start, end;
445
446                         gettimeofday(&start, NULL);
447                         copy(fd, src, dst, tmp, object_size, count);
448                         gettimeofday(&end, NULL);
449                         printf("Time to snooped copy %d bytes x %6d:    %7.3fµs, %s\n",
450                                object_size, count,
451                                elapsed(&start, &end, count),
452                                bytes_per_sec((char *)buf, object_size/elapsed(&start, &end, count)*1e6));
453                         fflush(stdout);
454                 }
455         }
456
457         igt_subtest("snooped-pwrite-blt-cpu_mmap-correctness")
458                 test_as_cpu_mmap(fd, src, dst, object_size);
459         igt_subtest("snooped-pwrite-blt-cpu_mmap-performance") {
460                 for (count = 1; count <= 1<<17; count <<= 1) {
461                         struct timeval start, end;
462
463                         gettimeofday(&start, NULL);
464                         as_cpu_mmap(fd, src, dst, tmp, object_size, count);
465                         gettimeofday(&end, NULL);
466                         printf("** mmap snooped copy %d bytes x %6d:    %7.3fµs, %s\n",
467                                object_size, count,
468                                elapsed(&start, &end, count),
469                                bytes_per_sec((char *)buf, object_size/elapsed(&start, &end, count)*1e6));
470                         fflush(stdout);
471                 }
472         }
473
474         gem_set_caching(fd, src, 2);
475         gem_set_caching(fd, dst, 2);
476
477         igt_subtest("display-copy-correctness")
478                 test_copy(fd, src, dst, tmp, object_size);
479         igt_subtest("display-copy-performance") {
480                 for (count = 1; count <= 1<<17; count <<= 1) {
481                         struct timeval start, end;
482
483                         gettimeofday(&start, NULL);
484                         copy(fd, src, dst, tmp, object_size, count);
485                         gettimeofday(&end, NULL);
486                         printf("Time to display copy %d bytes x %6d:    %7.3fµs, %s\n",
487                                object_size, count,
488                                elapsed(&start, &end, count),
489                                bytes_per_sec((char *)buf, object_size/elapsed(&start, &end, count)*1e6));
490                         fflush(stdout);
491                 }
492         }
493
494         igt_subtest("display-pwrite-blt-gtt_mmap-correctness")
495                 test_as_gtt_mmap(fd, src, dst, object_size);
496         igt_subtest("display-pwrite-blt-gtt_mmap-performance") {
497                 for (count = 1; count <= 1<<17; count <<= 1) {
498                         struct timeval start, end;
499
500                         gettimeofday(&start, NULL);
501                         as_gtt_mmap(fd, src, dst, tmp, object_size, count);
502                         gettimeofday(&end, NULL);
503                         printf("** mmap display copy %d bytes x %6d:    %7.3fµs, %s\n",
504                                object_size, count,
505                                elapsed(&start, &end, count),
506                                bytes_per_sec((char *)buf, object_size/elapsed(&start, &end, count)*1e6));
507                         fflush(stdout);
508                 }
509         }
510
511         free(tmp);
512         gem_close(fd, src);
513         gem_close(fd, dst);
514
515         close(fd);
516
517         igt_exit();
518 }