blob: 29c74865ee43b54bdd26587d6f01a46fb96e775d [file] [log] [blame]
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001//
2// Copyright 2016 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6// TimerQueriesTest.cpp
7// Various tests for EXT_disjoint_timer_query functionality and validation
8//
9
10#include "system_utils.h"
11#include "test_utils/ANGLETest.h"
12#include "random_utils.h"
13
14using namespace angle;
15
16class TimerQueriesTest : public ANGLETest
17{
18 protected:
19 TimerQueriesTest() : mProgram(0), mProgramCostly(0)
20 {
21 setWindowWidth(128);
22 setWindowHeight(128);
23 setConfigRedBits(8);
24 setConfigGreenBits(8);
25 setConfigBlueBits(8);
26 setConfigAlphaBits(8);
27 setConfigDepthBits(24);
28 }
29
30 virtual void SetUp()
31 {
32 ANGLETest::SetUp();
33
34 const std::string passthroughVS =
35 "attribute highp vec4 position; void main(void)\n"
36 "{\n"
37 " gl_Position = position;\n"
38 "}\n";
39
40 const std::string passthroughPS =
41 "precision highp float; void main(void)\n"
42 "{\n"
43 " gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
44 "}\n";
45
46 const std::string costlyVS =
47 "attribute highp vec4 position; varying highp vec4 testPos; void main(void)\n"
48 "{\n"
49 " testPos = position;\n"
50 " gl_Position = position;\n"
51 "}\n";
52
53 const std::string costlyPS =
54 "precision highp float; varying highp vec4 testPos; void main(void)\n"
55 "{\n"
56 " vec4 test = testPos;\n"
57 " for (int i = 0; i < 500; i++)\n"
58 " {\n"
59 " test = sqrt(test);\n"
60 " }\n"
61 " gl_FragColor = test;\n"
62 "}\n";
63
64 mProgram = CompileProgram(passthroughVS, passthroughPS);
65 ASSERT_NE(0u, mProgram) << "shader compilation failed.";
66
67 mProgramCostly = CompileProgram(costlyVS, costlyPS);
68 ASSERT_NE(0u, mProgramCostly) << "shader compilation failed.";
69 }
70
71 virtual void TearDown()
72 {
73 glDeleteProgram(mProgram);
74 glDeleteProgram(mProgramCostly);
75 ANGLETest::TearDown();
76 }
77
78 GLuint mProgram;
79 GLuint mProgramCostly;
80};
81
82// Tests the time elapsed query
83TEST_P(TimerQueriesTest, TimeElapsed)
84{
85 if (!extensionEnabled("GL_EXT_disjoint_timer_query"))
86 {
87 std::cout << "Test skipped because GL_EXT_disjoint_timer_query is not available."
88 << std::endl;
89 return;
90 }
91
92 GLint queryTimeElapsedBits = 0;
93 glGetQueryivEXT(GL_TIME_ELAPSED_EXT, GL_QUERY_COUNTER_BITS_EXT, &queryTimeElapsedBits);
94 ASSERT_GL_NO_ERROR();
95
96 std::cout << "Time elapsed counter bits: " << queryTimeElapsedBits << std::endl;
97
98 // Skip test if the number of bits is 0
99 if (queryTimeElapsedBits == 0)
100 {
101 std::cout << "Test skipped because of 0 counter bits" << std::endl;
102 return;
103 }
104
105 glDepthMask(GL_TRUE);
106 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
107
108 GLuint query1 = 0;
109 GLuint query2 = 0;
110 glGenQueriesEXT(1, &query1);
111 glGenQueriesEXT(1, &query2);
112
113 // Test time elapsed for a single quad
114 glBeginQueryEXT(GL_TIME_ELAPSED_EXT, query1);
115 drawQuad(mProgram, "position", 0.8f);
116 glEndQueryEXT(GL_TIME_ELAPSED_EXT);
117 ASSERT_GL_NO_ERROR();
118
119 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
120
121 // Test time elapsed for costly quad
122 glBeginQueryEXT(GL_TIME_ELAPSED_EXT, query2);
123 drawQuad(mProgramCostly, "position", 0.8f);
124 glEndQueryEXT(GL_TIME_ELAPSED_EXT);
125 ASSERT_GL_NO_ERROR();
126
127 swapBuffers();
128
129 int timeout = 10000;
130 GLuint ready = GL_FALSE;
131 while (ready == GL_FALSE && timeout > 0)
132 {
133 angle::Sleep(0);
134 glGetQueryObjectuivEXT(query1, GL_QUERY_RESULT_AVAILABLE_EXT, &ready);
135 timeout--;
136 }
137 ready = GL_FALSE;
138 while (ready == GL_FALSE && timeout > 0)
139 {
140 angle::Sleep(0);
141 glGetQueryObjectuivEXT(query2, GL_QUERY_RESULT_AVAILABLE_EXT, &ready);
142 timeout--;
143 }
144 ASSERT_LT(0, timeout) << "Query result available timed out" << std::endl;
145
146 GLuint64 result1 = 0;
147 GLuint64 result2 = 0;
148 glGetQueryObjectui64vEXT(query1, GL_QUERY_RESULT_EXT, &result1);
149 glGetQueryObjectui64vEXT(query2, GL_QUERY_RESULT_EXT, &result2);
150 ASSERT_GL_NO_ERROR();
151
152 glDeleteQueriesEXT(1, &query1);
153 glDeleteQueriesEXT(1, &query2);
154 ASSERT_GL_NO_ERROR();
155
156 std::cout << "Elapsed time: " << result1 << " cheap quad" << std::endl;
157 std::cout << "Elapsed time: " << result2 << " costly quad" << std::endl;
158
159 // The time elapsed should be nonzero
160 EXPECT_LT(0ul, result1);
161 EXPECT_LT(0ul, result2);
162
163 // The costly quad should take longer than the cheap quad
164 EXPECT_LT(result1, result2);
165}
166
167// Tests validation of query functions with respect to elapsed time query
168TEST_P(TimerQueriesTest, TimeElapsedValidationTest)
169{
170 if (!extensionEnabled("GL_EXT_disjoint_timer_query"))
171 {
172 std::cout << "Test skipped because GL_EXT_disjoint_timer_query is not available."
173 << std::endl;
174 return;
175 }
176
177 GLint queryTimeElapsedBits = 0;
178 glGetQueryivEXT(GL_TIME_ELAPSED_EXT, GL_QUERY_COUNTER_BITS_EXT, &queryTimeElapsedBits);
179 ASSERT_GL_NO_ERROR();
180
181 std::cout << "Time elapsed counter bits: " << queryTimeElapsedBits << std::endl;
182
183 // Skip test if the number of bits is 0
184 if (queryTimeElapsedBits == 0)
185 {
186 std::cout << "Test skipped because of 0 counter bits" << std::endl;
187 return;
188 }
189
190 GLuint query = 0;
191 glGenQueriesEXT(-1, &query);
192 EXPECT_GL_ERROR(GL_INVALID_VALUE);
193
194 glGenQueriesEXT(1, &query);
195 EXPECT_GL_NO_ERROR();
196
197 glBeginQueryEXT(GL_TIMESTAMP_EXT, query);
198 EXPECT_GL_ERROR(GL_INVALID_ENUM);
199
200 glBeginQueryEXT(GL_TIME_ELAPSED_EXT, 0);
201 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
202
203 glEndQueryEXT(GL_TIME_ELAPSED_EXT);
204 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
205
206 glBeginQueryEXT(GL_TIME_ELAPSED_EXT, query);
207 EXPECT_GL_NO_ERROR();
208
209 glBeginQueryEXT(GL_TIME_ELAPSED_EXT, query);
210 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
211
212 glEndQueryEXT(GL_TIME_ELAPSED_EXT);
213 EXPECT_GL_NO_ERROR();
214
215 glEndQueryEXT(GL_TIME_ELAPSED_EXT);
216 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
217}
218
219// Tests GPU timestamp functionality
220TEST_P(TimerQueriesTest, Timestamp)
221{
222 if (!extensionEnabled("GL_EXT_disjoint_timer_query"))
223 {
224 std::cout << "Test skipped because GL_EXT_disjoint_timer_query is not available."
225 << std::endl;
226 return;
227 }
228
229 GLint queryTimestampBits = 0;
230 glGetQueryivEXT(GL_TIMESTAMP_EXT, GL_QUERY_COUNTER_BITS_EXT, &queryTimestampBits);
231 ASSERT_GL_NO_ERROR();
232
233 std::cout << "Timestamp counter bits: " << queryTimestampBits << std::endl;
234
235 // Macs for some reason return 0 bits so skip the test for now if either are 0
236 if (queryTimestampBits == 0)
237 {
238 std::cout << "Test skipped because of 0 counter bits" << std::endl;
239 return;
240 }
241
242 glDepthMask(GL_TRUE);
243 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
244
245 GLuint query1 = 0;
246 GLuint query2 = 0;
247 glGenQueriesEXT(1, &query1);
248 glGenQueriesEXT(1, &query2);
249 glQueryCounterEXT(query1, GL_TIMESTAMP_EXT);
250 drawQuad(mProgram, "position", 0.8f);
251 glQueryCounterEXT(query2, GL_TIMESTAMP_EXT);
252
253 ASSERT_GL_NO_ERROR();
254
255 swapBuffers();
256
257 int timeout = 10000;
258 GLuint ready = GL_FALSE;
259 while (ready == GL_FALSE && timeout > 0)
260 {
261 angle::Sleep(0);
262 glGetQueryObjectuivEXT(query1, GL_QUERY_RESULT_AVAILABLE_EXT, &ready);
263 timeout--;
264 }
265 ready = GL_FALSE;
266 while (ready == GL_FALSE && timeout > 0)
267 {
268 angle::Sleep(0);
269 glGetQueryObjectuivEXT(query2, GL_QUERY_RESULT_AVAILABLE_EXT, &ready);
270 timeout--;
271 }
272 ASSERT_LT(0, timeout) << "Query result available timed out" << std::endl;
273
274 GLuint64 result1 = 0;
275 GLuint64 result2 = 0;
276 glGetQueryObjectui64vEXT(query1, GL_QUERY_RESULT_EXT, &result1);
277 glGetQueryObjectui64vEXT(query2, GL_QUERY_RESULT_EXT, &result2);
278
279 ASSERT_GL_NO_ERROR();
280
281 glDeleteQueriesEXT(1, &query1);
282 glDeleteQueriesEXT(1, &query2);
283
284 std::cout << "Timestamps: " << result1 << " " << result2 << std::endl;
285 EXPECT_LT(0ul, result1);
286 EXPECT_LT(0ul, result2);
287 EXPECT_LT(result1, result2);
288}
289
Ian Ewell53f59f42016-01-28 17:36:55 -0500290class TimerQueriesTestES3 : public TimerQueriesTest
291{
292
293};
294
295// Tests getting timestamps via glGetInteger64v
296TEST_P(TimerQueriesTestES3, TimestampGetInteger64)
297{
298 if (!extensionEnabled("GL_EXT_disjoint_timer_query"))
299 {
300 std::cout << "Test skipped because GL_EXT_disjoint_timer_query is not available."
301 << std::endl;
302 return;
303 }
304
305 GLint queryTimestampBits = 0;
306 glGetQueryivEXT(GL_TIMESTAMP_EXT, GL_QUERY_COUNTER_BITS_EXT, &queryTimestampBits);
307 ASSERT_GL_NO_ERROR();
308
309 std::cout << "Timestamp counter bits: " << queryTimestampBits << std::endl;
310
311 if (queryTimestampBits == 0)
312 {
313 std::cout << "Test skipped because of 0 counter bits" << std::endl;
314 return;
315 }
316
317 glDepthMask(GL_TRUE);
318 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
319
320 GLint64 result1 = 0;
321 GLint64 result2 = 0;
322 glGetInteger64v(GL_TIMESTAMP_EXT, &result1);
323 drawQuad(mProgram, "position", 0.8f);
324 glGetInteger64v(GL_TIMESTAMP_EXT, &result2);
325 ASSERT_GL_NO_ERROR();
326 std::cout << "Timestamps (getInteger64v): " << result1 << " " << result2 << std::endl;
327 EXPECT_LT(0l, result1);
328 EXPECT_LT(0l, result2);
329 EXPECT_LT(result1, result2);
330}
331
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500332ANGLE_INSTANTIATE_TEST(TimerQueriesTest,
333 ES2_D3D9(),
334 ES2_D3D11(),
335 ES3_D3D11(),
336 ES2_OPENGL(),
337 ES3_OPENGL());
Ian Ewell53f59f42016-01-28 17:36:55 -0500338
339ANGLE_INSTANTIATE_TEST(TimerQueriesTestES3,
340 ES3_D3D11(),
341 ES3_OPENGL());