2 * Copyright © 2012 Marek Olšák <maraeo@gmail.com>
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:
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
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
24 #include "piglit-util-gl.h"
26 #include <inttypes.h> /* for PRIu64 macro */
28 #include <unistd.h> /* for usleep */
31 /* GL_TIMESTAMP isn't expected to be reliable for measuring long durations and
32 * although the ARB_timer_query spec doesn't stipulate what kind of drifting
33 * from wall clock time is acceptable, we at least want a sanity check that
34 * things look reasonable...
36 #define DRIFT_NS_PER_SEC_THRESHOLD 3000000
39 * @file timestamp-get.c
41 * Test that GL_TIMESTAMP obtained via glGet and glQuery returns roughly
42 * the same value, and that durations measured via GL_TIMESTAMP have
46 PIGLIT_GL_TEST_CONFIG_BEGIN
48 config
.supports_gl_compat_version
= 10;
49 config
.window_visual
= PIGLIT_GL_VISUAL_DOUBLE
| PIGLIT_GL_VISUAL_RGBA
;
50 config
.khr_no_error_support
= PIGLIT_NO_ERRORS
;
52 PIGLIT_GL_TEST_CONFIG_END
55 get_gpu_time_via_query(GLuint q
)
59 glQueryCounter(q
, GL_TIMESTAMP
);
60 glGetQueryObjecti64v(q
, GL_QUERY_RESULT
, &time
);
65 get_gpu_time_via_get(GLuint q
)
69 glGetInteger64v(GL_TIMESTAMP
, &time
);
74 validate_times(GLint64 t1
, GLint64 t2
, GLint64 tolerance
)
77 printf("old time = %" PRIu64
" us\n", (uint64_t) t1
/ 1000);
78 printf("new time = %" PRIu64
" us\n", (uint64_t) t2
/ 1000);
79 puts("old time > new time");
80 piglit_report_result(PIGLIT_FAIL
);
83 /* the tolerance of 1 milisecond seems to be sufficient */
84 if (t2
- t1
> tolerance
) {
85 printf("time 1 = %" PRIu64
" us\n", (uint64_t) t1
/ 1000);
86 printf("time 2 = %" PRIu64
" us\n", (uint64_t) t2
/ 1000);
87 puts("too big difference");
88 piglit_report_result(PIGLIT_FAIL
);
93 validate_delta(GLint64 gl_ts1
, GLint64 gl_ts2
, GLint64 cpu_delay_ns
)
95 GLint64 gl_ts_delta
= gl_ts2
- gl_ts1
;
96 int64_t drift
= llabs(cpu_delay_ns
- gl_ts_delta
);
97 int64_t drift_per_sec
= drift
* 1000000000LL / cpu_delay_ns
;
99 /* XXX: technically we shouldn't be as strict about drift when the gpu
100 * clock is running fast and the duration is longer than expected,
101 * because we can't easily exclude other factors like OS scheduling
102 * affecting the measurements. For now though we don't take this into
105 if (drift_per_sec
> DRIFT_NS_PER_SEC_THRESHOLD
) {
106 printf("GL_TIMESTAMP 1 = %" PRId64
" us\n", gl_ts1
/ 1000);
107 printf("GL_TIMESTAMP 2 = %" PRId64
" us\n", gl_ts2
/ 1000);
108 printf("delta = %" PRId64
" us (expect >= %"PRId64
" us)\n",
109 gl_ts_delta
/ 1000, cpu_delay_ns
/ 1000);
111 piglit_loge("GL_TIMESTAMP drift of %" PRId64
" ns/sec, greater than %" PRId64
" ns/sec",
113 (int64_t)DRIFT_NS_PER_SEC_THRESHOLD
);
114 piglit_report_result(PIGLIT_FAIL
);
116 printf("GL_TIMESTAMP drift of approx. %" PRId64
" ns/sec\n",
124 GLint64 query_overhead
, get_overhead
, tolerance
;
130 /* this creates the query in the driver */
131 get_gpu_time_via_query(q
);
133 /* compute a reasonable tolerance based on driver overhead */
134 t1
= piglit_time_get_nano();
135 get_gpu_time_via_query(q
);
136 query_overhead
= piglit_time_get_nano() - t1
;
138 t1
= piglit_time_get_nano();
139 get_gpu_time_via_get(q
);
140 get_overhead
= piglit_time_get_nano() - t1
;
142 printf("glGet overhead: %" PRIu64
" us\n", (uint64_t) get_overhead
/ 1000);
143 printf("glQuery overhead: %" PRIu64
" us\n", (uint64_t) query_overhead
/ 1000);
145 /* minimum tolerance is 3 ms */
146 tolerance
= query_overhead
+ get_overhead
+ 3000000;
149 puts("Test: first glQuery, then glGet");
150 t1
= get_gpu_time_via_query(q
);
151 t2
= get_gpu_time_via_get(q
);
152 validate_times(t1
, t2
, tolerance
);
156 puts("Test: first glGet, then glQuery");
157 t1
= get_gpu_time_via_get(q
);
158 t2
= get_gpu_time_via_query(q
);
159 validate_times(t1
, t2
, tolerance
);
161 puts("Test: wall clock time via glQuery");
162 t1
= get_gpu_time_via_query(q
);
163 delay
= piglit_delay_ns(1000000000);
164 t2
= get_gpu_time_via_query(q
);
165 validate_delta(t1
, t2
, delay
);
167 puts("Test: wall clock time via glGet");
168 t1
= get_gpu_time_via_get(q
);
169 delay
= piglit_delay_ns(1000000000);
170 t2
= get_gpu_time_via_get(q
);
171 validate_delta(t1
, t2
, delay
);
173 glDeleteQueries(1, &q
);
179 piglit_init(int argc
, char **argv
)
181 piglit_automatic
= true;
183 piglit_require_gl_version(20);
185 piglit_require_extension("GL_ARB_timer_query");