Backed out changeset b462e7b742d8 (bug 1908261) for causing multiple reftest failures...
[gecko.git] / dom / canvas / test / webgl-conf / checkout / conformance / extensions / ext-disjoint-timer-query.html
blob7965987c642d178687c83856615686e8e44a37f2
1 <!--
2 Copyright (c) 2019 The Khronos Group Inc.
3 Use of this source code is governed by an MIT-style license that can be
4 found in the LICENSE.txt file.
5 -->
7 <!DOCTYPE html>
8 <html>
9 <head>
10 <meta charset="utf-8">
11 <title>WebGL EXT_disjoint_timer_query Conformance Tests</title>
12 <link rel="stylesheet" href="../../resources/js-test-style.css"/>
13 <script src="../../js/js-test-pre.js"></script>
14 <script src="../../js/webgl-test-utils.js"></script>
15 </head>
16 <body>
17 <div id="description"></div>
18 <canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
19 <div id="console"></div>
21 <script>
22 "use strict";
23 description("This test verifies the functionality of the EXT_disjoint_timer_query extension, if it is available.");
25 var wtu = WebGLTestUtils;
26 var canvas = document.getElementById("canvas");
27 var gl = wtu.create3DContext(canvas);
28 var gl2 = null;
29 var ext = null;
30 var ext2 = null;
31 var query = null;
32 var query2 = null;
33 var elapsed_query = null;
34 var timestamp_query1 = null;
35 var timestamp_query2 = null;
36 var availability_retry = 500;
37 var timestamp_counter_bits = 0;
39 if (!gl) {
40 testFailed("WebGL context does not exist");
41 finishTest();
42 } else {
43 testPassed("WebGL context exists");
45 // Query the extension and store globally so shouldBe can access it
46 ext = wtu.getExtensionWithKnownPrefixes(gl, "EXT_disjoint_timer_query");
47 if (!ext) {
48 testPassed("No EXT_disjoint_timer_query support -- this is legal");
49 finishTest();
50 } else {
51 if (wtu.getDefault3DContextVersion() > 1) {
52 testFailed("EXT_disjoint_timer_query must not be advertised on WebGL 2.0 contexts");
53 finishTest();
54 } else {
55 runSanityTests();
57 // Clear disjoint value.
58 gl.getParameter(ext.GPU_DISJOINT_EXT);
60 runElapsedTimeTest();
61 timestamp_counter_bits = ext.getQueryEXT(ext.TIMESTAMP_EXT, ext.QUERY_COUNTER_BITS_EXT);
62 if (timestamp_counter_bits > 0) {
63 runTimeStampTest();
65 verifyQueryResultsNotAvailable();
66 verifyDeleteQueryBehavior();
67 verifyDeleteQueryErrorBehavior();
69 window.requestAnimationFrame(checkQueryResults);
74 function runSanityTests() {
75 debug("");
76 debug("Testing timer query expectations");
78 shouldBe("ext.QUERY_COUNTER_BITS_EXT", "0x8864");
79 shouldBe("ext.CURRENT_QUERY_EXT", "0x8865");
80 shouldBe("ext.QUERY_RESULT_EXT", "0x8866");
81 shouldBe("ext.QUERY_RESULT_AVAILABLE_EXT", "0x8867");
82 shouldBe("ext.TIME_ELAPSED_EXT", "0x88BF");
83 shouldBe("ext.TIMESTAMP_EXT", "0x8E28");
84 shouldBe("ext.GPU_DISJOINT_EXT", "0x8FBB");
86 shouldBe("ext.isQueryEXT(null)", "false");
88 shouldBeTrue("ext.getQueryEXT(ext.TIME_ELAPSED_EXT, ext.CURRENT_QUERY_EXT) === null");
89 wtu.glErrorShouldBe(gl, gl.NO_ERROR);
90 shouldBeTrue("ext.getQueryEXT(ext.TIME_ELAPSED_EXT, ext.QUERY_COUNTER_BITS_EXT) >= 30");
91 wtu.glErrorShouldBe(gl, gl.NO_ERROR);
93 shouldBeTrue("ext.getQueryEXT(ext.TIMESTAMP_EXT, ext.CURRENT_QUERY_EXT) === null");
94 wtu.glErrorShouldBe(gl, gl.NO_ERROR);
96 // Certain drivers set timestamp counter bits to 0 as they don't support timestamps
97 shouldBeTrue("ext.getQueryEXT(ext.TIMESTAMP_EXT, ext.QUERY_COUNTER_BITS_EXT) >= 30 || " +
98 "ext.getQueryEXT(ext.TIMESTAMP_EXT, ext.QUERY_COUNTER_BITS_EXT) === 0");
99 wtu.glErrorShouldBe(gl, gl.NO_ERROR);
101 debug("");
102 debug("Testing time elapsed query lifecycle");
103 query = ext.createQueryEXT();
104 shouldBe("ext.isQueryEXT(query)", "false");
105 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Query creation must succeed.");
106 shouldThrow("ext.beginQueryEXT(ext.TIMESTAMP_EXT, null)");
107 ext.beginQueryEXT(ext.TIMESTAMP_EXT, query);
108 wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "Beginning a timestamp query should fail.");
109 ext.beginQueryEXT(ext.TIME_ELAPSED_EXT, query);
110 shouldBe("ext.isQueryEXT(query)", "true");
111 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Beginning an inactive time elapsed query should succeed.");
112 ext.beginQueryEXT(ext.TIME_ELAPSED_EXT, query);
113 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Attempting to begin an active query should fail.");
114 ext.getQueryObjectEXT(query, ext.QUERY_RESULT_AVAILABLE_EXT);
115 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Fetching query result availability of an active query should fail.");
116 ext.getQueryObjectEXT(query, ext.QUERY_RESULT_EXT);
117 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Fetching query result of an active query should fail.");
118 shouldBe("ext.getQueryEXT(ext.TIME_ELAPSED_EXT, ext.CURRENT_QUERY_EXT)", "query");
119 ext.endQueryEXT(ext.TIME_ELAPSED_EXT);
120 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Ending an active time elapsed query should succeed.");
121 shouldThrow("ext.getQueryObjectEXT(null, ext.QUERY_RESULT_AVAILABLE_EXT)");
122 ext.getQueryObjectEXT(query, ext.QUERY_RESULT_AVAILABLE_EXT);
123 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Fetching query result availability after query end should succeed.");
124 ext.endQueryEXT(ext.TIME_ELAPSED_EXT);
125 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Attempting to end an inactive query should fail.");
126 ext.queryCounterEXT(query, ext.TIMESTAMP_EXT);
127 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Should not be able to use time elapsed query to store a timestamp.");
128 ext.deleteQueryEXT(query);
129 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Query deletion must succeed.");
130 ext.beginQueryEXT(ext.TIME_ELAPSED_EXT, query);
131 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Beginning a deleted query must fail.");
132 ext.getQueryObjectEXT(query, ext.QUERY_RESULT_AVAILABLE_EXT);
133 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Fetching query result availability after query deletion should fail.");
134 shouldBe("ext.isQueryEXT(query)", "false");
136 debug("");
137 debug("Testing timestamp counter");
138 query = ext.createQueryEXT();
139 shouldThrow("ext.queryCounterEXT(null, ext.TIMESTAMP_EXT)");
140 ext.queryCounterEXT(query, ext.TIMESTAMP_EXT);
141 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Timestamp counter queries should work.");
142 ext.deleteQueryEXT(query);
143 wtu.glErrorShouldBe(gl, gl.NO_ERROR);
145 debug("");
146 debug("Performing parameter sanity checks");
147 gl.getParameter(ext.TIMESTAMP_EXT);
148 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "getParameter timestamp calls should work.");
149 gl.getParameter(ext.GPU_DISJOINT_EXT);
150 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "getParameter disjoint calls should work.");
152 debug("");
153 debug("Testing current query conditions");
154 query = ext.createQueryEXT();
155 query2 = ext.createQueryEXT();
156 shouldBe("ext.getQueryEXT(ext.TIME_ELAPSED_EXT, ext.CURRENT_QUERY_EXT)", "null");
157 ext.beginQueryEXT(ext.TIME_ELAPSED_EXT, query);
158 shouldBe("ext.getQueryEXT(ext.TIME_ELAPSED_EXT, ext.CURRENT_QUERY_EXT)", "query");
159 wtu.glErrorShouldBe(gl, gl.NO_ERROR);
161 debug("");
162 debug("Testing failed begin query should not change the current query.");
163 ext.beginQueryEXT(ext.TIME_ELAPSED_EXT, query2);
164 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Beginning an elapsed query without ending should fail.");
165 shouldBe("ext.getQueryEXT(ext.TIME_ELAPSED_EXT, ext.CURRENT_QUERY_EXT)", "query");
166 wtu.glErrorShouldBe(gl, gl.NO_ERROR);
168 debug("");
169 debug("Testing beginning a timestamp query is invalid and should not change the elapsed query.");
170 ext.beginQueryEXT(ext.TIMESTAMP_EXT, query2)
171 wtu.glErrorShouldBe(gl, gl.INVALID_ENUM);
172 shouldBe("ext.getQueryEXT(ext.TIME_ELAPSED_EXT, ext.CURRENT_QUERY_EXT)", "query");
173 wtu.glErrorShouldBe(gl, gl.NO_ERROR);
175 debug("");
176 debug("Testing timestamp queries end immediately so are never current.");
177 ext.queryCounterEXT(query2, ext.TIMESTAMP_EXT);
178 shouldBe("ext.getQueryEXT(ext.TIMESTAMP_EXT, ext.CURRENT_QUERY_EXT)", "null");
179 wtu.glErrorShouldBe(gl, gl.NO_ERROR);
181 debug("");
182 debug("Testing ending the query should clear the current query.");
183 ext.endQueryEXT(ext.TIME_ELAPSED_EXT);
184 shouldBe("ext.getQueryEXT(ext.TIME_ELAPSED_EXT, ext.CURRENT_QUERY_EXT)", "null");
185 wtu.glErrorShouldBe(gl, gl.NO_ERROR);
187 debug("");
188 debug("Testing beginning a elapsed query using a timestamp query should fail and not affect current query.")
189 ext.beginQueryEXT(ext.TIME_ELAPSED_EXT, query2);
190 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Switching query targets should fail.");
191 shouldBe("ext.getQueryEXT(ext.TIME_ELAPSED_EXT, ext.CURRENT_QUERY_EXT)", "null");
192 wtu.glErrorShouldBe(gl, gl.NO_ERROR);
194 ext.deleteQueryEXT(query);
195 ext.deleteQueryEXT(query2);
197 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors at end of sanity tests");
200 function runElapsedTimeTest() {
201 debug("");
202 debug("Testing elapsed time query");
204 elapsed_query = ext.createQueryEXT();
205 ext.beginQueryEXT(ext.TIME_ELAPSED_EXT, elapsed_query);
206 gl.clearColor(0, 0, 1, 1);
207 gl.clear(gl.COLOR_BUFFER_BIT);
208 ext.endQueryEXT(ext.TIME_ELAPSED_EXT);
209 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Time elapsed query should have no errors");
212 function runTimeStampTest() {
213 debug("");
214 debug("Testing timestamp query");
216 timestamp_query1 = ext.createQueryEXT();
217 timestamp_query2 = ext.createQueryEXT();
218 ext.queryCounterEXT(timestamp_query1, ext.TIMESTAMP_EXT);
219 gl.clearColor(1, 0, 0, 1);
220 gl.clear(gl.COLOR_BUFFER_BIT);
221 ext.queryCounterEXT(timestamp_query2, ext.TIMESTAMP_EXT);
222 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Timestamp queries should have no errors");
225 function verifyQueryResultsNotAvailable() {
226 debug("");
227 debug("Verifying queries' results don't become available too early");
229 // Verify as best as possible that the implementation doesn't
230 // allow a query's result to become available the same frame, by
231 // spin-looping for some time and ensuring that none of the
232 // queries' results become available.
233 var startTime = Date.now();
234 while (Date.now() - startTime < 2000) {
235 gl.finish();
236 if (ext.getQueryObjectEXT(elapsed_query, ext.QUERY_RESULT_AVAILABLE_EXT)) {
237 testFailed("One of the queries' results became available too early");
238 return;
240 if (timestamp_counter_bits > 0) {
241 if (ext.getQueryObjectEXT(timestamp_query1, ext.QUERY_RESULT_AVAILABLE_EXT) ||
242 ext.getQueryObjectEXT(timestamp_query2, ext.QUERY_RESULT_AVAILABLE_EXT)) {
243 testFailed("One of the queries' results became available too early");
244 return;
249 testPassed("Queries' results didn't become available in a spin loop");
252 function verifyDeleteQueryBehavior() {
253 debug("");
254 debug("Testing deleting an active query should end it.");
256 // Use a new context for this test
257 gl2 = wtu.create3DContext(null, null, 1);
258 if (!gl2) return;
259 ext2 = gl2.getExtension("EXT_disjoint_timer_query");
260 if (!ext2) return;
262 query = ext2.createQueryEXT();
263 ext2.beginQueryEXT(ext2.TIME_ELAPSED_EXT, query);
264 wtu.glErrorShouldBe(gl2, gl2.NONE, "The query began successfully");
265 ext2.deleteQueryEXT(query);
266 wtu.glErrorShouldBe(gl2, gl2.NONE, "Deletion of the active query succeeds");
267 shouldBeNull("ext2.getQueryEXT(ext2.TIME_ELAPSED_EXT, ext2.CURRENT_QUERY_EXT)");
268 shouldBeFalse("ext2.isQueryEXT(query)");
269 query = ext2.createQueryEXT();
270 ext2.beginQueryEXT(ext2.TIME_ELAPSED_EXT, query);
271 wtu.glErrorShouldBe(gl2, gl2.NONE, "Beginning a new query succeeds");
272 ext2.endQueryEXT(ext2.TIME_ELAPSED_EXT);
273 ext2.deleteQueryEXT(query);
274 wtu.glErrorShouldBe(gl2, gl2.NONE);
275 query = null;
276 ext2 = null;
277 gl2 = null;
280 function verifyDeleteQueryErrorBehavior() {
281 debug("");
282 debug("Testing deleting a query created by another context.");
284 // Use new contexts for this test
285 gl2 = wtu.create3DContext(null, null, 1);
286 var gl3 = wtu.create3DContext(null, null, 1);
287 if (!gl2 || !gl3) return;
288 ext2 = gl2.getExtension("EXT_disjoint_timer_query");
289 var ext3 = gl3.getExtension("EXT_disjoint_timer_query");
290 if (!ext2 || !ext3) return;
292 query = ext2.createQueryEXT();
293 ext2.beginQueryEXT(ext2.TIME_ELAPSED_EXT, query);
294 ext3.deleteQueryEXT(query);
295 wtu.glErrorShouldBe(gl3, gl3.INVALID_OPERATION);
296 shouldBeTrue("ext2.isQueryEXT(query)");
297 shouldBe("ext2.getQueryEXT(ext2.TIME_ELAPSED_EXT, ext2.CURRENT_QUERY_EXT)", "query");
298 ext2.endQueryEXT(ext2.TIME_ELAPSED_EXT);
299 ext2.deleteQueryEXT(query);
300 wtu.glErrorShouldBe(gl2, gl2.NONE);
301 query = null;
302 ext2 = null;
303 gl2 = null;
304 gl3 = null;
307 function checkQueryResults() {
308 if (availability_retry > 0) {
309 // Make a reasonable attempt to wait for the queries' results to become available.
310 if (!ext.getQueryObjectEXT(elapsed_query, ext.QUERY_RESULT_AVAILABLE_EXT) ||
311 (timestamp_counter_bits > 0 && !ext.getQueryObjectEXT(timestamp_query2, ext.QUERY_RESULT_AVAILABLE_EXT))) {
312 var error = gl.getError();
313 if (error != gl.NO_ERROR) {
314 testFailed("getQueryObjectEXT should have no errors: " + wtu.glEnumToString(gl, error));
315 debug("");
316 finishTest();
317 return;
319 availability_retry--;
320 window.requestAnimationFrame(checkQueryResults);
321 return;
325 debug("");
326 debug("Testing query results");
328 // Make sure queries are available.
329 shouldBe("ext.getQueryObjectEXT(elapsed_query, ext.QUERY_RESULT_AVAILABLE_EXT)", "true");
330 if (timestamp_counter_bits > 0) {
331 shouldBe("ext.getQueryObjectEXT(timestamp_query1, ext.QUERY_RESULT_AVAILABLE_EXT)", "true");
332 shouldBe("ext.getQueryObjectEXT(timestamp_query2, ext.QUERY_RESULT_AVAILABLE_EXT)", "true");
335 var disjoint_value = gl.getParameter(ext.GPU_DISJOINT_EXT);
336 if (disjoint_value) {
337 // Cannot validate results make sense, but this is okay.
338 testPassed("Disjoint triggered.");
339 } else {
340 var elapsed_result = ext.getQueryObjectEXT(elapsed_query, ext.QUERY_RESULT_EXT);
341 if (timestamp_counter_bits > 0) {
342 var timestamp_result1 = ext.getQueryObjectEXT(timestamp_query1, ext.QUERY_RESULT_EXT);
343 var timestamp_result2 = ext.getQueryObjectEXT(timestamp_query2, ext.QUERY_RESULT_EXT);
345 // Do some basic validity checking of the elapsed time query. There's no way it should
346 // take more than about half a second for a no-op query.
347 var halfSecondInNanos = 0.5 * 1000 * 1000 * 1000;
348 if (elapsed_result < 0 || elapsed_result > halfSecondInNanos) {
349 testFailed("Time elapsed query returned invalid data: " + elapsed_result);
350 } else {
351 testPassed("Time elapsed query results were valid.");
354 if (timestamp_counter_bits > 0) {
355 if (timestamp_result1 <= 0 ||
356 timestamp_result2 <= 0 ||
357 timestamp_result2 <= timestamp_result1) {
358 testFailed("Timestamp queries returned invalid data: timestamp_result1 = " +
359 timestamp_result1 + ", timestamp_result2 = " + timestamp_result2);
360 } else {
361 testPassed("Timestamp query results were valid.");
366 debug("");
367 finishTest();
369 </script>
370 </body>
371 </html>