xref: /aosp_15_r20/external/igt-gpu-tools/tests/i915/gem_fence_upload.c (revision d83cc019efdc2edc6c4b16e9034a3ceb8d35d77c)
1*d83cc019SAndroid Build Coastguard Worker /*
2*d83cc019SAndroid Build Coastguard Worker  * Copyright © 2014 Intel Corporation
3*d83cc019SAndroid Build Coastguard Worker  *
4*d83cc019SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
5*d83cc019SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
6*d83cc019SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
7*d83cc019SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*d83cc019SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
9*d83cc019SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
10*d83cc019SAndroid Build Coastguard Worker  *
11*d83cc019SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
12*d83cc019SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
13*d83cc019SAndroid Build Coastguard Worker  * Software.
14*d83cc019SAndroid Build Coastguard Worker  *
15*d83cc019SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*d83cc019SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*d83cc019SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18*d83cc019SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*d83cc019SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*d83cc019SAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21*d83cc019SAndroid Build Coastguard Worker  * IN THE SOFTWARE.
22*d83cc019SAndroid Build Coastguard Worker  *
23*d83cc019SAndroid Build Coastguard Worker  * Authors:
24*d83cc019SAndroid Build Coastguard Worker  *    Chris Wilson <[email protected]>
25*d83cc019SAndroid Build Coastguard Worker  *
26*d83cc019SAndroid Build Coastguard Worker  */
27*d83cc019SAndroid Build Coastguard Worker 
28*d83cc019SAndroid Build Coastguard Worker #include "config.h"
29*d83cc019SAndroid Build Coastguard Worker 
30*d83cc019SAndroid Build Coastguard Worker #include "igt.h"
31*d83cc019SAndroid Build Coastguard Worker #include <unistd.h>
32*d83cc019SAndroid Build Coastguard Worker #include <stdlib.h>
33*d83cc019SAndroid Build Coastguard Worker #include <stdio.h>
34*d83cc019SAndroid Build Coastguard Worker #include <string.h>
35*d83cc019SAndroid Build Coastguard Worker #include <fcntl.h>
36*d83cc019SAndroid Build Coastguard Worker #include <inttypes.h>
37*d83cc019SAndroid Build Coastguard Worker #include <errno.h>
38*d83cc019SAndroid Build Coastguard Worker #include <sys/time.h>
39*d83cc019SAndroid Build Coastguard Worker #include <pthread.h>
40*d83cc019SAndroid Build Coastguard Worker #include "drm.h"
41*d83cc019SAndroid Build Coastguard Worker #include "i915_drm.h"
42*d83cc019SAndroid Build Coastguard Worker 
43*d83cc019SAndroid Build Coastguard Worker #define OBJECT_SIZE (1024*1024) /* restricted to 1MiB alignment on i915 fences */
44*d83cc019SAndroid Build Coastguard Worker 
elapsed(const struct timeval * start,const struct timeval * end)45*d83cc019SAndroid Build Coastguard Worker static double elapsed(const struct timeval *start,
46*d83cc019SAndroid Build Coastguard Worker 		      const struct timeval *end)
47*d83cc019SAndroid Build Coastguard Worker {
48*d83cc019SAndroid Build Coastguard Worker 	return (end->tv_sec - start->tv_sec) + 1e-6*(end->tv_usec - start->tv_usec);
49*d83cc019SAndroid Build Coastguard Worker }
50*d83cc019SAndroid Build Coastguard Worker 
performance(void)51*d83cc019SAndroid Build Coastguard Worker static void performance(void)
52*d83cc019SAndroid Build Coastguard Worker {
53*d83cc019SAndroid Build Coastguard Worker 	int n, loop, count;
54*d83cc019SAndroid Build Coastguard Worker 	int fd, num_fences;
55*d83cc019SAndroid Build Coastguard Worker 	double linear[2], tiled[2];
56*d83cc019SAndroid Build Coastguard Worker 
57*d83cc019SAndroid Build Coastguard Worker 	fd = drm_open_driver(DRIVER_INTEL);
58*d83cc019SAndroid Build Coastguard Worker 
59*d83cc019SAndroid Build Coastguard Worker 	num_fences = gem_available_fences(fd);
60*d83cc019SAndroid Build Coastguard Worker 	igt_require(num_fences > 0);
61*d83cc019SAndroid Build Coastguard Worker 
62*d83cc019SAndroid Build Coastguard Worker 	for (count = 2; count < 4*num_fences; count *= 2) {
63*d83cc019SAndroid Build Coastguard Worker 		struct timeval start, end;
64*d83cc019SAndroid Build Coastguard Worker 		uint32_t handle[count];
65*d83cc019SAndroid Build Coastguard Worker 		void *ptr[count];
66*d83cc019SAndroid Build Coastguard Worker 
67*d83cc019SAndroid Build Coastguard Worker 		for (n = 0; n < count; n++) {
68*d83cc019SAndroid Build Coastguard Worker 			handle[n] = gem_create(fd, OBJECT_SIZE);
69*d83cc019SAndroid Build Coastguard Worker 			ptr[n] = gem_mmap__gtt(fd, handle[n], OBJECT_SIZE, PROT_READ | PROT_WRITE);
70*d83cc019SAndroid Build Coastguard Worker 		}
71*d83cc019SAndroid Build Coastguard Worker 
72*d83cc019SAndroid Build Coastguard Worker 		gettimeofday(&start, NULL);
73*d83cc019SAndroid Build Coastguard Worker 		for (loop = 0; loop < 1024; loop++) {
74*d83cc019SAndroid Build Coastguard Worker 			for (n = 0; n < count; n++)
75*d83cc019SAndroid Build Coastguard Worker 				memset(ptr[n], 0, OBJECT_SIZE);
76*d83cc019SAndroid Build Coastguard Worker 		}
77*d83cc019SAndroid Build Coastguard Worker 		gettimeofday(&end, NULL);
78*d83cc019SAndroid Build Coastguard Worker 
79*d83cc019SAndroid Build Coastguard Worker 		linear[count != 2] = count * loop / elapsed(&start, &end);
80*d83cc019SAndroid Build Coastguard Worker 		igt_info("Upload rate for %d linear surfaces:	%7.3fMiB/s\n", count, linear[count != 2]);
81*d83cc019SAndroid Build Coastguard Worker 
82*d83cc019SAndroid Build Coastguard Worker 		for (n = 0; n < count; n++)
83*d83cc019SAndroid Build Coastguard Worker 			gem_set_tiling(fd, handle[n], I915_TILING_X, 1024);
84*d83cc019SAndroid Build Coastguard Worker 
85*d83cc019SAndroid Build Coastguard Worker 		gettimeofday(&start, NULL);
86*d83cc019SAndroid Build Coastguard Worker 		for (loop = 0; loop < 1024; loop++) {
87*d83cc019SAndroid Build Coastguard Worker 			for (n = 0; n < count; n++)
88*d83cc019SAndroid Build Coastguard Worker 				memset(ptr[n], 0, OBJECT_SIZE);
89*d83cc019SAndroid Build Coastguard Worker 		}
90*d83cc019SAndroid Build Coastguard Worker 		gettimeofday(&end, NULL);
91*d83cc019SAndroid Build Coastguard Worker 
92*d83cc019SAndroid Build Coastguard Worker 		tiled[count != 2] = count * loop / elapsed(&start, &end);
93*d83cc019SAndroid Build Coastguard Worker 		igt_info("Upload rate for %d tiled surfaces:	%7.3fMiB/s\n", count, tiled[count != 2]);
94*d83cc019SAndroid Build Coastguard Worker 
95*d83cc019SAndroid Build Coastguard Worker 		for (n = 0; n < count; n++) {
96*d83cc019SAndroid Build Coastguard Worker 			munmap(ptr[n], OBJECT_SIZE);
97*d83cc019SAndroid Build Coastguard Worker 			gem_close(fd, handle[n]);
98*d83cc019SAndroid Build Coastguard Worker 		}
99*d83cc019SAndroid Build Coastguard Worker 
100*d83cc019SAndroid Build Coastguard Worker 	}
101*d83cc019SAndroid Build Coastguard Worker 
102*d83cc019SAndroid Build Coastguard Worker 	errno = 0;
103*d83cc019SAndroid Build Coastguard Worker 	igt_assert(linear[1] > 0.75 * linear[0]);
104*d83cc019SAndroid Build Coastguard Worker 	igt_assert(tiled[1] > 0.75 * tiled[0]);
105*d83cc019SAndroid Build Coastguard Worker }
106*d83cc019SAndroid Build Coastguard Worker 
107*d83cc019SAndroid Build Coastguard Worker struct thread_performance {
108*d83cc019SAndroid Build Coastguard Worker 	pthread_t thread;
109*d83cc019SAndroid Build Coastguard Worker 	int id, count, direction, loops;
110*d83cc019SAndroid Build Coastguard Worker 	void **ptr;
111*d83cc019SAndroid Build Coastguard Worker };
112*d83cc019SAndroid Build Coastguard Worker 
read_thread_performance(void * closure)113*d83cc019SAndroid Build Coastguard Worker static void *read_thread_performance(void *closure)
114*d83cc019SAndroid Build Coastguard Worker {
115*d83cc019SAndroid Build Coastguard Worker 	struct thread_performance *t = closure;
116*d83cc019SAndroid Build Coastguard Worker 	uint32_t x = 0;
117*d83cc019SAndroid Build Coastguard Worker 	int n, m;
118*d83cc019SAndroid Build Coastguard Worker 
119*d83cc019SAndroid Build Coastguard Worker 	for (n = 0; n < t->loops; n++) {
120*d83cc019SAndroid Build Coastguard Worker 		uint32_t *src = t->ptr[rand() % t->count];
121*d83cc019SAndroid Build Coastguard Worker 		src += (rand() % 256) * 4096 / 4;
122*d83cc019SAndroid Build Coastguard Worker 		for (m = 0; m < 4096/4; m++)
123*d83cc019SAndroid Build Coastguard Worker 			x += src[m];
124*d83cc019SAndroid Build Coastguard Worker 	}
125*d83cc019SAndroid Build Coastguard Worker 
126*d83cc019SAndroid Build Coastguard Worker 	return (void *)(uintptr_t)x;
127*d83cc019SAndroid Build Coastguard Worker }
128*d83cc019SAndroid Build Coastguard Worker 
write_thread_performance(void * closure)129*d83cc019SAndroid Build Coastguard Worker static void *write_thread_performance(void *closure)
130*d83cc019SAndroid Build Coastguard Worker {
131*d83cc019SAndroid Build Coastguard Worker 	struct thread_performance *t = closure;
132*d83cc019SAndroid Build Coastguard Worker 	int n;
133*d83cc019SAndroid Build Coastguard Worker 
134*d83cc019SAndroid Build Coastguard Worker 	for (n = 0; n < t->loops; n++) {
135*d83cc019SAndroid Build Coastguard Worker 		uint32_t *dst = t->ptr[rand() % t->count];
136*d83cc019SAndroid Build Coastguard Worker 		dst += (rand() % 256) * 4096 / 4;
137*d83cc019SAndroid Build Coastguard Worker 		memset(dst, 0, 4096);
138*d83cc019SAndroid Build Coastguard Worker 	}
139*d83cc019SAndroid Build Coastguard Worker 
140*d83cc019SAndroid Build Coastguard Worker 	return NULL;
141*d83cc019SAndroid Build Coastguard Worker }
142*d83cc019SAndroid Build Coastguard Worker 
143*d83cc019SAndroid Build Coastguard Worker #define READ (1<<0)
144*d83cc019SAndroid Build Coastguard Worker #define WRITE (1<<1)
direction_string(unsigned mask)145*d83cc019SAndroid Build Coastguard Worker static const char *direction_string(unsigned mask)
146*d83cc019SAndroid Build Coastguard Worker {
147*d83cc019SAndroid Build Coastguard Worker 	switch (mask) {
148*d83cc019SAndroid Build Coastguard Worker 	case READ: return "Download";
149*d83cc019SAndroid Build Coastguard Worker 	case WRITE: return "Upload";
150*d83cc019SAndroid Build Coastguard Worker 	case READ | WRITE: return "Combined";
151*d83cc019SAndroid Build Coastguard Worker 	default: return "Unknown";
152*d83cc019SAndroid Build Coastguard Worker 	}
153*d83cc019SAndroid Build Coastguard Worker }
thread_performance(unsigned mask)154*d83cc019SAndroid Build Coastguard Worker static void thread_performance(unsigned mask)
155*d83cc019SAndroid Build Coastguard Worker {
156*d83cc019SAndroid Build Coastguard Worker 	const int loops = 4096;
157*d83cc019SAndroid Build Coastguard Worker 	int n, count;
158*d83cc019SAndroid Build Coastguard Worker 	int fd, num_fences;
159*d83cc019SAndroid Build Coastguard Worker 	double linear[2], tiled[2];
160*d83cc019SAndroid Build Coastguard Worker 
161*d83cc019SAndroid Build Coastguard Worker 	fd = drm_open_driver(DRIVER_INTEL);
162*d83cc019SAndroid Build Coastguard Worker 
163*d83cc019SAndroid Build Coastguard Worker 	num_fences = gem_available_fences(fd);
164*d83cc019SAndroid Build Coastguard Worker 	igt_require(num_fences > 0);
165*d83cc019SAndroid Build Coastguard Worker 
166*d83cc019SAndroid Build Coastguard Worker 	for (count = 2; count < 4*num_fences; count *= 2) {
167*d83cc019SAndroid Build Coastguard Worker 		const int nthreads = (mask & READ ? count : 0) + (mask & WRITE ? count : 0);
168*d83cc019SAndroid Build Coastguard Worker 		struct timeval start, end;
169*d83cc019SAndroid Build Coastguard Worker 		struct thread_performance readers[count];
170*d83cc019SAndroid Build Coastguard Worker 		struct thread_performance writers[count];
171*d83cc019SAndroid Build Coastguard Worker 		uint32_t handle[count];
172*d83cc019SAndroid Build Coastguard Worker 		void *ptr[count];
173*d83cc019SAndroid Build Coastguard Worker 
174*d83cc019SAndroid Build Coastguard Worker 		for (n = 0; n < count; n++) {
175*d83cc019SAndroid Build Coastguard Worker 			handle[n] = gem_create(fd, OBJECT_SIZE);
176*d83cc019SAndroid Build Coastguard Worker 			ptr[n] = gem_mmap__gtt(fd, handle[n], OBJECT_SIZE, PROT_READ | PROT_WRITE);
177*d83cc019SAndroid Build Coastguard Worker 
178*d83cc019SAndroid Build Coastguard Worker 			if (mask & READ) {
179*d83cc019SAndroid Build Coastguard Worker 				readers[n].id = n;
180*d83cc019SAndroid Build Coastguard Worker 				readers[n].direction = READ;
181*d83cc019SAndroid Build Coastguard Worker 				readers[n].ptr = ptr;
182*d83cc019SAndroid Build Coastguard Worker 				readers[n].count = count;
183*d83cc019SAndroid Build Coastguard Worker 				readers[n].loops = loops;
184*d83cc019SAndroid Build Coastguard Worker 			}
185*d83cc019SAndroid Build Coastguard Worker 
186*d83cc019SAndroid Build Coastguard Worker 			if (mask & WRITE) {
187*d83cc019SAndroid Build Coastguard Worker 				writers[n].id = count - n - 1;
188*d83cc019SAndroid Build Coastguard Worker 				writers[n].direction = WRITE;
189*d83cc019SAndroid Build Coastguard Worker 				writers[n].ptr = ptr;
190*d83cc019SAndroid Build Coastguard Worker 				writers[n].count = count;
191*d83cc019SAndroid Build Coastguard Worker 				writers[n].loops = loops;
192*d83cc019SAndroid Build Coastguard Worker 			}
193*d83cc019SAndroid Build Coastguard Worker 		}
194*d83cc019SAndroid Build Coastguard Worker 
195*d83cc019SAndroid Build Coastguard Worker 		gettimeofday(&start, NULL);
196*d83cc019SAndroid Build Coastguard Worker 		for (n = 0; n < count; n++) {
197*d83cc019SAndroid Build Coastguard Worker 			if (mask & READ)
198*d83cc019SAndroid Build Coastguard Worker 				pthread_create(&readers[n].thread, NULL, read_thread_performance, &readers[n]);
199*d83cc019SAndroid Build Coastguard Worker 			if (mask & WRITE)
200*d83cc019SAndroid Build Coastguard Worker 				pthread_create(&writers[n].thread, NULL, write_thread_performance, &writers[n]);
201*d83cc019SAndroid Build Coastguard Worker 		}
202*d83cc019SAndroid Build Coastguard Worker 		for (n = 0; n < count; n++) {
203*d83cc019SAndroid Build Coastguard Worker 			if (mask & READ)
204*d83cc019SAndroid Build Coastguard Worker 				pthread_join(readers[n].thread, NULL);
205*d83cc019SAndroid Build Coastguard Worker 			if (mask & WRITE)
206*d83cc019SAndroid Build Coastguard Worker 				pthread_join(writers[n].thread, NULL);
207*d83cc019SAndroid Build Coastguard Worker 		}
208*d83cc019SAndroid Build Coastguard Worker 		gettimeofday(&end, NULL);
209*d83cc019SAndroid Build Coastguard Worker 
210*d83cc019SAndroid Build Coastguard Worker 		linear[count != 2] = nthreads * loops / elapsed(&start, &end) / (OBJECT_SIZE / 4096);
211*d83cc019SAndroid Build Coastguard Worker 		igt_info("%s rate for %d linear surfaces, %d threads:	%7.3fMiB/s\n", direction_string(mask), count, nthreads, linear[count != 2]);
212*d83cc019SAndroid Build Coastguard Worker 
213*d83cc019SAndroid Build Coastguard Worker 		for (n = 0; n < count; n++)
214*d83cc019SAndroid Build Coastguard Worker 			gem_set_tiling(fd, handle[n], I915_TILING_X, 1024);
215*d83cc019SAndroid Build Coastguard Worker 
216*d83cc019SAndroid Build Coastguard Worker 		gettimeofday(&start, NULL);
217*d83cc019SAndroid Build Coastguard Worker 		for (n = 0; n < count; n++) {
218*d83cc019SAndroid Build Coastguard Worker 			if (mask & READ)
219*d83cc019SAndroid Build Coastguard Worker 				pthread_create(&readers[n].thread, NULL, read_thread_performance, &readers[n]);
220*d83cc019SAndroid Build Coastguard Worker 			if (mask & WRITE)
221*d83cc019SAndroid Build Coastguard Worker 				pthread_create(&writers[n].thread, NULL, write_thread_performance, &writers[n]);
222*d83cc019SAndroid Build Coastguard Worker 		}
223*d83cc019SAndroid Build Coastguard Worker 		for (n = 0; n < count; n++) {
224*d83cc019SAndroid Build Coastguard Worker 			if (mask & READ)
225*d83cc019SAndroid Build Coastguard Worker 				pthread_join(readers[n].thread, NULL);
226*d83cc019SAndroid Build Coastguard Worker 			if (mask & WRITE)
227*d83cc019SAndroid Build Coastguard Worker 				pthread_join(writers[n].thread, NULL);
228*d83cc019SAndroid Build Coastguard Worker 		}
229*d83cc019SAndroid Build Coastguard Worker 		gettimeofday(&end, NULL);
230*d83cc019SAndroid Build Coastguard Worker 
231*d83cc019SAndroid Build Coastguard Worker 		tiled[count != 2] = nthreads * loops / elapsed(&start, &end) / (OBJECT_SIZE / 4096);
232*d83cc019SAndroid Build Coastguard Worker 		igt_info("%s rate for %d tiled surfaces, %d threads:	%7.3fMiB/s\n", direction_string(mask), count, nthreads, tiled[count != 2]);
233*d83cc019SAndroid Build Coastguard Worker 
234*d83cc019SAndroid Build Coastguard Worker 		for (n = 0; n < count; n++) {
235*d83cc019SAndroid Build Coastguard Worker 			munmap(ptr[n], OBJECT_SIZE);
236*d83cc019SAndroid Build Coastguard Worker 			gem_close(fd, handle[n]);
237*d83cc019SAndroid Build Coastguard Worker 		}
238*d83cc019SAndroid Build Coastguard Worker 	}
239*d83cc019SAndroid Build Coastguard Worker 
240*d83cc019SAndroid Build Coastguard Worker 	errno = 0;
241*d83cc019SAndroid Build Coastguard Worker 	igt_assert(linear[1] > 0.75 * linear[0]);
242*d83cc019SAndroid Build Coastguard Worker 	igt_assert(tiled[1] > 0.75 * tiled[0]);
243*d83cc019SAndroid Build Coastguard Worker }
244*d83cc019SAndroid Build Coastguard Worker 
245*d83cc019SAndroid Build Coastguard Worker struct thread_contention {
246*d83cc019SAndroid Build Coastguard Worker 	pthread_t thread;
247*d83cc019SAndroid Build Coastguard Worker 	uint32_t handle;
248*d83cc019SAndroid Build Coastguard Worker 	int loops, fd;
249*d83cc019SAndroid Build Coastguard Worker };
no_contention(void * closure)250*d83cc019SAndroid Build Coastguard Worker static void *no_contention(void *closure)
251*d83cc019SAndroid Build Coastguard Worker {
252*d83cc019SAndroid Build Coastguard Worker 	struct thread_contention *t = closure;
253*d83cc019SAndroid Build Coastguard Worker 	int n;
254*d83cc019SAndroid Build Coastguard Worker 
255*d83cc019SAndroid Build Coastguard Worker 	for (n = 0; n < t->loops; n++) {
256*d83cc019SAndroid Build Coastguard Worker 		uint32_t *ptr = gem_mmap__gtt(t->fd, t->handle, OBJECT_SIZE, PROT_READ | PROT_WRITE);
257*d83cc019SAndroid Build Coastguard Worker 		memset(ptr + (rand() % 256) * 4096 / 4, 0, 4096);
258*d83cc019SAndroid Build Coastguard Worker 		munmap(ptr, OBJECT_SIZE);
259*d83cc019SAndroid Build Coastguard Worker 	}
260*d83cc019SAndroid Build Coastguard Worker 
261*d83cc019SAndroid Build Coastguard Worker 	return NULL;
262*d83cc019SAndroid Build Coastguard Worker }
263*d83cc019SAndroid Build Coastguard Worker 
wc_mmap(void * closure)264*d83cc019SAndroid Build Coastguard Worker static void *wc_mmap(void *closure)
265*d83cc019SAndroid Build Coastguard Worker {
266*d83cc019SAndroid Build Coastguard Worker 	struct thread_contention *t = closure;
267*d83cc019SAndroid Build Coastguard Worker 	int n;
268*d83cc019SAndroid Build Coastguard Worker 
269*d83cc019SAndroid Build Coastguard Worker 	for (n = 0; n < t->loops; n++) {
270*d83cc019SAndroid Build Coastguard Worker 		uint32_t *ptr = gem_mmap__wc(t->fd, t->handle, 0, OBJECT_SIZE, PROT_READ | PROT_WRITE);
271*d83cc019SAndroid Build Coastguard Worker 		memset(ptr + (rand() % 256) * 4096 / 4, 0, 4096);
272*d83cc019SAndroid Build Coastguard Worker 		munmap(ptr, OBJECT_SIZE);
273*d83cc019SAndroid Build Coastguard Worker 	}
274*d83cc019SAndroid Build Coastguard Worker 
275*d83cc019SAndroid Build Coastguard Worker 	return NULL;
276*d83cc019SAndroid Build Coastguard Worker }
277*d83cc019SAndroid Build Coastguard Worker 
thread_contention(void)278*d83cc019SAndroid Build Coastguard Worker static void thread_contention(void)
279*d83cc019SAndroid Build Coastguard Worker {
280*d83cc019SAndroid Build Coastguard Worker 	const int loops = 4096;
281*d83cc019SAndroid Build Coastguard Worker 	int n, count;
282*d83cc019SAndroid Build Coastguard Worker 	int fd, num_fences;
283*d83cc019SAndroid Build Coastguard Worker 	double linear[2], tiled[2];
284*d83cc019SAndroid Build Coastguard Worker 
285*d83cc019SAndroid Build Coastguard Worker 	fd = drm_open_driver(DRIVER_INTEL);
286*d83cc019SAndroid Build Coastguard Worker 
287*d83cc019SAndroid Build Coastguard Worker 	num_fences = gem_available_fences(fd);
288*d83cc019SAndroid Build Coastguard Worker 	igt_require(num_fences > 0);
289*d83cc019SAndroid Build Coastguard Worker 
290*d83cc019SAndroid Build Coastguard Worker 	for (count = 1; count < 4*num_fences; count *= 2) {
291*d83cc019SAndroid Build Coastguard Worker 		struct timeval start, end;
292*d83cc019SAndroid Build Coastguard Worker 		struct thread_contention threads[count];
293*d83cc019SAndroid Build Coastguard Worker 
294*d83cc019SAndroid Build Coastguard Worker 		for (n = 0; n < count; n++) {
295*d83cc019SAndroid Build Coastguard Worker 			threads[n].handle = gem_create(fd, OBJECT_SIZE);
296*d83cc019SAndroid Build Coastguard Worker 			threads[n].loops = loops;
297*d83cc019SAndroid Build Coastguard Worker 			threads[n].fd = fd;
298*d83cc019SAndroid Build Coastguard Worker 		}
299*d83cc019SAndroid Build Coastguard Worker 
300*d83cc019SAndroid Build Coastguard Worker 		gettimeofday(&start, NULL);
301*d83cc019SAndroid Build Coastguard Worker 		for (n = 0; n < count; n++)
302*d83cc019SAndroid Build Coastguard Worker 			pthread_create(&threads[n].thread, NULL, no_contention, &threads[n]);
303*d83cc019SAndroid Build Coastguard Worker 		for (n = 0; n < count; n++)
304*d83cc019SAndroid Build Coastguard Worker 			pthread_join(threads[n].thread, NULL);
305*d83cc019SAndroid Build Coastguard Worker 		gettimeofday(&end, NULL);
306*d83cc019SAndroid Build Coastguard Worker 
307*d83cc019SAndroid Build Coastguard Worker 		linear[count != 2] = count * loops / elapsed(&start, &end) / (OBJECT_SIZE / 4096);
308*d83cc019SAndroid Build Coastguard Worker 		igt_info("Contended upload rate for %d linear threads:	%7.3fMiB/s\n", count, linear[count != 2]);
309*d83cc019SAndroid Build Coastguard Worker 
310*d83cc019SAndroid Build Coastguard Worker 		for (n = 0; n < count; n++)
311*d83cc019SAndroid Build Coastguard Worker 			gem_set_tiling(fd, threads[n].handle, I915_TILING_X, 1024);
312*d83cc019SAndroid Build Coastguard Worker 
313*d83cc019SAndroid Build Coastguard Worker 		gettimeofday(&start, NULL);
314*d83cc019SAndroid Build Coastguard Worker 		for (n = 0; n < count; n++)
315*d83cc019SAndroid Build Coastguard Worker 			pthread_create(&threads[n].thread, NULL, no_contention, &threads[n]);
316*d83cc019SAndroid Build Coastguard Worker 		for (n = 0; n < count; n++)
317*d83cc019SAndroid Build Coastguard Worker 			pthread_join(threads[n].thread, NULL);
318*d83cc019SAndroid Build Coastguard Worker 		gettimeofday(&end, NULL);
319*d83cc019SAndroid Build Coastguard Worker 
320*d83cc019SAndroid Build Coastguard Worker 		tiled[count != 2] = count * loops / elapsed(&start, &end) / (OBJECT_SIZE / 4096);
321*d83cc019SAndroid Build Coastguard Worker 		igt_info("Contended upload rate for %d tiled threads:	%7.3fMiB/s\n", count, tiled[count != 2]);
322*d83cc019SAndroid Build Coastguard Worker 
323*d83cc019SAndroid Build Coastguard Worker 		for (n = 0; n < count; n++) {
324*d83cc019SAndroid Build Coastguard Worker 			gem_close(fd, threads[n].handle);
325*d83cc019SAndroid Build Coastguard Worker 		}
326*d83cc019SAndroid Build Coastguard Worker 	}
327*d83cc019SAndroid Build Coastguard Worker 
328*d83cc019SAndroid Build Coastguard Worker 	errno = 0;
329*d83cc019SAndroid Build Coastguard Worker 	igt_assert(linear[1] > 0.75 * linear[0]);
330*d83cc019SAndroid Build Coastguard Worker 	igt_assert(tiled[1] > 0.75 * tiled[0]);
331*d83cc019SAndroid Build Coastguard Worker }
332*d83cc019SAndroid Build Coastguard Worker 
wc_contention(void)333*d83cc019SAndroid Build Coastguard Worker static void wc_contention(void)
334*d83cc019SAndroid Build Coastguard Worker {
335*d83cc019SAndroid Build Coastguard Worker 	const int loops = 4096;
336*d83cc019SAndroid Build Coastguard Worker 	int n, count;
337*d83cc019SAndroid Build Coastguard Worker 	int fd, num_fences;
338*d83cc019SAndroid Build Coastguard Worker 	double linear[2], tiled[2];
339*d83cc019SAndroid Build Coastguard Worker 
340*d83cc019SAndroid Build Coastguard Worker 	fd = drm_open_driver(DRIVER_INTEL);
341*d83cc019SAndroid Build Coastguard Worker 	gem_require_mmap_wc(fd);
342*d83cc019SAndroid Build Coastguard Worker 
343*d83cc019SAndroid Build Coastguard Worker 	num_fences = gem_available_fences(fd);
344*d83cc019SAndroid Build Coastguard Worker 	igt_require(num_fences > 0);
345*d83cc019SAndroid Build Coastguard Worker 
346*d83cc019SAndroid Build Coastguard Worker 	for (count = 1; count < 4*num_fences; count *= 2) {
347*d83cc019SAndroid Build Coastguard Worker 		struct timeval start, end;
348*d83cc019SAndroid Build Coastguard Worker 		struct thread_contention threads[count];
349*d83cc019SAndroid Build Coastguard Worker 
350*d83cc019SAndroid Build Coastguard Worker 		for (n = 0; n < count; n++) {
351*d83cc019SAndroid Build Coastguard Worker 			threads[n].handle = gem_create(fd, OBJECT_SIZE);
352*d83cc019SAndroid Build Coastguard Worker 			threads[n].loops = loops;
353*d83cc019SAndroid Build Coastguard Worker 			threads[n].fd = fd;
354*d83cc019SAndroid Build Coastguard Worker 		}
355*d83cc019SAndroid Build Coastguard Worker 
356*d83cc019SAndroid Build Coastguard Worker 		gettimeofday(&start, NULL);
357*d83cc019SAndroid Build Coastguard Worker 		for (n = 0; n < count; n++)
358*d83cc019SAndroid Build Coastguard Worker 			pthread_create(&threads[n].thread, NULL, wc_mmap, &threads[n]);
359*d83cc019SAndroid Build Coastguard Worker 		for (n = 0; n < count; n++)
360*d83cc019SAndroid Build Coastguard Worker 			pthread_join(threads[n].thread, NULL);
361*d83cc019SAndroid Build Coastguard Worker 		gettimeofday(&end, NULL);
362*d83cc019SAndroid Build Coastguard Worker 
363*d83cc019SAndroid Build Coastguard Worker 		linear[count != 2] = count * loops / elapsed(&start, &end) / (OBJECT_SIZE / 4096);
364*d83cc019SAndroid Build Coastguard Worker 		igt_info("Contended upload rate for %d linear threads/wc:	%7.3fMiB/s\n", count, linear[count != 2]);
365*d83cc019SAndroid Build Coastguard Worker 
366*d83cc019SAndroid Build Coastguard Worker 		for (n = 0; n < count; n++)
367*d83cc019SAndroid Build Coastguard Worker 			gem_set_tiling(fd, threads[n].handle, I915_TILING_X, 1024);
368*d83cc019SAndroid Build Coastguard Worker 
369*d83cc019SAndroid Build Coastguard Worker 		gettimeofday(&start, NULL);
370*d83cc019SAndroid Build Coastguard Worker 		for (n = 0; n < count; n++)
371*d83cc019SAndroid Build Coastguard Worker 			pthread_create(&threads[n].thread, NULL, wc_mmap, &threads[n]);
372*d83cc019SAndroid Build Coastguard Worker 		for (n = 0; n < count; n++)
373*d83cc019SAndroid Build Coastguard Worker 			pthread_join(threads[n].thread, NULL);
374*d83cc019SAndroid Build Coastguard Worker 		gettimeofday(&end, NULL);
375*d83cc019SAndroid Build Coastguard Worker 
376*d83cc019SAndroid Build Coastguard Worker 		tiled[count != 2] = count * loops / elapsed(&start, &end) / (OBJECT_SIZE / 4096);
377*d83cc019SAndroid Build Coastguard Worker 		igt_info("Contended upload rate for %d tiled threads/wc:	%7.3fMiB/s\n", count, tiled[count != 2]);
378*d83cc019SAndroid Build Coastguard Worker 
379*d83cc019SAndroid Build Coastguard Worker 		for (n = 0; n < count; n++) {
380*d83cc019SAndroid Build Coastguard Worker 			gem_close(fd, threads[n].handle);
381*d83cc019SAndroid Build Coastguard Worker 		}
382*d83cc019SAndroid Build Coastguard Worker 	}
383*d83cc019SAndroid Build Coastguard Worker 
384*d83cc019SAndroid Build Coastguard Worker 	errno = 0;
385*d83cc019SAndroid Build Coastguard Worker 	igt_assert(linear[1] > 0.75 * linear[0]);
386*d83cc019SAndroid Build Coastguard Worker 	igt_assert(tiled[1] > 0.75 * tiled[0]);
387*d83cc019SAndroid Build Coastguard Worker }
388*d83cc019SAndroid Build Coastguard Worker 
389*d83cc019SAndroid Build Coastguard Worker igt_main
390*d83cc019SAndroid Build Coastguard Worker {
391*d83cc019SAndroid Build Coastguard Worker 	igt_skip_on_simulation();
392*d83cc019SAndroid Build Coastguard Worker 
393*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("performance")
394*d83cc019SAndroid Build Coastguard Worker 		performance();
395*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("thread-contention")
396*d83cc019SAndroid Build Coastguard Worker 		thread_contention();
397*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("wc-contention")
398*d83cc019SAndroid Build Coastguard Worker 		wc_contention();
399*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("thread-performance-read")
400*d83cc019SAndroid Build Coastguard Worker 		thread_performance(READ);
401*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("thread-performance-write")
402*d83cc019SAndroid Build Coastguard Worker 		thread_performance(WRITE);
403*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("thread-performance-both")
404*d83cc019SAndroid Build Coastguard Worker 		thread_performance(READ | WRITE);
405*d83cc019SAndroid Build Coastguard Worker }
406