Expand gem_set_cacheing testing to handle the proposed DISPLAY domain
[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 <assert.h>
34 #include <fcntl.h>
35 #include <inttypes.h>
36 #include <errno.h>
37 #include <sys/stat.h>
38 #include <sys/ioctl.h>
39 #include <sys/mman.h>
40 #include <sys/time.h>
41 #include "drm.h"
42 #include "i915_drm.h"
43 #include "drmtest.h"
44 #include "intel_bufmgr.h"
45 #include "intel_batchbuffer.h"
46 #include "intel_gpu_tools.h"
47
48 #define OBJECT_SIZE 16384
49
50 #define COPY_BLT_CMD            (2<<29|0x53<<22|0x6)
51 #define BLT_WRITE_ALPHA         (1<<21)
52 #define BLT_WRITE_RGB           (1<<20)
53 #define BLT_SRC_TILED           (1<<15)
54 #define BLT_DST_TILED           (1<<11)
55
56 static void copy(int fd, uint32_t src, uint32_t dst, void *buf, int len, int loops)
57 {
58         struct drm_i915_gem_relocation_entry reloc[] = {
59                 { dst, 0, 4*sizeof(uint32_t), 0, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER },
60                 { src, 0, 7*sizeof(uint32_t), 0, I915_GEM_DOMAIN_RENDER, 0 },
61         };
62         struct drm_i915_gem_exec_object2 exec[] = {
63                 { src },
64                 { dst },
65                 { gem_create(fd, 4096), 2, (uintptr_t)reloc }
66         };
67         uint32_t batch[] = {
68                 COPY_BLT_CMD | BLT_WRITE_ALPHA | BLT_WRITE_RGB,
69                 0xcc << 16 | 1 << 25 | 1 << 24 | len,
70                 0,
71                 1 << 16 | (len / 4),
72                 0, /* dst */
73                 0,
74                 len,
75                 0, /* src */
76                 MI_BATCH_BUFFER_END,
77                 0
78         };
79         struct drm_i915_gem_execbuffer2 execbuf = {
80                 (uintptr_t)exec, 3,
81                 0, sizeof(batch),
82                 0, 0, 0, 0,
83                 HAS_BLT_RING(intel_get_drm_devid(fd)) ? I915_EXEC_BLT : 0,
84         };
85         gem_write(fd, exec[2].handle, 0, batch, sizeof(batch));
86
87         while (loops--) {
88                 gem_write(fd, src, 0, buf, len);
89                 do_or_die(drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf));
90                 gem_read(fd, dst, 0, buf, len);
91         }
92
93         gem_close(fd, exec[2].handle);
94 }
95
96 static void as_gtt_mmap(int fd, uint32_t src, uint32_t dst, void *buf, int len, int loops)
97 {
98         struct drm_i915_gem_relocation_entry reloc[] = {
99                 { dst, 0, 4*sizeof(uint32_t), 0, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER },
100                 { src, 0, 7*sizeof(uint32_t), 0, I915_GEM_DOMAIN_RENDER, 0 },
101         };
102         struct drm_i915_gem_exec_object2 exec[] = {
103                 { src },
104                 { dst },
105                 { gem_create(fd, 4096), 2, (uintptr_t)reloc }
106         };
107         uint32_t batch[] = {
108                 COPY_BLT_CMD | BLT_WRITE_ALPHA | BLT_WRITE_RGB,
109                 0xcc << 16 | 1 << 25 | 1 << 24 | len,
110                 0,
111                 1 << 16 | (len / 4),
112                 0, /* dst */
113                 0,
114                 len,
115                 0, /* src */
116                 MI_BATCH_BUFFER_END,
117                 0
118         };
119         struct drm_i915_gem_execbuffer2 execbuf = {
120                 (uintptr_t)exec, 3,
121                 0, sizeof(batch),
122                 0, 0, 0, 0,
123                 HAS_BLT_RING(intel_get_drm_devid(fd)) ? I915_EXEC_BLT : 0,
124         };
125         uint32_t *src_ptr, *dst_ptr;
126
127         gem_write(fd, exec[2].handle, 0, batch, sizeof(batch));
128
129         src_ptr = gem_mmap__gtt(fd, src, OBJECT_SIZE, PROT_WRITE);
130         dst_ptr = gem_mmap__gtt(fd, dst, OBJECT_SIZE, PROT_READ);
131
132         while (loops--) {
133                 gem_set_domain(fd, src,
134                                I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
135                 memcpy(src_ptr, buf, len);
136
137                 do_or_die(drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf));
138                 gem_set_domain(fd, dst,
139                                I915_GEM_DOMAIN_GTT, 0);
140                 memcpy(buf, dst_ptr, len);
141         }
142
143         munmap(dst_ptr, len);
144         munmap(src_ptr, len);
145         gem_close(fd, exec[2].handle);
146 }
147
148
149 static void as_cpu_mmap(int fd, uint32_t src, uint32_t dst, void *buf, int len, int loops)
150 {
151         struct drm_i915_gem_relocation_entry reloc[] = {
152                 { dst, 0, 4*sizeof(uint32_t), 0, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER },
153                 { src, 0, 7*sizeof(uint32_t), 0, I915_GEM_DOMAIN_RENDER, 0 },
154         };
155         struct drm_i915_gem_exec_object2 exec[] = {
156                 { src },
157                 { dst },
158                 { gem_create(fd, 4096), 2, (uintptr_t)reloc }
159         };
160         uint32_t batch[] = {
161                 COPY_BLT_CMD | BLT_WRITE_ALPHA | BLT_WRITE_RGB,
162                 0xcc << 16 | 1 << 25 | 1 << 24 | len,
163                 0,
164                 1 << 16 | (len / 4),
165                 0, /* dst */
166                 0,
167                 len,
168                 0, /* src */
169                 MI_BATCH_BUFFER_END,
170                 0
171         };
172         struct drm_i915_gem_execbuffer2 execbuf = {
173                 (uintptr_t)exec, 3,
174                 0, sizeof(batch),
175                 0, 0, 0, 0,
176                 HAS_BLT_RING(intel_get_drm_devid(fd)) ? I915_EXEC_BLT : 0,
177         };
178         uint32_t *src_ptr, *dst_ptr;
179
180         gem_write(fd, exec[2].handle, 0, batch, sizeof(batch));
181
182         src_ptr = gem_mmap__cpu(fd, src, OBJECT_SIZE, PROT_WRITE);
183         dst_ptr = gem_mmap__cpu(fd, dst, OBJECT_SIZE, PROT_READ);
184
185         while (loops--) {
186                 gem_set_domain(fd, src,
187                                I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
188                 memcpy(src_ptr, buf, len);
189
190                 do_or_die(drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf));
191                 gem_set_domain(fd, dst,
192                                I915_GEM_DOMAIN_CPU, 0);
193                 memcpy(buf, dst_ptr, len);
194         }
195
196         munmap(dst_ptr, len);
197         munmap(src_ptr, len);
198         gem_close(fd, exec[2].handle);
199 }
200
201 static void test_copy(int fd, uint32_t src, uint32_t dst, uint32_t *buf, int len)
202 {
203         struct drm_i915_gem_relocation_entry reloc[] = {
204                 { dst, 0, 4*sizeof(uint32_t), 0, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER },
205                 { src, 0, 7*sizeof(uint32_t), 0, I915_GEM_DOMAIN_RENDER, 0 },
206         };
207         struct drm_i915_gem_exec_object2 exec[] = {
208                 { src },
209                 { dst },
210                 { gem_create(fd, 4096), 2, (uintptr_t)reloc }
211         };
212         uint32_t batch[] = {
213                 COPY_BLT_CMD | BLT_WRITE_ALPHA | BLT_WRITE_RGB,
214                 0xcc << 16 | 1 << 25 | 1 << 24 | len,
215                 0,
216                 1 << 16 | (len / 4),
217                 0, /* dst */
218                 0,
219                 len,
220                 0, /* src */
221                 MI_BATCH_BUFFER_END,
222                 0
223         };
224         struct drm_i915_gem_execbuffer2 execbuf = {
225                 (uintptr_t)exec, 3,
226                 0, sizeof(batch),
227                 0, 0, 0, 0,
228                 HAS_BLT_RING(intel_get_drm_devid(fd)) ? I915_EXEC_BLT : 0,
229         };
230         int i;
231
232         gem_write(fd, exec[2].handle, 0, batch, sizeof(batch));
233
234         for (i = 0; i < len/4; i++)
235                 buf[i] = i;
236
237         gem_write(fd, src, 0, buf, len);
238         memset(buf, 0, len);
239
240         do_or_die(drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf));
241         gem_read(fd, dst, 0, buf, len);
242
243         gem_close(fd, exec[2].handle);
244
245         for (i = 0; i < len/4; i++)
246                 assert(buf[i] == i);
247 }
248
249 static void test_as_gtt_mmap(int fd, uint32_t src, uint32_t dst, int len)
250 {
251         struct drm_i915_gem_relocation_entry reloc[] = {
252                 { dst, 0, 4*sizeof(uint32_t), 0, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER },
253                 { src, 0, 7*sizeof(uint32_t), 0, I915_GEM_DOMAIN_RENDER, 0 },
254         };
255         struct drm_i915_gem_exec_object2 exec[] = {
256                 { src },
257                 { dst },
258                 { gem_create(fd, 4096), 2, (uintptr_t)reloc }
259         };
260         uint32_t batch[] = {
261                 COPY_BLT_CMD | BLT_WRITE_ALPHA | BLT_WRITE_RGB,
262                 0xcc << 16 | 1 << 25 | 1 << 24 | len,
263                 0,
264                 1 << 16 | (len / 4),
265                 0, /* dst */
266                 0,
267                 len,
268                 0, /* src */
269                 MI_BATCH_BUFFER_END,
270                 0
271         };
272         struct drm_i915_gem_execbuffer2 execbuf = {
273                 (uintptr_t)exec, 3,
274                 0, sizeof(batch),
275                 0, 0, 0, 0,
276                 HAS_BLT_RING(intel_get_drm_devid(fd)) ? I915_EXEC_BLT : 0,
277         };
278         uint32_t *src_ptr, *dst_ptr;
279         int i;
280
281         gem_write(fd, exec[2].handle, 0, batch, sizeof(batch));
282
283         src_ptr = gem_mmap__gtt(fd, src, OBJECT_SIZE, PROT_WRITE);
284         dst_ptr = gem_mmap__gtt(fd, dst, OBJECT_SIZE, PROT_READ);
285
286         gem_set_domain(fd, src, I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
287         for (i = 0; i < len/4; i++)
288                 src_ptr[i] = i;
289
290         do_or_die(drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf));
291         gem_close(fd, exec[2].handle);
292
293         gem_set_domain(fd, dst, I915_GEM_DOMAIN_GTT, 0);
294         for (i = 0; i < len/4; i++)
295                 assert(dst_ptr[i] == i);
296
297         munmap(dst_ptr, len);
298         munmap(src_ptr, len);
299 }
300
301 static void test_as_cpu_mmap(int fd, uint32_t src, uint32_t dst, int len)
302 {
303         struct drm_i915_gem_relocation_entry reloc[] = {
304                 { dst, 0, 4*sizeof(uint32_t), 0, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER },
305                 { src, 0, 7*sizeof(uint32_t), 0, I915_GEM_DOMAIN_RENDER, 0 },
306         };
307         struct drm_i915_gem_exec_object2 exec[] = {
308                 { src },
309                 { dst },
310                 { gem_create(fd, 4096), 2, (uintptr_t)reloc }
311         };
312         uint32_t batch[] = {
313                 COPY_BLT_CMD | BLT_WRITE_ALPHA | BLT_WRITE_RGB,
314                 0xcc << 16 | 1 << 25 | 1 << 24 | len,
315                 0,
316                 1 << 16 | (len / 4),
317                 0, /* dst */
318                 0,
319                 len,
320                 0, /* src */
321                 MI_BATCH_BUFFER_END,
322                 0
323         };
324         struct drm_i915_gem_execbuffer2 execbuf = {
325                 (uintptr_t)exec, 3,
326                 0, sizeof(batch),
327                 0, 0, 0, 0,
328                 HAS_BLT_RING(intel_get_drm_devid(fd)) ? I915_EXEC_BLT : 0,
329         };
330         uint32_t *src_ptr, *dst_ptr;
331         int i;
332
333         gem_write(fd, exec[2].handle, 0, batch, sizeof(batch));
334
335         src_ptr = gem_mmap__cpu(fd, src, OBJECT_SIZE, PROT_WRITE);
336         dst_ptr = gem_mmap__cpu(fd, dst, OBJECT_SIZE, PROT_READ);
337
338         gem_set_domain(fd, src, I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
339         for (i = 0; i < len/4; i++)
340                 src_ptr[i] = i;
341
342         do_or_die(drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf));
343         gem_close(fd, exec[2].handle);
344
345         gem_set_domain(fd, dst, I915_GEM_DOMAIN_CPU, 0);
346         for (i = 0; i < len/4; i++)
347                 assert(dst_ptr[i] == i);
348
349         munmap(dst_ptr, len);
350         munmap(src_ptr, len);
351 }
352
353 static double elapsed(const struct timeval *start,
354                       const struct timeval *end,
355                       int loop)
356 {
357         return (1e6*(end->tv_sec - start->tv_sec) + (end->tv_usec - start->tv_usec))/loop;
358 }
359
360 static const char *bytes_per_sec(char *buf, double v)
361 {
362         const char *order[] = {
363                 "",
364                 "KiB",
365                 "MiB",
366                 "GiB",
367                 "TiB",
368                 NULL,
369         }, **o = order;
370
371         while (v > 1000 && o[1]) {
372                 v /= 1000;
373                 o++;
374         }
375         sprintf(buf, "%.1f%s/s", v, *o);
376         return buf;
377 }
378
379 int main(int argc, char **argv)
380 {
381         int object_size = 0;
382         uint32_t buf[20];
383         uint32_t *tmp, src, dst;
384         int fd, count;
385
386         drmtest_subtest_init(argc, argv);
387         drmtest_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         fd = drm_open_any();
396
397         dst = gem_create(fd, object_size);
398         src = gem_create(fd, object_size);
399         tmp = malloc(object_size);
400
401         if (gem_set_cacheing(fd, src, 0) == 0 &&
402             gem_set_cacheing(fd, dst, 0) == 0) {
403                 if (drmtest_run_subtest("uncached-copy-correctness"))
404                         test_copy(fd, src, dst, tmp, object_size);
405                 if (drmtest_run_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                 if (drmtest_run_subtest("uncached-pwrite-blt-gtt_mmap-correctness"))
421                         test_as_gtt_mmap(fd, src, dst, object_size);
422                 if (drmtest_run_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
438         if (gem_set_cacheing(fd, src, 1) == 0 &&
439             gem_set_cacheing(fd, dst, 1) == 0) {
440                 if (drmtest_run_subtest("snooped-copy-correctness"))
441                         test_copy(fd, src, dst, tmp, object_size);
442                 if (drmtest_run_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                 if (drmtest_run_subtest("snooped-pwrite-blt-cpu_mmap-correctness"))
458                         test_as_cpu_mmap(fd, src, dst, object_size);
459                 if (drmtest_run_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
475         if (gem_set_cacheing(fd, src, 2) == 0 &&
476             gem_set_cacheing(fd, dst, 2) == 0) {
477                 if (drmtest_run_subtest("display-copy-correctness"))
478                         test_copy(fd, src, dst, tmp, object_size);
479                 if (drmtest_run_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                 if (drmtest_run_subtest("display-pwrite-blt-gtt_mmap-correctness"))
495                         test_as_gtt_mmap(fd, src, dst, object_size);
496                 if (drmtest_run_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
512         free(tmp);
513         gem_close(fd, src);
514         gem_close(fd, dst);
515
516         close(fd);
517
518         return 0;
519 }