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