blob: 40e2e478b55215216cef540443878e66a090d24b [file] [log] [blame]
Chris Wilson38b3bd62015-08-11 12:57:38 +01001/*
2 * Copyright © 2012 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/* Exercises the basic execbuffer using the handle LUT interface */
29
30#include <stdlib.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/time.h>
38#include "drm.h"
39#include "ioctl_wrappers.h"
40#include "igt_debugfs.h"
41#include "drmtest.h"
42
43#define LOCAL_I915_EXEC_NO_RELOC (1<<11)
44#define LOCAL_I915_EXEC_HANDLE_LUT (1<<12)
45
46#define SKIP_RELOC 0x1
47#define NO_RELOC 0x2
48#define CYCLE_BATCH 0x4
49#define FAULT 0x8
50#define LUT 0x10
51#define SEQUENTIAL_OFFSET 0x20
52#define REVERSE_OFFSET 0x40
53#define RANDOM_OFFSET 0x80
54
55static uint32_t
56hars_petruska_f54_1_random (void)
57{
58 static uint32_t state = 0x12345678;
59
60#define rol(x,k) ((x << k) | (x >> (32-k)))
61 return state = (state ^ rol (state, 5) ^ rol (state, 24)) + 0x37798849;
62#undef rol
63}
64
65#define ELAPSED(a,b) (1e6*((b)->tv_sec - (a)->tv_sec) + ((b)->tv_usec - (a)->tv_usec))
66static int run(unsigned batch_size,
67 unsigned flags,
68 int num_objects,
69 int num_relocs, int reps)
70{
71 uint32_t batch[2] = {MI_BATCH_BUFFER_END};
72 uint32_t cycle[16];
Chris Wilson5e68ad92015-08-21 22:26:42 +010073 int fd, n, count, c, size = 0;
74 struct drm_i915_gem_relocation_entry *reloc = NULL;
Chris Wilson38b3bd62015-08-11 12:57:38 +010075 struct drm_i915_gem_execbuffer2 execbuf;
76 struct drm_i915_gem_exec_object2 *objects;
77 struct timeval start, end;
Chris Wilson5e68ad92015-08-21 22:26:42 +010078 uint32_t reloc_handle = 0;
Chris Wilson38b3bd62015-08-11 12:57:38 +010079 struct drm_i915_gem_exec_object2 *gem_exec;
Chris Wilson5e68ad92015-08-21 22:26:42 +010080 struct drm_i915_gem_relocation_entry *mem_reloc = NULL;
Chris Wilson38b3bd62015-08-11 12:57:38 +010081 int *target;
82
83 gem_exec = calloc(sizeof(*gem_exec), num_objects + 1);
84 mem_reloc = calloc(sizeof(*mem_reloc), num_relocs);
85 target = calloc(sizeof(*target), num_relocs);
86
Micah Fedkec81d2932015-07-22 21:54:02 +000087 fd = drm_open_driver(DRIVER_INTEL);
Chris Wilson38b3bd62015-08-11 12:57:38 +010088
89 for (n = 0; n < num_objects; n++)
90 gem_exec[n].handle = gem_create(fd, 4096);
91
92 for (n = 0; n < 16; n++) {
93 cycle[n] = gem_create(fd, batch_size);
94 gem_write(fd, cycle[n], 0, batch, sizeof(batch));
95 }
96 gem_exec[num_objects].handle = cycle[c = 0];
97
98 for (n = 0; n < num_relocs; n++) {
99 mem_reloc[n].offset = 1024;
100 mem_reloc[n].read_domains = I915_GEM_DOMAIN_RENDER;
101 }
102 for (n = 0; n < num_relocs; n++) {
103 if (flags & SEQUENTIAL_OFFSET)
104 mem_reloc[n].offset = 8 + (8*n % (batch_size - 16));
105 else if (flags & REVERSE_OFFSET)
106 mem_reloc[n].offset = batch_size - 8 - (8*n % (batch_size - 16));
107 else if (flags & RANDOM_OFFSET)
108 mem_reloc[n].offset = 8 +
109 8*hars_petruska_f54_1_random() % (batch_size - 16);
110 else
111 mem_reloc[n].offset = 1024;
112 mem_reloc[n].read_domains = I915_GEM_DOMAIN_RENDER;
113 }
114
Chris Wilson5e68ad92015-08-21 22:26:42 +0100115 if (num_relocs) {
116 size = ALIGN(sizeof(*mem_reloc)*num_relocs, 4096);
117 reloc_handle = gem_create(fd, size);
Ville Syrjäläb8a77dd2015-10-09 18:29:28 +0300118 reloc = __gem_mmap__cpu(fd, reloc_handle, 0, size, PROT_READ | PROT_WRITE);
Chris Wilson5e68ad92015-08-21 22:26:42 +0100119 memcpy(reloc, mem_reloc, sizeof(*mem_reloc)*num_relocs);
120 munmap(reloc, size);
121
122 if (flags & FAULT) {
123 igt_disable_prefault();
Ville Syrjäläb8a77dd2015-10-09 18:29:28 +0300124 reloc = __gem_mmap__cpu(fd, reloc_handle, 0, size, PROT_READ | PROT_WRITE);
Chris Wilson5e68ad92015-08-21 22:26:42 +0100125 } else
126 reloc = mem_reloc;
127 }
Chris Wilson38b3bd62015-08-11 12:57:38 +0100128
129 gem_exec[num_objects].relocation_count = num_relocs;
130 gem_exec[num_objects].relocs_ptr = (uintptr_t)reloc;
131 objects = gem_exec;
132
133 memset(&execbuf, 0, sizeof(execbuf));
134 execbuf.buffers_ptr = (uintptr_t)objects;
135 execbuf.buffer_count = num_objects + 1;
136 if (flags & LUT)
137 execbuf.flags |= LOCAL_I915_EXEC_HANDLE_LUT;
138 if (flags & NO_RELOC)
139 execbuf.flags |= LOCAL_I915_EXEC_NO_RELOC;
140
141 for (n = 0; n < num_relocs; n++) {
142 target[n] = hars_petruska_f54_1_random() % num_objects;
143 if (flags & LUT)
144 reloc[n].target_handle = target[n];
145 else
146 reloc[n].target_handle = objects[target[n]].handle;
Chris Wilson7bd2ac62016-04-16 17:15:38 +0100147 reloc[n].presumed_offset = -1;
Chris Wilson38b3bd62015-08-11 12:57:38 +0100148 }
149
150 gem_execbuf(fd, &execbuf);
151
152 while (reps--) {
153 gettimeofday(&start, NULL);
154 for (count = 0; count < 1000; count++) {
155 if ((flags & SKIP_RELOC) == 0) {
156 for (n = 0; n < num_relocs; n++)
Chris Wilson7bd2ac62016-04-16 17:15:38 +0100157 reloc[n].presumed_offset = -1;
Chris Wilson38b3bd62015-08-11 12:57:38 +0100158 if (flags & CYCLE_BATCH) {
159 c = (c + 1) % 16;
160 gem_exec[num_objects].handle = cycle[c];
161 }
162 }
Chris Wilson5e68ad92015-08-21 22:26:42 +0100163 if (flags & FAULT && reloc) {
Chris Wilson38b3bd62015-08-11 12:57:38 +0100164 munmap(reloc, size);
Ville Syrjäläb8a77dd2015-10-09 18:29:28 +0300165 reloc = __gem_mmap__cpu(fd, reloc_handle, 0, size, PROT_READ | PROT_WRITE);
Chris Wilson38b3bd62015-08-11 12:57:38 +0100166 gem_exec[num_objects].relocs_ptr = (uintptr_t)reloc;
167 }
168 gem_execbuf(fd, &execbuf);
169 }
170 gettimeofday(&end, NULL);
171 printf("%.3f\n", ELAPSED(&start, &end));
172 }
173
Chris Wilson5e68ad92015-08-21 22:26:42 +0100174 if (flags & FAULT && reloc) {
Chris Wilson38b3bd62015-08-11 12:57:38 +0100175 munmap(reloc, size);
176 igt_enable_prefault();
177 }
178
179 return 0;
180}
181
182int main(int argc, char **argv)
183{
184 unsigned num_objects = 1, num_relocs = 0, flags = 0;
185 unsigned size = 4096;
186 int reps = 13;
187 int c;
188
189 while ((c = getopt (argc, argv, "b:r:s:e:l:m:o:")) != -1) {
190 switch (c) {
191 case 'l':
192 reps = atoi(optarg);
193 if (reps < 1)
194 reps = 1;
195 break;
196
197 case 's':
198 size = atoi(optarg);
199 if (size < 4096)
200 size = 4096;
201 size = ALIGN(size, 4096);
202 break;
203
204 case 'e':
205 if (strcmp(optarg, "busy") == 0) {
206 flags |= 0;
207 } else if (strcmp(optarg, "cyclic") == 0) {
208 flags |= CYCLE_BATCH;
209 } else if (strcmp(optarg, "fault") == 0) {
210 flags |= FAULT;
211 } else if (strcmp(optarg, "skip") == 0) {
212 flags |= SKIP_RELOC;
213 } else if (strcmp(optarg, "none") == 0) {
214 flags |= SKIP_RELOC | NO_RELOC;
215 } else {
216 abort();
217 }
218 break;
219
220 case 'm':
221 if (strcmp(optarg, "old") == 0) {
222 flags |= 0;
223 } else if (strcmp(optarg, "lut") == 0) {
224 flags |= LUT;
225 } else {
226 abort();
227 }
228 break;
229
230 case 'o':
231 if (strcmp(optarg, "constant") == 0) {
232 flags |= 0;
233 } else if (strcmp(optarg, "sequential") == 0) {
234 flags |= SEQUENTIAL_OFFSET;
235 } else if (strcmp(optarg, "reverse") == 0) {
236 flags |= REVERSE_OFFSET;
237 } else if (strcmp(optarg, "random") == 0) {
238 flags |= RANDOM_OFFSET;
239 } else {
240 abort();
241 }
242 break;
243
244 case 'b':
245 num_objects = atoi(optarg);
246 if (num_objects < 1)
247 num_objects = 1;
248 break;
249
250 case 'r':
251 num_relocs = atoi(optarg);
Chris Wilson38b3bd62015-08-11 12:57:38 +0100252 break;
253 }
254 }
255
256 return run(size, flags, num_objects, num_relocs, reps);
257}