1 /*
2 * Copyright © 2015 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
24 /** @file gem_read_read_speed.c
25 *
26 * This is a test of performance with multiple readers from the same source.
27 */
28
29 #include "igt.h"
30 #include "igt_sysfs.h"
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <fcntl.h>
35 #include <inttypes.h>
36 #include <errno.h>
37 #include <time.h>
38 #include <sys/stat.h>
39 #include <sys/time.h>
40 #include <sys/wait.h>
41
42 #include <drm.h>
43
44 #include "intel_bufmgr.h"
45
46 IGT_TEST_DESCRIPTION("Test speed of concurrent reads between engines.");
47
48 igt_render_copyfunc_t rendercopy;
49 struct intel_batchbuffer *batch;
50 int width, height;
51
rcs_copy_bo(drm_intel_bo * dst,drm_intel_bo * src)52 static drm_intel_bo *rcs_copy_bo(drm_intel_bo *dst, drm_intel_bo *src)
53 {
54 struct igt_buf d = {
55 .bo = dst,
56 .size = width * height * 4,
57 .num_tiles = width * height * 4,
58 .stride = width * 4,
59 .bpp = 32,
60 }, s = {
61 .bo = src,
62 .size = width * height * 4,
63 .num_tiles = width * height * 4,
64 .stride = width * 4,
65 .bpp = 32,
66 };
67 uint32_t swizzle;
68 drm_intel_bo *bo = batch->bo;
69 drm_intel_bo_reference(bo);
70
71 drm_intel_bo_get_tiling(dst, &d.tiling, &swizzle);
72 drm_intel_bo_get_tiling(src, &s.tiling, &swizzle);
73
74 rendercopy(batch, NULL,
75 &s, 0, 0,
76 width, height,
77 &d, 0, 0);
78
79 return bo;
80 }
81
bcs_copy_bo(drm_intel_bo * dst,drm_intel_bo * src)82 static drm_intel_bo *bcs_copy_bo(drm_intel_bo *dst, drm_intel_bo *src)
83 {
84 drm_intel_bo *bo = batch->bo;
85 drm_intel_bo_reference(bo);
86
87 intel_blt_copy(batch,
88 src, 0, 0, 4*width,
89 dst, 0, 0, 4*width,
90 width, height, 32);
91
92 return bo;
93 }
94
95 static void
set_bo(drm_intel_bo * bo,uint32_t val)96 set_bo(drm_intel_bo *bo, uint32_t val)
97 {
98 int size = width * height;
99 uint32_t *vaddr;
100
101 do_or_die(drm_intel_bo_map(bo, 1));
102 vaddr = bo->virtual;
103 while (size--)
104 *vaddr++ = val;
105 drm_intel_bo_unmap(bo);
106 }
107
elapsed(const struct timespec * start,const struct timespec * end,int loop)108 static double elapsed(const struct timespec *start,
109 const struct timespec *end,
110 int loop)
111 {
112 return (1e6*(end->tv_sec - start->tv_sec) + (end->tv_nsec - start->tv_nsec)/1000)/loop;
113 }
114
create_bo(drm_intel_bufmgr * bufmgr,const char * name)115 static drm_intel_bo *create_bo(drm_intel_bufmgr *bufmgr,
116 const char *name)
117 {
118 uint32_t tiling_mode = I915_TILING_X;
119 unsigned long pitch;
120 return drm_intel_bo_alloc_tiled(bufmgr, name,
121 width, height, 4,
122 &tiling_mode, &pitch, 0);
123 }
124
run(drm_intel_bufmgr * bufmgr,int _width,int _height,bool write_bcs,bool write_rcs)125 static void run(drm_intel_bufmgr *bufmgr, int _width, int _height,
126 bool write_bcs, bool write_rcs)
127 {
128 drm_intel_bo *src = NULL, *bcs = NULL, *rcs = NULL;
129 drm_intel_bo *bcs_batch, *rcs_batch;
130 struct timespec start, end;
131 int loops = 1000;
132
133 width = _width;
134 height = _height;
135
136 src = create_bo(bufmgr, "src");
137 bcs = create_bo(bufmgr, "bcs");
138 rcs = create_bo(bufmgr, "rcs");
139
140 set_bo(src, 0xdeadbeef);
141
142 if (write_bcs) {
143 bcs_batch = bcs_copy_bo(src, bcs);
144 } else {
145 bcs_batch = bcs_copy_bo(bcs, src);
146 }
147 if (write_rcs) {
148 rcs_batch = rcs_copy_bo(src, rcs);
149 } else {
150 rcs_batch = rcs_copy_bo(rcs, src);
151 }
152
153 drm_intel_bo_unreference(rcs);
154 drm_intel_bo_unreference(bcs);
155
156 drm_intel_gem_bo_start_gtt_access(src, true);
157 clock_gettime(CLOCK_MONOTONIC, &start);
158 for (int i = 0; i < loops; i++) {
159 drm_intel_gem_bo_context_exec(rcs_batch, NULL, 4096, I915_EXEC_RENDER);
160 drm_intel_gem_bo_context_exec(bcs_batch, NULL, 4096, I915_EXEC_BLT);
161 }
162 drm_intel_gem_bo_start_gtt_access(src, true);
163 clock_gettime(CLOCK_MONOTONIC, &end);
164
165 igt_info("Time to %s-%s %dx%d [%dk]: %7.3fµs\n",
166 write_bcs ? "write" : "read",
167 write_rcs ? "write" : "read",
168 width, height, 4*width*height/1024,
169 elapsed(&start, &end, loops));
170
171 drm_intel_bo_unreference(rcs_batch);
172 drm_intel_bo_unreference(bcs_batch);
173
174 drm_intel_bo_unreference(src);
175 }
176
177 igt_main
178 {
179 const int sizes[] = {1, 128, 256, 512, 1024, 2048, 4096, 8192, 0};
180 drm_intel_bufmgr *bufmgr = NULL;
181 int fd, i;
182
183 igt_skip_on_simulation();
184
185 igt_fixture {
186 int devid;
187
188 fd = drm_open_driver(DRIVER_INTEL);
189 igt_require_gem(fd);
190
191 devid = intel_get_drm_devid(fd);
192 igt_require(intel_gen(devid) >= 6);
193
194 rendercopy = igt_get_render_copyfunc(devid);
195 igt_require(rendercopy);
196
197 bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
198 igt_assert(bufmgr);
199
200 batch = intel_batchbuffer_alloc(bufmgr, devid);
201
202 gem_submission_print_method(fd);
203 }
204
205 for (i = 0; sizes[i] != 0; i++) {
206 igt_subtest_f("read-read-%dx%d", sizes[i], sizes[i])
207 run(bufmgr, sizes[i], sizes[i], false, false);
208 igt_subtest_f("read-write-%dx%d", sizes[i], sizes[i])
209 run(bufmgr, sizes[i], sizes[i], false, true);
210 igt_subtest_f("write-read-%dx%d", sizes[i], sizes[i])
211 run(bufmgr, sizes[i], sizes[i], true, false);
212 igt_subtest_f("write-write-%dx%d", sizes[i], sizes[i])
213 run(bufmgr, sizes[i], sizes[i], true, true);
214 }
215 }
216