tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ext-disjoint-timer-query-webgl2.html (15107B)


      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 -->
      6 
      7 <!DOCTYPE html>
      8 <html>
      9 <head>
     10 <meta charset="utf-8">
     11 <title>WebGL 2 EXT_disjoint_timer_query_webgl2 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>
     20 
     21 <script>
     22 "use strict";
     23 description("This test verifies the functionality of the EXT_disjoint_timer_query_webgl2 extension, if it is available.");
     24 
     25 var wtu = WebGLTestUtils;
     26 var canvas = document.getElementById("canvas");
     27 var gl = wtu.create3DContext(canvas, null, 2);
     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;
     38 
     39 if (!gl) {
     40    testFailed("WebGL context does not exist");
     41    finishTest();
     42 } else {
     43    testPassed("WebGL context exists");
     44 
     45    // Query the extension and store globally so shouldBe can access it
     46    ext = wtu.getExtensionWithKnownPrefixes(gl, "EXT_disjoint_timer_query_webgl2");
     47    if (!ext) {
     48        testPassed("No EXT_disjoint_timer_query_webgl2 support -- this is legal");
     49        finishTest();
     50    } else {
     51        runSanityTests();
     52        wtu.glErrorShouldBe(gl, gl.NO_ERROR);
     53 
     54        // Clear disjoint value.
     55        gl.getParameter(ext.GPU_DISJOINT_EXT);
     56        wtu.glErrorShouldBe(gl, gl.NO_ERROR);
     57 
     58        runElapsedTimeTest();
     59        wtu.glErrorShouldBe(gl, gl.NO_ERROR);
     60 
     61        timestamp_counter_bits = gl.getQuery(ext.TIMESTAMP_EXT, ext.QUERY_COUNTER_BITS_EXT);
     62        if (timestamp_counter_bits > 0) {
     63            runTimeStampTest();
     64            wtu.glErrorShouldBe(gl, gl.NO_ERROR);
     65        }
     66        verifyQueryResultsNotAvailable();
     67        verifyDeleteQueryBehavior();
     68        verifyDeleteQueryErrorBehavior();
     69        wtu.glErrorShouldBe(gl, gl.NO_ERROR);
     70 
     71        window.requestAnimationFrame(checkQueryResults);
     72    }
     73 }
     74 
     75 function runSanityTests() {
     76    debug("");
     77    debug("Testing other query types");
     78    query = gl.createQuery();
     79    gl.beginQuery(gl.ANY_SAMPLES_PASSED, query);
     80    shouldBeTrue("gl.getQuery(gl.ANY_SAMPLES_PASSED, gl.CURRENT_QUERY) !== null");
     81    gl.endQuery(gl.ANY_SAMPLES_PASSED);
     82    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "enabling EXT_disjoint_timer_query_webgl2 should not break other queries");
     83 
     84    debug("");
     85    debug("Testing timer query expectations");
     86 
     87    shouldBe("ext.QUERY_COUNTER_BITS_EXT", "0x8864");
     88    shouldBe("ext.TIME_ELAPSED_EXT", "0x88BF");
     89    shouldBe("ext.TIMESTAMP_EXT", "0x8E28");
     90    shouldBe("ext.GPU_DISJOINT_EXT", "0x8FBB");
     91 
     92    shouldBe("gl.isQuery(null)", "false");
     93 
     94    shouldBeTrue("gl.getQuery(ext.TIME_ELAPSED_EXT, gl.CURRENT_QUERY) === null");
     95    wtu.glErrorShouldBe(gl, gl.NO_ERROR);
     96    shouldBeTrue("gl.getQuery(ext.TIME_ELAPSED_EXT, ext.QUERY_COUNTER_BITS_EXT) >= 30");
     97    wtu.glErrorShouldBe(gl, gl.NO_ERROR);
     98 
     99    shouldBeTrue("gl.getQuery(ext.TIMESTAMP_EXT, gl.CURRENT_QUERY) === null");
    100    wtu.glErrorShouldBe(gl, gl.NO_ERROR);
    101 
    102    // Certain drivers set timestamp counter bits to 0 as they don't support timestamps
    103    shouldBeTrue("gl.getQuery(ext.TIMESTAMP_EXT, ext.QUERY_COUNTER_BITS_EXT) >= 30 || " +
    104                 "gl.getQuery(ext.TIMESTAMP_EXT, ext.QUERY_COUNTER_BITS_EXT) === 0");
    105    wtu.glErrorShouldBe(gl, gl.NO_ERROR);
    106 
    107    debug("");
    108    debug("Testing time elapsed query lifecycle");
    109    query = gl.createQuery();
    110    shouldBe("gl.isQuery(query)", "false");
    111    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Query creation must succeed.");
    112    gl.beginQuery(ext.TIMESTAMP_EXT, query);
    113    wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "Beginning a timestamp query should fail.");
    114    gl.beginQuery(ext.TIME_ELAPSED_EXT, query);
    115    shouldBe("gl.isQuery(query)", "true");
    116    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Beginning an inactive time elapsed query should succeed.");
    117    gl.beginQuery(ext.TIME_ELAPSED_EXT, query);
    118    wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Attempting to begin an active query should fail.");
    119    gl.getQueryParameter(query, gl.QUERY_RESULT_AVAILABLE);
    120    wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Fetching query result availability of an active query should fail.");
    121    gl.getQueryParameter(query, gl.QUERY_RESULT);
    122    wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Fetching query result of an active query should fail.");
    123    shouldBe("gl.getQuery(ext.TIME_ELAPSED_EXT, gl.CURRENT_QUERY)", "query");
    124    gl.endQuery(ext.TIME_ELAPSED_EXT);
    125    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Ending an active time elapsed query should succeed.");
    126    gl.getQueryParameter(query, gl.QUERY_RESULT_AVAILABLE);
    127    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Fetching query result availability after query end should succeed.");
    128    gl.endQuery(ext.TIME_ELAPSED_EXT);
    129    wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Attempting to end an inactive query should fail.");
    130    ext.queryCounterEXT(query, ext.TIMESTAMP_EXT);
    131    wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Should not be able to use time elapsed query to store a timestamp.");
    132    gl.deleteQuery(query);
    133    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Query deletion must succeed.");
    134    gl.beginQuery(ext.TIME_ELAPSED_EXT, query);
    135    wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Beginning a deleted query must fail.");
    136    gl.getQueryParameter(query, gl.QUERY_RESULT_AVAILABLE);
    137    wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Fetching query result availability after query deletion should fail.");
    138    shouldBe("gl.isQuery(query)", "false");
    139 
    140    debug("");
    141    debug("Testing timestamp counter");
    142    query = gl.createQuery();
    143    shouldThrow("ext.queryCounterEXT(null, ext.TIMESTAMP_EXT)");
    144    ext.queryCounterEXT(query, ext.TIMESTAMP_EXT);
    145    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Timestamp counter queries should work.");
    146    gl.deleteQuery(query);
    147    wtu.glErrorShouldBe(gl, gl.NO_ERROR);
    148 
    149    debug("");
    150    debug("Performing parameter sanity checks");
    151    gl.getParameter(ext.TIMESTAMP_EXT);
    152    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "getParameter timestamp calls should work.");
    153    gl.getParameter(ext.GPU_DISJOINT_EXT);
    154    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "getParameter disjoint calls should work.");
    155 
    156    debug("");
    157    debug("Testing current query conditions");
    158    query = gl.createQuery();
    159    query2 = gl.createQuery();
    160    shouldBe("gl.getQuery(ext.TIME_ELAPSED_EXT, gl.CURRENT_QUERY)", "null");
    161    gl.beginQuery(ext.TIME_ELAPSED_EXT, query);
    162    shouldBe("gl.getQuery(ext.TIME_ELAPSED_EXT, gl.CURRENT_QUERY)", "query");
    163    wtu.glErrorShouldBe(gl, gl.NO_ERROR);
    164 
    165    debug("");
    166    debug("Testing failed begin query should not change the current query.");
    167    gl.beginQuery(ext.TIME_ELAPSED_EXT, query2);
    168    wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Beginning an elapsed query without ending should fail.");
    169    shouldBe("gl.getQuery(ext.TIME_ELAPSED_EXT, gl.CURRENT_QUERY)", "query");
    170    wtu.glErrorShouldBe(gl, gl.NO_ERROR);
    171 
    172    debug("");
    173    debug("Testing beginning a timestamp query is invalid and should not change the elapsed query.");
    174    gl.beginQuery(ext.TIMESTAMP_EXT, query2)
    175    wtu.glErrorShouldBe(gl, gl.INVALID_ENUM);
    176    shouldBe("gl.getQuery(ext.TIME_ELAPSED_EXT, gl.CURRENT_QUERY)", "query");
    177    wtu.glErrorShouldBe(gl, gl.NO_ERROR);
    178 
    179    debug("");
    180    debug("Testing timestamp queries end immediately so are never current.");
    181    ext.queryCounterEXT(query2, ext.TIMESTAMP_EXT);
    182    shouldBe("gl.getQuery(ext.TIMESTAMP_EXT, gl.CURRENT_QUERY)", "null");
    183    wtu.glErrorShouldBe(gl, gl.NO_ERROR);
    184 
    185    debug("");
    186    debug("Testing ending the query should clear the current query.");
    187    gl.endQuery(ext.TIME_ELAPSED_EXT);
    188    shouldBe("gl.getQuery(ext.TIME_ELAPSED_EXT, gl.CURRENT_QUERY)", "null");
    189    wtu.glErrorShouldBe(gl, gl.NO_ERROR);
    190 
    191    debug("");
    192    debug("Testing beginning a elapsed query using a timestamp query should fail and not affect current query.")
    193    gl.beginQuery(ext.TIME_ELAPSED_EXT, query2);
    194    wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Switching query targets should fail.");
    195    shouldBe("gl.getQuery(ext.TIME_ELAPSED_EXT, gl.CURRENT_QUERY)", "null");
    196    wtu.glErrorShouldBe(gl, gl.NO_ERROR);
    197 
    198    gl.deleteQuery(query);
    199    gl.deleteQuery(query2);
    200 
    201    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors at end of sanity tests");
    202 }
    203 
    204 function runElapsedTimeTest() {
    205    debug("");
    206    debug("Testing elapsed time query");
    207 
    208    elapsed_query = gl.createQuery();
    209    gl.beginQuery(ext.TIME_ELAPSED_EXT, elapsed_query);
    210    gl.clearColor(0, 0, 1, 1);
    211    gl.clear(gl.COLOR_BUFFER_BIT);
    212    gl.endQuery(ext.TIME_ELAPSED_EXT);
    213    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Time elapsed query should have no errors");
    214 }
    215 
    216 function runTimeStampTest() {
    217    debug("");
    218    debug("Testing timestamp query");
    219 
    220    timestamp_query1 = gl.createQuery();
    221    timestamp_query2 = gl.createQuery();
    222    ext.queryCounterEXT(timestamp_query1, ext.TIMESTAMP_EXT);
    223    gl.clearColor(1, 0, 0, 1);
    224    gl.clear(gl.COLOR_BUFFER_BIT);
    225    ext.queryCounterEXT(timestamp_query2, ext.TIMESTAMP_EXT);
    226    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Timestamp queries should have no errors");
    227 }
    228 
    229 function verifyQueryResultsNotAvailable() {
    230    debug("");
    231    debug("Verifying queries' results don't become available too early");
    232 
    233    // Verify as best as possible that the implementation doesn't
    234    // allow a query's result to become available the same frame, by
    235    // spin-looping for some time and ensuring that none of the
    236    // queries' results become available.
    237    var startTime = Date.now();
    238    while (Date.now() - startTime < 2000) {
    239        gl.finish();
    240        if (gl.getQueryParameter(elapsed_query, gl.QUERY_RESULT_AVAILABLE)) {
    241            testFailed("One of the queries' results became available too early");
    242            return;
    243        }
    244        if (timestamp_counter_bits > 0) {
    245            if (gl.getQueryParameter(timestamp_query1, gl.QUERY_RESULT_AVAILABLE) ||
    246                gl.getQueryParameter(timestamp_query2, gl.QUERY_RESULT_AVAILABLE)) {
    247                testFailed("One of the queries' results became available too early");
    248                return;
    249            }
    250        }
    251    }
    252 
    253    testPassed("Queries' results didn't become available in a spin loop");
    254 }
    255 
    256 function verifyDeleteQueryBehavior() {
    257    debug("");
    258    debug("Testing deleting an active query should end it.");
    259 
    260    // Use a new context for this test
    261    gl2 = wtu.create3DContext(null, null, 2);
    262    if (!gl2) return;
    263    ext2 = gl2.getExtension("EXT_disjoint_timer_query_webgl2");
    264    if (!ext2) return;
    265 
    266    query = gl2.createQuery();
    267    gl2.beginQuery(ext.TIME_ELAPSED_EXT, query);
    268    wtu.glErrorShouldBe(gl2, gl2.NONE, "The query began successfully");
    269    gl2.deleteQuery(query);
    270    wtu.glErrorShouldBe(gl2, gl2.NONE, "Deletion of the active query succeeds");
    271    shouldBeNull("gl2.getQuery(ext2.TIME_ELAPSED_EXT, gl2.CURRENT_QUERY)");
    272    shouldBeFalse("gl2.isQuery(query)");
    273    query = gl2.createQuery();
    274    gl2.beginQuery(ext2.TIME_ELAPSED_EXT, query);
    275    wtu.glErrorShouldBe(gl, gl2.NONE, "Beginning a new query succeeds");
    276    gl2.endQuery(gl2.TIME_ELAPSED_EXT);
    277    gl2.deleteQuery(query);
    278    wtu.glErrorShouldBe(gl, gl.NONE);
    279    query = null;
    280    ext2 = null;
    281    gl2 = null;
    282 }
    283 
    284 function verifyDeleteQueryErrorBehavior() {
    285    debug("");
    286    debug("Testing deleting a query created by another context.");
    287 
    288    // Use new contexts for this test
    289    gl2 = wtu.create3DContext(null, null, 2);
    290    var gl3 = wtu.create3DContext(null, null, 2);
    291    if (!gl2 || !gl3) return;
    292    ext2 = gl2.getExtension("EXT_disjoint_timer_query_webgl2");
    293    if (!ext2) return;
    294 
    295    query = gl2.createQuery();
    296    gl2.beginQuery(ext2.TIME_ELAPSED_EXT, query);
    297    gl3.deleteQuery(query);
    298    wtu.glErrorShouldBe(gl3, gl3.INVALID_OPERATION);
    299    shouldBeTrue("gl2.isQuery(query)");
    300    shouldBe("gl2.getQuery(ext2.TIME_ELAPSED_EXT, gl2.CURRENT_QUERY)", "query");
    301    gl2.endQuery(ext2.TIME_ELAPSED_EXT);
    302    gl2.deleteQuery(query);
    303    wtu.glErrorShouldBe(gl2, gl2.NONE);
    304    query = null;
    305    ext2 = null;
    306    gl2 = null;
    307    gl3 = null;
    308 }
    309 
    310 function checkQueryResults() {
    311    if (availability_retry > 0) {
    312        // Make a reasonable attempt to wait for the queries' results to become available.
    313        if (!gl.getQueryParameter(elapsed_query, gl.QUERY_RESULT_AVAILABLE) ||
    314            (timestamp_counter_bits > 0 && !gl.getQueryParameter(timestamp_query2, gl.QUERY_RESULT_AVAILABLE))) {
    315            var error = gl.getError();
    316            if (error != gl.NO_ERROR) {
    317                testFailed("getQueryParameter should have no errors: " + wtu.glEnumToString(gl, error));
    318                debug("");
    319                finishTest();
    320                return;
    321            }
    322            availability_retry--;
    323            window.requestAnimationFrame(checkQueryResults);
    324            return;
    325        }
    326    }
    327 
    328    debug("");
    329    debug("Testing query results");
    330 
    331    // Make sure queries are available.
    332    shouldBe("gl.getQueryParameter(elapsed_query, gl.QUERY_RESULT_AVAILABLE)", "true");
    333    if (timestamp_counter_bits > 0) {
    334        shouldBe("gl.getQueryParameter(timestamp_query1, gl.QUERY_RESULT_AVAILABLE)", "true");
    335        shouldBe("gl.getQueryParameter(timestamp_query2, gl.QUERY_RESULT_AVAILABLE)", "true");
    336    }
    337 
    338    var disjoint_value = gl.getParameter(ext.GPU_DISJOINT_EXT);
    339    if (disjoint_value) {
    340        // Cannot validate results make sense, but this is okay.
    341        testPassed("Disjoint triggered.");
    342    } else {
    343        var elapsed_result = gl.getQueryParameter(elapsed_query, gl.QUERY_RESULT);
    344        if (timestamp_counter_bits > 0) {
    345            var timestamp_result1 = gl.getQueryParameter(timestamp_query1, gl.QUERY_RESULT);
    346            var timestamp_result2 = gl.getQueryParameter(timestamp_query2, gl.QUERY_RESULT);
    347        }
    348        // Do some basic validity checking of the elapsed time query. There's no way it should
    349        // take more than about half a second for a no-op query.
    350        var halfSecondInNanos = 0.5 * 1000 * 1000 * 1000;
    351        if (elapsed_result < 0 || elapsed_result > halfSecondInNanos) {
    352            testFailed("Time elapsed query returned invalid data: " + elapsed_result);
    353        } else {
    354            testPassed("Time elapsed query results were valid.");
    355        }
    356 
    357        if (timestamp_counter_bits > 0) {
    358            if (timestamp_result1 <= 0 ||
    359                timestamp_result2 <= 0 ||
    360                timestamp_result2 <= timestamp_result1) {
    361                testFailed("Timestamp queries returned invalid data: timestamp_result1 = " +
    362                           timestamp_result1 + ", timestamp_result2 = " + timestamp_result2);
    363            } else {
    364                testPassed("Timestamp query results were valid.");
    365            }
    366        }
    367    }
    368 
    369    debug("");
    370    finishTest();
    371 }
    372 </script>
    373 </body>
    374 </html>