summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Jakobi2015-11-29 21:12:14 -0600
committerEmil Velikov2015-12-18 11:42:54 -0600
commit2e4b9f08c74fa591a0fd1655c0caa5f41eb9a5b6 (patch)
tree18c1cc9f3f1dc70265ba789e65d9f5da1b5be842
parent2191ed904f9301d25d16c8b462ab029a81810601 (diff)
downloadexternal-libdrm-2e4b9f08c74fa591a0fd1655c0caa5f41eb9a5b6.tar.gz
external-libdrm-2e4b9f08c74fa591a0fd1655c0caa5f41eb9a5b6.tar.xz
external-libdrm-2e4b9f08c74fa591a0fd1655c0caa5f41eb9a5b6.zip
tests/exynos: add fimg2d performance analysis
Currently only fast solid color clear performance is measured. A large buffer is allocated and solid color clear operations are executed on it with randomly chosen properties (position and size of the region, clear color). Execution time is measured and output together with the amount of pixels processed. The 'simple' variant only executes one G2D command buffer at a time, while the 'multi' variant executes multiple ones. This can be used to measure setup/exec overhead. The test also serves a stability check. If clocks/voltages are too high or low respectively, the test quickly reveals this. Tested-by: Hyungwon Hwang <human.hwang@samsung.com> Reviewed-by: Hyungwon Hwang <human.hwang@samsung.com> Signed-off-by: Tobias Jakobi <tjakobi@math.uni-bielefeld.de>
-rw-r--r--.gitignore1
-rw-r--r--tests/exynos/Makefile.am19
-rw-r--r--tests/exynos/exynos_fimg2d_perf.c327
3 files changed, 345 insertions, 2 deletions
diff --git a/.gitignore b/.gitignore
index a45e0afc..ddb37f1e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -95,5 +95,6 @@ tests/proptest/proptest
95tests/kmstest/kmstest 95tests/kmstest/kmstest
96tests/vbltest/vbltest 96tests/vbltest/vbltest
97tests/radeon/radeon_ttm 97tests/radeon/radeon_ttm
98tests/exynos/exynos_fimg2d_perf
98tests/exynos/exynos_fimg2d_test 99tests/exynos/exynos_fimg2d_test
99man/*.3 100man/*.3
diff --git a/tests/exynos/Makefile.am b/tests/exynos/Makefile.am
index b21d0169..e82d199a 100644
--- a/tests/exynos/Makefile.am
+++ b/tests/exynos/Makefile.am
@@ -5,16 +5,31 @@ AM_CFLAGS = \
5 -I $(top_srcdir)/exynos \ 5 -I $(top_srcdir)/exynos \
6 -I $(top_srcdir) 6 -I $(top_srcdir)
7 7
8bin_PROGRAMS =
9noinst_PROGRAMS =
10
8if HAVE_LIBKMS 11if HAVE_LIBKMS
9if HAVE_INSTALL_TESTS 12if HAVE_INSTALL_TESTS
10bin_PROGRAMS = \ 13bin_PROGRAMS += \
11 exynos_fimg2d_test 14 exynos_fimg2d_test
12else 15else
13noinst_PROGRAMS = \ 16noinst_PROGRAMS += \
14 exynos_fimg2d_test 17 exynos_fimg2d_test
15endif 18endif
16endif 19endif
17 20
21if HAVE_INSTALL_TESTS
22bin_PROGRAMS += \
23 exynos_fimg2d_perf
24else
25noinst_PROGRAMS += \
26 exynos_fimg2d_perf
27endif
28
29exynos_fimg2d_perf_LDADD = \
30 $(top_builddir)/libdrm.la \
31 $(top_builddir)/exynos/libdrm_exynos.la
32
18exynos_fimg2d_test_LDADD = \ 33exynos_fimg2d_test_LDADD = \
19 $(top_builddir)/libdrm.la \ 34 $(top_builddir)/libdrm.la \
20 $(top_builddir)/libkms/libkms.la \ 35 $(top_builddir)/libkms/libkms.la \
diff --git a/tests/exynos/exynos_fimg2d_perf.c b/tests/exynos/exynos_fimg2d_perf.c
new file mode 100644
index 00000000..1699bba7
--- /dev/null
+++ b/tests/exynos/exynos_fimg2d_perf.c
@@ -0,0 +1,327 @@
1/*
2 * Copyright (C) 2015 - Tobias Jakobi
3 *
4 * This is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published
6 * by the Free Software Foundation, either version 2 of the License,
7 * or (at your option) any later version.
8 *
9 * It is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with it. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include <stdlib.h>
18#include <stdio.h>
19#include <time.h>
20#include <getopt.h>
21#include <errno.h>
22
23#include <xf86drm.h>
24
25#include "exynos_drm.h"
26#include "exynos_drmif.h"
27#include "exynos_fimg2d.h"
28
29static int output_mathematica = 0;
30
31static int fimg2d_perf_simple(struct exynos_bo *bo, struct g2d_context *ctx,
32 unsigned buf_width, unsigned buf_height, unsigned iterations)
33{
34 struct timespec tspec = { 0 };
35 struct g2d_image img = { 0 };
36
37 unsigned long long g2d_time;
38 unsigned i;
39 int ret = 0;
40
41 img.width = buf_width;
42 img.height = buf_height;
43 img.stride = buf_width * 4;
44 img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
45 img.buf_type = G2D_IMGBUF_GEM;
46 img.bo[0] = bo->handle;
47
48 srand(time(NULL));
49
50 printf("starting simple G2D performance test\n");
51 printf("buffer width = %u, buffer height = %u, iterations = %u\n",
52 buf_width, buf_height, iterations);
53
54 if (output_mathematica)
55 putchar('{');
56
57 for (i = 0; i < iterations; ++i) {
58 unsigned x, y, w, h;
59
60 x = rand() % buf_width;
61 y = rand() % buf_height;
62
63 if (x == (buf_width - 1))
64 x -= 1;
65 if (y == (buf_height - 1))
66 y -= 1;
67
68 w = rand() % (buf_width - x);
69 h = rand() % (buf_height - y);
70
71 if (w == 0) w = 1;
72 if (h == 0) h = 1;
73
74 img.color = rand();
75
76 ret = g2d_solid_fill(ctx, &img, x, y, w, h);
77
78 clock_gettime(CLOCK_MONOTONIC, &tspec);
79
80 if (ret == 0)
81 ret = g2d_exec(ctx);
82
83 if (ret != 0) {
84 fprintf(stderr, "error: iteration %u failed (x = %u, y = %u, w = %u, h = %u)\n",
85 i, x, y, w, h);
86 break;
87 } else {
88 struct timespec end = { 0 };
89 clock_gettime(CLOCK_MONOTONIC, &end);
90
91 g2d_time = (end.tv_sec - tspec.tv_sec) * 1000000000ULL;
92 g2d_time += (end.tv_nsec - tspec.tv_nsec);
93
94 if (output_mathematica) {
95 if (i != 0) putchar(',');
96 printf("{%u,%llu}", w * h, g2d_time);
97 } else {
98 printf("num_pixels = %u, usecs = %llu\n", w * h, g2d_time);
99 }
100 }
101 }
102
103 if (output_mathematica)
104 printf("}\n");
105
106 return ret;
107}
108
109static int fimg2d_perf_multi(struct exynos_bo *bo, struct g2d_context *ctx,
110 unsigned buf_width, unsigned buf_height, unsigned iterations, unsigned batch)
111{
112 struct timespec tspec = { 0 };
113 struct g2d_image *images;
114
115 unsigned long long g2d_time;
116 unsigned i, j;
117 int ret = 0;
118
119 images = calloc(batch, sizeof(struct g2d_image));
120 if (images == NULL) {
121 fprintf(stderr, "error: failed to allocate G2D images.\n");
122 return -ENOMEM;
123 }
124
125 for (i = 0; i < batch; ++i) {
126 images[i].width = buf_width;
127 images[i].height = buf_height;
128 images[i].stride = buf_width * 4;
129 images[i].color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
130 images[i].buf_type = G2D_IMGBUF_GEM;
131 images[i].bo[0] = bo->handle;
132 }
133
134 srand(time(NULL));
135
136 printf("starting multi G2D performance test (batch size = %u)\n", batch);
137 printf("buffer width = %u, buffer height = %u, iterations = %u\n",
138 buf_width, buf_height, iterations);
139
140 if (output_mathematica)
141 putchar('{');
142
143 for (i = 0; i < iterations; ++i) {
144 unsigned num_pixels = 0;
145
146 for (j = 0; j < batch; ++j) {
147 unsigned x, y, w, h;
148
149 x = rand() % buf_width;
150 y = rand() % buf_height;
151
152 if (x == (buf_width - 1))
153 x -= 1;
154 if (y == (buf_height - 1))
155 y -= 1;
156
157 w = rand() % (buf_width - x);
158 h = rand() % (buf_height - y);
159
160 if (w == 0) w = 1;
161 if (h == 0) h = 1;
162
163 images[j].color = rand();
164
165 num_pixels += w * h;
166
167 ret = g2d_solid_fill(ctx, &images[j], x, y, w, h);
168 if (ret != 0)
169 break;
170 }
171
172 clock_gettime(CLOCK_MONOTONIC, &tspec);
173
174 if (ret == 0)
175 ret = g2d_exec(ctx);
176
177 if (ret != 0) {
178 fprintf(stderr, "error: iteration %u failed (num_pixels = %u)\n", i, num_pixels);
179 break;
180 } else {
181 struct timespec end = { 0 };
182 clock_gettime(CLOCK_MONOTONIC, &end);
183
184 g2d_time = (end.tv_sec - tspec.tv_sec) * 1000000000ULL;
185 g2d_time += (end.tv_nsec - tspec.tv_nsec);
186
187 if (output_mathematica) {
188 if (i != 0) putchar(',');
189 printf("{%u,%llu}", num_pixels, g2d_time);
190 } else {
191 printf("num_pixels = %u, usecs = %llu\n", num_pixels, g2d_time);
192 }
193 }
194 }
195
196 if (output_mathematica)
197 printf("}\n");
198
199 free(images);
200
201 return ret;
202}
203
204static void usage(const char *name)
205{
206 fprintf(stderr, "usage: %s [-ibwh]\n\n", name);
207
208 fprintf(stderr, "\t-i <number of iterations>\n");
209 fprintf(stderr, "\t-b <size of a batch> (default = 3)\n\n");
210
211 fprintf(stderr, "\t-w <buffer width> (default = 4096)\n");
212 fprintf(stderr, "\t-h <buffer height> (default = 4096)\n\n");
213
214 fprintf(stderr, "\t-M <enable Mathematica styled output>\n");
215
216 exit(0);
217}
218
219int main(int argc, char **argv)
220{
221 int fd, ret, c, parsefail;
222
223 struct exynos_device *dev;
224 struct g2d_context *ctx;
225 struct exynos_bo *bo;
226
227 unsigned int iters = 0, batch = 3;
228 unsigned int bufw = 4096, bufh = 4096;
229
230 ret = 0;
231 parsefail = 0;
232
233 while ((c = getopt(argc, argv, "i:b:w:h:M")) != -1) {
234 switch (c) {
235 case 'i':
236 if (sscanf(optarg, "%u", &iters) != 1)
237 parsefail = 1;
238 break;
239 case 'b':
240 if (sscanf(optarg, "%u", &batch) != 1)
241 parsefail = 1;
242 break;
243 case 'w':
244 if (sscanf(optarg, "%u", &bufw) != 1)
245 parsefail = 1;
246 break;
247 case 'h':
248 if (sscanf(optarg, "%u", &bufh) != 1)
249 parsefail = 1;
250 break;
251 case 'M':
252 output_mathematica = 1;
253 break;
254 default:
255 parsefail = 1;
256 break;
257 }
258 }
259
260 if (parsefail || (argc == 1) || (iters == 0))
261 usage(argv[0]);
262
263 if (bufw < 2 || bufw > 4096 || bufh < 2 || bufh > 4096) {
264 fprintf(stderr, "error: buffer width/height should be in the range 2 to 4096.\n");
265 ret = -1;
266
267 goto out;
268 }
269
270 if (bufw == 0 || bufh == 0) {
271 fprintf(stderr, "error: buffer width/height should be non-zero.\n");
272 ret = -1;
273
274 goto out;
275 }
276
277 fd = drmOpen("exynos", NULL);
278 if (fd < 0) {
279 fprintf(stderr, "error: failed to open drm\n");
280 ret = -1;
281
282 goto out;
283 }
284
285 dev = exynos_device_create(fd);
286 if (dev == NULL) {
287 fprintf(stderr, "error: failed to create device\n");
288 ret = -2;
289
290 goto fail;
291 }
292
293 ctx = g2d_init(fd);
294 if (ctx == NULL) {
295 fprintf(stderr, "error: failed to init G2D\n");
296 ret = -3;
297
298 goto g2d_fail;
299 }
300
301 bo = exynos_bo_create(dev, bufw * bufh * 4, 0);
302 if (bo == NULL) {
303 fprintf(stderr, "error: failed to create bo\n");
304 ret = -4;
305
306 goto bo_fail;
307 }
308
309 ret = fimg2d_perf_simple(bo, ctx, bufw, bufh, iters);
310
311 if (ret == 0)
312 ret = fimg2d_perf_multi(bo, ctx, bufw, bufh, iters, batch);
313
314 exynos_bo_destroy(bo);
315
316bo_fail:
317 g2d_fini(ctx);
318
319g2d_fail:
320 exynos_device_destroy(dev);
321
322fail:
323 drmClose(fd);
324
325out:
326 return ret;
327}